File size: 3,200 Bytes
8d1f456
 
 
 
 
3c84581
8d1f456
 
 
 
a3ea8dc
8d1f456
 
a3ea8dc
 
8d1f456
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a3ea8dc
3c84581
a3ea8dc
 
 
 
 
3c84581
a3ea8dc
 
 
 
 
 
3c84581
a3ea8dc
 
 
 
 
 
 
 
 
3c84581
8d1f456
a3ea8dc
 
8d1f456
a3ea8dc
8d1f456
 
 
 
a3ea8dc
8d1f456
 
 
a3ea8dc
 
8d1f456
 
a3ea8dc
 
8d1f456
 
a3ea8dc
 
8d1f456
 
 
a3ea8dc
8d1f456
 
 
a3ea8dc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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 API", 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

@app.on_event("startup")
async def startup_event():
    global engine
    logger.info("🚀 Starting Nexus-Core...")
    
    # FIXED: Check both possible paths
    possible_paths = [
        "/app/app/models/nexus-core.onnx",  # When uploaded to app/models/
        "/app/models/nexus-core.onnx"        # When uploaded to models/
    ]
    
    model_path = None
    for path in possible_paths:
        if os.path.exists(path):
            model_path = path
            logger.info(f"✅ Found model at: {path}")
            break
    
    if not model_path:
        logger.error("❌ Model not found in any expected location")
        logger.error(f"Checked paths: {possible_paths}")
        # List all .onnx files
        for root, dirs, files in os.walk("/app"):
            for file in files:
                if file.endswith('.onnx'):
                    logger.error(f"Found .onnx at: {os.path.join(root, file)}")
        raise FileNotFoundError("Model not found")
    
    try:
        engine = NexusCoreEngine(model_path=model_path, num_threads=2)
        logger.info("✅ Engine loaded!")
    except Exception as e:
        logger.error(f"❌ Failed: {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"}

@app.post("/get-move", response_model=MoveResponse)
async def get_move(request: MoveRequest):
    if not engine: raise HTTPException(503, "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"✓ {result['best_move']} | {result['evaluation']:+.2f} | {result['time_taken']}ms")
        return MoveResponse(**result)
    except Exception as e:
        logger.error(f"Error: {e}", exc_info=True)
        raise HTTPException(500, str(e))

@app.get("/")
async def root():
    return {"name": "Nexus-Core", "version": "2.0.0", "status": "online" if engine else "starting"}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=7860, log_level="info")