File size: 4,431 Bytes
2ebef02
 
 
 
e2a364d
2ebef02
 
 
 
 
 
 
 
 
e2a364d
2ebef02
e2a364d
2ebef02
e2a364d
b9b2b1e
2ebef02
e2a364d
b9b2b1e
 
e2a364d
 
 
b9b2b1e
2ebef02
 
e2a364d
2ebef02
e2a364d
394611c
e2a364d
 
 
2ebef02
b9b2b1e
2ebef02
 
e2a364d
2ebef02
e2a364d
 
394611c
e2a364d
 
2ebef02
e2a364d
 
 
 
 
 
 
394611c
2ebef02
e2a364d
2ebef02
394611c
e2a364d
2ebef02
 
 
e2a364d
 
 
 
2ebef02
e2a364d
 
 
 
 
2ebef02
 
 
b9b2b1e
 
2ebef02
 
 
e2a364d
2ebef02
e2a364d
 
 
 
 
 
 
 
 
 
 
2ebef02
e2a364d
 
2ebef02
 
e2a364d
2ebef02
 
e2a364d
2ebef02
e2a364d
 
 
2ebef02
 
e2a364d
394611c
2ebef02
e2a364d
2ebef02
 
 
e2a364d
394611c
2ebef02
394611c
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
111
112
113
114
115
116
117
118
119
120
121
122
"""
LLM Provider Factory for Flare
"""
import os
from typing import Optional
from dotenv import load_dotenv

from llm_interface import LLMInterface, SparkLLM, GPT4oLLM
from config_provider import ConfigProvider
from utils import log

class LLMFactory:
    @staticmethod
    def create_provider() -> LLMInterface:
        """Create LLM provider based on configuration"""
        cfg = ConfigProvider.get()
        llm_config = cfg.global_config.llm_provider
        
        if not llm_config:
            raise ValueError("No LLM provider configured")
        
        provider_name = llm_config.name
        log(f"🏭 Creating LLM provider: {provider_name}")
        
        # Get provider definition
        provider_def = cfg.global_config.get_provider_config("llm", provider_name)
        if not provider_def:
            raise ValueError(f"Unknown LLM provider: {provider_name}")
        
        # Get API key
        api_key = LLMFactory._get_api_key(provider_name, llm_config.api_key)
        
        # Create provider based on name
        if provider_name == "spark":
            return LLMFactory._create_spark_provider(llm_config, api_key, provider_def)
        elif provider_name in ["gpt4o", "gpt4o-mini"]:
            return LLMFactory._create_gpt_provider(llm_config, api_key, provider_def)
        else:
            raise ValueError(f"Unsupported LLM provider: {provider_name}")
    
    @staticmethod
    def _create_spark_provider(llm_config, api_key: str, provider_def) -> SparkLLM:
        """Create Spark LLM provider"""
        if not llm_config.endpoint:
            raise ValueError("Spark endpoint is required")
        
        if not api_key:
            raise ValueError("Spark API token is required")
        
        # Extract work mode variant (for backward compatibility)
        provider_variant = "cloud"  # Default
        if os.getenv("SPACE_ID"):  # HuggingFace Space
            provider_variant = "hfcloud"
        
        log(f"πŸš€ Initializing SparkLLM: {llm_config.endpoint}")
        log(f"πŸ”§ Provider variant: {provider_variant}")
        
        return SparkLLM(
            spark_endpoint=llm_config.endpoint,
            spark_token=api_key,
            provider_variant=provider_variant,
            settings=llm_config.settings
        )
    
    @staticmethod
    def _create_gpt_provider(llm_config, api_key: str, provider_def) -> GPT4oLLM:
        """Create GPT-4 provider"""
        if not api_key:
            raise ValueError("OpenAI API key is required")
        
        # Get model-specific settings
        settings = llm_config.settings or {}
        model = provider_def.name  # gpt4o or gpt4o-mini
        
        log(f"πŸ€– Initializing GPT4oLLM with model: {model}")
        
        return GPT4oLLM(
            api_key=api_key,
            model=model,
            settings=settings
        )
    
    @staticmethod
    def _get_api_key(provider_name: str, config_key: Optional[str]) -> Optional[str]:
        """Get API key from config or environment"""
        # First check config
        if config_key:
            if config_key.startswith("enc:"):
                # Decrypt if encrypted
                from encryption_utils import decrypt
                decrypted = decrypt(config_key)
                log(f"πŸ”“ Using encrypted API key from config: ***{decrypted[-4:]}")
                return decrypted
            else:
                log(f"πŸ”‘ Using plain API key from config: ***{config_key[-4:]}")
                return config_key
        
        # Then check environment
        env_mappings = {
            "spark": "SPARK_TOKEN",
            "gpt4o": "OPENAI_API_KEY",
            "gpt4o-mini": "OPENAI_API_KEY"
        }
        
        env_var = env_mappings.get(provider_name)
        if env_var:
            # Check if we're in HuggingFace Space
            if os.getenv("SPACE_ID"):
                # HuggingFace mode - direct environment
                api_key = os.environ.get(env_var)
                if api_key:
                    log(f"πŸ”‘ Using API key from HuggingFace secrets: {env_var}")
                    return api_key
            else:
                # Local mode - use dotenv
                load_dotenv()
                api_key = os.getenv(env_var)
                if api_key:
                    log(f"πŸ”‘ Using API key from .env: {env_var}")
                    return api_key
        
        return None