Wardrobe如何可靠运行AI图像任务:job状态机、原子写入与崩溃自动恢复开发指南
【免费下载链接】wardrobeYour clothes, extracted and organized with gpt-image.项目地址: https://gitcode.com/gh_mirrors/wardro/wardrobe
Wardrobe 是一个基于 gpt-image 的本地优先 AI 衣柜:上传穿搭照片,它会自动识别每件衣物、抠出透明底商品图并生成真人上身效果图。为了让这些耗时长、易中断的 AI 图像任务可靠运行,Wardrobe 用了三个机制:job 状态机、原子写入与崩溃自动恢复——任务状态随时落盘,进程崩溃后重启即可自动续跑。
🚀 快速上手:3 步跑起 Wardrobe AI 衣柜
Wardrobe 要求 Node.js 22+,本地运行只需三步(配置说明见 README.md):
git clone https://gitcode.com/gh_mirrors/wardro/wardrobe cd wardrobe npm install cp .env.example .env npm run dev在.env中填入OPENAI_API_KEY,并在data/model-reference.png放一张本人 PNG 参考照,服务启动后打开localhost:5173即可。所有配置项(数据目录、模型、图像质量)都通过环境变量控制,无需改动代码。
👀 先看看成品:AI 衣柜长什么样
Wardrobe 把每件衣物以「透明底商品图 + 可选模特效果图」的形式存入本地画廊,支持按上装、裤装、鞋履等分类筛选,并可编辑名称、颜色与标签。所有数据——原图、任务记录、生成图、JSON 数据库——都保存在本地data/目录,这正是后文状态机与恢复机制的落点。
🧩 Job 状态机:把 AI 图像任务拆成 3 个可追踪阶段
上传一张照片后,视觉模型先识别图中所有衣物,每件衣物独立创建一个 job。每个 job 内部固定包含 3 个阶段(stage):
- crop(裁剪):按检测框裁出目标衣物,进入人工确认;
- garment(商品图):调用 gpt-image 在纯色背景下重构完整衣物,再本地抠除背景得到透明底商品图;
- modeled(模特图):把商品图与本人参考照一起交给模型,生成横版上身效果图。
每个阶段都有统一的状态字段:status(pending / queued / processing / review / approved / rejected / failed)、decision、attempts、assetUrl、error等,初始状态定义见 scripts/import-job-api.mjs。
状态如何流转:approve / reject / regenerate
- pending → processing → review:阶段生成完成后进入 review,等待你在界面上审核;
- review → approved:批准 crop 会自动触发 garment 生成;批准 garment 会把衣物写入衣橱数据库并触发 modeled 生成;批准 modeled 则把整个 job 标记为
complete并归档; - review → rejected:整条任务连同图片文件一起删除,队列保持干净;
- review → queued(regenerate):可附上一句"再生成方向"提示词重新生成,
attempts计数 +1,历史产物文件保留供对照; - processing → failed:API 报错或背景清洗失败都会把
error写入状态,并保留失败源图,支持本地"背景重清理"而不必重新调用模型。
关键约束:只有处于 review 的阶段才允许 approve/reject,其他状态下调用会返回 409,防止界面与后端状态错乱,流转逻辑见 scripts/import-job-api.mjs。
另外,同一 job 的同一阶段用内存锁(jobId:stage)去重——重复点击"重试"不会并发发起两次图像生成,见 scripts/import-job-api.mjs。
💾 原子写入:job.json 为什么永远不会被写坏
任务状态文件(data/jobs/<job-id>/job.json)和衣橱数据库(data/library.json)的每次更新都走同一个atomicJson函数,思路是经典的"临时文件 + rename":
- 先写入一个带随机 UUID 的临时文件
<目标文件>.<uuid>.tmp; - 再用文件系统原生的
rename把临时文件原子地覆盖到目标路径——同一目录内的 rename 要么完整成功、要么不发生,不存在"写了一半"的中间状态; - 若 rename 因文件系统限制失败(
EBUSY / EXDEV / EPERM),回退为copyFile+ 删除临时文件。
实现见 scripts/import-job-api.mjs。配合两个工程习惯,可靠性进一步拉满:
- 先落盘,再干活:每次发起 AI 生成前,先把阶段状态改为
processing并保存 job,再开始耗时的图像调用; - 磁盘是唯一事实源:每次状态变更都重新读取最新副本再修改,避免内存里的过期对象覆盖新状态,核心生成流程见 scripts/import-job-api.mjs。
即使进程在"生成中"被强杀,job.json也只会停留在processing或pending,绝不会出现半截 JSON。
🛡️ 崩溃自动恢复:重启后任务从断点继续
让状态机真正"可靠"的最后一块拼图,是启动时的恢复钩子。插件在configResolved阶段(挂载于 vite.config.mjs)扫描data/jobs/,对每个遗留 job 自动决策,逻辑见 scripts/import-job-api.mjs:
| 遗留状态 | 自动动作 |
|---|---|
status: complete但尚未归档 | 补写data/library.json与归档图片,然后删除 job 目录 |
任一阶段被rejected | 视为已放弃,直接清理目录 |
| crop 尚未批准 | 保持等待,交回给用户审核 |
garment 停在processing / queued(生成中被崩溃打断) | 重置为pending并自动重新发起生成 |
garment 已批准、modeled 停在pending / processing / queued | 重置为pending并自动续跑模特图生成 |
也就是说:AI 任务跑到一半断电、服务重启,不需要任何手工干预,任务会自动从磁盘上的断点状态继续。这正是"状态机 + 原子写入"组合的价值——内存可以丢,磁盘上的状态永远可信。
🖥️ 前端如何消费任务状态:轮询 + 人工审核
前端导入面板(src/import-flow.jsx)把后端状态机翻译成人类可读的进度:
- 状态推导:
deriveStatus按 modeled → garment → crop 的优先级推导当前文案(如"Styling modeled image""Ready for review"),见 src/import-flow.jsx; - 自动刷新:只要还有阶段处于
processing / queued,就以 900ms 间隔轮询 job 状态,界面实时跟进,见 src/import-flow.jsx; - 三个审核动作:审核通过 / 拒绝 / 带提示词再生成,一一对应状态机上的
approve / reject / regenerate; - 失败兜底:生成失败时打开"背景清理"编辑器,拖动容忍度滑杆在本地重算抠图效果(不再调用图像模型),满意后一键接受,见 src/import-flow.jsx。
📁 源码地图:按路径快速定位
| 想改什么 | 看哪里 |
|---|---|
| job 创建、状态流转、生成编排 | scripts/import-job-api.mjs |
| 原子写入实现 | scripts/import-job-api.mjs |
| 崩溃恢复钩子 | scripts/import-job-api.mjs |
| 前端导入面板与审核交互 | src/import-flow.jsx |
| 插件挂载(dev / preview 双端生效) | vite.config.mjs |
| 响应式图片服务 | scripts/responsive-image-api.mjs |
| 配置项与快速开始 | README.md |
| 贡献指南 | CONTRIBUTING.md |
数据布局全部在本地data/:data/jobs/<job-id>/存原图、裁剪图与各次生成产物及job.json;data/library.json是衣橱数据库;data/imported/存归档图片。
✅ 小结:可迁移到任何 AI 任务项目的 3 条经验
Wardrobe 的可靠性设计可以浓缩为三条:
- 把长任务拆成有限阶段,每阶段显式状态机——状态先落盘,再干活;
- 所有持久化文件走"临时文件 + rename"原子写入——杜绝半截文件;
- 启动时按状态机规则自动修复 / 续跑——崩溃只是中断,不是失败。
掌握这套「job 状态机 + 原子写入 + 崩溃自动恢复」的组合,你构建的任何 AI 图像任务流水线都会更稳、更省心。
【免费下载链接】wardrobeYour clothes, extracted and organized with gpt-image.项目地址: https://gitcode.com/gh_mirrors/wardro/wardrobe
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考