gaia-enhanced-agent / utils /simple_answer_formatter.py
GAIA Agent Deployment
Deploy Complete Enhanced GAIA Agent with Phase 1-6 Improvements
9a6a4dc
"""
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."""