1. 项目概述
今天我要分享一个很有意思的项目:使用SKILL+MCP技术栈构建一个智能旅行规划Agent。这个项目完美结合了大语言模型的决策能力和外部工具的执行能力,能够根据用户需求生成个性化的旅行计划。
作为一名经常需要出差和旅行的开发者,我深知规划行程的痛点:需要查询航班、酒店、景点等各种信息,还要考虑时间安排和预算控制。这个项目正是为了解决这些问题而设计的。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心技术解析
2.1 SKILL与MCP架构设计
这个项目的核心架构基于两个关键概念:SKILL和MCP。让我用开发者的视角来解释一下它们的区别:
-
SKILL(技能):相当于AI的"大脑",定义了AI在特定场景下的思考方式和行为模式。在我们的旅行规划场景中,SKILL规定了如何分析用户需求、如何调用工具、如何整合信息等逻辑流程。
-
MCP(模型上下文协议):相当于AI的"手和眼",提供了访问外部数据和执行具体操作的能力。在我们的项目中,MCP封装了航班查询、酒店搜索、天气获取等具体工具接口。
这种架构设计的优势在于:
- 将决策逻辑(SKILL)与具体实现(MCP)解耦
- 可以独立扩展SKILL或MCP而不影响对方
- 便于复用和组合不同的SKILL和MCP
2.2 技术栈选型
项目采用了以下技术栈:
- Python 3.8+:作为主要开发语言
- OpenAI API:使用GPT-4模型作为核心决策引擎
- MCP框架:用于构建和管理工具接口
- Pydantic:用于数据验证和模型定义
- asyncio:实现异步工具调用
- httpx:用于HTTP请求
选择这些技术的主要考虑:
- Python生态丰富,适合快速开发AI应用
- OpenAI API提供了强大的语言理解能力
- MCP框架专门为工具调用场景设计
- 异步架构提高系统响应速度
3. 核心实现细节
3.1 项目目录结构
code复制travel_agent/
├── skills/ # 技能定义
│ └── travel_plan/ # 旅行规划技能
│ └── SKILL.md # 技能说明文档
├── mcp_servers/ # MCP服务实现
│ └── travel_tools/ # 旅行相关工具
│ ├── __init__.py
│ ├── server.py # 工具服务实现
│ └── run_server.py # 服务启动脚本
├── llm_client.py # LLM客户端封装
├── main.py # 主程序入口
└── requirements.txt # 依赖文件
3.2 SKILL定义实现
SKILL定义在skills/travel_plan/SKILL.md中,它规定了旅行规划Agent的行为模式:
markdown复制# 智能旅行规划技能
你是一位专业的旅行规划师,擅长根据用户需求制定个性化旅行计划。
## 核心能力
- 分析用户旅行需求(目的地、时间、预算、兴趣)
- 智能调用相关工具获取实时信息
- 整合多源数据生成最优旅行方案
## 规划流程
1. 分析用户需求 → 确定关键参数
2. 调用航班工具 → 搜索最佳航班
3. 调用酒店工具 → 筛选合适住宿
4. 调用天气工具 → 考虑天气因素
5. 调用景点工具 → 安排每日行程
6. 整合信息 → 生成完整旅行计划
## 输出要求
- 包含航班、酒店、天气、景点等完整信息
- 按天安排行程,考虑地理位置和时间合理性
- 提供预算估算和实用建议
- 对特殊需求(如亲子、老人)给予特别考虑
- 严格使用MCP工具中的数据,不准捏造或者参考历史数据
3.3 MCP工具服务实现
MCP工具服务在mcp_servers/travel_tools/server.py中实现,提供了四个核心工具:
- 航班搜索工具:根据出发地、目的地和日期查询航班信息
- 酒店搜索工具:根据城市、入住和离店日期查询酒店信息
- 天气预报工具:获取指定城市和日期的天气情况
- 景点搜索工具:按类别查询城市景点信息
每个工具都定义了输入参数模型,例如:
python复制class SearchFlightsParams(BaseModel):
departure_city: str
arrival_city: str
date: str
class SearchHotelsParams(BaseModel):
city: str
check_in_date: str
check_out_date: str
工具调用采用异步方式实现,确保系统响应速度:
python复制@server.call_tool()
async def call_tool(tool_name: str, arguments: dict):
try:
if tool_name == "search_flights":
# 处理航班查询逻辑
pass
elif tool_name == "search_hotels":
# 处理酒店查询逻辑
pass
# 其他工具处理...
except Exception as e:
return [TextContent(type="text", text=f"工具调用失败: {str(e)}")]
3.4 LLM客户端实现
LLM客户端封装在llm_client.py中,主要职责是:
- 初始化OpenAI客户端
- 构建系统提示词(包含SKILL和可用工具信息)
- 调用GPT模型生成旅行计划
核心代码如下:
python复制class LLMClient:
def __init__(self, api_key=None, base_url=None, model="gpt-4"):
self.client = OpenAI(
api_key=api_key or os.getenv("OPENAI_API_KEY"),
base_url=base_url or os.getenv("OPENAI_BASE_URL")
)
self.model = model
async def plan_travel(self, user_request: str, available_tools: List[Dict]) -> str:
system_prompt = self._build_system_prompt(available_tools)
response = self.client.chat.completions.create(
model=self.model,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_request}
],
temperature=0.3
)
return response.choices[0].message.content
4. 系统运行流程
4.1 启动流程
- 初始化LLM客户端和MCP服务器
- 列出所有可用工具
- 将工具信息传递给LLM
- LLM根据SKILL生成规划流程
- 执行规划流程并调用相应工具
- 整合工具返回结果生成最终报告
4.2 核心执行代码
主程序在main.py中实现:
python复制class LLMSkillsMCPDemo:
def __init__(self):
self.llm_client = LLMClient()
async def run(self, user_request: str):
# 1. 启动MCP服务器
server_params = StdioServerParameters(
command="python",
args=["run_server.py"]
)
async with stdio_client(server_params) as (read_stream, write_stream):
async with ClientSession(read_stream, write_stream) as session:
await session.initialize()
# 2. 获取可用工具
tools_result = await session.list_tools()
available_tools = [{"name": tool.name, "description": tool.description}
for tool in tools_result.tools]
# 3. LLM智能规划
travel_plan = await self.llm_client.plan_travel(user_request, available_tools)
# 4. 执行计划
final_report = await self._execute_plan(travel_plan, session)
return final_report
4.3 示例运行结果
当用户输入以下请求时:
code复制我想规划一个3天2晚的上海之旅,时间定在2月15日-17日。
预算大概3000元左右,希望住在市中心交通方便的地方。
我对文化历史景点比较感兴趣,还想体验当地美食。
请帮我制定一个详细的旅行计划。
系统会生成如下报告:
code复制🌟 智能旅行规划完成!
以下是基于你的需求生成的个性化旅行计划:
### 上海文化美食三日游个性化计划 (2025年2月15日-17日)
#### 一、 行程概览
* 主题:海派文化寻踪与舌尖体验
* 天数:3天2晚
* 核心区域:黄浦区、徐汇区
* 天气提示:根据预报,2月15日多云,16-17日有小雨...
#### 二、 每日详细行程安排
第一天:城市脉络·外滩万国建筑博览
- 上午:抵达上海,入住酒店
- 下午:上海博物馆
- 晚上:外滩夜景
第二天:法租界漫步·文艺与小资
- 上午:徐家汇天主教堂
- 下午:衡复历史文化风貌区
- 晚上:新天地
第三天:老城厢记忆·告别之旅
- 上午:豫园及城隍庙
- 下午:根据时间自由活动
#### 三、 预算估算
* 住宿:1000元
* 餐饮:450元
* 交通:45元
* 景点门票:50元
* 总预算:约2645-3045元
#### 四、 实用建议
1. 下载"Metro大都会"APP方便乘坐地铁
2. 热门场馆提前预约
3. 尝试本地特色小吃
4. 注意2月上海湿冷天气
5. 开发经验与优化建议
5.1 开发中遇到的挑战
-
工具调用稳定性:初期工具调用经常超时或失败
- 解决方案:增加重试机制和超时设置
- 代码示例:
python复制async def call_tool_with_retry(tool_name, arguments, max_retries=3): for attempt in range(max_retries): try: return await call_tool(tool_name, arguments) except Exception as e: if attempt == max_retries - 1: raise await asyncio.sleep(1 * (attempt + 1))
-
LLM输出格式不一致:LLM生成的报告格式经常变化
- 解决方案:在SKILL中严格定义输出格式,并在prompt中提供示例
- 优化后的prompt部分:
code复制
## 输出格式要求 请严格按照以下格式生成报告: ### 行程概览 [概要描述] ### 每日详细安排 [按天详细安排] ### 预算估算 [详细预算] ### 实用建议 [实用提示]
-
工具参数验证不足:初期经常收到无效参数
- 解决方案:使用Pydantic严格验证输入参数
- 示例:
python复制class SearchFlightsParams(BaseModel): departure_city: str = Field(..., min_length=2) arrival_city: str = Field(..., min_length=2) date: str = Field(..., regex=r'^\d{4}-\d{2}-\d{2}$')
5.2 性能优化技巧
-
并行工具调用:当多个工具调用没有依赖关系时,使用asyncio.gather并行执行
python复制async def get_travel_info(city, date): hotel_task = search_hotels(city, date) weather_task = get_weather(city, date) hotels, weather = await asyncio.gather(hotel_task, weather_task) return hotels, weather -
LLM调用缓存:对相似的请求使用缓存,减少API调用
python复制from functools import lru_cache @lru_cache(maxsize=100) async def plan_travel_cached(user_request: str, tools_json: str): return await plan_travel(user_request, json.loads(tools_json)) -
工具结果预处理:在工具端对数据进行预处理,减少传输量和LLM处理负担
python复制async def search_hotels(city, date): raw_data = await fetch_hotel_data(city, date) # 预处理:只保留关键字段,排序,过滤异常值 processed = process_hotel_data(raw_data) return processed
5.3 扩展建议
-
增加更多工具类型:
- 餐厅推荐工具
- 交通路线规划工具
- 当地活动查询工具
-
支持多语言:
- 根据用户语言偏好自动切换输出语言
- 示例实现:
python复制async def plan_travel(user_request, tools, language="zh"): prompt = build_prompt(tools, language) # 其余逻辑不变
-
增加用户偏好学习:
- 记录用户历史选择和反馈
- 在后续规划中优先推荐相似选项
-
实现渐进式规划:
- 先提供大纲让用户确认
- 再逐步填充细节
- 最后生成完整报告
6. 部署与使用指南
6.1 环境准备
- 安装Python 3.8+
- 安装依赖库:
bash复制
pip install openai mcp httpx pydantic asyncio - 设置OpenAI API密钥:
bash复制export OPENAI_API_KEY='your-api-key'
6.2 启动服务
- 启动MCP工具服务:
bash复制
python -m mcp_servers.travel_tools.server - 运行主程序:
bash复制
python main.py
6.3 接口调用示例
可以通过修改main.py中的用户请求来测试不同场景:
python复制user_request = """
我想规划一个5天4晚的北京之旅,
时间定在10月1日-5日。
预算5000元左右,希望住在故宫附近。
对历史文化和传统美食感兴趣。
请帮我制定一个详细的旅行计划。
"""
6.4 容器化部署
建议使用Docker容器化部署:
dockerfile复制FROM python:3.8-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["python", "main.py"]
构建和运行:
bash复制docker build -t travel-agent .
docker run -e OPENAI_API_KEY=your_key travel-agent
7. 项目总结与展望
这个项目展示了如何将大语言模型与专业工具结合,构建实用的智能应用。通过SKILL+MCP的架构,我们实现了:
- 清晰的职责分离:SKILL负责决策,MCP负责执行
- 灵活的扩展能力:可以轻松添加新的SKILL或MCP工具
- 可靠的实际应用:生成的旅行计划具有实际可操作性
在实际使用中,这个系统已经能够处理大多数常规的旅行规划需求。测试表明,对于3-5天的国内旅行规划,系统生成的方案在合理性和实用性上已经接近专业旅行顾问的水平。
未来可以考虑从以下几个方向进行增强:
- 实时数据集成:接入真实的航班、酒店API,而不是使用模拟数据
- 多模态输出:除了文本报告,还可以生成地图标记、行程图表等
- 交互式规划:支持用户中途调整需求,系统实时更新方案
- 个性化推荐:基于用户历史偏好提供更精准的建议
这个项目的代码已经具备了良好的扩展性,要实现这些增强功能,主要工作是开发新的MCP工具和优化SKILL定义,而核心架构可以保持不变。
