Update agent.py
Browse files
agent.py
CHANGED
@@ -4,6 +4,7 @@ import requests
|
|
4 |
import tempfile
|
5 |
import pandas as pd
|
6 |
from openai import OpenAI
|
|
|
7 |
try:
|
8 |
from duckduckgo_search import DDGS
|
9 |
except ImportError:
|
@@ -38,7 +39,7 @@ class BasicAgent:
|
|
38 |
href = result.get('href', '')
|
39 |
formatted_results += f"{i}. {title}\n URL: {href}\n Description: {body}\n\n"
|
40 |
return formatted_results
|
41 |
-
except Exception
|
42 |
return ""
|
43 |
|
44 |
def excel_tool(self, file_url: str) -> str:
|
@@ -55,7 +56,7 @@ class BasicAgent:
|
|
55 |
return f"{round(total, 2)}"
|
56 |
total = df.select_dtypes(include='number').sum().sum()
|
57 |
return f"{round(total, 2)}"
|
58 |
-
except Exception
|
59 |
return ""
|
60 |
|
61 |
def fetch_file_url(self, task_id):
|
@@ -70,7 +71,6 @@ class BasicAgent:
|
|
70 |
return None
|
71 |
|
72 |
def solve_chess_image(self, image_url: str) -> str:
|
73 |
-
"""Uses GPT-4o Vision to answer a chess image question (requires image URL)."""
|
74 |
prompt = (
|
75 |
"You are a chess engine. Only answer with the best move for Black in algebraic notation (e.g., Qd1#). "
|
76 |
"Do not explain your reasoning, do not include any commentary, only the move."
|
@@ -92,32 +92,31 @@ class BasicAgent:
|
|
92 |
temperature=0.0,
|
93 |
)
|
94 |
result = response.choices[0].message.content.strip()
|
95 |
-
# Remove commentary, keep only first move if any
|
96 |
move = re.findall(r"\b([KQRNB]?[a-h]?[1-8]?x?[a-h][1-8](?:=[QRNB])?#?)\b", result)
|
97 |
if move:
|
98 |
return move[0]
|
99 |
return result
|
100 |
-
except Exception
|
101 |
return ""
|
102 |
|
103 |
def __call__(self, question: str, task_id: str = None) -> str:
|
104 |
file_url = self.fetch_file_url(task_id) if task_id else None
|
105 |
file_result = None
|
106 |
|
107 |
-
# --- Chess image detection (
|
108 |
if file_url and ("chess" in question.lower() or "move" in question.lower() or "image" in question.lower() or "position" in question.lower()):
|
109 |
-
|
110 |
-
if
|
111 |
-
return
|
112 |
|
113 |
-
# --- Excel
|
114 |
ext = file_url.split('.')[-1].lower() if file_url else ""
|
115 |
if file_url and (ext in ["xlsx", "xls"] or "excel" in question.lower() or "spreadsheet" in question.lower()):
|
116 |
file_result = self.excel_tool(file_url)
|
117 |
if file_result and re.match(r'^\d+(\.\d+)?$', file_result):
|
118 |
return file_result
|
119 |
|
120 |
-
# --- Web search + LLM
|
121 |
search_snippet = self.web_search(question)
|
122 |
prompt = PROMPT + f"\n\nWeb search results:\n{search_snippet}\n\nQuestion: {question}"
|
123 |
response = self.llm.chat.completions.create(
|
@@ -133,7 +132,7 @@ class BasicAgent:
|
|
133 |
final_line = line.split(":", 1)[-1].strip(" .\"'")
|
134 |
break
|
135 |
|
136 |
-
# --- Fallback
|
137 |
bads = [
|
138 |
"", "unknown", "unable to determine", "unable to provide page numbers",
|
139 |
"unable to access video content directly", "unable to analyze video content",
|
@@ -144,7 +143,6 @@ class BasicAgent:
|
|
144 |
]
|
145 |
norm_final = (final_line or "").lower()
|
146 |
if norm_final in bads or norm_final.startswith("unable") or norm_final.startswith("i'm sorry") or norm_final.startswith("i apologize"):
|
147 |
-
# Try to extract a plausible answer from web or file
|
148 |
numbers = re.findall(r'\b\d{2,}\b', search_snippet)
|
149 |
if numbers:
|
150 |
return numbers[0]
|
@@ -158,7 +156,6 @@ class BasicAgent:
|
|
158 |
file_words = re.findall(r'\b[A-Z][a-z]{2,}\b', str(file_result))
|
159 |
if file_words:
|
160 |
return file_words[0]
|
161 |
-
# --- Try to re-ask the LLM without apologies ---
|
162 |
retry_prompt = (
|
163 |
"Based ONLY on the search results and/or file content above, return a direct answer to the question. "
|
164 |
"If you do not know, make your best plausible guess. Do NOT apologize or say you cannot assist. "
|
|
|
4 |
import tempfile
|
5 |
import pandas as pd
|
6 |
from openai import OpenAI
|
7 |
+
|
8 |
try:
|
9 |
from duckduckgo_search import DDGS
|
10 |
except ImportError:
|
|
|
39 |
href = result.get('href', '')
|
40 |
formatted_results += f"{i}. {title}\n URL: {href}\n Description: {body}\n\n"
|
41 |
return formatted_results
|
42 |
+
except Exception:
|
43 |
return ""
|
44 |
|
45 |
def excel_tool(self, file_url: str) -> str:
|
|
|
56 |
return f"{round(total, 2)}"
|
57 |
total = df.select_dtypes(include='number').sum().sum()
|
58 |
return f"{round(total, 2)}"
|
59 |
+
except Exception:
|
60 |
return ""
|
61 |
|
62 |
def fetch_file_url(self, task_id):
|
|
|
71 |
return None
|
72 |
|
73 |
def solve_chess_image(self, image_url: str) -> str:
|
|
|
74 |
prompt = (
|
75 |
"You are a chess engine. Only answer with the best move for Black in algebraic notation (e.g., Qd1#). "
|
76 |
"Do not explain your reasoning, do not include any commentary, only the move."
|
|
|
92 |
temperature=0.0,
|
93 |
)
|
94 |
result = response.choices[0].message.content.strip()
|
|
|
95 |
move = re.findall(r"\b([KQRNB]?[a-h]?[1-8]?x?[a-h][1-8](?:=[QRNB])?#?)\b", result)
|
96 |
if move:
|
97 |
return move[0]
|
98 |
return result
|
99 |
+
except Exception:
|
100 |
return ""
|
101 |
|
102 |
def __call__(self, question: str, task_id: str = None) -> str:
|
103 |
file_url = self.fetch_file_url(task_id) if task_id else None
|
104 |
file_result = None
|
105 |
|
106 |
+
# --- Chess image detection (priority) ---
|
107 |
if file_url and ("chess" in question.lower() or "move" in question.lower() or "image" in question.lower() or "position" in question.lower()):
|
108 |
+
move = self.solve_chess_image(file_url)
|
109 |
+
if move and len(move) <= 6:
|
110 |
+
return move
|
111 |
|
112 |
+
# --- Excel file detection ---
|
113 |
ext = file_url.split('.')[-1].lower() if file_url else ""
|
114 |
if file_url and (ext in ["xlsx", "xls"] or "excel" in question.lower() or "spreadsheet" in question.lower()):
|
115 |
file_result = self.excel_tool(file_url)
|
116 |
if file_result and re.match(r'^\d+(\.\d+)?$', file_result):
|
117 |
return file_result
|
118 |
|
119 |
+
# --- Web search + LLM ---
|
120 |
search_snippet = self.web_search(question)
|
121 |
prompt = PROMPT + f"\n\nWeb search results:\n{search_snippet}\n\nQuestion: {question}"
|
122 |
response = self.llm.chat.completions.create(
|
|
|
132 |
final_line = line.split(":", 1)[-1].strip(" .\"'")
|
133 |
break
|
134 |
|
135 |
+
# --- Fallback for non-answers ---
|
136 |
bads = [
|
137 |
"", "unknown", "unable to determine", "unable to provide page numbers",
|
138 |
"unable to access video content directly", "unable to analyze video content",
|
|
|
143 |
]
|
144 |
norm_final = (final_line or "").lower()
|
145 |
if norm_final in bads or norm_final.startswith("unable") or norm_final.startswith("i'm sorry") or norm_final.startswith("i apologize"):
|
|
|
146 |
numbers = re.findall(r'\b\d{2,}\b', search_snippet)
|
147 |
if numbers:
|
148 |
return numbers[0]
|
|
|
156 |
file_words = re.findall(r'\b[A-Z][a-z]{2,}\b', str(file_result))
|
157 |
if file_words:
|
158 |
return file_words[0]
|
|
|
159 |
retry_prompt = (
|
160 |
"Based ONLY on the search results and/or file content above, return a direct answer to the question. "
|
161 |
"If you do not know, make your best plausible guess. Do NOT apologize or say you cannot assist. "
|