Spaces:
Sleeping
Sleeping
import os | |
from dotenv import load_dotenv | |
# Import models from SmolaAgents | |
from smolagents import CodeAgent, LiteLLMModel, OpenAIServerModel | |
# Import SmolaAgents tools | |
from smolagents.default_tools import FinalAnswerTool, PythonInterpreterTool | |
# Import custom tools | |
from tools import ( | |
AddDocumentToVectorStoreTool, | |
ArxivSearchTool, | |
DownloadFileFromLinkTool, | |
DuckDuckGoSearchTool, | |
QueryVectorStoreTool, | |
ReadFileContentTool, | |
TranscibeVideoFileTool, | |
TranscribeAudioTool, | |
VisitWebpageTool, | |
WikipediaSearchTool, | |
image_question_answering | |
) | |
# Import utility functions | |
from utils import extract_final_answer, replace_tool_mentions | |
class BoomBot: | |
def __init__(self, provider="meta"): | |
""" | |
Initialize the BoomBot with the specified provider. | |
Args: | |
provider (str): The model provider to use (e.g., "groq", "qwen", "gemma", "anthropic", "deepinfra", "meta") | |
""" | |
load_dotenv() | |
self.provider = provider | |
self.model = self._initialize_model() | |
self.agent = self._create_agent() | |
def _initialize_model(self): | |
""" | |
Initialize the appropriate model based on the provider. | |
Returns: | |
The initialized model object | |
""" | |
if self.provider == "qwen": | |
qwen_model = "ollama_chat/qwen3:8b" | |
return LiteLLMModel( | |
model_id=qwen_model, | |
device="cuda", | |
num_ctx=32768, | |
temperature=0.6, | |
top_p=0.95, | |
) | |
elif self.provider == "gemma": | |
gemma_model = "ollama_chat/gemma3:12b-it-qat" | |
return LiteLLMModel( | |
model_id=gemma_model, | |
num_ctx=65536, | |
temperature=1.0, | |
device="cuda", | |
top_k=64, | |
top_p=0.95, | |
min_p=0.0, | |
) | |
elif self.provider == "anthropic": | |
model_id = "anthropic/claude-3-5-sonnet-latest" | |
return LiteLLMModel(model_id=model_id, temperature=0.6, max_tokens=8192) | |
elif self.provider == "deepinfra": | |
deepinfra_model = "Qwen/Qwen3-235B-A22B" | |
return OpenAIServerModel( | |
model_id=deepinfra_model, | |
api_base="https://api.deepinfra.com/v1/openai", | |
# api_key=os.environ["DEEPINFRA_API_KEY"], | |
flatten_messages_as_text=True, | |
max_tokens=8192, | |
temperature=0.1, | |
) | |
elif self.provider == "meta": | |
meta_model = "meta-llama/Llama-3.3-70B-Instruct-Turbo" | |
return OpenAIServerModel( | |
model_id=meta_model, | |
api_base="https://api.deepinfra.com/v1/openai", | |
# api_key=os.environ["DEEPINFRA_API_KEY"], | |
flatten_messages_as_text=True, | |
max_tokens=8192, | |
temperature=0.7, | |
) | |
elif self.provider == "groq": | |
# Default to use groq's claude-3-opus or llama-3 | |
model_id = "claude-3-opus-20240229" | |
return LiteLLMModel(model_id=model_id, temperature=0.7, max_tokens=8192) | |
else: | |
raise ValueError(f"Unsupported provider: {self.provider}") | |
def _create_agent(self): | |
""" | |
Create and configure the agent with all necessary tools. | |
Returns: | |
The configured CodeAgent | |
""" | |
# Initialize tools | |
download_file = DownloadFileFromLinkTool() | |
read_file_content = ReadFileContentTool() | |
visit_webpage = VisitWebpageTool() | |
transcribe_video = TranscibeVideoFileTool() | |
transcribe_audio = TranscribeAudioTool() | |
get_wikipedia_info = WikipediaSearchTool() | |
web_searcher = DuckDuckGoSearchTool() | |
arxiv_search = ArxivSearchTool() | |
add_doc_vectorstore = AddDocumentToVectorStoreTool() | |
retrieve_doc_vectorstore = QueryVectorStoreTool() | |
# SmolaAgents default tools | |
python_interpreter = PythonInterpreterTool() | |
final_answer = FinalAnswerTool() | |
# Combine all tools | |
agent_tools = [ | |
web_searcher, | |
download_file, | |
read_file_content, | |
visit_webpage, | |
transcribe_video, | |
transcribe_audio, | |
get_wikipedia_info, | |
arxiv_search, | |
add_doc_vectorstore, | |
retrieve_doc_vectorstore, | |
image_question_answering, | |
python_interpreter, | |
final_answer, | |
] | |
# Additional imports for the Python interpreter | |
additional_imports = [ | |
"json", | |
"os", | |
"glob", | |
"pathlib", | |
"pandas", | |
"numpy", | |
"matplotlib", | |
"seaborn", | |
"sklearn", | |
"tqdm", | |
"argparse", | |
"pickle", | |
"io", | |
"re", | |
"datetime", | |
"collections", | |
"math", | |
"random", | |
"csv", | |
"zipfile", | |
"itertools", | |
"functools", | |
] | |
# Create the agent | |
agent = CodeAgent( | |
tools=agent_tools, | |
max_steps=12, | |
model=self.model, | |
add_base_tools=False, | |
stream_outputs=True, | |
additional_authorized_imports=additional_imports, | |
) | |
# Modify the system prompt | |
modified_prompt = replace_tool_mentions(agent.system_prompt) | |
agent.system_prompt = modified_prompt | |
return agent | |
def _get_system_prompt(self): | |
""" | |
Return the system prompt for the agent. | |
Returns: | |
str: The system prompt | |
""" | |
return """ | |
YOUR BEHAVIOR GUIDELINES: | |
• Do NOT make unfounded assumptions—always ground answers in reliable sources or search results. | |
• For math or puzzles: break the problem into code/math, then solve programmatically. | |
RESEARCH WORKFLOW (in rough priority order): | |
1. SEARCH | |
- Try web_search, wikipedia_search, or arxiv_search first. | |
- Refine your query rather than repeating the exact same terms. | |
- If one search tool yields insufficient info, switch to another before downloading. | |
2. VISIT | |
- Use visit_webpage to extract and read page content when a promising link appears after one of the SEARCH tools. | |
- For each visited link, also download the file and add to the vector store, you might need to query this later, especially if you have a lot of search results. | |
3. EVALUATE | |
- ✅ If the page or search snippet fully answers the question, respond immediately. | |
- ❌ If not, move on to deeper investigation. | |
4. DOWNLOAD | |
- Use download_file_from_link tool on relevant links found (yes you can download webpages as html). | |
- For arXiv papers, target the /pdf/ or DOI link (e.g https://arxiv.org/pdf/2011.10672). | |
- | |
5. INDEX & QUERY | |
- Add downloaded documents to the vector store with add_document_to_vector_store. | |
- Use query_downloaded_documents for detailed answers. | |
6. READ | |
- You have access to a read_file_content tool to read most types of files. You can also directly interact with downloaded files in your python code (do this for csv files and excel files) | |
FALLBACK & ADAPTATION: | |
• If a tool fails, reformulate your query or try a different search method before dropping to download. | |
• If a tool fails multiple times, try a different tool. | |
• For arXiv: you might discover a paper link via web_search tool and then directly use download_file_from_link tool | |
COMMON TOOL CHAINS (conceptual outlines): | |
These are just guidelines, each task might require a unique workflow. | |
A tool can provide useful information for the task, it will not always contain the answer. You need to work to get to a final_answer that makes sense. | |
• FACTUAL Qs: | |
web_search → final_answer | |
• CURRENT EVENTS: | |
To have some summary information use web_search, that might output a promising website to visit and read content from using (visit_webpage or download_file_from_link and read_file_content) | |
web_search → visit_webpage → final_answer | |
• DOCUMENT-BASED Qs: | |
web_search → download_file_from_link → add_document_to_vector_store → query_downloaded_documents → final_answer | |
• ARXIV PAPERS: | |
The arxiv search tool provides a list of results with summary content, to inspect the whole paper you need to download it with download_file_from_link tool. | |
arxiv_search → download_file_from_link → read_file_content | |
If that fails | |
arxiv_search → download_file_from_link → add_document_to_vector_store → query_downloaded_documents | |
• MEDIA ANALYSIS: | |
download_file_from_link → transcribe_video/transcribe_audio/describe_image → final_answer | |
FINAL ANSWER FORMAT: | |
- Begin with "FINAL ANSWER: " | |
- Number → digits only (e.g., 42) | |
- String → exact text (e.g., Pope Francis) | |
- List → comma-separated, one space (e.g., 2, 3, 4) | |
- Conclude with: FINAL ANSWER: <your_answer> | |
""" | |
def run(self, question: str, task_id: str, to_download) -> str: | |
""" | |
Run the agent with the given question, task_id, and download flag. | |
Args: | |
question (str): The question or task for the agent to process | |
task_id (str): A unique identifier for the task | |
to_download (Bool): Flag indicating whether to download resources | |
Returns: | |
str: The agent's response | |
""" | |
prompt = self._get_system_prompt() | |
# Task introduction | |
prompt += "\nHere is the Task you need to solve:\n\n" | |
prompt += f"Task: {question}\n\n" | |
# Include download instructions if applicable | |
if to_download: | |
link = f"https://agents-course-unit4-scoring.hf.space/files/{task_id}" | |
prompt += ( | |
"IMPORTANT: Before solving the task, you must download a required file.\n" | |
f"Use the `download_file_from_link` tool with this link: {link}\n" | |
"After downloading, use the appropriate tool to read or process the file " | |
"before attempting to solve the task.\n\n" | |
) | |
# Run the agent with the given question | |
result = self.agent.generate_response(question) | |
# Extract the final answer from the result | |
final_answer = extract_final_answer(result) | |
return final_answer | |
# Example of how to use this code (commented out) | |
# if __name__ == "__main__": | |
# agent = BasicAgent() | |
# response = agent("What is the current population of Tokyo?", "population_query", True) | |
# print(f"Response: {response}") | |