From 9fae48d3a237b8af0384be73323c62e9aab8477e Mon Sep 17 00:00:00 2001 From: zihanjian Date: Wed, 4 Feb 2026 17:52:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(tools):=20=E4=B8=BA=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=89=A7=E8=A1=8C=E7=8A=B6=E6=80=81=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E5=B9=B6=E4=BC=98=E5=8C=96=E5=B7=A5=E5=85=B7=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E6=8C=87=E5=BC=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- commands/handlers.py | 20 +++++++++++++++++++- tools/__init__.py | 27 ++++++++++++++++++++++++++- tools/history.py | 1 + tools/reminder.py | 1 + tools/web_search.py | 1 + 5 files changed, 48 insertions(+), 2 deletions(-) diff --git a/commands/handlers.py b/commands/handlers.py index 74ae750..559e1e1 100644 --- a/commands/handlers.py +++ b/commands/handlers.py @@ -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 # ── 调用 LLM(Agent 循环在 _execute_with_tools 中)── try: diff --git a/tools/__init__.py b/tools/__init__.py index 29c34bc..521d55d 100644 --- a/tools/__init__.py +++ b/tools/__init__.py @@ -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): diff --git a/tools/history.py b/tools/history.py index c9ad78a..d271325 100644 --- a/tools/history.py +++ b/tools/history.py @@ -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" diff --git a/tools/reminder.py b/tools/reminder.py index cae13b1..c7d7183 100644 --- a/tools/reminder.py +++ b/tools/reminder.py @@ -106,6 +106,7 @@ tool_registry.register(Tool( "创建提醒。支持 once(一次性)、daily(每日)、weekly(每周) 三种类型。" "当前时间已在对话上下文中提供,请据此计算目标时间。" ), + status_text="正在设置提醒...", parameters={ "type": "object", "properties": { diff --git a/tools/web_search.py b/tools/web_search.py index 384aa83..5b0f173 100644 --- a/tools/web_search.py +++ b/tools/web_search.py @@ -42,6 +42,7 @@ tool_registry.register(Tool( "在网络上搜索信息。用于回答需要最新数据、实时信息或你不确定的事实性问题。" "deep_research 仅在问题非常复杂、需要深度研究时才开启。" ), + status_text="正在联网搜索: ", parameters={ "type": "object", "properties": {