Refactored from agent to multi-agent
Browse files
agent.py
CHANGED
@@ -19,21 +19,54 @@ BASE_PYTHON_TOOLS["io"] = io
|
|
19 |
BASE_PYTHON_TOOLS["contextlib"] = contextlib
|
20 |
BASE_PYTHON_TOOLS["exec"] = exec
|
21 |
|
22 |
-
|
23 |
-
class BasicAgent:
|
24 |
def __init__(self, settings: Settings):
|
25 |
self.agent = CodeAgent(
|
|
|
|
|
26 |
add_base_tools=False,
|
27 |
tools=[GoogleSearchTool("serper"),
|
28 |
VisitWebpageTool(max_output_length=100000),
|
29 |
-
FinalAnswerTool(),
|
30 |
-
GetTaskFileTool(settings),
|
31 |
VideoUnderstandingTool(settings, GoogleModelID.GEMINI_2_0_FLASH),
|
32 |
-
AudioUnderstandingTool(settings, GoogleModelID.GEMINI_2_0_FLASH)
|
33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
ChessGameFenTool(settings, OpenRouterModelID.GPT_O4_MINI),
|
35 |
BestChessMoveTool(settings),
|
36 |
-
ConvertChessMoveTool(settings, OpenRouterModelID.QWEN_3_14B_FREE)
|
37 |
],
|
38 |
additional_authorized_imports=[
|
39 |
"unicodedata",
|
@@ -53,13 +86,28 @@ class BasicAgent:
|
|
53 |
max_steps=10,
|
54 |
verbosity_level=1,
|
55 |
model=LiteLLMModel(
|
56 |
-
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
# model_id=OpenRouterModelID.GROK_3_BETA,
|
59 |
# model_id=OpenRouterModelID.GROK_3_MINI_BETA,
|
|
|
60 |
api_key = settings.openrouter_api_key.get_secret_value(),
|
61 |
temperature=0.0, timeout=180
|
62 |
-
)
|
|
|
63 |
)
|
64 |
# print("BasicAgent initialized.")
|
65 |
def __call__(self, question: str) -> str:
|
|
|
19 |
BASE_PYTHON_TOOLS["contextlib"] = contextlib
|
20 |
BASE_PYTHON_TOOLS["exec"] = exec
|
21 |
|
22 |
+
class ResearchAgent:
|
|
|
23 |
def __init__(self, settings: Settings):
|
24 |
self.agent = CodeAgent(
|
25 |
+
name="researcher",
|
26 |
+
description="Searches the web, works with files, and answers questions for you. Give it your query as an argument.",
|
27 |
add_base_tools=False,
|
28 |
tools=[GoogleSearchTool("serper"),
|
29 |
VisitWebpageTool(max_output_length=100000),
|
|
|
|
|
30 |
VideoUnderstandingTool(settings, GoogleModelID.GEMINI_2_0_FLASH),
|
31 |
+
AudioUnderstandingTool(settings, GoogleModelID.GEMINI_2_0_FLASH)
|
32 |
+
],
|
33 |
+
additional_authorized_imports=[
|
34 |
+
"unicodedata",
|
35 |
+
"stat",
|
36 |
+
"datetime",
|
37 |
+
"random",
|
38 |
+
"pandas",
|
39 |
+
"itertools",
|
40 |
+
"math",
|
41 |
+
"statistics",
|
42 |
+
"queue",
|
43 |
+
"time",
|
44 |
+
"collections",
|
45 |
+
"re",
|
46 |
+
"os"
|
47 |
+
],
|
48 |
+
max_steps=10,
|
49 |
+
verbosity_level=1,
|
50 |
+
model=LiteLLMModel(
|
51 |
+
model_id=OpenRouterModelID.GPT_O4_MINI,
|
52 |
+
# model_id=OpenRouterModelID.GPT_4_1_MINI,
|
53 |
+
# model_id=OpenRouterModelID.GROK_3_BETA,
|
54 |
+
# model_id=OpenRouterModelID.GROK_3_MINI_BETA,
|
55 |
+
api_key = settings.openrouter_api_key.get_secret_value(),
|
56 |
+
temperature=0.0, timeout=180
|
57 |
+
)
|
58 |
+
)
|
59 |
+
|
60 |
+
class ChessAgent:
|
61 |
+
def __init__(self, settings: Settings):
|
62 |
+
self.agent = CodeAgent(
|
63 |
+
name="chess_player",
|
64 |
+
description="Makes a chess move. Give it a query including board image filepath and player turn (black or white).",
|
65 |
+
add_base_tools=False,
|
66 |
+
tools=[ChessPiecePlacementTool(),
|
67 |
ChessGameFenTool(settings, OpenRouterModelID.GPT_O4_MINI),
|
68 |
BestChessMoveTool(settings),
|
69 |
+
ConvertChessMoveTool(settings, OpenRouterModelID.QWEN_3_14B_FREE),
|
70 |
],
|
71 |
additional_authorized_imports=[
|
72 |
"unicodedata",
|
|
|
86 |
max_steps=10,
|
87 |
verbosity_level=1,
|
88 |
model=LiteLLMModel(
|
89 |
+
model_id=OpenRouterModelID.GPT_O4_MINI,
|
90 |
+
api_key = settings.openrouter_api_key.get_secret_value(),
|
91 |
+
temperature=0.0, timeout=180
|
92 |
+
)
|
93 |
+
)
|
94 |
+
|
95 |
+
class ManagerAgent:
|
96 |
+
def __init__(self, settings: Settings):
|
97 |
+
self.researcher = ResearchAgent(settings).agent
|
98 |
+
self.chess_player = ChessAgent(settings).agent
|
99 |
+
self.agent = CodeAgent(
|
100 |
+
tools=[GetTaskFileTool(settings), FinalAnswerTool()],
|
101 |
+
model=LiteLLMModel(
|
102 |
+
model_id=OpenRouterModelID.GPT_O4_MINI,
|
103 |
+
# model_id=OpenRouterModelID.GPT_4_1_MINI,
|
104 |
# model_id=OpenRouterModelID.GROK_3_BETA,
|
105 |
# model_id=OpenRouterModelID.GROK_3_MINI_BETA,
|
106 |
+
# model_id=OpenRouterModelID.QWEN_3_14B_FREE,
|
107 |
api_key = settings.openrouter_api_key.get_secret_value(),
|
108 |
temperature=0.0, timeout=180
|
109 |
+
),
|
110 |
+
managed_agents=[self.researcher, self.chess_player],
|
111 |
)
|
112 |
# print("BasicAgent initialized.")
|
113 |
def __call__(self, question: str) -> str:
|
runner.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
from settings import Settings
|
2 |
from models import Question, QuestionAnswerPair
|
3 |
-
from agent import
|
4 |
import pandas as pd
|
5 |
import logging
|
6 |
import json
|
@@ -9,7 +9,6 @@ import nest_asyncio
|
|
9 |
nest_asyncio.apply()
|
10 |
logger = logging.getLogger(__name__)
|
11 |
|
12 |
-
|
13 |
class Runner():
|
14 |
def __init__(self, settings: Settings):
|
15 |
self.settings = settings
|
@@ -28,8 +27,11 @@ class Runner():
|
|
28 |
f"{item.question} "
|
29 |
"Think hard to answer. Parse all statements in the question to make a plan. "
|
30 |
"Your final answer should be a number or as few words as possible. "
|
31 |
-
"
|
32 |
-
|
|
|
|
|
|
|
33 |
)
|
34 |
if file_name:
|
35 |
question_text = f"{question_text} file_name: {file_name} (use tools to fetch the file)"
|
@@ -40,7 +42,7 @@ class Runner():
|
|
40 |
task_id = item.task_id
|
41 |
question_text = self._enrich_question_text(item)
|
42 |
try:
|
43 |
-
answer = await asyncio.to_thread(
|
44 |
except Exception as e:
|
45 |
logger.error(f"Error running agent on task {task_id}: {e}")
|
46 |
answer = f"AGENT ERROR: {e}"
|
|
|
1 |
from settings import Settings
|
2 |
from models import Question, QuestionAnswerPair
|
3 |
+
from agent import ManagerAgent
|
4 |
import pandas as pd
|
5 |
import logging
|
6 |
import json
|
|
|
9 |
nest_asyncio.apply()
|
10 |
logger = logging.getLogger(__name__)
|
11 |
|
|
|
12 |
class Runner():
|
13 |
def __init__(self, settings: Settings):
|
14 |
self.settings = settings
|
|
|
27 |
f"{item.question} "
|
28 |
"Think hard to answer. Parse all statements in the question to make a plan. "
|
29 |
"Your final answer should be a number or as few words as possible. "
|
30 |
+
"Only use abbreviations when the question calls for abbreviations. "
|
31 |
+
"If needed, use a comma separated list of values; the comma is always followed by a space"
|
32 |
+
f"Critically review your answer before making it the final answer. "
|
33 |
+
f"Double check the answer to make sure it meets all format requirements stated in the question. "
|
34 |
+
f"task_id: {task_id}."
|
35 |
)
|
36 |
if file_name:
|
37 |
question_text = f"{question_text} file_name: {file_name} (use tools to fetch the file)"
|
|
|
42 |
task_id = item.task_id
|
43 |
question_text = self._enrich_question_text(item)
|
44 |
try:
|
45 |
+
answer = await asyncio.to_thread(ManagerAgent(self.settings), question_text)
|
46 |
except Exception as e:
|
47 |
logger.error(f"Error running agent on task {task_id}: {e}")
|
48 |
answer = f"AGENT ERROR: {e}"
|
tools.py
CHANGED
@@ -21,10 +21,10 @@ class BaseCustomTool(Tool):
|
|
21 |
|
22 |
class GetTaskFileTool(BaseCustomTool):
|
23 |
name = "get_task_file_tool"
|
24 |
-
description = """
|
25 |
inputs = {
|
26 |
-
"task_id": {"type": "string", "description": "Task ID"},
|
27 |
-
"file_name": {"type": "string", "description": "File name"},
|
28 |
}
|
29 |
output_type = "string"
|
30 |
|
|
|
21 |
|
22 |
class GetTaskFileTool(BaseCustomTool):
|
23 |
name = "get_task_file_tool"
|
24 |
+
description = """If a file_name is provided, download file associated with a given task_id. Get absolute file path"""
|
25 |
inputs = {
|
26 |
+
"task_id": {"type": "string", "description": "Task ID (required)"},
|
27 |
+
"file_name": {"type": "string", "description": "File name (required)"},
|
28 |
}
|
29 |
output_type = "string"
|
30 |
|