Rafs-an09002 commited on
Commit
2d387ea
·
verified ·
1 Parent(s): 4357f6e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -22
app.py CHANGED
@@ -1,70 +1,160 @@
 
 
 
 
 
1
  from fastapi import FastAPI, HTTPException
2
  from fastapi.middleware.cors import CORSMiddleware
3
  from pydantic import BaseModel, Field
4
  import time
5
  import logging
6
- import os
7
- from typing import Optional
8
 
9
  from engine import NexusCoreEngine
10
 
11
- logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
 
 
 
 
12
  logger = logging.getLogger(__name__)
13
 
14
- app = FastAPI(title="Nexus-Core API", version="2.0.0")
15
- app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"])
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
 
17
  engine = None
18
 
 
 
19
  class MoveRequest(BaseModel):
20
- fen: str
21
- depth: Optional[int] = Field(4, ge=1, le=6)
22
- time_limit: Optional[int] = Field(3000, ge=1000, le=10000)
 
23
 
24
  class MoveResponse(BaseModel):
25
  best_move: str
26
  evaluation: float
27
  depth_searched: int
 
28
  nodes_evaluated: int
29
  time_taken: int
 
 
 
 
30
 
31
  class HealthResponse(BaseModel):
32
  status: str
33
  model_loaded: bool
34
  version: str
 
35
 
 
 
36
  @app.on_event("startup")
37
  async def startup_event():
38
  global engine
39
- logger.info("🚀 Starting Nexus-Core API...")
40
- model_path = "/app/models/nexus-core.onnx"
 
41
  try:
42
- engine = NexusCoreEngine(model_path=model_path, num_threads=2)
43
- logger.info("✅ Nexus-Core engine loaded")
 
 
 
 
44
  except Exception as e:
45
- logger.error(f"❌ Failed to load engine: {e}")
46
  raise
47
 
 
 
48
  @app.get("/health", response_model=HealthResponse)
49
  async def health_check():
50
- return {"status": "healthy" if engine else "unhealthy", "model_loaded": engine is not None, "version": "2.0.0"}
 
 
 
 
 
 
51
 
 
52
  @app.post("/get-move", response_model=MoveResponse)
53
  async def get_move(request: MoveRequest):
54
- if not engine: raise HTTPException(503, "Engine not loaded")
55
- if not engine.validate_fen(request.fen): raise HTTPException(400, "Invalid FEN")
56
- start = time.time()
 
 
 
 
 
57
  try:
58
- result = engine.get_best_move(request.fen, request.depth, request.time_limit)
59
- logger.info(f"Move: {result['best_move']} | Eval: {result['evaluation']:+.2f} | Time: {result['time_taken']}ms")
60
- return MoveResponse(**result)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  except Exception as e:
62
  logger.error(f"Error: {e}")
63
- raise HTTPException(500, str(e))
64
 
 
 
65
  @app.get("/")
66
  async def root():
67
- return {"name": "Nexus-Core", "version": "2.0.0", "status": "online" if engine else "starting"}
 
 
 
 
 
 
 
 
 
 
 
68
 
69
  if __name__ == "__main__":
70
  import uvicorn
 
1
+ """
2
+ Nexus-Core Inference API
3
+ 13.2M parameter chess engine
4
+ """
5
+
6
  from fastapi import FastAPI, HTTPException
7
  from fastapi.middleware.cors import CORSMiddleware
8
  from pydantic import BaseModel, Field
9
  import time
10
  import logging
11
+ from typing import Optional, List
 
12
 
13
  from engine import NexusCoreEngine
14
 
15
+ # Logging
16
+ logging.basicConfig(
17
+ level=logging.INFO,
18
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
19
+ )
20
  logger = logging.getLogger(__name__)
21
 
22
+ # FastAPI
23
+ app = FastAPI(
24
+ title="Nexus-Core Inference API",
25
+ description="13.2M parameter ResNet-20 chess engine",
26
+ version="2.0.0"
27
+ )
28
+
29
+ # CORS
30
+ app.add_middleware(
31
+ CORSMiddleware,
32
+ allow_origins=["*"],
33
+ allow_credentials=True,
34
+ allow_methods=["*"],
35
+ allow_headers=["*"],
36
+ )
37
 
38
+ # Global engine
39
  engine = None
40
 
41
+
42
+ # Models
43
  class MoveRequest(BaseModel):
44
+ fen: str = Field(..., description="FEN notation")
45
+ depth: Optional[int] = Field(5, ge=1, le=8, description="Search depth")
46
+ time_limit: Optional[int] = Field(3000, ge=1000, le=15000, description="Time in ms")
47
+
48
 
49
  class MoveResponse(BaseModel):
50
  best_move: str
51
  evaluation: float
52
  depth_searched: int
53
+ seldepth: int
54
  nodes_evaluated: int
55
  time_taken: int
56
+ nps: int
57
+ pv: List[str]
58
+ tt_hit_rate: Optional[float] = None
59
+
60
 
61
  class HealthResponse(BaseModel):
62
  status: str
63
  model_loaded: bool
64
  version: str
65
+ model_size_mb: Optional[float] = None
66
 
67
+
68
+ # Startup
69
  @app.on_event("startup")
70
  async def startup_event():
71
  global engine
72
+
73
+ logger.info("🚀 Starting Nexus-Core API v2.0...")
74
+
75
  try:
76
+ engine = NexusCoreEngine(
77
+ model_path="/app/models/nexus-core.onnx",
78
+ num_threads=2
79
+ )
80
+ logger.info("✅ Engine loaded")
81
+
82
  except Exception as e:
83
+ logger.error(f"❌ Failed: {e}")
84
  raise
85
 
86
+
87
+ # Health
88
  @app.get("/health", response_model=HealthResponse)
89
  async def health_check():
90
+ return {
91
+ "status": "healthy" if engine else "unhealthy",
92
+ "model_loaded": engine is not None,
93
+ "version": "2.0.0",
94
+ "model_size_mb": engine.get_model_size() if engine else None
95
+ }
96
+
97
 
98
+ # Main endpoint
99
  @app.post("/get-move", response_model=MoveResponse)
100
  async def get_move(request: MoveRequest):
101
+ if engine is None:
102
+ raise HTTPException(status_code=503, detail="Engine not loaded")
103
+
104
+ if not engine.validate_fen(request.fen):
105
+ raise HTTPException(status_code=400, detail="Invalid FEN")
106
+
107
+ start_time = time.time()
108
+
109
  try:
110
+ result = engine.get_best_move(
111
+ fen=request.fen,
112
+ depth=request.depth,
113
+ time_limit=request.time_limit
114
+ )
115
+
116
+ time_taken = int((time.time() - start_time) * 1000)
117
+
118
+ logger.info(
119
+ f"Move: {result['best_move']} | "
120
+ f"Eval: {result['evaluation']:+.2f} | "
121
+ f"Depth: {result['depth_searched']}/{result['seldepth']} | "
122
+ f"Nodes: {result['nodes_evaluated']} | "
123
+ f"NPS: {result['nps']}"
124
+ )
125
+
126
+ return MoveResponse(
127
+ best_move=result['best_move'],
128
+ evaluation=result['evaluation'],
129
+ depth_searched=result['depth_searched'],
130
+ seldepth=result['seldepth'],
131
+ nodes_evaluated=result['nodes_evaluated'],
132
+ time_taken=time_taken,
133
+ nps=result['nps'],
134
+ pv=result['pv'],
135
+ tt_hit_rate=result['tt_stats']['hit_rate']
136
+ )
137
+
138
  except Exception as e:
139
  logger.error(f"Error: {e}")
140
+ raise HTTPException(status_code=500, detail=str(e))
141
 
142
+
143
+ # Root
144
  @app.get("/")
145
  async def root():
146
+ return {
147
+ "name": "Nexus-Core Inference API",
148
+ "version": "2.0.0",
149
+ "model": "13.2M parameters (ResNet-20)",
150
+ "search": "PVS + NMP + LMR",
151
+ "endpoints": {
152
+ "POST /get-move": "Get best move",
153
+ "GET /health": "Health check",
154
+ "GET /docs": "Documentation"
155
+ }
156
+ }
157
+
158
 
159
  if __name__ == "__main__":
160
  import uvicorn