Spaces:
Runtime error
Runtime error
Initial commit with LlamaIndex-based agent
Browse files
app.py
CHANGED
@@ -43,6 +43,7 @@ class SmartAgent:
|
|
43 |
model_options = [
|
44 |
"microsoft/DialoGPT-medium", # Much smaller, works well for chat
|
45 |
"google/flan-t5-base", # Good for reasoning tasks
|
|
|
46 |
"HuggingFaceH4/zephyr-7b-beta" # Original (may fail in limited memory)
|
47 |
]
|
48 |
|
@@ -54,12 +55,13 @@ class SmartAgent:
|
|
54 |
self.llm = HuggingFaceLLM(
|
55 |
model_name=model_name,
|
56 |
tokenizer_name=model_name,
|
57 |
-
context_window=
|
58 |
-
max_new_tokens=
|
59 |
generate_kwargs={
|
60 |
-
"temperature": 0.
|
61 |
"do_sample": True,
|
62 |
-
"
|
|
|
63 |
},
|
64 |
device_map="auto",
|
65 |
# Add memory optimization parameters
|
@@ -67,7 +69,9 @@ class SmartAgent:
|
|
67 |
"torch_dtype": torch.float16, # Use half precision
|
68 |
"low_cpu_mem_usage": True,
|
69 |
"load_in_8bit": True, # Enable 8-bit quantization if available
|
70 |
-
}
|
|
|
|
|
71 |
)
|
72 |
print(f"Successfully loaded model: {model_name}")
|
73 |
|
@@ -88,8 +92,24 @@ class SmartAgent:
|
|
88 |
)
|
89 |
print(f"Successfully loaded fallback model: {fallback_model}")
|
90 |
except Exception as e2:
|
91 |
-
print(f"
|
92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
# Define tools with real implementations
|
95 |
self.tools = [
|
@@ -129,20 +149,21 @@ class SmartAgent:
|
|
129 |
|
130 |
try:
|
131 |
with DDGS() as ddgs:
|
132 |
-
results = list(ddgs.text(query, max_results=
|
133 |
if results:
|
134 |
formatted_results = []
|
135 |
for i, r in enumerate(results, 1):
|
136 |
title = r.get('title', 'No title')
|
137 |
-
body = r.get('body', 'No description')[:
|
138 |
url = r.get('href', '')
|
139 |
-
formatted_results.append(f"{i}. {title}
|
|
|
140 |
return "\n\n".join(formatted_results)
|
141 |
else:
|
142 |
-
return "No search results found for
|
143 |
except Exception as e:
|
144 |
print(f"Web search error: {e}")
|
145 |
-
return f"Error during web search: {str(e)}"
|
146 |
|
147 |
def math_calculator(self, expression: str) -> str:
|
148 |
"""Safe math evaluation using SymPy"""
|
@@ -171,34 +192,81 @@ class SmartAgent:
|
|
171 |
|
172 |
def __call__(self, question: str) -> str:
|
173 |
print(f"Processing question (first 50 chars): {question[:50]}...")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
try:
|
175 |
if self.agent:
|
|
|
176 |
response = self.agent.query(question)
|
177 |
-
|
178 |
-
else:
|
179 |
-
# Fallback: Direct tool usage based on question content
|
180 |
-
question_lower = question.lower()
|
181 |
-
if any(word in question_lower for word in ['calculate', 'math', 'equation', '+', '-', '*', '/', '=']):
|
182 |
-
# Try math calculator
|
183 |
-
math_terms = []
|
184 |
-
for word in question.split():
|
185 |
-
if any(char in word for char in '0123456789+-*/()'):
|
186 |
-
math_terms.append(word)
|
187 |
-
if math_terms:
|
188 |
-
expression = ' '.join(math_terms)
|
189 |
-
return self.math_calculator(expression)
|
190 |
|
191 |
-
|
192 |
-
|
193 |
-
|
|
|
194 |
|
195 |
-
|
196 |
-
|
|
|
|
|
197 |
|
198 |
except Exception as e:
|
199 |
print(f"Agent error: {str(e)}")
|
200 |
print(f"Full traceback: {traceback.format_exc()}")
|
201 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
202 |
|
203 |
|
204 |
# --- Memory cleanup function ---
|
|
|
43 |
model_options = [
|
44 |
"microsoft/DialoGPT-medium", # Much smaller, works well for chat
|
45 |
"google/flan-t5-base", # Good for reasoning tasks
|
46 |
+
"microsoft/DialoGPT-small", # Smallest fallback
|
47 |
"HuggingFaceH4/zephyr-7b-beta" # Original (may fail in limited memory)
|
48 |
]
|
49 |
|
|
|
55 |
self.llm = HuggingFaceLLM(
|
56 |
model_name=model_name,
|
57 |
tokenizer_name=model_name,
|
58 |
+
context_window=1024, # Increased for better reasoning
|
59 |
+
max_new_tokens=256, # Increased for better responses
|
60 |
generate_kwargs={
|
61 |
+
"temperature": 0.3, # Lower temperature for more focused responses
|
62 |
"do_sample": True,
|
63 |
+
"top_p": 0.9,
|
64 |
+
"repetition_penalty": 1.1
|
65 |
},
|
66 |
device_map="auto",
|
67 |
# Add memory optimization parameters
|
|
|
69 |
"torch_dtype": torch.float16, # Use half precision
|
70 |
"low_cpu_mem_usage": True,
|
71 |
"load_in_8bit": True, # Enable 8-bit quantization if available
|
72 |
+
},
|
73 |
+
# Add system message for better instruction following
|
74 |
+
system_message="You are a helpful AI assistant that can search the web and perform calculations. Always provide detailed, accurate answers."
|
75 |
)
|
76 |
print(f"Successfully loaded model: {model_name}")
|
77 |
|
|
|
92 |
)
|
93 |
print(f"Successfully loaded fallback model: {fallback_model}")
|
94 |
except Exception as e2:
|
95 |
+
print(f"Flan-T5 also failed: {e2}")
|
96 |
+
# Try an even more basic approach with a very small model
|
97 |
+
try:
|
98 |
+
basic_model = "microsoft/DialoGPT-small"
|
99 |
+
print(f"Final fallback to: {basic_model}")
|
100 |
+
self.llm = HuggingFaceLLM(
|
101 |
+
model_name=basic_model,
|
102 |
+
tokenizer_name=basic_model,
|
103 |
+
context_window=512,
|
104 |
+
max_new_tokens=128,
|
105 |
+
generate_kwargs={"temperature": 0.3, "do_sample": True},
|
106 |
+
device_map="cpu", # Force CPU to avoid memory issues
|
107 |
+
model_kwargs={"low_cpu_mem_usage": True}
|
108 |
+
)
|
109 |
+
print(f"Successfully loaded final fallback: {basic_model}")
|
110 |
+
except Exception as e3:
|
111 |
+
print(f"All model loading attempts failed: {e3}")
|
112 |
+
raise Exception("Unable to load any language model")
|
113 |
|
114 |
# Define tools with real implementations
|
115 |
self.tools = [
|
|
|
149 |
|
150 |
try:
|
151 |
with DDGS() as ddgs:
|
152 |
+
results = list(ddgs.text(query, max_results=5)) # Get more results
|
153 |
if results:
|
154 |
formatted_results = []
|
155 |
for i, r in enumerate(results, 1):
|
156 |
title = r.get('title', 'No title')
|
157 |
+
body = r.get('body', 'No description')[:300] # More context
|
158 |
url = r.get('href', '')
|
159 |
+
formatted_results.append(f"{i}. **{title}**\n{body}...\nSource: {url}")
|
160 |
+
|
161 |
return "\n\n".join(formatted_results)
|
162 |
else:
|
163 |
+
return f"No search results found for '{query}'. Try rephrasing your search terms."
|
164 |
except Exception as e:
|
165 |
print(f"Web search error: {e}")
|
166 |
+
return f"Error during web search for '{query}': {str(e)}"
|
167 |
|
168 |
def math_calculator(self, expression: str) -> str:
|
169 |
"""Safe math evaluation using SymPy"""
|
|
|
192 |
|
193 |
def __call__(self, question: str) -> str:
|
194 |
print(f"Processing question (first 50 chars): {question[:50]}...")
|
195 |
+
|
196 |
+
# Enhanced reasoning approach
|
197 |
+
question_lower = question.lower()
|
198 |
+
|
199 |
+
# Check if we need to analyze files
|
200 |
+
if any(word in question_lower for word in ['file', 'excel', 'csv', 'spreadsheet', 'data', 'attached']):
|
201 |
+
return "I cannot access attached files in this environment. Please ensure the file is accessible via a direct URL or describe the data content directly in your question."
|
202 |
+
|
203 |
+
# Check if we need web search
|
204 |
+
needs_web_search = any(word in question_lower for word in [
|
205 |
+
'current', 'latest', 'recent', 'today', 'news', 'who is', 'what is',
|
206 |
+
'competition', 'winner', 'recipient', 'nationality', 'country',
|
207 |
+
'malko', 'century', 'award', 'born', 'died'
|
208 |
+
])
|
209 |
+
|
210 |
+
# Check if we need math calculation
|
211 |
+
needs_calculation = any(word in question_lower for word in [
|
212 |
+
'calculate', 'compute', 'sum', 'total', 'average', 'percentage',
|
213 |
+
'equation', 'solve', 'math', 'number'
|
214 |
+
]) or any(char in question for char in '+-*/=()0123456789')
|
215 |
+
|
216 |
try:
|
217 |
if self.agent:
|
218 |
+
# Try using the ReAct agent first
|
219 |
response = self.agent.query(question)
|
220 |
+
response_str = str(response)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
221 |
|
222 |
+
# Check if the response is too short or nonsensical
|
223 |
+
if len(response_str.strip()) < 3 or response_str.strip() in ['!', '?', 'what', 'I', 'The', 'A']:
|
224 |
+
print("Agent gave a poor response, trying direct tool approach...")
|
225 |
+
return self._direct_tool_approach(question, needs_web_search, needs_calculation)
|
226 |
|
227 |
+
return response_str
|
228 |
+
else:
|
229 |
+
# Use direct tool approach
|
230 |
+
return self._direct_tool_approach(question, needs_web_search, needs_calculation)
|
231 |
|
232 |
except Exception as e:
|
233 |
print(f"Agent error: {str(e)}")
|
234 |
print(f"Full traceback: {traceback.format_exc()}")
|
235 |
+
# Try direct tool approach as fallback
|
236 |
+
try:
|
237 |
+
return self._direct_tool_approach(question, needs_web_search, needs_calculation)
|
238 |
+
except:
|
239 |
+
return f"I apologize, but I'm having technical difficulties processing your question. The question appears to be: {question[:100]}..."
|
240 |
+
|
241 |
+
def _direct_tool_approach(self, question: str, needs_web_search: bool, needs_calculation: bool) -> str:
|
242 |
+
"""Direct tool usage when agent fails"""
|
243 |
+
|
244 |
+
if needs_web_search:
|
245 |
+
# Extract key search terms
|
246 |
+
search_terms = []
|
247 |
+
important_words = question.split()
|
248 |
+
for word in important_words:
|
249 |
+
if len(word) > 3 and word.lower() not in ['what', 'when', 'where', 'who', 'how', 'the', 'and', 'or', 'but', 'from', 'with']:
|
250 |
+
search_terms.append(word)
|
251 |
+
|
252 |
+
search_query = ' '.join(search_terms[:5]) # Limit to 5 key terms
|
253 |
+
print(f"Performing web search for: {search_query}")
|
254 |
+
|
255 |
+
search_result = self.web_search(search_query)
|
256 |
+
return f"Based on my web search for '{search_query}':\n\n{search_result}\n\nPlease review the search results above to find the specific information you're looking for."
|
257 |
+
|
258 |
+
if needs_calculation:
|
259 |
+
# Try to extract mathematical expressions
|
260 |
+
import re
|
261 |
+
# Look for mathematical expressions
|
262 |
+
math_patterns = re.findall(r'[\d+\-*/().\s]+', question)
|
263 |
+
for pattern in math_patterns:
|
264 |
+
if any(char in pattern for char in '+-*/') and any(char.isdigit() for char in pattern):
|
265 |
+
result = self.math_calculator(pattern.strip())
|
266 |
+
return f"Mathematical calculation result: {result}"
|
267 |
+
|
268 |
+
# Default response with better reasoning
|
269 |
+
return f"I understand you're asking about: {question[:150]}... However, I need more specific information or context to provide an accurate answer. Could you please rephrase your question or provide additional details?"
|
270 |
|
271 |
|
272 |
# --- Memory cleanup function ---
|