[控场AI]
· 7 分钟阅读· 3,844 字

LLM工具误选实战:用pre_gateway_dispatch钩子纠正语音备忘技能

LLM工具误选实战:用pre_gateway_dispatch钩子纠正语音备忘技能

通过网关层钩子拦截并注入硬编码指令,彻底解决Qwen模型将语音备忘误判为内置memory工具的问题。

本文记录了一次真实的AI Agent调试过程:在基于Hermes Agent与Qwen 3.6-35B模型的语音备忘系统中,以韩语"메모"开头的语音指令始终被模型路由至内置`memory`工具,而非专用`voice-memo`技能,技能激活率为0/3。根因是网关仅向模型传递纯文本,缺乏语音来源标记,导致模型无法区分随口提及与正式命令,只能凭字面语义猜测。修改激活条件与优化Whisper提示词均告失效,作者转而编写`pre_gateway_dispatch`钩子,在消息进入模型前进行轻量预转写与关键词检测,匹配成功则注入硬编码约束指令,明确禁止调用memory工具。修复后技能激活率达3/3、memory工具零调用。核心结论是:当提示工程反复失效时,在数据流层面施加强约束往往比继续调教模型更可靠。

在构建语音驱动的自动化系统时,一个看似简单的问题常常让开发者抓狂:模型明明收到了正确的指令,却偏偏调用了错误的工具。这篇来自真实工程实践的调试记录,展示了如何在Hermes Agent上解决语音备忘(voice-memo)技能被误判为内置记忆工具的问题——核心手段是绕过提示工程,直接在网关层拦截并改写消息。

问题场景:转写成功,技能却从不触发

整套系统运行在NVIDIA DGX Spark上,搭载Hermes Agent(v0.20.6)与Qwen 3.6-35B模型。预期流程是:用户通过Telegram发送语音备忘,由本地Whisper服务转写,再由Agent将文本整理成结构化文档,保存到/sandbox/notes/memos/目录。

问题出在技能激活环节。第二轮测试中,尽管语音转写全部成功,voice-memo技能的激活率却是0/3。转写文本正确地以韩语单词메모(意为"备忘")开头,但Qwen模型始终选择默认的memory工具来存储信息,而不是调用专门的voice-memo技能。结果所有笔记都被写进了通用的MEMORY.md文件,根本没有被加工成目标目录下的结构化Markdown文档。

Hermes Agent语音备忘技能误判问题调试记录

两次失败的尝试

作者首先尝试了最直觉的办法——修改技能激活条件,让转写文本以메모开头时触发。结果失败了:模型依旧优先选择memory工具,无视了激活条件。

第二个尝试针对转写质量,给Whisper STT引擎增加了技术术语提示词以减少转写错误。这一步部分有效,在特定测试用例中把错误从6个降到了3个。但这只是提升了输入质量,并没有触及工具选择的核心矛盾。

两次尝试的共同启示是:当问题根源在模型的语义理解层面时,调优输入或微调条件往往治标不治本。

根因:模型层面的语义误解

真正的病灶是模型层面的语义混淆。当Agent收到以메모开头的消息时,Qwen模型把意图理解为"记住这件事",于是调用了内置的memory工具。

关键在于,Hermes v0.20.6的网关只是把转写后的文本作为一个普通的引号字符串传给模型,没有附带任何语音标记或来源信息。这意味着模型无从区分两种情况:一种是对话中随口提到"备忘"这个词,另一种是触发voice-memo技能的正式命令。缺少上下文信号,模型只能凭字面语义猜测,而猜测的结果恰好是错的。

这类问题在工具调用(tool calling)场景中相当典型:功能相近的工具之间,模型的选择高度依赖输入信号的明确性,而不是开发者的"善意期望"。

工具调用(Tool Calling / Function Calling)是当前大语言模型Agent架构的核心机制:模型在生成回复时,可以输出一段结构化的"调用意图",由框架层实际执行对应函数后再将结果返回给模型。这一机制的副作用是工具选择高度依赖模型对输入语义的理解,而非硬编码的规则路由。当系统中存在语义相近的工具时——例如本文中"记录一条备忘"与"调用voice-memo技能"在字面含义上几乎重叠——模型会在推理阶段根据上下文概率分布"猜"出最合适的工具。如果输入信号不够显著,模型往往选择它在预训练语料中见过更多次的通用工具(如memory),而非针对特定场景设计的专有技能。这种选择偏差本质上是一个概率问题,无法单靠调整激活条件或优化上游输入来彻底消除。

解决方案:pre_gateway_dispatch钩子

作者的做法是编写一个自定义Hermes插件,使用pre_gateway_dispatch钩子。这个钩子会在消息到达模型之前进行拦截:

  • 对于音频消息,先做一次轻量的预转写(约0.7秒),检查首词是否为메모;
  • 对于文本消息,检查是否以메모:开头。

一旦匹配成功,插件就改写消息,注入一段硬编码指令,明确告诉模型:这是作者的备忘,不要使用memory工具,而要调用名为voice-memo的技能并严格执行。核心逻辑如下:

SPOKEN = re.compile(r"^\W*메모(?=[\s,.:!?~…]|$)")
TYPED = re.compile(r"^\s*메모\s*[::]")
INSTRUCTION = ("[voice-memo] This message is the author's memo (it starts with the word 메모). "
               "Do not use the memory tool and do not continue earlier topics. "
               "Call skill_view with name \"voice-memo\" and follow it exactly...")

def on_dispatch(event=None, **_):
    try:
        kind = getattr(getattr(event, "message_type", None), "value", "")
        text = (getattr(event, "text", "") or "").strip()
        if kind == "text" and TYPED.match(text):
            return {"action": "rewrite", "text": f"{INSTRUCTION}\n\n{text}"}
        media = list(getattr(event, "media_urls", None) or [])
        if kind in ("voice", "audio") and media and SPOKEN.match(_transcribe(media[0]).strip()):
            return {"action": "rewrite", "text": f"{text}\n\n{INSTRUCTION}" if text else INSTRUCTION}
    except Exception as e:
        logger.warning("voice_memo: 판단 실패 %s", e)
    return None

钩子的注册也很简洁:

def register(ctx):
    ctx.register_hook("pre_gateway_dispatch", on_dispatch)

值得关注的是异常处理设计——即便钩子判断失败,消息仍按原样放行,保证了对正常对话流程零干扰。这种"失败即降级"的工程防御是生产级插件的基本功。

钩子(Hook)机制是中间件与插件架构中的经典模式:框架在处理流程的关键节点预留"插槽",允许外部代码在不修改核心逻辑的前提下注入自定义行为。pre_gateway_dispatch 即"网关分发前"钩子,其触发时机位于消息进入大模型推理之前、完成来源校验之后,恰好处于可以安全改写消息内容的窗口期。相比在提示词(System Prompt)中添加软性指令,网关层的硬编码注入具有决定性优势:它是同步且确定的,不依赖模型对提示词的遵从程度。这也体现了"防御性工程"(Defensive Engineering)的思路——在数据流的物理路径上施加约束,而非依赖模型的"理解意愿"。类似的拦截机制在内容过滤、权限校验、请求改写等场景中被广泛采用,是生产级Agent系统的常见架构手段。

结果:3/3成功,memory工具零调用

第三轮测试中,修复完全奏效:文档保存成功率达到3/3,memory工具被调用了0次,所有笔记都正确进入目标目录并被整理成结构化文档。

从0/3到3/3的提升,验证了一个判断:当提示工程反复失效时,在数据流层面注入强约束往往比继续调教模型更可靠。

经验总结与遗留问题

作者提炼了两条可复用的经验:

  • 当LLM持续把某条命令误判为另一个工具时,不要单纯依赖提示词,而应使用预分发钩子注入明确约束;
  • 对于语音驱动的自动化,在网关层做一次轻量预转写,可以提供引导模型行为所需的关键上下文。

系统仍有未解决的问题。其一是中断处理:当Agent正忙时若有新语音消息到达(busy_input_mode: interrupt),当前轮次会被打断。其二是转写幻觉——Whisper在静默段末尾偶尔会凭空添加"Thank you"之类的内容。

这些遗留问题提醒我们,语音自动化链路上的每一环(STT、网关、模型、并发调度)都可能成为误差来源,端到端的稳定性需要在多个层面协同治理。

注:原文由作者的本地Gemma模型根据提交日志与实验笔记撰写,并由本地Qwen3.6模型对照核实,未经人工编辑。这一元信息本身也折射出本地LLM辅助工程记录的新实践。

#LLM工具调用#pre_gateway_dispatch#Hermes Agent#语音备忘自动化#Qwen模型#工具误选#Whisper转写#AI Agent插件
分享:

相关推荐