项目demo地址下载

如果刚开始接触智能体,最容易卡住的地方通常不是“概念听不懂”,而是“看完原理还是不知道怎么自己跑起来”。这篇文章的目标很直接:结合 Datawhale《Hello Agents》第一章 1.3 小节“动手体验:5 分钟实现第一个智能体”的思路,分析我手上的这个 travel_agent_demo 项目,并给出一条适合本地环境的实践路径。

这份项目的价值在于,它没有上来就引入一堆框架,而是保留了 Agent 最核心的闭环:

  • 大模型负责理解任务和做决策
  • Python 函数负责充当工具
  • 主循环负责执行 Thought -> Action -> Observation

如果你本地已经安装了 ollama,并且已经拉好了 gemma4:31b,那么这个项目基本就是一份很适合入门的最小可运行样例。

先看理论:1.3 小节到底讲了什么

Datawhale 在 1.3 小节里做了一件很重要的事:它没有先讲复杂框架,而是先带你手写一个最小智能体。这个例子的核心任务是:

先查询天气,再根据天气推荐景点。

这个任务看起来简单,但已经完整覆盖了一个 Agent 的基本能力:

  • 接收用户目标
  • 将目标拆成多个步骤
  • 在每一步决定是否调用工具
  • 读取工具返回结果
  • 基于新观察继续推理
  • 在信息足够时输出最终答案

这正是 Thought-Action-Observation 范式最适合演示的地方。Datawhale 1.3 小节把这个过程拆成了三部分:

  1. 定义系统提示词,约束模型输出 ThoughtAction
  2. 定义工具,例如天气查询和景点推荐
  3. 写一个循环,不断把历史上下文和工具观察结果喂给模型

它的重点不在“代码很多”,而在“闭环完整”。这一点,正好和当前这个项目完全对上。

参考链接: Datawhale 原文

这个项目和 1.3 小节是一一对应的

travel_agent_demo 的结构非常克制,只有 4 个核心文件:

  • config.py
  • tools.py
  • llm_client.py
  • agent.py

如果按 1.3 小节的思路去看,它们的分工非常清晰。

1. config.py:把“提示词”显式写出来

Datawhale 1.3 的第一步是写 AGENT_SYSTEM_PROMPT,告诉模型:

  • 你是谁
  • 你有哪些工具
  • 你必须用什么格式回复

这个项目同样把提示词放在了 config.py 里,并明确要求模型每次只能输出一组:

  • Thought: ...
  • Action: ...

同时要求 Action 只能是两种形式:

  • 工具调用:function_name(arg="value")
  • 结束任务:Finish[最终答案]

这一步很关键。很多初学者以为“有模型就有 Agent”,其实不对。没有明确的动作协议,模型就无法稳定进入“可执行”的状态。

2. tools.py:把外部世界变成可调用能力

在 Agent 体系里,工具就是模型接触环境的“手”和“眼”。这个项目提供了 3 个工具:

  • get_weather(city: str)
  • web_search(query: str)
  • get_attraction(city: str, weather: str)

它们背后的实现也非常直白:

  • get_weather 调用 wttr.in
  • web_search 调用 Tavily 搜索 API
  • get_attraction 本质上是构造一个景点推荐搜索词,再复用 web_search

这和 1.3 小节的设计是同一种思想:工具不用复杂,但要让模型真的“能做事”。

3. llm_client.py:对接 OpenAI 兼容接口

1.3 小节专门强调了一个现实问题:很多模型服务都走 OpenAI 兼容接口,所以最好封一个通用客户端。这个项目正是这么做的。

llm_client.py 里的 OpenAICompatibleClient 很轻量,核心只有一件事:把 system_promptuser prompt 发送给兼容 OpenAI Chat Completions 的接口。

这也是它能直接接入本地 Ollama 的原因。只要你的 Ollama 开了 OpenAI 兼容入口,配置好:

  • LLM_BASE_URL
  • LLM_API_KEY
  • LLM_MODEL

就可以把本地模型当成 Agent 的“大脑”。

4. agent.py:真正的 Agent 循环

整个项目最像 1.3 小节“原样落地”的部分,就是 agent.py

它做了几件非常典型的事:

  1. 接收用户输入
  2. 拼接历史上下文 prompt_history
  3. 调用大模型生成 Thought + Action
  4. 解析 Action
  5. 如果是工具调用,就执行对应 Python 函数
  6. 把结果写成 Observation
  7. 继续下一轮,直到遇到 Finish[...]

这就是一个标准的最小 Agent 闭环。

如果只用一句话概括这个项目,可以这么说:

它不是“把大模型接到 Python 上”,而是“让大模型在一个受控循环里学会决定何时调用工具”。

为什么这个项目适合写成“第一个智能体”

因为它刚好处在一个很好的平衡点上:

  • 比纯 Prompt Demo 更完整,因为已经有工具调用和多轮循环
  • 比 LangChain、AutoGen 之类框架更容易理解,因为每一步都能直接看到
  • 比只会对话的聊天机器人更接近真正的 Agent,因为它具备行动能力

对于博客读者来说,这种项目有三个优点。

第一,代码量小,读者不会在框架封装里迷路。

第二,概念和实现能一一对应。你在书里看到的:

  • 提示词
  • 工具
  • 动作解析
  • 观察回填
  • 结束条件

在项目代码里都能找到落点。

第三,容易迁移。你今天做的是旅行助手,明天就能改成:

  • 本地知识库问答 Agent
  • 网页检索 Agent
  • 天气与出行建议 Agent
  • 带记忆的个性化推荐 Agent

用本地 Ollama 跑这个项目

你的环境已经具备一个关键前提:本地安装了 ollama,并且已经拉好了 gemma4:31b。这意味着 LLM 侧基本已经准备完成。

这个项目的 README 给出的配置思路如下:

pip install -r requirements.txt

然后准备 .env

TAVILY_API_KEY=你的key
LLM_API_KEY=ollama
LLM_BASE_URL=http://127.0.0.1:11434/v1
LLM_MODEL=gemma4:31b

注意一件事:项目当前 README 里示例地址写的是局域网 IP http://局域网IP:11434/v1。如果你就是在本机运行 Ollama,更常见也更稳妥的写法是:

LLM_BASE_URL=http://127.0.0.1:11434/v1

启动方式很简单:

python agent.py

然后输入类似:

帮我查询今天贵阳的天气,并推荐一个适合现在去的景点

运行前要知道的两个现实问题

这个项目能跑,不代表它已经“产品化”。如果你要写博客,最好把下面两点讲清楚。

1. 没有 TAVILY_API_KEY,景点推荐链路会失败

项目里 get_attraction() 实际上是复用 web_search() 完成的,而 web_search() 依赖 Tavily。

这意味着:

  • 查天气可以走 wttr.in
  • 查景点推荐依赖 Tavily
  • 如果没配置 TAVILY_API_KEY,涉及网页搜索和景点推荐的步骤会返回错误

所以如果你想完整复现 Datawhale 1.3 里的“天气 -> 景点推荐 -> 最终总结”三步链路,最好提前准备 Tavily Key。

2. 大模型越大,多轮循环越容易变慢

项目作者已经意识到了这一点,所以在 agent.py 里做了一个很实用的小优化:对 Observation 做摘要截断,避免上下文越来越长。

这件事在本地模型场景下尤其重要。gemma4:31b 的效果会更稳,但如果机器资源一般,多轮推理的等待感会明显上升。博客里可以直接提醒读者:

  • 入门先关注闭环是否跑通
  • 再关注响应速度
  • 最后再考虑更复杂的记忆、规划和反思机制

从“能跑”到“像一个真正的智能体”,这个项目还差什么

如果把标准放在“第一个智能体”,这个项目已经合格。如果把标准放在“更像真实 Agent 系统”,它还可以继续往前走。

1. 记忆

当前 prompt_history 只保存本次会话中的历史,没有用户长期偏好。

如果要增强,可以增加:

  • 用户偏好存储
  • 预算约束
  • 喜欢的景点类型
  • 历史拒绝记录

这正好对应 Datawhale 习题里提到的“记住用户偏好”方向。

2. 反思与容错

目前如果工具失败,模型只能在错误信息上继续推理,但没有明确的重试策略和回退策略。

更稳一点的做法是增加:

  • 工具失败重试
  • 参数修正
  • 备选工具
  • 明确的失败收敛条件
3. 更强的动作协议

现在 parse_action() 通过正则解析参数,足够轻量,但对复杂参数不够稳。

如果后续想扩展更多工具,更建议演进成:

  • JSON 格式动作
  • 函数调用 schema
  • 严格参数校验
4. 更真实的旅游场景

当前的“景点推荐”本质上还是网页搜索摘要,离真正旅游助手还有距离。下一步可以扩展的能力包括:

  • 酒店查询
  • 路线规划
  • 门票信息
  • 用户预算约束
  • 多城市 itinerary 生成

从 Datawhale 1.3 小节到这个 travel_agent_demo,最大的体会是:第一个智能体不需要复杂,关键是先把闭环搭起来。只要模型能按照约定输出动作、程序能解析动作、工具能把外部信息带回来,一个真正意义上的 Agent 就已经出现了。

而当这个闭环跑在本地 Ollama + gemma4:31b 上时,学习体验会非常具体。你不再只是“理解概念”,而是真的看见模型如何决定先查天气、再查景点、最后合成答案。对初学者来说,这一步比额外学习十个框架更重要。

参考资料