ai_gemini.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. from __future__ import annotations
  2. from typing import Any
  3. from urllib.parse import quote
  4. import httpx
  5. DEFAULT_GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta"
  6. def normalize_base_url(base_url: str | None) -> str:
  7. return (base_url or DEFAULT_GEMINI_BASE_URL).rstrip("/")
  8. def chat(provider: dict[str, Any], model: dict[str, Any], prompt: str, temperature: float) -> dict[str, Any]:
  9. base_url = normalize_base_url(provider.get("base_url"))
  10. headers = {"Content-Type": "application/json"}
  11. api_key = provider.get("api_key")
  12. if api_key:
  13. headers["x-goog-api-key"] = api_key
  14. payload = {
  15. "contents": [{"parts": [{"text": prompt}]}],
  16. "generationConfig": {"temperature": temperature},
  17. }
  18. model_name = quote(model["name"], safe="")
  19. with httpx.Client(timeout=120) as client:
  20. response = client.post(f"{base_url}/models/{model_name}:generateContent", json=payload, headers=headers)
  21. response.raise_for_status()
  22. data = response.json()
  23. parts = data.get("candidates", [{}])[0].get("content", {}).get("parts", [])
  24. content = "".join(part.get("text", "") for part in parts)
  25. return {"content": content, "raw_response": data}
  26. def chat_with_images(
  27. provider: dict[str, Any],
  28. model: dict[str, Any],
  29. prompt: str,
  30. images: list[dict[str, str]],
  31. temperature: float,
  32. ) -> dict[str, Any]:
  33. base_url = normalize_base_url(provider.get("base_url"))
  34. headers = {"Content-Type": "application/json"}
  35. api_key = provider.get("api_key")
  36. if api_key:
  37. headers["x-goog-api-key"] = api_key
  38. parts: list[dict[str, Any]] = [{"text": prompt}]
  39. for image in images:
  40. parts.append(
  41. {
  42. "inlineData": {
  43. "mimeType": image["mime_type"],
  44. "data": image["base64"],
  45. }
  46. }
  47. )
  48. payload = {
  49. "contents": [{"parts": parts}],
  50. "generationConfig": {"temperature": temperature},
  51. }
  52. model_name = quote(model["name"], safe="")
  53. with httpx.Client(timeout=180) as client:
  54. response = client.post(f"{base_url}/models/{model_name}:generateContent", json=payload, headers=headers)
  55. response.raise_for_status()
  56. data = response.json()
  57. response_parts = data.get("candidates", [{}])[0].get("content", {}).get("parts", [])
  58. content = "".join(part.get("text", "") for part in response_parts)
  59. return {"content": content, "raw_response": data}