- Add new fields in AssistantConfig for FastGPT connection details, including `fastgpt_api_url`, `fastgpt_api_key`, and `fastgpt_app_id`. - Update the pipeline to utilize the new FastGPT configuration, ensuring proper integration with external services. - Introduce type handling for different assistant types, including support for realtime modes and external brain management. - Refactor frontend components to include hints for FastGPT configuration inputs, improving user guidance during setup.
108 lines
5.1 KiB
Python
108 lines
5.1 KiB
Python
"""assistant_id → 运行时配置(把真 key 在服务端组装好)。
|
|
|
|
浏览器只传 assistant_id;真 key 在这里从 model_resources 取出注入。
|
|
助手按 capability binding 引用资源;取不到则回退该能力默认资源,再回退 .env。
|
|
"""
|
|
|
|
import config
|
|
from db.models import Assistant, AssistantModelBinding, ModelResource
|
|
from models import AssistantConfig
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
|
|
async def _resource_for(
|
|
session: AsyncSession,
|
|
assistant_id: str,
|
|
capability: str,
|
|
) -> ModelResource | None:
|
|
binding = await session.get(AssistantModelBinding, (assistant_id, capability))
|
|
resource_id = binding.model_resource_id if binding else None
|
|
resource = await session.get(ModelResource, resource_id) if resource_id else None
|
|
if resource and resource.capability != capability:
|
|
resource = None
|
|
if resource is None:
|
|
resource = (
|
|
await session.execute(
|
|
select(ModelResource)
|
|
.where(ModelResource.capability == capability, ModelResource.enabled.is_(True))
|
|
.order_by(ModelResource.is_default.desc(), ModelResource.id.asc())
|
|
.limit(1)
|
|
)
|
|
).scalar_one_or_none()
|
|
return resource
|
|
|
|
|
|
def _value(resource: ModelResource | None, key: str, default):
|
|
if not resource:
|
|
return default
|
|
value = (resource.values or {}).get(key, default)
|
|
return default if value is None else value
|
|
|
|
|
|
def _secret(resource: ModelResource | None, key: str, default: str) -> str:
|
|
if not resource:
|
|
return default
|
|
return str((resource.secrets or {}).get(key) or default)
|
|
|
|
|
|
async def resolve_runtime_config(
|
|
session: AsyncSession, assistant_id: str
|
|
) -> AssistantConfig:
|
|
"""加载助手 + 解析模型资源,产出可直接交给管线的运行时配置(含真 key)。"""
|
|
assistant = await session.get(Assistant, assistant_id)
|
|
if assistant is None:
|
|
raise ValueError(f"助手不存在: {assistant_id}")
|
|
|
|
llm_resource = await _resource_for(session, assistant.id, "LLM")
|
|
stt_resource = await _resource_for(session, assistant.id, "ASR")
|
|
tts_resource = await _resource_for(session, assistant.id, "TTS")
|
|
realtime_resource = await _resource_for(session, assistant.id, "Realtime")
|
|
|
|
return AssistantConfig(
|
|
name=assistant.name,
|
|
type=assistant.type,
|
|
greeting=assistant.greeting,
|
|
# prompt 现在是真列;外部类型由其平台编排,这里给个兜底
|
|
prompt=assistant.prompt or "你是一个有帮助的助手。",
|
|
runtimeMode=assistant.runtime_mode, # type: ignore[arg-type]
|
|
enableInterrupt=assistant.enable_interrupt,
|
|
# workflow 图:仅 workflow 类型非空,引擎据此启用图驱动对话
|
|
graph=(assistant.graph or {}) if assistant.type == "workflow" else {},
|
|
# 外部托管类型连接信息(DB 存真 key,直接注入)
|
|
fastgpt_api_url=assistant.api_url,
|
|
fastgpt_api_key=assistant.api_key,
|
|
fastgpt_app_id=assistant.app_id,
|
|
# 模型/音色:模型资源中的配置优先
|
|
model=str(_value(llm_resource, "modelId", "")),
|
|
asr=str(_value(stt_resource, "modelId", "")),
|
|
tts_model=str(_value(tts_resource, "modelId", "")),
|
|
voice=str(_value(tts_resource, "voice", "")),
|
|
stt_language=str(_value(stt_resource, "language", "")),
|
|
tts_speed=float(_value(tts_resource, "speed", 1.0)),
|
|
llm_interface_type=(llm_resource.interface_type if llm_resource else "openai-llm"),
|
|
stt_interface_type=(stt_resource.interface_type if stt_resource else "openai-asr"),
|
|
tts_interface_type=(tts_resource.interface_type if tts_resource else "openai-tts"),
|
|
realtimeModel=str(_value(realtime_resource, "modelId", "")),
|
|
llm_values=(llm_resource.values or {}) if llm_resource else {},
|
|
llm_secrets=(llm_resource.secrets or {}) if llm_resource else {},
|
|
stt_values=(stt_resource.values or {}) if stt_resource else {},
|
|
stt_secrets=(stt_resource.secrets or {}) if stt_resource else {},
|
|
tts_values=(tts_resource.values or {}) if tts_resource else {},
|
|
tts_secrets=(tts_resource.secrets or {}) if tts_resource else {},
|
|
realtime_interface_type=(
|
|
realtime_resource.interface_type if realtime_resource else ""
|
|
),
|
|
realtime_values=(realtime_resource.values or {}) if realtime_resource else {},
|
|
realtime_secrets=(realtime_resource.secrets or {}) if realtime_resource else {},
|
|
# 运行时连接信息(真 key + url):模型资源优先,否则 .env 兜底
|
|
llm_api_key=_secret(llm_resource, "apiKey", config.LLM_API_KEY),
|
|
llm_base_url=str(_value(llm_resource, "apiUrl", config.LLM_BASE_URL)),
|
|
stt_api_key=_secret(stt_resource, "apiKey", config.STT_API_KEY),
|
|
stt_base_url=str(_value(stt_resource, "apiUrl", config.STT_BASE_URL)),
|
|
tts_api_key=_secret(tts_resource, "apiKey", config.TTS_API_KEY),
|
|
tts_base_url=str(_value(tts_resource, "apiUrl", config.TTS_BASE_URL)),
|
|
realtime_api_key=_secret(realtime_resource, "apiKey", ""),
|
|
realtime_base_url=str(_value(realtime_resource, "apiUrl", "")),
|
|
)
|