Rafs-an09002 commited on
Commit
a3ea8dc
·
verified ·
1 Parent(s): d249d53

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +36 -110
app.py CHANGED
@@ -1,8 +1,3 @@
1
- """
2
- Nexus-Core Inference API - Path Fixed
3
- Model: /app/models/nexus-core.onnx
4
- """
5
-
6
  from fastapi import FastAPI, HTTPException
7
  from fastapi.middleware.cors import CORSMiddleware
8
  from pydantic import BaseModel, Field
@@ -13,35 +8,19 @@ from typing import Optional
13
 
14
  from engine import NexusCoreEngine
15
 
16
- logging.basicConfig(
17
- level=logging.INFO,
18
- format='%(asctime)s - %(levelname)s - %(message)s'
19
- )
20
  logger = logging.getLogger(__name__)
21
 
22
- app = FastAPI(
23
- title="Nexus-Core Inference API",
24
- description="Fast chess engine (13M params)",
25
- version="2.0.0"
26
- )
27
-
28
- app.add_middleware(
29
- CORSMiddleware,
30
- allow_origins=["*"],
31
- allow_credentials=True,
32
- allow_methods=["*"],
33
- allow_headers=["*"],
34
- )
35
 
36
  engine = None
37
 
38
-
39
  class MoveRequest(BaseModel):
40
  fen: str
41
  depth: Optional[int] = Field(4, ge=1, le=6)
42
  time_limit: Optional[int] = Field(3000, ge=1000, le=10000)
43
 
44
-
45
  class MoveResponse(BaseModel):
46
  best_move: str
47
  evaluation: float
@@ -49,120 +28,67 @@ class MoveResponse(BaseModel):
49
  nodes_evaluated: int
50
  time_taken: int
51
 
52
-
53
  class HealthResponse(BaseModel):
54
  status: str
55
  model_loaded: bool
56
  version: str
57
- model_path: Optional[str] = None
58
-
59
 
60
  @app.on_event("startup")
61
  async def startup_event():
62
  global engine
63
- logger.info("🚀 Starting Nexus-Core API...")
64
-
65
- # FIXED: Correct model path with hyphen
66
- model_path = "/app/models/nexus-core.onnx"
67
-
68
- # Debug logging
69
- logger.info(f"Looking for model at: {model_path}")
70
 
71
- if os.path.exists("/app/models"):
72
- logger.info("📂 Files in /app/models/:")
73
- for f in os.listdir("/app/models"):
74
- full_path = os.path.join("/app/models", f)
75
- if os.path.isfile(full_path):
76
- size = os.path.getsize(full_path) / (1024*1024)
77
- logger.info(f" ✓ {f} ({size:.2f} MB)")
78
- else:
79
- logger.error("❌ /app/models/ directory does not exist!")
80
- raise FileNotFoundError("/app/models/ not found")
81
 
82
- if not os.path.exists(model_path):
83
- logger.error(f"❌ Model not found at: {model_path}")
84
- logger.error("💡 Available files:", os.listdir("/app/models"))
85
- raise FileNotFoundError(f"Model file missing: {model_path}")
 
 
86
 
87
- logger.info(f"✅ Model found: {os.path.getsize(model_path)/(1024*1024):.2f} MB")
 
 
 
 
 
 
 
 
88
 
89
  try:
90
- engine = NexusCoreEngine(
91
- model_path=model_path,
92
- num_threads=2
93
- )
94
- logger.info("✅ Nexus-Core engine loaded successfully!")
95
-
96
  except Exception as e:
97
- logger.error(f"❌ Engine load failed: {e}", exc_info=True)
98
  raise
99
 
100
-
101
  @app.get("/health", response_model=HealthResponse)
102
  async def health_check():
103
- return {
104
- "status": "healthy" if engine else "unhealthy",
105
- "model_loaded": engine is not None,
106
- "version": "2.0.0",
107
- "model_path": "/app/models/nexus-core.onnx"
108
- }
109
-
110
 
111
  @app.post("/get-move", response_model=MoveResponse)
112
  async def get_move(request: MoveRequest):
113
- if not engine:
114
- raise HTTPException(status_code=503, detail="Engine not loaded")
115
-
116
- if not engine.validate_fen(request.fen):
117
- raise HTTPException(status_code=400, detail="Invalid FEN string")
118
-
119
  start = time.time()
120
-
121
  try:
122
- result = engine.get_best_move(
123
- fen=request.fen,
124
- depth=request.depth,
125
- time_limit=request.time_limit
126
- )
127
-
128
- logger.info(
129
- f"✓ Move: {result['best_move']} | "
130
- f"Eval: {result['evaluation']:+.2f} | "
131
- f"Depth: {result['depth_searched']} | "
132
- f"Nodes: {result['nodes_evaluated']} | "
133
- f"Time: {result['time_taken']}ms"
134
- )
135
-
136
  return MoveResponse(**result)
137
-
138
  except Exception as e:
139
- logger.error(f"❌ Search error: {e}", exc_info=True)
140
- raise HTTPException(status_code=500, detail=str(e))
141
-
142
 
143
  @app.get("/")
144
  async def root():
145
- return {
146
- "name": "Nexus-Core Inference API",
147
- "version": "2.0.0",
148
- "model": "13M parameters",
149
- "architecture": "ResNet CNN",
150
- "speed": "0.5-1s per move @ depth 4",
151
- "status": "online" if engine else "starting",
152
- "endpoints": {
153
- "POST /get-move": "Get best chess move",
154
- "GET /health": "API health check",
155
- "GET /docs": "Interactive API documentation"
156
- }
157
- }
158
-
159
 
160
  if __name__ == "__main__":
161
  import uvicorn
162
- uvicorn.run(
163
- app,
164
- host="0.0.0.0",
165
- port=7860,
166
- log_level="info",
167
- access_log=True
168
- )
 
 
 
 
 
 
1
  from fastapi import FastAPI, HTTPException
2
  from fastapi.middleware.cors import CORSMiddleware
3
  from pydantic import BaseModel, Field
 
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
 
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...")
 
 
 
 
 
 
40
 
41
+ # FIXED: Check both possible paths
42
+ possible_paths = [
43
+ "/app/app/models/nexus-core.onnx", # When uploaded to app/models/
44
+ "/app/models/nexus-core.onnx" # When uploaded to models/
45
+ ]
 
 
 
 
 
46
 
47
+ model_path = None
48
+ for path in possible_paths:
49
+ if os.path.exists(path):
50
+ model_path = path
51
+ logger.info(f"✅ Found model at: {path}")
52
+ break
53
 
54
+ if not model_path:
55
+ logger.error("❌ Model not found in any expected location")
56
+ logger.error(f"Checked paths: {possible_paths}")
57
+ # List all .onnx files
58
+ for root, dirs, files in os.walk("/app"):
59
+ for file in files:
60
+ if file.endswith('.onnx'):
61
+ logger.error(f"Found .onnx at: {os.path.join(root, file)}")
62
+ raise FileNotFoundError("Model not found")
63
 
64
  try:
65
+ engine = NexusCoreEngine(model_path=model_path, num_threads=2)
66
+ logger.info("✅ Engine loaded!")
 
 
 
 
67
  except Exception as e:
68
+ logger.error(f"❌ Failed: {e}", exc_info=True)
69
  raise
70
 
 
71
  @app.get("/health", response_model=HealthResponse)
72
  async def health_check():
73
+ return {"status": "healthy" if engine else "unhealthy", "model_loaded": engine is not None, "version": "2.0.0"}
 
 
 
 
 
 
74
 
75
  @app.post("/get-move", response_model=MoveResponse)
76
  async def get_move(request: MoveRequest):
77
+ if not engine: raise HTTPException(503, "Not loaded")
78
+ if not engine.validate_fen(request.fen): raise HTTPException(400, "Invalid FEN")
 
 
 
 
79
  start = time.time()
 
80
  try:
81
+ result = engine.get_best_move(request.fen, request.depth, request.time_limit)
82
+ logger.info(f"✓ {result['best_move']} | {result['evaluation']:+.2f} | {result['time_taken']}ms")
 
 
 
 
 
 
 
 
 
 
 
 
83
  return MoveResponse(**result)
 
84
  except Exception as e:
85
+ logger.error(f"Error: {e}", exc_info=True)
86
+ raise HTTPException(500, str(e))
 
87
 
88
  @app.get("/")
89
  async def root():
90
+ return {"name": "Nexus-Core", "version": "2.0.0", "status": "online" if engine else "starting"}
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
  if __name__ == "__main__":
93
  import uvicorn
94
+ uvicorn.run(app, host="0.0.0.0", port=7860, log_level="info")