Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -110,9 +110,6 @@ class SuperSmartAgent:
|
|
| 110 |
final_state = self.graph.invoke(initial_state)
|
| 111 |
return final_state["response"]
|
| 112 |
|
| 113 |
-
|
| 114 |
-
# --- HELPER METHODS (NOW PART OF THE CLASS) ---
|
| 115 |
-
|
| 116 |
def score_text(self, text):
|
| 117 |
alnum_count = sum(c.isalnum() for c in text)
|
| 118 |
space_count = text.count(' ')
|
|
@@ -468,7 +465,6 @@ class SuperSmartAgent:
|
|
| 468 |
cell = re.sub(r'\s+', ' ', cell).strip()
|
| 469 |
return cell
|
| 470 |
|
| 471 |
-
|
| 472 |
def extract_answer(self, question, context, tables=None):
|
| 473 |
"""
|
| 474 |
Enhanced general purpose answer extraction from text context using spaCy.
|
|
@@ -729,7 +725,7 @@ class SuperSmartAgent:
|
|
| 729 |
scored_numbers.sort(reverse=True, key=lambda x: x[0])
|
| 730 |
return (scored_numbers[0][1], scored_numbers[0][2])
|
| 731 |
|
| 732 |
-
|
| 733 |
"""Find the most relevant location entity based on question context using spaCy."""
|
| 734 |
location_entities = [ent for ent in entities if ent[1] in ["GPE", "LOC"]]
|
| 735 |
if not location_entities:
|
|
@@ -763,80 +759,79 @@ class SuperSmartAgent:
|
|
| 763 |
best_location = loc_text
|
| 764 |
|
| 765 |
return best_location
|
| 766 |
-
|
| 767 |
-
|
| 768 |
-
|
| 769 |
-
|
| 770 |
-
|
| 771 |
-
|
| 772 |
-
|
| 773 |
-
if not tables:
|
| 774 |
-
return None
|
| 775 |
-
|
| 776 |
-
question_keywords = self.extract_key_phrases(question)
|
| 777 |
-
question_lower = question.lower()
|
| 778 |
-
|
| 779 |
-
for table in tables:
|
| 780 |
-
if not table:
|
| 781 |
-
continue
|
| 782 |
-
|
| 783 |
-
# Assuming the first row is headers if present
|
| 784 |
-
headers = [self._clean_cell_content(cell).lower() for cell in table[0]] if table else []
|
| 785 |
-
data_rows = table[1:] if len(table) > 1 else []
|
| 786 |
-
|
| 787 |
-
# Determine column types (placeholder for now, needs implementation)
|
| 788 |
-
column_types = self.detect_column_types(table)
|
| 789 |
-
|
| 790 |
-
# ... (Rest of your table search logic would go here)
|
| 791 |
-
# For now, just return a dummy answer if a table is found to avoid the error.
|
| 792 |
-
# You'll need to implement the actual table search and answer extraction logic.
|
| 793 |
-
# Example:
|
| 794 |
-
if "president" in question_lower and "usa" in question_lower and headers and "name" in headers:
|
| 795 |
-
name_col_idx = headers.index("name")
|
| 796 |
-
# More complex logic needed to find relevant row
|
| 797 |
-
return "Placeholder: Found answer in table for president question."
|
| 798 |
-
|
| 799 |
-
# Simple keyword match within table cells as a basic example
|
| 800 |
-
for row_idx, row in enumerate(table):
|
| 801 |
-
for cell_idx, cell_content in enumerate(row):
|
| 802 |
-
cell_lower = cell_content.lower()
|
| 803 |
-
if any(keyword in cell_lower for keyword in question_keywords):
|
| 804 |
-
# This is very basic, a proper implementation would consider column headers
|
| 805 |
-
# and question type to return a specific cell or a combination.
|
| 806 |
-
if headers and cell_idx < len(headers):
|
| 807 |
-
return f"Found '{cell_content}' under '{headers[cell_idx]}' in a table."
|
| 808 |
-
else:
|
| 809 |
-
return f"Found '{cell_content}' in a table."
|
| 810 |
return None
|
| 811 |
-
|
| 812 |
-
|
| 813 |
-
|
| 814 |
-
|
| 815 |
-
|
| 816 |
-
|
| 817 |
-
|
| 818 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 819 |
|
| 820 |
-
|
| 821 |
-
|
| 822 |
-
|
| 823 |
-
|
| 824 |
-
|
| 825 |
-
|
| 826 |
-
|
| 827 |
-
|
| 828 |
-
|
| 829 |
-
|
| 830 |
-
|
| 831 |
-
|
| 832 |
-
|
| 833 |
-
|
| 834 |
-
|
| 835 |
-
|
| 836 |
-
|
| 837 |
-
|
| 838 |
-
|
| 839 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 840 |
|
| 841 |
# --- Gradio Interface (as provided, assuming it will call agent correctly) ---
|
| 842 |
|
|
|
|
| 110 |
final_state = self.graph.invoke(initial_state)
|
| 111 |
return final_state["response"]
|
| 112 |
|
|
|
|
|
|
|
|
|
|
| 113 |
def score_text(self, text):
|
| 114 |
alnum_count = sum(c.isalnum() for c in text)
|
| 115 |
space_count = text.count(' ')
|
|
|
|
| 465 |
cell = re.sub(r'\s+', ' ', cell).strip()
|
| 466 |
return cell
|
| 467 |
|
|
|
|
| 468 |
def extract_answer(self, question, context, tables=None):
|
| 469 |
"""
|
| 470 |
Enhanced general purpose answer extraction from text context using spaCy.
|
|
|
|
| 725 |
scored_numbers.sort(reverse=True, key=lambda x: x[0])
|
| 726 |
return (scored_numbers[0][1], scored_numbers[0][2])
|
| 727 |
|
| 728 |
+
def find_relevant_location_spacy(self, question, entities):
|
| 729 |
"""Find the most relevant location entity based on question context using spaCy."""
|
| 730 |
location_entities = [ent for ent in entities if ent[1] in ["GPE", "LOC"]]
|
| 731 |
if not location_entities:
|
|
|
|
| 759 |
best_location = loc_text
|
| 760 |
|
| 761 |
return best_location
|
| 762 |
+
|
| 763 |
+
def find_answer_in_tables(self, question, tables):
|
| 764 |
+
"""
|
| 765 |
+
Search through extracted tables to find an answer to the question.
|
| 766 |
+
Improved with better column type detection and keyword matching.
|
| 767 |
+
"""
|
| 768 |
+
if not tables:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 769 |
return None
|
| 770 |
+
|
| 771 |
+
question_keywords = self.extract_key_phrases(question)
|
| 772 |
+
question_lower = question.lower()
|
| 773 |
+
|
| 774 |
+
for table in tables:
|
| 775 |
+
if not table:
|
| 776 |
+
continue
|
| 777 |
+
|
| 778 |
+
# Assuming the first row is headers if present
|
| 779 |
+
headers = [self._clean_cell_content(cell).lower() for cell in table[0]] if table else []
|
| 780 |
+
data_rows = table[1:] if len(table) > 1 else []
|
| 781 |
+
|
| 782 |
+
# Determine column types (placeholder for now, needs implementation)
|
| 783 |
+
column_types = self.detect_column_types(table)
|
| 784 |
+
|
| 785 |
+
# ... (Rest of your table search logic would go here)
|
| 786 |
+
# For now, just return a dummy answer if a table is found to avoid the error.
|
| 787 |
+
# You'll need to implement the actual table search and answer extraction logic.
|
| 788 |
+
# Example:
|
| 789 |
+
if "president" in question_lower and "usa" in question_lower and headers and "name" in headers:
|
| 790 |
+
name_col_idx = headers.index("name")
|
| 791 |
+
# More complex logic needed to find relevant row
|
| 792 |
+
return "Placeholder: Found answer in table for president question."
|
| 793 |
|
| 794 |
+
# Simple keyword match within table cells as a basic example
|
| 795 |
+
for row_idx, row in enumerate(table):
|
| 796 |
+
for cell_idx, cell_content in enumerate(row):
|
| 797 |
+
cell_lower = cell_content.lower()
|
| 798 |
+
if any(keyword in cell_lower for keyword in question_keywords):
|
| 799 |
+
# This is very basic, a proper implementation would consider column headers
|
| 800 |
+
# and question type to return a specific cell or a combination.
|
| 801 |
+
if headers and cell_idx < len(headers):
|
| 802 |
+
return f"Found '{cell_content}' under '{headers[cell_idx]}' in a table."
|
| 803 |
+
else:
|
| 804 |
+
return f"Found '{cell_content}' in a table."
|
| 805 |
+
return None
|
| 806 |
+
|
| 807 |
+
def detect_column_types(self, table):
|
| 808 |
+
"""
|
| 809 |
+
Detects the type of data in each column (e.g., 'number', 'text', 'date').
|
| 810 |
+
This is a placeholder and would need a robust implementation.
|
| 811 |
+
"""
|
| 812 |
+
if not table or not table[0]:
|
| 813 |
+
return []
|
| 814 |
+
|
| 815 |
+
num_cols = len(table[0])
|
| 816 |
+
column_types = ["text"] * num_cols # Default to text
|
| 817 |
+
|
| 818 |
+
# Example: rudimentary detection for the first few rows
|
| 819 |
+
for col_idx in range(num_cols):
|
| 820 |
+
num_count = 0
|
| 821 |
+
date_count = 0
|
| 822 |
+
for row_idx in range(1, min(len(table), 5)): # Check first 5 data rows
|
| 823 |
+
if col_idx < len(table[row_idx]):
|
| 824 |
+
cell_content = self._clean_cell_content(table[row_idx][col_idx])
|
| 825 |
+
if re.match(r'^\d+(\.\d+)?$', cell_content):
|
| 826 |
+
num_count += 1
|
| 827 |
+
if re.match(r'\b\d{4}\b', cell_content) or re.match(r'\b(Jan|Feb|Mar)\w*\s+\d{1,2}(?:st|nd|rd|th)?(?:,\s+\d{4})?\b', cell_content, re.IGNORECASE):
|
| 828 |
+
date_count += 1
|
| 829 |
+
|
| 830 |
+
if num_count > 2: # Heuristic: if more than 2 numbers
|
| 831 |
+
column_types[col_idx] = "number"
|
| 832 |
+
elif date_count > 1: # Heuristic: if more than 1 date
|
| 833 |
+
column_types[col_idx] = "date"
|
| 834 |
+
return column_types
|
| 835 |
|
| 836 |
# --- Gradio Interface (as provided, assuming it will call agent correctly) ---
|
| 837 |
|