上周我帮朋友规划泰国游,光是对比曼谷酒店价格、查实时天气、换算美元到泰铢就开了6个网页,最后预算还算错了——相信不少人都有过这种“旅行计划比上班还累”的经历。但现在不一样了:用Streamlit+LangChain搭一个AI旅行代理,输入“5天泰国游,预算800美元”,3秒就能拿到带天气、酒店、行程和视频的完整方案,甚至连每天的饭钱都给你算明白。
这篇文章不是干巴巴的API文档,而是一份“从0到部署”的实战指南——不管你是想解决自己的旅行规划难题,还是想练手AI应用开发,跟着做就能出成果。
序章:旅行计划的“旧痛”与AI的“新解”
做旅行计划时,我们总在重复三件麻烦事:打开天气APP查目的地温度,切换到酒店平台比价,再用计算器手动算总花费,最后还得去B站找旅行视频——信息散在各处,预算经常超支,花两小时做的计划可能还漏了关键景点。
而这个AI旅行代理恰好把这些事打包解决了:它用OpenWeatherMap查天气,靠Google Serper搜实时酒店价格,借LangChain的工具链自动算预算,最后用Streamlit把结果做成清爽的网页。核心技术栈其实很亲民:LangChain负责“让AI知道该调用什么工具”,Streamlit负责“把AI的结果变成人能看懂的界面”,OpenAI GPT-4则负责理解你的需求(比如“预算800美元转成印度卢比”)。
对普通人来说,这是个能直接用的旅行工具;对开发者来说,这是个绝佳的“AI+垂直场景”练手项目——毕竟不是所有AI项目都需要复杂的模型训练,把现成工具组合好,就能解决实际问题。
直觉:这个AI代理到底能帮你做什么?
先别着急写代码,我们先看看它的“硬实力”。假设你输入:“3天曼谷游,预算500美元,转成印度卢比,要查天气、找 budget 酒店、看旅行视频”,它会返回这些内容:
-
实时天气:曼谷当前气温、湿度,甚至会提醒你“今日有雷阵雨,建议带伞”(数据来自OpenWeatherMap,和手机天气APP一样准); -
酒店推荐:3家每晚30-40美元的酒店,附地址和评分,还会算好3天总费用(比如35美元/晚×3天=105美元,折合成印度卢比约8750); -
行程表:每天的安排都带价格——第一天大皇宫(门票10美元)+ 湄南河游船(15美元),第二天暹罗广场购物(无门票)+ 街头小吃(5美元/餐); -
旅行视频:3个YouTube链接,标题都是“2025曼谷旅行攻略”“曼谷街头美食指南”这类精准内容; -
预算 breakdown:总花费380美元(含酒店、餐饮、景点),还剩120美元可灵活支配。
和某猪、某程这类传统旅行APP比,它的核心优势是“动态计算”——不是给你一堆酒店列表让你自己挑,而是根据你的预算主动筛选,甚至会帮你避开“价格看起来低但位置偏远”的坑(靠搜索工具爬取用户评分)。
实战:从0搭建开发环境(3步搞定)
接下来进入实操环节,不管你用Windows还是Mac,跟着做就能跑通。首先要准备三个东西:GitHub账号(用来存代码)、三个API密钥(OpenAI、Google Serper、OpenWeatherMap),以及电脑上的Python环境(3.8+就行)。
第一步:克隆代码仓库并进入目录
先打开终端(Windows用PowerShell,Mac用终端),执行这行命令克隆项目:
git clone https://github.com/yourusername/ai-travel-agent.git
cd ai-travel-agent
这里把“yourusername”换成你的GitHub用户名——如果还没建仓库,先在GitHub上新建一个空仓库,再把本地代码推上去(后面部署会用到)。
第二步:创建虚拟环境并安装依赖
为了避免依赖冲突,我们先建一个虚拟环境。执行以下命令:
# 创建虚拟环境
python -m venv venv
# 激活环境(Mac/Linux)
source venv/bin/activate
# 激活环境(Windows)
venv\Scripts\activate
激活后,终端前面会出现“(venv)”,说明环境没问题。接下来安装依赖:
pip install -r requirements.txt
requirements.txt里已经包含了Streamlit、LangChain、OpenAI等所有需要的库——这里要注意,如果你用的是Python 3.12+,可能会遇到“python-dotenv”安装警告,忽略就行,不影响使用。
第三步:配置API密钥(关键步骤,别踩坑)
项目需要三个API密钥才能工作,分别是:
-
OpenAI API:用来让AI理解你的需求(获取链接); -
Google Serper API:用来搜酒店、汇率、景点价格(获取链接); -
OpenWeatherMap API:用来查天气(获取链接)。
拿到密钥后,在项目根目录新建一个.env文件(注意文件名前面有个点),里面写:
OPENAI_API_KEY=你的OpenAI密钥
SERPER_API_KEY=你的Google Serper密钥
OPENWEATHERMAP_API_KEY=你的OpenWeatherMap密钥
这里有个坑要提醒:密钥后面别加空格!我之前多打了个空格,结果启动时一直报“API密钥无效”,查了半小时才发现问题。另外,千万别把.env文件提交到GitHub——项目里的.gitignore已经帮你排除了这个文件,放心用。
项目结构快速解读
此时你的项目文件夹里应该有这些文件:
ai-travel-agent/
├── app.py # 核心:Streamlit界面和逻辑
├── Assignment.ipynb # 原始Jupyter笔记本(可备用)
├── requirements.txt # 依赖列表
├── .env # 你的API密钥(本地用)
└── .streamlit/ # Streamlit配置(后面自定义主题用)
└── config.toml
重点关注app.py——所有的界面显示、AI调用逻辑都在这里;.streamlit/config.toml则是用来改界面主题的,比如把背景色改成浅蓝色,后面会讲。
实战:跑起第一个AI旅行代理(5分钟看到效果)
环境搭好后,我们马上启动应用,看看它到底能不能用。
启动命令的三种玩法
在终端执行最基础的启动命令:
streamlit run app.py
执行后,终端会显示“您的应用正在运行”,并自动打开浏览器,地址是http://localhost:8501——这是Streamlit的默认端口。
如果遇到“端口8501已被占用”的错误(比如你之前开了其他Streamlit应用),可以换个端口:
# 用8502端口启动
streamlit run app.py --server.port 8502
如果想边改代码边看效果(开发模式),可以加--server.runOnSave true,这样改完app.py保存后,应用会自动刷新:
streamlit run app.py --server.runOnSave true
首次运行的常见问题排查
如果启动后浏览器显示“API密钥错误”,先检查这两点:
-
.env文件里的密钥是否正确(复制粘贴时别漏字符); -
终端是否激活了虚拟环境(有没有“(venv)”标识)——如果没激活,Python找不到 python-dotenv库,就无法读取.env文件。
如果显示“无法连接到OpenAI”,可能是网络问题——可以试试切换网络,或者检查OpenAI API的配额(免费用户有5美元额度,足够测试)。
最小可运行示例:查一次曼谷行程
在浏览器的输入框里,粘贴这段查询(和之前的例子一样):
3天曼谷游,预算500美元,转成印度卢比。查当前天气,找每晚低于40美元的酒店,算总花费,给旅行视频链接。
点击“提交”后,界面会显示“AI正在处理”的加载动画——这个过程大概3-5秒(取决于网络速度和API响应时间)。
预期结果应该是这样的:
-
顶部显示曼谷当前天气:比如“28℃,多云,湿度65%”; -
酒店部分:3家酒店,每家电价35-40美元,总费用105-120美元,折合成印度卢比约8750-10000; -
行程表:每天的景点、餐饮、费用,比如“第一天:大皇宫(10美元)+ 泰式午餐(5美元)”; -
视频部分:3个YouTube链接,标题包含“曼谷旅行攻略2025”; -
预算总结:总花费约320美元,剩余180美元。
如果能看到这些内容,说明你的AI旅行代理已经跑通了——接下来就可以玩更多功能,比如查东京、巴黎的行程,或者调整预算。
实战:核心功能拆解(知道它为什么能工作)
光会用还不够,我们简单拆解一下核心功能,让你知道背后的逻辑——以后想加新功能(比如机票查询),也知道从哪下手。
1. 天气查询:怎么做到实时准确?
当你输入“查曼谷天气”时,app.py里的get_weather(city)函数会被调用——它会把“曼谷”作为参数,传给OpenWeatherMap API,拿到返回的JSON数据后,提取出气温、湿度、天气状况,再用Streamlit显示出来。
你可以在app.py里找到这段逻辑(简化版):
def get_weather(city):
api_key = os.getenv("OPENWEATHERMAP_API_KEY")
url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric"
response = requests.get(url)
data = response.json()
return f"{city}当前气温:{data['main']['temp']}℃,天气:{data['weather'][0]['description']}"
这里的units=metric表示用摄氏度(默认是华氏度),如果想改回华氏度,把metric换成imperial就行。
2. 预算计算:实时汇率从哪来?
当你需要“把美元转成印度卢比”时,AI会调用search_google工具,搜索“2025年X月X日美元兑印度卢比汇率”——数据来自Google搜索结果,和你在Google上查的汇率一致。
比如当前汇率是1美元=83印度卢比,AI会自动计算:35美元/晚×3天=105美元×83=8715印度卢比——这个计算过程用的是LangChain里的addition/multiply工具,不用你写复杂的数学逻辑。
3. 视频推荐:怎么找到精准的YouTube视频?
视频推荐靠的是youtube_search函数,它会把你的查询(比如“曼谷旅行攻略”)作为关键词,调用YouTube的搜索API,返回最新的3-5个视频链接。
你可以在app.py里调整视频数量——找到youtube_search函数,把max_results=3改成max_results=5,就能多要两个视频链接。
进阶:把代理部署到云端(让朋友也能用上)
本地跑通后,我们把它部署到云端,这样不管在哪,打开链接就能用——推荐用Streamlit Cloud,免费、简单,不用懂服务器。
Streamlit Cloud部署(推荐,10分钟搞定)
-
把代码推到GitHub:先在GitHub上新建一个仓库(比如叫
ai-travel-agent),然后在本地终端执行:# 初始化Git(如果没初始化过) git init # 添加文件 git add . # 提交 git commit -m "初始提交:AI旅行代理" # 关联远程仓库(换成你的仓库地址) git remote add origin https://github.com/yourusername/ai-travel-agent.git # 推到GitHub git push -u origin main这里要注意:
.env文件不会被推上去(因为.gitignore里排除了),所以云端需要重新配置密钥。 -
连接Streamlit Cloud:打开Streamlit Cloud官网,用GitHub账号登录,点击“New app”,然后:
-
Repository:选择你刚推的 yourusername/ai-travel-agent; -
Branch:选 main; -
Main file path:填 app.py(核心文件);
点击“Deploy”,等待1-2分钟。
-
-
配置云端密钥:部署后,点击“Manage app”→“Secrets”,在文本框里输入:
OPENAI_API_KEY = "你的OpenAI密钥" SERPER_API_KEY = "你的Google Serper密钥" OPENWEATHERMAP_API_KEY = "你的OpenWeatherMap密钥"点击“Save”,应用会自动重启——此时你的AI旅行代理已经在线了,链接是
https://your-app-name.streamlit.app(可以分享给朋友)。
其他部署方案对比
如果Streamlit Cloud满足不了你(比如需要更高的访问量),可以试试这两个方案:
-
Heroku:需要创建 Procfile和setup.sh文件(用来配置端口),免费额度有限(550小时/月); -
Railway:不用写配置文件,连接GitHub后自动部署,但免费额度用完后会收费。
具体的部署步骤可以参考项目文档,这里就不展开了——对大多数人来说,Streamlit Cloud足够用。
进阶:3个技巧让你的代理更好用
跑通和部署只是开始,我们可以做一些优化,让体验更好。
1. 用缓存减少API调用(省 money + 提速)
每次查询都调用API,不仅慢,还会消耗配额(比如OpenAI API是按调用次数收费的)。用Streamlit的@st.cache_data装饰器,可以缓存相同查询的结果——比如你查了“曼谷天气”,10分钟内再查,会直接返回缓存结果,不重复调用API。
在app.py的get_weather函数上面加一行代码:
@st.cache_data(ttl=600) # ttl=600表示缓存10分钟(600秒)
def get_weather(city):
# 原函数逻辑不变
同理,search_google、youtube_search函数也可以加这个装饰器——注意,涉及实时数据的函数(比如汇率),ttl别设太长,建议1小时(3600秒)以内。
2. 自定义界面主题(换个“旅行风”皮肤)
默认的Streamlit界面是白色的,我们可以改成浅蓝色(像天空一样,符合旅行主题)。在.streamlit/config.toml里写:
[theme]
primaryColor = "#4A90E2" # 主色调:浅蓝色
backgroundColor = "#F5F7FA" # 背景色:浅灰色
secondaryBackgroundColor = "#E8F0FE" # 次要背景色:更浅的蓝
textColor = "#333333" # 文字色:深灰色
[server]
runOnSave = true # 保存即刷新
保存后,重启应用,界面就会变成你设置的颜色——如果想换其他颜色,搜“Streamlit theme color codes”,有很多现成的配色方案。
3. 保存聊天历史(不用重复输入)
默认情况下,每次刷新页面,之前的查询记录会消失。用Streamlit的session_state可以保存聊天历史——在app.py里加一段代码:
# 初始化会话状态(如果没有)
if "messages" not in st.session_state:
st.session_state.messages = []
# 显示历史消息
for msg in st.session_state.messages:
st.chat_message(msg["role"]).write(msg["content"])
# 处理新输入
if prompt := st.chat_input("输入你的旅行需求..."):
# 把新输入加入会话状态
st.session_state.messages.append({"role": "user", "content": prompt})
# 调用AI处理(原逻辑不变)
response = react_graph.invoke(...)
# 把AI的回复加入会话状态
st.session_state.messages.append({"role": "assistant", "content": response})
这样不管怎么刷新页面,之前的查询和回复都不会丢——对需要多次调整行程的用户来说,体验提升很多。
结论:不止是旅行工具,更是AI落地的思路
到这里,你已经拥有了一个能查天气、算预算、生行程的AI旅行代理——但这个项目的价值不止于此。
对普通人来说,它解决了“旅行计划耗时”的实际问题;对开发者来说,它展示了“如何把AI工具组合起来解决垂直场景问题”:LangChain负责“工具调用逻辑”(什么时候用天气API,什么时候用搜索API),Streamlit负责“用户交互”(把复杂的AI输出变成简单的界面),两者结合,就能快速做出有用的AI应用。
接下来你可以尝试扩展功能:
-
加“机票查询”:集成Skyscanner API,输入出发地和日期,就能查机票价格; -
加“签证提醒”:调用目的地国家的大使馆API,提醒签证办理时间; -
加“多人协作”:用Firebase存储行程,让多个人一起编辑。
AI应用开发不一定要从零开始——把现成的工具用好,解决一个小痛点,就是一个好项目。
常见问题解答(FAQ)
Q:API调用次数多了会花钱吗?
A:会,但新手足够用。OpenAI免费用户有5美元额度(调用GPT-4约0.03美元/次),Google Serper免费版每月100次搜索,OpenWeatherMap免费版每天可查60次天气——测试阶段完全够,后续不够可以升级付费版。
Q:部署后访问速度慢怎么办?
A:有两个优化方向:1. 用@st.cache_data缓存API结果,减少调用次数;2. 把应用部署到离你近的区域(Streamlit Cloud可以选区域,比如亚洲的新加坡节点)。
Q:能不能让AI推荐小众景点,而不是热门景点?
A:可以。在search_google函数的查询关键词里加“小众景点”,比如把“曼谷景点”改成“曼谷小众景点 2025”——AI会根据新的关键词搜索,返回更符合需求的结果。
Q:Windows系统激活虚拟环境时提示“权限不足”怎么办?
A:以管理员身份打开PowerShell,执行Set-ExecutionPolicy RemoteSigned,然后输入“Y”确认——这是Windows默认的执行策略限制,改完就能激活虚拟环境了。
工程化checklist(可复制到GitHub Issue)
-
[ ] 已克隆代码仓库并进入目录 -
[ ] 已创建并激活虚拟环境( venv\Scripts\activate或source venv/bin/activate) -
[ ] 已安装所有依赖( pip install -r requirements.txt) -
[ ] 已创建 .env文件并填入3个API密钥(无多余空格) -
[ ] 本地运行 streamlit run app.py成功,能查询行程 -
[ ] 已将代码推到GitHub( .env未提交) -
[ ] 已部署到Streamlit Cloud并配置Secrets -
[ ] 已添加缓存装饰器( @st.cache_data)优化性能
思考题与答案
-
问题:如何给AI旅行代理增加“机票价格查询”功能?
答案:
步骤1:注册Skyscanner API(官网链接),获取API密钥;
步骤2:在.env文件中添加SKYSCANNER_API_KEY=你的密钥;
步骤3:在app.py中新建get_flights(origin, destination, date)函数,调用Skyscanner API获取机票价格(示例代码):def get_flights(origin, destination, date): api_key = os.getenv("SKYSCANNER_API_KEY") url = f"https://partners.api.skyscanner.net/apiservices/browsequotes/v1.0/CN/CNY/zh-CN/{origin}/{destination}/{date}" params = {"apiKey": api_key} response = requests.get(url, params=params) data = response.json() # 提取最低价格 min_price = data["Quotes"][0]["MinPrice"] return f"{origin}到{destination}({date})的最低机票价格:{min_price}元"步骤4:在AI工具链中添加
get_flights函数,让AI能识别“查机票”需求并调用该函数;
步骤5:在Streamlit界面添加“出发地、目的地、日期”输入框,关联机票查询功能。 -
问题:为什么部署时必须用“环境变量”存储API密钥,而不是直接写在代码里?
答案:
有三个核心原因:
① 安全风险:如果把密钥写在代码里,提交到GitHub后会被公开——任何人都能拿去调用API,产生高额费用(曾有人泄露OpenAI密钥,一天被刷走几百美元);
② 环境适配:本地开发和云端部署可能用不同的密钥(比如本地用测试密钥,云端用生产密钥),用环境变量可以灵活切换,不用改代码;
③ 合规要求:大多数API服务商(如OpenAI、Google)都要求密钥不能公开存储,违反会被封禁账号——用环境变量是符合最佳实践的做法。
