Spaces:
Running
Running
""" | |
Simple Answer Formatter - Following 100% Successful GAIA Space Patterns | |
This implementation abandons complex hardcoded pattern matching in favor of: | |
1. Trust in core agent output with proper prompting | |
2. Simple extraction of FINAL ANSWER format | |
3. Minimal post-processing focused on GAIA exact match requirements | |
Based on analysis of successful spaces: fisherman611/gaia-agent, baixianger/RobotPai, ZeroTimo/RobotPai | |
""" | |
import re | |
import logging | |
from typing import Optional | |
logger = logging.getLogger(__name__) | |
class SimpleGAIAAnswerFormatter: | |
""" | |
Simple answer formatter following successful GAIA space patterns. | |
Key principles: | |
1. Trust the agent's output when properly prompted | |
2. Extract FINAL ANSWER format cleanly | |
3. Apply minimal GAIA-specific formatting rules | |
4. No complex hardcoded pattern matching | |
""" | |
def __init__(self): | |
"""Initialize the simple formatter.""" | |
logger.info("β Simple GAIA Answer Formatter initialized") | |
def format_answer(self, raw_answer: str) -> str: | |
""" | |
Format answer following successful space patterns. | |
Args: | |
raw_answer: The raw answer from the agent | |
Returns: | |
Formatted answer for GAIA evaluation | |
""" | |
try: | |
# Step 1: Extract FINAL ANSWER using simple slicing (matches 100% successful spaces) | |
if "FINAL ANSWER:" in raw_answer: | |
# Use simple slicing like top 100% spaces: answer[14:] | |
final_answer_index = raw_answer.rfind("FINAL ANSWER:") | |
if final_answer_index != -1: | |
answer = raw_answer[final_answer_index + 14:].strip() | |
# Take only the first line if multi-line | |
answer = answer.split('\n')[0].strip() | |
logger.info(f"β Extracted FINAL ANSWER: {answer}") | |
else: | |
answer = raw_answer.strip() | |
logger.warning("β οΈ FINAL ANSWER found but extraction failed, using raw answer") | |
else: | |
# Fallback: use the raw answer | |
answer = raw_answer.strip() | |
logger.warning("β οΈ No FINAL ANSWER format found, using raw answer") | |
# Step 2: Apply enhanced GAIA formatting rules | |
formatted_answer = self._apply_enhanced_gaia_rules(answer) | |
logger.info(f"β Final formatted answer: {formatted_answer}") | |
return formatted_answer | |
except Exception as e: | |
logger.error(f"β Error formatting answer: {e}") | |
return raw_answer.strip() | |
def _apply_enhanced_gaia_rules(self, answer: str) -> str: | |
""" | |
Apply enhanced GAIA formatting rules based on 100% successful spaces analysis. | |
GAIA exact match requirements: | |
- Numbers: No commas, no units (unless specified), consistent decimal formatting | |
- Strings: No articles, no abbreviations, digits in plain text | |
- Lists: Comma-separated, alphabetically sorted when appropriate | |
""" | |
answer = answer.strip() | |
# Rule 1: Remove common formatting artifacts | |
answer = self._clean_basic_artifacts(answer) | |
# Rule 2: Enhanced number handling (critical fix) | |
answer = self._format_numbers_enhanced(answer) | |
# Rule 3: Enhanced list processing | |
answer = self._format_lists_enhanced(answer) | |
# Rule 4: Handle common string issues | |
answer = self._format_strings(answer) | |
return answer | |
def _clean_basic_artifacts(self, answer: str) -> str: | |
"""Remove basic formatting artifacts.""" | |
# Remove quotes around single answers | |
if answer.startswith('"') and answer.endswith('"'): | |
answer = answer[1:-1] | |
if answer.startswith("'") and answer.endswith("'"): | |
answer = answer[1:-1] | |
# Remove trailing periods for single word/number answers | |
# But preserve periods in full sentences | |
words = answer.split() | |
if len(words) <= 2 and not ',' in answer and answer.endswith('.'): | |
answer = answer[:-1] | |
return answer.strip() | |
def _format_numbers_enhanced(self, answer: str) -> str: | |
"""Enhanced number formatting based on successful GAIA spaces analysis.""" | |
if ',' not in answer and '.' not in answer: | |
return answer | |
result = answer | |
# Remove commas from large numbers (e.g., "1,234" -> "1234") | |
# But preserve commas that separate list items | |
while re.search(r'(\d),(\d)', result): | |
result = re.sub(r'(\d),(\d)', r'\1\2', result) | |
# Handle decimal formatting consistency | |
# Ensure consistent decimal representation (no trailing zeros unless significant) | |
def clean_decimal(match): | |
number = match.group(0) | |
try: | |
# Convert to float and back to remove unnecessary trailing zeros | |
float_val = float(number) | |
# If it's a whole number, return as integer | |
if float_val.is_integer(): | |
return str(int(float_val)) | |
else: | |
# Remove trailing zeros after decimal point | |
return str(float_val).rstrip('0').rstrip('.') | |
except ValueError: | |
return number | |
# Apply decimal cleaning to standalone numbers | |
result = re.sub(r'\b\d+\.\d+\b', clean_decimal, result) | |
return result | |
def _format_strings(self, answer: str) -> str: | |
"""Format strings according to GAIA rules.""" | |
# This is intentionally minimal - successful spaces trust the agent | |
# to provide properly formatted answers when prompted correctly | |
# Only remove articles if this looks like a single entity name | |
# Don't remove articles from full sentences | |
words = answer.split() | |
if len(words) <= 3: # Only for short answers | |
if answer.lower().startswith('the '): | |
answer = answer[4:] | |
elif answer.lower().startswith('a '): | |
answer = answer[2:] | |
elif answer.lower().startswith('an '): | |
answer = answer[3:] | |
return answer.strip() | |
def _format_lists_enhanced(self, answer: str) -> str: | |
"""Enhanced list processing based on successful GAIA spaces analysis.""" | |
# Check if this looks like a comma-separated list | |
if ',' in answer and len(answer.split(',')) > 1: | |
items = [item.strip() for item in answer.split(',')] | |
# Remove "and" from the last item if present | |
if len(items) > 1 and items[-1].lower().startswith('and '): | |
items[-1] = items[-1][4:].strip() | |
# Check if all items are simple strings (not complex phrases) | |
# Only sort if they appear to be simple names/entities | |
if all(len(item.split()) <= 3 for item in items) and len(items) <= 10: | |
# Sort alphabetically for consistency (common GAIA requirement) | |
items.sort() | |
return ', '.join(items) | |
return answer | |
def create_simple_formatter() -> SimpleGAIAAnswerFormatter: | |
"""Create a simple GAIA answer formatter instance.""" | |
return SimpleGAIAAnswerFormatter() | |
# Enhanced system prompt for GAIA (following successful space patterns) | |
GAIA_SYSTEM_PROMPT = """You are a helpful assistant tasked with answering questions using a set of tools. | |
Available tools: | |
- Mathematical operations (add, subtract, multiply, divide, power, square_root, factorial, etc.) | |
- Code execution (execute_python, execute_sql, execute_bash) | |
- Web search (web_search, wikipedia_search, arxiv_search) | |
- Text processing (extract_numbers, count_words, count_characters) | |
For computational questions, use the code execution tools. | |
For current information, use the search tools. | |
For basic math, use the mathematical operation tools. | |
CRITICAL: Always end your response with the following template: | |
FINAL ANSWER: [YOUR FINAL ANSWER] | |
FORMATTING RULES (CRITICAL FOR EVALUATION): | |
For NUMBERS: | |
- Provide just the number without commas: "42" not "42,000" | |
- No units unless specifically requested: "3.14159" not "3.14159 meters" | |
- No trailing zeros: "3.5" not "3.50" | |
- Examples: "42", "3.14159", "1000000" | |
For STRINGS: | |
- No articles (a, an, the): "Paris" not "The Paris" | |
- No abbreviations: "New York" not "NY" | |
- Write digits in plain text: "twenty one" not "21" | |
- Examples: "Paris", "Albert Einstein", "twenty one" | |
For LISTS: | |
- Comma-separated values: "apple, banana, orange" | |
- Apply number/string rules to each element | |
- Alphabetical order when appropriate | |
- No "and" before last item: "red, blue, green" not "red, blue, and green" | |
- Examples: "1, 2, 3", "apple, banana, orange", "Einstein, Newton, Tesla" | |
EXAMPLES OF CORRECT FORMATTING: | |
- Question: "What is 1,234 + 5,678?" β FINAL ANSWER: 6912 | |
- Question: "Name the capital of France" β FINAL ANSWER: Paris | |
- Question: "List three colors" β FINAL ANSWER: blue, green, red | |
- Question: "How many sides does a triangle have?" β FINAL ANSWER: 3 | |
Your answer should ONLY start with "FINAL ANSWER: " followed by the properly formatted answer.""" |