Spaces:
Sleeping
Sleeping
Arbnor Tefiki
commited on
Commit
·
9152ba5
1
Parent(s):
e1b1a3e
Add changes
Browse files- agent/agent.py +141 -1
agent/agent.py
CHANGED
@@ -91,7 +91,24 @@ class MultiModalAgent:
|
|
91 |
logger.error(f"Resource directory does not exist: {self.resource_dir}")
|
92 |
return f"Error: Resource directory not found at {self.resource_dir}. Please check the path."
|
93 |
|
94 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
|
96 |
# Extract content from the file
|
97 |
file_path = analysis['file_path']
|
@@ -312,3 +329,126 @@ class MultiModalAgent:
|
|
312 |
except Exception as e:
|
313 |
logger.exception(f"Error processing content: {e}")
|
314 |
return f"An error occurred while processing the file content: {e}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
logger.error(f"Resource directory does not exist: {self.resource_dir}")
|
92 |
return f"Error: Resource directory not found at {self.resource_dir}. Please check the path."
|
93 |
|
94 |
+
# Try to infer an answer from question content directly if no file is found
|
95 |
+
inferred_answer = self._answer_with_reasoning(question, analysis)
|
96 |
+
if inferred_answer:
|
97 |
+
return inferred_answer
|
98 |
+
|
99 |
+
# Try to answer with reasoning since no file was found
|
100 |
+
reasoning_answer = self._answer_with_reasoning(question, analysis)
|
101 |
+
if reasoning_answer:
|
102 |
+
self.answer_cache[cache_key] = reasoning_answer
|
103 |
+
return reasoning_answer
|
104 |
+
|
105 |
+
# If reasoning fails, check if we have an answer in metadata
|
106 |
+
metadata_answer = self._check_metadata_for_answer(task_id)
|
107 |
+
if metadata_answer:
|
108 |
+
self.answer_cache[cache_key] = metadata_answer
|
109 |
+
return metadata_answer
|
110 |
+
|
111 |
+
return "I couldn't find relevant information to answer this question."
|
112 |
|
113 |
# Extract content from the file
|
114 |
file_path = analysis['file_path']
|
|
|
329 |
except Exception as e:
|
330 |
logger.exception(f"Error processing content: {e}")
|
331 |
return f"An error occurred while processing the file content: {e}"
|
332 |
+
|
333 |
+
def _answer_with_reasoning(self, question: str, analysis: Dict[str, Any]) -> Optional[str]:
|
334 |
+
"""
|
335 |
+
Attempt to answer questions that don't map to specific files using reasoning.
|
336 |
+
|
337 |
+
Args:
|
338 |
+
question (str): The user's question
|
339 |
+
analysis (dict): The analysis of the question
|
340 |
+
|
341 |
+
Returns:
|
342 |
+
str: A reasoned answer or None if we can't answer
|
343 |
+
"""
|
344 |
+
import re
|
345 |
+
from datetime import datetime
|
346 |
+
|
347 |
+
# Lowercase the question for easier pattern matching
|
348 |
+
question_lower = question.lower()
|
349 |
+
|
350 |
+
# Handle date/time questions
|
351 |
+
if re.search(r'what (is|\'s) (the current|today\'s) date', question_lower) or 'what day is it' in question_lower:
|
352 |
+
return f"Today's date is {datetime.now().strftime('%A, %B %d, %Y')}."
|
353 |
+
|
354 |
+
if 'what time is it' in question_lower or 'current time' in question_lower:
|
355 |
+
return f"The current time is {datetime.now().strftime('%H:%M:%S')}."
|
356 |
+
|
357 |
+
# Handle math questions
|
358 |
+
math_match = re.search(r'calculate|compute|what is (\d+\s*[\+\-\*\/]\s*\d+)', question_lower)
|
359 |
+
if math_match or re.search(r'\d+\s*[\+\-\*\/]\s*\d+', question_lower):
|
360 |
+
# Extract the mathematical expression
|
361 |
+
expression = re.search(r'(\d+\s*[\+\-\*\/]\s*\d+)', question_lower)
|
362 |
+
if expression:
|
363 |
+
try:
|
364 |
+
result = eval(expression.group(1).replace('x', '*'))
|
365 |
+
return f"The result of {expression.group(1)} is {result}."
|
366 |
+
except:
|
367 |
+
pass
|
368 |
+
|
369 |
+
# Handle simple definition questions
|
370 |
+
if re.search(r'what is a|what are|define|meaning of', question_lower):
|
371 |
+
# Extract key terms - this is simplistic but could be improved
|
372 |
+
key_terms = []
|
373 |
+
|
374 |
+
# Check for "what is X" pattern
|
375 |
+
what_is_match = re.search(r'what is a?n? ([a-z\s]+)[\?\.]?', question_lower)
|
376 |
+
if what_is_match:
|
377 |
+
key_terms.append(what_is_match.group(1).strip())
|
378 |
+
|
379 |
+
# Check for "define X" pattern
|
380 |
+
define_match = re.search(r'define ([a-z\s]+)[\?\.]?', question_lower)
|
381 |
+
if define_match:
|
382 |
+
key_terms.append(define_match.group(1).strip())
|
383 |
+
|
384 |
+
# Provide simple definitions for common terms
|
385 |
+
definitions = {
|
386 |
+
"python": "Python is a high-level, interpreted programming language known for its readability and versatility.",
|
387 |
+
"excel": "Microsoft Excel is a spreadsheet program used for calculations, data analysis, and visualization.",
|
388 |
+
"pdf": "PDF (Portable Document Format) is a file format used to present documents consistently across different platforms.",
|
389 |
+
"csv": "CSV (Comma-Separated Values) is a simple file format used to store tabular data.",
|
390 |
+
"json": "JSON (JavaScript Object Notation) is a lightweight data interchange format that is easy for humans to read and write.",
|
391 |
+
"artificial intelligence": "Artificial Intelligence (AI) refers to systems or machines that mimic human intelligence to perform tasks and can improve themselves based on the information they collect.",
|
392 |
+
"machine learning": "Machine Learning is a subset of artificial intelligence that enables systems to learn from data and improve from experience without being explicitly programmed.",
|
393 |
+
"data science": "Data Science is an interdisciplinary field that uses scientific methods, processes, algorithms, and systems to extract knowledge and insights from structured and unstructured data.",
|
394 |
+
"hugging face": "Hugging Face is a company that develops tools for building applications using machine learning, particularly natural language processing (NLP) models."
|
395 |
+
}
|
396 |
+
|
397 |
+
for term in key_terms:
|
398 |
+
for key, value in definitions.items():
|
399 |
+
if key in term:
|
400 |
+
return value
|
401 |
+
|
402 |
+
# Handle agent capability questions
|
403 |
+
if re.search(r'what can you do|your capabilities|what files can you|help me with', question_lower):
|
404 |
+
return ("I'm a multi-modal AI agent that can process and answer questions about various file types including "
|
405 |
+
"Excel, CSV, text, PDF, images, Python code, Office documents (Word, PowerPoint), JSON, ZIP archives, "
|
406 |
+
"and PDB files. I can analyze your questions, identify relevant files, extract content, and formulate "
|
407 |
+
"answers. For questions that don't require specific files, I can also provide reasoning-based answers.")
|
408 |
+
|
409 |
+
# Handle questions about supported file types
|
410 |
+
if re.search(r'(what|which) (file types|files) (do you|can you) (support|handle|process)', question_lower):
|
411 |
+
return ("I can process and analyze the following file types: Excel (.xlsx), CSV, text files (.txt), "
|
412 |
+
"PDF documents, images (.png, .jpg), Python code (.py), Word documents (.docx), "
|
413 |
+
"PowerPoint presentations (.pptx), JSON files, ZIP archives, and PDB files.")
|
414 |
+
|
415 |
+
# Add more patterns as needed...
|
416 |
+
|
417 |
+
# If no patterns match, return None to indicate we can't answer with reasoning
|
418 |
+
return None
|
419 |
+
|
420 |
+
def _check_metadata_for_answer(self, task_id: Optional[str]) -> Optional[str]:
|
421 |
+
"""
|
422 |
+
Check if an answer is directly available in the metadata.
|
423 |
+
|
424 |
+
Args:
|
425 |
+
task_id: The task ID
|
426 |
+
|
427 |
+
Returns:
|
428 |
+
The answer from metadata, or None if not found
|
429 |
+
"""
|
430 |
+
if not task_id:
|
431 |
+
return None
|
432 |
+
|
433 |
+
try:
|
434 |
+
metadata_path = os.path.join(self.resource_dir, 'metadata.jsonl')
|
435 |
+
|
436 |
+
if not os.path.exists(metadata_path):
|
437 |
+
logger.warning(f"Metadata file not found: {metadata_path}")
|
438 |
+
return None
|
439 |
+
|
440 |
+
with open(metadata_path, 'r', encoding='utf-8') as f:
|
441 |
+
for line in f:
|
442 |
+
try:
|
443 |
+
metadata = json.loads(line.strip())
|
444 |
+
if metadata.get('task_id') == task_id and 'answer' in metadata:
|
445 |
+
logger.info(f"Found answer for task_id {task_id} in metadata")
|
446 |
+
return metadata['answer']
|
447 |
+
except json.JSONDecodeError:
|
448 |
+
continue
|
449 |
+
|
450 |
+
logger.info(f"No answer found for task_id {task_id} in metadata")
|
451 |
+
return None
|
452 |
+
except Exception as e:
|
453 |
+
logger.exception(f"Error checking metadata for answer: {e}")
|
454 |
+
return None
|