bardd commited on
Commit
be2f959
·
verified ·
1 Parent(s): 1a1171e

Update src/rotator_library/providers/gemini_provider.py

Browse files
src/rotator_library/providers/gemini_provider.py CHANGED
@@ -14,6 +14,7 @@ if not lib_logger.handlers:
14
  class GeminiProvider(ProviderInterface):
15
  """
16
  Provider implementation for the Google Gemini API.
 
17
  """
18
  async def get_models(self, api_key: str, client: httpx.AsyncClient) -> List[str]:
19
  """
@@ -88,54 +89,103 @@ class GeminiProvider(ProviderInterface):
88
 
89
  return gemini_settings
90
 
 
 
 
 
 
 
 
91
  def handle_thinking_parameter(self, payload: Dict[str, Any], model: str):
92
  """
93
- Handles reasoning parameters for Gemini models, with three distinct paths:
94
- 1. Applies a non-standard, high-value token budget if 'custom_reasoning_budget' is true.
95
- 2. Leaves the 'reasoning_effort' parameter alone for LiteLLM to handle if it's present
96
- without the custom flag.
97
- 3. Applies a default 'thinking' value for specific models if no other reasoning
98
- parameters are provided, ensuring they 'think' by default.
99
  """
100
  # Set default temperature to 1 if not provided
101
  if "temperature" not in payload:
102
  payload["temperature"] = 1
103
 
104
- custom_reasoning_budget = payload.get("custom_reasoning_budget", False)
105
- reasoning_effort = payload.get("reasoning_effort")
106
 
107
  # If 'thinking' is already explicitly set, do nothing to avoid overriding it.
108
  if "thinking" in payload:
109
  return
110
 
111
- # Path 1: Custom budget is explicitly requested.
112
- if custom_reasoning_budget:
113
- # Case 1a: Both params are present, so we can apply the custom budget.
114
- if reasoning_effort:
115
- if "gemini-2.5-pro" in model:
116
- budgets = {"low": 8192, "medium": 16384, "high": 32768}
117
- elif "gemini-2.5-flash" in model:
118
- budgets = {"low": 6144, "medium": 12288, "high": 24576}
119
- else: # Fallback for other models if the custom flag is still used
120
- budgets = {"low": 1024, "medium": 2048, "high": 4096}
121
-
122
- budget = budgets.get(reasoning_effort)
123
- if budget is not None:
124
- payload["thinking"] = {"type": "enabled", "budget_tokens": budget}
125
- elif reasoning_effort == "disable":
126
- payload["thinking"] = {"type": "enabled", "budget_tokens": 0}
127
-
128
- # Clean up the handled 'reasoning_effort' parameter.
129
- payload.pop("reasoning_effort", None)
130
-
131
- # Case 1b: In all cases where the custom flag was present, remove it
132
- # as it's not a standard LiteLLM parameter.
133
- payload.pop("custom_reasoning_budget", None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  return
135
 
136
- # Path 2: No custom budget. Now check for standard or default behavior.
137
- # If 'reasoning_effort' is present, we do nothing, allowing LiteLLM to handle it.
138
- # If 'reasoning_effort' is NOT present, then we apply the default thinking behavior.
139
- if not reasoning_effort:
140
- if "gemini-2.5-pro" in model or "gemini-2.5-flash" in model:
141
- payload["thinking"] = {"type": "enabled", "budget_tokens": -1}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  class GeminiProvider(ProviderInterface):
15
  """
16
  Provider implementation for the Google Gemini API.
17
+ # TEST EDIT
18
  """
19
  async def get_models(self, api_key: str, client: httpx.AsyncClient) -> List[str]:
20
  """
 
89
 
90
  return gemini_settings
91
 
92
+ def _is_gemini_3(self, model: str) -> bool:
93
+ """
94
+ Helper to identify Gemini 3 models.
95
+ """
96
+ model_name = model.split("/")[-1].replace(":thinking", "")
97
+ return model_name.startswith("gemini-3-")
98
+
99
  def handle_thinking_parameter(self, payload: Dict[str, Any], model: str):
100
  """
101
+ Handles reasoning parameters for Gemini models (Gemini 2.5 and Gemini 3).
102
+ Maps 'reasoning_effort' to the appropriate Gemini-specific format for LiteLLM.
 
 
 
 
103
  """
104
  # Set default temperature to 1 if not provided
105
  if "temperature" not in payload:
106
  payload["temperature"] = 1
107
 
108
+ reasoning_effort = payload.pop("reasoning_effort", None)
109
+ custom_reasoning_budget = payload.pop("custom_reasoning_budget", False)
110
 
111
  # If 'thinking' is already explicitly set, do nothing to avoid overriding it.
112
  if "thinking" in payload:
113
  return
114
 
115
+ is_gemini_25 = "gemini-2.5" in model
116
+ is_gemini_3 = self._is_gemini_3(model)
117
+ is_gemini_3_flash = "gemini-3-flash" in model
118
+
119
+ if not (is_gemini_25 or is_gemini_3):
120
+ return
121
+
122
+ # Normalize and validate effort
123
+ if reasoning_effort is None:
124
+ effort = "auto"
125
+ elif isinstance(reasoning_effort, str):
126
+ effort = reasoning_effort.strip().lower() or "auto"
127
+ else:
128
+ effort = "auto"
129
+
130
+ valid_efforts = {
131
+ "auto", "disable", "off", "none", "minimal", "low",
132
+ "low_medium", "medium", "medium_high", "high"
133
+ }
134
+ if effort not in valid_efforts:
135
+ effort = "auto"
136
+
137
+ # Path 1: Gemini 3 Logic (Native Level Strings)
138
+ if is_gemini_3:
139
+ if is_gemini_3_flash:
140
+ # minimal/low/medium/high
141
+ if effort in ("disable", "off", "none"):
142
+ level = "minimal"
143
+ elif effort in ("minimal", "low"):
144
+ level = "low"
145
+ elif effort in ("low_medium", "medium"):
146
+ level = "medium"
147
+ else: # auto, medium_high, high
148
+ level = "high"
149
+ else: # Gemini 3 Pro (usually only low/high)
150
+ if effort in ("disable", "off", "none", "minimal", "low", "low_medium"):
151
+ level = "low"
152
+ else: # auto, medium, medium_high, high
153
+ level = "high"
154
+
155
+ payload["thinking"] = {"type": "enabled", "thinking_level": level}
156
+ return
157
+
158
+ # Path 2: Gemini 2.5 Logic (Token Budget)
159
+ if effort in ("disable", "off", "none"):
160
+ payload["thinking"] = {"type": "enabled", "budget_tokens": 0}
161
+ return
162
+
163
+ # If auto is used without custom budget, LiteLLM handles with -1
164
+ if effort == "auto" and not custom_reasoning_budget:
165
+ payload["thinking"] = {"type": "enabled", "budget_tokens": -1}
166
  return
167
 
168
+ # Model-specific budgets
169
+ if "gemini-2.5-flash" in model:
170
+ budgets = {
171
+ "minimal": 3072,
172
+ "low": 6144,
173
+ "low_medium": 9216,
174
+ "medium": 12288,
175
+ "medium_high": 18432,
176
+ "high": 24576,
177
+ "auto": 12288 if custom_reasoning_budget else -1
178
+ }
179
+ else: # Gemini 2.5 Pro
180
+ budgets = {
181
+ "minimal": 4096,
182
+ "low": 8192,
183
+ "low_medium": 12288,
184
+ "medium": 16384,
185
+ "medium_high": 24576,
186
+ "high": 32768,
187
+ "auto": 16384 if custom_reasoning_budget else -1
188
+ }
189
+
190
+ budget = budgets.get(effort, budgets["auto"])
191
+ payload["thinking"] = {"type": "enabled", "budget_tokens": budget}