1. 项目概述:智能旅行规划系统的技术实现
这个基于LangChain的旅游规划与应急助手Agent,本质上是一个融合了大语言模型推理能力与实时数据获取的动态决策系统。我在实际开发中发现,传统旅游推荐系统最大的痛点在于静态化——一旦生成行程就无法应对天气突变、交通管制等突发状况。而这个系统的创新点在于构建了一个闭环反馈机制:通过实时工具调用获取外部数据,再基于Pydantic模型的结构化输出能力进行动态调整。
从技术架构上看,系统主要由三个核心模块组成:
- 智能体引擎(agent.py):负责对话管理、工具调度和决策逻辑
- 数据模型(models.py):使用Pydantic定义行程、活动等数据结构
- 工具集(tools.py):封装各类实时API调用接口
关键设计原则:所有工具调用都遵循"必要才调用"的原则,通过大语言模型先分析用户意图,再决定是否需要获取实时数据。这能有效降低API调用次数和响应延迟。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境配置与依赖安装
2.1 基础环境准备
建议使用Python 3.9+环境,以下是必须安装的核心依赖包:
bash复制pip install langchain langchain-core pydantic requests python-dotenv
对于需要更高性能的场景,可以额外安装:
bash复制pip install langchain-experimental # 包含最新实验性功能
2.2 API密钥配置
系统需要配置以下API密钥(在项目根目录创建.env文件):
code复制DEEPSEEK_API_KEY=your_api_key_here
WEATHER_API_KEY=your_weather_provider_key
MAPS_API_KEY=your_maps_provider_key
安全提示:永远不要将API密钥直接硬编码在代码中。我习惯在.gitignore中添加.env条目,防止误提交敏感信息。
3. 核心数据模型设计
3.1 行程数据结构(Itinerary)
在models.py中定义的行程模型是整个系统的基础:
python复制from pydantic import BaseModel
from datetime import datetime
from typing import List, Optional
class Activity(BaseModel):
name: str
location: str
start_time: datetime
end_time: datetime
category: str # e.g. "历史文化","美食","自然风光"
indoor_status: bool
priority: int = 1
class Itinerary(BaseModel):
date: datetime
city: str
activities: List[Activity]
emergency_contacts: Optional[List[str]] = None
这个设计有几个精妙之处:
- 明确区分室内/室外活动(indoor_status字段),为天气应急调整提供基础
- 优先级字段(priority)允许系统在需要删减活动时做出合理选择
- 所有时间字段使用datetime类型,便于后续进行时间冲突检测
3.2 用户偏好模型
系统通过专门的UserPreference模型捕获个性化需求:
python复制class UserPreference(BaseModel):
interests: List[str] # 兴趣标签
physical_ability: str # 体力等级
budget_level: str # 预算等级
dietary_restrictions: Optional[List[str]] = None
4. 工具集实现细节
4.1 实时天气查询工具
在tools.py中实现的天气查询工具演示了如何封装外部API:
python复制import requests
from typing import Dict
def get_current_weather(location: str) -> Dict:
"""获取指定地点的实时天气数据"""
base_url = "https://api.weatherapi.com/v1/current.json"
params = {
'key': os.getenv('WEATHER_API_KEY'),
'q': location,
'aqi': 'no'
}
response = requests.get(base_url, params=params)
data = response.json()
return {
"location": data["location"]["name"],
"condition": data["current"]["condition"]["text"],
"temp_c": data["current"]["temp_c"],
"precip_mm": data["current"]["precip_mm"],
"is_day": data["current"]["is_day"] == 1
}
实战经验:天气API的响应时间直接影响系统流畅度。建议添加缓存机制,对同一地点5分钟内的重复查询直接返回缓存结果。
4.2 交通状况检查工具
交通工具的实现展示了多数据源整合:
python复制def check_traffic(origin: str, destination: str) -> Dict:
"""检查两点间的实时交通状况"""
# 获取路线规划数据
route_data = get_route_from_maps(origin, destination)
# 获取实时交通事件
incidents = get_traffic_incidents(origin, destination)
return {
"distance_km": route_data["distance"],
"duration_min": route_data["duration"],
"traffic_level": route_data["traffic_level"],
"incidents": incidents
}
5. 智能体核心逻辑实现
5.1 工具绑定与初始化
在agent.py中,智能体的初始化过程展示了LangChain的强大集成能力:
python复制from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.messages import HumanMessage
from langchain_core.prompts import ChatPromptTemplate
def initialize_agent():
tools = [weather_tool, traffic_tool, events_tool, emergency_tool]
prompt = ChatPromptTemplate.from_messages([
("system", SYSTEM_PROMPT),
("placeholder", "{chat_history}"),
("human", "{input}"),
("placeholder", "{agent_scratchpad}"),
])
agent = create_tool_calling_agent(llm, tools, prompt)
return AgentExecutor(agent=agent, tools=tools)
其中SYSTEM_PROMPT的设计尤为关键,它定义了智能体的行为准则:
code复制你是一个专业的旅行规划助手,需要遵循以下原则:
1. 首先明确用户的旅行偏好和约束条件
2. 生成行程前必须检查当天的天气状况
3. 安排活动时要考虑地理位置邻近性
4. 为每个活动预留至少15分钟缓冲时间
5. 当检测到天气或交通异常时,主动提出调整建议
5.2 多轮决策流程
系统的工作流程实际上是一个状态机:
- 接收用户请求(如"为上海一日游制定历史文化主题行程")
- 分析是否需要实时数据(此时会决定调用天气查询)
- 基于返回数据生成初步行程
- 持续监听外部变化(通过定时检查工具实现)
- 当检测到变化时(如突然下雨),重新评估行程
- 提出调整建议并等待用户确认
6. 应急场景处理机制
6.1 天气突变应对方案
当检测到降雨概率>30%时,系统会自动:
- 识别所有室外活动
- 查找同类别室内替代方案
- 计算调整后的交通时间
- 生成对比方案供用户选择
python复制def handle_weather_change(itinerary: Itinerary, weather_data: Dict):
if weather_data["precip_mm"] > 0:
outdoor_activities = [
act for act in itinerary.activities
if not act.indoor_status
]
# 为每个室外活动寻找替代方案...
6.2 交通中断处理流程
遇到交通问题时,系统会:
- 评估受影响活动的紧急程度
- 查找周边同类替代选项
- 必要时重新排序活动时间
- 更新所有相关交通路线
7. 测试与优化经验
7.1 端到端测试案例
一个典型的测试场景:
python复制# 初始化
agent = initialize_agent()
# 用户请求
response = agent.invoke({
"input": "为明天上海的历史文化一日游制定行程,从上午9点到晚上8点"
})
# 模拟天气突变
weather_data["precip_mm"] = 5.0
update_weather_cache(weather_data)
# 检查系统是否自动提出调整
response = agent.invoke({
"input": "当前行程是否需要调整?"
})
7.2 性能优化技巧
在实际部署中发现几个关键优化点:
- 工具调用并行化:当需要同时检查多个地点的天气时,使用asyncio并行请求
- 地理缓存:对同一区域的活动进行地理聚类,减少地图API调用次数
- 模型蒸馏:对大语言模型进行微调,使其更熟悉旅游领域术语
8. 扩展与定制建议
8.1 多语言支持
通过修改SYSTEM_PROMPT并添加翻译工具,可以轻松实现:
python复制def add_translation_tool():
def translate_text(text: str, target_lang: str) -> str:
# 调用翻译API实现
...
return Tool.from_function(
func=translate_text,
name="translator",
description="用于多语言交流的翻译工具"
)
8.2 商业场景扩展
对于商业应用,可以考虑添加:
- 酒店/餐厅预订集成
- 门票购买功能
- 团体行程协调工具
- 基于位置的推送通知
这个系统最令我惊喜的是它的适应能力。在一次实地测试中,当外滩突然因活动封闭时,系统在30秒内就提出了绕行方案和替代景点,比当地导游反应还快。这证明实时数据与LLM推理的结合确实能创造实用价值。
