05 · 项目一:智能旅行助手从 0 到 1
对应官方仓库
code/chapter13/helloagents-trip-planner。输入"城市 + 日期 + 偏好",四个 Agent 协作调用高德地图,生成带地图、天气、酒店、预算的完整行程。本篇按里程碑推进,每个里程碑结束都有一个可验证的 checkpoint,不通过不要往下走。
0. 开工前核对
- [ ] 第 02 篇的 LLM 三件套(
LLM_MODEL_ID/LLM_API_KEY/LLM_BASE_URL)已验证可用 - [ ] 高德Web 服务 Key 和 Web 端 JS API Key 都已到手
- [ ]
hello-agents仓库已 clone - [ ]
uvx --version有输出(MCP 服务器靠它启动)
1. 项目全景
用户浏览器 (Vue, :5173)
│ POST /api/trip/plan
▼
FastAPI 后端 (:8000)
│
▼
MultiAgentTripPlanner ──── 顺序执行四步 ────────────────┐
1️⃣ 景点搜索专家 ──[TOOL_CALL]──▶ 高德MCP maps_text_search
2️⃣ 天气查询专家 ──[TOOL_CALL]──▶ 高德MCP maps_weather
3️⃣ 酒店推荐专家 ──[TOOL_CALL]──▶ 高德MCP maps_text_search
4️⃣ 行程规划专家 ──(无工具)──▶ 整合前三步结果,输出行程JSON
└──────────────────────────────────────────────────┘
│ 解析JSON为 TripPlan
▼
前端 Result.vue 渲染:每日卡片 + 高德JS地图打点 + 预算表
后端目录(先混个脸熟,里程碑 3 逐个精读):
backend/
├── run.py # 启动入口
├── requirements.txt
├── .env.example # 环境变量模板
└── app/
├── config.py # 读取.env的配置类
├── api/main.py # FastAPI应用 + CORS + 挂路由
├── api/routes/trip.py # POST /api/trip/plan(主流程)
├── api/routes/map.py # 地图相关接口
├── api/routes/poi.py # POI搜索接口(POI=Point of Interest"兴趣点",地图术语,泛指景点/餐厅/酒店等地点)
├── agents/trip_planner_agent.py # ⭐核心:四Agent协作系统
├── services/llm_service.py # 构造HelloAgentsLLM
├── services/amap_service.py # 高德HTTP API封装(MCP之外的直调)
├── services/unsplash_service.py # 景点配图(可选)
└── models/schemas.py # ⭐所有Pydantic模型
2. 里程碑一:后端跑起来(约 1 小时)
cd hello-agents/code/chapter13/helloagents-trip-planner/backend
uv venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
uv pip install -r requirements.txt
cp .env.example .env
编辑 .env,至少填四项:
LLM_MODEL_ID=deepseek-chat
LLM_API_KEY=sk-你的key
LLM_BASE_URL=https://api.deepseek.com/v1
AMAP_API_KEY=你的高德Web服务Key
启动:
uvicorn app.api.main:app --reload --host 0.0.0.0 --port 8000
✅ Checkpoint 1:终端出现多智能体系统初始化成功的日志(能看到四个 Agent 各自的工具数);浏览器打开 http://localhost:8000/docs 能看到接口列表。
初始化卡在"创建共享 MCP 工具"?那是
uvx第一次下载amap-mcp-server,等一两分钟;一直失败则检查网络和 uv 安装。
3. 里程碑二:不碰前端,先用 /docs 调通主接口(约 1 小时)
打开 /docs → POST /api/trip/plan → Try it out,填入:
{
"city": "北京",
"start_date": "2026-09-01",
"end_date": "2026-09-03",
"travel_days": 3,
"preferences": ["历史文化"],
"transportation": "公共交通",
"accommodation": "经济型"
}
(八个字段中 city、start_date、end_date、travel_days、transportation、accommodation 为必填,另有可选的 free_text_input 传额外要求;422 报错时对照 models/schemas.py 的 TripRequest 修改。)
点 Execute 后转到后端终端看直播:四个步骤依次打印——搜索景点 → 查询天气 → 搜索酒店 → 生成行程计划。全程 1~3 分钟,这是 LLM 多次调用的正常耗时。
✅ Checkpoint 2:响应体是 {"success": true, "message": ..., "data": {...}} 的包装结构,data 里是完整行程:days 数组里每天有 attractions、meals、hotel,外层还有 weather_info、budget 和 overall_suggestions。
常见失败:
- 景点搜索为空 →
AMAP_API_KEY填成了 JS API 的 Key,换成 Web 服务 Key - 返回了兜底计划(内容明显是模板)→ 看终端 Traceback,多半是规划 Agent 输出的 JSON 解析失败,重试一次或换更强的模型
4. 里程碑三:精读后端代码(约 1~2 天)
推荐阅读顺序(每读一个文件,回答括号里的问题):
models/schemas.py(整个系统流转的数据长什么样?TripPlan里有哪些嵌套模型?)config.py(.env里每个变量被谁读走了?)api/routes/trip.py(HTTP 请求进来后,到调用 planner 之间发生了什么?)agents/trip_planner_agent.py⭐ 逐行读,重点: - 四段 system prompt:为什么每段都给[TOOL_CALL:...]的完整示例?(答:让模型照抄格式,提高工具调用成功率) -MCPTool只创建一次、四个 Agent 共享(避免重复启动 MCP 子进程) -_build_planner_query:前三个 Agent 的输出如何拼进第四个的输入 -_parse_response:从 LLM 回复里抠 JSON + 失败兜底_create_fallback_planservices/amap_service.py(哪些高德能力走 MCP、哪些走直接 HTTP?为什么两条路都要?)
✅ Checkpoint 3:合上代码,你能在纸上画出"一次请求从进入到返回"经过的每个文件。
5. 里程碑四:前端跑起来(约半天)
cd ../frontend
npm install
cp .env.example .env
编辑前端 .env,三个变量(注意两个高德 Key 都要填,且和后端那个是三个不同的 Key):
# 后端API地址(本机开发保持默认)
VITE_API_BASE_URL=http://localhost:8000
# 高德地图 Web API Key(与后端 AMAP_API_KEY 相同的那种"Web服务"Key)
VITE_AMAP_WEB_KEY=你的高德Web服务Key
# 高德地图 Web端 JS API Key(地图显示用)
VITE_AMAP_WEB_JS_KEY=你的高德JS API Key
启动(保持后端也在运行,两个终端):
npm run dev
✅ Checkpoint 4:打开 http://localhost:5173,填表单生成计划,等待后跳转结果页:行程卡片、地图打点、天气、预算全部显示。
- 地图空白 →
VITE_AMAP_WEB_JS_KEY填错或和 Web 服务 Key 填反了(浏览器 F12 控制台会有高德的具体报错);改完.env要重启npm run dev才生效 - 请求发不出去/CORS 报错 → 后端
.env的CORS_ORIGINS要包含http://localhost:5173
6. 里程碑五:动手改造(检验真懂了没有)
按难度递增,至少完成前两个:
- 改提示词:让行程规划专家在每天行程里增加一条"拍照打卡建议"。(改
PLANNER_AGENT_PROMPT的 JSON 模板 +schemas.py对应模型 + 前端展示,三处联动——体会"改一个字段要动几个文件") - 加接口:后端加
GET /api/trip/tips?city=xxx,用一个新的 SimpleAgent 返回该城市的 3 条旅行贴士。 - 加 Agent:插入第五个"美食搜索专家"(prompt 仿照酒店专家,keywords 用"美食"),把结果也拼给规划专家。
- 提速:并发化前三步:景点/天气/酒店三个 Agent 互不依赖,却在
plan_trip里串行执行。用concurrent.futures.ThreadPoolExecutor让它们并行跑,总耗时约缩短一半。(规划专家必须等三者都完成,仍在最后) - 换 MCP:把
server_command换成其他 MCP 服务器(如天气类),观察auto_expand展开出的新工具名。
7. 本项目带走的能力
- 多 Agent 顺序流水线的完整实现套路(共享工具、prompt 分工、结果拼接)
- MCP 工具从配置到调用的全链路
- "LLM 输出 JSON → Pydantic 模型 → 前端渲染"的数据管道,以及每一环的容错