feat: SaluteSpeech STT for the pilot + no foreign STT outside the demo (ADR-016)
CI / ruff · pytest (pull_request) Successful in 2m16s
CI / ruff · pytest (pull_request) Successful in 2m16s
Refs #121 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+20
-3
@@ -42,12 +42,18 @@ class Settings(BaseSettings):
|
||||
chat_agent_timeout_s: float = 25.0
|
||||
chat_agent_max_steps: int = 5
|
||||
|
||||
# Voice input (#116): speech-to-text for the patient's messages. `auto` = OpenRouter if a key is set, else mock.
|
||||
# OpenRouter STT is synthetic data only (ADR-014): the audio leaves the RF and cannot be scrubbed.
|
||||
stt_provider: Literal["auto", "off", "mock", "openrouter"] = "auto"
|
||||
# Voice input (#116, #121): speech-to-text for the patient's messages. `auto` = SaluteSpeech if credentials are
|
||||
# set; otherwise, in the demo only, OpenRouter if a key is set, else mock. OpenRouter STT is synthetic data only
|
||||
# (ADR-014): the audio leaves the RF and cannot be scrubbed — forbidden with DEMO_CLOCK=false (validator below).
|
||||
stt_provider: Literal["auto", "off", "mock", "openrouter", "salute"] = "auto"
|
||||
stt_model: str = "google/gemini-2.5-flash" # needs audio input
|
||||
stt_timeout_s: float = 30.0
|
||||
stt_max_seconds: int = Field(default=60, ge=5, le=300)
|
||||
# SaluteSpeech (Sber, RF contour) — the pilot provider (#121, ADR-016). Credentials = the base64 authorization key.
|
||||
salute_speech_credentials: SecretStr = SecretStr("")
|
||||
salute_speech_scope: str = "SALUTE_SPEECH_PERS"
|
||||
# Russian Trusted Root CA (Минцифры) is not in certifi: point to the .crt/.pem to verify Sber's TLS chain.
|
||||
salute_speech_ca: Path | None = None
|
||||
|
||||
# Telegram is used only for the prototype on synthetic data; prod channel is MAX / Gosuslugi.
|
||||
tg_bot_token: str = ""
|
||||
@@ -65,6 +71,17 @@ class Settings(BaseSettings):
|
||||
max_ca_bundle: Path | None = None
|
||||
max_link_ttl_seconds: int = Field(default=600, ge=60, le=1800)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_stt(self) -> "Settings":
|
||||
if self.stt_provider == "openrouter" and not self.demo_clock:
|
||||
raise ValueError(
|
||||
"STT_PROVIDER=openrouter is for synthetic data only (ADR-014) and is forbidden with DEMO_CLOCK=false: "
|
||||
"use STT_PROVIDER=salute"
|
||||
)
|
||||
if self.salute_speech_ca is not None and not self.salute_speech_ca.is_file():
|
||||
raise ValueError("SALUTE_SPEECH_CA must point to an existing CA certificate file")
|
||||
return self
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_max(self) -> "Settings":
|
||||
if not self.max_enabled:
|
||||
|
||||
Reference in New Issue
Block a user