文章目录
-
- [1. 引言](#1. 引言)
- [2. 认识 Hermes:为什么它适合做 Agent](#2. 认识 Hermes:为什么它适合做 Agent)
-
- [2.1 版本选型建议](#2.1 版本选型建议)
- [3. 环境准备:先让裸模型跑起来](#3. 环境准备:先让裸模型跑起来)
-
- [3.1 硬件与软件基线](#3.1 硬件与软件基线)
- [3.2 获取模型权重](#3.2 获取模型权重)
- [4. 基础对话:配置 Chat Template 与系统提示词](#4. 基础对话:配置 Chat Template 与系统提示词)
-
- [4.1 使用 Transformers 加载](#4.1 使用 Transformers 加载)
- [4.2 系统提示词设计](#4.2 系统提示词设计)
- [5. 开启 Function Calling:Agent 的「手」](#5. 开启 Function Calling:Agent 的「手」)
-
- [5.1 工具声明](#5.1 工具声明)
- [5.2 注入对话并生成调用](#5.2 注入对话并生成调用)
- [5.3 常见问题排查](#5.3 常见问题排查)
- [6. Tool Use 闭环:让 Agent 真正干活](#6. Tool Use 闭环:让 Agent 真正干活)
- [7. 接入 Agent 框架:推荐 LangGraph](#7. 接入 Agent 框架:推荐 LangGraph)
-
- [7.1 定义状态与节点](#7.1 定义状态与节点)
- [7.2 组装工作流](#7.2 组装工作流)
- [8. 部署与性能调优](#8. 部署与性能调优)
-
- [8.1 使用 vLLM 提升吞吐](#8.1 使用 vLLM 提升吞吐)
- [8.2 量化策略](#8.2 量化策略)
- [8.3 并发与资源规划](#8.3 并发与资源规划)
- [9. 安全护栏与上线检查](#9. 安全护栏与上线检查)
-
- [9.1 工具权限最小化](#9.1 工具权限最小化)
- [9.2 输出校验](#9.2 输出校验)
- [9.3 上线检查清单](#9.3 上线检查清单)
- [10. 实战:从需求到 Agent 落地](#10. 实战:从需求到 Agent 落地)
- [11. 常见问题速查](#11. 常见问题速查)
- [12. 总结](#12. 总结)
1. 引言
在开源大模型生态里,Hermes 系列(由 Nous Research 维护,如 Hermes 3、Hermes 4 以及社区衍生的 OpenHermes)以其对 Function Calling、工具调用和长上下文任务的出色适配,被大量开发者用于构建 AI Agent。相比单纯追求「聊天丝滑」的对话模型,Hermes 更像是为 Agent 场景量身定制的「操作型模型」:它擅长遵循结构化指令、输出可解析的 JSON、调用外部工具并保持多轮任务状态。
本文的定位不是「模型原理考古」,而是一份可落地的全配置指南。我们从一张裸卡、一套推理框架开始,逐步配置到能够稳定完成「规划---调用工具---汇总结果」的 Agent 形态,并覆盖量化、部署、护栏等工程细节。
阅读完本文,你将能够:
- 明确 Hermes 模型家族选型思路;
- 在本地或云端跑通 Hermes 基础推理;
- 配置结构化的 Function Calling 与 Tool Use;
- 将 Hermes 接入主流 Agent 框架;
- 完成推理加速、资源规划与安全护栏。
下面给出本文的整体配置路径:
#mermaid-svg-uIvjMdiw6VCM2idB{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uIvjMdiw6VCM2idB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uIvjMdiw6VCM2idB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uIvjMdiw6VCM2idB .error-icon{fill:#552222;}#mermaid-svg-uIvjMdiw6VCM2idB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uIvjMdiw6VCM2idB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uIvjMdiw6VCM2idB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uIvjMdiw6VCM2idB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uIvjMdiw6VCM2idB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uIvjMdiw6VCM2idB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uIvjMdiw6VCM2idB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uIvjMdiw6VCM2idB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uIvjMdiw6VCM2idB .marker.cross{stroke:#333333;}#mermaid-svg-uIvjMdiw6VCM2idB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uIvjMdiw6VCM2idB p{margin:0;}#mermaid-svg-uIvjMdiw6VCM2idB .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uIvjMdiw6VCM2idB .cluster-label text{fill:#333;}#mermaid-svg-uIvjMdiw6VCM2idB .cluster-label span{color:#333;}#mermaid-svg-uIvjMdiw6VCM2idB .cluster-label span p{background-color:transparent;}#mermaid-svg-uIvjMdiw6VCM2idB .label text,#mermaid-svg-uIvjMdiw6VCM2idB span{fill:#333;color:#333;}#mermaid-svg-uIvjMdiw6VCM2idB .node rect,#mermaid-svg-uIvjMdiw6VCM2idB .node circle,#mermaid-svg-uIvjMdiw6VCM2idB .node ellipse,#mermaid-svg-uIvjMdiw6VCM2idB .node polygon,#mermaid-svg-uIvjMdiw6VCM2idB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uIvjMdiw6VCM2idB .rough-node .label text,#mermaid-svg-uIvjMdiw6VCM2idB .node .label text,#mermaid-svg-uIvjMdiw6VCM2idB .image-shape .label,#mermaid-svg-uIvjMdiw6VCM2idB .icon-shape .label{text-anchor:middle;}#mermaid-svg-uIvjMdiw6VCM2idB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uIvjMdiw6VCM2idB .rough-node .label,#mermaid-svg-uIvjMdiw6VCM2idB .node .label,#mermaid-svg-uIvjMdiw6VCM2idB .image-shape .label,#mermaid-svg-uIvjMdiw6VCM2idB .icon-shape .label{text-align:center;}#mermaid-svg-uIvjMdiw6VCM2idB .node.clickable{cursor:pointer;}#mermaid-svg-uIvjMdiw6VCM2idB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uIvjMdiw6VCM2idB .arrowheadPath{fill:#333333;}#mermaid-svg-uIvjMdiw6VCM2idB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uIvjMdiw6VCM2idB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uIvjMdiw6VCM2idB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uIvjMdiw6VCM2idB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uIvjMdiw6VCM2idB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uIvjMdiw6VCM2idB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uIvjMdiw6VCM2idB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uIvjMdiw6VCM2idB .cluster text{fill:#333;}#mermaid-svg-uIvjMdiw6VCM2idB .cluster span{color:#333;}#mermaid-svg-uIvjMdiw6VCM2idB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uIvjMdiw6VCM2idB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uIvjMdiw6VCM2idB rect.text{fill:none;stroke-width:0;}#mermaid-svg-uIvjMdiw6VCM2idB .icon-shape,#mermaid-svg-uIvjMdiw6VCM2idB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uIvjMdiw6VCM2idB .icon-shape p,#mermaid-svg-uIvjMdiw6VCM2idB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uIvjMdiw6VCM2idB .icon-shape .label rect,#mermaid-svg-uIvjMdiw6VCM2idB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uIvjMdiw6VCM2idB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uIvjMdiw6VCM2idB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uIvjMdiw6VCM2idB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 选择 Hermes 模型版本
准备推理环境
基础对话跑通
配置 Chat Template
开启 Function Calling
接入 Agent 框架
量化与推理加速
安全护栏与上线
2. 认识 Hermes:为什么它适合做 Agent
Hermes 系列的核心能力来自两方面:高质量指令微调数据 与针对工具调用的专门训练。与通用对话模型相比,它在以下场景优势明显:
- 函数调用:能够根据用户意图稳定输出符合格式的函数名与参数 JSON;
- 结构化输出:擅长生成可被程序直接解析的 JSON、XML 等结构;
- 角色一致性:配合系统提示词时,能长期保持 Agent 的角色设定;
- 长上下文:较新的版本支持较长上下文窗口,适合多轮工具调用累积。
需要澄清一个常见误区:Hermes 本身并不等同于「一个开箱即用的 Agent 软件」。它是模型层;要构建 Agent,还需要推理引擎、工具执行环境与编排逻辑。本文做的就是把这套「模型---框架---工程」链路配置完整。
2.1 版本选型建议
| 版本 | 典型参数量 | 适合场景 |
|---|---|---|
| Hermes 3 系列 | 3B / 8B / 70B / 405B | 生产级 Agent,函数调用稳定 |
| Hermes 4 系列 | 按发布版本 | 更强推理与工具组合能力 |
| OpenHermes 社区版 | 7B / 13B 等 | 实验、教学、低资源验证 |
如果你的目标是业务 Agent,优先选择参数规模更大、函数调用经过系统性评测的版本;如果只是先跑通流程,7B/8B 量级配合量化已经足够用于开发验证。
3. 环境准备:先让裸模型跑起来
3.1 硬件与软件基线
以一个典型 8B 模型为例,给出最低可运行配置:
- GPU 显存:FP16 推理建议 20 GB 以上;8-bit 量化可降至约 12 GB;4-bit 量化可降至约 8 GB;
- 内存:建议 32 GB 以上,便于加载 tokenizer 与缓存;
- 存储:预留模型权重体积的 1.5 倍以上,8B 模型通常需要 20~40 GB;
- Python:3.10 或 3.11,配合当前主流推理库。
安装基础依赖:
bash
pip install torch transformers accelerate
如果你的目标是更高效的生产部署,建议同时准备 vLLM 或 SGLang:
bash
pip install vllm
3.2 获取模型权重
Hermes 官方权重多发布在 Hugging Face 上,可通过 huggingface-cli 下载:
bash
huggingface-cli download NousResearch/Hermes-3-Llama-3.1-8B \
--local-dir ./models/Hermes-3-8B
正式接入业务前,请核对模型的开源协议与使用限制,确保合规。
4. 基础对话:配置 Chat Template 与系统提示词
Hermes 系列基于不同底座(如 Llama、Qwen 等)会有不同的聊天模板。模板配置错误会导致模型输出错乱,这是很多「跑通但效果差」问题的根源。
4.1 使用 Transformers 加载
先用最小代码验证模型能否正常对话:
python
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
model_id = "./models/Hermes-3-8B"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
model_id,
torch_dtype=torch.bfloat16,
device_map="auto",
)
messages = [
{"role": "system", "content": "你是一名严谨、可靠的 AI Agent,优先使用工具解决问题。"},
{"role": "user", "content": "你好,介绍一下你自己。"},
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True,
)
inputs = tokenizer(text, return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_new_tokens=256, do_sample=False)
reply = tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
print(reply)
4.2 系统提示词设计
Agent 场景下,系统提示词应明确三件事:身份 、能力边界 、输出规范。一个可复用的模板如下:
markdown
你是一名专业 AI Agent。
- 当用户请求需要调用工具时,你只能通过工具完成,不得编造结果;
- 工具返回失败时,如实说明原因,不要猜测;
- 最终回复使用简洁中文,技术术语保留英文原名;
- 如果信息不足,先向用户提出最关键的一个澄清问题。
系统提示词看似简单,却直接影响后续函数调用的稳定性,建议在实际业务中持续迭代。
5. 开启 Function Calling:Agent 的「手」
Function Calling 是 Hermes 作为 Agent 的分水岭能力。配置核心在于工具声明格式 与对话模板对齐。
5.1 工具声明
以查询天气为例,按 OpenAI 风格的 JSON Schema 声明工具:
python
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市当前天气",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,如 北京",
}
},
"required": ["city"],
},
},
}
]
5.2 注入对话并生成调用
不同后端对工具注入方式略有差异。以 vLLM 的 OpenAI 兼容接口为例:
python
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="token-not-required",
)
messages = [
{"role": "system", "content": "你是一名 AI Agent,请调用工具获取信息。"},
{"role": "user", "content": "北京今天天气怎么样?"},
]
resp = client.chat.completions.create(
model="Hermes-3-8B",
messages=messages,
tools=tools,
tool_choice="auto",
)
msg = resp.choices[0].message
if msg.tool_calls:
print(msg.tool_calls[0].function.name)
print(msg.tool_calls[0].function.arguments)
模型此时应返回类似:
json
{"name": "get_weather", "arguments": "{\"city\": \"北京\"}"}
5.3 常见问题排查
- 返回空
tool_calls:检查是否启用了正确的聊天模板,以及tools是否被后端正确转化; - 参数字段错位 :多数是工具描述不够清晰,或参数
description缺失; - 每次都调用工具 :可在
tool_choice设为auto,并在系统提示词中补充「仅当需要时调用工具」。
6. Tool Use 闭环:让 Agent 真正干活
Function Calling 只解决「模型想调用什么」,真正执行还需要你搭建 Tool Use 闭环:
- 模型给出
tool_calls; - 你的代码解析并执行对应函数;
- 将执行结果以
tool角色消息回填; - 再次请求模型生成最终回复。
下面是一个完整闭环示例:
python
def get_weather(city: str) -> str:
# 实际业务中替换为真实天气服务调用
return f"{city}今天晴,气温 25 摄氏度。"
available_functions = {"get_weather": get_weather}
# 第一轮:模型请求调用
messages.append(
{
"role": "assistant",
"content": None,
"tool_calls": [
{
"id": msg.tool_calls[0].id,
"type": "function",
"function": {
"name": msg.tool_calls[0].function.name,
"arguments": msg.tool_calls[0].function.arguments,
},
}
],
}
)
# 执行函数并回填
import json
args = json.loads(msg.tool_calls[0].function.arguments)
result = available_functions[msg.tool_calls[0].function.name](**args)
messages.append(
{
"role": "tool",
"tool_call_id": msg.tool_calls[0].id,
"content": result,
}
)
# 第二轮:模型汇总结果
resp = client.chat.completions.create(
model="Hermes-3-8B",
messages=messages,
)
print(resp.choices[0].message.content)
这个闭环是所有 Agent 框架的底层逻辑。只要这一层稳定,上层编排就是策略问题。
7. 接入 Agent 框架:推荐 LangGraph
手动管理多轮工具调用很快就会失控,推荐用框架统一编排。以 LangGraph 为例,其「graph + node + state」模型非常适合 Hermes 这类函数调用型模型。
7.1 定义状态与节点
python
from typing import Annotated, TypedDict
from langgraph.graph import StateGraph, END
from langgraph.graph.message import add_messages
from langchain_openai import ChatOpenAI
class AgentState(TypedDict):
messages: Annotated[list, add_messages]
llm = ChatOpenAI(
base_url="http://localhost:8000/v1",
api_key="token-not-required",
model="Hermes-3-8B",
temperature=0,
).bind_tools(tools)
def call_model(state: AgentState):
return {"messages": [llm.invoke(state["messages"])]}
def call_tool(state: AgentState):
from langgraph.prebuilt import ToolNode
return ToolNode(tools).invoke(state)
7.2 组装工作流
python
def should_continue(state: AgentState):
last_msg = state["messages"][-1]
if getattr(last_msg, "tool_calls", None):
return "tools"
return END
graph = StateGraph(AgentState)
graph.add_node("agent", call_model)
graph.add_node("tools", call_tool)
graph.set_entry_point("agent")
graph.add_conditional_edges("agent", should_continue, {"tools": "tools", END: END})
graph.add_edge("tools", "agent")
app = graph.compile()
result = app.invoke({"messages": [("user", "北京今天天气怎么样?")]})
print(result["messages"][-1].content)
采用框架后,多轮工具调用、重试、并行工具执行都能通过图结构统一管理,显著降低业务代码复杂度。
8. 部署与性能调优
Agent 对延迟非常敏感:一次「多轮思考---调用工具---汇总」可能产生多次前向推理。以下策略能直接改善体验。
8.1 使用 vLLM 提升吞吐
启动带 OpenAI 兼容接口的 vLLM 服务:
bash
vllm serve ./models/Hermes-3-8B \
--served-model-name Hermes-3-8B \
--port 8000 \
--gpu-memory-utilization 0.9 \
--max-model-len 8192
说明:
--gpu-memory-utilization控制显存占用,建议不要拉满以预留 KV Cache 弹性;--max-model-len与模型支持的最大上下文对齐;- 生产环境建议加上
--enable-prefix-caching复用系统提示词前缀。
8.2 量化策略
若显存紧张,可选择 AWQ 或 GPTQ 量化版本:
python
from transformers import AutoModelForCausalLM, AutoTokenizer, AwqConfig
model = AutoModelForCausalLM.from_pretrained(
"casperhansen/hermes-3-llama-3.1-8b-awq",
quantization_config=AwqConfig(bits=4),
device_map="auto",
)
注意:量化对函数调用的 JSON 输出稳定性几乎无影响,但极低 bit 量化可能略微降低复杂推理质量,上线前需在真实任务集上做回归评测。
8.3 并发与资源规划
以 8B + 单卡 24G 为例的经验值:
| 并发请求 | 量化方式 | 显存占用参考 |
|---|---|---|
| 4 | FP16 | 约 20 GB |
| 8 | AWQ 4bit | 约 10 GB |
| 16 | 多卡或分片 | 视部署方案 |
实际数值受 max_model_len 与批处理策略影响,应以压测结果为准。
9. 安全护栏与上线检查
Agent 会执行真实工具,风险随之从「说错话」升级为「做错事」。上线前必须配置护栏。
9.1 工具权限最小化
- 每个工具只授予完成任务的最小权限,避免模型误调用敏感操作;
- 对高风险操作(删除、支付、外发消息)增加二次确认 或人工审批;
- 限制单次调用参数范围,例如金额上限、目标白名单。
9.2 输出校验
不要完全信任模型的 JSON,执行前进行 schema 校验:
python
from jsonschema import validate, ValidationError
schema = {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
}
args = json.loads(msg.tool_calls[0].function.arguments)
try:
validate(instance=args, schema=schema)
except ValidationError as e:
# 记录日志并要求模型重新生成参数
raise
9.3 上线检查清单
text
- [ ] 模型协议与数据合规已确认
- [ ] 聊天模板与后端版本匹配
- [ ] 工具 schema 描述清晰,required 字段完整
- [ ] 工具执行结果有统一格式与错误处理
- [ ] 高风险工具具备人工确认机制
- [ ] 量化模型在真实评测集上通过回归
- [ ] 推理服务具备健康检查与限流
- [ ] 日志保留但不记录敏感用户数据
10. 实战:从需求到 Agent 落地
下面用一个「智能文档助手」需求串起全文配置:
- 需求:用户上传文档摘要,Agent 查询知识库并输出结论;
- 工具 :
search_docs(查询知识库)、read_doc(读取文档详情); - 编排:先搜索、再按需读取、最后汇总引用来源。
配置要点:
- 系统提示词写明「回答必须附来源编号」;
- 工具描述给出明确的输入输出语义;
- 用 LangGraph 组织「检索---读取---回答」三个节点;
- 最终回复阶段强制检查是否包含来源引用,缺失则补一轮。
一个最小可用的检索工具声明如下:
python
search_docs_tool = {
"type": "function",
"function": {
"name": "search_docs",
"description": "在知识库中检索与查询相关的文档,返回文档 id 与摘要",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "检索关键词,尽量具体"},
"top_k": {"type": "integer", "description": "返回文档数量,默认 5"},
},
"required": ["query"],
},
},
}
按此模式扩展,就能把 Hermes 逐步配置成贴合业务的天花板级 Agent。
11. 常见问题速查
- 模型输出不是有效 JSON :优先检查
do_sample=False或降低 temperature,同时检查聊天模板。 - 工具调用后陷入循环:为流程设置最大迭代次数,并在提示词中要求「工具结果已足够时立即回答」。
- 长会话显存暴涨 :限制
max_model_len,开启 prefix caching,并定期清理历史消息。 - 同一工具被反复误调用:重写工具 description,加入明确的正反例说明。
- 多工具场景下参数混淆 :为每个参数补充
description,区分语义相近的参数名。
12. 总结
从一个裸版 Hermes 权重,到能稳定执行「规划---调用---汇总」的 AI Agent,核心配置路径可归纳为四步:选对模型版本、对齐聊天模板、跑通 Function Calling 闭环、用框架编排并加护栏。这一步一步串起来并不神秘,难点往往不在「模型会不会调工具」,而在工具描述是否清晰、闭环是否健壮、部署是否可观测。
建议你从最小的 7B/8B 量化版开始完整走一遍本文链路,再逐步替换为更大参数版本。工程上持续积累「工具回归用例」与「真实任务评测集」,远比频繁换模型更能提升 Agent 稳定性。
希望这份指南能帮你把 Hermes 真正配置成业务中的 AI Agent 天花板。