Rafs-an09002's picture
Update app.py
3c84581 verified
raw
history blame
4.35 kB
"""
Nexus-Core Inference API (Fixed)
Fast and efficient chess engine with proper error handling
"""
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
import time
import logging
import os
from typing import Optional
from engine import NexusCoreEngine
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
app = FastAPI(
title="Nexus-Core Inference API",
description="Fast chess engine (13M params)",
version="2.0.0"
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
engine = None
class MoveRequest(BaseModel):
fen: str
depth: Optional[int] = Field(4, ge=1, le=6)
time_limit: Optional[int] = Field(3000, ge=1000, le=10000)
class MoveResponse(BaseModel):
best_move: str
evaluation: float
depth_searched: int
nodes_evaluated: int
time_taken: int
class HealthResponse(BaseModel):
status: str
model_loaded: bool
version: str
model_path: Optional[str] = None
@app.on_event("startup")
async def startup_event():
global engine
logger.info("🚀 Starting Nexus-Core API...")
# Check model file
model_path = "/app/models/nexus_core.onnx"
# Debug: List files in models directory
if os.path.exists("/app/models"):
logger.info(f"📂 Files in /app/models/:")
for f in os.listdir("/app/models"):
full_path = os.path.join("/app/models", f)
size = os.path.getsize(full_path) / (1024*1024)
logger.info(f" - {f} ({size:.2f} MB)")
else:
logger.error("❌ /app/models/ directory does not exist!")
raise FileNotFoundError("/app/models/ not found")
# Check if model exists
if not os.path.exists(model_path):
logger.error(f"❌ Model not found at {model_path}")
logger.error("Available files:", os.listdir("/app/models") if os.path.exists("/app/models") else "No models dir")
raise FileNotFoundError(f"Model file not found: {model_path}")
logger.info(f"✅ Model found: {model_path} ({os.path.getsize(model_path)/(1024*1024):.2f} MB)")
try:
engine = NexusCoreEngine(
model_path=model_path,
num_threads=2
)
logger.info("✅ Nexus-Core engine loaded successfully")
except Exception as e:
logger.error(f"❌ Failed to load engine: {e}", exc_info=True)
raise
@app.get("/health", response_model=HealthResponse)
async def health_check():
return {
"status": "healthy" if engine else "unhealthy",
"model_loaded": engine is not None,
"version": "2.0.0",
"model_path": "/app/models/nexus_core.onnx" if engine else None
}
@app.post("/get-move", response_model=MoveResponse)
async def get_move(request: MoveRequest):
if not engine:
raise HTTPException(503, "Engine not loaded")
if not engine.validate_fen(request.fen):
raise HTTPException(400, "Invalid FEN")
start = time.time()
try:
result = engine.get_best_move(
request.fen,
request.depth,
request.time_limit
)
logger.info(
f"Move: {result['best_move']} | "
f"Eval: {result['evaluation']:+.2f} | "
f"Depth: {result['depth_searched']} | "
f"Nodes: {result['nodes_evaluated']} | "
f"Time: {result['time_taken']}ms"
)
return MoveResponse(**result)
except Exception as e:
logger.error(f"Error during search: {e}", exc_info=True)
raise HTTPException(500, str(e))
@app.get("/")
async def root():
return {
"name": "Nexus-Core API",
"version": "2.0.0",
"model": "13M parameters",
"speed": "Ultra-fast (0.5-1s per move)",
"status": "healthy" if engine else "loading",
"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")