Final_Assignment_GAIAAgent / src /gaia /utils /credential_validator.py
JoachimVC's picture
Upload GAIA agent implementation files for assessment
c922f8b
"""
API Credential Validator
This module provides utilities for validating API credentials before running tests.
It checks if required API keys are set and validates them with minimal API calls
to ensure they are valid before running comprehensive tests.
"""
import os
import logging
import requests
from typing import Dict, Any, List, Optional
# Configure logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s"
)
logger = logging.getLogger(__name__)
def validate_api_credentials(tools: List[str] = None) -> Dict[str, bool]:
"""
Validate API credentials for the specified tools.
Args:
tools: List of tool names to validate (default: all tools)
Returns:
Dict[str, bool]: Dictionary with validation status for each tool
"""
if not tools:
tools = ["duckduckgo", "perplexity", "serper", "arxiv", "youtube", "reasoning"]
validation_results = {tool: False for tool in tools}
# Validate DuckDuckGo (no API key required, just check connectivity)
if "duckduckgo" in tools:
validation_results["duckduckgo"] = validate_duckduckgo()
# Validate Perplexity
if "perplexity" in tools:
validation_results["perplexity"] = validate_perplexity()
# Validate Serper
if "serper" in tools:
validation_results["serper"] = validate_serper()
# Validate ArXiv (no API key required, just check connectivity)
if "arxiv" in tools:
validation_results["arxiv"] = validate_arxiv()
# Validate YouTube (no API key required for basic usage)
if "youtube" in tools:
validation_results["youtube"] = validate_youtube()
# Validate Reasoning (no API key required, check if class is importable)
if "reasoning" in tools:
validation_results["reasoning"] = validate_reasoning()
return validation_results
def validate_duckduckgo() -> bool:
"""
Validate DuckDuckGo connectivity.
Returns:
bool: True if validation is successful, False otherwise
"""
try:
response = requests.get("https://api.duckduckgo.com/?q=test&format=json")
return response.status_code == 200
except Exception as e:
logger.error(f"DuckDuckGo validation error: {str(e)}")
return False
def validate_perplexity() -> bool:
"""
Validate Perplexity API key.
Returns:
bool: True if validation is successful, False otherwise
"""
api_key = os.environ.get("PERPLEXITY_API_KEY")
if not api_key:
logger.error("PERPLEXITY_API_KEY environment variable not set")
return False
try:
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
# Make a minimal API call to validate the key
response = requests.post(
"https://api.perplexity.ai/chat/completions",
headers=headers,
json={
"model": "sonar-small-chat",
"messages": [{"role": "user", "content": "Hello"}],
"max_tokens": 1
}
)
if response.status_code == 200:
return True
else:
logger.error(f"Perplexity API validation failed: Status {response.status_code}, {response.text}")
return False
except Exception as e:
logger.error(f"Perplexity validation error: {str(e)}")
return False
def validate_serper() -> bool:
"""
Validate Serper API key.
Returns:
bool: True if validation is successful, False otherwise
"""
api_key = os.environ.get("SERPER_API_KEY")
if not api_key:
logger.error("SERPER_API_KEY environment variable not set")
return False
try:
headers = {
"X-API-KEY": api_key,
"Content-Type": "application/json"
}
# Make a minimal API call to validate the key
response = requests.post(
"https://google.serper.dev/search",
headers=headers,
json={
"q": "test",
"num": 1
}
)
if response.status_code == 200:
return True
else:
logger.error(f"Serper API validation failed: Status {response.status_code}, {response.text}")
return False
except Exception as e:
logger.error(f"Serper validation error: {str(e)}")
return False
def validate_arxiv() -> bool:
"""
Validate ArXiv connectivity.
Returns:
bool: True if validation is successful, False otherwise
"""
try:
response = requests.get("http://export.arxiv.org/api/query?search_query=test&start=0&max_results=1")
return response.status_code == 200
except Exception as e:
logger.error(f"ArXiv validation error: {str(e)}")
return False
def validate_youtube() -> bool:
"""
Validate YouTube connectivity.
Returns:
bool: True if validation is successful, False otherwise
"""
try:
# Try to access a known YouTube video page
response = requests.get("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
return response.status_code == 200
except Exception as e:
logger.error(f"YouTube validation error: {str(e)}")
return False
def validate_reasoning() -> bool:
"""
Validate Reasoning tool importability.
Returns:
bool: True if validation is successful, False otherwise
"""
try:
# Try to import the ReasoningTool class
from src.gaia.tools.reasoning_tools import ReasoningTool
return True
except ImportError as e:
logger.error(f"Reasoning tool import error: {str(e)}")
return False
except Exception as e:
logger.error(f"Reasoning tool validation error: {str(e)}")
return False
def validate_supabase_connection() -> bool:
"""
Validate Supabase connection for memory integration tests.
Returns:
bool: True if validation is successful, False otherwise
"""
try:
# Try to import Supabase components
from src.gaia.memory.supabase_memory import SupabaseMemory
from src.gaia.agent.config import get_memory_config
# Get memory configuration
memory_config = get_memory_config()
memory_config["enabled"] = True
# Initialize Supabase memory
memory = SupabaseMemory(memory_config)
# Check if initialized
return memory.initialized
except ImportError as e:
logger.error(f"Supabase component import error: {str(e)}")
return False
except Exception as e:
logger.error(f"Supabase connection validation error: {str(e)}")
return False
if __name__ == "__main__":
# Run credential validation for all tools
print("\n=== API Credential Validation ===\n")
results = validate_api_credentials()
print("\nValidation Results:\n")
for tool, is_valid in results.items():
status = "✅ VALID" if is_valid else "❌ INVALID"
print(f"{tool.capitalize():15} : {status}")
# Also check Supabase connection
supabase_valid = validate_supabase_connection()
status = "✅ VALID" if supabase_valid else "❌ INVALID"
print(f"\nSupabase Memory: {status}")
# Summary
total = len(results) + 1 # +1 for Supabase
valid_count = sum(1 for is_valid in results.values() if is_valid) + (1 if supabase_valid else 0)
print(f"\n{valid_count} of {total} validations succeeded")
if valid_count < total:
print("\nPlease check the error messages above and configure the missing credentials.")
print("For details on required API keys, see the project documentation.")