Ch14 Agent原理修订于 二〇二六年七月六日

概念-Hook机制

一句话理解

Hook 机制(Hook Mechanism)是一种早期的”伪 Function Calling”实现:模型输出特定标记时触发外部函数,如 [SEARCH:xxx] → 执行搜索 → 结果插回上下文。在 2023 年 LLM 还不支持原生 Tool Use 的年代,开发者通过正则匹配模型输出中的特殊标记,来模拟”模型调用工具”的行为。这是上下文管理技术中最”hack”、最不稳定、但也最有创造力的一种。

类比:在智能手机出现之前,有人用诺基亚的功能机 + 外挂键盘 + 第三方软件,硬生生模拟出了”智能手机”的体验。Hook 机制就是这种”外挂”——用正则匹配模拟 Function Calling。

核心机制

Hook 工作流程

┌──────────────────────────────────────────────────────┐
│                  Hook 机制工作流程                      │
│                                                      │
│  1. System Prompt 中定义 Hook 标记语法                  │
│     "当你需要搜索时,输出 [SEARCH: 关键词]"               │
│           │                                          │
│           ▼                                          │
│  2. 模型生成带标记的输出                                │
│     "让我查一下... [SEARCH: 量子计算 最新进展]"           │
│           │                                          │
│           ▼                                          │
│  3. 正则匹配 Hook 标记                                 │
│     re.findall(r'\[SEARCH: (.*?)\]', response)       │
│           │                                          │
│           ▼                                          │
│  4. 执行对应的外部函数                                  │
│     search_results = google_search("量子计算 最新进展")  │
│           │                                          │
│           ▼                                          │
│  5. 结果注入上下文,继续对话                             │
│     messages.append({"role": "user", "content":       │
│       "搜索结果: ..."})                                │
│           │                                          │
│           ▼                                          │
│  6. 模型基于结果继续生成                                │
│     重复步骤 2-5,直到模型输出不含 Hook 标记             │
└──────────────────────────────────────────────────────┘

代码示例:正则匹配实现 Hook

import re
from typing import Callable

# 定义 Hook 处理器
HOOK_PATTERNS = {
    r'\[SEARCH:\s*(.*?)\]': "search",     # 搜索 Hook
    r'\[CALC:\s*(.*?)\]': "calculate",    # 计算 Hook
    r'\[DB_QUERY:\s*(.*?)\]': "db_query", # 数据库查询 Hook
    r'\[FETCH_URL:\s*(.*?)\]': "fetch_url", # URL 抓取 Hook
}

def search(query: str) -> str:
    """执行搜索"""
    results = google_search(query)
    return format_search_results(results)

def calculate(expression: str) -> str:
    """执行计算"""
    try:
        result = eval(expression)
        return f"计算结果: {result}"
    except Exception as e:
        return f"计算错误: {e}"

def db_query(sql: str) -> str:
    """执行数据库查询"""
    results = database.execute(sql)
    return format_db_results(results)

def fetch_url(url: str) -> str:
    """抓取 URL 内容"""
    content = requests.get(url).text[:1000]  # 截取前1000字符
    return f"URL内容摘要: {content[:500]}..."

# Hook 处理器映射
HOOK_HANDLERS: dict[str, Callable] = {
    "search": search,
    "calculate": calculate,
    "db_query": db_query,
    "fetch_url": fetch_url,
}

# Hook 系统提示词
HOOK_SYSTEM_PROMPT = """你是一个可以使用外部工具的助手。当你需要使用工具时,请在你的回复中插入以下标记:

- [SEARCH: 搜索关键词] — 搜索互联网
- [CALC: 数学表达式] — 执行数学计算
- [DB_QUERY: SQL查询] — 查询数据库
- [FETCH_URL: 网址] — 获取网页内容

工具执行结果会自动追加到你的回复中。你可以在一轮中使用多个工具。"""

def detect_and_execute_hooks(text: str) -> tuple[str, list[str]]:
    """检测文本中的 Hook 标记并执行对应操作"""
    results = []

    for pattern, hook_type in HOOK_PATTERNS.items():
        matches = re.findall(pattern, text, re.IGNORECASE)
        for match in matches:
            handler = HOOK_HANDLERS.get(hook_type)
            if handler:
                result = handler(match.strip())
                results.append(f"[{hook_type} 结果: {match}]\n{result}")

    # 移除 Hook 标记,保留其他文本
    cleaned = text
    for pattern in HOOK_PATTERNS:
        cleaned = re.sub(pattern, '', cleaned)

    return cleaned, results

def hook_loop(user_query: str, max_iterations: int = 5) -> str:
    """Hook 机制的主循环"""
    messages = [
        {"role": "system", "content": HOOK_SYSTEM_PROMPT},
        {"role": "user", "content": user_query}
    ]

    for iteration in range(max_iterations):
        response = llm_call(messages)

        # 检测 Hook 标记
        cleaned_text, hook_results = detect_and_execute_hooks(response)

        if not hook_results:
            # 没有 Hook 标记,说明模型给出了最终回答
            return response

        # 有 Hook 标记,执行并将结果注入
        messages.append({"role": "assistant", "content": response})
        messages.append({"role": "user", "content": f"工具执行结果:\n" + "\n".join(hook_results)})

    return "达到最大迭代次数"

# 使用
result = hook_loop("帮我搜索量子计算的最新进展,并计算 2^10 的值")

Hook 机制的局限性

局限说明严重程度
依赖模型配合模型必须严格按照格式输出标记,但 LLM 输出天然不稳定高
标记格式歧义如果正常内容中包含 [SEARCH: ...] 的文字,会被误触发中
多轮状态管理上下文越来越长,模型可能忘记之前的 Hook 结果中
无法传递复杂参数正则只能匹配简单文本,复杂参数(如 JSON)难以处理高
错误处理困难工具执行失败时,模型可能不理解错误信息并继续出错中
调试困难Hook 的触发和结果注入都是隐式的,难以追踪问题中
Token 浪费标记语法本身占用 Token,工具结果也占用 Token低
安全风险模型可能被诱导输出恶意标记,触发危险操作高

2026 年:被 Function Calling 完全取代

Hook 机制的所有功能,都已被原生 Function Calling / Tool Use 完全取代,且原生方案在各方面都更优:

维度Hook 机制Function Calling
触发方式正则匹配模型输出文本模型输出结构化 tool_call
可靠性低(依赖文本格式)高(结构化输出,schema 约束)
参数传递简单文本(正则提取)结构化 JSON(schema 定义)
错误处理手动处理框架自动处理
并发调用不支持原生支持并行 tool calls
流式支持难以实现原生支持 streaming tool calls
安全性低(任意文本可触发)高(需显式定义工具)
开发成本高(手动实现所有逻辑)低(框架/API 内置)

Hook 机制的历史价值

虽然 Hook 机制已经过时,但它在 AI 应用开发史上的价值不可忽视:

  1. 概念验证(Proof of Concept):Hook 机制证明了”模型可以主动使用外部工具”这个想法是可行的,为 Function Calling 的设计提供了经验基础
  2. 思维启发:Hook 机制让开发者开始思考”模型应该做什么 vs 系统应该做什么”的边界问题
  3. 社区贡献:LangChain 的 Agent 模块、AutoGPT 等早期 Agent 框架,底层都是 Hook 机制的变体
  4. 遗留影响:一些低延迟场景(如嵌入式设备)仍在使用简化的 Hook 机制,因为原生 Function Calling 需要更强大的硬件支持

相关笔记

来源

关联10

知识图谱

局部图谱 · 点节点跳转