# TravelMind — 多角色智能旅行规划系统 TravelMind 是一个基于 **LangGraph 多角色 Agent 工作流** 的智能行程规划系统:用户用自然语言描述旅行需求(出发地、目的地、日期、预算、偏好等),系统自动完成需求解析、航班/酒店资源查询、目的地地图研究、行程编排、风险评审与迭代优化,最终输出结构化多日行程。 > 项目名中的 "Mind" 取自 *multi-agent mind*:多个各司其职的 Agent 以 Supervisor 模式协同工作,像一支"思维团队"一样规划行程。 ## ✨ 核心特性 - **自然语言直接规划**:输入"帮我规划 6 月下旬从北京去东京玩 5 天,预算 1.5 万以内",即可获得完整行程方案 - **多角色 Agent 协作**:需求解析、资源查询、地图研究、行程规划、行程评审 5 个 Agent 分工协作 - **Supervisor 迭代评审**:规划结果经过确定性校验与独立评审,不合格自动重新规划(带重试上限,避免死循环) - **真实数据查询**:航班/酒店走 **SerpApi Google Flights/Hotels**,景点/餐饮/天气走 **高德地图官方 MCP** - **MCP 标准化接入**:自建航班/酒店搜索 MCP 服务器(FastMCP),与外部高德 MCP 统一接入 - **防编造设计**:候选筛选、路线评估、计划校验等环节使用**确定性代码**而非 LLM,保证 ID、日期、价格等信息的真实性,防止模型编造航班、酒店、景点和价格 - **模型无关**:兼容 OpenAI 及其兼容服务(DeepSeek、通义千问等),仅需配置 `MODEL_BASE_URL` ## 🏗️ 架构总览 系统采用 **LangGraph 状态图** 编排完整工作流,Supervisor 在关键节点做路由决策: ``` 用户需求 │ ▼ ┌──────────────┐ 澄清/报错(条件路由) ┌──────────────────┐ │ 需求解析Agent │ ─────────────────────► │ 补充需求/终止 │ └──────┬───────┘ └──────────────────┘ │ TravelRequest(结构化) ▼ ┌──────────────┐ 高德 MCP 工具 ┌──────────────────┐ │ 资源查询Agent │ ─────────────────────► │ 地图研究Agent │ │ 航班/酒店 │ │ 景点/餐饮/天气 │ └──────┬───────┘ └────────┬─────────┘ │ 候选资源 │ POI 数据 ▼ ▼ ┌──────────────────────────────────────────────────────────────┐ │ 候选筛选 → 路线评估 → 行程规划Agent │ │ (生成结构化多日行程) │ └──────────────────────┬───────────────────────────────────────┘ │ ▼ ┌──────────────────┐ 未通过(重新规划循环) ┌──────────────┐ │ 校验 → 评审Agent │ ◄────────────────────── │ Supervisor │ └──────┬───────────┘ │ (路由决策) │ │ 通过 └──────────────┘ ▼ ┌──────────────────┐ │ 最终定稿/输出 │ └──────────────────┘ ``` 工作流环节:**需求解析 → 资源查询 → 候选筛选 → 地图研究 → 路线评估 → 行程规划 → 校验 → 评审 → 最终定稿**,其中规划/评审环节存在带重试上限的迭代循环(`recursion_limit = 80`)。 ### 角色分工 | Agent | 职责 | |-------|------| | **RequirementAgent** 需求解析 | 把自然语言转换为结构化 `TravelRequest`,意图识别与字段提取(仅解析,不规划);缺字段时走澄清流程 | | **ResourceSearchAgent** 资源查询 | 调用航班/酒店 MCP 工具搜索外部资源,指导工具调用顺序并汇总为结构化结果 | | **MapResearchAgent** 地图研究 | 调用高德地图 MCP 工具,搜索目的地周边景点、餐饮与天气,返回结构化 POI 数据 | | **ItineraryPlannerAgent** 行程规划 | 基于候选资源与地图研究结果,生成包含每日活动安排的结构化多日行程 | | **TripReviewerAgent** 行程评审 | 从风险控制角度独立评审,识别节奏、地理、预算等维度的问题并给出修改意见 | | **Supervisor** 监督协调 | 汇总校验与评审意见,决定 `replan` / `finalize` / `finalize_with_risks` / `terminate` | ### 确定性模块(不使用 LLM) 以下环节刻意使用确定性代码,保证准确性与成本控制: | 模块 | 原因 | |------|------| | Candidate Selector | 排序和过滤规则确定 | | Route Evaluator | 距离和评分可确定性计算 | | Plan Validator | ID、日期、预算必须准确 | | Finalizer | 防止最终展示阶段重新编造信息 | LLM 只负责自然语言理解、复杂取舍、行程编排和体验审查。 ### MCP 集成 通过 `langchain-mcp-adapters` 的 `MultiServerMCPClient` 同时接入两个 MCP 服务器: 1. **travel_search(自建)**:stdio 传输,`mcp_servers/travel_search_server.py`(FastMCP)包装 `TravelSearchService`,提供 `search_airports`、`search_flights`、`search_return_flights`、`search_hotels` 工具,底层调用 SerpApi 2. **amap(高德官方)**:Streamable HTTP 传输,`https://mcp.amap.com/mcp`,提供 `maps_*` 系列工具(POI 搜索、餐饮、天气、距离测量、路线规划等) ## 🛠️ 技术栈 - **Python ≥ 3.10**,[uv](https://docs.astral.sh/uv/) 包管理 - **LangChain 1.x / LangGraph**:Agent 与状态图编排 - **langchain-openai**:统一模型接入(OpenAI / DeepSeek / Qwen 等) - **langchain-mcp-adapters + mcp**:MCP 客户端与自建 MCP 服务器(FastMCP) - **httpx**:SerpApi HTTP 调用(支持 SOCKS 代理) - **pydantic / pydantic-settings**:数据模型与配置管理 - **rich**:终端输出美化 - **pytest**:单元测试 ## 🚀 快速开始 ### 1. 环境准备 需要 [uv](https://docs.astral.sh/uv/) 包管理器(或使用任意虚拟环境工具): ```bash # 进入项目目录并安装依赖(自动创建 .venv) uv sync ``` ### 2. 配置环境变量 ```bash cp .env.example .env ``` 编辑 `.env`,填写以下必填项(`app/config.py` 会从项目根目录 `.env` 读取,缺配置时会给出明确错误): | 变量 | 说明 | 必填 | |------|------|------| | `MODEL_API_KEY` | OpenAI 或兼容服务的 API Key | ✅ | | `MODEL_NAME` | 模型名,如 `gpt-4.1-mini`、`qwen-plus`、`deepseek-chat` | ✅ | | `MODEL_BASE_URL` | OpenAI 官方接口可留空;兼容接口填对应 Base URL | 视服务 | | `SERPAPI_API_KEY` | SerpApi 密钥(Google Flights/Hotels 搜索) | ✅ | | `AMAP_API_KEY` | 高德开放平台密钥(MCP 地图服务) | ✅ | | `REQUEST_TIMEOUT_SECONDS` | 请求超时(秒),默认 `120` | 否 | > ⚠️ `.env` 包含敏感密钥,已被 `.gitignore` 排除,**切勿提交到版本库**。密钥缺失时,`Settings.require()` 会抛出带具体变量名的错误。 ### 3. 运行 支持两种输入方式: ```bash # 方式一:命令行参数直接传入 uv run python main.py 帮我规划6月下旬从北京去东京玩5天,预算1.5万以内 # 方式二:交互式输入(支持多行,输入空行结束) uv run python main.py ``` 运行结束后会输出最终行程方案与执行状态(trace_id、各环节执行次数、Supervisor 决策、总耗时等)。 ## 🧪 测试 ```bash # 运行全部单元测试 uv run pytest # 或使用自动化回归入口(只跑本地单元测试) uv run python -m scripts.run_regression # 真实接口集成测试(会调用真实模型、SerpApi 和高德 MCP,可能产生费用) uv run python -m scripts.run_regression --integration ``` ## 📁 项目结构 ``` travel-mind/ ├── main.py # CLI 入口:读取需求并执行完整工作流 ├── pyproject.toml # 项目配置与依赖(uv) ├── .env.example # 环境变量模板(.env 不入库) ├── app/ │ ├── config.py # pydantic-settings 配置中心(读取 .env) │ ├── llm.py # 大模型工厂(兼容 OpenAI/DeepSeek/Qwen) │ ├── mcp_client.py # MCP 工具加载器(自建 + 高德双服务器) │ ├── agents/ # 五个角色 Agent │ │ ├── requirement_agent.py # 需求解析 │ │ ├── resource_agent.py # 资源查询 │ │ ├── map_agent.py # 地图研究 │ │ ├── itinerary_agent.py # 行程规划 │ │ └── reviewer_agent.py # 行程评审 │ ├── graph/ # LangGraph 工作流(builder + nodes + state) │ │ ├── planner_builder.py # 完整主图编排 │ │ ├── supervisor_nodes.py # 监督协调与路由 │ │ └── ... # 各环节节点 │ ├── schemas/ # Pydantic 数据模型(航班/酒店/行程/路线…) │ ├── services/ # 业务服务(搜索/筛选/评估/校验/定稿) │ ├── clients/ │ │ └── serpapi_client.py # SerpApi HTTP 客户端 │ └── logging_config.py # 日志与 trace_id ├── mcp_servers/ │ └── travel_search_server.py # 自建旅行搜索 MCP 服务器(FastMCP) ├── scripts/ # 各环节调试脚本 + 回归测试入口 └── tests/ # pytest 单元测试 ``` ## 📌 当前限制 该项目是生产架构导向的可运行 MVP,而不是已上线商业系统: - 航班和酒店数据用于查询与规划,不执行真实预订 - 航班接口报价的计价范围需以供应商页面为准 - 部分未来日期无法查询准确天气 - 未完整覆盖门票、餐饮和市内交通价格 - 没有数据库和长期会话持久化 - 没有针对大规模并发进行压力测试 - MCP 和第三方 API 失效时的降级能力仍可增强 ## 🔭 生产化方向 - FastAPI 服务接口 - Redis 缓存与限流 - LangGraph Checkpointer 持久化 - 用户会话管理 - MCP 超时、熔断和降级 - OpenTelemetry 链路追踪 - Agent 调用成本统计 - Prompt 和工作流评测集 - Docker 与 CI/CD - 多供应商数据源切换 ## 📄 许可 个人学习/作业项目,未指定开源许可证。