import os import logging import sys import time import markitdown import smolagents # Logs appear to be swallowed. 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. """ # Don't need third-party plugins. 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.") # too big # self.manager_model_id = "google/gemma-3-27B-it" # self.manager_model_id = "OpenGVLab/InternVL3-14B" # self.manager_model_id = "AIDC-AI/Ovis2-34B" 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, # self.convert_files_to_markdown, ], 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