大模型通识 / 大模型应用开发入门
15. 交给别人运行——配置、启动与部署边界
原文备份 · 第 17 / 19 篇 · 查看极客时间原知识库 ↗
本篇目录 · 9 节
来源:大模型应用开发入门
你已经能在自己的电脑上使用笔记助手:打开页面,生成复习卡,保存计划,退出再打开也能找回。现在把项目文件夹发给朋友,对方却问:“该运行哪个文件?为什么找不到Flask?这个config要不要覆盖?你的历史怎么也在里面?”
这些问题不需要更强的模型,需要把程序从“我知道怎么用”整理成“别人能按说明运行”。本篇交付一个独立的源码包、一套启动入口和一份可以直接放进项目的README。另一个人从新目录开始,不依赖你的虚拟环境、密钥和运行数据,也能完成一次离线演示。
同时,我们会划清一个边界:让朋友在自己的电脑上运行,和把你的服务公开到互联网,是两件不同的事。前者本篇会实际验证;后者需要理解新增的运行与权限责任,不能靠修改一个监听地址就宣布完成。
下载本篇代码 · 独立运行说明 · 上一篇:SQLite会话与计划
核实日期:2026年10月4日。代码沿用Python 3.11+、openai 3.24.0和Flask 3.1.3,实测Python 3.11.8。网页、数据库和模型调用主体保持第14篇行为,新增
run_local.py与package_project.py。演示不读取真实API密钥、不调用付费API;安装依赖会连接软件包服务,与模型调用不同。
一、发出去之前,把文件分成三类
一个运行过的项目目录同时装着代码、环境和个人数据。压缩整个文件夹,往往把它们混在一起。先看每类文件的用途:
| 类别 | 本项目例子 | 如何交付 |
|---|---|---|
| 可复用源码与公开样例 | Python文件、HTML模板、requirements.txt、config.example.json、两份教学笔记 | 放进源码包,供接收者重新运行 |
| 本机环境与个人配置 | .venv、config.json | 接收者重建环境,由模板生成自己的配置 |
| 已产生的工作数据 | data、records、tool-records、plans等 | 本人单独备份,不作为通用源码发送 |
.venv中包含本机安装的解释器路径和依赖。它不是一份适合直接拷给另一台电脑的“软件绿色版”。Python官方建议在新位置重新创建虚拟环境,而不是搬运已有环境。Python venv文档
data/session.key也不该和公开代码一起发出。它虽然不是DeepSeek密钥,却负责签署浏览器会话身份。data还包含笔记全文快照、绝对路径、答案和计划。上篇讨论的备份,是为本人保留这些状态;本篇的源码交付,目的是让别人得到一个干净起点。
.gitignore仍有价值,但它只影响Git对文件的跟踪,不会阻止你用系统压缩工具把文件压进去。因此我们加一个明确的打包入口,不让它递归收集整个运行目录。
二、把“首次启动”变成一条清楚的路线
下载本篇ZIP,解压后进入lesson-15目录。不要覆盖第14篇已经运行过的目录。下面假定机器已经装有Python 3.11或以上版本;先运行python3 --version,Windows可运行py -3 --version确认。版本不符时先安装合适版本,不在系统Python里混装依赖。
macOS/Linux:
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python -m pip check
.venv/bin/python run_local.py init
.venv/bin/python run_local.py check
.venv/bin/python run_local.py serve
Windows PowerShell:
py -3 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe -m pip check
.\.venv\Scripts\python.exe run_local.py init
.\.venv\Scripts\python.exe run_local.py check
.\.venv\Scripts\python.exe run_local.py serve
每一行成功后再继续。我们直接指定虚拟环境中的Python,所以不用先激活环境,也不用为了这份教程修改PowerShell脚本执行策略。python -m pip把安装动作绑定到你选中的解释器,减少“安装在一个Python里,运行时却用了另一个”的混乱。
这里有两种检查。pip check检查已安装软件包声明的依赖是否相容,正常可看到No broken requirements found.;它不检查笔记目录或项目配置。pip check文档
run_local.py check则检查本项目的启动条件。它会显示解释器、项目目录、网页数据目录、两个直接依赖的版本和非秘密配置。第一次正常运行时,应看到“数据库尚未创建;首次serve将初始化”,最后是:
本地启动检查通过;未读取API Key、未调用API、未测试端口或网络可达性。
再运行serve,终端应显示本机地址http://127.0.0.1:8765。打开页面,顶部仍是“离线演示 · 不请求模型”。从默认两份笔记生成卡片,填写一个复习日期、20分钟,预览并确认计划。预期结果与上篇相同:卡片为validated_needs_review,计划显示“计划已保存”。
在另一个终端、同一项目目录执行.venv/bin/python inspect_db.py,Windows用.\.venv\Scripts\python.exe inspect_db.py。全新目录只做一次流程,应有一个会话、一个操作和一个计划;刷新页面不增加操作数。至此,对方不需要API账户也可以验证应用安装和主要流程。
三、init、check、serve分别做什么
把几个命令合成一个入口,不是为了隐藏错误,而是让各阶段职责清楚。
init仅在缺少config.json时,从config.example.json创建它。如果文件已经存在,就提示保留,绝不覆盖。它不创建数据库、会话密钥或虚拟环境。你第二次执行init看到“保留已有config.json”,属于正常结果。
核心代码是独占创建:
try:
with target.open("xb") as f:
f.write(content)
except FileExistsError:
print("保留已有config.json;请继续运行check。")
return False
x表示文件存在就失败,而不是打开后清空。这个小选择可以避免一条初始化命令把读者刚调整过的配置抹掉。已有文件是否有效,由下一步check判断。
check检查当前解释器、两个直接依赖版本及导入、配置字段、可选笔记、数据位置的写权限,以及已有数据库和会话密钥的基本状态。为了验证写权限,它会创建并清理一个临时目录;不会创建新数据库或重写已有数据库。已有数据库却缺少session.key时,它会要求检查备份,避免启动过程中生成新密钥导致旧会话失效。
它不是无所不能的“健康认证”。它不会联网试密钥,不检查账户余额,不确认模型名在服务端可用,不逐份解析笔记内容,也不预占端口。笔记长度和检索规则仍在预览时检查;端口是否可绑定由真正启动时决定。
serve先运行同一检查,通过后用当前Python解释器启动已有web_app.py。因此虚拟环境不会在中途被换掉。默认启动离线模式;只有显式加入--live,才进入终端隐藏输入Key的流程。原有web_app.py仍可直接使用,但交付给初学者时推荐这个带前置检查的入口。
再次打开项目时,不需要重建环境或重新安装,只执行:
.venv/bin/python run_local.py serve
Windows仍替换成对应解释器路径。停止服务用原终端的Ctrl+C;终端结束、电脑休眠或关机后,服务不会继续可靠运行。本课没有后台守护、自动重启和开机启动。
四、配置放在哪里,哪些东西不要放进去
模板只有三个字段:
{
"model": "deepseek-flash",
"max_tokens": 1024,
"timeout_seconds": 60
}
模型名必须是非空字符串;输出预算限制为1—4096,超时为1—120,二者必须是整数。这里的范围是本课程为了控制实验规模设定的限制,不是DeepSeek服务的完整上限。
配置按照脚本所在目录定位,不按终端恰好在哪个目录决定。因此从其他目录运行脚本,仍会使用它旁边的config.json和data。检查命令把实际路径打印出来,帮助你发现是否启动了旧副本。
本项目没有自动读取.env,也没有把环境变量作为隐藏的配置覆盖层。更不接受在config.json里追加api_key。把Key写进一个程序根本不读取的位置,既不能修好认证问题,又增加误分享的可能性。
本课继续使用官方https://api.deepseek.com地址和deepseek-flash模型标识;本日官方入门文档仍列出这个地址与名称。DeepSeek官方接入说明
如果你决定进行可能计费的真实验证,先停止离线服务,再运行:
.venv/bin/python run_local.py serve --live
Windows运行.\.venv\Scripts\python.exe run_local.py serve --live。Key由本人在终端输入,页面不接收Key,重启后需要重新输入。预览仍不请求模型;点击真实生成时,选中的笔记片段和问题会发送到API。关闭思考、非流式JSON、单次尝试等规则沿用前篇。
默认示例能启动,只证明本地依赖和演示路径可用。真实Key是否有效、网络是否可达、账户能否支付以及模型输出是否合格,需要另行验证,不能从离线成功推出来。
五、固定版本,为什么还不能说“任何机器上完全一样”
requirements.txt把直接使用的SDK和Flask固定到本篇测试过的版本,启动检查也会拒绝不同版本。这是为了让跟课过程可复现,不表示其他版本必定不能运行;自行升级后需要重新验证,不能只改检查提示就宣布兼容。
这两个库还依赖其他包。当前文件没有逐个固定全部间接依赖,也没有提供包文件哈希,因此它不是一份完整锁文件。在不同安装时间、Python版本和操作系统上,间接依赖或可用二进制包仍可能变化。更严格的重复安装可进一步固定全部依赖、核对哈希或准备适合目标平台的安装包,但也要承担更新维护工作。pip重复安装说明
本篇采取适合入门的做法:固定关键版本,使用隔离环境,用pip check与应用检查发现问题,再从全新目录验证真实启动流程。不要把自己电脑上混用多个项目的环境直接pip freeze成清单发给别人,那会把与本项目无关的依赖一并带进去。
当你需要升级,先复制一份干净源码、重建环境验证,再决定迁移原数据。第14篇数据库有版本号,本篇没有改变结构;但这不意味着未来任意版本代码都能打开同一份库。
六、生成一份不含个人历史的源码包
在当前项目目录运行:
.venv/bin/python package_project.py --output ../notes-assistant-source.zip
Windows PowerShell:
.\.venv\Scripts\python.exe package_project.py --output ..\notes-assistant-source.zip
命令会把源码ZIP写到项目的上一级目录。输出父目录必须已存在;如果目标ZIP已经存在,程序拒绝覆盖,你可以改成notes-assistant-source-v2.zip等新名字。
正常结果是“已生成37文件源码包”。打开ZIP查看,应有顶层目录notes-assistant,下面是代码、README、模板、固定依赖和教学样例。它不应包含data、config.json、.venv、.env、请求日志,也不包含你另外放进sample-notes的私人笔记。
打包器使用代码中的FILES白名单。只有列出的相对路径才会被读取;缺少必要文件、路径中有符号链接时会停止。两份教学笔记还会核对原始哈希,若你已经把rag.md改成自己的内容,也会拒绝打包。此时应另取干净的教学副本,不要为了通过检查覆盖自己已经写好的笔记。
这个机制有明确范围:如果你把秘密手写进清单内的Python源码或README,白名单不会识别它。打包前仍需审阅自己修改过的文件。反过来,如果你新增了一个必要Python模块,打包器也不会自动认识它;需要审阅后补进FILES,再做解压验证。
源码包也不是数据备份。自己的历史、会话密钥和计划仍在原data中,按照上篇停服备份整目录。不要因为生成了源码ZIP,就删除原项目。
七、用“接收者的方式”再运行一次
不要在仍有旧配置、旧数据库和旧环境的目录里证明包能用。真正的检查应从源码包解压后的目录开始:
- 停止原服务,保留原文件。
- 把刚生成的ZIP解压到另一个位置,例如一个新的测试文件夹。
- 进入其中的
notes-assistant目录,按第二节重建.venv、安装依赖、执行init与check。 - 启动离线网页,首页应没有原来的历史,也不应要求输入Key。
- 用默认样例生成卡片、确认一份计划,运行
inspect_db.py独立核对,再停服重启检查恢复。
新副本有自己的数据库和会话签名密钥。浏览器访问新副本时可能获得新的会话Cookie;不要同时运行新旧两份,再指望切换端口能隔离Cookie。验证旧数据是否还在,应回到对应目录用只读检查核对,而不是仅凭浏览器首页判断。
这次练习的价值是找出“只在我电脑上成立”的假设:代码是否依赖旧绝对路径,是否漏打包模板,是否误用全局安装,是否把个人配置当成必需文件。直到新副本从零完成这条链路,再把源码包交给学习伙伴。他是否进行真实API验证,由他自行决定,使用他自己的账户。
八、共享源码和公开服务,差在哪里
共享源码时,每个人运行自己的进程,使用自己的资料和Key。公开服务时,是你的后端长期接受别人的请求;模型费用、数据访问、故障恢复都汇聚到同一个服务上。浏览器中的一个按钮,可能开始消耗你的API额度。
本篇的serve仍调用Flask开发服务器。它适合本地开发教学;即使只有本人长期使用,正式部署也应改用合适的WSGI服务器或托管平台。Flask官方明确区分了开发运行与生产部署,生产环境不等同于“用户很多”。Flask部署文档
WSGI服务器负责长期接收HTTP请求并把它们交给Python应用;它不会自动补出登录、用户配额或业务授权。公开服务至少会改变以下几组设计:
| 当前教学版 | 对外服务需要解决的问题 |
|---|---|
| 只监听127.0.0.1,本机HTTP | 服务入口、HTTPS、可信代理与Cookie配置 |
| 随机浏览器会话,无登录找回 | 可验证用户身份、退出与失效、记录和文件访问权限 |
| 所有人可选同一资料目录 | 用户资料分区、上传限制、授权后读取 |
| 单进程,前台运行,Key终端输入 | 进程管理、密钥注入、更新与异常恢复 |
| 本地SQLite和操作文件 | 持久化磁盘、备份恢复、写入并发与容量管理 |
| 单次请求有限制 | 用户配额、请求速率、总费用控制与可观察的失败记录 |
这不是让个人项目一开始就搭建复杂基础设施。它是在告诉你,哪一类变化会让现有假设失效。例如,部署平台重新创建实例时若没有持久化磁盘,SQLite文件可能丢失;启多个服务进程时,任务状态和写入竞争需要重新验证;日志若收集完整请求,笔记内容也会进入日志系统。
因此本篇不提供一条“把地址改成0.0.0.0即可上线”的命令,也没有替你购买服务器或公开端口。你已经得到可以交给别人本地学习的包;如果下一步确实需要共同使用一个在线服务,应按具体使用者、资料与费用范围设计那套部署。
九、别人报告“打不开”,先问清失败在哪一层
| 现象 | 下一步 |
|---|---|
| 找不到Python或版本过低 | 确认安装与版本,先让版本命令成功 |
No module named flask/openai |
对照check显示的解释器,用同一个Python安装requirements |
| pip下载失败 | 检查软件包网络和安装错误;不是DeepSeek密钥的问题 |
| init说已有配置 | 配置被保留了,接着check;不要默认删掉重建 |
| check报字段或范围错误 | 对照三字段模板,数值不要写成字符串或布尔值 |
| check通过但网页没起来 | 查看启动终端;可能端口被占用,用serve --port 8766换空闲端口 |
| 页面404、历史不见了 | 对照项目路径、data路径、Cookie与会话密钥;只读检查数据库 |
| 检查提示已有库缺密钥 | 保留文件,找对应备份;不要用新密钥冒充会话恢复 |
| 第一次调用才报认证、额度或网络错误 | 本地检查没验证远端,按第8篇分类处理,不自动无限重试 |
| 打包拒绝修改后的样例 | 用干净教学副本,保留自己的笔记,不绕过内容边界 |
失败时保留终端中有用的错误类型和步骤。给别人反馈问题前,去掉Key、笔记全文和个人路径等不必要内容。只说“模型不行”会把安装、应用和模型三种不同问题混在一起。
本篇完成112项离线回归,覆盖前篇97项行为及15项启动/打包边界;并用全新虚拟环境安装依赖、从导出的源码包重新运行。网页业务流程未改,离线验证不代表API可用或Windows实机通过。
最后做一个判断练习:把.venv一并打包是不是最省心?通常不是,应在接收者电脑重建。check通过是否意味着Key余额充足?不是,它没有连接模型。新源码包没有旧计划是不是数据丢失?不是,这正是干净交付的预期,旧数据应保留在原目录和备份中。
下一篇将用一组可重复的验收场景检查整个助手,再讨论把它迁移为自己的项目时,应该先改需求、资料、工具还是模型接口。