| from smolagents import CodeAgent, tool, OpenAIServerModel |
| import requests |
| import io |
| from PIL import Image |
| from constants import DEFAULT_API_URL |
|
|
| class BasicAgent: |
| def __init__(self, OPENROUTER_API: str, OPENROUTER_MODEL: str, api_url: str): |
| self.api_url = api_url |
| self.model = OpenAIServerModel( |
| model_id=OPENROUTER_MODEL, |
| api_base="https://openrouter.ai/api/v1", |
| api_key=OPENROUTER_API |
| ) |
| self.agent = None |
|
|
| def initialize_agent(self): |
| self.agent = CodeAgent( |
| model=self.model, |
| tools=[get_file], |
| add_base_tools=True, |
| additional_authorized_imports=['pandas', 'io'] |
| ) |
| |
| return self.agent |
|
|
|
|
| def run(self, input: tuple): |
| id, question, file = input |
|
|
| |
| img = None |
| if file and file.split('.')[1] == 'png': |
| img = [Image.open(get_file(file))] |
|
|
| |
| prompt = f""" |
| You are CodeAgent assistant. The user asks you a question and you provide them with a verified and specific answer. |
| As an agent you have some tools to use. You may use them on demand. |
| Your normal workflow should follow the following sequence: |
| 1. You received the question and (in some cases) additional information as a file_id. You analize it. |
| 2. At the planning stage you making a sequence of steps to complete this task in planning variable |
| 3. At the execution stage you provide an executable python code which will be parsed and executed by the program. |
| Remember to provide executable code here, without any additional characters which may crash the execution and parsing. |
| 4. After execution you decide whether you had a final result an you can close the task providing this result or you should continue. |
| If ccontinue, review you previous planning sequence: what is done, what should be change in this plan or what we should add to it? |
| EACH STEP INCLUDES BOTH PLANNING AND EXECUTIONS STAGES: |
| * you provide planning in a separate variable at the beggining of your answer, variable name: planning |
| * execution is the rest code where you trying to achive the planned goals. |
| |
| The example: |
| User: What is Axelord? |
| [Step 1] |
| Agent: |
| Planning stage: |
| planning = " |
| Okay, user want me to tell him what is Axelord. I do not have this answer in my memory so I need to find it. |
| Plan: |
| 1. To search: What is Axelord. |
| 2. Provide an aswer. |
| " |
| Execution stage: |
| query = "What is Axelord?" |
| search_result = web_search(query) |
| print(search_result) |
| Result: |
| The pages about this topic. |
| Output: |
| None |
| [Step 2] |
| Agent: |
| Planning stage: |
| planning = " |
| Okay, I found some websites about that. |
| Plan: |
| 1. To search: What is Axelord. - DONE. |
| 2. Visit the webpage to get more inforamtion. |
| 3. Provide an answer. |
| " |
| Execution stage: |
| url = "https://en.wikipedia.org/wiki/Axelord" |
| wikipedia_page = visit_webpage(url) |
| print(wikipedia_page) |
| Result: |
| page html output which contains an answer. |
| Output: |
| FinalAnswerTool(Answer) |
| |
| In the example above you saw how you can use searching tools, but you also has some others. |
| You complete the task step by step. You recognise when the planning stage and you can do planning, and when |
| the execution stage and you MUST provide an executable python code. |
| |
| The user's question is: |
| {question} |
| |
| --- |
| Additional information you may use: |
| file_id: {file} |
| |
| IMPORTANT: |
| * You do not answer in plain text. |
| * You only answer in python code. Every plain text you need to provide you should include in a text variable |
| * You may receive both images sometimes as a context. Do not forget to use them to handle the task. |
| """ |
|
|
| |
| return self.agent.run( |
| task = prompt, |
| images = img |
| ) |
|
|
| |
| @tool |
| def get_file(file_id: str) -> io.BytesIO | io.StringIO | None: |
| """A tool that fetches the file's content from the server. |
| Use it every time you need to get file for completing the task. |
| IMPORTANT: ONLY USE IT WHEN THE FILE_ID ARGUMENT IS NOT EMPTY. |
| YOU MUST ENSURE THAT FILE_ID ARGUMENT IS NOT EMPTY WHEN YOU USE IT. |
| Args: |
| file_id: id of a file required to fetch |
| Returns: |
| io.BytesIO: file emulation for .xlsx or .png files. You can use this object as a file itself. It is already converted to BytesIO. |
| io.StringIO: file emulation for .py files. You can use this object as a file itself. It is already converted to StringIO. |
| """ |
| |
| response = requests.get(DEFAULT_API_URL+'/files/'+file_id.split('.')[0], timeout=15) |
| response.raise_for_status() |
|
|
| |
| file_format = file_id.split('.')[1] |
| match file_format: |
| case 'png': |
| print('png uploaded') |
| return io.BytesIO(response.content) |
| case 'xlsx': |
| print('xlsx uploaded') |
| return io.BytesIO(response.content) |
| case 'py': |
| print('py uploaded') |
| return io.StringIO(response.text) |
| case _: |
| return None |
|
|