""" 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")