|
from typing import Any, List, Optional |
|
|
|
from smolagents import CodeAgent |
|
|
|
from utils.logger import get_logger |
|
|
|
logger = get_logger(__name__) |
|
|
|
|
|
class Agent: |
|
""" |
|
Agent class that wraps a CodeAgent and provides a callable interface for answering questions. |
|
|
|
Args: |
|
model (Any): The language model to use. |
|
tools (Optional[List[Any]]): List of tools to provide to the agent. |
|
prompt (Optional[str]): Custom prompt template for the agent. |
|
""" |
|
|
|
def __init__( |
|
self, |
|
model: Any, |
|
tools: Optional[List[Any]] = None, |
|
prompt: Optional[str] = None, |
|
): |
|
logger.info("Initializing Agent") |
|
self.model = model |
|
self.tools = tools |
|
self.imports = [ |
|
"pandas", |
|
"numpy", |
|
"os", |
|
"requests", |
|
"tempfile", |
|
"datetime", |
|
"json", |
|
"time", |
|
"re", |
|
"openpyxl", |
|
"pathlib", |
|
"sys", |
|
] |
|
self.agent = CodeAgent( |
|
model=self.model, |
|
tools=self.tools, |
|
add_base_tools=True, |
|
additional_authorized_imports=self.imports, |
|
) |
|
self.prompt = prompt or ( |
|
""" |
|
You are an advanced AI assistant specialized in solving complex, real-world tasks that require multi-step reasoning, factual accuracy, and use of external tools. |
|
|
|
Follow these principles: |
|
- Be precise and concise. The final answer must strictly match the required format with no extra commentary. |
|
- Use tools intelligently. If a question involves external information, structured data, images, or audio, call the appropriate tool to retrieve or process it. |
|
- Reason step-by-step. Think through the solution logically and plan your actions carefully before answering. |
|
- Validate information. Always verify facts when possible instead of guessing. |
|
- Use code if needed. For calculations, parsing, or transformations, generate Python code and execute it. But be careful, some questions contains time-consuming tasks, so you should be careful with the code you run. Better analyze the question and think about the best way to solve it. |
|
- Don't forget to use `final_answer` to give the final answer. |
|
- Use name of file ONLY FROM "FILE:" section. THIS IF ALWAYS A FILE. |
|
|
|
IMPORTANT: When giving the final answer, output only the direct required result without any extra text like "Final Answer:" or explanations. YOU MUST RESPOND IN THE EXACT FORMAT AS THE QUESTION. |
|
|
|
QUESTION: {question} |
|
|
|
FILE: {context} |
|
|
|
ANSWER: |
|
""" |
|
) |
|
logger.info("Agent initialized") |
|
|
|
def __call__(self, question: str, file_path: Optional[str] = None) -> str: |
|
""" |
|
Run the agent to answer a question, optionally using a file as context. |
|
|
|
Args: |
|
question (str): The question to answer. |
|
file_path (Optional[str]): Path to a file to use as context (if any). |
|
|
|
Returns: |
|
str: The agent's answer as a string. |
|
""" |
|
answer = self.agent.run( |
|
self.prompt.format(question=question, context=file_path) |
|
) |
|
answer = str(answer).strip("'").strip('"').strip() |
|
return answer |
|
|