Amogh1221 commited on
Commit
ee0df29
Β·
verified Β·
1 Parent(s): 7560b32

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +34 -23
main.py CHANGED
@@ -120,17 +120,38 @@ def health():
120
  return {"status": "error", "message": "Engine binary not found"}
121
  return {"status": "ok", "engine": "Deepcastle"}
122
 
 
 
 
123
  async def get_engine():
124
- if not os.path.exists(ENGINE_PATH):
125
- raise HTTPException(status_code=500, detail="Engine binary not found")
126
- transport, engine = await chess.engine.popen_uci(ENGINE_PATH)
127
- if os.path.exists(NNUE_PATH):
128
  try:
129
- await engine.configure({"EvalFile": NNUE_PATH})
130
- await engine.configure({"Hash": 512, "Threads": 2})
 
131
  except Exception:
132
- pass
133
- return engine
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
  def get_normalized_score(info) -> tuple[float, Optional[int]]:
136
  """Returns the score from White's perspective in centipawns."""
@@ -140,19 +161,21 @@ def get_normalized_score(info) -> tuple[float, Optional[int]]:
140
  if raw.is_mate():
141
  m = raw.mate() or 0
142
  return (10000.0 if m > 0 else -10000.0), m
143
- return raw.score() or 0.0, None
144
 
145
  # ─── Engine Inference Route ────────────────────────────────────────────────────
146
  @app.post("/move", response_model=MoveResponse)
147
  async def get_move(request: MoveRequest):
148
- engine = None
149
  try:
150
  engine = await get_engine()
151
  board = chess.Board(request.fen)
152
  limit = chess.engine.Limit(time=request.time, depth=request.depth)
153
 
 
154
  result = await engine.play(board, limit)
155
- info = await engine.analyse(board, limit)
 
 
156
 
157
  # From White's perspective in CP -> converted to Pawns for UI
158
  score_cp, mate_in = get_normalized_score(info)
@@ -194,12 +217,6 @@ async def get_move(request: MoveRequest):
194
  except Exception as e:
195
  print(f"Error: {e}")
196
  raise HTTPException(status_code=500, detail=str(e))
197
- finally:
198
- if engine:
199
- try:
200
- await engine.quit()
201
- except Exception:
202
- pass
203
 
204
 
205
  import math
@@ -483,12 +500,6 @@ async def analyze_game(request: AnalyzeRequest):
483
  except Exception as e:
484
  print(f"Analysis Error: {e}")
485
  raise HTTPException(status_code=500, detail=str(e))
486
- finally:
487
- if engine:
488
- try:
489
- await engine.quit()
490
- except Exception:
491
- pass
492
 
493
 
494
  if __name__ == "__main__":
 
120
  return {"status": "error", "message": "Engine binary not found"}
121
  return {"status": "ok", "engine": "Deepcastle"}
122
 
123
+ # Global engine instance to save memory and improve performance
124
+ _GLOBAL_ENGINE = None
125
+
126
  async def get_engine():
127
+ global _GLOBAL_ENGINE
128
+ if _GLOBAL_ENGINE is not None:
 
 
129
  try:
130
+ # Check if engine is still alive
131
+ if not _GLOBAL_ENGINE.is_terminated():
132
+ return _GLOBAL_ENGINE
133
  except Exception:
134
+ _GLOBAL_ENGINE = None
135
+
136
+ if not os.path.exists(ENGINE_PATH):
137
+ raise HTTPException(status_code=500, detail=f"Engine NOT FOUND at {ENGINE_PATH}")
138
+
139
+ try:
140
+ transport, engine = await chess.engine.popen_uci(ENGINE_PATH)
141
+
142
+ # Configure once
143
+ await engine.configure({"Hash": 256, "Threads": 1}) # More conservative for singleton
144
+
145
+ if os.path.exists(NNUE_PATH):
146
+ try:
147
+ await engine.configure({"EvalFile": NNUE_PATH})
148
+ except Exception:
149
+ pass
150
+
151
+ _GLOBAL_ENGINE = engine
152
+ return engine
153
+ except Exception as e:
154
+ raise HTTPException(status_code=500, detail=f"Failed to start engine: {str(e)}")
155
 
156
  def get_normalized_score(info) -> tuple[float, Optional[int]]:
157
  """Returns the score from White's perspective in centipawns."""
 
161
  if raw.is_mate():
162
  m = raw.mate() or 0
163
  return (10000.0 if m > 0 else -10000.0), m
164
+ return float(raw.score() or 0.0), None
165
 
166
  # ─── Engine Inference Route ────────────────────────────────────────────────────
167
  @app.post("/move", response_model=MoveResponse)
168
  async def get_move(request: MoveRequest):
 
169
  try:
170
  engine = await get_engine()
171
  board = chess.Board(request.fen)
172
  limit = chess.engine.Limit(time=request.time, depth=request.depth)
173
 
174
+ # Search for best move
175
  result = await engine.play(board, limit)
176
+
177
+ # Get evaluation separately to avoid blocking
178
+ info = await engine.analyse(board, chess.engine.Limit(time=0.1, depth=limit.depth or 12))
179
 
180
  # From White's perspective in CP -> converted to Pawns for UI
181
  score_cp, mate_in = get_normalized_score(info)
 
217
  except Exception as e:
218
  print(f"Error: {e}")
219
  raise HTTPException(status_code=500, detail=str(e))
 
 
 
 
 
 
220
 
221
 
222
  import math
 
500
  except Exception as e:
501
  print(f"Analysis Error: {e}")
502
  raise HTTPException(status_code=500, detail=str(e))
 
 
 
 
 
 
503
 
504
 
505
  if __name__ == "__main__":