File size: 4,223 Bytes
3370983
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""OpenAI API settings."""

import sys
from functools import lru_cache
from pydantic import Field, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict


class OpenAISettings(BaseSettings):
    """
    OpenAI API configuration.
    
    Validates that OPENAI_API_KEY is set and provides a helpful error message
    if missing, especially useful in Docker environments.
    """
    
    model_config = SettingsConfigDict(
        extra="ignore",
    )
    
    api_key: str = Field(
        default="",
        alias="OPENAI_API_KEY",
        description="OpenAI API key for model access",
    )
    
    @model_validator(mode="after")
    def validate_api_key(self) -> "OpenAISettings":
        """Validate that API key is set and provide helpful error message."""
        if not self.api_key:
            error_message = """
╔══════════════════════════════════════════════════════════════════════════════╗
β•‘                        ⚠️  OPENAI_API_KEY NOT SET  ⚠️                         β•‘
╠══════════════════════════════════════════════════════════════════════════════╣
β•‘                                                                              β•‘
β•‘  The OPENAI_API_KEY environment variable is required but not set.           β•‘
β•‘                                                                              β•‘
β•‘  To fix this:                                                                β•‘
β•‘                                                                              β•‘
β•‘  1. Create a .env file in the project root:                                  β•‘
β•‘     OPENAI_API_KEY=sk-your-api-key-here                                      β•‘
β•‘                                                                              β•‘
β•‘  2. Or set it directly in your shell:                                        β•‘
β•‘     export OPENAI_API_KEY=sk-your-api-key-here                               β•‘
β•‘                                                                              β•‘
β•‘  3. Or pass it to Docker:                                                    β•‘
β•‘     docker compose --env-file .env -f docker/docker-compose.yml up           β•‘
β•‘                                                                              β•‘
β•‘  Get your API key at: https://platform.openai.com/api-keys                   β•‘
β•‘                                                                              β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
"""
            print(error_message, file=sys.stderr)
            raise ValueError("OPENAI_API_KEY environment variable is required")
        
        # Basic validation that it looks like an OpenAI key
        if not (self.api_key.startswith("sk-") or self.api_key.startswith("org-")):
            print(
                "⚠️  Warning: OPENAI_API_KEY doesn't start with 'sk-' - "
                "make sure it's a valid OpenAI API key.",
                file=sys.stderr
            )
        
        return self
    
    def __repr__(self) -> str:
        """Safe representation without exposing the key."""
        masked = f"{self.api_key[:7]}...{self.api_key[-4:]}" if len(self.api_key) > 11 else "***"
        return f"OpenAISettings(api_key={masked})"


@lru_cache
def get_openai_settings() -> OpenAISettings:
    """
    Get cached OpenAI settings.
    
    Raises ValueError with helpful message if OPENAI_API_KEY is not set.
    """
    return OpenAISettings()


def get_openai_api_key() -> str:
    """
    Convenience function to get just the API key.
    
    Raises ValueError with helpful message if OPENAI_API_KEY is not set.
    """
    return get_openai_settings().api_key