feat(tools): 为工具添加执行状态提示并优化工具使用指引

This commit is contained in:
zihanjian
2026-02-04 17:52:27 +08:00
parent f0339f79ac
commit 9fae48d3a2
5 changed files with 48 additions and 2 deletions

View File

@@ -105,12 +105,30 @@ def handle_chitchat(ctx: 'MessageContext', match: Optional[Match]) -> bool:
# ── 构建系统提示 ──────────────────────────────────────
persona_text = getattr(ctx, 'persona', None)
system_prompt_override = None
# 工具使用指引:告诉 LLM 何时该用工具
tool_guidance = ""
if tools:
tool_guidance = (
"\n\n## 工具使用指引\n"
"你可以调用工具来辅助回答,以下是决策原则:\n"
"- 用户询问需要最新信息、实时数据、或你不确定的事实 → 调用 web_search\n"
"- 用户想设置/查看/删除提醒 → 调用 reminder_create / reminder_list / reminder_delete\n"
"- 用户提到之前聊过的内容、或你需要回顾更早的对话 → 调用 lookup_chat_history\n"
"- 日常闲聊、观点讨论、情感交流 → 直接回复,不需要调用任何工具\n"
"你可以在一次对话中多次调用工具(例如先搜索再设提醒),每次调用的结果会反馈给你继续推理。"
)
if persona_text:
try:
system_prompt_override = build_persona_system_prompt(chat_model, persona_text)
base_prompt = build_persona_system_prompt(chat_model, persona_text)
system_prompt_override = base_prompt + tool_guidance if base_prompt else tool_guidance or None
except Exception as persona_exc:
if ctx.logger:
ctx.logger.error(f"构建人设系统提示失败: {persona_exc}", exc_info=True)
system_prompt_override = tool_guidance or None
elif tool_guidance:
system_prompt_override = tool_guidance
# ── 调用 LLMAgent 循环在 _execute_with_tools 中)──
try:

View File

@@ -20,6 +20,7 @@ class Tool:
description: str
parameters: dict # JSON Schema
handler: Callable[..., str] = None # (ctx, **kwargs) -> str
status_text: str = "" # 执行前发给用户的状态提示,空则不发
def to_openai_schema(self) -> dict:
return {
@@ -54,9 +55,30 @@ class ToolRegistry:
return [t.to_openai_schema() for t in self._tools.values()]
def create_handler(self, ctx: Any) -> Callable[[str, dict], str]:
"""创建一个绑定了消息上下文的 tool_handler 函数。"""
"""创建一个绑定了消息上下文的 tool_handler 函数。
执行工具前,如果该工具配置了 status_text会先给用户发一条状态提示
让用户知道"机器人在干什么"(类似 OpenClaw/OpenCode 的中间过程输出)。
"""
registry = self._tools
def _send_status(tool: 'Tool', arguments: dict) -> None:
"""发送工具执行状态消息给用户。"""
if not tool.status_text:
return
try:
# 对搜索类工具,把查询关键词带上
status = tool.status_text
if tool.name == "web_search" and arguments.get("query"):
status = f"{status}{arguments['query']}"
elif tool.name == "lookup_chat_history" and arguments.get("keywords"):
kw_str = "".join(str(k) for k in arguments["keywords"][:3])
status = f"{status}{kw_str}"
ctx.send_text(status, record_message=False)
except Exception:
pass # 状态提示失败不影响工具执行
def handler(tool_name: str, arguments: dict) -> str:
tool = registry.get(tool_name)
if not tool:
@@ -64,6 +86,9 @@ class ToolRegistry:
{"error": f"Unknown tool: {tool_name}"},
ensure_ascii=False,
)
_send_status(tool, arguments)
try:
result = tool.handler(ctx, **arguments)
if not isinstance(result, str):

View File

@@ -142,6 +142,7 @@ def _handle_lookup_chat_history(ctx, mode: str = "", keywords: list = None,
tool_registry.register(Tool(
name="lookup_chat_history",
status_text="正在翻阅聊天记录: ",
description=(
"查询聊天历史记录。你当前只能看到最近的消息,调用此工具可以回溯更早的上下文。"
"支持三种模式:\n"

View File

@@ -106,6 +106,7 @@ tool_registry.register(Tool(
"创建提醒。支持 once(一次性)、daily(每日)、weekly(每周) 三种类型。"
"当前时间已在对话上下文中提供,请据此计算目标时间。"
),
status_text="正在设置提醒...",
parameters={
"type": "object",
"properties": {

View File

@@ -42,6 +42,7 @@ tool_registry.register(Tool(
"在网络上搜索信息。用于回答需要最新数据、实时信息或你不确定的事实性问题。"
"deep_research 仅在问题非常复杂、需要深度研究时才开启。"
),
status_text="正在联网搜索: ",
parameters={
"type": "object",
"properties": {