99
1010from __future__ import annotations
1111
12- import asyncio
1312import json
1413import logging
1514import os
@@ -115,26 +114,33 @@ async def generate_response(
115114 if dry_run :
116115 return f"[DRY RUN / MOCK MODE] Generated response for input:\n { prompt_text } "
117116
118- # Dispatch to provider
119- if self .provider == "anthropic" or (self .anthropic_api_key and not self .gemini_api_key ):
120- try :
121- return await self ._generate_anthropic (system_instruction , prompt_text )
122- except Exception as e :
123- logger .warning (f"Anthropic generation failed: { e } " )
124-
125- if self .provider == "openai" or (self .openai_api_key and not self .gemini_api_key ):
126- try :
127- return await self ._generate_openai (system_instruction , prompt_text )
128- except Exception as e :
129- logger .warning (f"OpenAI generation failed: { e } " )
117+ provider_generators = {
118+ "gemini" : lambda : self ._generate_gemini (system_instruction , prompt_text , dry_run = dry_run , tier = tier ),
119+ "openai" : lambda : self ._generate_openai (system_instruction , prompt_text ),
120+ "anthropic" : lambda : self ._generate_anthropic (system_instruction , prompt_text ),
121+ "ollama" : lambda : self ._generate_ollama (system_instruction , prompt_text ),
122+ }
123+ configured = {
124+ "gemini" : bool (self .gemini_api_key ),
125+ "openai" : bool (self .openai_api_key ),
126+ "anthropic" : bool (self .anthropic_api_key ),
127+ "ollama" : bool (self .ollama_host ),
128+ }
129+ provider_order = [self .provider ] + [name for name , enabled in configured .items () if enabled and name != self .provider ]
130+ last_error : Optional [Exception ] = None
130131
131- if self .provider == "ollama" :
132+ for provider in provider_order :
133+ generator = provider_generators .get (provider )
134+ if not generator or (provider != "gemini" and not configured [provider ]):
135+ continue
132136 try :
133- return await self ._generate_ollama (system_instruction , prompt_text )
134- except Exception as e :
135- logger .warning (f"Ollama generation failed: { e } " )
137+ return await generator ()
138+ except Exception as exc :
139+ last_error = exc
140+ logger .warning ("%s generation failed; trying next configured provider: %s" , provider , exc )
136141
137- # Default / Fallback: Google Gemini
142+ if last_error :
143+ raise RuntimeError (f"All configured LLM providers failed. Last error: { last_error } " ) from last_error
138144 return await self ._generate_gemini (system_instruction , prompt_text , dry_run = dry_run , tier = tier )
139145
140146 def _get_gemini_candidate_models (self , tier : str = "fast" ) -> List [str ]:
@@ -216,8 +222,6 @@ async def _generate_gemini(self, system_instruction: str, user_input: str, dry_r
216222 except Exception as e :
217223 last_error = e
218224 print (f"[LLM:Gemini] ⚠️ Model { model_name } (SDK) failed: { e } " )
219- if "429" in str (e ) or "RESOURCE_EXHAUSTED" in str (e ):
220- await asyncio .sleep (2 )
221225
222226 # 2. Try Gemini REST API
223227 if self .gemini_api_key :
@@ -241,8 +245,6 @@ async def _generate_gemini(self, system_instruction: str, user_input: str, dry_r
241245 else :
242246 last_error = f"HTTP { resp .status_code } : { resp .text } "
243247 print (f"[LLM:Gemini-REST] ⚠️ Model { model_name } (REST) failed with HTTP { resp .status_code } : { resp .text [:120 ]} " )
244- if resp .status_code == 429 :
245- await asyncio .sleep (2 )
246248 except Exception as e :
247249 last_error = e
248250 print (f"[LLM:Gemini-REST] ⚠️ REST request for { model_name } failed: { e } " )
0 commit comments