Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| """ | |
| Configuration and API key management for GAIA Solver Agent | |
| Handles missing API keys gracefully and provides user guidance | |
| """ | |
| import os | |
| import sys | |
| from typing import Dict, List, Optional | |
| # Required API keys and their purposes | |
| API_KEYS_INFO = { | |
| "GOOGLE_API_KEY": { | |
| "purpose": "Google Gemini AI for file analysis and video processing", | |
| "required_for": ["FileAttachmentQueryTool", "GeminiVideoQA", "Primary LLM"], | |
| "fallback": "Use DuckDuckGo search and text-only processing", | |
| "how_to_get": "https://makersuite.google.com/app/apikey" | |
| }, | |
| "GEMINI_API_KEY": { | |
| "purpose": "Alternative Gemini API key (can be same as GOOGLE_API_KEY)", | |
| "required_for": ["LiteLLM model configuration"], | |
| "fallback": "Use GOOGLE_API_KEY if available", | |
| "how_to_get": "https://makersuite.google.com/app/apikey" | |
| }, | |
| "GOOGLE_SEARCH_API_KEY": { | |
| "purpose": "Google Custom Search API for web searches", | |
| "required_for": ["GoogleSearchTool"], | |
| "fallback": "Use DuckDuckGo search (free but less comprehensive)", | |
| "how_to_get": "https://developers.google.com/custom-search/v1/introduction" | |
| }, | |
| "GOOGLE_SEARCH_ENGINE_ID": { | |
| "purpose": "Google Custom Search Engine ID", | |
| "required_for": ["GoogleSearchTool"], | |
| "fallback": "Use DuckDuckGo search", | |
| "how_to_get": "https://programmablesearchengine.google.com/" | |
| } | |
| } | |
| # Optional environment variables | |
| OPTIONAL_ENV_VARS = { | |
| "SPACE_ID": "Hugging Face Space ID (auto-detected in HF Spaces)", | |
| "SPACE_HOST": "Hugging Face Space host (auto-detected in HF Spaces)" | |
| } | |
| class ConfigManager: | |
| """Manages API keys and configuration with graceful fallbacks""" | |
| def __init__(self, silent_mode: bool = False): | |
| self.silent_mode = silent_mode | |
| self.available_keys = {} | |
| self.missing_keys = {} | |
| self.warnings = [] | |
| self._check_api_keys() | |
| if not silent_mode: | |
| self._display_status() | |
| def _check_api_keys(self): | |
| """Check which API keys are available""" | |
| for key, info in API_KEYS_INFO.items(): | |
| value = os.getenv(key) | |
| if value: | |
| self.available_keys[key] = value | |
| else: | |
| self.missing_keys[key] = info | |
| def _display_status(self): | |
| """Display API key status to user""" | |
| if self.available_keys: | |
| print("β Available API Keys:") | |
| for key in self.available_keys: | |
| masked_key = f"...{self.available_keys[key][-4:]}" if len(self.available_keys[key]) >= 4 else "***" | |
| print(f" {key}: {masked_key}") | |
| if self.missing_keys: | |
| print("\nβ οΈ Missing API Keys:") | |
| for key, info in self.missing_keys.items(): | |
| print(f" {key}: {info['purpose']}") | |
| print(f" Fallback: {info['fallback']}") | |
| print(f" Get key: {info['how_to_get']}\n") | |
| print("π‘ To set up API keys, add them to your environment:") | |
| print(" export GOOGLE_API_KEY='your_key_here'") | |
| print(" export GOOGLE_SEARCH_API_KEY='your_key_here'") | |
| print(" # etc.\n") | |
| print("π The agent will run with available features only.") | |
| print(" Some advanced capabilities may be limited.\n") | |
| def get_key(self, key_name: str) -> Optional[str]: | |
| """Get an API key with graceful handling""" | |
| return self.available_keys.get(key_name) | |
| def has_key(self, key_name: str) -> bool: | |
| """Check if a key is available""" | |
| return key_name in self.available_keys | |
| def require_key(self, key_name: str, feature_name: str = "this feature") -> str: | |
| """Require a key or raise informative error""" | |
| if key_name in self.available_keys: | |
| return self.available_keys[key_name] | |
| info = API_KEYS_INFO.get(key_name, {}) | |
| error_msg = f""" | |
| β Missing API Key: {key_name} | |
| {feature_name} requires the {key_name} environment variable. | |
| Purpose: {info.get('purpose', 'API access')} | |
| Get key: {info.get('how_to_get', 'Check API provider documentation')} | |
| To fix this: | |
| 1. Get your API key from the provider | |
| 2. Set environment variable: export {key_name}='your_key_here' | |
| 3. Restart the application | |
| Fallback: {info.get('fallback', 'Feature will be disabled')} | |
| """ | |
| raise ValueError(error_msg) | |
| def get_available_tools(self) -> List[str]: | |
| """Get list of tools that can work with current API keys""" | |
| available_tools = [ | |
| "MathSolver", # No API key needed | |
| "TextPreprocesser", # No API key needed | |
| "WikipediaTitleFinder", # No API key needed | |
| "WikipediaContentFetcher", # No API key needed | |
| "RiddleSolver", # No API key needed | |
| "WebPageFetcher" # No API key needed | |
| ] | |
| if self.has_key("GOOGLE_SEARCH_API_KEY") and self.has_key("GOOGLE_SEARCH_ENGINE_ID"): | |
| available_tools.append("GoogleSearchTool") | |
| else: | |
| available_tools.append("DuckDuckGoSearchTool") # Free fallback | |
| if self.has_key("GOOGLE_API_KEY"): | |
| available_tools.extend([ | |
| "FileAttachmentQueryTool", | |
| "GeminiVideoQA" | |
| ]) | |
| return available_tools | |
| # Global configuration instance | |
| config = ConfigManager() | |
| def safe_getenv(key: str, default: str = None, feature_name: str = None) -> Optional[str]: | |
| """Safely get environment variable with user-friendly error""" | |
| value = os.getenv(key, default) | |
| if value is None and feature_name: | |
| print(f"β οΈ {key} not set - {feature_name} will use fallback method") | |
| return value | |
| def check_required_keys_interactive() -> bool: | |
| """Interactive check for required keys""" | |
| missing = [] | |
| for key, info in API_KEYS_INFO.items(): | |
| if not os.getenv(key): | |
| missing.append((key, info)) | |
| if not missing: | |
| return True | |
| print("\n" + "="*60) | |
| print("π§ GAIA SOLVER AGENT - API KEY SETUP") | |
| print("="*60) | |
| print("Some API keys are missing. The agent can still run with limited functionality.\n") | |
| for key, info in missing: | |
| print(f"β {key}") | |
| print(f" Purpose: {info['purpose']}") | |
| print(f" Fallback: {info['fallback']}") | |
| print(f" Get key: {info['how_to_get']}\n") | |
| print("Options:") | |
| print("1. Continue with limited functionality (recommended for testing)") | |
| print("2. Exit and set up API keys for full functionality") | |
| print("3. Show detailed setup instructions") | |
| while True: | |
| choice = input("\nChoose option (1/2/3): ").strip() | |
| if choice == "1": | |
| print("β Continuing with available features...") | |
| return True | |
| elif choice == "2": | |
| print("Please set up your API keys and restart the agent.") | |
| return False | |
| elif choice == "3": | |
| show_setup_instructions() | |
| else: | |
| print("Please enter 1, 2, or 3") | |
| def show_setup_instructions(): | |
| """Show detailed API key setup instructions""" | |
| print("\n" + "="*60) | |
| print("π§ DETAILED API KEY SETUP INSTRUCTIONS") | |
| print("="*60) | |
| print("\n1. GOOGLE/GEMINI API KEY (Recommended):") | |
| print(" β’ Go to: https://makersuite.google.com/app/apikey") | |
| print(" β’ Sign in with Google account") | |
| print(" β’ Click 'Create API Key'") | |
| print(" β’ Copy the key and run:") | |
| print(" export GOOGLE_API_KEY='your_key_here'") | |
| print(" β’ For Gemini model access:") | |
| print(" export GEMINI_API_KEY='your_key_here' # Can be same key") | |
| print("\n2. GOOGLE CUSTOM SEARCH (Optional but recommended):") | |
| print(" β’ Go to: https://developers.google.com/custom-search/v1/introduction") | |
| print(" β’ Create a Custom Search Engine at: https://programmablesearchengine.google.com/") | |
| print(" β’ Get your Search Engine ID") | |
| print(" β’ Get API key from Google Cloud Console") | |
| print(" β’ Set environment variables:") | |
| print(" export GOOGLE_SEARCH_API_KEY='your_search_api_key'") | |
| print(" export GOOGLE_SEARCH_ENGINE_ID='your_engine_id'") | |
| print("\n3. Environment Variable Setup:") | |
| print(" β’ For current session:") | |
| print(" export KEY_NAME='your_key_value'") | |
| print(" β’ For permanent setup (add to ~/.zshrc or ~/.bashrc):") | |
| print(" echo 'export GOOGLE_API_KEY=\"your_key\"' >> ~/.zshrc") | |
| print(" source ~/.zshrc") | |
| print("\n4. Hugging Face Space Deployment:") | |
| print(" β’ Add keys in Space Settings > Repository secrets") | |
| print(" β’ Keys will be automatically available as environment variables") | |
| print("\nπ‘ TIP: You can start with just GOOGLE_API_KEY for basic functionality!") | |
| print("="*60 + "\n") | |
| if __name__ == "__main__": | |
| # Demo the configuration manager | |
| print("GAIA Solver Agent - Configuration Check") | |
| print("="*50) | |
| config = ConfigManager() | |
| print(f"\nAvailable tools: {', '.join(config.get_available_tools())}") | |
| if not config.available_keys: | |
| print("\nπ‘ Run with API keys for full functionality!") | |
| check_required_keys_interactive() | |