"""Klient pro OpenAI — Whisper přepis + Chat Completions (slučování), přes httpx.""" import httpx from ..config import OPENAI_BASE_URL, UPSTREAM_TIMEOUT_SECONDS from ..errors import UpstreamError, raise_for_upstream from ..logging_config import get_logger log = get_logger("audio-transcription.openai") async def transcribe( *, api_key: str, audio: bytes, filename: str, content_type: str, model: str, language: str | None = None, ) -> str: """Přepíše audio přes OpenAI Whisper (/audio/transcriptions) a vrátí text.""" headers = {"Authorization": f"Bearer {api_key}"} files = {"file": (filename or "audio.mp3", audio, content_type or "application/octet-stream")} # temperature=0 => deterministický přepis, méně halucinací na tichu/šumu. form = {"model": model, "temperature": "0"} if language: form["language"] = language url = f"{OPENAI_BASE_URL}/audio/transcriptions" try: async with httpx.AsyncClient(timeout=UPSTREAM_TIMEOUT_SECONDS) as client: resp = await client.post(url, headers=headers, data=form, files=files) except httpx.HTTPError as exc: log.error("OpenAI transcription request failed: %s", exc) raise UpstreamError(f"OpenAI Whisper request se nezdařil: {exc}") from exc if resp.status_code >= 400: log.warning("OpenAI transcription returned %s: %s", resp.status_code, resp.text[:500]) raise_for_upstream("OpenAI Whisper", resp.status_code, resp.text) data = resp.json() return data.get("text", "") or "" async def merge_transcripts( *, api_key: str, model: str, system_prompt: str, text_deepgram: str, text_whisper: str, ) -> str: """Sloučí dva přepisy do jednoho přes Chat Completions dle system promptu.""" headers = {"Authorization": f"Bearer {api_key}"} payload = { "model": model, "messages": [ {"role": "system", "content": system_prompt}, {"role": "user", "content": f"Text z Deepgram: {text_deepgram}"}, {"role": "user", "content": f"Text z OpenAI Whisper: {text_whisper}"}, ], } url = f"{OPENAI_BASE_URL}/chat/completions" try: async with httpx.AsyncClient(timeout=UPSTREAM_TIMEOUT_SECONDS) as client: resp = await client.post(url, headers=headers, json=payload) except httpx.HTTPError as exc: log.error("OpenAI chat request failed: %s", exc) raise UpstreamError(f"OpenAI chat (merge) request se nezdařil: {exc}") from exc if resp.status_code >= 400: log.warning("OpenAI chat returned %s: %s", resp.status_code, resp.text[:500]) raise_for_upstream("OpenAI chat (merge)", resp.status_code, resp.text) data = resp.json() try: return data["choices"][0]["message"]["content"] or "" except (KeyError, IndexError, TypeError) as exc: log.error("Unexpected OpenAI chat response shape: %s", exc) raise UpstreamError("Neočekávaná struktura odpovědi z OpenAI chatu.") from exc