gabejavitt commited on
Commit
48c0860
·
verified ·
1 Parent(s): ae370ed

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +109 -0
app.py CHANGED
@@ -1207,7 +1207,116 @@ def audio_transcription_tool(file_path: str) -> str:
1207
  telemetry.record_call("audio_transcription_tool", time.time() - start_time, False)
1208
  raise ToolError("audio_transcription_tool", e)
1209
 
 
 
 
1210
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1211
  class ImageAnalysisInput(BaseModel):
1212
  file_path: str = Field(description="Image file path")
1213
  query: str = Field(description="What to analyze")
 
1207
  telemetry.record_call("audio_transcription_tool", time.time() - start_time, False)
1208
  raise ToolError("audio_transcription_tool", e)
1209
 
1210
+ class ChessAnalysisInput(BaseModel):
1211
+ image_path: str = Field(description="Path to chess board image")
1212
+ description: str = Field(description="Context about position", default="")
1213
 
1214
+ @tool(args_schema=ChessAnalysisInput)
1215
+ def analyze_chess_position(image_path: str, description: str = "") -> str:
1216
+ """
1217
+ Analyze chess position using Stockfish.
1218
+ Requires stockfish binary installed.
1219
+ """
1220
+ start_time = time.time()
1221
+
1222
+ try:
1223
+ print(f"♟️ Analyzing chess: {image_path}")
1224
+
1225
+ # Find image
1226
+ chess_image = find_file(image_path)
1227
+ if not chess_image and os.path.exists(image_path):
1228
+ chess_image = Path(image_path)
1229
+
1230
+ if not chess_image or not chess_image.exists():
1231
+ raise FileNotFoundError(f"Chess image not found: {image_path}")
1232
+
1233
+ # Extract FEN using Gemini Vision
1234
+ GOOGLE_API_KEY = os.getenv("GEMINI_API_KEY")
1235
+ if not GOOGLE_API_KEY:
1236
+ raise ValueError("GEMINI_API_KEY not set")
1237
+
1238
+ img = Image.open(chess_image)
1239
+ if img.mode not in ['RGB', 'RGBA']:
1240
+ img = img.convert('RGB')
1241
+
1242
+ buffered = io.BytesIO()
1243
+ img.save(buffered, format="JPEG")
1244
+ img_base64 = base64.b64encode(buffered.getvalue()).decode()
1245
+
1246
+ vision_llm = ChatGoogleGenerativeAI(
1247
+ model="gemini-2.5-flash",
1248
+ google_api_key=GOOGLE_API_KEY,
1249
+ temperature=0
1250
+ )
1251
+
1252
+ fen_prompt = """Analyze this chess board and provide FEN notation.
1253
+ Return ONLY the FEN string, nothing else.
1254
+ Format: piece_placement active_color castling en_passant halfmove fullmove"""
1255
+
1256
+ message = HumanMessage(
1257
+ content=[
1258
+ {"type": "text", "text": fen_prompt},
1259
+ {"type": "image_url", "image_url": f"data:image/jpeg;base64,{img_base64}"}
1260
+ ]
1261
+ )
1262
+
1263
+ response = vision_llm.invoke([message])
1264
+ fen = response.content.strip()
1265
+
1266
+ # Clean FEN
1267
+ for line in fen.split('\n'):
1268
+ line = line.strip().replace('```', '').replace('fen', '')
1269
+ if '/' in line and ' ' in line:
1270
+ fen = line
1271
+ break
1272
+
1273
+ print(f"✓ FEN: {fen}")
1274
+
1275
+ # Analyze with Stockfish
1276
+ try:
1277
+ import chess
1278
+ from stockfish import Stockfish
1279
+ except ImportError:
1280
+ raise ImportError("Need: pip install python-chess stockfish")
1281
+
1282
+ # Find Stockfish binary
1283
+ stockfish_paths = [
1284
+ "/usr/games/stockfish",
1285
+ "/usr/local/bin/stockfish",
1286
+ "/usr/bin/stockfish",
1287
+ "stockfish"
1288
+ ]
1289
+
1290
+ stockfish_path = None
1291
+ for path in stockfish_paths:
1292
+ if os.path.exists(path):
1293
+ stockfish_path = path
1294
+ break
1295
+
1296
+ if not stockfish_path:
1297
+ raise FileNotFoundError("Stockfish binary not found. Install: apt-get install stockfish")
1298
+
1299
+ stockfish = Stockfish(path=stockfish_path, depth=20)
1300
+ stockfish.set_fen_position(fen)
1301
+
1302
+ best_move_uci = stockfish.get_best_move()
1303
+ if not best_move_uci:
1304
+ raise ValueError("No legal move found")
1305
+
1306
+ # Convert to SAN
1307
+ board = chess.Board(fen)
1308
+ uci_move = chess.Move.from_uci(best_move_uci)
1309
+ san_move = board.san(uci_move)
1310
+
1311
+ print(f"✓ Best move: {san_move}")
1312
+
1313
+ telemetry.record_call("analyze_chess_position", time.time() - start_time, True)
1314
+ return san_move
1315
+
1316
+ except Exception as e:
1317
+ telemetry.record_call("analyze_chess_position", time.time() - start_time, False)
1318
+ raise ToolError("analyze_chess_position", e, "Check if stockfish installed")
1319
+
1320
  class ImageAnalysisInput(BaseModel):
1321
  file_path: str = Field(description="Image file path")
1322
  query: str = Field(description="What to analyze")