feat(costs): Filler-Übersetzung + OpenRouter-TTS kostenerfasst

- fillers.py translate_pool: usage:{include:true} + Ist-Kosten (Kategorie llm).
- OpenRouter-TTS: geschaetzte Kosten (Zeichen × openrouter_tts_usd_per_char,
  Kategorie tts) — der Audio-Endpunkt liefert keine inline-usage. Preis (Default
  ~$15/1M Zeichen) live-setzbar; an Modellpreis anpassbar.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-06-30 19:25:34 +02:00
commit a1e49dde11
5 changed files with 23 additions and 2 deletions

View file

@ -17,6 +17,8 @@ import re
import httpx
from app.core.costs import record_openrouter_cost
logger = logging.getLogger(__name__)
ENDPOINT = "https://openrouter.ai/api/v1/chat/completions"
@ -107,13 +109,15 @@ def make_openrouter_translator(api_key: str, model: str):
f"no quotes, no extra words. Output ONLY a numbered list of the translations."
f"\n\n{numbered}"
)
payload = {"model": model, "temperature": 0.4,
payload = {"model": model, "temperature": 0.4, "usage": {"include": True},
"messages": [{"role": "user", "content": prompt}]}
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
async with httpx.AsyncClient(timeout=httpx.Timeout(30.0)) as client:
resp = await client.post(ENDPOINT, json=payload, headers=headers)
resp.raise_for_status()
text = resp.json()["choices"][0]["message"]["content"]
data = resp.json()
record_openrouter_cost(data.get("usage"), "llm")
text = data["choices"][0]["message"]["content"]
return _parse_numbered(text, len(phrases))
return translate_pool