聊 Agent 绕不开 Function Calling,聊开源 Function Calling 模型绕不开 Nous Research 的 Hermes 系列。这篇文章帮你吃透 Hermes。


一、Hermes 是什么?

Hermes 是 AI 研究组织 Nous Research 推出的一系列开源 LLM,核心定位就是 Agent 能力——特别是函数调用(Function Calling)、工具使用(Tool Use)和指令遵循(Instruction Following)。

一句话概括:

Hermes = 开源社区最早系统性地做 Function Calling 微调的模型系列。

它的命名灵感来自希腊神话中的赫尔墨斯——众神的信使,桥梁与边界的穿越者。这也暗合了 Hermes 模型的使命:连接 LLM 与外部工具/API


二、Hermes 系列演进

版本基座模型核心改进发布时间
Hermes 1Llama 2 7B/13B首次引入函数调用微调数据2023 Q3
Hermes 2Llama 2 + Mistral改进函数调用格式,增强推理2023 Q4
Hermes 2 ProMistral 8x7B 等引入结构化 JSON 输出2024 Q1
Hermes 3Llama 3.1 8B/70B/405B长上下文 + 复杂多步工具调用 + 角色扮演2024 Q3

Hermes 3 的关键能力升级

  • 复杂多步 Function Calling:能在一个对话轮次中合理编排多个工具调用

  • 长上下文(128K+):适合处理长文档和长时间 Agent 任务

  • System Prompt 遵循度极高:比同规模通用模型更能按指令约束行为

  • 多语言支持:在中文、日文、法文等语言上的函数调用能力也明显优于同期的开源模型


三、Hermes 的 Function Calling 格式

这是 Hermes 最核心的技术贡献,也是面试中能拉开差距的知识点。

3.1 工具定义(Tool Definition)

使用 OpenAI 兼容的 JSON Schema 描述工具:

{
  "type": "function",
  "function": {
    "name": "get_weather",
    "description": "获取指定城市的当前天气",
    "parameters": {
      "type": "object",
      "properties": {
        "city": {
          "type": "string",
          "description": "城市名称,如 '北京'"
        },
        "unit": {
          "type": "string",
          "enum": ["celsius", "fahrenheit"],
          "description": "温度单位"
        }
      },
      "required": ["city"]
    }
  }
}

这些工具定义通过 system prompt 注入模型,模型被训练为理解工具描述语义生成符合参数约束的调用 JSON

3.2 调用输出格式

当模型决定调用工具时,它会输出一个严格的 JSON 块:

<tool_call>
{
  "name": "get_weather",
  "arguments": {
    "city": "北京",
    "unit": "celsius"
  }
}
</tool_call>

解析器从 <tool_call> 标签中提取 JSON,执行工具,然后将结果以特定格式回传:

<tool_response>
{
  "temperature": 22,
  "condition": "晴",
  "humidity": 45
}
</tool_response>

3.3 核心设计思想

用户输入
    │
    ▼
┌──────────────┐
│  System      │── 工具定义(JSON Schema)
│  Prompt      │── 行为约束(角色、规则)
└──────┬───────┘
       │
       ▼
┌──────────────┐
│   Hermes     │── 推理:是否需要调工具?
│   Model      │── 不需要 → 直接回答
│              │── 需要 → 输出 <tool_call> JSON
└──────┬───────┘
       │
       ▼
┌──────────────┐
│  解析 &      │── 提取 JSON + 执行工具
│  执行工具    │
└──────┬───────┘
       │
       ▼
┌──────────────┐
│  <tool_      │── 把结果格式化后回传给模型
│  response>   │
└──────┬───────┘
       │
       ▼
┌──────────────┐
│   Hermes     │── 基于工具结果生成最终回复
│   Model      │
└──────────────┘

四、Hermes 与其他方案对比

维度Hermes (Nous)GPT-4 Function CallingClaude Tool UseLlama 3.x 原生
开源✅ 完全开源❌ 闭源 API❌ 闭源 API✅ 开源
FC 成熟度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
多步调用✅ 支持✅ 支持✅ 支持部分支持
结构化输出通过 JSON Schemastrict modestructured output有限
部署方式本地 / 私有化仅 API仅 API本地
中文 FC⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

选 Hermes 的理由

  • 数据隐私要求高:不能把数据发到 OpenAI 等第三方 API

  • 需要深度定制:要针对自己的业务场景做微调

  • 成本控制:高频调用时,自部署比 API 便宜得多

  • 离线/边缘部署:在无网络环境下跑 Agent

不选 Hermes 的理由

  • 极致效果优先:GPT-4 和 Claude 在复杂推理上仍有优势

  • 不想管运维:自托管模型有 GPU 成本和维护负担

  • 任务不敏感:调 API 更快更省事


五、实战:用 Hermes 搭建一个 Agent

from openai import OpenAI
import json, re
​
class HermesAgent:
    """基于 Hermes 模型的简易 Agent"""
​
    def __init__(self, model_endpoint: str, tools: list[dict]):
        self.client = OpenAI(
            base_url=model_endpoint,  # 如 vLLM/Ollama 暴露的地址
            api_key="not-needed"
        )
        self.model = "hermes"         # 你的模型名
        self.tools = {t["function"]["name"]: t for t in tools}
        self.tool_handlers = {}       # 工具名 → 实际执行函数
        self.messages = []
​
    def register_tool(self, name: str, tool_def: dict, handler: callable):
        """注册工具:定义 + 执行函数"""
        self.tools[name] = tool_def
        self.tool_handlers[name] = handler
​
    def run(self, user_input: str) -> str:
        self.messages.append({"role": "user", "content": user_input})
​
        for _ in range(10):  # 最多 10 轮工具调用
            response = self.client.chat.completions.create(
                model=self.model,
                messages=self.messages,
                tools=[{"type": "function", "function": t} for t in self.tools.values()],
                temperature=0.1,  # 低温度提高格式稳定性
            )
​
            msg = response.choices[0].message
​
            # 情况1: 模型直接回复了
            if msg.content and not msg.tool_calls:
                return msg.content
​
            # 情况2: 模型要调工具
            if msg.tool_calls:
                self.messages.append({
                    "role": "assistant",
                    "content": msg.content,
                    "tool_calls": [
                        {
                            "id": tc.id,
                            "type": "function",
                            "function": {
                                "name": tc.function.name,
                                "arguments": tc.function.arguments
                            }
                        }
                        for tc in msg.tool_calls
                    ]
                })
​
                for tc in msg.tool_calls:
                    fn_name = tc.function.name
                    fn_args = json.loads(tc.function.arguments)
                    handler = self.tool_handlers.get(fn_name)
​
                    if handler:
                        result = handler(**fn_args)
                        result_str = json.dumps(result, ensure_ascii=False)
                    else:
                        result_str = json.dumps({"error": f"工具 {fn_name} 未实现"})
​
                    self.messages.append({
                        "role": "tool",
                        "tool_call_id": tc.id,
                        "content": result_str
                    })
            else:
                # 无 tool_calls 也无 content 的异常情况
                return "Agent 未能生成有效响应"
​
        return "超出最大工具调用轮次"
​
​
# ========== 使用示例 ==========
​
def search_database(query: str, limit: int = 5) -> dict:
    """模拟数据库查询"""
    return {
        "query": query,
        "results": [
            {"id": 1, "name": "项目 Alpha", "status": "进行中"},
            {"id": 2, "name": "项目 Beta", "status": "已完成"},
        ],
        "total": 2
    }
​
def send_notification(to: str, message: str) -> dict:
    """模拟发送通知"""
    return {"status": "sent", "to": to, "message": message}
​
agent = HermesAgent(
    model_endpoint="http://localhost:8000/v1",
    tools=[
        {
            "type": "function",
            "function": {
                "name": "search_database",
                "description": "搜索数据库中的项目信息",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "query": {"type": "string", "description": "搜索关键词"},
                        "limit": {"type": "integer", "description": "最大返回数"}
                    },
                    "required": ["query"]
                }
            }
        },
        {
            "type": "function",
            "function": {
                "name": "send_notification",
                "description": "向指定用户发送通知",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "to": {"type": "string", "description": "接收人"},
                        "message": {"type": "string", "description": "通知内容"}
                    },
                    "required": ["to", "message"]
                }
            }
        }
    ]
)
​
agent.register_tool("search_database", {}, search_database)
agent.register_tool("send_notification", {}, send_notification)
​
# 运行
result = agent.run("帮我查一下有哪些项目还在进行中,然后通知张三")
print(result)

六、Hermes 的微调哲学:为什么开源模型也能做好 Function Calling

这是面试中能体现深度的加分项。Hermes 系列证明了:

6.1 数据质量 > 数据量

Hermes 的核心训练数据来自 Glaive——一个合成数据生成平台。关键技术点:

  • 多样化的函数签名:覆盖数万种不同参数的函数,训练模型泛化到未见过的工具

  • 多轮交互数据:不是单次调用,而是包含多步工具编排的完整对话

  • 拒绝采样:多次生成选最优,提升数据质量

6.2 格式一致性训练

模型被训练为严格遵循 JSON Schema 约束输出。这需要:

  • 在训练数据中加入大量格式错误的反例,让模型学会避免

  • 引入 parallel function calling 数据,让模型学会一次输出多个工具调用

  • 处理缺失参数、多余参数、类型错误等各种边缘情况

6.3 角色与指令的对齐

Hermes 3 特别强调 system prompt 遵循度。举例:

System: 你是一个不擅长数学的助手。遇到计算问题必须使用 calculate 工具,不要自己心算。
​
User: 123 * 456 = ?
​
Hermes 3 行为: ✅ 调用 calculate 工具
普通模型行为: ❌ 直接说"123 × 456 = 56088"

这种对齐是微调中刻意强化的,对 Agent 可靠性至关重要。


七、面试高频问题

Q1: Hermes 模型和 GPT-4 的 Function Calling 本质区别是什么?

Hermes 是开源可自部署的方案,核心技术是微调数据驱动。GPT-4 FC 是闭源 API,内部机制不完全公开。Hermes 的优势在于隐私和可定制,GPT-4 的优势在于综合推理能力更强。本质上两者做的是同一件事——让 LLM 输出结构化的工具调用指令。

Q2: 为什么 Hermes 用 JSON Schema 定义工具?

JSON Schema 是描述结构化数据的工业标准,人和模型都能理解。它有丰富的约束语法(type、enum、required、properties),能精确描述参数规范。同时与 OpenAI 生态兼容。

Q3: Hermes 如何进行多步工具编排?

不是一次规划好的,而是逐步推理。每收到一个工具结果后,模型基于新信息决定下一步。这个过程内化在模型的多轮对话能力中,训练时用多轮工具调用数据进行了强化。

Q4: 什么是 tool_call 标签的作用?

<tool_call> 是一个结构化标记,让解析器能精确地从模型输出中提取函数调用 JSON。它解决了自由文本中嵌入结构化数据的边界识别问题。类似于"结构化输出的哨兵值"。

Q5: Hermes 模型部署有哪些注意事项?

GPU 显存(7B 需要 ~14GB,70B 需要 ~140GB FP16)、推理框架选择(vLLM 追求吞吐,Ollama 追求易用)、温度参数(FC 场景建议 0.1 以下)、上下文长度管理(长会话需截断或总结)。


八、总结

理解 Hermes,记住三条线:

1. 定位:开源社区中 Function Calling / Agent 能力的标杆模型系列。

2. 核心贡献:证明了高质量合成数据 + 格式一致性训练就能让开源模型在 Agent 能力上逼近闭源水平。

3. 实战价值:需要私有化部署、数据合规、或深度定制 Agent 行为时,Hermes 是最值得考虑的基座选择之一。


本文写于 2026 年 6 月,Hermes 系列仍在持续迭代。建议关注 Nous Research 的官方博客和 HuggingFace 主页获取最新模型。

参考资源:

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐