feat: organize tools and enable qwen realtime calls
This commit is contained in:
@@ -1,56 +1,45 @@
|
||||
"""Shared contracts for platform-owned conversation system tools."""
|
||||
"""Contracts and adapters for platform-owned built-in conversation tools."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterable, Mapping
|
||||
from typing import Any
|
||||
from typing import Any, Mapping
|
||||
|
||||
from models import RuntimeTool
|
||||
from services.state_expressions import validate_update_rules
|
||||
|
||||
|
||||
SYSTEM_TOOL_SPECS: dict[str, dict[str, str]] = {
|
||||
"end_conversation": {
|
||||
"id": "tool_end_call_default",
|
||||
"name": "结束对话",
|
||||
"function_name": "end_conversation",
|
||||
"description": (
|
||||
"礼貌地结束本次对话。当用户明确告别、表示任务已完成"
|
||||
"或要求挂断时调用。"
|
||||
),
|
||||
"description": "礼貌地结束本次对话。",
|
||||
},
|
||||
"update_state": {
|
||||
"id": "tool_update_state_default",
|
||||
"name": "更新状态",
|
||||
"function_name": "update_state",
|
||||
"description": (
|
||||
"静默更新本次对话中已经声明并明确授权的动态变量。"
|
||||
"只提交本轮获得或确认的信息,更新后继续当前回答。"
|
||||
),
|
||||
"description": "静默更新已经声明并明确授权的会话状态。",
|
||||
},
|
||||
"skip_turn": {
|
||||
"id": "tool_skip_turn_default",
|
||||
"name": "跳过本轮",
|
||||
"function_name": "skip_turn",
|
||||
"description": (
|
||||
"跳过当前轮次,不生成任何语音回复。"
|
||||
"仅当用户明确要求稍等、话还没说完,或输入可确认只是噪音时调用。"
|
||||
),
|
||||
"description": "跳过当前轮次,不生成语音回复。",
|
||||
},
|
||||
"request_human_handoff": {
|
||||
"id": "tool_request_human_handoff_default",
|
||||
"name": "转接人工",
|
||||
"function_name": "request_human_handoff",
|
||||
"description": (
|
||||
"提交人工接管请求。当用户明确要求人工服务、投诉升级或 AI 无法"
|
||||
"解决时调用。该工具只提交请求,不代表人工已经接通;调用后继续"
|
||||
"回复用户并说明正在等待人工响应。"
|
||||
),
|
||||
"description": "提交人工接管请求,并继续告知用户当前进展。",
|
||||
},
|
||||
}
|
||||
|
||||
SYSTEM_TOOL_KINDS = frozenset(SYSTEM_TOOL_SPECS)
|
||||
RESERVED_TOOL_NAMES = frozenset(
|
||||
spec["function_name"] for spec in SYSTEM_TOOL_SPECS.values()
|
||||
)
|
||||
|
||||
|
||||
def system_tool_kind(definition: Mapping[str, Any] | None) -> str | None:
|
||||
"""Return the supported platform behavior declared by a System resource."""
|
||||
"""Compatibility helper for old fixtures and the one-time migration."""
|
||||
|
||||
config = (definition or {}).get("config")
|
||||
if not isinstance(config, Mapping):
|
||||
return None
|
||||
@@ -58,28 +47,56 @@ def system_tool_kind(definition: Mapping[str, Any] | None) -> str | None:
|
||||
return kind if kind in SYSTEM_TOOL_KINDS else None
|
||||
|
||||
|
||||
def runtime_system_tools(
|
||||
built_in_tools: Mapping[str, Any] | None,
|
||||
) -> list[RuntimeTool]:
|
||||
"""Adapt immutable built-in configs to existing brain tool builders."""
|
||||
|
||||
result: list[RuntimeTool] = []
|
||||
aliases = {
|
||||
"endConversation": "end_conversation",
|
||||
"updateState": "update_state",
|
||||
"skipTurn": "skip_turn",
|
||||
"requestHumanHandoff": "request_human_handoff",
|
||||
}
|
||||
config_aliases = {
|
||||
"messageType": "message_type",
|
||||
"customMessage": "custom_message",
|
||||
"captureReason": "capture_reason",
|
||||
"allowEndInterruption": "allow_end_interruption",
|
||||
}
|
||||
for raw_kind, config in (built_in_tools or {}).items():
|
||||
kind = aliases.get(str(raw_kind), str(raw_kind))
|
||||
if kind not in SYSTEM_TOOL_SPECS or not isinstance(config, Mapping):
|
||||
continue
|
||||
spec = SYSTEM_TOOL_SPECS[kind]
|
||||
normalized_config = dict(config)
|
||||
for camel, snake in config_aliases.items():
|
||||
if camel in normalized_config and snake not in normalized_config:
|
||||
normalized_config[snake] = normalized_config.pop(camel)
|
||||
result.append(
|
||||
RuntimeTool(
|
||||
id=f"builtin_{kind}",
|
||||
name=spec["name"],
|
||||
function_name=spec["function_name"],
|
||||
type="system",
|
||||
description=str(
|
||||
normalized_config.get("description") or spec["description"]
|
||||
),
|
||||
definition={
|
||||
"type": "system",
|
||||
"config": {"kind": kind, **normalized_config},
|
||||
},
|
||||
)
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
def state_update_properties(
|
||||
definitions: Mapping[str, Mapping[str, Any]] | None,
|
||||
*,
|
||||
allowed_names: Iterable[str] | None = None,
|
||||
rules: list[Mapping[str, Any]] | None = None,
|
||||
) -> dict[str, dict[str, Any]]:
|
||||
"""Build an explicit LLM schema for writable declared variables."""
|
||||
definitions = definitions or {}
|
||||
names = (
|
||||
list(dict.fromkeys(str(name) for name in allowed_names))
|
||||
if allowed_names is not None
|
||||
else list(definitions)
|
||||
)
|
||||
properties: dict[str, dict[str, Any]] = {}
|
||||
for name in names:
|
||||
definition = definitions.get(name)
|
||||
if not isinstance(definition, Mapping):
|
||||
continue
|
||||
variable_type = str(definition.get("type") or "string")
|
||||
if variable_type not in {"string", "number", "boolean"}:
|
||||
continue
|
||||
properties[name] = {
|
||||
"type": variable_type,
|
||||
"description": f"更新动态变量 {name}。",
|
||||
}
|
||||
return properties
|
||||
"""Build the LLM schema from explicit v4 expression rules."""
|
||||
|
||||
return validate_update_rules(rules or [], definitions, allow_llm=True)
|
||||
|
||||
Reference in New Issue
Block a user