FD900's picture
Update tools/chess_tools.py
e0152b8 verified
raw
history blame
2.93 kB
import shutil
from smolagents import Tool
import requests
class ChessEngineLocatorTool(Tool):
name = "locate_chess_engine"
description = "Locates the installed Stockfish chess engine binary on the system."
inputs = {}
output_type = "string"
def forward(self) -> str:
engine_path = shutil.which("stockfish")
return engine_path or "Stockfish engine not found."
class ChessboardImageToFENTool(Tool):
name = "image_to_fen"
description = "Analyzes a chessboard image and returns its FEN representation."
inputs = {
"image_url": {
"type": "string",
"description": "A public image URL or a base64 data URL containing a chessboard photo."
}
}
output_type = "string"
def __init__(self, endpoint_url: str, hf_token: str, **kwargs):
super().__init__(**kwargs)
self.endpoint_url = endpoint_url
self.hf_token = hf_token
def forward(self, image_url: str) -> str:
headers = {
"Authorization": f"Bearer {self.hf_token}",
"Content-Type": "application/json"
}
payload = {
"inputs": [
{
"role": "user",
"content": [
{"type": "input_text", "text": "Extract chess piece positions from this image."},
{"type": "input_image", "image_url": image_url}
]
},
{
"role": "user",
"content": [
{
"type": "input_text",
"text": (
"Using the extracted pieces, list each one with its position in format <piece><square> (e.g., Kd4).\n"
"Use uppercase for white, lowercase for black. Output only the lines with positions."
)
}
]
}
]
}
response = requests.post(self.endpoint_url, headers=headers, json=payload)
response.raise_for_status()
raw_text = response.json().get("generated_text", "")
squares = {}
for line in raw_text.splitlines():
line = line.strip()
if len(line) == 3:
squares[line[1:3]] = line[0]
fen_rows = []
for rank in range(8, 0, -1):
row = ""
empty = 0
for file in "abcdefgh":
pos = f"{file}{rank}"
if pos in squares:
if empty > 0:
row += str(empty)
empty = 0
row += squares[pos]
else:
empty += 1
if empty:
row += str(empty)
fen_rows.append(row)
return "/".join(fen_rows)