别信“本地没问题”:AI 项目上线必看的 5 个部署避坑指南
故障一:昨天还能用的代码库,今天突然找不到了
我的 RAG 对话机器人里有一行引用代码,跑了几周都没问题:
from langchain.chains import ConversationalRetrievalChain # 从 langchain 核心包中导入对话检索链功能
本地运行:一切正常。
部署到线上:直接崩溃,提示找不到模块。
原因很简单:你的电脑里缓存的是几个月前安装的老版本 LangChain 库,里面还包含这个旧功能。但线上服务器每次部署都是“全新安装”,会自动下载最新版本。而新版 LangChain 早就把这个功能移出去了。
正确的修复方法:不要盲目追新,在配置文件中把版本号“钉死”在还能用的旧版本上:
langchain==0.3.7 # 锁定 langchain 主库的精确版本号
langchain-community==0.3.7 # 锁定社区扩展库的精确版本号,确保环境一致
💡 提米哥提醒:本地能跑通,往往只是因为你电脑环境“很久没动过”。线上服务器每次都是白纸一张。提前锁死版本号,能避免半夜紧急查 bug。
故障二:文件明明在,上线却读取出错
我的项目需要从本地加载一个预训练好的向量数据库文件:
vectorstore = FAISS.load_local("faiss_index", embedding, allow_dangerous_deserialization=True) # 加载本地向量库,开启反序列化权限
本地加载:秒开。
线上运行:底层直接崩溃,连个像样的报错信息都没有。
真实原因:这是 Git LFS(大文件存储)在作怪。我的大文件其实是被 Git LFS 管理了,它只在仓库里存了一个“小文本指针”。我本地装了 LFS 客户端,它会自动把指针变成真实文件,所以我根本没察觉。但线上服务器拉代码时没装 LFS,直接拿到了那个只有几百字节的“假文件”(指针),自然读不出二进制数据。
修复方法:让 Git 别再管这个大文件了,直接把它当成普通文件提交:
git lfs untrack "faiss_index/*" # 停止用 LFS 跟踪该目录下的文件
git rm --cached faiss_index/index.faiss # 从 Git 缓存中移除旧的指针记录
git add faiss_index/index.faiss # 将真实文件作为普通二进制文件添加
git commit -m "Stop using LFS" # 提交更改,备注改用普通存储
git push # 推送到远程服务器
💡 提米哥提醒:Git LFS 就像一个“隐形管家”,它在本地默默干活你感觉不到,只有当你把项目搬到不支持它的云端时,它才会让你发现“文件根本不存在”。
故障三:同一个平台,两种不同的文件大小限制
我想把一个 83MB 的 PyTorch 模型文件拖拽上传到 GitHub 网页端,结果被拦截:
Yowza, that's a big file. Try again with a file smaller than 25MB. # 网页拦截提示:文件过大,网页端上限为 25MB
我以为平台就是不支持大文件。其实不然:网页拖拽确实限制 25MB,但如果你用命令行 git push,限制其实是 100MB。同一个平台,走不同的“门”,规矩不一样。
修复方法:改用命令行推送,并适当调大上传缓存区,防止网络慢时传到一半断线:
git add model.pth # 添加模型文件到暂存区
git commit -m "Add model" # 提交更改
git config --global http.postBuffer 157286400 # 设置上传缓冲区为 150MB,防止大文件传输中途超时
git push # 通过命令行推送,走独立限制通道
💡 提米哥提醒:遇到“卡在一个整齐的数字(如 25、100)”报错时,别急着改代码。先想想是不是你用的上传入口本身有大小限制,换个上传姿势可能就通了。
故障四:云平台悄悄升级了环境,我的依赖全乱了
部署进行到一半,一个本来跑了几天的项目突然报出一大堆导入错误。我的代码一个字都没改。
真实原因:托管云平台为了“优化”,自动把我用的 Python 版本升级了。新版本太新,导致我依赖的几个重型工具包还没来得及发布兼容的编译版本,环境对不上号。
最稳的修复方法:别跟云平台的自动升级较劲。如果你的项目数据量不大,根本不需要那些沉重的 AI 计算库,直接砍掉!换成最轻量的依赖:
streamlit==1.40.0 # 仅保留界面运行库
requests==2.32.3 # 仅保留网络请求库
python-dotenv==1.0.1 # 仅保留环境变量读取库,无编译依赖更稳定
💡 提米哥提醒:当运行环境不受你控制时,最聪明的做法不是拼命锁定所有版本,而是“做减法”。依赖越少,编译冲突的概率就越低,上线就越稳。
故障五:推送显示成功,网页上却找不到文件
这是最让人懵圈的一次:git push 显示全部成功,没报错。但去 GitHub 网页上一看,文件根本不在那儿。
真实原因:分支名字搞混了。GitHub 仓库创建时默认的主分支叫 main,但我一直在往本地的 master 分支写代码。虽然推送成功了,但它把文件推到了服务器上那个平行的、没人看的 master 分支里。
修复方法:把本地代码直接推送到 GitHub 默认显示的那个分支:
git branch -a # 查看所有分支,确认本地 master 与远程 main 并行存在
git push origin master:main # 将本地 master 的内容推送到远程的 main 分支进行覆盖
💡 提米哥提醒:推送成功,只代表“数据传过去了”,不代表“传到了你正在看的那个页面”。动手前务必用命令查一下分支对应关系。
提米哥总结:为什么代码没 bug,上线却总挂?
上面这 5 个坑,没有一个是代码逻辑写错了。它们全源于一个核心矛盾:你以为“本地”和“线上”是一模一样的,但其实根本不是。
- 本地用的是缓存旧包,线上装的是全新最新版。
- 本地能自动解压大文件指针,线上拿到的只是空文本。
- 本地拖网页有限制,线上走命令行是另一套规则。
- 你以为指定了运行环境,云平台却悄悄换了版本。
- 你往 A 分支交卷,系统只在 B 分支展示。
“本地能跑”只是在你自己的小环境里成立。真正的部署,就是去检验你那些“默认没问题”的假设,到底经不经得起现实考验。
✅ 下次部署前,花 30 秒过一遍这张清单
为了不再重蹈覆辙,以后每次点“部署”之前,我都会问自己这 5 个问题:
– 我的依赖包版本号是精确到具体数字(如 1.2.3),还是写了个模糊的范围?
– 仓库里有没有用 Git LFS 管理的大文件?我的部署平台支持自动解析它吗?
– 有没有哪个文件快撞到平台的大小限制了?我走的是网页上传还是命令行推送?
– 那些特别重、特别依赖特定系统的第三方包,能不能直接砍掉或替换成轻量方案?
– 我推送的目标分支,是不是我在浏览器里真正看的那个分支?
提前花 30 秒问一遍,能省下事后熬夜排查的几十个小时。
