1. 引言
随着大语言模型(LLM)能力的快速提升,越来越多的开发者开始构建基于 LLM 的智能体(Agent)应用。然而,面对 LangChain、AutoGen 等重量级框架,不少开发者会感到「杀鸡焉用牛刀」------项目规模不大,却要引入大量依赖和抽象概念。
Hermes Agent 正是为解决这一痛点而生的轻量级智能体框架。它设计简洁、依赖极少、上手门槛低,同时保留了智能体应用的核心能力:工具调用、多轮对话、上下文管理、任务规划等。本文将从零开始,带你一步步掌握 Hermes Agent 的核心用法,并给出可直接运行的实战示例。
2. Hermes Agent 是什么
2.1 设计理念
Hermes Agent 的核心设计理念可以概括为三个词:轻量、透明、可扩展。
- 轻量:核心库只依赖 OpenAI SDK 和少量基础工具库,安装体积小,启动速度快。
- 透明:不引入复杂的抽象层,Agent 的执行流程清晰可见,方便调试和二次开发。
- 可扩展:通过简单的装饰器或注册机制即可扩展工具函数,无需理解框架内部复杂的生命周期。
2.2 与主流框架的对比
| 特性 | Hermes Agent | LangChain | AutoGen |
|---|---|---|---|
| 安装体积 | 极小 | 较大 | 中等 |
| 学习曲线 | 平缓 | 陡峭 | 中等 |
| 工具扩展 | 装饰器注册 | Chain/工具类 | 函数注册 |
| 多智能体协作 | 基础支持 | 需额外组件 | 原生支持 |
| 适用场景 | 中小型项目、快速原型 | 复杂流水线 | 多智能体协作研究 |
3. 环境准备与安装
3.1 环境要求
- Python 3.9 及以上版本
- 一个可用的 OpenAI 兼容 API(可以是官方 API,也可以是本地部署的 vLLM、Ollama 等)
3.2 安装 Hermes Agent
使用 pip 即可完成安装:
bash
pip install hermes-agent
如果你需要使用本地模型(如通过 Ollama 或 vLLM 部署),可以安装带有额外依赖的版本:
bash
pip install hermes-agent[local]
3.3 配置 API Key
推荐使用环境变量来管理 API Key,避免硬编码在代码中:
bash
export OPENAI_API_KEY="sk-xxxxxx"
export OPENAI_BASE_URL="https://api.openai.com/v1"
如果你使用的是本地模型,可以将 OPENAI_BASE_URL 指向本地服务地址,例如 http://localhost:8000/v1。
4. 快速上手:第一个 Agent
4.1 最小示例
下面是一个最简单的 Hermes Agent 示例,它能够回答用户的问题:
python
from hermes_agent import Agent
# 创建 Agent 实例
agent = Agent(
model="gpt-4o-mini",
system_prompt="你是一个乐于助人的智能助手。"
)
# 与 Agent 对话
response = agent.chat("你好,请用一句话介绍你自己。")
print(response)
运行上述代码,你会看到 Agent 基于系统提示词和用户输入生成回复。
4.2 多轮对话
Agent 默认会维护对话历史,因此你可以直接进行多轮对话:
python
agent = Agent(model="gpt-4o-mini")
print(agent.chat("我的名字是张三。"))
print(agent.chat("我叫什么名字?")) # Agent 会记得之前的对话
4.3 重置对话
当需要开启一段全新的对话时,可以调用 reset 方法清空历史:
python
agent.reset()
5. 工具调用:让 Agent 拥有「动手能力」
5.1 定义工具函数
Hermes Agent 使用装饰器来注册工具函数,非常简单直观:
python
from hermes_agent import Agent, tool
@tool
def add(a: float, b: float) -> float:
"""计算两个数字的和。"""
return a + b
@tool
def get_weather(city: str) -> str:
"""查询指定城市的天气情况。"""
# 这里可以接入真实的天气 API
return f"{city} 今天晴,气温 25°C。"
5.2 将工具绑定到 Agent
创建 Agent 时,通过 tools 参数传入工具列表:
python
agent = Agent(
model="gpt-4o-mini",
tools=[add, get_weather]
)
response = agent.chat("请计算 123 和 456 的和。")
print(response)
response = agent.chat("北京今天天气怎么样?")
print(response)
Agent 会自动判断何时需要调用工具,并将工具结果整合进最终回复中。
5.3 工具调用的执行流程
下面是 Hermes Agent 处理一次工具调用的完整流程:
#mermaid-svg-FHAXWvubAUN80UTo{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-FHAXWvubAUN80UTo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FHAXWvubAUN80UTo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FHAXWvubAUN80UTo .error-icon{fill:#552222;}#mermaid-svg-FHAXWvubAUN80UTo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FHAXWvubAUN80UTo .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FHAXWvubAUN80UTo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FHAXWvubAUN80UTo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FHAXWvubAUN80UTo .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FHAXWvubAUN80UTo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FHAXWvubAUN80UTo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FHAXWvubAUN80UTo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FHAXWvubAUN80UTo .marker.cross{stroke:#333333;}#mermaid-svg-FHAXWvubAUN80UTo svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FHAXWvubAUN80UTo p{margin:0;}#mermaid-svg-FHAXWvubAUN80UTo .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FHAXWvubAUN80UTo .cluster-label text{fill:#333;}#mermaid-svg-FHAXWvubAUN80UTo .cluster-label span{color:#333;}#mermaid-svg-FHAXWvubAUN80UTo .cluster-label span p{background-color:transparent;}#mermaid-svg-FHAXWvubAUN80UTo .label text,#mermaid-svg-FHAXWvubAUN80UTo span{fill:#333;color:#333;}#mermaid-svg-FHAXWvubAUN80UTo .node rect,#mermaid-svg-FHAXWvubAUN80UTo .node circle,#mermaid-svg-FHAXWvubAUN80UTo .node ellipse,#mermaid-svg-FHAXWvubAUN80UTo .node polygon,#mermaid-svg-FHAXWvubAUN80UTo .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FHAXWvubAUN80UTo .rough-node .label text,#mermaid-svg-FHAXWvubAUN80UTo .node .label text,#mermaid-svg-FHAXWvubAUN80UTo .image-shape .label,#mermaid-svg-FHAXWvubAUN80UTo .icon-shape .label{text-anchor:middle;}#mermaid-svg-FHAXWvubAUN80UTo .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FHAXWvubAUN80UTo .rough-node .label,#mermaid-svg-FHAXWvubAUN80UTo .node .label,#mermaid-svg-FHAXWvubAUN80UTo .image-shape .label,#mermaid-svg-FHAXWvubAUN80UTo .icon-shape .label{text-align:center;}#mermaid-svg-FHAXWvubAUN80UTo .node.clickable{cursor:pointer;}#mermaid-svg-FHAXWvubAUN80UTo .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FHAXWvubAUN80UTo .arrowheadPath{fill:#333333;}#mermaid-svg-FHAXWvubAUN80UTo .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FHAXWvubAUN80UTo .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FHAXWvubAUN80UTo .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FHAXWvubAUN80UTo .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FHAXWvubAUN80UTo .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FHAXWvubAUN80UTo .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FHAXWvubAUN80UTo .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FHAXWvubAUN80UTo .cluster text{fill:#333;}#mermaid-svg-FHAXWvubAUN80UTo .cluster span{color:#333;}#mermaid-svg-FHAXWvubAUN80UTo 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-FHAXWvubAUN80UTo .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FHAXWvubAUN80UTo rect.text{fill:none;stroke-width:0;}#mermaid-svg-FHAXWvubAUN80UTo .icon-shape,#mermaid-svg-FHAXWvubAUN80UTo .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FHAXWvubAUN80UTo .icon-shape p,#mermaid-svg-FHAXWvubAUN80UTo .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FHAXWvubAUN80UTo .icon-shape .label rect,#mermaid-svg-FHAXWvubAUN80UTo .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FHAXWvubAUN80UTo .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FHAXWvubAUN80UTo .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FHAXWvubAUN80UTo :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否
是
用户输入
Agent 接收消息
是否需要调用工具?
直接生成回复
生成工具调用参数
执行工具函数
将结果返回给 Agent
Agent 生成最终回复
输出给用户
6. 进阶用法
6.1 自定义系统提示词
系统提示词决定了 Agent 的角色和行为风格,是构建专业 Agent 的关键:
python
system_prompt = """
你是一位资深的前端开发工程师,擅长 HTML、CSS 和 JavaScript。
在回答问题时,请给出具体的代码示例,并解释关键知识点。
"""
agent = Agent(
model="gpt-4o-mini",
system_prompt=system_prompt
)
6.2 控制模型参数
你可以通过 model_kwargs 传递模型生成参数,例如温度、最大 token 数等:
python
agent = Agent(
model="gpt-4o-mini",
model_kwargs={
"temperature": 0.7,
"max_tokens": 1024
}
)
6.3 流式输出
对于需要实时展示生成内容的场景(如聊天机器人),可以启用流式输出:
python
agent = Agent(model="gpt-4o-mini", stream=True)
for chunk in agent.chat_stream("讲一个关于程序员的笑话"):
print(chunk, end="", flush=True)
6.4 使用本地模型
Hermes Agent 兼容任何 OpenAI 格式的 API,因此可以无缝对接本地部署的模型:
python
agent = Agent(
model="qwen2.5-7b-instruct",
base_url="http://localhost:8000/v1",
api_key="EMPTY" # 本地服务通常不需要真实 Key
)
7. 实战案例:构建一个代码审查助手
下面我们综合运用前面学到的知识,构建一个实用的代码审查助手。
7.1 定义审查工具
python
from hermes_agent import Agent, tool
@tool
def check_style(code: str) -> str:
"""检查代码风格问题。"""
issues = []
if len(code.split("\n")) > 50:
issues.append("函数过长,建议拆分为多个小函数。")
if "TODO" in code:
issues.append("存在未完成的 TODO 标记。")
if not issues:
return "代码风格良好,未发现明显问题。"
return "\n".join(issues)
@tool
def check_security(code: str) -> str:
"""检查代码中的安全隐患。"""
issues = []
if "eval(" in code:
issues.append("检测到 eval 使用,存在代码注入风险。")
if "password" in code and "input(" in code:
issues.append("检测到明文密码输入,建议使用安全输入方式。")
if not issues:
return "未发现明显安全隐患。"
return "\n".join(issues)
7.2 组装审查 Agent
python
review_agent = Agent(
model="gpt-4o-mini",
system_prompt="你是一位严谨的代码审查专家,会调用工具检查代码质量,并给出改进建议。",
tools=[check_style, check_security]
)
code = """
def process(data):
result = eval(data)
# TODO: 添加异常处理
return result
"""
response = review_agent.chat(f"请审查以下代码:\n```python\n{code}\n```")
print(response)
7.3 运行效果
Agent 会自动调用 check_style 和 check_security 两个工具,结合工具返回的结果,给出综合的审查意见和改进建议。
8. 常见问题与排查
8.1 工具调用失败怎么办
- 确认工具函数的参数类型注解是否完整,Hermes Agent 依赖类型注解生成调用参数。
- 检查工具函数的 docstring 是否清晰描述了功能,这会影响模型对工具的理解。
- 在创建 Agent 时设置
debug=True,可以打印详细的调用日志。
8.2 如何控制 Agent 的工具调用频率
可以通过 tool_choice 参数控制:
python
# 强制 Agent 每次都必须调用工具
agent = Agent(model="gpt-4o-mini", tools=[add], tool_choice="required")
# 禁止 Agent 调用工具
agent = Agent(model="gpt-4o-mini", tools=[add], tool_choice="none")
8.3 上下文过长如何处理
当对话历史过长时,可以设置最大历史轮数,自动裁剪早期消息:
python
agent = Agent(
model="gpt-4o-mini",
max_history_rounds=10 # 只保留最近 10 轮对话
)
9. 总结
Hermes Agent 是一个设计精巧的轻量级智能体框架,它用极小的学习成本换来了构建智能体应用的核心能力。通过本文的学习,你已经掌握了:
- Hermes Agent 的安装与基本配置
- 创建 Agent 并进行多轮对话
- 通过装饰器注册工具,赋予 Agent 动手能力
- 流式输出、本地模型对接等进阶用法
- 构建一个完整的代码审查助手实战案例
如果你的项目需要一个快速、简洁、可扩展的智能体解决方案,Hermes Agent 值得一试。后续你可以进一步探索它的多智能体协作、记忆管理等高级特性,构建更强大的智能应用。