Add pipecat-based backend with WebRTC/WS voice routes, Next.js frontend, and Docker Compose orchestration. Co-authored-by: Cursor <cursoragent@cursor.com>
65 lines
2.6 KiB
Python
65 lines
2.6 KiB
Python
"""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),
|
|
)
|