File size: 3,829 Bytes
cacd4d0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
"""
API Key Management for GEPA Optimizer
"""

import os
from dotenv import load_dotenv
from typing import Optional, Dict, List

class APIKeyManager:
    """Handles API keys securely without hardcoding"""
    
    def __init__(self):
        # Load .env file if present
        load_dotenv()
        self._keys: Dict[str, str] = {}
        self._load_from_env()

    def _load_from_env(self):
        """Load API keys from environment variables"""
        env_mappings = {
            'openai': 'OPENAI_API_KEY',
            'anthropic': 'ANTHROPIC_API_KEY',
            'huggingface': 'HUGGINGFACE_API_KEY',
            'cohere': 'COHERE_API_KEY',
            'ai21': 'AI21_API_KEY',
            'together': 'TOGETHER_API_KEY',
            'replicate': 'REPLICATE_API_TOKEN',
            'groq': 'GROQ_API_KEY',
            'ollama': 'OLLAMA_API_KEY',
            'google': 'GEMINI_API_KEY',
            'gemini': 'GEMINI_API_KEY' 
        }
        
        for provider, env_var in env_mappings.items():
            key = os.getenv(env_var)
            if key:
                self._keys[provider] = key

    def get_api_key(self, provider: str) -> Optional[str]:
        """Get API key for a specific provider"""
        return self._keys.get(provider.lower())
    
    def set_api_key(self, provider: str, key: str):
        """Set API key for a provider at runtime"""
        provider_lower = provider.lower()
        self._keys[provider_lower] = key
    
    # Handle aliases - if setting google, also set gemini and vice versa
        if provider_lower == 'google':
            self._keys['gemini'] = key
        elif provider_lower == 'gemini':
            self._keys['google'] = key
    
    def has_key(self, provider: str) -> bool:
        """Check if API key exists for provider"""
        return provider.lower() in self._keys
    
    def get_missing_keys(self, providers: List[str]) -> List[str]:
        """Get list of providers missing API keys"""
        return [p for p in providers if not self.has_key(p)]
    
    def validate_keys(self, providers: List[str]) -> Dict[str, bool]:
        """Validate API keys for multiple providers"""
        return {provider: self.has_key(provider) for provider in providers}

    # Legacy methods for backward compatibility
    def set_openai_key(self, key: str):
        """Set OpenAI API key at runtime"""
        self.set_api_key('openai', key)

    def set_anthropic_key(self, key: str):
        """Set Anthropic API key at runtime"""
        self.set_api_key('anthropic', key)

    def set_google_key(self, key: str):
        """Set Google API key at runtime"""
        self.set_api_key('google', key)

    def set_gemini_key(self, key: str):
        """Set Gemini API key at runtime (alias for Google)"""
        self.set_api_key('google', key)

    def get_openai_key(self) -> str:
        """Get OpenAI key or raise error if missing"""
        key = self.get_api_key('openai')
        if not key:
            raise RuntimeError(
                "OpenAI API key missing. Set via:\n"
                "1. Environment variable: OPENAI_API_KEY=your_key\n"
                "2. .env file: OPENAI_API_KEY=your_key\n"
                "3. Code: api_manager.set_api_key('openai', 'your_key')"
            )
        return key

    def get_anthropic_key(self) -> Optional[str]:
        """Get Anthropic key (optional)"""
        return self.get_api_key('anthropic')

    def get_google_key(self) -> Optional[str]:
        """Get Google key (optional)"""
        return self.get_api_key('google')

    def get_gemini_key(self) -> Optional[str]:
        """Get Gemini key (alias for Google)"""
        return self.get_api_key('google')

    def has_required_keys(self) -> bool:
        """Check if required keys are available"""
        return bool(self.get_api_key('openai'))