from __future__ import annotations from typing import Any import httpx DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1" def normalize_base_url(base_url: str | None) -> str: return (base_url or DEFAULT_OPENAI_BASE_URL).rstrip("/") def chat(provider: dict[str, Any], model: dict[str, Any], prompt: str, temperature: float) -> dict[str, Any]: base_url = normalize_base_url(provider.get("base_url")) headers = {"Content-Type": "application/json"} api_key = provider.get("api_key") if api_key: headers["Authorization"] = f"Bearer {api_key}" payload = { "model": model["name"], "messages": [{"role": "user", "content": prompt}], "temperature": temperature, } with httpx.Client(timeout=120) as client: response = client.post(f"{base_url}/chat/completions", json=payload, headers=headers) response.raise_for_status() data = response.json() content = data.get("choices", [{}])[0].get("message", {}).get("content") if content is None: content = "" return {"content": content, "raw_response": data} def chat_with_images( provider: dict[str, Any], model: dict[str, Any], prompt: str, images: list[dict[str, str]], temperature: float, ) -> dict[str, Any]: base_url = normalize_base_url(provider.get("base_url")) headers = {"Content-Type": "application/json"} api_key = provider.get("api_key") if api_key: headers["Authorization"] = f"Bearer {api_key}" content: list[dict[str, Any]] = [{"type": "text", "text": prompt}] for image in images: content.append( { "type": "image_url", "image_url": {"url": f"data:{image['mime_type']};base64,{image['base64']}"}, } ) payload = { "model": model["name"], "messages": [{"role": "user", "content": content}], "temperature": temperature, } with httpx.Client(timeout=180) as client: response = client.post(f"{base_url}/chat/completions", json=payload, headers=headers) response.raise_for_status() data = response.json() result = data.get("choices", [{}])[0].get("message", {}).get("content") or "" return {"content": result, "raw_response": data}