commit
Browse files- my_chess_analysis_tool.py +51 -0
- my_chess_board_tool.py +3 -7
- my_fen_tool.py +8 -14
- requirements.txt +2 -2
- simple.py +38 -5
- test_tools.py +15 -1
my_chess_analysis_tool.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from smolagents import Tool
|
| 2 |
+
from stockfish import Stockfish
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
#AUTHORIZED_TYPES = [
|
| 6 |
+
# "string",
|
| 7 |
+
# "boolean",
|
| 8 |
+
# "integer",
|
| 9 |
+
# "number",
|
| 10 |
+
# "image",
|
| 11 |
+
# "audio",
|
| 12 |
+
# "array",
|
| 13 |
+
# "object",
|
| 14 |
+
# "any",
|
| 15 |
+
# "null",
|
| 16 |
+
#]
|
| 17 |
+
|
| 18 |
+
# https://pypi.org/project/stockfish/
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
class ChessAnalysisTool(Tool):
|
| 22 |
+
name = "_my_chess_analysis"
|
| 23 |
+
description = """
|
| 24 |
+
Analyze chess board provided in FEN notation and provide best move for given color
|
| 25 |
+
"""
|
| 26 |
+
|
| 27 |
+
inputs = {
|
| 28 |
+
"fen": {
|
| 29 |
+
"type": "string",
|
| 30 |
+
"description": "board position in FEN notation",
|
| 31 |
+
},
|
| 32 |
+
"player_color": {
|
| 33 |
+
"type": "string",
|
| 34 |
+
"description": "black or white to make next move",
|
| 35 |
+
}
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
output_type = "string"
|
| 39 |
+
|
| 40 |
+
def __init__(self):
|
| 41 |
+
self.engine = Stockfish()
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def forward(self, fen: str, player_color: str) -> str:
|
| 45 |
+
self.engine.set_fen_position(fen)
|
| 46 |
+
board = self.engine.get_board_visual()
|
| 47 |
+
print(f"{board}")
|
| 48 |
+
top_3_moves = self.engine.get_top_moves(3)
|
| 49 |
+
print(f"Top 3 moves:\n{top_3_moves}")
|
| 50 |
+
best_move = self.engine.get_best_move()
|
| 51 |
+
return best_move
|
my_chess_board_tool.py
CHANGED
|
@@ -12,7 +12,7 @@ import traceback
|
|
| 12 |
class ChessBoard(Tool):
|
| 13 |
name = "_my_chess_board"
|
| 14 |
description = """
|
| 15 |
-
|
| 16 |
"""
|
| 17 |
|
| 18 |
inputs = {
|
|
@@ -247,19 +247,15 @@ class ChessBoard(Tool):
|
|
| 247 |
try:
|
| 248 |
print(f"***KS*** Analyzing chess board image for image: {img}")
|
| 249 |
cv2_image = cv2.cvtColor(numpy.array(img), cv2.COLOR_RGB2BGR)
|
| 250 |
-
print(f"***KS*** Got CV2 image shape: {cv2_image.shape}")
|
| 251 |
|
| 252 |
# Image(PIL) -> Image(CV2)(32x32) []
|
| 253 |
squares_resized = self.__extract_pieces_from_image_board(cv2_image)
|
| 254 |
-
print(f"***KS*** Squares resized: {len(squares_resized)}")
|
| 255 |
|
| 256 |
# Image(CV2)(32x32) [] -> str[]
|
| 257 |
pieces_list = self.__detect_chess_pieces(squares_resized)
|
| 258 |
print(f"***KS*** Pieces list: {pieces_list}")
|
| 259 |
-
|
| 260 |
-
# str[] -> str(FEN)
|
| 261 |
-
#fen = self.__convert_pieces_list_to_fen(pieces_list)
|
| 262 |
-
#print(f"***KS*** FEN acquired: {fen}")
|
| 263 |
except Exception as ex:
|
| 264 |
print(traceback.format_exc())
|
| 265 |
print(f"***KS*** Exception invoking ChessBoard: {ex}")
|
|
|
|
| 12 |
class ChessBoard(Tool):
|
| 13 |
name = "_my_chess_board"
|
| 14 |
description = """
|
| 15 |
+
Process an image representing a chess board and return board position as a list of chess pieces
|
| 16 |
"""
|
| 17 |
|
| 18 |
inputs = {
|
|
|
|
| 247 |
try:
|
| 248 |
print(f"***KS*** Analyzing chess board image for image: {img}")
|
| 249 |
cv2_image = cv2.cvtColor(numpy.array(img), cv2.COLOR_RGB2BGR)
|
| 250 |
+
#print(f"***KS*** Got CV2 image shape: {cv2_image.shape}")
|
| 251 |
|
| 252 |
# Image(PIL) -> Image(CV2)(32x32) []
|
| 253 |
squares_resized = self.__extract_pieces_from_image_board(cv2_image)
|
| 254 |
+
#print(f"***KS*** Squares resized: {len(squares_resized)}")
|
| 255 |
|
| 256 |
# Image(CV2)(32x32) [] -> str[]
|
| 257 |
pieces_list = self.__detect_chess_pieces(squares_resized)
|
| 258 |
print(f"***KS*** Pieces list: {pieces_list}")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 259 |
except Exception as ex:
|
| 260 |
print(traceback.format_exc())
|
| 261 |
print(f"***KS*** Exception invoking ChessBoard: {ex}")
|
my_fen_tool.py
CHANGED
|
@@ -21,7 +21,7 @@ import textwrap
|
|
| 21 |
|
| 22 |
|
| 23 |
class FENTool(Tool):
|
| 24 |
-
name = "
|
| 25 |
description = """
|
| 26 |
Convert a bord provided a s alist of chest pieces into FEN notation
|
| 27 |
"""
|
|
@@ -42,28 +42,22 @@ class FENTool(Tool):
|
|
| 42 |
.replace('1111','4').replace('111','3').replace('11','2')
|
| 43 |
|
| 44 |
def forward(self, _inp: str) -> str:
|
| 45 |
-
#arr = np.array(list(_inp)).reshape(8, 8)
|
| 46 |
-
#print(f"Arr: {arr.shape}\n{arr}")
|
| 47 |
-
|
| 48 |
-
#arr = np.flip(arr, axis=0)
|
| 49 |
-
#print(f"Arr flipped: {arr.shape}\n{arr}")
|
| 50 |
-
|
| 51 |
-
#fen = [str(r) for r in arr]
|
| 52 |
-
#print(f"rows as str: {fen}")
|
| 53 |
-
|
| 54 |
arr = textwrap.wrap(_inp, 8)
|
| 55 |
-
print(f"Arr: \n{arr}")
|
| 56 |
|
| 57 |
arr = arr[::-1]
|
| 58 |
-
print(f"Arr: \n{arr}")
|
|
|
|
|
|
|
| 59 |
|
| 60 |
fen_long = "/".join(arr)
|
| 61 |
-
print(f"FEN long: \n{fen_long}")
|
| 62 |
|
| 63 |
fen_short = self.__shortenFEN(fen_long)
|
| 64 |
-
print(f"FEN short: \n{fen_short}")
|
| 65 |
|
| 66 |
fen_enhanced = f"{fen_short} b - - 0 1"
|
|
|
|
| 67 |
|
| 68 |
_out = fen_enhanced
|
| 69 |
return _out
|
|
|
|
| 21 |
|
| 22 |
|
| 23 |
class FENTool(Tool):
|
| 24 |
+
name = "_my_fen_tool"
|
| 25 |
description = """
|
| 26 |
Convert a bord provided a s alist of chest pieces into FEN notation
|
| 27 |
"""
|
|
|
|
| 42 |
.replace('1111','4').replace('111','3').replace('11','2')
|
| 43 |
|
| 44 |
def forward(self, _inp: str) -> str:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
arr = textwrap.wrap(_inp, 8)
|
| 46 |
+
#print(f"Arr: \n{arr}")
|
| 47 |
|
| 48 |
arr = arr[::-1]
|
| 49 |
+
#print(f"Arr: \n{arr}")
|
| 50 |
+
|
| 51 |
+
arr = [row[::-1] for row in arr]
|
| 52 |
|
| 53 |
fen_long = "/".join(arr)
|
| 54 |
+
#print(f"FEN long: \n{fen_long}")
|
| 55 |
|
| 56 |
fen_short = self.__shortenFEN(fen_long)
|
| 57 |
+
#print(f"FEN short: \n{fen_short}")
|
| 58 |
|
| 59 |
fen_enhanced = f"{fen_short} b - - 0 1"
|
| 60 |
+
print(f"FEN: {fen_enhanced}")
|
| 61 |
|
| 62 |
_out = fen_enhanced
|
| 63 |
return _out
|
requirements.txt
CHANGED
|
@@ -5,6 +5,6 @@ gradio[oauth]
|
|
| 5 |
pytest
|
| 6 |
matplotlib
|
| 7 |
PyQt6
|
| 8 |
-
chess
|
| 9 |
opencv-python
|
| 10 |
-
torch
|
|
|
|
|
|
| 5 |
pytest
|
| 6 |
matplotlib
|
| 7 |
PyQt6
|
|
|
|
| 8 |
opencv-python
|
| 9 |
+
torch
|
| 10 |
+
stockfish
|
simple.py
CHANGED
|
@@ -10,12 +10,15 @@ from dotenv import load_dotenv
|
|
| 10 |
from my_reverse_string import ReverseStringTool
|
| 11 |
from my_image_load import ImageLoadTool
|
| 12 |
from my_chess_board_tool import ChessBoard
|
|
|
|
|
|
|
| 13 |
from PIL import Image
|
| 14 |
|
| 15 |
|
| 16 |
task_id = "cca530fc-4052-43b2-b130-b30968d8aa44"
|
| 17 |
|
| 18 |
MODEL_REASONING = "Qwen/Qwen2.5-Coder-32B-Instruct"
|
|
|
|
| 19 |
#MODEL_REASONING = "Qwen/Qwen2.5-72B-Instruct" not good
|
| 20 |
#"meta-llama/Meta-Llama-3-70B-Instruct"
|
| 21 |
# jayasuryajsk/chess-reasoner-qwen
|
|
@@ -34,7 +37,13 @@ PROMPT_TEMPLATES = PromptTemplates(
|
|
| 34 |
Use the tools provided. If you are going to use a tool, describe in detail how you are going
|
| 35 |
to use that particular tool and explain parameters used to invoke the tool.
|
| 36 |
|
| 37 |
-
Tools provided
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
|
| 39 |
YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of
|
| 40 |
numbers and/or strings.
|
|
@@ -71,11 +80,23 @@ PROMPT_TEMPLATES = PromptTemplates(
|
|
| 71 |
|
| 72 |
#question = f"Load an image for task id {task_id} and describe the chess position shown on the image. "
|
| 73 |
#question = f"Load an image for task id {task_id} and display it using matplotlib "
|
| 74 |
-
question = f"Load an image for task id {task_id}
|
|
|
|
| 75 |
|
| 76 |
chess_board_model_name = "my_chess_pieces_recognition.pth"
|
| 77 |
chess_board_model_dir = "/mnt/c/Users/krzsa/IdeaProjects/Agents-Course-Assignment/saved_models"
|
| 78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
reasoning_agent = CodeAgent(
|
| 80 |
name="CourseAssistant",
|
| 81 |
description="General AI Assistant",
|
|
@@ -83,13 +104,25 @@ reasoning_agent = CodeAgent(
|
|
| 83 |
ImageLoadTool(),
|
| 84 |
FinalAnswerTool(),
|
| 85 |
ReverseStringTool(),
|
| 86 |
-
ChessBoard(chess_board_model_name, chess_board_model_dir)
|
|
|
|
|
|
|
| 87 |
],
|
| 88 |
model=InferenceClientModel(model_id=MODEL_REASONING),
|
| 89 |
planning_interval=3, # This is where you activate planning!,
|
| 90 |
prompt_templates=PROMPT_TEMPLATES,
|
| 91 |
-
|
| 92 |
-
additional_authorized_imports=[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
)
|
| 94 |
|
| 95 |
reasoning_agent.run(question)
|
|
|
|
| 10 |
from my_reverse_string import ReverseStringTool
|
| 11 |
from my_image_load import ImageLoadTool
|
| 12 |
from my_chess_board_tool import ChessBoard
|
| 13 |
+
from my_fen_tool import FENTool
|
| 14 |
+
from my_chess_analysis_tool import ChessAnalysisTool
|
| 15 |
from PIL import Image
|
| 16 |
|
| 17 |
|
| 18 |
task_id = "cca530fc-4052-43b2-b130-b30968d8aa44"
|
| 19 |
|
| 20 |
MODEL_REASONING = "Qwen/Qwen2.5-Coder-32B-Instruct"
|
| 21 |
+
MODEL_CHESS = "jayasuryajsk/chess-reasoner-qwen"
|
| 22 |
#MODEL_REASONING = "Qwen/Qwen2.5-72B-Instruct" not good
|
| 23 |
#"meta-llama/Meta-Llama-3-70B-Instruct"
|
| 24 |
# jayasuryajsk/chess-reasoner-qwen
|
|
|
|
| 37 |
Use the tools provided. If you are going to use a tool, describe in detail how you are going
|
| 38 |
to use that particular tool and explain parameters used to invoke the tool.
|
| 39 |
|
| 40 |
+
Tools provided :
|
| 41 |
+
_my_image_load : load an image for given task_id ,
|
| 42 |
+
_my_chess_board : process an image and extract list of chess pieces ,
|
| 43 |
+
_my_fen_tool : convert list of chess pieces into FEN notation ,
|
| 44 |
+
_my_chess_analysis : analyze chess position provided in FEN notation and provide best move ,
|
| 45 |
+
_my_reverse_string : reverse a string ,
|
| 46 |
+
final_answer : provide final answer
|
| 47 |
|
| 48 |
YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of
|
| 49 |
numbers and/or strings.
|
|
|
|
| 80 |
|
| 81 |
#question = f"Load an image for task id {task_id} and describe the chess position shown on the image. "
|
| 82 |
#question = f"Load an image for task id {task_id} and display it using matplotlib "
|
| 83 |
+
question = (f"Load an image for task id {task_id}, extyract checc pieces position into FEN notation, and provide "
|
| 84 |
+
f"best move for black ")
|
| 85 |
|
| 86 |
chess_board_model_name = "my_chess_pieces_recognition.pth"
|
| 87 |
chess_board_model_dir = "/mnt/c/Users/krzsa/IdeaProjects/Agents-Course-Assignment/saved_models"
|
| 88 |
|
| 89 |
+
#chess_agent = CodeAgent(
|
| 90 |
+
# name="ChessAgent",
|
| 91 |
+
# description="Chess Board Analysis Agent",
|
| 92 |
+
# tools=[],
|
| 93 |
+
# model=InferenceClientModel(model_id=MODEL_CHESS),
|
| 94 |
+
# #planning_interval=3, # This is where you activate planning!,
|
| 95 |
+
# #prompt_templates=PROMPT_TEMPLATES,
|
| 96 |
+
# #managed_agents=[web_search_agent],
|
| 97 |
+
# additional_authorized_imports=[],
|
| 98 |
+
#)
|
| 99 |
+
|
| 100 |
reasoning_agent = CodeAgent(
|
| 101 |
name="CourseAssistant",
|
| 102 |
description="General AI Assistant",
|
|
|
|
| 104 |
ImageLoadTool(),
|
| 105 |
FinalAnswerTool(),
|
| 106 |
ReverseStringTool(),
|
| 107 |
+
ChessBoard(chess_board_model_name, chess_board_model_dir),
|
| 108 |
+
FENTool(),
|
| 109 |
+
ChessAnalysisTool()
|
| 110 |
],
|
| 111 |
model=InferenceClientModel(model_id=MODEL_REASONING),
|
| 112 |
planning_interval=3, # This is where you activate planning!,
|
| 113 |
prompt_templates=PROMPT_TEMPLATES,
|
| 114 |
+
managed_agents=[],
|
| 115 |
+
additional_authorized_imports=[
|
| 116 |
+
"PIL",
|
| 117 |
+
"chess",
|
| 118 |
+
"matplotlib",
|
| 119 |
+
"matplotlib.pyplot",
|
| 120 |
+
"my_chess_board_tool",
|
| 121 |
+
"my_fen_tool",
|
| 122 |
+
"my_image_load",
|
| 123 |
+
"my_reverse_string",
|
| 124 |
+
"my_chess_analysis_tool"
|
| 125 |
+
],
|
| 126 |
)
|
| 127 |
|
| 128 |
reasoning_agent.run(question)
|
test_tools.py
CHANGED
|
@@ -2,6 +2,7 @@ from my_reverse_string import ReverseStringTool
|
|
| 2 |
from my_image_load import ImageLoadTool
|
| 3 |
from my_chess_board_tool import ChessBoard
|
| 4 |
from my_fen_tool import FENTool
|
|
|
|
| 5 |
import pytest
|
| 6 |
import matplotlib.pyplot as plt
|
| 7 |
import matplotlib as mp
|
|
@@ -38,10 +39,11 @@ def test_tool_chess_board(_task_id,_exp):
|
|
| 38 |
assert pieces == _exp
|
| 39 |
|
| 40 |
|
|
|
|
| 41 |
@pytest.mark.parametrize("_pieces_list,_exp",
|
| 42 |
[
|
| 43 |
("1K1111111PP11111P11RBBqP1111n111Q1111111p11b11111pp111pp1k11r111",
|
| 44 |
-
"
|
| 45 |
])
|
| 46 |
def test_tool_fen(_pieces_list,_exp):
|
| 47 |
print(f"\nConverting pieces list to FEN: {_pieces_list}")
|
|
@@ -49,3 +51,15 @@ def test_tool_fen(_pieces_list,_exp):
|
|
| 49 |
fen = t.forward(_pieces_list)
|
| 50 |
print(f"Got result: {fen}")
|
| 51 |
assert fen == _exp
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
from my_image_load import ImageLoadTool
|
| 3 |
from my_chess_board_tool import ChessBoard
|
| 4 |
from my_fen_tool import FENTool
|
| 5 |
+
from my_chess_analysis_tool import ChessAnalysisTool
|
| 6 |
import pytest
|
| 7 |
import matplotlib.pyplot as plt
|
| 8 |
import matplotlib as mp
|
|
|
|
| 39 |
assert pieces == _exp
|
| 40 |
|
| 41 |
|
| 42 |
+
#@pytest.mark.skip(reason="disabled")
|
| 43 |
@pytest.mark.parametrize("_pieces_list,_exp",
|
| 44 |
[
|
| 45 |
("1K1111111PP11111P11RBBqP1111n111Q1111111p11b11111pp111pp1k11r111",
|
| 46 |
+
"3r2k1/pp3pp1/4b2p/7Q/3n4/PqBBR2P/5PP1/6K1 b - - 0 1")
|
| 47 |
])
|
| 48 |
def test_tool_fen(_pieces_list,_exp):
|
| 49 |
print(f"\nConverting pieces list to FEN: {_pieces_list}")
|
|
|
|
| 51 |
fen = t.forward(_pieces_list)
|
| 52 |
print(f"Got result: {fen}")
|
| 53 |
assert fen == _exp
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
@pytest.mark.parametrize("_fen,_exp",
|
| 57 |
+
[
|
| 58 |
+
("3r2k1/pp3pp1/4b2p/7Q/3n4/PqBBR2P/5PP1/6K1 b - - 0 1","d8d5")
|
| 59 |
+
])
|
| 60 |
+
def test_tool_chess_analysis(_fen,_exp):
|
| 61 |
+
print(f"\nAnalysing FEN: {_fen}")
|
| 62 |
+
t = ChessAnalysisTool()
|
| 63 |
+
best_move = t.forward(_fen)
|
| 64 |
+
print(f"Got result: {best_move}")
|
| 65 |
+
assert best_move == _exp
|