Rafs-an09002's picture
Update app.py
e2a8333 verified
"""
Synapse-Base Inference API (Updated)
State-of-the-art search engine with modular architecture
"""
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
import time
import logging
from typing import Optional, List
from engine import SynapseEngine
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# Initialize FastAPI
app = FastAPI(
title="Synapse-Base Inference API",
description="State-of-the-art chess engine with neural evaluation",
version="3.0.0"
)
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Global engine
engine = None
# Models
class MoveRequest(BaseModel):
fen: str = Field(..., description="Board position in FEN notation")
depth: Optional[int] = Field(5, ge=1, le=10, description="Search depth (1-10)")
time_limit: Optional[int] = Field(5000, ge=1000, le=30000, description="Time limit in ms")
class MoveResponse(BaseModel):
best_move: str
evaluation: float
depth_searched: int
seldepth: int
nodes_evaluated: int
time_taken: int
nps: int
pv: List[str]
tt_hit_rate: Optional[float] = None
class HealthResponse(BaseModel):
status: str
model_loaded: bool
version: str
model_size_mb: Optional[float] = None
# Startup
@app.on_event("startup")
async def startup_event():
global engine
logger.info("🚀 Starting Synapse-Base Inference API v3.0...")
try:
engine = SynapseEngine(
model_path="/app/models/synapse_base.onnx",
num_threads=2
)
logger.info("✅ Engine loaded successfully")
except Exception as e:
logger.error(f"❌ Failed to load engine: {e}")
raise
# Health check
@app.get("/health", response_model=HealthResponse)
async def health_check():
return {
"status": "healthy" if engine is not None else "unhealthy",
"model_loaded": engine is not None,
"version": "3.0.0",
"model_size_mb": engine.get_model_size() if engine else None
}
# Main endpoint
@app.post("/get-move", response_model=MoveResponse)
async def get_move(request: MoveRequest):
if engine is None:
raise HTTPException(status_code=503, detail="Engine not loaded")
if not engine.validate_fen(request.fen):
raise HTTPException(status_code=400, detail="Invalid FEN string")
start_time = time.time()
try:
result = engine.get_best_move(
fen=request.fen,
depth=request.depth,
time_limit=request.time_limit
)
time_taken = int((time.time() - start_time) * 1000)
logger.info(
f"Move: {result['best_move']} | "
f"Eval: {result['evaluation']:+.2f} | "
f"Depth: {result['depth_searched']}/{result['seldepth']} | "
f"Nodes: {result['nodes_evaluated']} | "
f"Time: {time_taken}ms | "
f"NPS: {result['nps']}"
)
return MoveResponse(
best_move=result['best_move'],
evaluation=result['evaluation'],
depth_searched=result['depth_searched'],
seldepth=result['seldepth'],
nodes_evaluated=result['nodes_evaluated'],
time_taken=time_taken,
nps=result['nps'],
pv=result['pv'],
tt_hit_rate=result['tt_stats']['hit_rate']
)
except Exception as e:
logger.error(f"Error: {e}")
raise HTTPException(status_code=500, detail=str(e))
# Root
@app.get("/")
async def root():
return {
"name": "Synapse-Base Inference API",
"version": "3.0.0",
"model": "38.1M parameters",
"architecture": "CNN-Transformer Hybrid",
"search": "PVS + NMP + LMR + TT",
"endpoints": {
"POST /get-move": "Get best move",
"GET /health": "Health check",
"GET /docs": "API documentation"
}
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860, log_level="info")