Compare commits
No commits in common. "9156962ee3b0d728422915925e4eefe3f335351f" and "77f0ec90b54b0d46c86da9f93108236b589cb941" have entirely different histories.
9156962ee3
...
77f0ec90b5
7 changed files with 3 additions and 33 deletions
|
|
@ -3,15 +3,6 @@
|
|||
Alle nennenswerten Änderungen an **Alexis**. Format lose nach [Keep a Changelog](https://keepachangelog.com/de/);
|
||||
Versionierung nach [SemVer](https://semver.org/lang/de/) (prä-1.0: `0.x`).
|
||||
|
||||
## [0.3.5] — 2026-06-30
|
||||
|
||||
### Hinzugefügt
|
||||
- **Kostenerfassung vervollständigt:**
|
||||
- **Filler-Übersetzung** (OpenRouter) bucht jetzt ihre Ist-Kosten (Kategorie `llm`).
|
||||
- **OpenRouter-TTS** wird geschätzt erfasst (Zeichen × `openrouter_tts_usd_per_char`,
|
||||
Kategorie `tts`) — der Audio-Endpunkt liefert keine inline-`usage`. Preis im Admin
|
||||
live einstellbar (Default ≈ $15/1M Zeichen, an Modellpreis anpassen).
|
||||
|
||||
## [0.3.4] — 2026-06-30
|
||||
|
||||
### Hinzugefügt
|
||||
|
|
|
|||
|
|
@ -194,7 +194,6 @@ class Settings(BaseSettings):
|
|||
# Kostenerfassung Stufe 2 (geschätzte Quellen). Siehe Docs/kosten-erfassung.md.
|
||||
usd_per_eur: float = 1.08 # Umrechnung EUR-naher Schätzungen in die USD-Anzeige
|
||||
cartesia_usd_per_char: float = 0.00005 # Cartesia: 100k Credits ≈ 100.000 Zeichen → $5
|
||||
openrouter_tts_usd_per_char: float = 0.000015 # OpenRouter-TTS (Schätzung, ≈ $15/1M Zeichen) — an Modellpreis anpassen
|
||||
emergency_alert_eur: float = 0.20 # SMS+Voice pro Alarm (Schätzung)
|
||||
# Lokales LLM: Stromkosten pro Anfrage (marginal über Leerlauf), 2× RTX 3090.
|
||||
gpu_idle_watts: float = 40.0 # Leerlauf je GPU = Infrastruktur (nicht pro Anfrage)
|
||||
|
|
|
|||
|
|
@ -102,17 +102,6 @@ def cartesia_usd(n_chars, cfg=None) -> float:
|
|||
return max(0, n) * cfg.cartesia_usd_per_char
|
||||
|
||||
|
||||
def openrouter_tts_usd(n_chars, cfg=None) -> float:
|
||||
"""OpenRouter-TTS-Kosten (USD) fuer `n_chars` (Schaetzung — der Audio-Endpunkt
|
||||
liefert keine inline-Kosten wie der Chat-Endpunkt)."""
|
||||
cfg = _cfg(cfg)
|
||||
try:
|
||||
n = int(n_chars or 0)
|
||||
except (TypeError, ValueError):
|
||||
return 0.0
|
||||
return max(0, n) * cfg.openrouter_tts_usd_per_char
|
||||
|
||||
|
||||
def eur_to_usd(eur, cfg=None) -> float:
|
||||
cfg = _cfg(cfg)
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@ import re
|
|||
|
||||
import httpx
|
||||
|
||||
from app.core.costs import record_openrouter_cost
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
ENDPOINT = "https://openrouter.ai/api/v1/chat/completions"
|
||||
|
|
@ -109,15 +107,13 @@ 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, "usage": {"include": True},
|
||||
payload = {"model": model, "temperature": 0.4,
|
||||
"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()
|
||||
data = resp.json()
|
||||
record_openrouter_cost(data.get("usage"), "llm")
|
||||
text = data["choices"][0]["message"]["content"]
|
||||
text = resp.json()["choices"][0]["message"]["content"]
|
||||
return _parse_numbered(text, len(phrases))
|
||||
|
||||
return translate_pool
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import asyncio
|
|||
|
||||
import httpx
|
||||
|
||||
from app.core.costs import add_cost, openrouter_tts_usd
|
||||
from app.providers.tts.base import TTSProvider
|
||||
|
||||
# Preview-TTS-Modelle liefern gelegentlich HTTP 200 mit LEEREM Body oder ein
|
||||
|
|
@ -71,9 +70,6 @@ class OpenRouterTTSProvider(TTSProvider):
|
|||
raise RuntimeError(f"OpenRouter TTS transport error: {exc}") from exc
|
||||
else:
|
||||
if response.content:
|
||||
# Geschätzte TTS-Kosten (Zeichen × Preis); Audio-Endpunkt
|
||||
# liefert keine inline-usage.
|
||||
add_cost(openrouter_tts_usd(len(text.strip())), "tts")
|
||||
return response.content
|
||||
# HTTP 200 mit leerem Body -> transienter Aussetzer, erneut versuchen.
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ RUNTIME_SETTABLE: dict[str, tuple[str, str, str]] = {
|
|||
"electricity_price_eur_per_kwh": ("Strompreis (€/kWh)", "float", "Kosten lokaler LLM-Anfragen (z.B. 0.33)"),
|
||||
"emergency_alert_eur": ("Notruf-Kosten (€/Alarm)", "float", "SMS+Anruf pro Alarm (z.B. 0.20)"),
|
||||
"cartesia_usd_per_char": ("Cartesia-TTS ($/Zeichen)", "float", "z.B. 0.00005 (100k Credits ≈ 100.000 Zeichen)"),
|
||||
"openrouter_tts_usd_per_char": ("OpenRouter-TTS ($/Zeichen)", "float", "Schätzung, z.B. 0.000015 — an Modellpreis anpassen"),
|
||||
"emergency_cooldown_minutes": ("Notruf-Sperre (Minuten)", "int", "Erneuter Alarm für N Minuten blockiert (Standard 5, 0 = aus)"),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "voice-assistant-gateway"
|
||||
version = "0.3.5"
|
||||
version = "0.3.4"
|
||||
description = "Modular voice assistant gateway with pluggable audio endpoints and provider adapters"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue