|
|
|
import os |
|
import requests |
|
import pandas as pd |
|
import google.genai as genai |
|
import base64 |
|
from openai import OpenAI |
|
from smolagents import Tool |
|
|
|
|
|
from consts import DEFAULT_API_URL |
|
|
|
|
|
try: |
|
from app import _SELECTED_MODEL_ID |
|
if not _SELECTED_MODEL_ID: |
|
raise ImportError("Model ID not set in app.py") |
|
except ImportError: |
|
_SELECTED_MODEL_ID = "gpt-4.1-mini" |
|
|
|
class GetTaskFileTool(Tool): |
|
name = "get_task_file_tool" |
|
description = """This tool downloads the file content associated with the given task_id if exists. Returns absolute file path""" |
|
inputs = { |
|
"task_id": {"type": "string", "description": "Task id"}, |
|
"file_name": {"type": "string", "description": "File name"}, |
|
} |
|
output_type = "string" |
|
|
|
def forward(self, task_id: str, file_name: str) -> str: |
|
response = requests.get(f"{DEFAULT_API_URL}/files/{task_id}", timeout=15) |
|
response.raise_for_status() |
|
with open(file_name, 'wb') as file: |
|
file.write(response.content) |
|
return os.path.abspath(file_name) |
|
|
|
class LoadXlsxFileTool(Tool): |
|
name = "load_xlsx_file_tool" |
|
description = """This tool loads xlsx file into pandas and returns it""" |
|
inputs = { |
|
"file_path": {"type": "string", "description": "File path"} |
|
} |
|
output_type = "object" |
|
|
|
def forward(self, file_path: str) -> object: |
|
return pd.read_excel(file_path) |
|
|
|
class LoadTextFileTool(Tool): |
|
name = "load_text_file_tool" |
|
description = """This tool loads any text file""" |
|
inputs = { |
|
"file_path": {"type": "string", "description": "File path"} |
|
} |
|
output_type = "string" |
|
|
|
def forward(self, file_path: str) -> object: |
|
with open(file_path, 'r', encoding='utf-8') as file: |
|
return file.read() |
|
|
|
class AnalyzeImageTool(Tool): |
|
name = "analyze_image_tool" |
|
description = """This tool performs a custom analysis of the provided image and returns the corresponding result.""" |
|
inputs = { |
|
"image_path": {"type": "string", "description": "Image path"}, |
|
"task": {"type": "string", "description": "Task to perform on the image, be detailed and clear"}, |
|
} |
|
output_type = "string" |
|
|
|
def __init__(self, model_id=None): |
|
super().__init__() |
|
self.model_id = model_id or "gpt-4.1-mini" |
|
|
|
def forward(self, image_path: str, task: str) -> str: |
|
""" |
|
Analyze the image at `image_path` according to `task` and return the textual result. |
|
""" |
|
header = "Image analysis result:\n\n" |
|
llm_instruction = ( |
|
"You are a highly capable image analysis tool, designed to examine images and deliver detailed descriptions, " |
|
"insights, and relevant interpretations based on the task at hand.\n\n" |
|
"Approach the task methodically and provide a thorough and well-reasoned response to the following:\n\n---\nTask:\n" |
|
f"{task}\n\n" |
|
) |
|
try: |
|
if "gemini" in self.model_id: |
|
return header + self._analyze_with_gemini(image_path, llm_instruction) |
|
return header + self._analyze_with_openai(image_path, llm_instruction) |
|
except Exception as e: |
|
return f"Error analyzing image: {e}.\nPlease try again." |
|
|
|
def _analyze_with_gemini(self, image_path: str, task: str) -> str: |
|
api_key = os.getenv("GOOGLEAI_API_KEY") |
|
if not api_key: |
|
raise ValueError("Environment variable GOOGLEAI_API_KEY is not set.") |
|
client = genai.Client(api_key=api_key) |
|
|
|
with open(image_path, "rb") as f: |
|
image_data = f.read() |
|
|
|
contents = [ |
|
{"inline_data": {"mime_type": "image/jpeg", "data": image_data}}, |
|
{"text": task}, |
|
] |
|
response = client.models.generate_content(model=self.model_id, contents=contents) |
|
return response.candidates[0].content.parts[0].text |
|
|
|
def _analyze_with_openai(self, image_path: str, task: str) -> str: |
|
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) |
|
|
|
with open(image_path, "rb") as f: |
|
encoded_image = base64.b64encode(f.read()).decode("utf-8") |
|
|
|
payload = [ |
|
{ |
|
"role": "user", |
|
"content": [ |
|
{"type": "input_text", "text": task}, |
|
{"type": "input_image", "image_url": f"data:image/jpeg;base64,{encoded_image}"}, |
|
], |
|
} |
|
] |
|
response = client.responses.create(model=self.model_id, input=payload) |
|
return response.output[0].content[0].text |
|
|