66 lines
2.3 KiB
Python
66 lines
2.3 KiB
Python
"""Capability gates for Prompt tools in speech-to-speech runtimes."""
|
||||
|
|
|
|||
|
|
from __future__ import annotations
|
|||
|
|
|
|||
|
|
from collections.abc import Mapping
|
|||
|
|
|
|||
|
|
from services.system_tools import RESERVED_TOOL_NAMES
|
|||
|
|
|
|||
|
|
|
|||
|
|
QWEN_PROMPT_TOOL_FEATURES = {
|
|||
|
|
"externalTypes": ["http", "mcp", "client"],
|
|||
|
|
"builtIns": [
|
|||
|
|
"endConversation",
|
|||
|
|
"updateState",
|
|||
|
|
"requestHumanHandoff",
|
|||
|
|
],
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
def realtime_prompt_tool_features(interface_type: str) -> dict[str, list[str]]:
|
|||
|
|
"""Return the server-trusted runtime capabilities for one provider."""
|
|||
|
|
|
|||
|
|
if interface_type == "qwen-audio-realtime":
|
|||
|
|
return {
|
|||
|
|
key: list(values) for key, values in QWEN_PROMPT_TOOL_FEATURES.items()
|
|||
|
|
}
|
|||
|
|
return {"externalTypes": [], "builtIns": []}
|
|||
|
|
|
|||
|
|
|
|||
|
|
def validate_runtime_prompt_tools(
|
|||
|
|
*,
|
|||
|
|
interface_type: str,
|
|||
|
|
external_types: set[str],
|
|||
|
|
built_in_tools: Mapping[str, object] | None,
|
|||
|
|
external_function_names: set[str] | None = None,
|
|||
|
|
) -> None:
|
|||
|
|
"""Reject stale or inline runtime configurations before opening a socket."""
|
|||
|
|
|
|||
|
|
features = realtime_prompt_tool_features(interface_type)
|
|||
|
|
unsupported_external = external_types - set(features["externalTypes"])
|
|||
|
|
reserved_external = set(external_function_names or set()) & RESERVED_TOOL_NAMES
|
|||
|
|
aliases = {
|
|||
|
|
"end_conversation": "endConversation",
|
|||
|
|
"update_state": "updateState",
|
|||
|
|
"skip_turn": "skipTurn",
|
|||
|
|
"request_human_handoff": "requestHumanHandoff",
|
|||
|
|
}
|
|||
|
|
requested_built_ins = {
|
|||
|
|
aliases.get(str(name), str(name))
|
|||
|
|
for name, config in (built_in_tools or {}).items()
|
|||
|
|
if config is not None
|
|||
|
|
}
|
|||
|
|
unsupported_built_ins = requested_built_ins - set(features["builtIns"])
|
|||
|
|
if unsupported_external or unsupported_built_ins or reserved_external:
|
|||
|
|
details = []
|
|||
|
|
if unsupported_external:
|
|||
|
|
details.append("外部工具:" + ",".join(sorted(unsupported_external)))
|
|||
|
|
if unsupported_built_ins:
|
|||
|
|
details.append("内建工具:" + ",".join(sorted(unsupported_built_ins)))
|
|||
|
|
if reserved_external:
|
|||
|
|
details.append("外部工具使用平台保留名:" + ",".join(sorted(reserved_external)))
|
|||
|
|
raise ValueError(
|
|||
|
|
f"Realtime 接口 {interface_type or 'unknown'} 不支持 "
|
|||
|
|
+ ";".join(details)
|
|||
|
|
)
|