第50集:【实战】打造一个能查机票、订酒店、写攻略的旅行规划师
核心知识点讲解
旅行规划师智能体的系统架构
一个完整的旅行规划师智能体需要具备以下核心组件:
- 核心决策引擎:负责理解用户需求,制定旅行计划
- 工具集成层:整合机票查询、酒店预订等外部服务
- 信息处理模块:处理和分析旅行相关信息
- 内容生成模块:创建个性化旅行攻略
- 用户交互界面:提供友好的用户交互体验
技术栈选择
- 框架:LangChain + OpenAI API
- 工具集成:机票API、酒店API、天气API、地图API
- 数据存储:本地缓存 + 向量数据库(可选)
- 前端界面:Streamlit或Gradio(可选)
核心功能模块
- 需求分析:理解用户的旅行目的地、时间、预算等需求
- 航班查询:根据出发地、目的地和日期查询航班信息
- 酒店预订:根据目的地、入住时间和预算查询并预订酒店
- 行程规划:基于目的地景点和用户兴趣制定行程
- 攻略生成:生成详细的旅行攻略,包括景点介绍、交通建议、美食推荐等
- 预算计算:估算整个旅行的费用
实用案例分析
案例:周末上海游规划
场景描述:用户想要在本周末去上海游玩,希望智能体能够:
- 查询从北京到上海的往返机票
- 预订两晚的酒店
- 制定两天的行程
- 生成详细的旅行攻略
- 估算总预算
实现思路:
- 收集用户需求:出发地、目的地、日期、预算、偏好
- 调用机票查询工具获取航班信息
- 调用酒店查询工具获取住宿选项
- 基于目的地信息制定行程
- 生成完整的旅行攻略
- 计算并呈现总预算
代码实现
1. 工具定义与集成
from langchain.tools import BaseTool
from langchain.pydantic_v1 import BaseModel, Field
import requests
import json
import logging
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# 机票查询工具
class FlightSearchInput(BaseModel):
origin: str = Field(description="出发城市机场代码")
destination: str = Field(description="目的地城市机场代码")
departure_date: str = Field(description="出发日期,格式:YYYY-MM-DD")
return_date: str = Field(description="返回日期,格式:YYYY-MM-DD")
adults: int = Field(default=1, description="成人数量")
class FlightSearchTool(BaseTool):
name = "flight_search"
description = "查询航班信息,需要提供出发地、目的地、出发日期、返回日期和成人数量"
args_schema = FlightSearchInput
def _run(self, origin: str, destination: str,
departure_date: str, return_date: str,
adults: int = 1) -> str:
"""查询航班信息"""
try:
# 模拟航班API调用
# 实际项目中应替换为真实的航班API
logger.info(f"查询航班: {origin} -> {destination}, 出发: {departure_date}, 返回: {return_date}")
# 模拟航班数据
flights = {
"departure": [
{
"airline": "中国国航",
"flight_number": "CA1831",
"departure_time": "08:00",
"arrival_time": "10:20",
"price": "¥850"
},
{
"airline": "东方航空",
"flight_number": "MU5138",
"departure_time": "12:30",
"arrival_time": "14:50",
"price": "¥780"
}
],
"return": [
{
"airline": "东方航空",
"flight_number": "MU5137",
"departure_time": "15:30",
"arrival_time": "17:50",
"price": "¥720"
},
{
"airline": "中国国航",
"flight_number": "CA1832",
"departure_time": "19:00",
"arrival_time": "21:20",
"price": "¥800"
}
]
}
return json.dumps(flights, ensure_ascii=False, indent=2)
except Exception as e:
logger.error(f"航班查询失败: {e}")
return f"航班查询失败: {str(e)}"
# 酒店查询工具
class HotelSearchInput(BaseModel):
destination: str = Field(description="目的地城市")
checkin_date: str = Field(description="入住日期,格式:YYYY-MM-DD")
checkout_date: str = Field(description="退房日期,格式:YYYY-MM-DD")
guests: int = Field(default=2, description="入住人数")
budget: str = Field(default="mid", description="预算级别:low, mid, high")
class HotelSearchTool(BaseTool):
name = "hotel_search"
description = "查询酒店信息,需要提供目的地、入住日期、退房日期、人数和预算级别"
args_schema = HotelSearchInput
def _run(self, destination: str, checkin_date: str,
checkout_date: str, guests: int = 2,
budget: str = "mid") -> str:
"""查询酒店信息"""
try:
# 模拟酒店API调用
logger.info(f"查询酒店: {destination}, 入住: {checkin_date}, 退房: {checkout_date}, 人数: {guests}, 预算: {budget}")
# 模拟酒店数据
hotels = [
{
"name": "上海外滩华尔道夫酒店",
"address": "上海市黄浦区中山东一路2号",
"price": "¥2500/晚",
"rating": "5星",
"description": "豪华五星级酒店,位于外滩核心区域,俯瞰黄浦江"
},
{
"name": "上海浦东香格里拉大酒店",
"address": "上海市浦东新区富城路33号",
"price": "¥1800/晚",
"rating": "5星",
"description": "豪华酒店,位于陆家嘴金融区,视野开阔"
},
{
"name": "上海静安瑞吉酒店",
"address": "上海市静安区北京西路1008号",
"price": "¥1500/晚",
"rating": "5星",
"description": "高端酒店,位于市中心,交通便利"
}
]
# 根据预算过滤酒店
if budget == "low":
hotels = [h for h in hotels if int(h["price"].replace("¥", "").split("/")[0]) < 1000]
elif budget == "high":
hotels = [h for h in hotels if int(h["price"].replace("¥", "").split("/")[0]) > 2000]
return json.dumps(hotels, ensure_ascii=False, indent=2)
except Exception as e:
logger.error(f"酒店查询失败: {e}")
return f"酒店查询失败: {str(e)}"
# 天气查询工具
class WeatherSearchInput(BaseModel):
city: str = Field(description="城市名称")
date: str = Field(description="查询日期,格式:YYYY-MM-DD")
class WeatherSearchTool(BaseTool):
name = "weather_search"
description = "查询城市天气信息,需要提供城市名称和日期"
args_schema = WeatherSearchInput
def _run(self, city: str, date: str) -> str:
"""查询天气信息"""
try:
# 模拟天气API调用
logger.info(f"查询天气: {city}, 日期: {date}")
# 模拟天气数据
weather = {
"city": city,
"date": date,
"temperature": "18-25°C",
"condition": "晴转多云",
"humidity": "60%",
"wind": "东北风3级",
"suggestion": "天气适宜出行,建议携带轻便衣物"
}
return json.dumps(weather, ensure_ascii=False, indent=2)
except Exception as e:
logger.error(f"天气查询失败: {e}")
return f"天气查询失败: {str(e)}"2. 智能体构建
from langchain.agents import initialize_agent, AgentType
from langchain.chat_models import ChatOpenAI
from langchain.memory import ConversationBufferMemory
import os
# 设置API密钥
os.environ["OPENAI_API_KEY"] = "your-openai-api-key"
# 初始化工具
flight_tool = FlightSearchTool()
travel_tools = [flight_tool, HotelSearchTool(), WeatherSearchTool()]
# 初始化LLM
llm = ChatOpenAI(temperature=0.7, model="gpt-3.5-turbo-16k")
# 初始化记忆
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
# 初始化智能体
travel_agent = initialize_agent(
tools=travel_tools,
llm=llm,
agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION,
memory=memory,
verbose=True,
agent_kwargs={
"system_message": "你是一个专业的旅行规划师,能够帮助用户查询机票、预订酒店、了解天气情况,并生成详细的旅行攻略。请根据用户的需求,提供专业、贴心的旅行建议。"
}
)
# 测试智能体
response = travel_agent.run("我想在本周末(5月13-14日)从北京去上海玩,预算3000元,帮我规划一下行程。")
print(response)3. 攻略生成模块
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
# 攻略生成提示词
itinerary_template = """
你是一位专业的旅行攻略作家,请根据以下信息为用户生成一份详细的旅行攻略:
目的地:{destination}
旅行日期:{start_date} 至 {end_date}
预算:{budget}
用户偏好:{preferences}
攻略应包含以下内容:
1. 行程概览
2. 详细的每日行程安排(包括景点、交通、餐饮建议)
3. 交通指南(如何在城市内出行)
4. 美食推荐(当地特色美食和推荐餐厅)
5. 住宿建议
6. 购物指南
7. 注意事项和旅行提示
8. 预算明细
请确保攻略内容详细、实用,并且符合用户的预算和偏好。
"""
# 创建提示词模板
itinerary_prompt = PromptTemplate(
input_variables=["destination", "start_date", "end_date", "budget", "preferences"],
template=itinerary_template
)
# 创建攻略生成链
itinerary_chain = LLMChain(llm=llm, prompt=itinerary_prompt)
# 生成攻略
def generate_itinerary(destination, start_date, end_date, budget, preferences):
"""生成旅行攻略"""
try:
logger.info(f"生成{destination}的旅行攻略")
result = itinerary_chain.run(
destination=destination,
start_date=start_date,
end_date=end_date,
budget=budget,
preferences=preferences
)
return result
except Exception as e:
logger.error(f"攻略生成失败: {e}")
return f"攻略生成失败: {str(e)}"
# 测试攻略生成
itinerary = generate_itinerary(
destination="上海",
start_date="2024-05-13",
end_date="2024-05-14",
budget="3000元",
preferences="喜欢历史文化景点和美食"
)
print(itinerary)4. 完整的旅行规划师集成
class TravelPlanner:
"""旅行规划师类"""
def __init__(self):
# 初始化工具和智能体
self.flight_tool = FlightSearchTool()
self.hotel_tool = HotelSearchTool()
self.weather_tool = WeatherSearchTool()
self.tools = [self.flight_tool, self.hotel_tool, self.weather_tool]
# 初始化LLM
self.llm = ChatOpenAI(temperature=0.7, model="gpt-3.5-turbo-16k")
# 初始化记忆
self.memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
# 初始化智能体
self.agent = initialize_agent(
tools=self.tools,
llm=self.llm,
agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION,
memory=self.memory,
verbose=True,
agent_kwargs={
"system_message": "你是一个专业的旅行规划师,能够帮助用户查询机票、预订酒店、了解天气情况,并生成详细的旅行攻略。请根据用户的需求,提供专业、贴心的旅行建议。"
}
)
# 初始化攻略生成链
self.itinerary_prompt = PromptTemplate(
input_variables=["destination", "start_date", "end_date", "budget", "preferences"],
template=itinerary_template
)
self.itinerary_chain = LLMChain(llm=self.llm, prompt=self.itinerary_prompt)
def plan_trip(self, user_query):
"""规划旅行"""
try:
# 1. 理解用户需求
logger.info(f"处理用户请求: {user_query}")
# 2. 使用智能体处理请求
agent_response = self.agent.run(user_query)
# 3. 提取关键信息(这里简化处理,实际项目中需要更复杂的信息提取)
# 示例:从用户查询中提取目的地、日期、预算等信息
# 实际项目中可以使用NLP技术或结构化输出解析
# 4. 生成详细攻略
# 这里假设我们已经提取了关键信息
itinerary = self.itinerary_chain.run(
destination="上海",
start_date="2024-05-13",
end_date="2024-05-14",
budget="3000元",
preferences="喜欢历史文化景点和美食"
)
# 5. 整合结果
final_response = f"{agent_response}\n\n=== 详细旅行攻略 ===\n{itinerary}"
return final_response
except Exception as e:
logger.error(f"旅行规划失败: {e}")
return f"旅行规划失败: {str(e)}"
# 测试完整的旅行规划师
planner = TravelPlanner()
result = planner.plan_trip("我想在本周末(5月13-14日)从北京去上海玩,预算3000元,帮我规划一下行程。")
print(result)代码分析
关键技术点
工具集成:
- 封装外部API调用为LangChain工具
- 处理API响应和错误
- 提供标准化的输入输出格式
智能体设计:
- 使用CHAT_CONVERSATIONAL_REACT_DESCRIPTION代理类型
- 结合记忆功能实现上下文理解
- 设计专业的系统提示词
攻略生成:
- 使用专门的提示词模板
- 结构化输出详细的旅行攻略
- 考虑用户偏好和预算约束
信息提取:
- 从用户查询中提取关键信息
- 处理不完整或模糊的用户需求
- 填充默认值和合理假设
高级技巧
1. 多工具协同策略
- 工具选择逻辑:根据用户需求自动选择合适的工具
- 工具调用顺序:先查询航班和酒店,再根据结果生成攻略
- 结果整合:将多个工具的结果整合为统一的旅行方案
2. 个性化推荐
- 用户画像:基于历史交互构建用户偏好模型
- 兴趣匹配:根据用户兴趣推荐相关景点和活动
- 季节性建议:根据旅行时间提供季节性建议
3. 实时数据集成
- API集成:整合真实的航班、酒店、天气API
- 数据缓存:缓存频繁查询的结果,提高响应速度
- 价格监控:监控航班和酒店价格变动,提供最优选择
4. 多语言支持
- 语言检测:自动检测用户语言
- 多语言响应:支持多语言旅行攻略生成
- 本地化建议:提供符合当地文化的旅行建议
最佳实践
工具设计最佳实践
- 参数标准化:为所有工具定义清晰的参数结构
- 错误处理:为每个工具实现完善的错误处理机制
- 结果格式化:统一工具返回格式,便于智能体处理
- 超时设置:为API调用设置合理的超时时间
代码实现最佳实践
- 模块化设计:将不同功能模块分离为独立组件
- 配置外部化:将API密钥和配置信息外部化
- 日志记录:实现详细的日志记录,便于调试和监控
- 性能优化:使用异步调用处理多个API请求
工具使用最佳实践
- 上下文感知:根据对话历史理解用户需求
- 主动追问:当信息不足时,主动向用户追问
- 多方案对比:提供多个旅行方案供用户选择
- 用户反馈:收集用户对旅行规划的反馈,持续改进
部署与安全最佳实践
- API密钥保护:使用环境变量或密钥管理服务存储API密钥
- 速率限制:遵守API提供商的速率限制,避免被封禁
- 数据隐私:保护用户的个人信息和旅行计划
- 系统监控:监控系统运行状态,及时发现和解决问题
常见问题与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| API调用失败 | 网络问题或API密钥无效 | 实现重试机制,提供友好的错误提示 |
| 信息提取不准确 | 用户输入模糊或不完整 | 主动追问用户,使用默认值填充缺失信息 |
| 攻略生成质量低 | 提示词不够详细 | 优化提示词模板,提供更具体的生成指导 |
| 系统响应缓慢 | 多个API调用串行执行 | 使用异步编程,并行处理多个API请求 |
| 预算估算不准确 | 缺少实时价格数据 | 集成实时价格API,定期更新价格信息 |
未来发展趋势
- 多模态旅行规划:结合图片、视频等多模态信息提供更丰富的旅行建议
- 智能行程调整:根据实时天气、交通状况自动调整行程
- 社交化旅行规划:支持多人协作规划旅行,整合不同人的偏好
- AR导航集成:结合AR技术提供实时导航和景点介绍
- 个性化推荐系统:基于用户行为和偏好的智能推荐
总结
本集通过实战案例,详细介绍了如何构建一个集成机票查询、酒店预订和旅行攻略生成功能的AI旅行规划师智能体。我们从工具定义、智能体构建到攻略生成,实现了一个完整的旅行规划系统。
在实现过程中,我们学习了多工具集成、错误处理、上下文理解等关键技术,以及模块化设计、配置管理等最佳实践。这些技术和实践不仅适用于旅行规划场景,也可以推广到其他需要多工具协作的智能体应用中。
随着API集成技术的不断发展和LLM能力的提升,旅行规划师智能体将变得越来越智能和个性化,为用户提供更加贴心、专业的旅行规划服务。未来,我们可以进一步扩展其功能,如整合更多服务、提供实时行程调整、支持多语言等,打造一个真正智能的旅行助手。
思考与练习:
- 尝试集成真实的航班和酒店API,替换模拟数据
- 为旅行规划师添加景点推荐功能
- 实现一个简单的前端界面,提供可视化的旅行规划体验
- 扩展系统支持多目的地旅行规划
扩展阅读:
- LangChain工具集成文档
- 航班和酒店API使用指南
- 旅行规划应用的用户体验设计
- 多工具协作智能体的设计模式