|
""" |
|
OpenSearchAgent - A web search agent for answering questions using the internet |
|
|
|
This module implements a powerful agent that can search the web, navigate pages, |
|
and analyze content to answer complex questions. It uses the smolagents library |
|
to create a hierarchical agent system with a manager agent and a web browser agent. |
|
|
|
The agent can: |
|
- Search the web using Google (via SerpAPI) |
|
- Visit and navigate web pages |
|
- Find and analyze text content |
|
- Process PDF files and other document formats |
|
- Visualize content when needed |
|
|
|
Environment variables required: |
|
- SERPAPI_API_KEY: API key for SerpAPI (for web search) |
|
- OPENAI_API_KEY: API key for OpenAI (for the language model) |
|
- HF_TOKEN: Hugging Face token (for accessing HF resources) |
|
""" |
|
|
|
import os |
|
import threading |
|
|
|
from dotenv import load_dotenv |
|
from huggingface_hub import login |
|
from scripts.text_inspector_tool import TextInspectorTool |
|
from scripts.text_web_browser import ( |
|
ArchiveSearchTool, |
|
FinderTool, |
|
FindNextTool, |
|
PageDownTool, |
|
PageUpTool, |
|
SimpleTextBrowser, |
|
VisitTool, |
|
) |
|
from scripts.visual_qa import visualizer |
|
|
|
from smolagents import ( |
|
CodeAgent, |
|
GoogleSearchTool, |
|
|
|
LiteLLMModel, |
|
ToolCallingAgent, |
|
OpenAIServerModel, |
|
) |
|
|
|
|
|
|
|
load_dotenv(override=True) |
|
login(os.getenv("HF_TOKEN")) |
|
|
|
|
|
custom_role_conversions = {"tool-call": "assistant", "tool-response": "user"} |
|
|
|
|
|
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0" |
|
|
|
|
|
BROWSER_CONFIG = { |
|
"viewport_size": 1024 * 5, |
|
"downloads_folder": "downloads_folder", |
|
"request_kwargs": { |
|
"headers": {"User-Agent": user_agent}, |
|
"timeout": 300, |
|
}, |
|
"serpapi_key": os.getenv("SERPAPI_API_KEY"), |
|
} |
|
|
|
|
|
os.makedirs(f"./{BROWSER_CONFIG['downloads_folder']}", exist_ok=True) |
|
|
|
|
|
class OpenSearchAgent: |
|
""" |
|
A portable agent that can search the web and answer questions. |
|
This class encapsulates the functionality of the web search agent. |
|
""" |
|
|
|
def __init__(self, model_id="o1"): |
|
""" |
|
Initialize the OpenSearchAgent with the specified model. |
|
|
|
Args: |
|
model_id (str): The model ID to use for the agent. Default is "o1". |
|
Other options include "gpt-4o", "claude-3-opus", etc. |
|
""" |
|
self.model_id = model_id |
|
self.agent = self._create_agent() |
|
|
|
def _create_agent(self): |
|
""" |
|
Create and configure the agent with the appropriate tools and models. |
|
|
|
This is where you can customize the agent by adding new tools or |
|
changing the configuration of existing ones. |
|
|
|
Returns: |
|
CodeAgent: The configured agent ready to answer questions. |
|
""" |
|
|
|
model_params = { |
|
"model_id": self.model_id, |
|
"custom_role_conversions": custom_role_conversions, |
|
"max_completion_tokens": 8192, |
|
} |
|
if self.model_id == "o1": |
|
model_params["reasoning_effort"] = "high" |
|
print(f"Using model parameters: {model_params}") |
|
|
|
|
|
|
|
|
|
model = OpenAIServerModel(model_id="gpt-4o") |
|
|
|
|
|
text_limit = 100000 |
|
browser = SimpleTextBrowser(**BROWSER_CONFIG) |
|
|
|
|
|
|
|
WEB_TOOLS = [ |
|
GoogleSearchTool(provider="serpapi"), |
|
VisitTool(browser), |
|
PageUpTool(browser), |
|
PageDownTool(browser), |
|
FinderTool(browser), |
|
FindNextTool(browser), |
|
ArchiveSearchTool(browser), |
|
TextInspectorTool(model, text_limit), |
|
|
|
|
|
|
|
|
|
|
|
|
|
] |
|
|
|
|
|
text_webbrowser_agent = ToolCallingAgent( |
|
model=model, |
|
tools=WEB_TOOLS, |
|
max_steps=20, |
|
verbosity_level=2, |
|
planning_interval=4, |
|
name="search_agent", |
|
description="""A team member that will search the internet to answer your question. |
|
Ask him for all your questions that require browsing the web. |
|
Provide him as much context as possible, in particular if you need to search on a specific timeframe! |
|
And don't hesitate to provide him with a complex search task, like finding a difference between two webpages. |
|
Your request must be a real sentence, not a google search! Like "Find me this information (...)" rather than a few keywords. |
|
""", |
|
provide_run_summary=True, |
|
) |
|
|
|
|
|
text_webbrowser_agent.prompt_templates["managed_agent"]["task"] += """You can navigate to .txt online files. |
|
If a non-html page is in another format, especially .pdf or a Youtube video, use tool 'inspect_file_as_text' to inspect it. |
|
Additionally, if after some searching you find out that you need more information to answer the question, you can use `final_answer` with your request for clarification as argument to request for more information.""" |
|
|
|
|
|
|
|
|
|
manager_agent = CodeAgent( |
|
model=model, |
|
tools=[ |
|
visualizer, |
|
TextInspectorTool(model, text_limit), |
|
|
|
|
|
|
|
|
|
|
|
], |
|
max_steps=12, |
|
verbosity_level=2, |
|
additional_authorized_imports=["*"], |
|
planning_interval=4, |
|
managed_agents=[ |
|
text_webbrowser_agent, |
|
|
|
|
|
|
|
|
|
|
|
], |
|
) |
|
|
|
return manager_agent |
|
|
|
def __call__(self, question: str) -> str: |
|
""" |
|
Run the agent on the given question. |
|
|
|
Args: |
|
question (str): The question to answer. |
|
|
|
Returns: |
|
str: The agent's answer to the question. |
|
""" |
|
print(f"OpenSearchAgent received question: {question[:50]}...") |
|
answer = self.agent.run(question) |
|
|
|
|
|
answer_str = str(answer) |
|
print(f"OpenSearchAgent found answer: {answer_str[:100]}...") |
|
|
|
return answer_str |
|
|
|
|
|
def main(): |
|
""" |
|
Example usage of the OpenSearchAgent. |
|
|
|
This function demonstrates how to create and use the OpenSearchAgent. |
|
You can modify the question or model_id to test different configurations. |
|
""" |
|
|
|
question = "How many studio albums did Mercedes Sosa release before 2007?" |
|
|
|
|
|
agent = OpenSearchAgent(model_id="o1") |
|
|
|
|
|
answer = agent(question) |
|
|
|
print(f"Got this answer: {answer}") |
|
|
|
|
|
if __name__ == "__main__": |
|
main() |
|
|