|
import os |
|
import logging |
|
import sys |
|
import time |
|
|
|
import markitdown |
|
import smolagents |
|
|
|
|
|
LOG = logging.getLogger(__name__) |
|
|
|
SYSTEM_PROMPT = """ |
|
You are a general AI assistant. I will ask you a question. Report your thoughts, and finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER]. YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string. |
|
|
|
The current date is April 30, 2025. |
|
|
|
Take the time to plan the steps to reach the solution. Show the steps and then execute the steps. |
|
|
|
The question is below: |
|
""" |
|
|
|
SUFFIX_PROMPT = """ |
|
Remember - The FINAL ANSWER must be a string, a number or a comma separated list that is only strings and numbers. No other output is allowed for a FINAL ANSWER! If any other output is provided other than a string, number or comma separated list that contains only strings and numbers, you fail. Don't fail. |
|
""" |
|
|
|
|
|
@smolagents.tool |
|
def convert_from_url(url: str) -> str: |
|
"""Convert data at a url into a markdown string. |
|
|
|
This method takes a url as input and converts the contents |
|
into a markdown. It can convert file formats such as |
|
pdf, excel, xlsx, csv, powerpoint, ppt, etc. |
|
|
|
It can also transcribe audio files such as mp3. |
|
|
|
Args: |
|
url: the url to access the file. If the file is on the |
|
local machine, the url should start with "file://" |
|
instead of the traditional "http://" or "https://". |
|
|
|
Returns: |
|
string that is in the markdown format. |
|
""" |
|
|
|
md = markitdown.MarkItDown(enable_plugins=False) |
|
result = md.convert(url) |
|
return result.text_content |
|
|
|
|
|
class BasicAgent: |
|
|
|
def check_results(self, final_answer, agent_memory): |
|
if isinstance(final_answer, str) or isinstance( |
|
final_answer, int) or isinstance(final_answer, float): |
|
return True |
|
failure = "FAILED! The final answer must be a string, a number or a comma separated list of strings and numbers." |
|
print(f"Feedback: {failure}") |
|
raise Exception(failure) |
|
|
|
def __init__(self): |
|
print("BasicAgent initializing.") |
|
|
|
|
|
|
|
|
|
|
|
|
|
self.manager_model_id = "meta-llama/Llama-3.3-70B-Instruct" |
|
self.manager_model = None |
|
|
|
self.code_model_id = "Qwen/Qwen2.5-Coder-32B-Instruct" |
|
self.code_model = None |
|
|
|
if not self.manager_model: |
|
self.manager_model = smolagents.HfApiModel( |
|
max_tokens=64000, |
|
temperature=0.3, |
|
model_id=self.manager_model_id, |
|
custom_role_conversions=None, |
|
) |
|
|
|
if not self.code_model: |
|
self.code_model = smolagents.HfApiModel( |
|
max_tokens=32000, |
|
temperature=0.3, |
|
model_id=self.code_model_id, |
|
custom_role_conversions=None, |
|
) |
|
|
|
print(f"NEW5: BasicAgent {self.manager_model_id=} {self.code_model_id=}") |
|
|
|
math_tools = [ |
|
smolagents.FinalAnswerTool(), |
|
] |
|
self.math_agent = smolagents.CodeAgent( |
|
name="date_time_math_agent", |
|
description="Handle date, time and math caclulations", |
|
model=self.code_model, |
|
tools=math_tools, |
|
max_steps=6, |
|
verbosity_level=2, |
|
planning_interval=None, |
|
additional_authorized_imports=["datetime", "time", "calendar"], |
|
) |
|
|
|
web_search_tools = [ |
|
smolagents.DuckDuckGoSearchTool(), |
|
smolagents.VisitWebpageTool(), |
|
smolagents.FinalAnswerTool() |
|
] |
|
|
|
self.web_search_agent = smolagents.CodeAgent( |
|
name="web_search_agent", |
|
description="Search the web", |
|
model=self.code_model, |
|
tools=web_search_tools, |
|
max_steps=6, |
|
verbosity_level=2, |
|
planning_interval=None, |
|
additional_authorized_imports=["duckduckgo_search"], |
|
) |
|
|
|
wikipedia_search_tools = [ |
|
smolagents.WikipediaSearchTool(), |
|
smolagents.VisitWebpageTool(), |
|
smolagents.FinalAnswerTool() |
|
] |
|
|
|
self.wikipedia_search_agent = smolagents.CodeAgent( |
|
name="wikipedia_search_agent", |
|
description="Best search of wikipedia pages", |
|
model=self.code_model, |
|
tools=wikipedia_search_tools, |
|
max_steps=6, |
|
verbosity_level=2, |
|
planning_interval=None, |
|
additional_authorized_imports=["wikipedia-api"], |
|
) |
|
|
|
manager_tools = [ |
|
convert_from_url, |
|
smolagents.FinalAnswerTool(), |
|
] |
|
self.manager_agent = smolagents.CodeAgent( |
|
name="manager_agent", |
|
description="Manger of other agents", |
|
tools=manager_tools, |
|
model=self.manager_model, |
|
add_base_tools=True, |
|
max_steps=15, |
|
verbosity_level=2, |
|
planning_interval=3, |
|
additional_authorized_imports=[ |
|
"duckduckgo_search", |
|
"wikipedia-api", |
|
"markitdown", |
|
"requests", |
|
"pandas", |
|
"io", |
|
], |
|
managed_agents=[ |
|
self.web_search_agent, |
|
self.wikipedia_search_agent, |
|
self.math_agent, |
|
|
|
], |
|
final_answer_checks=[self.check_results], |
|
) |
|
|
|
def __call__(self, question: str) -> str: |
|
print(f"Agent received question (first 50 chars): {question[:50]}...") |
|
prompt = f'{SYSTEM_PROMPT}\n\n{question}\n\n {SUFFIX_PROMPT}' |
|
answer = self.manager_agent.run(prompt) |
|
print(f"{answer=}") |
|
return answer |
|
|