feat(gemini): migrate to google-genai SDK (no more deprecation warning)
This commit is contained in:
parent
97ccecb82b
commit
b8ccb2f250
@ -11,7 +11,7 @@ dependencies = [
|
||||
"pydantic>=2.6.0",
|
||||
"pydantic-settings>=2.2.0",
|
||||
"pyyaml>=6.0.1",
|
||||
"google-generativeai>=0.8.0",
|
||||
"google-genai>=0.8.0",
|
||||
"anthropic>=0.40.0",
|
||||
"openai>=1.50.0",
|
||||
"requests>=2.32.0",
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
"""Google-Gemini-Client mit JSON-Output."""
|
||||
"""Google-Gemini-Client mit JSON-Output (neues google-genai SDK)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
import time
|
||||
|
||||
import google.generativeai as genai
|
||||
from google.api_core.exceptions import ResourceExhausted
|
||||
from google import genai
|
||||
from google.genai import errors as genai_errors
|
||||
from google.genai import types
|
||||
|
||||
from ..config import Settings
|
||||
from ..logging_setup import get_logger
|
||||
@ -17,10 +18,17 @@ log = get_logger(__name__)
|
||||
|
||||
|
||||
def _extract_retry_seconds(err: Exception, fallback: float) -> float:
|
||||
m = re.search(r"retry in (\d+(?:\.\d+)?)", str(err))
|
||||
m = re.search(r"retry in (\d+(?:\.\d+)?)", str(err), re.IGNORECASE)
|
||||
return float(m.group(1)) if m else fallback
|
||||
|
||||
|
||||
def _is_rate_limit(err: Exception) -> bool:
|
||||
code = getattr(err, "code", None) or getattr(err, "status_code", None)
|
||||
if code == 429:
|
||||
return True
|
||||
return "429" in str(err) or "RESOURCE_EXHAUSTED" in str(err).upper()
|
||||
|
||||
|
||||
class GeminiClient:
|
||||
provider = "gemini"
|
||||
|
||||
@ -29,31 +37,29 @@ class GeminiClient:
|
||||
) -> None:
|
||||
if not settings.gemini_api_key:
|
||||
raise RuntimeError("GEMINI_API_KEY nicht gesetzt")
|
||||
genai.configure(api_key=settings.gemini_api_key)
|
||||
self.model = model or "gemini-2.0-flash"
|
||||
self.model = model or "gemini-2.5-flash-lite"
|
||||
self.temperature = temperature
|
||||
self._model = genai.GenerativeModel(
|
||||
self.model,
|
||||
self.client = genai.Client(api_key=settings.gemini_api_key)
|
||||
self._config = types.GenerateContentConfig(
|
||||
system_instruction=SYSTEM_PROMPT,
|
||||
temperature=self.temperature,
|
||||
response_mime_type="application/json",
|
||||
response_schema=JSON_SCHEMA,
|
||||
)
|
||||
self.timeout = settings.ai.timeout_seconds
|
||||
|
||||
def decide(self, user_prompt: str) -> TradeDecision:
|
||||
attempts = 0
|
||||
max_attempts = 3
|
||||
while True:
|
||||
try:
|
||||
resp = self._model.generate_content(
|
||||
user_prompt,
|
||||
generation_config={
|
||||
"response_mime_type": "application/json",
|
||||
"response_schema": JSON_SCHEMA,
|
||||
"temperature": self.temperature,
|
||||
},
|
||||
request_options={"timeout": self.timeout},
|
||||
resp = self.client.models.generate_content(
|
||||
model=self.model,
|
||||
contents=user_prompt,
|
||||
config=self._config,
|
||||
)
|
||||
break
|
||||
except ResourceExhausted as e:
|
||||
except genai_errors.APIError as e:
|
||||
if _is_rate_limit(e):
|
||||
attempts += 1
|
||||
if attempts >= max_attempts:
|
||||
log.warning("gemini.rate_limit_giveup", attempts=attempts)
|
||||
@ -64,10 +70,20 @@ class GeminiClient:
|
||||
wait = min(_extract_retry_seconds(e, 30.0) + 2, 60.0)
|
||||
log.warning("gemini.rate_limit", attempt=attempts, wait_s=wait)
|
||||
time.sleep(wait)
|
||||
text = resp.text or "{}"
|
||||
continue
|
||||
log.warning("gemini.api_error", error=str(e)[:300])
|
||||
return TradeDecision(
|
||||
action="HOLD", confidence=0.0, suggested_size_pct=0.0,
|
||||
reasoning=f"api_error: {e}",
|
||||
)
|
||||
|
||||
text = (resp.text or "{}").strip()
|
||||
try:
|
||||
data = json.loads(text)
|
||||
return TradeDecision.model_validate(data)
|
||||
except Exception as e:
|
||||
log.warning("gemini.parse_failed", error=str(e), raw=text[:300])
|
||||
return TradeDecision(action="HOLD", confidence=0.0, suggested_size_pct=0.0, reasoning=f"parse_error: {e}")
|
||||
return TradeDecision(
|
||||
action="HOLD", confidence=0.0, suggested_size_pct=0.0,
|
||||
reasoning=f"parse_error: {e}",
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user