| from datetime import datetime, timezone |
| from dotenv import load_dotenv |
| from colorama import Fore, Style |
| from langchain.agents import create_agent |
| from langchain_core.messages import HumanMessage |
| from agent.api.api import get_llm |
| from agent.tools.math_solver import math_solver |
| from agent.tools.file_downloader import file_downloader |
| from agent.tools.ocr_reader import ocr_reader |
| from agent.tools.list_files import list_files |
| from agent.tools.http_get import http_get |
|
|
| from agent.agents.websearchagents import web_search_agents |
|
|
| |
| from agent.agents.answer_extractor import extract_answer |
|
|
| load_dotenv() |
|
|
|
|
| def supervisor_agent(): |
| """Return a supervisor agent instance with math_solver and websearch_agent.""" |
| return create_agent( |
| model=get_llm(), |
| |
| tools=[ |
| math_solver, |
| web_search_agents, |
| file_downloader, |
| ocr_reader, |
| list_files, |
| http_get, |
| ], |
| system_prompt=( |
| f"You are a supervisor agent. " |
| f"Current time is: {datetime.now(timezone.utc).isoformat()}. " |
| f"Your memory are out of date. " |
| f"For any math or calculation questions, use the math_solver tool for check, " |
| f"the accurate is the most important. " |
| f"All questions that need real-time, must use the web_search_agents tool " |
| f"to get a concise and accurate final answer. " |
| f"If an image or photo file is attached, download and use the ocr_reader tool " |
| f"to extract and describe the content before answering. " |
| f"Once you have found the answer, respond immediately. " |
| f"Do NOT continue searching or verifying unnecessarily — " |
| f"you have a limited number of action steps and must avoid exceeding them. " |
| f"If you do not have enough information to answer the question " |
| f"and no tool can help, respond with: " |
| f"'Insufficient information to provide an answer.'" |
| ), |
| ) |
|
|
|
|
| def run(query: str, file_url: str | None = None, max_retries: int = 3) -> str: |
| """Entry point: let the supervisor agent finish the work.""" |
| last_error: str | None = None |
|
|
| |
| full_query = query |
| if file_url: |
| full_query += f"\n\nAttached file URL: {file_url}" |
|
|
| for attempt in range(1, max_retries + 1): |
| print( |
| f"{Fore.CYAN}[Supervisor] Processing query (attempt {attempt}/{max_retries})...\n" |
| f"[Supervisor] Query: {full_query}{Style.RESET_ALL}" |
| ) |
| agent = supervisor_agent() |
|
|
| messages = [HumanMessage(content=full_query)] |
| if last_error: |
| messages.append( |
| HumanMessage( |
| content=( |
| f"Previous attempt failed with error: {last_error}\n" |
| f"Try thinking about the problem more simply. " |
| f"Use fewer steps and a more straightforward approach." |
| ) |
| ) |
| ) |
|
|
| try: |
| result = agent.invoke( |
| {"messages": messages}, |
| |
| config={"recursion_limit": 30}, |
| ) |
| content = result["messages"][-1].content |
| if isinstance(content, list): |
| content = content[0].get("text", "") |
| else: |
| content = str(content) |
| return extract_answer(content, query) |
| except Exception as e: |
| last_error = str(e) |
| print( |
| f"{Fore.RED}[Supervisor] Attempt {attempt} failed: {last_error}{Style.RESET_ALL}" |
| ) |
|
|
| print(f"{Fore.RED}[Supervisor] All {max_retries} attempts failed.{Style.RESET_ALL}") |
| return extract_answer( |
| f"Agent failed after {max_retries} attempts. Last error: {last_error}", query |
| ) |
|
|
|
|
| if __name__ == "__main__": |
| |
| |
| agent = supervisor_agent() |
| chat_history: list = [] |
| while True: |
| query = input("\nYou: ") |
| if query.lower() in ("exit", "quit"): |
| break |
| chat_history.append(HumanMessage(content=query)) |
| result = agent.invoke({"messages": chat_history}) |
| chat_history = result["messages"] |
| content = chat_history[-1].content |
| if isinstance(content, list): |
| content = content[0].get("text", "") |
| print(f"Agent: {content}") |
|
|