"""assistant_id → 运行时配置(把真 key 在服务端组装好)。 浏览器只传 assistant_id;真 key 在这里从 provider_credentials 取出注入。 取不到凭证记录时,降级用 .env 默认值(开发期零配置仍能跑)。 """ import config from db.models import Assistant, ProviderCredential from models import AssistantConfig from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession async def _get_credential( session: AsyncSession, type_: str, name: str = "" ) -> ProviderCredential | None: """取某类(LLM/ASR/TTS)凭证:优先按资源名匹配,否则取该类默认。""" stmt = select(ProviderCredential).where(ProviderCredential.type == type_) if name: # 助手按资源名引用(如 model="DeepSeek-V3");命中则用它 named = ( await session.execute(stmt.where(ProviderCredential.name == name).limit(1)) ).scalar_one_or_none() if named: return named stmt = stmt.order_by( ProviderCredential.is_default.desc(), ProviderCredential.id.asc() ).limit(1) return (await session.execute(stmt)).scalar_one_or_none() async def resolve_runtime_config( session: AsyncSession, assistant_id: str ) -> AssistantConfig: """加载助手 + 解析凭证,产出可直接交给管线的运行时配置(含真 key)。 type 映射:LLM→大模型, ASR→语音识别, TTS→语音合成。 """ assistant = await session.get(Assistant, assistant_id) if assistant is None: raise ValueError(f"助手不存在: {assistant_id}") llm = await _get_credential(session, "LLM", assistant.model) stt = await _get_credential(session, "ASR", assistant.asr) tts = await _get_credential(session, "TTS") return AssistantConfig( name=assistant.name, greeting=assistant.greeting, prompt=assistant.prompt, runtimeMode=assistant.runtime_mode, # type: ignore[arg-type] enableInterrupt=assistant.enable_interrupt, # 模型/音色:凭证的模型ID优先,否则助手里填的 model=(llm.model_id if llm else assistant.model), asr=(stt.model_id if stt else assistant.asr), voice=assistant.voice, # 运行时连接信息(真 key + url):凭证优先,否则 .env 兜底 llm_api_key=(llm.api_key if llm else config.LLM_API_KEY), llm_base_url=(llm.api_url if llm else config.LLM_BASE_URL), stt_api_key=(stt.api_key if stt else config.STT_API_KEY), stt_base_url=(stt.api_url if stt else config.STT_BASE_URL), tts_api_key=(tts.api_key if tts else config.TTS_API_KEY), tts_base_url=(tts.api_url if tts else config.TTS_BASE_URL), )