feat: organize tools and enable qwen realtime calls
This commit is contained in:
@@ -5,9 +5,11 @@ import uuid
|
||||
from db.models import (
|
||||
Assistant,
|
||||
AssistantModelBinding,
|
||||
AssistantToolBinding,
|
||||
InterfaceDefinition,
|
||||
KnowledgeBase,
|
||||
ModelResource,
|
||||
Tool,
|
||||
)
|
||||
from db.session import get_session
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
@@ -51,6 +53,7 @@ def _definition_dict(row: InterfaceDefinition) -> dict:
|
||||
"name": row.name,
|
||||
"capability": row.capability,
|
||||
"fields": (row.field_schema or {}).get("fields", []),
|
||||
"features": (row.field_schema or {}).get("features", {}),
|
||||
}
|
||||
|
||||
|
||||
@@ -137,6 +140,78 @@ async def _clear_incompatible_references(
|
||||
)
|
||||
|
||||
|
||||
async def _ensure_realtime_prompt_tools_remain_supported(
|
||||
session: AsyncSession,
|
||||
resource: ModelResource,
|
||||
definition: InterfaceDefinition,
|
||||
) -> None:
|
||||
"""Reject provider changes that would silently disable bound Prompt tools."""
|
||||
|
||||
if resource.capability != "Realtime":
|
||||
return
|
||||
features = {}
|
||||
if definition.capability == "Realtime":
|
||||
features = (
|
||||
((definition.field_schema or {}).get("features") or {}).get(
|
||||
"realtimePromptTools"
|
||||
)
|
||||
or {}
|
||||
)
|
||||
supported_external = set(features.get("externalTypes") or [])
|
||||
supported_built_ins = set(features.get("builtIns") or [])
|
||||
assistants = (
|
||||
await session.execute(
|
||||
select(Assistant)
|
||||
.join(
|
||||
AssistantModelBinding,
|
||||
AssistantModelBinding.assistant_id == Assistant.id,
|
||||
)
|
||||
.where(
|
||||
AssistantModelBinding.model_resource_id == resource.id,
|
||||
AssistantModelBinding.capability == "Realtime",
|
||||
Assistant.type == "prompt",
|
||||
Assistant.runtime_mode == "realtime",
|
||||
)
|
||||
)
|
||||
).scalars().all()
|
||||
aliases = {
|
||||
"end_conversation": "endConversation",
|
||||
"update_state": "updateState",
|
||||
"skip_turn": "skipTurn",
|
||||
"request_human_handoff": "requestHumanHandoff",
|
||||
}
|
||||
for assistant in assistants:
|
||||
requested_built_ins = {
|
||||
aliases.get(str(name), str(name))
|
||||
for name, config in (assistant.built_in_tools or {}).items()
|
||||
if config is not None
|
||||
}
|
||||
if requested_built_ins - supported_built_ins:
|
||||
raise HTTPException(
|
||||
409,
|
||||
f"模型资源被 Prompt Realtime 助手 {assistant.name} 使用,"
|
||||
"新接口不支持其内建工具",
|
||||
)
|
||||
tool_types = set(
|
||||
(
|
||||
await session.execute(
|
||||
select(Tool.type)
|
||||
.join(
|
||||
AssistantToolBinding,
|
||||
AssistantToolBinding.tool_id == Tool.id,
|
||||
)
|
||||
.where(AssistantToolBinding.assistant_id == assistant.id)
|
||||
)
|
||||
).scalars().all()
|
||||
)
|
||||
if tool_types - supported_external:
|
||||
raise HTTPException(
|
||||
409,
|
||||
f"模型资源被 Prompt Realtime 助手 {assistant.name} 使用,"
|
||||
"新接口不支持其外部工具",
|
||||
)
|
||||
|
||||
|
||||
@router.get("/interface-definitions", response_model=list[InterfaceDefinitionOut])
|
||||
async def list_interface_definitions(
|
||||
capability: str | None = Query(default=None),
|
||||
@@ -252,6 +327,7 @@ async def update_model_resource(
|
||||
if not row:
|
||||
raise HTTPException(404, "模型资源不存在")
|
||||
definition, secrets = await _validate(session, body, row.secrets or {})
|
||||
await _ensure_realtime_prompt_tools_remain_supported(session, row, definition)
|
||||
await _clear_incompatible_references(session, row, definition.capability)
|
||||
row.name = body.name
|
||||
row.capability = definition.capability
|
||||
|
||||
Reference in New Issue
Block a user