llm_provider.py
1 """ 2 Generic LLM Provider - Supports Multiple LLMs 3 4 Supports: 5 - OpenAI (GPT-4, GPT-3.5, GPT-4o-mini) 6 - Anthropic Claude (Claude 3 Opus, Sonnet, Haiku) 7 - Google Gemini (Gemini 2.5 Pro, 1.5 Pro, 1.5 Flash) 8 - Ollama (Local models: qwen3, llama3, mistral, , etc.) 9 """ 10 11 from langchain_core.language_models import BaseChatModel 12 from langchain_openai import ChatOpenAI 13 from langchain_anthropic import ChatAnthropic 14 from langchain_google_genai import ChatGoogleGenerativeAI 15 from langchain_community.chat_models import ChatOllama 16 from pydantic import SecretStr 17 import os 18 from enum import Enum 19 20 21 # ============================================================================ 22 # LLM PROVIDER ENUM 23 # ============================================================================ 24 25 class LLMProvider(str, Enum): 26 """Supported LLM providers""" 27 OPENAI = "openai" 28 ANTHROPIC = "anthropic" 29 GEMINI = "gemini" 30 OLLAMA = "ollama" 31 32 # ============================================================================ 33 # LLM FACTORY 34 # ============================================================================ 35 36 class LLMFactory: 37 """ 38 Factory class to create LLM instances based on provider 39 """ 40 41 @staticmethod 42 def create_llm( 43 provider: str = None, 44 model: str = None, 45 temperature: float = 0.3, 46 max_tokens: int = 1000, 47 api_key: str = None, 48 base_url: str = None, 49 **kwargs 50 ) -> BaseChatModel: 51 """ 52 Create an LLM instance based on provider 53 54 Args: 55 provider: LLM provider (openai, anthropic, gemini, ollama, mock) 56 model: Model name 57 temperature: Temperature setting (0-1) 58 max_tokens: Maximum tokens in response 59 api_key: API key for the provider 60 base_url: Base URL for API (for Ollama or custom endpoints) 61 **kwargs: Additional provider-specific parameters 62 63 Returns: 64 Configured LLM instance 65 """ 66 # Get provider from environment if not specified 67 if provider is None: 68 provider = os.getenv("LLM_PROVIDER", "openai").lower() 69 70 provider = provider.lower() 71 72 # Create LLM based on provider 73 if provider == LLMProvider.OPENAI: 74 return LLMFactory._create_openai(model, temperature, max_tokens, api_key, **kwargs) 75 76 elif provider == LLMProvider.ANTHROPIC: 77 return LLMFactory._create_anthropic(model, temperature, max_tokens, api_key, **kwargs) 78 79 elif provider == LLMProvider.GEMINI: 80 return LLMFactory._create_gemini(model, temperature, max_tokens, api_key, **kwargs) 81 82 elif provider == LLMProvider.OLLAMA: 83 return LLMFactory._create_ollama(model, temperature, max_tokens, base_url, **kwargs) 84 85 else: 86 raise ValueError(f"Unsupported LLM provider: {provider}") 87 88 @staticmethod 89 def _create_openai( 90 model: str = None, 91 temperature: float = 0.3, 92 max_tokens: int = 1000, 93 api_key: str = None, 94 **kwargs 95 ) -> ChatOpenAI: 96 """Create OpenAI LLM instance""" 97 model = model or os.getenv("OPENAI_MODEL", "gpt-4o-mini") 98 api_key = api_key or os.getenv("OPENAI_API_KEY") 99 100 llm_kwargs = { 101 "model": model, 102 "temperature": temperature, 103 "max_tokens": max_tokens, 104 } 105 106 if api_key: 107 llm_kwargs["api_key"] = SecretStr(api_key) 108 109 # Add any additional kwargs 110 llm_kwargs.update(kwargs) 111 112 return ChatOpenAI(**llm_kwargs) 113 114 @staticmethod 115 def _create_anthropic( 116 model: str = None, 117 temperature: float = 0.3, 118 max_tokens: int = 1000, 119 api_key: str = None, 120 **kwargs 121 ) -> ChatAnthropic: 122 """Create Anthropic Claude LLM instance""" 123 model = model or os.getenv("ANTHROPIC_MODEL", "claude-3-5-sonnet-20241022") 124 api_key = api_key or os.getenv("ANTHROPIC_API_KEY") 125 126 llm_kwargs = { 127 "model": model, 128 "temperature": temperature, 129 "max_tokens": max_tokens, 130 } 131 132 if api_key: 133 llm_kwargs["api_key"] = SecretStr(api_key) 134 135 # Add any additional kwargs 136 llm_kwargs.update(kwargs) 137 138 return ChatAnthropic(**llm_kwargs) 139 140 @staticmethod 141 def _create_gemini( 142 model: str = None, 143 temperature: float = 0.3, 144 max_tokens: int = 1000, 145 api_key: str = None, 146 **kwargs 147 ) -> ChatGoogleGenerativeAI: 148 """Create Google Gemini LLM instance""" 149 model = model or os.getenv("GEMINI_MODEL", "gemini-2.5-pro") 150 api_key = api_key or os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY") 151 152 llm_kwargs = { 153 "model": model, 154 "temperature": temperature, 155 "max_tokens": max_tokens, 156 } 157 158 if api_key: 159 llm_kwargs["google_api_key"] = api_key 160 161 # Add any additional kwargs 162 llm_kwargs.update(kwargs) 163 164 return ChatGoogleGenerativeAI(**llm_kwargs) 165 166 @staticmethod 167 def _create_ollama( 168 model: str = None, 169 temperature: float = 0.3, 170 max_tokens: int = 1000, 171 base_url: str = None, 172 **kwargs 173 ) -> ChatOllama: 174 """Create Ollama (local) LLM instance""" 175 model = model or os.getenv("OLLAMA_MODEL", "qwen3:8b") 176 base_url = base_url or os.getenv("OLLAMA_BASE_URL", "http://localhost:11434") 177 178 llm_kwargs = { 179 "model": model, 180 "temperature": temperature, 181 "base_url": base_url, 182 } 183 184 # Add any additional kwargs 185 llm_kwargs.update(kwargs) 186 187 return ChatOllama(**llm_kwargs) 188 189 190 # ============================================================================ 191 # CONVENIENCE FUNCTIONS 192 # ============================================================================ 193 194 def create_extraction_llm( 195 provider: str = None, 196 model: str = None, 197 api_key: str = None 198 ) -> BaseChatModel: 199 """ 200 Create LLM optimized for data extraction 201 202 Args: 203 provider: LLM provider (openai, anthropic, ollama, mock) 204 model: Specific model name (optional) 205 api_key: API key (optional, uses env var if not provided) 206 """ 207 return LLMFactory.create_llm( 208 provider=provider, 209 model=model, 210 temperature=0.2, 211 max_tokens=500, 212 api_key=api_key 213 ) 214 215 216 def create_job_skills_llm( 217 provider: str = None, 218 model: str = None, 219 api_key: str = None 220 ) -> BaseChatModel: 221 """ 222 Create LLM optimized for job skills extraction 223 224 Args: 225 provider: LLM provider (openai, anthropic, ollama, mock) 226 model: Specific model name (optional) 227 api_key: API key (optional, uses env var if not provided) 228 """ 229 return LLMFactory.create_llm( 230 provider=provider, 231 model=model, 232 temperature=0.0, 233 max_tokens=600, 234 api_key=api_key 235 ) 236 237 238 def create_summary_llm( 239 provider: str = None, 240 model: str = None, 241 api_key: str = None 242 ) -> BaseChatModel: 243 """ 244 Create LLM optimized for summarization 245 246 Args: 247 provider: LLM provider (openai, anthropic, ollama, mock) 248 model: Specific model name (optional) 249 api_key: API key (optional, uses env var if not provided) 250 """ 251 return LLMFactory.create_llm( 252 provider=provider, 253 model=model, 254 temperature=0.5, 255 max_tokens=300, 256 api_key=api_key 257 ) 258 259 260 def create_evaluation_llm( 261 provider: str = None, 262 model: str = None, 263 api_key: str = None 264 ) -> BaseChatModel: 265 """ 266 Create LLM optimized for evaluation 267 268 Args: 269 provider: LLM provider (openai, anthropic, ollama, mock) 270 model: Specific model name (optional) 271 api_key: API key (optional, uses env var if not provided) 272 """ 273 return LLMFactory.create_llm( 274 provider=provider, 275 model=model, 276 temperature=0.4, 277 max_tokens=600, 278 api_key=api_key 279 ) 280 281 282 # ============================================================================ 283 # USAGE EXAMPLES 284 # ============================================================================ 285 286 """ 287 Example 1: Using OpenAI (Default) 288 ---------------------------------- 289 llm = create_summary_llm() 290 # or 291 llm = create_summary_llm(provider="openai", model="gpt-4") 292 293 294 Example 2: Using Anthropic Claude 295 ---------------------------------- 296 llm = create_summary_llm( 297 provider="anthropic", 298 model="claude-3-5-sonnet-20241022", 299 api_key="your-anthropic-key" 300 ) 301 302 303 Example 3: Using Google Gemini 304 ------------------------------- 305 llm = create_summary_llm( 306 provider="gemini", 307 model="gemini-2.5-pro", 308 api_key="your-google-api-key" 309 ) 310 311 312 Example 4: Using Ollama (Local, Free) 313 -------------------------------------- 314 llm = create_summary_llm( 315 provider="ollama", 316 model="qwen3:8b" 317 ) 318 319 320 Example 6: Using Environment Variables 321 --------------------------------------- 322 # Set in .env: 323 # LLM_PROVIDER=gemini 324 # GEMINI_API_KEY=your-key 325 # GEMINI_MODEL=gemini-2.5-pro 326 327 llm = create_summary_llm() # Automatically uses env vars 328 329 330 Example 7: Custom Configuration 331 -------------------------------- 332 llm = LLMFactory.create_llm( 333 provider="gemini", 334 model="gemini-1.5-pro", 335 temperature=0.7, 336 max_tokens=2000, 337 top_p=0.9 338 ) 339 """