ai_openai.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. from __future__ import annotations
  2. from typing import Any
  3. import httpx
  4. DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1"
  5. def normalize_base_url(base_url: str | None) -> str:
  6. return (base_url or DEFAULT_OPENAI_BASE_URL).rstrip("/")
  7. def chat(provider: dict[str, Any], model: dict[str, Any], prompt: str, temperature: float) -> dict[str, Any]:
  8. base_url = normalize_base_url(provider.get("base_url"))
  9. headers = {"Content-Type": "application/json"}
  10. api_key = provider.get("api_key")
  11. if api_key:
  12. headers["Authorization"] = f"Bearer {api_key}"
  13. payload = {
  14. "model": model["name"],
  15. "messages": [{"role": "user", "content": prompt}],
  16. "temperature": temperature,
  17. }
  18. with httpx.Client(timeout=120) as client:
  19. response = client.post(f"{base_url}/chat/completions", json=payload, headers=headers)
  20. response.raise_for_status()
  21. data = response.json()
  22. content = data.get("choices", [{}])[0].get("message", {}).get("content")
  23. if content is None:
  24. content = ""
  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["Authorization"] = f"Bearer {api_key}"
  38. content: list[dict[str, Any]] = [{"type": "text", "text": prompt}]
  39. for image in images:
  40. content.append(
  41. {
  42. "type": "image_url",
  43. "image_url": {"url": f"data:{image['mime_type']};base64,{image['base64']}"},
  44. }
  45. )
  46. payload = {
  47. "model": model["name"],
  48. "messages": [{"role": "user", "content": content}],
  49. "temperature": temperature,
  50. }
  51. with httpx.Client(timeout=180) as client:
  52. response = client.post(f"{base_url}/chat/completions", json=payload, headers=headers)
  53. response.raise_for_status()
  54. data = response.json()
  55. result = data.get("choices", [{}])[0].get("message", {}).get("content") or ""
  56. return {"content": result, "raw_response": data}