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 |
|