From e9072aecf2ac6ec856c82357cee894f41fb8ac0a Mon Sep 17 00:00:00 2001 From: Ukawka <140130066+Ukawka@users.noreply.github.com> Date: Mon, 21 Sep 2026 00:23:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 118 +++++++++ README.md | 311 +++++++++++------------ docs/1-understanding-stage.md | 454 +++++++++------------------------- docs/2-segmentation-stage.md | 202 +++++++++------ docs/3-completion-stage.md | 252 +++++++++++-------- docs/model-stages.md | 172 ------------- 6 files changed, 643 insertions(+), 866 deletions(-) delete mode 100644 docs/model-stages.md diff --git a/AGENTS.md b/AGENTS.md index 1c2c2c9..ec5af1e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,3 +17,121 @@ - 测试在 `ai-spine` 环境下执行:`conda run -n ai-spine npm test`。不要为了绕过依赖问题临时新建环境。 - 验证结果必须如实记录;缺少依赖导致未运行的检查,不得声称通过。 - 保留用户已有修改和实验产物,不覆盖旧实验输出。 + +## 跨会话上下文与阅读顺序 + +本节于 2026-09-21 根据当前代码与已检查产物整理。它是后续对话的上下文入口;后续修改应同步更新对应状态,实际源码、配置和具体实验 manifest 优先于历史总结。不要把旧实验统计套到新输出上。 + +1. 先阅读本文件和 `git status --short`,保留用户已有修改。 +2. 阅读 [README](README.md) 了解项目、环境、配置与命令。 +3. 按任务阅读 [第一阶段](docs/1-understanding-stage.md)、[第二阶段](docs/2-segmentation-stage.md)、[第三阶段](docs/3-completion-stage.md),再核对相关实现与实际产物。 +4. 用户说“继续”时,先核对工作区和最近任务进展,不能只凭历史总结重复请求付费模型或覆盖实验。 + +## 用户目标与固定偏好 + +- 目标是将单张 2D 角色图拆成可以用于 Spine 的部件,保留画风、姿态、左右、不对称性及原有像素关系,补足遮挡和关节连接。 +- 第二阶段使用本地 SAM 代码和权重,通过临时 Conda 子进程在本机 GPU 推理,完成后退出;不部署常驻独立服务。 +- 需要可直接执行的 PowerShell 命令;说明当前已实现行为、实测结果与未来计划,不能把几何通过写成资产合格。 +- 不确定的部件语义、遮挡和候选点需要复核,不得用前景检查、覆盖率或模型分数代替语义准确性。 +- 输出使用独立目录,保留原候选和诊断;已有候选优先离线复检,避免无意义重复生成。 + +## 文档维护约定 + +- 各文档文件名保持不变。`docs/` 当前保留三份阶段文档;`docs/model-stages.md` 在本次文档整理前已处于用户删除状态,不自行恢复,相关说明归入 README 和阶段文档。 +- 三份阶段文档有且仅有以下八个二级章节,细节必须归入对应章节: + 1. 阶段简介 + 2. 输入、输出与执行链路 + 3. 阶段执行命令示例及参数说明 + 4. 输入格式要求 + 5. 执行链路中重要部分代码文件及原理说明(包括重点说明) + 6. 各个代码文件职责索引 + 7. 产物详细说明 + 8. 当前阶段可改进点说明 +- 外层 README 负责整体介绍、Conda 准备、配置及每阶段命令;本文件负责约定和后续会话必要上下文。已存在的环境与修改约定必须保留。 +- 改进项明确写为待实现/待验证;实现后更新状态、命令、产物说明及本文件。PowerShell 反引号后不能有空格;示例变量先定义,示例输出目录相互独立。 + +## 工作区、环境与配置 + +- 当前实际项目目录:`F:\Study\taonier\AI_spine`。用户历史命令也出现过 `F:\Study\taonier\AI\_spine`,不要盲目复制旧路径,先确认 cwd。 +- 当前 SAM 根目录为 `F:\Study\SAM3`;源码仓库 `F:\Study\SAM3\sam3`;权重 `F:\Study\SAM3\sam3.1checkpoint\sam3.1_multiplex.pt`。早期 `F:\Study\sam3.1` 已不是当前约定路径。 +- 已验证组合:Python 3.11、torch 2.7.1+cu126、torchvision 0.22.1、NumPy 1.26.4、OpenCV 4.11.0.86;RTX 3060 Laptop 6 GB。机器环境可能变化,执行前按需探测。 +- Node.js >=20,无额外 npm 运行时依赖。自动化使用 Conda ai-spine 执行 Node/Python;运行 SAM 可用 `conda run --no-capture-output -n ai-spine node ...`。 +- 默认配置是 `configs/astra-qwen.json`;示例推荐明确传 config,避免环境变量导致选错提供方。 +- `configs/deepseek-qwen.json`:deepseek-flash / Chat Completions / 非流式;补全 qwen-image-3.0。 +- `configs/astra-qwen.json`:gpt-6-astra / Responses / 流式;补全 qwen-image-3.0。 +- 上述两份读取 VECTOR_ENGINE_BASE_URL / VECTOR_ENGINE_API_KEY,模型变量为 SPINE_UNDERSTANDING_MODEL / SPINE_COMPLETION_MODEL。 +- `configs/tiantoken.json`:独立 TIANTOKEN_BASE_URL / TIANTOKEN_API_KEY,地址 https://api.tiantoken.com;理解 gpt-6-astra,补全 gpt-image-2;模型变量为 TIANTOKEN_UNDERSTANDING_MODEL / TIANTOKEN_COMPLETION_MODEL。 +- CLI 模型 > stage.model > 对应模型环境变量 > default_model;shell 同名变量优先于 .env。模型 ID 原样发送,不加隐式别名。 +- 用户提供的密钥仅留在本地忽略的 `.env`;禁止在文档、命令日志、聊天或提交中暴露,不要读取/打印完整 .env 来诊断。 +- 三份配置的图片编辑能力均为 multiple_images=false、mask=false。接口已预留分支不代表中转已支持;开启前需验证。Astra 理解接口与图片编辑接口不同,当前没有 Astra Responses 图片生成工具链。 + +## 三阶段实现与不能丢失的边界 + +### 第一阶段:理解与几何候选 + +- 入口 `tools/model-check.mjs --stage understanding`,或 `pipeline.mjs --mode annotated-parts`;后者仅转发新入口。 +- `stages/model-stage.mjs` 调用视觉模型,`lib/validate-parts.mjs` 校验 v2:rig_role、bind_to、三项 completion 及 needs_completion 一致性。 +- `normalize_reference.py` 保留原画布,使用 Alpha 或边界连通近白背景处理;`geometry_grounding.py` 用 Alpha/ROI 距离变换生成候选,不是再次请求 AI。 +- 模型原始点仅诊断;程序候选也未获语义确认;pivot 独立保留,不吸附前景。 +- 第二阶段输入必须为同一实验的 source.png、semantic-parts.json、segmentation-prompts.json。 +- `--parts-file` 可离线迁移 v1/检查 v2 并生成新候选;旧 annotated.svg 不会自动更新。 + +### 第二阶段:SAM 可见拆件 + +- 入口 `--stage segmentation --input-dir 理解目录`;实现为 stages/segmentation-stage.mjs、sam_runtime.py、sam_segment.py、segmentation_outputs.py。 +- 环境探测与推理分别为短期子进程,禁止在线下载权重。multiplex detector 适配实际严格加载 1130 个张量,忽略 36 个未使用视频 neck 张量;不要因此改成 strict=False 或修改外部 SAM 源码。 +- BF16 仅用于推理 autocast;不要整体转换模型而破坏复数缓冲区/FP32 路径。 +- 使用文本和文本+粗框两组候选;当前图像概念接口未接收点提示,Alpha 种子仅参与 mask 排序。 +- 与原图 Alpha 取交集后提取原像素;mask 为原画布二值图,parts 为紧裁剪 RGBA。重叠保留、覆盖率仅为像素覆盖,semantic_verified=false。 +- annotated.png 为原图纹理上半透明颜色叠加,parts-sheet.png 为白底拆件;纯色遮罩角色图与可选大模型去毛边尚未实现。 + +### 第三阶段:受限部件补全 + +- 入口 `--stage completion --input-dir SAM目录`;实现为 stages/completion-stage.mjs、completion_geometry.py、providers/image-edits.mjs。 +- 输入须含 source.png、v2 计划、segmentation.json 及所有记录的全画布 masks;单独 parts/ 不够。 +- 仅处理 needs_completion=true、非隐藏、有可见 mask 且允许区域非空的部件。--part 不绕过筛选;目前不重新评估 SAM 缺损。 +- 默认 1024 方形局部画布,原像素不缩放。允许区来自轮廓外 32 像素范围与遮挡 mask / pivot 圆盘交集,排除可见 mask;不是完整隐藏形状生成。 +- 当前真实请求只发白底 input.png;context.png、edit-mask.png 默认不发送。开启 multiple_images 也只是发送同坐标局部 context,并非独立全角色参考。 +- 图片解码已修复“空 b64_json 但有有效 URL”情况,回退下载 URL;该问题与画布尺寸不符不同。 +- 在线请求现显式传 size,配置冲突失败。strict 默认拒绝尺寸不同;uniform 仅恢复同宽高比整画布尺寸,保留原候选,继续原有验收,不单独移动/缩放物体。 +- 验收阈值:可见不透明像素 RGB MAE≤30、保留率≥95%;有效新增须在允许区且连接可见部件;原可见 RGBA 随后逐像素恢复。 +- unfulfilled_regions 当前只记录、不硬拒绝;语义错误、接缝、关节补够与否尚无可靠验收。错误 SAM 可见像素会被强制保留。 +- prepare-only 不联网;candidates-dir 可读平铺 ID.png 或匹配 manifest 的旧任务首张候选。--resume 不是失败断点续发,准备/生成/复检使用独立目录。 +- parts/ 只含通过检查的补全部件,不包含全部原拆件。完整角色组装、旋转验收、新管线 Spine 导出尚未接入。 +- 旧 `--stage completion --image ... --prompt-file ...` 是接口探针,不能和 input-dir 混用,不执行完整几何验收。 + +## 已检查实验与质量结论 + +以下为已有实验记录,不代表后续每次运行的结果;不必为了文档修改重跑 GPU 或付费模型。 + +| 目录(相对于项目) | 事实与意义 | +| --- | --- | +| output/sombrero-grounding-v2 | 旧计划离线几何检查,28 个程序候选通过前景检查;未证明语义正确 | +| output/sombrero-sam31-v3 | 较早 SAM 实验,28 个 mask,约 67.18% 覆盖率;肢体/鞋子重复、漏分,不合格 | +| output/20260918-183532/sam | 当前讨论基线:32 个计划项、10 个 hidden、22 个 mask;约 83.3% 覆盖,32719 像素未分配;前臂/手混入衣料、袖子与上衣缺损 | +| output/20260918-183532/complete2_gpt | 真实 Tiantoken gpt-image-2 请求 12 部件;旧请求未传 size,返回 1248/1254,预期 1024,全部 CANVAS_SIZE_MISMATCH | +| output/20260918-183532/complete2_gpt-size-recheck-v2 | 离线 uniform 复检,未重生成:8 个几何通过;head、pants_thigh_l、pants_thigh_r、shoe_l 4 个拒绝;通过项仍有误分和未完成区域 | +| output/20260918-183532/complete-recovered-head-check | 更早 Qwen 头部候选恢复检查,不能与 GPT 批次混为一谈 | + +- 当前 22→12 的原因:sombrero、sleeve_l、sleeve_r、eye_l、eye_r、eyebrow_l、eyebrow_r、nose、mouth、mustache 共 10 个被第一阶段标记 NO_COMPLETION_NEEDED;不能解释为它们的实际 SAM mask 已完整。 +- 2026-09-20 尺寸修复后曾通过 22 项 Node 测试(含 Python 补全回归)。这是历史验证;新改动按范围重新验证,不自动沿用“全部通过”。显式 size 构造已测试,修复后中转是否遵守尚无新实测。 +- 总体判断:上游部件归属、模型缺少原图参考与遮罩、区域规则粗糙、验收不足共同导致低质量。不能仅换模型、强制处理全部 mask、放宽阈值或解决尺寸错误就宣称修好。 + +## 当前改进方向与后续顺序 + +本轮用户要求重整文档,以下功能是待实现需求,不因写入文档就成为已完成功能: + +1. 第二阶段输出仅色彩遮罩组成的完整角色图,保留当前原图叠色预览,并明确未分配/重叠区域。 +2. 第二阶段每个 SAM 部件可选经过一次大模型去毛边,保留原始拆件、原图参考、坐标、变更区域与前后对照。 +3. 第三阶段将角色原图或部件相关原图局部作为参考交给补全模型,验证中转多图/遮罩能力及实际发送内容。 +4. 第三阶段输出使用补全部件组装的完整角色,复用无需补全的原部件,明确失败/回退状态。 +5. 技术优先级:先修正 SAM 部件归属与输入门槛,再按实际 mask 重建补全计划;用头、前臂、上衣三类小样验证参考图和遮罩,然后增加回贴与关节旋转验收,最后批量与 Spine 导出。 + +详细改进说明保留在各阶段文档第 8 节;若后续用户改变优先级,应更新此处。 + +## 旧管线与范围识别 + +- `pipeline.mjs` 未指定 --mode annotated-parts 时走旧“生成拆件图→CV 定位→Spine”流程,不是新三阶段自动串联。 +- `segment.py` 为旧拆件图分割;`compose_preview.py` 为旧布局组装;`run_case_matrix.py` 为旧定位对照工具。不要因为 IDE 当前打开这些文件就误改新阶段入口。 +- 相邻 `spine-animation-ai` 为外部只读依赖,保留其 PolyForm Noncommercial 许可证约束;新阶段尚未复用为完成的导出流程。 +- 不要把文档改写任务扩大成付费图片生成、SAM 推理、依赖安装或功能实现;需要实现时遵从用户后续任务范围。 diff --git a/README.md b/README.md index 99324b4..c3ceed8 100644 --- a/README.md +++ b/README.md @@ -1,83 +1,45 @@ # AI Spine 角色拆件与动画管线 -本项目用于把单张 2D 角色参考图转换为可供 Spine 动画使用的语义部件、透明拆件和骨骼资源。 +本项目探索将单张 2D 角色图转换为可用于 Spine 动画的部件与骨骼资源。当前主线分为三个阶段:视觉 LLM 理解结构、本地 SAM 分割可见部件、图片编辑模型补全隐藏区域和关节连接。 -当前正在实现的新管线分为三个核心阶段: +| 阶段 | 输入 → 输出 | 当前状态 | +| --- | --- | --- | +| 1. 结构理解 | PNG → v2 语义计划、粗框、pivot、程序候选点 | 可在线理解或离线复检;语义待复核 | +| 2. SAM 分割 | 第一阶段目录 → mask、原像素透明部件、标注图与拆解图 | 本机 GPU 实测可运行;存在误分与漏分 | +| 3. 部件补全 | SAM 目录 → 局部编辑候选、几何 QA、通过检查的补全部件 | 已真实调用图片模型;结果质量尚不合格 | -1. 视觉 LLM 输出语义、层级、骨骼/附件分类、遮挡、粗框和粗关节;程序用 Alpha 检查 ROI 并生成候选种子。 -2. 使用 SAM 根据语义、粗框和程序候选生成 mask,经语义/几何检查后从原图提取可见像素。 -3. 使用图片编辑模型补全被遮挡的部件,再进行几何验收和 Spine 导出。 +第三阶段尚未输出使用补全部件组装的完整角色,新管线 Spine 导出也未完成。执行成功、mask 覆盖率高、几何检查通过,均不等于动画资产可用。 -目前第一、二阶段可运行,第三阶段已接入部件画布准备、图片编辑请求、候选几何检查及可见像素恢复。第二阶段在 `ai-spine` Conda 环境的临时子进程中加载本地 SAM 3.1 权重,使用 GPU 分割并生成半透明标注图、白底拆解图和透明部件。分割与补全结果仍需语义复核;新管线的 Spine 导出尚未完成。第三阶段已通过离线及 mock 接口验证,真实图片编辑质量尚待验证。 +仓库保留旧版“生成白底拆件图 → OpenCV 拆分 → Genielabs 定位 → Spine 导出”作为对照;它与当前三阶段主线并存,产物不能直接混用。 -仓库仍保留旧版“AI 生成白底拆件图 → OpenCV 拆分 → Genielabs 定位 → Spine 导出”流程,用于对照和回归测试。 +## 文档入口 -## 文档 +- [AGENTS.md](AGENTS.md):修改约定、跨会话上下文、当前基线及后续优先级。 +- [第一阶段](docs/1-understanding-stage.md):理解、数据契约、Alpha 候选与粗标注。 +- [第二阶段](docs/2-segmentation-stage.md):本地 SAM、mask 选择、拆件与质量边界。 +- [第三阶段](docs/3-completion-stage.md):筛选、局部画布、图片请求、几何验收及补全改进。 -- [项目修改约定](AGENTS.md):每次修改都必须遵守,Python 固定使用 `ai-spine` Conda 环境。 -- [第一阶段:视觉 LLM 角色结构理解](docs/1-understanding-stage.md):执行流程、代码对应关系、数据格式和输出文件。 -- [第二阶段:本地 SAM 分割](docs/2-segmentation-stage.md):环境、运行命令、权重适配、输出和质量边界。 -- [第三阶段:部件补全](docs/3-completion-stage.md):局部画布、遮挡/关节延展区域、生成调用、可见像素恢复及几何检查。 -- [模型阶段配置与实验说明](docs/model-stages.md):模型切换、协议适配、图片编辑探针、缓存和错误处理。 +阶段文档统一采用八节:简介;输入输出与链路;命令参数;输入格式;重要代码原理;职责索引;产物;可改进点。配置与实验说明已归入上述文档。 -## 环境准备 +## Conda 环境准备 -### Node.js +所有 Python 操作固定使用 **ai-spine**,不使用 `.venv`、其他虚拟环境、Conda base 或系统 Python。Node.js 要求 20 或以上;项目没有额外 npm 运行时依赖。 -第一阶段要求 Node.js 20 或更高版本,以及下方 Python 几何依赖;没有额外 npm 运行时依赖。 +在 PowerShell 中进入实际项目根目录。本工作区路径如下;若本机使用其他目录,仅替换这一行: ```powershell +Set-Location F:\Study\taonier\AI_spine node --version -conda run -n ai-spine npm test +conda env list ``` -### 中转站配置 - -在项目目录复制环境变量模板: +仅在没有 ai-spine 环境的新机器上,手动创建一次;当前机器已有环境则跳过: ```powershell -Copy-Item .\.env.example .\.env +conda create -n ai-spine python=3.11 -y ``` -编辑 `.env`: - -```dotenv -VECTOR_ENGINE_BASE_URL=https://router.genarrative.world/v1 -VECTOR_ENGINE_API_KEY=你的令牌 - -# 可选:覆盖配置文件中的默认模型 -SPINE_UNDERSTANDING_MODEL=deepseek-flash -SPINE_COMPLETION_MODEL=qwen-image-3.0 - -# 本地 SAM 根目录和源码仓库;分割结束后子进程退出 -SAM_MODEL_DIR=F:/Study/SAM3 -SAM_CODE_DIR=F:/Study/SAM3/sam3 -``` - -模型 ID 会原样发送给中转站,不进行隐式别名转换。不要把 API Key 写进 JSON 配置或提交到版本库。 - -另一个中转站 Tiantoken 使用独立配置 [configs/tiantoken.json](configs/tiantoken.json)。在本地 `.env` 设置 `TIANTOKEN_BASE_URL=https://api.tiantoken.com` 和 `TIANTOKEN_API_KEY`,运行时增加 `--config .\configs\tiantoken.json`;原中转站配置保持独立。 - -```powershell -node .\tools\model-check.mjs --config .\configs\tiantoken.json --list-models -node .\tools\model-check.mjs --config .\configs\tiantoken.json --dry-run -``` - -该配置默认第一阶段使用 `gpt-6-astra`(Responses),第三阶段使用 `gpt-image-2`(images/edits),可通过 `TIANTOKEN_UNDERSTANDING_MODEL`、`TIANTOKEN_COMPLETION_MODEL` 或对应 CLI 参数覆盖。2026-09-20 已验证认证与模型列表访问,返回 113 个模型,含上述两个 ID;尚未验证实际理解、图片编辑或 Responses 图片生成工具能力。此配置不等于已接入 Astra 主导的第三阶段图片生成。 - -### Python 与外部项目 - -本项目固定使用 **Conda 环境 `ai-spine`**,不使用或创建 `.venv`。第一阶段的 Alpha 校验需要 Python 3、`Pillow`、`numpy`、`opencv-python`。 - -执行项目命令前先 `conda activate ai-spine`。Node 管线会检查 Python 属于该 Conda 环境;`--python` 也只能指定该环境的解释器。未激活环境或缺少依赖时会报错,不会自动创建环境或安装依赖。 - -旧版拆件和 Spine 导出还需要: - -- Python 3; -- `Pillow`、`numpy`、`opencv-python`; -- 相邻目录中的 `spine-animation-ai` 项目。 - -当前本机验证组合为 Python 3.11、PyTorch 2.7.1 + CUDA 12.6、torchvision 0.22.1。在 `AI_spine` 目录补全依赖;已有此 CUDA 版本时跳过第一条安装命令: +补齐项目依赖。以下是本机已验证的 CUDA 12.6 组合;已有匹配 PyTorch 时可跳过第一条安装命令。代码不会自动安装依赖或创建环境。 ```powershell conda activate ai-spine @@ -86,174 +48,183 @@ python -m pip install -r .\requirements.txt python -m pip install --no-deps --no-build-isolation -e F:\Study\SAM3\sam3 ``` -不激活终端也可明确指定安装目标: +不激活终端时,明确指定目标环境: ```powershell conda run -n ai-spine python -m pip install -r .\requirements.txt ``` -检查解释器和依赖: +本地 SAM 代码和权重由用户提供,当前位置为: -```powershell -conda run -n ai-spine python -c "import sys, cv2, PIL, numpy; print(sys.executable); print('Dependencies OK')" +```text +F:/Study/SAM3/sam3/ 源码仓库 +F:/Study/SAM3/sam3.1checkpoint/sam3.1_multiplex.pt 权重 ``` -`spine-animation-ai` 是外部只读依赖,使用时需要遵守其 PolyForm Noncommercial 许可证。 - -## 常用命令 - -以下命令默认在 `AI_spine` 目录、已激活的 `ai-spine` Conda 环境中运行。自动化可使用 `conda run -n ai-spine node ...`。 - -### 查询中转站模型 +检查解释器、基础依赖与 GPU: ```powershell -node .\tools\model-check.mjs --list-models +conda run -n ai-spine python -c "import sys, cv2, PIL, numpy, torch; print(sys.executable); print('torch', torch.__version__); print('CUDA', torch.cuda.is_available()); print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'No CUDA GPU')" ``` -### 检查本地配置 +第二阶段要求可用 CUDA GPU。本机已验证 RTX 3060 Laptop 6 GB;默认 BF16 推理保留模型参数和缓冲区所需精度。第一、三阶段的本地几何处理不运行 SAM。Node 入口会验证 Python 属于 ai-spine;`--python` 也不能绕过此约定。 -不请求模型,也不生成付费内容: +## 中转站配置 + +仅在本地 `.env` 不存在时复制模板,随后自行填写密钥: ```powershell -node .\pipeline.mjs --mode annotated-parts ` +if (-not (Test-Path .\.env)) { Copy-Item .\.env.example .\.env } +``` + +```dotenv +# 原中转站 +VECTOR_ENGINE_BASE_URL=https://router.genarrative.world/v1 +VECTOR_ENGINE_API_KEY=填写你的令牌 + +# Tiantoken 独立配置 +TIANTOKEN_BASE_URL=https://api.tiantoken.com +TIANTOKEN_API_KEY=填写你的令牌 + +# 本地 SAM +SAM_MODEL_DIR=F:/Study/SAM3 +SAM_CODE_DIR=F:/Study/SAM3/sam3 +``` + +不要把密钥写入文档、JSON 配置或提交到版本库;不要输出 `.env` 内容。 + +| 配置文件 | 第一阶段 | 第三阶段 | 模型环境变量 | +| --- | --- | --- | --- | +| [deepseek-qwen.json](configs/deepseek-qwen.json) | deepseek-flash,Chat Completions,非流式 | qwen-image-3.0,images/edits | SPINE_UNDERSTANDING_MODEL / SPINE_COMPLETION_MODEL | +| [astra-qwen.json](configs/astra-qwen.json) | gpt-6-astra,Responses,流式 | qwen-image-3.0,images/edits | 同上 | +| [tiantoken.json](configs/tiantoken.json) | gpt-6-astra,Responses,流式 | gpt-image-2,images/edits | TIANTOKEN_UNDERSTANDING_MODEL / TIANTOKEN_COMPLETION_MODEL | + +CLI > 配置 stage.model > 对应模型环境变量 > default_model;shell 环境变量优先于 `.env`。不指定配置时入口默认 astra-qwen.json,建议实验始终显式指定。模型 ID 原样发送,中转能力以实际请求为准。Tiantoken 图片编辑已真实执行;第三阶段尚未适配 Astra Responses 图片生成工具。 + +三个配置当前均关闭多图参考与编辑 mask 能力。第三阶段默认只发送白底单部件图;本地 context.png/edit-mask.png 已生成但不默认发送。改进计划见第三阶段文档。 + +查询模型列表和检查配置: + +```powershell +node .\tools\model-check.mjs --config .\configs\tiantoken.json --list-models +node .\tools\model-check.mjs --config .\configs\tiantoken.json --dry-run +``` + +前者联网,后者不请求模型;列表存在某个 ID 不代表其所有能力已验证。 + +## 三阶段执行命令 + +以下命令按顺序在同一个 PowerShell 会话执行。反引号后不能带空格。每次实验使用新的 runId;分阶段重开终端时,将路径变量设置成已有的对应目录。 + +```powershell +conda activate ai-spine +$runId = Get-Date -Format "yyyyMMdd-HHmmss" +$runRoot = ".\output\$runId" +$reference = ".\output\20260918-183532\sam\source.png" +``` + +示例复用现有角色原图,可替换 `$reference` 为自己的 PNG。不要混用不同实验的 source、计划和 mask。 + +### 第一阶段:理解角色结构 + +此命令调用视觉模型: + +```powershell +node .\tools\model-check.mjs --stage understanding ` --config .\configs\deepseek-qwen.json ` - --reference ..\spine-animation-ai\demo\character_reference.png ` - --dry-run + --reference $reference ` + --out-dir "$runRoot\understand" ``` -### 使用 DeepSeek Flash 理解角色结构 +检查 `understand/report.html`、`semantic-parts.json`、`geometry-validation.json`。程序候选点来自 Alpha 距离变换,落在前景不代表属于正确部件。 -当前已验证可用的配置是 `deepseek-flash + chat-completions + stream=false`: +已有计划可离线重新检查;输出独立目录,不重跑模型: ```powershell -node .\pipeline.mjs --mode annotated-parts ` - --config .\configs\deepseek-qwen.json ` - --reference ..\spine-animation-ai\demo\character_reference.png ` - --out-dir .\output\sombrero-understand-deepseek ` - --stop-after understand +node .\tools\model-check.mjs --stage understanding ` + --reference .\output\20260918-183532\sam\source.png ` + --parts-file .\output\20260918-183532\sam\semantic-parts.json ` + --out-dir "$runRoot\understand-offline" ``` -重点检查输出目录中的: - -- `report.html`:人工复核页面; -- `semantic-parts.json`:v2 语义计划,包含 `rig_role`、`bind_to`、三项 `completion`; -- `geometry-validation.json`:原始点诊断、框内前景比例、候选及阻塞原因; -- `segmentation-prompts.json`:程序生成的 SAM 候选提示;模型原始正负点不会传入; -- `validation.json`:本地结构校验结果; -- `manifest.json`:模型、输入、代码版本和产物记录。 - -输入保留画布尺寸。已有透明背景直接保留 Alpha;不透明白底只移除与边界连通的近白区域。其他背景需先提供抠图 PNG。候选来自粗框内前景的距离变换,不能保证属于目标部件,仍需语义复核。关节点不会吸附到前景。 - -已有结果可离线检查,无需再次请求模型: +### 第二阶段:本地 SAM 分割 ```powershell -node .\tools\model-check.mjs ` - --reference .\output\sombrero-understand-deepseek-flash\source.png ` - --parts-file .\output\sombrero-understand-deepseek-flash\semantic-parts.json ` - --out-dir .\output\sombrero-grounding-review -``` - -旧版 v1 计划会保守迁移到 v2,迁移推断写入 notes,仍需复核;原文件不覆盖。 - -### 使用 GPT-6 Astra 做对照实验 - -```powershell -node .\pipeline.mjs --mode annotated-parts ` - --config .\configs\astra-qwen.json ` - --reference ..\spine-animation-ai\demo\character_reference.png ` - --out-dir .\output\sombrero-understand-astra ` - --stop-after understand -``` - -当前中转站的 Astra 通道要求 Responses 协议和流式响应。若中转站返回 overloaded,应使用新的输出目录稍后重试。 - -### 临时覆盖理解模型 - -```powershell -node .\pipeline.mjs --mode annotated-parts ` - --config .\configs\deepseek-qwen.json ` - --understanding-model YOUR_EXACT_MODEL_ID ` - --understanding-protocol chat-completions ` - --stream false ` - --reference .\reference.png ` - --out-dir .\output\model-experiment ` - --stop-after understand -``` - -每组模型实验应使用独立的输出目录,避免覆盖对照结果。只有输入、配置、代码和产物哈希全部一致时,才可以通过 `--resume` 复用结果。 - -### 使用本地 SAM 生成标注和拆解图 - -复用已有第一阶段结果,不重新请求 DeepSeek,也不需要中转站密钥: - -```powershell -conda run --no-capture-output -n ai-spine node .\tools\model-check.mjs ` - --stage segmentation ` - --input-dir .\output\sombrero-grounding-v2 ` - --out-dir .\output\sombrero-sam-local ` +node .\tools\model-check.mjs --stage segmentation ` + --input-dir "$runRoot\understand" ` + --out-dir "$runRoot\sam" ` --sam-dir F:/Study/SAM3 ``` -打开输出目录的 `report.html`:`annotated.png` 是原图上的不同半透明颜色标注,`parts-sheet.png` 是白底拆解图,`parts/` 保存原像素透明部件。运行期间加载 GPU 权重,完成后子进程退出,不启动常驻服务。 +若使用前面的离线计划,input-dir 改为 understand-offline。该命令只运行本地临时 GPU 子进程;添加 `--dry-run` 可探测环境而不加载模型。检查 `sam/report.html`、`annotated.png`、`parts-sheet.png`、漏分图和 mask 归属,错误部件应先修正。 -加入 `--dry-run` 可检查环境与本地路径,不加载权重推理。输入必须含 `source.png`、v2 `semantic-parts.json`、`segmentation-prompts.json`。完整参数与质量检查见[第二阶段文档](docs/2-segmentation-stage.md)。 +### 第三阶段:准备与补全 -### 第三阶段:按部件补全 - -先从已有 SAM 输出准备画布、允许新增区域和提示词,不请求模型: +先离线准备任务,不请求模型: ```powershell node .\tools\model-check.mjs --stage completion ` - --input-dir .\output\sombrero-sam31-v3 ` - --out-dir .\output\sombrero-completion-prepare ` - --completion-model qwen-image-3.0 ` + --config .\configs\tiantoken.json ` + --input-dir "$runRoot\sam" ` + --out-dir "$runRoot\complete-prepare" ` --prepare-only ``` -打开 `report.html` 检查部件和允许新增区域。以下命令对 `head` 发起一次部件编辑任务,再检查候选并恢复原图可见像素;会调用中转站图片模型: +复核允许区域后,按实际存在的 ID 试一个部件;下面会调用图片模型: ```powershell node .\tools\model-check.mjs --stage completion ` - --input-dir .\output\sombrero-sam31-v3 ` - --out-dir .\output\sombrero-completion-head ` - --completion-model qwen-image-3.0 ` + --config .\configs\tiantoken.json ` + --input-dir "$runRoot\sam" ` + --out-dir "$runRoot\complete-head" ` --part head ``` -`--part` 可重复;省略则处理所有具备可见 mask、补全需求和允许区域的部件。当前 SAM 示例仍有错分,应先复核。补全不会自动纠正上游语义;通过几何检查的 PNG 保存到 `parts/`,仍需人工复核。完整参数、离线候选导入与限制见[第三阶段文档](docs/3-completion-stage.md)。 - -第三阶段请求会显式发送与局部画布一致的 `size`(默认 `1024x1024`)。如果中转站仍返回其他尺寸,可使用 `--candidates-dir 旧补全目录 --candidate-size-policy uniform` 离线复查:只允许同宽高比的画布等比例缩放,保留原候选,继续检查位置与新增区域并恢复原像素。默认 strict 模式仍拒绝尺寸不符;详细命令见第三阶段文档。 - -### 单独测试图片补全接口 - -此命令只验证图片编辑适配器并保存原始候选,不代表补全部件已经验收通过: +处理所有具备可见 mask、补全需求和允许区域的部件: ```powershell node .\tools\model-check.mjs --stage completion ` - --image .\local-part.png ` - --prompt-file .\task.txt ` - --out-dir .\output\qwen-edit-test ` - --completion-model qwen-image-3.0 + --config .\configs\tiantoken.json ` + --input-dir "$runRoot\sam" ` + --out-dir "$runRoot\complete" ``` -### 运行旧版完整管线 +省略 part 不意味着强制补全全部 mask。检查 `completion-plan.json` 的跳过原因和 `completion-result.json` 的 QA;parts/ 仅包含通过检查的补全部件。所有结果仍需语义复核。 + +旧候选尺寸不符时,可离线导入复检,避免重新生成: + +```powershell +node .\tools\model-check.mjs --stage completion ` + --config .\configs\tiantoken.json ` + --input-dir .\output\20260918-183532\sam ` + --candidates-dir .\output\20260918-183532\complete2_gpt ` + --out-dir "$runRoot\complete-size-recheck" ` + --candidate-size-policy uniform +``` + +uniform 仅恢复同宽高比的整画布尺寸,不纠正物体位移、变形或语义。在线请求现已显式传 size;参数及中转实测边界见[第三阶段文档](docs/3-completion-stage.md)。 + +## 旧管线与验证 + +旧版依赖相邻 `spine-animation-ai` 外部项目,使用时遵守其 PolyForm Noncommercial 许可证;不要修改外部依赖。旧版命令会调用图片生成并尝试定位、导出: ```powershell node .\pipeline.mjs ` - --reference ..\spine-animation-ai\demo\character_reference.png ` - --out-dir .\output\legacy-character ` + --reference $reference ` + --out-dir "$runRoot\legacy" ` --genielabs-dir ..\spine-animation-ai ` --image-model qwen-image-3.0 ` --attempts 1 ` --animations idle,walk,wave ``` -旧流程依赖生成式拆件与传统 CV 定位,对低纹理、低分辨率和生成后外观变化较大的角色不稳定。其输出应通过 `assembled.png` 和 `preview-rigged.html` 人工检查后再导入 Spine。 +`segment.py` 为旧版拆件分割,`compose_preview.py` 组装预览,`run_case_matrix.py` 对照定位方案;当前 SAM 入口为 sam_segment.py。旧产物需检查 assembled.png 和 preview-rigged.html,不能据此声称新三阶段已经完成 Spine 导出。 -### 运行测试 +测试与命令帮助: ```powershell -conda run -n ai-spine npm test +conda run --no-capture-output -n ai-spine npm test +node .\tools\model-check.mjs --help ``` -测试使用本地 mock HTTP 服务或注入响应,不调用真实付费模型。 +测试使用本地 mock 或注入响应,不请求真实付费模型。自动化运行任一阶段可用 `conda run --no-capture-output -n ai-spine node ...`。保留旧实验;resume 只复用完整匹配产物,失败任务另建输出目录。 diff --git a/docs/1-understanding-stage.md b/docs/1-understanding-stage.md index 61c1d31..b295903 100644 --- a/docs/1-understanding-stage.md +++ b/docs/1-understanding-stage.md @@ -1,371 +1,147 @@ # 第一阶段:视觉 LLM 角色结构理解 -第一阶段把单张角色参考图转换为结构化的语义部件计划,供后续 SAM 分割、遮挡补全和 Spine 骨骼生成使用。 +## 1. 阶段简介 -本阶段只做角色结构理解和粗标注,不生成精确 mask、透明拆件 PNG 或补全后的隐藏部件。 +将单张角色图转换为部件语义计划:确定部件名称、骨骼与附件分类、运动层级、遮挡、可见区域粗框、关节点和补全需求。视觉模型负责结构理解;本地程序负责格式校验和前景候选点生成。 -## 1. 输入、输出与执行链路 +本阶段不生成精确 mask、透明拆件、隐藏纹理或 Spine 文件。结构合法不等于识别正确,结果仍为 `quality_status=needs_review`。 -输入是一张完整的 PNG 角色参考图。核心输出是 semantic-parts.json,其中记录: +## 2. 输入、输出与执行链路 -- 角色由哪些可动部件组成; -- 每个部件的语义名称; -- 部件之间的运动父子关系; -- 部件之间的视觉遮挡关系; -- 可见、部分可见或完全隐藏状态; -- 可见区域粗框、预计关节位置,骨骼/附件角色与绑定目标; -- 程序用 Alpha 校验后另行输出的 SAM 候选点; -- 是否需要在第三阶段补全; -- 模型对判断结果的自报置信度。 +输入为 PNG 角色图;在线模式需要模型配置与密钥,离线模式需要已有语义计划。核心输出为语义计划和 SAM 提示。 -整体执行链路: +```text +tools/model-check.mjs(或 pipeline.mjs --mode annotated-parts) +→ 读取配置、图片、提示词与 Schema,计算实验指纹 +→ Python 保留 Alpha / 去除边界连通白底,保持原画布 +→ 在线:视觉模型理解;离线:读取计划并按需迁移 v1 +→ 提取 JSON,校验字段、引用、层级和补全一致性 +→ 在 Alpha 前景与粗框交集中生成距离变换候选点 +→ 保存 semantic-parts.json、segmentation-prompts.json、诊断及报告 +→ 第二阶段读取 source.png + 计划 + SAM 提示 +``` -~~~text -角色原图 - ↓ -保留 Alpha 或去除边界连通白底(不缩放裁剪) - ↓ -读取模型配置、提示词和输出 Schema - ↓ -构造视觉 LLM 请求 - ↓ -DeepSeek Flash / GPT-6 Astra - ↓ -提取模型返回的 JSON 文本 - ↓ -Schema 校验和部件关系校验 - ↓ -semantic-parts.json - ↓ -Alpha / ROI 校验、距离变换候选点、segmentation-prompts.json - ↓ -生成 annotated.svg 和 report.html - ↓ -人工复核后交给 SAM 分割阶段 -~~~ +`--parts-file` 不请求模型,也不运行 SAM。`--stop-after segment` 可接续第二阶段,输出到理解目录的 `segmentation/`;第三阶段独立调用。 -## 2. 命令入口 +## 3. 阶段执行命令示例及参数说明 -示例: +以下 PowerShell 命令在项目根目录执行,环境准备见 [README](../README.md)。反引号必须在行尾,后面不能有空格。 -~~~powershell -node .\tools\model-check.mjs ` - --stage understanding ` - --understanding-model gpt-6-astra ` - --reference .\output\sombrero-grounding-v2\source.png ` - --out-dir ".\output\$runId\understand" ` - --config .\configs\tiantoken.json -~~~ +```powershell +conda activate ai-spine +$runId = Get-Date -Format "yyyyMMdd-HHmmss" +node .\tools\model-check.mjs --stage understanding ` + --config .\configs\deepseek-qwen.json ` + --reference .\output\20260918-183532\sam\source.png ` + --out-dir ".\output\$runId\understand" +``` -第一步由以下两个文件负责: +参考图可替换成自己的 PNG。切换 Tiantoken:将配置改为 `--config .\configs\tiantoken.json`,默认理解模型为 `gpt-6-astra`,也可显式传入 `--understanding-model gpt-6-astra`。 -1. [pipeline.mjs](../pipeline.mjs) 检测 --mode annotated-parts,把命令转交给新管线,不进入旧版“生成拆件图 → CV 定位”流程。 -2. [tools/model-check.mjs](../tools/model-check.mjs) 解析参数、加载配置、应用命令行覆盖、检查输入并调用 runUnderstanding()。 +已有计划离线生成新候选,不重跑 AI: -## 3. 配置解析 +```powershell +node .\tools\model-check.mjs --stage understanding ` + --reference .\output\20260918-183532\sam\source.png ` + --parts-file .\output\20260918-183532\sam\semantic-parts.json ` + --out-dir ".\output\$runId\understand-offline" +``` -当前提供两组实验配置: - -| 配置 | 理解模型 | 协议 | 流式 | -| --- | --- | --- | --- | -| [configs/deepseek-qwen.json](../configs/deepseek-qwen.json) | deepseek-flash | chat-completions | false | -| [configs/astra-qwen.json](../configs/astra-qwen.json) | gpt-6-astra | responses | true | - -[lib/config.mjs](../lib/config.mjs) 负责读取: - -- JSON 配置文件; -- 项目 .env 或 --env-file; -- 当前 shell 环境变量; -- 模型、协议、输出模式、超时和重试设置; -- 阶段提示词; -- SAM checkpoint 路径。 - -模型选择优先级: - -~~~text -命令行 --understanding-model - > stage.model - > SPINE_UNDERSTANDING_MODEL - > stage.default_model -~~~ - -Shell 环境变量优先于 .env。模型 ID 会原样传给中转站,不做隐式别名转换。 - -配置中的 params 不能覆盖模型、消息体、输入、流式选项和认证字段,避免实验配置改变基础请求语义或泄漏密钥。 - -## 4. 读取参考图 - -[lib/images.mjs](../lib/images.mjs) 读取参考图,并得到: - -- 原始文件字节; -- MIME 类型; -- 图片宽高; -- SHA-256; -- 模型请求使用的 Base64 Data URL。 - -本阶段要求参考图为 PNG。原始输入保存为 source-original.png,模型实际看到的预处理 RGBA 保存为 source.png,不缩放、不裁剪。已有透明背景时保留原像素;不透明白底使用连通域仅去除与画布边界相连、RGB 各通道均 ≥240 的区域。其他背景或空前景会在请求模型前失败,需先提供抠图 PNG。去白底存在白色主体接触边界的局限,预处理记录保存在 preprocessing.json。 - -这一层调用 normalize_reference.py 和 geometry_grounding.py,固定使用 Conda 环境 ai-spine 及 requirements.txt 中的依赖。先执行 conda activate ai-spine;自动化使用 conda run -n ai-spine node ...。--python 也只能指定该环境的解释器,不创建其他环境。每次修改须遵守 [AGENTS.md](../AGENTS.md)。 - -## 5. 理解提示词 - -提示词位于 [prompts/understand-v1.txt](../prompts/understand-v1.txt),要求视觉 LLM: - -- 保留角色原始姿势、朝向和不对称性; -- 仅在独立运动有意义且图像支持时拆分部件; -- 区分运动父子关系和视觉遮挡关系; -- 使用完整画布的归一化坐标; -- 输出语义、粗框、预计关节和 rig_role/bind_to;正负提示点留空; -- 不把粗框声称为像素级 mask; -- 不凭空创造没有视觉证据的隐藏肢体或附件; -- 将不确定性和假设写入 notes。 - -请求适配器还会附加原图画布尺寸和完整 JSON Schema,并要求模型只返回符合 Schema 的 JSON。最终提示词副本保存在 prompt.txt。 - -## 6. 输出数据契约 - -结构定义位于 [schemas/semantic-parts.schema.json](../schemas/semantic-parts.schema.json)。顶层格式: - -~~~json -{ - "schema_version": 2, - "coordinate_space": "normalized_xy_top_left", - "parts": [], - "notes": [] -} -~~~ - -每个部件包含: - -| 字段 | 含义 | +| 参数 | 说明 | | --- | --- | -| id | 稳定、唯一的小写 ASCII 部件 ID | -| semantic | 部件语义说明 | -| parent | 运动层级中的父部件;null 表示未来挂到 root | -| rig_role | bone_part / attachment / facial_feature,附件不自动创建骨骼 | -| bind_to | 附件绑定的 bone_part;骨骼部件使用 parent,bind_to 为 null | -| visibility | visible、partial 或 hidden | -| bbox_norm_xyxy | 可见区域粗框 [xmin, ymin, xmax, ymax] | -| pivot_norm | 预计的关节或连接点 | -| positive_points_norm | 模型粗估点,仅为旧版诊断兼容保留,新请求留空 | -| negative_points_norm | 模型负点,仅保留作记录,不传给 SAM | -| occluded_by | 视觉上遮挡当前部件的其他部件 | -| completion | occlusion_fill / joint_extension_parent / joint_extension_child 三项 boolean | -| needs_completion | 三项 completion 的逻辑或;包括独立旋转需要的隐藏纹理和关节重叠 | -| confidence | LLM 自报置信度,范围 0~1 | +| `--stage understanding` | 第一阶段,也是入口默认阶段 | +| `--reference FILE` | 必需,角色 PNG | +| `--out-dir DIR` | 实际执行必需,使用独立新目录 | +| `--config FILE` | JSON 配置;默认 `configs/astra-qwen.json` | +| `--env-file FILE` | 默认项目 `.env`;shell 同名变量优先 | +| `--understanding-model ID` | 原样发送模型 ID,不转换别名 | +| `--understanding-protocol NAME` | `chat-completions` 或 `responses` | +| `--stream true/false` | 覆盖配置流式设置 | +| `--output-mode NAME` | `text-json`、`json-object`、`json-schema`;需确认中转能力 | +| `--parts-file FILE` | 离线读取有效 v2 或保守迁移 v1 | +| `--python FILE` | 仅允许 Conda ai-spine 的解释器 | +| `--stop-after understand/segment` | 理解结束或接续 SAM | +| `--dry-run` | 检查配置与图片格式,不生成产物;不代表完整 Python 几何链路已验证 | +| `--resume` | 仅复用已完成且指纹、产物哈希一致的结果,不是失败请求续发 | +| `--list-models` | 联网查询所选提供方模型列表,不能与 dry-run 同用 | -所有坐标都以完整画布左上角为原点并归一化到 0~1。例如: +模型优先级:CLI > `stage.model` > 配置指定的模型环境变量 > `stage.default_model`。提示词路径相对于配置文件。DeepSeek 预设为 Chat Completions 非流式;两个 Astra 预设为 Responses 流式。配置不代表中转所有能力均已验证。 -~~~json -"bbox_norm_xyxy": [0.36, 0.36, 0.70, 0.62] -~~~ +## 4. 输入格式要求 -对应像素坐标: +参考图必须是有效 PNG,建议单角色、透明背景、完整画布。透明图保留 Alpha;不透明白底只去除与边界连通、RGB 各通道均 ≥240 的区域。复杂背景需先抠图,空前景会失败;白色主体接触边界可能被误删。 -~~~text -xmin = canvas_width × 0.36 -ymin = canvas_height × 0.36 -xmax = canvas_width × 0.70 -ymax = canvas_height × 0.62 -~~~ +离线计划采用 [v2 Schema](../schemas/semantic-parts.schema.json):顶层 `schema_version=2`、`coordinate_space=normalized_xy_top_left`、`parts` 数组和 `notes`。实际部件数量为 1~64。 -## 7. 构造视觉模型请求 - -[providers/vision.mjs](../providers/vision.mjs) 根据配置选择请求格式。 - -### Chat Completions - -DeepSeek Flash 使用: - -~~~text -POST /v1/chat/completions -~~~ - -一个用户消息中同时包含文本提示词、画布尺寸、Schema 和采用 Data URL 编码的角色原图。 - -### Responses - -GPT-6 Astra 使用: - -~~~text -POST /v1/responses -~~~ - -适配器把同一任务转换成 input_text 和 input_image 格式,因此模型业务逻辑与具体 API 协议保持分离。 - -output_mode 支持: - -- text-json:通过提示词约束 JSON,再在本地严格校验; -- json-object:中转站确认支持后使用 JSON Object 模式; -- json-schema:中转站确认支持后使用 Structured Outputs。 - -当前已验证的 DeepSeek 配置使用 text-json。 - -## 8. 中转站通信 - -[providers/http.mjs](../providers/http.mjs) 负责: - -- 拼接 base URL 和协议路由; -- 添加 Bearer Authorization; -- 控制请求超时; -- 对明确的 HTTP 429 和 5xx 有限重试; -- 解析普通 JSON 或完整 SSE; -- 拒绝被截断的流式响应; -- 记录请求 ID、模型、token、耗时和尝试次数; -- 从错误信息和落盘文件中脱敏 API Key。 - -超时或网络中断不会自动重试,因为服务端可能已经执行并计费。失败时会尽量生成 response.error.json,保存脱敏后的状态码、响应片段或网络错误码。 - -## 9. 提取与校验模型结果 - -[providers/vision.mjs](../providers/vision.mjs) 从不同协议的响应中提取模型文本,并拒绝: - -- 模型 refusal; -- 非正常 finish_reason; -- 未完成的 Responses 状态; -- 没有结构理解文本的响应。 - -提取后的内容保存在 response.txt。 - -[lib/validate-parts.mjs](../lib/validate-parts.mjs) 首先去掉模型可能添加的 Markdown JSON 代码块,然后执行 JSON 解析和两层本地校验。 - -### Schema 校验 - -- 必填字段是否齐全; -- 类型与枚举是否正确; -- ID 格式是否合法; -- 坐标和置信度是否在 0~1; -- 部件数量是否在 1~64; -- 是否出现未知字段。 - -### 结构语义校验 - -- 部件 ID 不能重复; -- parent 和 occluded_by 必须引用已有部件; -- 部件不能引用自己; -- 父子关系和遮挡关系不能形成环; -- 可见部件必须具有正面积 bbox; -- 模型正点可为空;落在 bbox 外只产生警告并丢弃其提示作用; -- bind_to 必须引用骨骼部件,骨骼的 parent 也必须是骨骼部件; -- partial/hidden 必须声明 occlusion_fill,needs_completion 与三项补全字段一致; -- 附件和面部特征不能声明独立骨骼关节延展; -- 完全隐藏部件必须没有可见框和正点,并设置 needs_completion=true; -- 自报置信度低于 0.6 时产生人工复核警告。 - -校验结果写入 validation.json。只有校验通过时才会写出正式的 semantic-parts.json。 - -随后进行像素几何检查:以 alpha > 0 为前景,记录原始模型点是否落在前景和粗框内。在粗框与前景交集中,用距离变换选择远离轮廓和 ROI 边界的像素作为候选。像素坐标使用 floor(norm × size),1 映射到最后一个像素;候选归一化坐标使用像素中心。粗框按 floor/ceil 转为半开像素范围。 - -框内无前景、没有像素中心或 Alpha 不可用时标记 blocked,不生成点。隐藏部件标记 hidden。记录框内前景比例、连通域数量和候选到轮廓距离,不把候选声称为已确认的语义种子;原始 pivot 完全保留。 - -## 10. 可视化与人工复核 - -[lib/report.mjs](../lib/report.mjs) 将结构理解结果叠加到原图: - -- 彩色矩形:模型预测的可见区域粗框; -- 红色实心圆:无效模型点;黄色实心圆:前景上的不可信模型点; -- 青色方块:程序生成的 Alpha 候选,仍需确认部件语义; -- 空心圆:部件 pivot; -- 虚线:当前部件到父部件的关系; -- 文本:部件 ID。 - -它会生成: - -- annotated.svg:可缩放的原图标注; -- report.html:包含标注图、校验结果、部件表、模型说明和请求元数据的自包含检查页。 - -status=completed 只表示请求、解析和本地校验完成。成功结果仍设置 quality_status=needs_review,因为结构合法不等于语义和框位置一定正确。 - -人工复核至少应检查: - -1. 是否遗漏身体、头部或关键肢体; -2. 左右肢体是否符合画面方向; -3. 是否过度拆分面部或服饰细节; -4. 父子关系能否支持预期动画; -5. 遮挡关系是否与原图一致; -6. bbox 和提示点是否落在正确部件上; -7. needs_completion 是否覆盖确实需要补全的部分。 - -## 11. 阶段调度与实验留档 - -[stages/model-stage.mjs](../stages/model-stage.mjs) 是第一阶段总调度器: - -~~~text -读取图片 -→ 计算输入、Schema、配置和代码指纹 -→ 创建运行目录 -→ 保存输入、提示词和请求摘要 -→ 调用视觉 LLM -→ 保存原始响应和请求元数据 -→ 提取并校验 JSON -→ 保存正式语义结果 -→ 生成标注和检查报告 -→ 更新 manifest -~~~ - -[lib/run-artifacts.mjs](../lib/run-artifacts.mjs) 负责输出目录、恢复校验、产物哈希和最终状态。 - ---resume 只在原图、模型、协议、参数、提示词、Schema、相关源代码和已有产物全部一致时复用结果。不同模型或提示词实验应使用不同输出目录。 - -## 12. 输出文件 - -| 文件 | 作用 | +| 部件字段 | 格式与含义 | | --- | --- | -| source-original.png | 原始输入副本 | -| source.png | 模型实际看到的预处理 RGBA | -| preprocessing.json | 背景处理方式和像素统计 | -| geometry-validation.json | 原始点诊断、框内前景比例、连通域、候选和阻塞原因 | -| segmentation-prompts.json | 语义、粗框、程序生成的正点;负点为空,requires_mask_qa=true | -| prompt.txt | 本次解析后的阶段提示词 | -| request.json | 可复现实验的请求摘要,不包含 API Key 或完整 Base64 请求体 | -| response.raw.json | 中转站原始成功响应 | -| response.txt | 从协议响应中提取的模型文本 | -| request-metadata.json | 请求模型、返回模型、request ID、usage、耗时、次数和 wire format | -| validation.json | Schema 与结构语义校验结果 | -| semantic-parts.json | 校验通过后的正式结构理解结果 | -| annotated.svg | 原图上的粗框、pivot、提示点和父子连线 | -| report.html | 用于人工语义复核的综合页面 | -| manifest.json | 状态、配置、输入哈希、代码版本、SAM 信息和全部产物哈希 | -| response.error.json | HTTP、SSE 或网络失败时的脱敏诊断信息;成功时不存在 | +| `id` / `semantic` | 唯一小写 ASCII ID / 语义说明 | +| `parent` | 父骨骼 ID 或 null;运动关系 | +| `rig_role` | `bone_part`、`attachment`、`facial_feature` | +| `bind_to` | 附件绑定的骨骼 ID 或 null(root);骨骼自身为 null | +| `visibility` | `visible`、`partial`、`hidden` | +| `bbox_norm_xyxy` | `[xmin,ymin,xmax,ymax]` 可见粗框;隐藏为 null | +| `pivot_norm` | `[x,y]` 关节或连接点,可处于遮挡区域 | +| `positive_points_norm` / `negative_points_norm` | 旧模型点兼容字段,新提示词要求留空 | +| `occluded_by` | 遮挡者 ID 数组,与运动关系分开 | +| `completion` | `occlusion_fill`、`joint_extension_parent`、`joint_extension_child` 三个布尔值 | +| `needs_completion` | 三项 completion 的逻辑或 | +| `confidence` | 0~1 自报置信度;说明与不确定性写入顶层 notes,部件内没有 notes 字段 | -request.json 是请求身份摘要,不等同于线上发送的完整 HTTP body。图片内容单独保存在 source.png,密钥不会写入产物。 +坐标以完整画布左上角为原点,归一化到 0~1。可见框须为正面积;partial/hidden 必须声明遮挡补全,hidden 无可见框和正点。附件及面部特征不能声明独立骨骼关节延展。引用必须存在,不能自引用或形成父子/遮挡环路,绑定目标必须是骨骼。完整类型与必填项以 Schema 为准。 -## 13. 代码职责索引 +v1 迁移依据 ID 推断角色分类和补全需求,推断写入 notes,不重新识别图片、不覆盖旧文件。计划必须对应同一张图、同一画布。 + +## 5. 执行链路中重要部分代码文件及原理说明(包括重点说明) + +**请求和结构校验。** `stages/model-stage.mjs` 调度;`providers/vision.mjs` 将图片 Data URL、画布尺寸、提示词与 Schema 转成对应协议,再提取 JSON,拒绝 refusal、异常结束和未完成响应。`lib/validate-parts.mjs` 校验字段、引用、层级和补全一致性,成功后写正式计划。低置信度等产生告警,不能据结构校验认定语义正确。 + +**候选点并非重新由 AI 生成。** `geometry_grounding.py` 对粗框与 `alpha>0` 的交集计算距离变换,选取远离边界的像素中心;无有效前景则 blocked。归一化点转像素采用 floor,1 映射到最后一个像素;粗框按 floor/ceil 转半开范围。候选仍可能属于框内的其他部件。 + +**pivot 与种子独立。** 关节点不吸附到前景,模型原始正负点仅作诊断。第二阶段当前只用程序种子排序返回的 mask,未把它们作为 SAM 点提示。 + +**通信、可视化与留档。** `providers/http.mjs` 负责 HTTP、SSE、超时和脱敏;明确的 429/5xx 有限重试,超时/网络中断不自动重复请求。`lib/report.mjs` 用红/黄圆区分原模型点、青色方块表示程序候选、空心圆表示 pivot。旧输出不会随代码修改自动更新。`lib/run-artifacts.mjs` 按输入、模型、参数、提示词、Schema、代码和产物哈希复用结果;completed 仅表示执行完成。 + +## 6. 各个代码文件职责索引 | 文件 | 职责 | | --- | --- | -| [pipeline.mjs](../pipeline.mjs) | 顶层入口;把 annotated-parts 模式转发到新管线 | -| [tools/model-check.mjs](../tools/model-check.mjs) | CLI 参数解析、配置解析入口、模型列表和阶段分发 | -| [configs/deepseek-qwen.json](../configs/deepseek-qwen.json) | DeepSeek 理解 + Qwen 补全实验预设 | -| [configs/astra-qwen.json](../configs/astra-qwen.json) | Astra 理解 + Qwen 补全实验预设 | -| [prompts/understand-v1.txt](../prompts/understand-v1.txt) | 第一阶段任务约束 | -| [schemas/semantic-parts.schema.json](../schemas/semantic-parts.schema.json) | 第一阶段输出数据契约 | -| [lib/config.mjs](../lib/config.mjs) | JSON、环境变量和阶段配置解析 | -| [lib/images.mjs](../lib/images.mjs) | 图片读取、格式识别、尺寸、哈希和 Data URL | -| [providers/vision.mjs](../providers/vision.mjs) | Chat Completions/Responses 请求构造与文本提取 | -| [providers/http.mjs](../providers/http.mjs) | HTTP、认证、超时、重试、SSE、元数据和脱敏 | -| [lib/validate-parts.mjs](../lib/validate-parts.mjs) | JSON 解析、Schema 校验和关系校验 | -| [lib/geometry.mjs](../lib/geometry.mjs) | Python 环境选择与几何阶段调用 | -| [geometry_grounding.py](../geometry_grounding.py) | Alpha/ROI 诊断与距离变换候选生成 | -| [normalize_reference.py](../normalize_reference.py) | RGBA 保留与边界连通白底去除 | -| [lib/report.mjs](../lib/report.mjs) | SVG 标注和 HTML 检查报告 | -| [lib/run-artifacts.mjs](../lib/run-artifacts.mjs) | 输出目录、恢复校验、状态和产物哈希 | -| [stages/model-stage.mjs](../stages/model-stage.mjs) | 第一阶段总调度与失败处理 | +| [pipeline.mjs](../pipeline.mjs) / [tools/model-check.mjs](../tools/model-check.mjs) | 新管线转发 / CLI、模型列表和阶段分发 | +| [stages/model-stage.mjs](../stages/model-stage.mjs) | 理解总调度与留档;另含图片编辑探针 | +| [lib/config.mjs](../lib/config.mjs) / [lib/images.mjs](../lib/images.mjs) | 配置解析 / 图片格式、尺寸、哈希和 Data URL | +| [lib/python-runtime.mjs](../lib/python-runtime.mjs) / [lib/geometry.mjs](../lib/geometry.mjs) | Conda 检查 / Python 几何调用 | +| [normalize_reference.py](../normalize_reference.py) / [geometry_grounding.py](../geometry_grounding.py) | Alpha 与去白底 / ROI 诊断和候选生成 | +| [providers/vision.mjs](../providers/vision.mjs) / [providers/http.mjs](../providers/http.mjs) | 视觉协议 / 通信与脱敏 | +| [lib/validate-parts.mjs](../lib/validate-parts.mjs) | 解析、Schema/关系校验、v1 迁移 | +| [lib/report.mjs](../lib/report.mjs) / [lib/run-artifacts.mjs](../lib/run-artifacts.mjs) | SVG/HTML / 状态、指纹与缓存 | +| [prompts/understand-v1.txt](../prompts/understand-v1.txt) | 理解提示词;文件名保留 v1,当前使用 v2 契约 | +| [v2 Schema](../schemas/semantic-parts.schema.json) / [v1 Schema](../schemas/semantic-parts-v1.schema.json) | 正式契约 / 兼容输入 | +| [DeepSeek](../configs/deepseek-qwen.json)、[Astra](../configs/astra-qwen.json)、[Tiantoken](../configs/tiantoken.json) 配置 | 模型、协议和环境变量预设 | +| [tests/model-stages.test.mjs](../tests/model-stages.test.mjs) / [tests/test_geometry.py](../tests/test_geometry.py) | 协议、计划、留档及几何回归 | -## 14. 当前边界与下一阶段接口 +## 7. 产物详细说明 -第一阶段输出的是语义计划,而不是分割结果: +| 路径 | 内容与用途 | +| --- | --- | +| `source-original.png` | 原始输入副本 | +| `source.png` | 预处理 RGBA,在线模型所见图片,后续坐标基准 | +| `preprocessing.json` | 背景处理方式与像素统计 | +| `semantic-parts.json` / `validation.json` | 正式 v2 计划 / 字段、关系校验及告警 | +| `geometry-validation.json` | 原点诊断、ROI 前景比例、连通域、候选与阻塞原因 | +| `segmentation-prompts.json` | 画布、部件 ID、candidate/hidden/blocked 状态、粗框、程序种子和 QA 要求 | +| `annotated.svg` / `report.html` | 粗标注 / 综合复核页;不是 SAM 分割图 | +| `prompt.txt` / `request.json` | 阶段提示词副本 / 请求身份摘要,不是完整 HTTP body | +| `response.raw.json` / `response.txt` | 响应留档 / 提取文本;离线模式使用本地计划记录 | +| `request-metadata.json` | 请求与返回模型、request ID、usage、耗时、次数和协议元数据 | +| `response.error.json` | 可获取时保存的脱敏请求失败诊断 | +| `manifest.json` | 模式、状态、输入/代码/产物哈希;SAM 路径仅记录,不加载模型 | -~~~text -视觉 LLM 输出 - = 部件语义 + 层级 + rig_role/bind_to + 遮挡 + 粗框 + 粗关节 + 补全需求 +失败可能只有部分产物。第二阶段前应复核左右、粗框、层级、遮挡、分类和补全需求,不能只看点是否落在前景。 -视觉 LLM 不输出 - = 可信的像素 mask + 透明拆件 + 隐藏区域补全 + 最终骨骼 -~~~ +## 8. 当前阶段可改进点说明 -已实现的[第二阶段](2-segmentation-stage.md)读取 source.png、semantic-parts.json 和 segmentation-prompts.json,仅处理 status=candidate 的可见部件。SAM 图像概念接口接收文本和框;程序候选点参与返回 mask 的排序,不作为点提示传入此接口。模型原始正负点不传给 SAM。候选始终 semantic_verified=false:框内可能混有多个部件,Alpha、重叠和连通域检查不能替代语义复核。 - -已有 v1 结果可以通过 --parts-file 旧计划.json --reference 原图.png --out-dir 新目录 离线迁移与校验,不请求模型。迁移按 ID 推断骨骼/附件类型,袖子优先绑定同侧上臂,面部绑定头部;部分可见部件开启遮挡补全,骨骼连接处保守建议延展。这些推断在 notes 标注为待复核,不替代模型或人工判断。输入计划哈希和所有新产物参与 resume 校验。 - -第一阶段 manifest.json 只记录 SAM 路径信息,runtime_status=local_subprocess_not_probed,第一阶段不加载 SAM。第二阶段单独探测 Conda/CUDA、严格加载本地权重,并在自己的 manifest 中记录运行环境、权重哈希及子进程退出状态。 +- 明确角色左右与画面左右命名约定,提升粗框、遮挡及隐藏状态判断,减少 SAM 衣料/肢体混淆。 +- 根据预期动画审查拆分粒度与附件绑定,区分隐藏骨骼占位项和真正可见拆件。 +- 增加可审阅的计划修正流程,修正后重新生成几何提示;Alpha 候选不能代替语义复核。 +- 第二阶段后根据实际 mask 重新评估补全需求,不能因第一阶段 needs_completion=false 永久跳过有缺损的拆件。 +- 增加结构和像素证据一致性检查,区分“不确定”“结构合法”“人工确认正确”。 diff --git a/docs/2-segmentation-stage.md b/docs/2-segmentation-stage.md index aa4f397..ba4823d 100644 --- a/docs/2-segmentation-stage.md +++ b/docs/2-segmentation-stage.md @@ -1,116 +1,156 @@ # 第二阶段:本地 SAM 分割 -本阶段读取第一阶段的语义计划,使用本地 SAM 3.1 图像检测分支生成部件 mask,从原图提取可见像素,并输出两张预览图。Python 固定使用 `ai-spine` Conda 环境,遵守 [AGENTS.md](../AGENTS.md)。 +## 1. 阶段简介 -## 运行方式 +读取第一阶段语义计划,用本地 SAM 3.1 图像检测分支生成部件 mask,再从原图提取可见像素。当前输出半透明颜色叠加的角色图、白底拆解图和透明部件。 -在 `AI_spine` 目录执行: +SAM 在 Conda `ai-spine` 的临时 GPU 子进程中运行,结束后退出;不部署常驻服务、不下载权重、不调用中转站、不自动回退 CPU。本阶段尚无大模型去毛边步骤,也不补画隐藏纹理。 + +## 2. 输入、输出与执行链路 + +输入为第一阶段目录,加本地 SAM 代码和权重;输出为可见部件 mask、原像素拆件、诊断和预览。 + +```text +tools/model-check.mjs --stage segmentation +→ stages/segmentation-stage.mjs 检查输入、路径、参数与 Conda +→ 临时探测子进程检查依赖和 CUDA,不加载权重 +→ 计算输入、代码、权重指纹,复制输入到新输出目录 +→ 临时推理子进程:sam_segment.py → sam_runtime.py +→ 严格加载检测分支,一次编码原图 +→ 每部件分别取得文本、文本+粗框候选,排序选 mask +→ 与原图 Alpha 取交集,提取原像素并渲染报告 +→ 子进程退出,manifest 记录产物与退出状态 +→ 第三阶段读取 source.png、计划、segmentation.json 和 masks/ +``` + +`hidden/blocked` 不进入推理;没有合格候选会记录跳过原因,不用矩形或种子伪造 mask。所有输出仍为 `semantic_verified=false`、`quality_status=needs_review`。 + +## 3. 阶段执行命令示例及参数说明 + +在项目根目录执行,环境安装见 [README](../README.md)。以下独立命令复用已有计划,无需模型密钥: + +```powershell +conda activate ai-spine +$runId = Get-Date -Format "yyyyMMdd-HHmmss" +node .\tools\model-check.mjs --stage segmentation ` + --input-dir .\output\sombrero-grounding-v2 ` + --out-dir ".\output\$runId\sam" ` + --sam-dir F:/Study/SAM3 +``` + +将 `--input-dir` 替换为本次第一阶段的 `understand` 目录,即可接续新实验。自动化可以使用 `conda run --no-capture-output -n ai-spine node ...`。 + +仅探测环境与输入,不进行模型推理: ```powershell conda run --no-capture-output -n ai-spine node .\tools\model-check.mjs ` --stage segmentation ` --input-dir .\output\sombrero-grounding-v2 ` - --out-dir .\output\sombrero-sam-local ` - --sam-dir F:/Study/SAM3 - -node .\tools\model-check.mjs ` - --stage segmentation ` - --input-dir ".\output\$runId\understand" ` - --out-dir ".\output\$runId\sam" ` - --sam-dir F:/Study/SAM3 + --sam-dir F:/Study/SAM3 ` + --dry-run ``` -输出目录必须是新目录。相同输入、代码、权重、参数及完整产物可加 `--resume` 复用;失败结果保留,另建目录重跑。独立分割不调用视觉 LLM 或图片编辑接口,不需要 API Key。 - -输入目录必须包含: - -| 文件 | 要求 | +| 参数 | 说明 | | --- | --- | -| `source.png` | 第一阶段预处理后的原尺寸 RGBA | -| `semantic-parts.json` | 通过结构校验的 v2 语义计划 | -| `segmentation-prompts.json` | 与计划 ID、画布匹配的程序候选提示 | +| `--stage segmentation` | 独立运行第二阶段 | +| `--input-dir DIR` | 必需,第一阶段输出目录 | +| `--out-dir DIR` | 推理必需,使用独立新目录;dry-run 可省略 | +| `--sam-dir DIR` | SAM 根目录,优先于 SAM_MODEL_DIR 和配置默认值 | +| `--sam-code-dir DIR` | 源码仓库,优先于 SAM_CODE_DIR 和根目录下 sam3 | +| `--sam-checkpoint FILE` | 显式本地权重,覆盖根目录自动查找 | +| `--sam-confidence FLOAT` | 候选模型分数阈值,默认 0.2,严格介于 0 和 1;不是语义准确率 | +| `--sam-precision NAME` | 默认 bf16,可选 fp32;后者显存占用更高 | +| `--config FILE` / `--env-file FILE` | 配置与环境变量文件,默认 astra-qwen.json / 项目 .env | +| `--python FILE` | 仅允许 ai-spine 的解释器 | +| `--dry-run` | 检查路径、Conda、依赖导入和 CUDA;不校验完整权重加载或推理显存 | +| `--resume` | 输入、参数、代码、权重和完整产物一致时复用;失败任务另建目录 | -仅 `status=candidate` 的可见部件进入推理。hidden/blocked 记入跳过列表;无可用 SAM mask 的部件记录失败原因,不用矩形或候选点伪造分割。 +也可在第一阶段命令上使用 `--stop-after segment --sam-dir F:/Study/SAM3`,输出位于理解目录的 `segmentation/`。该方式会先执行理解阶段,可能调用付费模型。 -可以在命令末尾加 `--dry-run` 检查代码路径、权重存在性、Conda、依赖导入和 CUDA;它不加载权重,因此不验证权重内容或完整推理显存需求。 +## 4. 输入格式要求 -如需从第一阶段接续运行,在原结构理解命令中使用 `--stop-after segment --sam-dir F:/Study/SAM3`。第二阶段输出到理解目录下的 `segmentation/`。原理解命令仍可能请求付费模型;已有计划优先使用上面的独立命令。 +| 输入 | 要求 | +| --- | --- | +| `source.png` | 第一阶段预处理 RGBA,保留完整原画布 | +| `semantic-parts.json` | 通过结构校验的 v2 计划,旧版须先离线迁移 | +| `segmentation-prompts.json` | 宽高匹配 source;部件 ID 与计划完整一致 | +| candidate 提示 | 非隐藏部件,seed_source 为 alpha_roi_distance_transform;整数粗框在画布内;至少一个整数种子在粗框与 Alpha 前景内 | +| SAM 代码 | 源码仓库内部必须有 sam3/model_builder.py | +| SAM 权重 | 本地 sam3.1_multiplex.pt,与本项目适配的检测分支结构匹配 | -## 环境与权重 - -本机已经验证:Python 3.11、PyTorch `2.7.1+cu126`、torchvision `0.22.1+cu126`、NumPy `1.26.4`、OpenCV `4.11.0.86`、Windows Triton `3.3.1.post21`,GPU 为 RTX 3060 Laptop 6 GB。 - -环境补全命令见 [README](../README.md#python-与外部项目),依赖记录在 [requirements.txt](../requirements.txt)。程序不会自动安装依赖、创建环境或切换到 CPU。 - -默认布局: +当前本机布局: ```text F:/Study/SAM3/ - sam3/ 源码仓库 + sam3/ sam3/model_builder.py sam3.1checkpoint/ sam3.1_multiplex.pt ``` -路径优先级为 CLI 覆盖、环境变量、配置默认值。`SAM_MODEL_DIR` 指定根目录,`SAM_CODE_DIR` 可单独指定源码仓库。若 `.env` 中仍是旧路径,修改为上述路径或显式传入 CLI 参数。 +权重默认先查找上述子目录,再查找 SAM 根目录下同名文件。当前已验证环境为 Python 3.11、PyTorch 2.7.1+cu126、torchvision 0.22.1、NumPy 1.26.4、OpenCV 4.11.0.86,RTX 3060 Laptop 6 GB。这是本机验证组合,不是所有机器的兼容保证。 -| 参数 | 含义 | +## 5. 执行链路中重要部分代码文件及原理说明(包括重点说明) + +**本地生命周期与权重。** `stages/segmentation-stage.mjs` 先探测,再启动一次推理进程;离线环境变量禁止 Hugging Face 下载。推理超时 20 分钟,结束、报错或取消后退出。`sam_runtime.py` 从 multiplex 权重提取 detector 分支,适配三个特征尺度,移除未使用的第四尺度并取消 scalp;忽略不参与当前推理的视频 neck,实际加载参数使用 strict=True。外部 SAM 源码不作修改。 + +**精度不能简单全模型转换。** 模型参数和复数位置编码缓冲区保持原精度,在推理上下文开启 BF16 autocast;直接对整个模型调用 BF16 转换会影响复数缓冲区及要求 FP32 的路径。 + +**提示和选择。** `sam_segment.py` 将原图合成白底 RGB,GPU 只编码一次;每个部件分别收集 text_only 与 text_and_box 候选。排序结合模型分数、粗框内比例、Alpha 越界比例和种子命中;前景不足 4 像素或框内比例低于 10% 的候选被拒绝。粗框是提示,并非强制裁剪边界。 + +**重点:当前不是 SAM 点提示分割。** 所用图像概念接口接受文本和框。第一阶段程序种子仅参与返回 mask 排序,模型原始点不传入 SAM。提高种子前景命中率不能保证选中正确部件。 + +**像素与质量。** `segmentation_outputs.py` 用原图 Alpha 裁掉背景,从原图复制 RGB/Alpha,不重绘、不缩放;保留多部件重叠。记录越界、碎片、未命中种子、漏分、重叠和 IoU≥0.8 的疑似重复。覆盖率不是语义准确率,原像素保真也不能修复错误归属。 + +**当前预览含原图纹理。** `annotated.png` 是原图上 Alpha=100 的彩色 mask 叠加,不是仅用纯色区域组成的角色图;`parts-sheet.png` 为带 ID 的白底拆件。纯色遮罩角色图属于第 8 节的待实现项。 + +## 6. 各个代码文件职责索引 + +| 文件 | 职责 | | --- | --- | -| `--sam-dir` | SAM 根目录 | -| `--sam-code-dir` | 源码仓库目录,内部应包含 `sam3/model_builder.py` | -| `--sam-checkpoint` | 本地权重文件 | -| `--sam-confidence` | SAM 候选分数阈值,默认 0.2,不是语义正确率 | -| `--sam-precision` | 默认 bf16 自动混合精度;可设 fp32,可能需要更多显存 | +| [tools/model-check.mjs](../tools/model-check.mjs) | 独立分割入口、参数解析 | +| [stages/segmentation-stage.mjs](../stages/segmentation-stage.mjs) | 输入校验、环境探测、子进程、哈希、日志与失败处理 | +| [lib/config.mjs](../lib/config.mjs) | SAM 路径与配置解析 | +| [lib/python-runtime.mjs](../lib/python-runtime.mjs) | ai-spine 解释器与基础依赖检查 | +| [lib/images.mjs](../lib/images.mjs) / [lib/validate-parts.mjs](../lib/validate-parts.mjs) | PNG 元数据 / v2 计划结构校验 | +| [lib/run-artifacts.mjs](../lib/run-artifacts.mjs) | 输出目录、复用、产物哈希 | +| [sam_runtime.py](../sam_runtime.py) | 依赖/CUDA 探测、源码路径、检测权重适配与严格加载 | +| [sam_segment.py](../sam_segment.py) | 提示校验、GPU 推理、候选排序、诊断与阶段组织 | +| [segmentation_outputs.py](../segmentation_outputs.py) | mask QA、原像素提取、标注图、拆件图、HTML | +| [tests/test_segmentation.py](../tests/test_segmentation.py) | 候选、提示、Alpha、裁剪保真和重叠回归 | +| [tests/model-stages.test.mjs](../tests/model-stages.test.mjs) | 阶段入口和相关本地回归调度 | -Node 先启动环境探测子进程,再启动一次推理子进程。模型只加载到后者;没有监听端口或常驻服务,正常结束、报错、超时或收到取消信号后退出。推理超时为 20 分钟。禁用 Hugging Face 在线下载,权重只能来自本地。 +`segment.py` 是旧版白底拆件图分割器,不是本阶段 SAM 入口;`compose_preview.py`、`run_case_matrix.py` 是旧版定位/组装对照工具,不应与新阶段混用。 -`sam_runtime.py` 从 multiplex checkpoint 提取 `detector.*`。SAM 3.1 的检测分支有三个特征尺度;图像 builder 的第四尺度原本会被 scalp 丢弃,因此适配器移除该未使用尺度并取消 scalp。忽略视频交互/传播 neck,随后 `strict=True` 加载所有实际使用参数;结构不匹配会报错。未修改外部 SAM 源码。 +## 7. 产物详细说明 -保留 FP32 参数和复数位置编码缓冲区,仅在推理上下文开启 BF16 autocast。不能直接把整个模型转换为 BF16,这会破坏复数缓冲区及上游要求 FP32 的解码器路径。 - -## 提示、选择与质量检查 - -1. 在白色背景上合成参考图,保持原尺寸;GPU 只编码一次图像。 -2. 每个部件先用语义文本推理,再加入归一化粗框推理,保留两组候选。 -3. 根据模型分数、粗框内比例、越出角色 Alpha 的比例及候选点命中情况排序。拒绝前景不足 4 像素或框内比例低于 10% 的结果。 -4. 最终 mask 与原图 Alpha 前景取交集,从原图提取 RGB 和 Alpha,不重绘、不缩放。原始选中 mask 另存用于检查越界。 -5. 记录漏分、重叠、碎片化、候选点未覆盖,以及不同部件 mask IoU ≥ 0.8 的疑似重复。 - -当前使用的 SAM 图像概念接口接受文本与框,不接受点。第一阶段的 Alpha 候选点仅用于 mask 排序;模型原始点仍只用于第一阶段诊断。这次 mask 来自真实 GPU 模型推理。 - -粗框、候选点及模型分数都不能保证部件语义正确。因此所有结果保持 `quality_status=needs_review`、`semantic_verified=false`。重叠 mask 保留,未强行分配成互斥部件,也未补全遮挡纹理。人工复核通过后才能继续补全或导出。 - -## 输出 - -| 文件 | 内容 | +| 路径 | 内容与用途 | | --- | --- | -| `annotated.png` | 原尺寸角色图,各候选部件用不同半透明颜色叠加,透明背景显示为白色 | -| `parts-sheet.png` | 白底拆解图,部件保持原尺寸、分开排布,并标注 ID 和颜色 | -| `parts/.png` | 紧裁剪的 RGBA 部件,保留原图像素及 Alpha | -| `masks/.png` | 原图尺寸黑白 mask,已裁掉 Alpha 背景 | -| `candidates/-raw.png` | 选中的 SAM 原始 mask,裁掉背景前 | -| `unassigned-mask.png` | 白色表示没有被任何部件 mask 覆盖的角色像素 | -| `overlap-mask.png` | 白色表示被多个部件 mask 覆盖的像素 | -| `segmentation.json` | 裁剪坐标、拆解图坐标、颜色、质量指标、运行环境和模型加载信息 | -| `candidate-diagnostics.json` | 两种提示的候选分数、排序、拒绝原因及最终选择 | -| `report.html` | 两张预览、部件链接、告警、漏分及重复检查 | -| `worker.log` / `worker-error.json` | 子进程日志 / 失败诊断(发生错误时) | -| `manifest.json` | 状态、输入/代码/权重/产物哈希,完成时记录子进程已退出 | +| `source.png` / `semantic-parts.json` / `segmentation-prompts.json` | 输入副本,保留坐标与语义来源 | +| `annotated.png` | 原尺寸原图 + 半透明彩色 mask,背景合成白色 | +| `parts-sheet.png` | 原尺寸拆件分开排布的白底图,含 ID 与颜色标记 | +| `parts/.png` | 紧裁剪 RGBA 部件,保留原图像素 | +| `masks/.png` | 原画布尺寸的二值 mask,0/255,已裁掉 Alpha 背景 | +| `candidates/-raw.png` | 选中的原始 SAM mask,尚未裁 Alpha,用于越界诊断 | +| `unassigned-mask.png` | 白色为没有任何部件覆盖的角色前景 | +| `overlap-mask.png` | 白色为多个部件共同覆盖的区域 | +| `segmentation.json` | 部件路径、crop_xyxy、sheet_xyxy、颜色、QA、跳过列表、覆盖率、运行环境、加载记录 | +| `candidate-diagnostics.json` | 两种提示候选的分数、排序、拒绝原因和最终选择 | +| `report.html` | 预览、部件链接、告警及漏分/重复复核 | +| `worker.log` / `worker-error.json` | 日志 / 子进程错误诊断(失败时) | +| `manifest.json` | 状态、输入/代码/权重/产物哈希;完成后 gpu_worker_exited=true | -`crop_xyxy` 使用原图坐标,右下角为开区间;`sheet_xyxy` 使用白底拆解图坐标。覆盖率是像素覆盖比例,不是准确率。 +`crop_xyxy` 为原图坐标,`sheet_xyxy` 为拆解图坐标,右下角均为开区间。第三阶段依赖全画布 masks,不以紧裁剪 parts 反推位置。 -## 代码与验证记录 +当前质量基线是 `output/20260918-183532/sam`:32 个计划项中 10 个 hidden 跳过,22 个 mask,前景覆盖率约 83.3%,32719 像素未分配。图中 forearm_r/hand_r 存在衣料误分,前臂混入手部,上衣及袖子存在缺失。更早 `sombrero-sam31-v3` 为另一批 28 个 mask、约 67.18% 覆盖率,不能混用统计。真实 GPU 推理跑通不代表拆件可直接用于动画。 -- [stages/segmentation-stage.mjs](../stages/segmentation-stage.mjs):输入校验、Conda 子进程、哈希、缓存、日志和失败处理。 -- [sam_runtime.py](../sam_runtime.py):环境探测和本地权重严格加载。 -- [sam_segment.py](../sam_segment.py):GPU 推理、两组候选选择和诊断。 -- [segmentation_outputs.py](../segmentation_outputs.py):mask QA、原像素拆件、两张预览和报告。 -- [tests/test_segmentation.py](../tests/test_segmentation.py):Alpha 越界、候选选择、提示完整性、像素保真和重叠/重复检查。 +## 8. 当前阶段可改进点说明 -2026-09-18 实测 `output/sombrero-grounding-v2` → `output/sombrero-sam31-v3`:28 个部件返回 mask,严格加载 1130 个检测参数/缓冲张量;推理及渲染约 11.64 秒(不含环境探测和加载权重),PyTorch 峰值已分配显存约 4.97 GiB,结束后无 SAM 子进程。 +以下均为待实现或待验证的改进方向: -这组结果覆盖原图前景约 67.18%,仍有 64286 像素未覆盖、30569 像素重叠。`shin_left` 和 `foot_left` 的 mask IoU 约 0.843,实际都分到了鞋子;躯干及其他肢体也存在碎片或错分。文本候选对照未解决这些问题。这说明推理和输出链路已跑通,但当前旧语义计划与提示策略尚不能产出合格的最终拆件;需要修正部件粗框并继续验证提示及 mask 语义。 - -同日 `conda run --no-capture-output -n ai-spine npm test` 的 17 项测试全部通过(包括 Python 分割回归用例);真实产物 `--resume` 哈希校验复用通过。测试通过仅验证程序行为,不表示上述分割质量合格。 - -后续已接入[第三阶段部件补全](3-completion-stage.md)。该阶段直接读取本目录的 `source.png`、`semantic-parts.json`、`segmentation.json` 和全画布 `masks/`;保留本阶段的告警,不能通过生成隐藏纹理来修复错误的部件归属。 +- **输出仅色彩遮罩的完整角色图。** 在原画布上以各部件纯色展示分区,不叠加原图纹理;保留现有 annotated.png。需明确重叠显示顺序,将未分配区域单独标识,不能为了“完整”伪造已识别区域。 +- **可选的大模型去毛边。** 对每个通过部件归属复核的 SAM 拆件增加一次可选边缘清理,提供对应原图局部参考,约束修改范围,保存清理前后、mask 差异和坐标。默认保留原始拆件;清理不能冒充隐藏补全,也不能把重绘结果称为原像素。 +- **先修正语义误分。** 明确左右、隐藏状态和粗框,复核衣料/皮肤/手部归属;对明显错误、缺失或疑似重复输出阻断性状态,再进入补全。 +- **改善覆盖和边界。** 对未分配前景、过度重叠及大孔洞做定位复核;区分合理遮挡与分割缺口,避免一刀切强制所有 mask 互斥。 +- **重评补全需求。** 基于实际 mask 检查袖子、衣服等缺损,反馈第三阶段;不能仅沿用第一阶段 needs_completion。 +- **增加语义验收。** 模型分数、前景命中和覆盖率只作辅助;将原图、候选、最终 mask 并排复核,记录人工修正及来源。 diff --git a/docs/3-completion-stage.md b/docs/3-completion-stage.md index b970aa3..cdf09a9 100644 --- a/docs/3-completion-stage.md +++ b/docs/3-completion-stage.md @@ -1,149 +1,193 @@ # 第三阶段:部件补全 -本阶段处理第一阶段声明的 `occlusion_fill`、`joint_extension_parent`、`joint_extension_child`,读取第二阶段的可见 mask,为部件生成局部画布,调用图片编辑模型并合并受限的新增像素。原图已可见区域的 RGBA 像素始终从原图恢复,不使用模型重绘的版本。 +## 1. 阶段简介 -使用 [AGENTS.md](../AGENTS.md) 规定的 Conda `ai-spine` 环境,不需要额外安装依赖。第三阶段几何处理使用本地 Python;图片生成通过现有中转站 `images/edits` 接口完成。 +读取 SAM 可见 mask,为需要遮挡补全或关节延伸的部件准备局部画布,调用中转站图片编辑模型,再将允许区域内的新增像素与原可见像素合并。Python 几何处理固定使用 Conda `ai-spine`;图片生成在远端完成,本阶段不加载本地 SAM。 -切换 Tiantoken 中转站时,在命令中增加 `--config .\configs\tiantoken.json`,并删除示例中的 `--completion-model qwen-image-3.0`,或改为 `--completion-model gpt-image-2`。该配置读取独立的 `TIANTOKEN_BASE_URL` / `TIANTOKEN_API_KEY`,第三阶段默认 `gpt-image-2`。目前仅验证模型列表可访问,实际图片编辑能力尚未实测;`gpt-6-astra` 的 Responses 图片生成工具仍需另行适配。 +当前已实现准备、真实图片请求、离线候选导入、几何检查与透明补全部件输出。尚未输出使用补全部件组装的完整角色,尚未接入新管线 Spine 导出。几何通过仍为 `needs_review`,不能等同于部件可用。 -## 命令 +## 2. 输入、输出与执行链路 -在 PowerShell 中进入项目并激活环境: +输入是第二阶段目录;输出是任务画布、候选、检查报告及通过几何检查的补全部件。 + +```text +tools/model-check.mjs --stage completion --input-dir SAM目录 +→ stages/completion-stage.mjs 校验计划、mask 文件、参数及 Conda +→ completion_geometry.py prepare + 筛选需求 → 计算允许区域 → 建立局部画布与编辑 mask +→ prepare-only:保存任务和报告后结束 +→ 否则:串行请求 images/edits,或读取离线候选 +→ completion_geometry.py merge + 检查画布/前景/对齐 → 限制新增区域与连通性 → 恢复原可见像素 +→ 每部件选第一个通过几何检查的候选 +→ finalize 输出透明部件、原图坐标和报告 +``` + +任务必须同时满足:计划 `needs_completion=true`、非 hidden、有可见 SAM mask、允许新增区域非空。指定 `--part` 只缩小范围,不强制绕过筛选。分别记录 `NO_COMPLETION_NEEDED`、`NO_VISIBLE_SAM_MASK`、`NO_ALLOWED_EXTENSION`。 + +以 `output/20260918-183532/sam` 为例:32 个计划项中 10 个 hidden 没有 mask;22 个有 mask,其中 12 个进入补全。帽子、两袖、两眼、两眉、鼻、嘴、胡子这 10 个因第一阶段标记不需补全而跳过,没有重新由模型判断实际 mask 完整性。 + +## 3. 阶段执行命令示例及参数说明 + +以下命令在项目根目录执行;输入示例是已有实验,不代表其 mask 已合格。 ```powershell -Set-Location F:\Study\taonier\AI_spine conda activate ai-spine $runId = Get-Date -Format "yyyyMMdd-HHmmss" -``` +$samInput = ".\output\20260918-183532\sam" -只准备任务(离线、无需 API Key): - -```powershell +# 离线准备所有符合条件的任务,无需密钥 node .\tools\model-check.mjs --stage completion ` - --input-dir .\output\sombrero-sam31-v3 ` - --out-dir ".\output\$runId-prepare" ` - --completion-model qwen-image-3.0 ` + --config .\configs\tiantoken.json ` + --input-dir $samInput ` + --out-dir ".\output\$runId\complete-prepare" ` --prepare-only -``` -真正调用模型补全一个部件,需要 `.env` 中的中转站地址与密钥,会产生图片请求: - -```powershell +# 单部件真实图片编辑请求 node .\tools\model-check.mjs --stage completion ` - --input-dir .\output\sombrero-sam31-v3 ` - --out-dir ".\output\$runId-complete-head" ` - --completion-model qwen-image-3.0 ` + --config .\configs\tiantoken.json ` + --input-dir $samInput ` + --out-dir ".\output\$runId\complete-head" ` + --completion-model gpt-image-2 ` --part head -``` -`--part head --part neck` 指定多个部件。省略 `--part` 时处理所有可用且需要补全的部件,每个部件单独发出请求;当前模型配置 `n=1`。程序串行调用,沿用提供方的超时及显式 429/5xx 重试策略,超时/网络中断不自动重复生成。发生请求错误保留候选和诊断,停止后续部件。 - -离线导入已经生成的候选(无需 API Key): - -```powershell +# 所有符合条件的部件,逐部件请求模型 node .\tools\model-check.mjs --stage completion ` - --input-dir .\output\sombrero-sam31-v3 ` - --out-dir ".\output\$runId-merge" ` - --part head ` - --candidates-dir .\completion-candidates + --config .\configs\tiantoken.json ` + --input-dir $samInput ` + --out-dir ".\output\$runId\complete" ``` -候选文件名为 `completion-candidates/head.png`,必须与对应任务的局部画布尺寸、坐标完全一致。准备与合并必须使用相同输入、`--completion-size` 和 `--extension-radius`。缺失候选记为 `missing_candidate`,不会联网补发。可将先前任务保存的原始候选复制为 `ID.png`,离线检查它,避免重复计费。 +使用 Qwen 时改为 `--config .\configs\deepseek-qwen.json --completion-model qwen-image-3.0`,读取原中转配置。Tiantoken 配置第三阶段为 `gpt-image-2`,第一阶段的 `gpt-6-astra` 不是当前图片编辑接入的替代品;未实现 Astra Responses 图片生成工具链。 -`--candidates-dir` 也支持直接指向旧补全输出目录:读取 `tasks//candidate-1.png`(亦支持 jpg/webp),不下载、不重新生成。程序先核对旧 manifest 中的源图、语义计划、SAM mask 哈希及画布/延展参数是否与本次一致;不同则拒绝复用。该模式只取每部件首张原候选。 - -### 返回尺寸与输入不一致时 - -`--completion-size` 控制局部画布,不能单靠提示词保证模型输出相同尺寸。修复后第三阶段会同时发送 multipart 参数 `size=画布宽x画布高`,默认 `1024x1024`,并在每部件 `request.json` 记录实际请求尺寸。配置中的 `completion.params.size` 若与画布不同会在调用前报错。[OpenAI 编辑接口的 size 参数](https://developers.openai.com/api/reference/cli/resources/images/methods/edit)有明确的输出尺寸含义,但中转站是否遵守仍以实测结果为准。 - -默认 `--candidate-size-policy strict` 仍拒绝尺寸不一致。已有候选可以使用 `uniform` 模式离线尝试恢复:仅允许相同宽高比的整张画布等比例缩放,再执行原有的颜色/位置、可见像素保留率、新增区域和连通性检查。不对物体单独缩放、不平移、不裁剪,也不放宽对齐阈值。原图和 SAM mask 始终不缩放。 +旧候选离线复检,不重新请求模型: ```powershell node .\tools\model-check.mjs --stage completion ` --config .\configs\tiantoken.json ` - --input-dir .\output\20260918-183532\sam ` + --input-dir $samInput ` --candidates-dir .\output\20260918-183532\complete2_gpt ` - --out-dir ".\output\$runId-size-recheck" ` + --out-dir ".\output\$runId\complete-recheck" ` --candidate-size-policy uniform ``` -该命令不请求图片模型。原始候选保留,缩放后的候选另存为 `merged-N-normalized.png`,QA 记录原始/目标尺寸、比例、重采样方法和告警。即便最终通过几何检查也仍需语义复核;如果模型同时重绘、放大或移动了部件,可能继续报 `VISIBLE_ALIGNMENT_MISMATCH`。 +仅测试图片编辑接口的独立探针: -2026-09-20 对 `complete2_gpt` 的 12 张原始候选实测:输入均为 1024×1024,输出为 1248×1248 或 1254×1254。旧请求未发送 size。离线 uniform 复查后 8 个通过几何检查、4 个因对齐不符或无有效新增像素拒绝;原始文件未覆盖,也没有重新请求生成。报告位于 `output/20260918-183532/complete2_gpt-size-recheck-v2/report.html`。22 项测试通过,含请求 size、等比例恢复后的像素保真、宽高比/偏移拒绝及旧任务输入匹配检查。显式 size 已通过请求构造测试,尚未再次付费验证中转站是否遵守。 +```powershell +node .\tools\model-check.mjs --stage completion ` + --config .\configs\tiantoken.json ` + --image .\output\20260918-183532\complete2_gpt\tasks\head\input.png ` + --prompt-file .\output\20260918-183532\complete2_gpt\tasks\head\prompt.txt ` + --out-dir ".\output\$runId\edit-probe" +``` -每个输出目录必须是新目录;`--resume` 仅复用已完整结束且输入、参数、源码和产物哈希一致的任务。准备模式与生成模式使用不同目录。失败任务不自动续发请求。 +探针只保存候选,不执行部件准备与几何验收,不能与 `--input-dir` 混用。 -| 参数 | 作用 | +| 参数 | 说明 | | --- | --- | -| `--input-dir` | SAM 输出目录,必须含 `source.png`、v2 计划、`segmentation.json`、`masks/.png` | -| `--part ID` | 指定部件,可重复;省略时处理全部有补全需求的部件 | -| `--prepare-only` | 只准备画布、区域与提示词,不请求图片模型 | -| `--candidates-dir` | 离线读取 `ID.png` 或旧补全目录首张候选,与 prepare-only 互斥 | -| `--candidate-size-policy` | strict(默认):严格尺寸一致;uniform:同宽高比缩放后重新检查 | -| `--completion-size` | 方形局部画布边长,默认 1024,128~4096;不缩放原像素 | -| `--extension-radius` | 新增区域距可见 mask 的最大距离,默认 32 像素,1~256 | -| `--completion-model` | 图片模型原始 ID,当前示例使用 qwen-image-3.0 | -| `--dry-run` | 检查输入文件、计划、参数和 Python 环境,不生成画布或请求模型 | +| `--input-dir DIR` | 完整 SAM 输出目录,部件补全必需 | +| `--out-dir DIR` | 独立新目录,准备与生成使用不同目录 | +| `--part ID` | 可重复,ID 必须存在且不重复;省略时处理所有符合筛选条件的部件 | +| `--prepare-only` | 只生成画布、区域、提示词和报告,不请求模型 | +| `--candidates-dir DIR` | 离线导入候选,与 prepare-only 互斥 | +| `--completion-size N` | 方形画布边长,默认 1024,整数 128~4096;原像素不缩放 | +| `--extension-radius N` | 轮廓延展距离与关节圆盘半径,默认 32,整数 1~256 | +| `--candidate-size-policy NAME` | strict 默认拒绝尺寸不符;uniform 允许同宽高比整画布缩放后复检 | +| `--completion-model ID` | 图片模型 ID,原样发送 | +| `--config FILE` / `--env-file FILE` | 默认 astra-qwen.json / 项目 .env;shell 同名变量优先 | +| `--python FILE` | 仅允许 ai-spine 解释器 | +| `--dry-run` | 检查输入文件、计划、参数和 Python 基础环境,不准备画布或请求模型;完整像素级 mask 校验在 prepare 中执行 | +| `--resume` | 仅复用已完成、输入/配置/源码/产物一致的任务,不自动续发失败请求 | +| `--image FILE` / `--prompt-file FILE` | 仅用于探针:PNG 图片 / 文本提示词;多次 image 需配置多图能力 | +| `--mask FILE` | 仅用于探针:透明处可编辑的 RGBA PNG,需配置 mask 能力 | -旧的 `--stage completion --image ... --prompt-file ...` 保留为独立接口探针,不能与 `--input-dir` 混用。`--stop-after` 目前仍只支持 understand/segment;第三阶段独立调用。 +配置中默认 `n=1`,逐部件串行调用。明确的 429/5xx 有限重试,超时/断网不自动重试;请求失败保留诊断并停止后续部件,几何拒绝会记录结果并继续。`--stop-after` 不支持 completion。 -## 允许新增区域 +## 4. 输入格式要求 -候选不可以随意扩大部件。程序在原图坐标中构造以下区域,并始终排除原可见 mask: - -- 遮挡补全:可见轮廓外 `extension-radius` 范围,与 `occluded_by` 指向的 SAM mask 的交集。 -- 向父关节延展:同一距离范围,与本部件 `pivot_norm` 附近半径为 `extension-radius` 的圆盘的交集。 -- 向子关节延展:同一距离范围,与直接子骨骼部件的 pivot 圆盘的交集。 - -这些是保守的几何候选区域,不是推断出的完整隐藏形状。缺少遮挡 mask、关节过远或没有子骨骼时,相应区域为空并记录告警。所有区域都为空时跳过该部件。完全隐藏或没有可见 SAM mask 的部件也跳过,不凭空生成完整肢体。 - -局部画布包含可见区域与允许新增区域,至少留 16 像素边距。`origin_xy` 记录局部左上角在原图中的坐标,可为负数;只有平移和补透明边,不进行缩放。所需范围放不下时失败,需增大画布。新增区域目前限定在原图画布范围内。 - -输入给模型的是白底可见部件。只有配置明确声明 `capabilities.mask=true` 时才发送 RGBA 编辑 mask(透明处可编辑);只有 `multiple_images=true` 时才发送第二张局部原图参考。默认配置二者均为 false,不假定中转站支持这些能力。无论是否发送编辑 mask,返回候选都经过本地允许区域约束。 - -## 返回候选的检查和合并 - -1. 默认要求尺寸与局部画布完全一致。显式选择 uniform 时,只对同宽高比候选做整画布等比例恢复;宽高比不同仍拒绝。所有模式都不自动重定位或裁切。 -2. 已有透明背景保留;不透明白底使用边界连通近白区域去底。无法提取前景则拒绝。 -3. 使用原部件 Alpha ≥240 的像素检查对齐:候选保留率至少 95%,RGB 平均绝对误差不大于 30。无不透明锚点则拒绝。这只能发现明显偏移或重绘,不能保证语义正确。 -4. 只保留允许区域中的新增像素,并去掉与原可见部分不连通的新增块。越界和不连通像素数量写入 QA。没有新增像素则拒绝。 -5. 原可见 mask 内 RGBA 逐像素恢复;候选仅提供新增像素。记录各补全子区域新增数量及 `unfulfilled_regions`,存在空缺的要求不会冒充已完成。 -6. 每个返回候选分别检查,选择第一个通过几何条件的候选。输出始终 `semantic_verified=false`、`quality_status=needs_review`。 - -上游 SAM mask 有碎片、重复或语义错分时会原样影响补全,告警保存在 JSON 和报告中。颜色/位置检查也不能验证隐藏纹理是否合理。白底去除可能影响贴边白色细节,仍需人工检查。 - -## 产物 - -| 路径 | 内容 | +| 输入 | 要求 | | --- | --- | -| `completion-plan.json` | 所有已准备任务、区域及跳过原因 | -| `tasks//input.png` | 发给模型的白底局部部件 | -| `tasks//visible.png` | 从原图保存的 RGBA 可见部件,合并时恢复像素 | -| `tasks//context.png` | 同坐标局部原图参考 | -| `tasks//edit-mask.png` | RGBA 编辑 mask,透明处允许编辑 | -| `tasks//allowed-mask.png` | 白色表示允许新增像素的区域 | -| `tasks//<补全字段>.png` | 三种补全要求各自的允许区域 | -| `tasks//task.json` / `prompt.txt` | 坐标、补全需求、上游告警 / 实际提示词 | -| `tasks//candidate-N.*` | 模型或离线导入的原始候选,拒绝时也保留 | -| `tasks//qa-N.json` | 单候选检查结果与拒绝原因 | -| `tasks//merged-N.png` | 通过几何检查后的局部 RGBA,已恢复可见像素 | -| `parts/.png` | 被选中的补全候选,紧裁剪透明 PNG | -| `completion-result.json` | 每部件状态、候选 QA、原图裁剪坐标和输出路径 | -| `report.html` | 原可见部件、允许新增区域、补全候选和告警 | -| `manifest.json` | 运行模式、网络请求标记、输入/代码/产物哈希及计数 | +| `source.png` | 原画布 PNG,使用第二阶段的 RGBA 原图 | +| `semantic-parts.json` | 有效 v2 计划;部件分类、遮挡、pivot 和补全需求合法 | +| `segmentation.json` | parts 数组,ID 唯一且存在于计划中 | +| `masks/.png` | segmentation.parts 中每个 ID 都必须有文件;原画布尺寸,灰度值仅 0/255,非空,不覆盖原图 Alpha=0 区域 | +| 中转配置 | 在线模式需地址、密钥、images-edits 提供方及图片模型;prepare-only/离线导入无需密钥 | -`parts/` 只包含本次被选中且通过几何检查的补全部件。无需补全、未选中和被拒绝的部件不会被伪装成新补全结果;最终组装需结合原 SAM 部件及这里的替换文件。Spine 导出尚未接入。 +只提供 SAM 的 `parts/` 或白底拆解图不满足要求。输入目录中无需存在 annotated.png 才能运行,但建议先通过报告复核语义。 -## 实现和验证 +离线候选支持两种形式: -[stages/completion-stage.mjs](../stages/completion-stage.mjs) 调度准备、请求、候选检查及缓存;[completion_geometry.py](../completion_geometry.py) 实现区域构造、Alpha 提取、原像素恢复和报告;[providers/image-edits.mjs](../providers/image-edits.mjs) 复用现有图片接口。 +- 平铺目录:`.png`,必须对应本次局部画布坐标、尺寸与部件;平铺文件没有旧任务 manifest 可自动核对,需自行保证一致。 +- 旧补全目录:含 manifest 和 `tasks//candidate-1.png`,也支持 jpg/webp;逐项核对源图、计划、segmentation.json、全部 mask 哈希以及画布/延展参数。每部件只取首张候选。缺失记为 missing_candidate,不联网补发。 -测试覆盖原尺寸坐标映射、Alpha 保真、三个补全字段、越界裁剪、尺寸/位移/空白候选拒绝、离线模式、显式多图与 mask 能力、错误诊断和缓存失效。使用 `conda run --no-capture-output -n ai-spine npm test` 执行,不调用真实付费模型。 +不同原图、mask 或参数的候选不能混用。尺寸之外,部件位置、朝向、比例也必须保持一致。 -最初接入时,sombrero-sam31-v3 输出可离线准备 17 个补全任务,11 个部件因无需补全而跳过。当时验证了真实输入的画布准备与 mock 编辑响应的完整合并链路,尚未执行真实 Qwen 图片生成。 +## 5. 执行链路中重要部分代码文件及原理说明(包括重点说明) -本轮验证结果:22 项 Node 测试通过(其中包含 7 个 Python 补全用例),真实输入的 `--prepare-only` 和 `--resume` 均成功。准备产物位于 `output/sombrero-completion-prepared-v2/`,打开其中 `report.html` 可检查每个部件的画布与允许新增区域。 +**允许区域。** `completion_geometry.py::allowed_regions()` 先计算可见 mask 外、距轮廓不超过 extension-radius 的区域,再分别与以下区域取交集:遮挡补全用 occluded_by 的 mask 并集;父关节延展用本部件 pivot 周围圆盘;子关节延展用直接子骨骼部件 pivot 圆盘。始终排除原可见 mask,新增范围限制在原图画布内。它是保守几何范围,不是完整隐藏形状推断。 -2026-09-20 用户运行 `output/20260918-183532/sam` 的补全任务时,head 的真实响应同时含有有效 `url` 和空字符串 `b64_json`。原解码器将空字符串误当图片,报“不支持的 PNG/JPEG/WebP 格式”。已修复为空值时使用 URL 下载,并覆盖空串、空白字符串及 null 的回归测试;22 项测试通过。 +**局部坐标。** `prepare()` 将可见区和允许区居中放入方形画布,至少留 16 像素边距,只平移和补边。`origin_xy` 是局部左上角在原图的位置,可为负数;原图位置=局部位置+origin。放不下时失败,不能偷偷缩放原像素。 -本次已从保存的 `complete/tasks/head/response.raw.json` 下载原生成结果,没有再次调用生成接口。图片保存在同级 `complete-recovered-candidates/head.png`。真实输出为 2048×2048,输入画布为 1024×1024,因此离线合并被 `CANVAS_SIZE_MISMATCH` 拒绝,报告位于 `complete-recovered-head-check/report.html`。这次格式解析问题已解决,但尺寸约束尚未通过;不能把已有 1024 输入任务的候选直接改用 `--completion-size 2048` 合并,因为新画布的像素坐标也会变化。 +**重点:当前实际发送什么。** `stages/completion-stage.mjs` 默认只发送白底 `input.png`。三个现有配置均为 `multiple_images=false`、`mask=false`,因此本地生成 context.png 和 edit-mask.png 不意味着发给模型。只有开启并验证对应能力后,分支才发送第二张同坐标局部原图参考和编辑遮罩;当前没有独立全角色参考图输入。文字边界说明及返回后的区域裁剪不能替代模型侧遮罩约束。 + +**图片解码与尺寸。** `providers/image-edits.mjs` 使用 multipart images/edits,支持非空 b64_json 或返回 URL 下载;空 b64_json 会回退有效 URL。当前部件请求显式发送 size=画布宽x高,并写入 request.json;配置 params.size 冲突会报错。strict 模式拒绝 CANVAS_SIZE_MISMATCH;uniform 仅将同宽高比整画布 LANCZOS 缩放到目标尺寸,保留原候选,不平移、不裁剪、不单独缩放物体,也不改变原图/mask。 + +**几何验收与合并。** `merge_candidate()` 去除边界连通白底,在原部件 Alpha≥240 的像素处检查 RGB 平均绝对误差≤30、可见保留率≥95%;无不透明锚点拒绝。只取允许区域内且与原部件连通的新增像素,没有有效新增即拒绝。通过后逐像素恢复原可见 RGBA,模型只提供新增部分。 + +**重点:验收仍有缺口。** `unfulfilled_regions` 记录未补到的子区域,但当前不是硬性拒绝条件;某一区域新增少量像素也不代表关节补够。语义、接缝、材质、运动露底没有自动验收。错误 SAM 像素会被原样恢复;若头部 mask 已含眼睛/胡子,当前规则也不能清除这些内部附件生成干净脸底。 + +## 6. 各个代码文件职责索引 + +| 文件 | 职责 | +| --- | --- | +| [tools/model-check.mjs](../tools/model-check.mjs) | 部件补全与独立探针分发、参数互斥检查 | +| [stages/completion-stage.mjs](../stages/completion-stage.mjs) | 输入指纹、准备、串行请求/离线读取、候选选择、状态留档 | +| [completion_geometry.py](../completion_geometry.py) | allowed_regions、prepare、merge_candidate、finalize 与报告 | +| [normalize_reference.py](../normalize_reference.py) | 候选 Alpha 保留、边界连通白底提取 | +| [providers/image-edits.mjs](../providers/image-edits.mjs) | multipart 编辑请求、能力检查、Base64/URL 图片解码 | +| [providers/http.mjs](../providers/http.mjs) | HTTP、超时、重试、诊断和脱敏 | +| [stages/model-stage.mjs](../stages/model-stage.mjs) | runCompletionProbe,仅验证编辑接口 | +| [lib/config.mjs](../lib/config.mjs) / [lib/images.mjs](../lib/images.mjs) | 提供方、模型与能力配置 / 图片格式、尺寸和哈希 | +| [lib/python-runtime.mjs](../lib/python-runtime.mjs) / [lib/validate-parts.mjs](../lib/validate-parts.mjs) | Conda 检查 / v2 结构校验 | +| [lib/run-artifacts.mjs](../lib/run-artifacts.mjs) | 输出目录、复用、状态和产物哈希 | +| [prompts/complete-v1.txt](../prompts/complete-v1.txt) | 保持姿势、尺寸、可见纹理与隐藏区域补全约束 | +| [Tiantoken](../configs/tiantoken.json)、[DeepSeek/Qwen](../configs/deepseek-qwen.json)、[Astra/Qwen](../configs/astra-qwen.json) 配置 | 图片模型、认证变量、请求参数与能力开关 | +| [tests/completion-stage.test.mjs](../tests/completion-stage.test.mjs) / [tests/test_completion.py](../tests/test_completion.py) | mock 编辑、离线复用、尺寸/对齐拒绝、像素保真与区域回归 | +| [tests/model-stages.test.mjs](../tests/model-stages.test.mjs) | 提供方与探针相关回归 | + +## 7. 产物详细说明 + +| 路径 | 内容与用途 | +| --- | --- | +| `source.png`、`semantic-parts.json`、`segmentation.json`、`masks/` | 输入快照,用于复现与离线候选身份核对 | +| `completion-plan.json` | 准备任务、允许区域、参数和跳过原因 | +| `tasks//input.png` | 白底局部可见部件,默认唯一模型输入图 | +| `tasks//visible.png` | 原图可见 RGBA,合并时恢复像素 | +| `tasks//context.png` | 同坐标局部原图参考,当前默认不发送 | +| `tasks//edit-mask.png` | RGBA 编辑遮罩,透明处可编辑,当前默认不发送 | +| `tasks//allowed-mask.png` | 白色表示允许新增区域 | +| `tasks//<补全字段>.png` | 启用的补全子区域 mask | +| `tasks//task.json` / `prompt.txt` | origin、区域、需求和告警 / 实际提示词 | +| `tasks//request.json` | 在线请求模型、图片哈希、是否发送 mask;修复后含 size | +| `tasks//response.raw.json` / `request-metadata.json` | 在线响应留档 / 请求 ID、耗时等元数据 | +| `tasks//response.error.json` | 可获取时保存的脱敏请求失败诊断 | +| `tasks//candidate-N.*` | 模型或离线导入的原始候选,拒绝也保留 | +| `tasks//merged-N-normalized.png` | uniform 实际重采样时保存的候选;不代表通过 | +| `tasks//qa-N.json` | 尺寸、对齐、新增/丢弃像素、各区域完成情况、拒绝原因 | +| `tasks//merged-N.png` | 通过几何检查且恢复原可见像素后的局部 RGBA | +| `parts/.png` | 每部件选中结果的紧裁剪透明 PNG | +| `completion-result.json` | 每部件状态、候选 QA、原图 crop_xyxy 和路径 | +| `report.html` / `manifest.json` | 人工检查页 / 模式、网络标记、状态、输入/代码/产物哈希 | + +parts/ 只含本次选中且通过检查的补全部件,不是全部 SAM 部件集合。无需补全、失败和未选中的部件不会自动复制进来,也没有完整角色组装图。 + +当前实验:`output/20260918-183532/complete2_gpt` 已真实请求 Tiantoken gpt-image-2 共 12 个部件。旧请求未传 size,返回 1248/1254 方形图,预期为 1024,全部严格尺寸拒绝。`complete2_gpt-size-recheck-v2` 离线复用原候选后,8 个几何通过;head、pants_thigh_l、pants_thigh_r、shoe_l 共 4 个因对齐或无有效新增拒绝。通过项中仍有衣料误分、错误手部和未补全子区域。显式 size 的请求构造已验证,但尚无修复后中转遵守 size 的新实测结论。 + +## 8. 当前阶段可改进点说明 + +- **补全后输出使用补全部件的完整角色。** 按原图坐标和遮挡顺序组装,复用无需补全的原拆件,明确标记失败项及回退来源;输出补全前后对比、接缝/重叠诊断。不能只展示少数 parts 文件作为完整结果。 +- **把原图或部件相关原图区域交给补全模型参考。** 接入并实测全角色/局部上下文参考和编辑 mask,记录实际发送内容。不能仅把 capabilities 改为 true 就宣称中转支持;需验证图片顺序、mask 语义、返回尺寸和画面保持能力。 +- **根据 SAM 实际结果重建需求。** 区分分割缺口修复、遮挡补全、关节延伸、附件底图清理;对应建立保留区域与可编辑区域,避免误分像素被永久保护。 +- **改进画布与补全区域。** 固定 32 像素不适配所有部件;小部件在 1024 大白底中占比低。可验证按部件设计区域、显式局部放大并记录逆变换,保证回贴坐标可检查。 +- **加强验收。** 对必需区域定义有效覆盖要求,增加部件语义、接缝、材质、回贴和关节旋转露底检查;不能放宽阈值来掩盖重绘、位移或错误输入。 +- **按小样验证后批量。** 先修正 SAM 输入,再用头、前臂、上衣验证参考图与遮罩,比较原输入、原候选、合并图和回贴图,确认改善后再跑全量。 diff --git a/docs/model-stages.md b/docs/model-stages.md deleted file mode 100644 index 10fd4e8..0000000 --- a/docs/model-stages.md +++ /dev/null @@ -1,172 +0,0 @@ -# 第一阶段:可替换模型接口与角色结构理解 - -本轮实现结构理解、图片编辑适配器、结构 JSON 校验、Alpha 几何校验、候选种子、诊断预览和实验缓存。几何层需要 Python 与 requirements.txt,不运行旧的“拆件图 → SIFT 定位”流程。 - -结构理解支持停在 `understand`,也可通过 `--stop-after segment` 接续本地 SAM 分割,或使用 `--stage segmentation --input-dir` 独立执行第二阶段。第三阶段使用 `--stage completion --input-dir SAM目录` 完成部件画布准备、候选生成、限制新增区域和原像素恢复,详见[第三阶段文档](3-completion-stage.md)。掩码语义修正、补全的语义验收和 Spine 骨骼导出尚未完成。旧的 `--image --prompt-file` 图片编辑探针仍只保存原始候选。 - -## 环境与模型 - -要求 Node.js 20 或更高版本,无新增 npm 依赖。在 `AI_spine` 目录、已激活的 `ai-spine` Conda 环境中运行。每次修改须遵守 [AGENTS.md](../AGENTS.md)。 - -复用现有 `.env` 的地址和密钥,可增加: - -```dotenv -SPINE_UNDERSTANDING_MODEL=gpt-6-astra -SPINE_COMPLETION_MODEL=qwen-image-3.0 -SAM_MODEL_DIR=F:/Study/SAM3 -``` - -不配置这三项时,`configs/astra-qwen.json` 已提供相同默认值。不会自动改写用户的 `.env`。 - -查询中转站模型 ID(只读取列表,不调用生成): - -```powershell -node .\tools\model-check.mjs --list-models -``` - -模型展示名不等于 API ID。2026-09-17 的本机接口查询包含 `gpt-6-astra` 和 `qwen-image-3.0`。支持列表不保证所有端点/多图/mask 参数可用,需要分别验证。 - -本地配置检查(不联网,不生成图片): - -```powershell -node .\tools\model-check.mjs --dry-run -``` - -## 运行结构理解 - -```powershell -node .\pipeline.mjs --mode annotated-parts --reference ..\spine-animation-ai\demo\character_reference.png --out-dir .\output\sombrero-astra --stop-after understand -``` - -首次调用会向配置的中转站发送参考图。每个实验使用新输出目录;本轮不会自动覆盖旧产物。 - -切换理解模型: - -```powershell -node .\pipeline.mjs --mode annotated-parts --reference ..\spine-animation-ai\demo\character_reference.png --out-dir .\output\sombrero-other --understanding-model YOUR_EXACT_MODEL_ID --stop-after understand -``` - -切换协议(需中转站实际支持): - -```powershell -node .\pipeline.mjs --mode annotated-parts --reference ..\spine-animation-ai\demo\character_reference.png --out-dir .\output\sombrero-responses --understanding-protocol responses --stop-after understand -``` - -协议可选 `chat-completions` / `responses`,默认 `responses`:本机中转站实测 Astra 的 codex channel 明确拒绝 `/v1/chat/completions`。输出模式默认 `text-json`:在提示词中提供 Schema,并始终在本地严格校验。显式确认中转站支持后,可使用 `--output-mode json-object` 或 `--output-mode json-schema`。不会因 400/不支持的协议自动换模型或偷偷降低输出约束。 - -该 Astra 通道还要求 `stream=true`,所以默认配置启用流式 Responses,并设置 `store=false`。适配器收集 SSE 后只接受完整的终止事件,输出仍是普通 JSON 文件。新模型可在阶段配置中设置 `stream: false`。`response.raw.json` 对 SSE 保存终止事件中的 response 对象,非逐字节 SSE 日志;`request-metadata.json` 记录 wire_format。 - -切换到非流式 Chat Completions 模型时可使用 `--understanding-protocol chat-completions --stream false`,不会沿用 Astra 的流式设置。 - -项目同时提供 `configs/deepseek-qwen.json`。它把第一阶段固定为 -`deepseek-flash + chat-completions + stream=false`,第三阶段仍使用 -`qwen-image-3.0`,适合与默认的 `configs/astra-qwen.json` 做对照实验: - -```powershell -node .\pipeline.mjs --mode annotated-parts ` - --config .\configs\deepseek-qwen.json ` - --reference ..\spine-animation-ai\demo\character_reference.png ` - --out-dir .\output\sombrero-understand-deepseek ` - --stop-after understand -``` - -主要产物: - -| 文件 | 含义 | -| --- | --- | -| `source-original.png` / `source.png` | 原始输入 / 预处理 RGBA,不缩放、不裁剪 | -| `preprocessing.json` | Alpha 保留或边界连通白底去除记录 | -| `semantic-parts.json` | 已通过结构校验的部件清单 | -| `geometry-validation.json` | 原始点 Alpha 检查、ROI 前景比例、候选来源和阻塞原因 | -| `segmentation-prompts.json` | 语义 + 粗框 + 程序候选点;不转发模型原始点,始终需要 mask QA | -| `annotated.svg` | 原图上的粗框、关节点、正点和父子连线,可直接浏览器打开 | -| `report.html` | 自包含检查页面,带部件表和模型记录 | -| `validation.json` | 字段、坐标、引用、父子环和遮挡环校验结果 | -| `response.raw.json` / `response.txt` | 原始服务端响应 / 提取的文本 | -| `prompt.txt` / `request.json` | 提示词 / 请求设置与输入哈希;图片内容单独保存在 source.png | -| `request-metadata.json` | requested/returned model、request ID、usage、耗时和请求次数 | -| `manifest.json` | 运行状态、配置、代码版本、源文件哈希和产物哈希 | - -`status=completed` 仅表示这一步执行完成。`quality_status=needs_review` 表示仍需人工检查语义和框的位置。粗框不是像素 mask,输出也不是自动批准的骨骼。 - -v2 计划新增 `rig_role`、`bind_to` 和 `completion`(遮挡补全、父关节延展、子关节延展),`needs_completion` 必须等于三项逻辑或。新提示词让模型正负点留空;旧点仅用于诊断,程序从 ROI ∩ Alpha 前景重新生成候选,pivot 不参与前景吸附。空 ROI 标记 blocked,不生成替代点。 - -使用 `--parts-file semantic-parts.json --reference source.png --out-dir 新目录` 可离线迁移 v1 或检查 v2,无需密钥或网络。Python 固定使用 Conda 环境 `ai-spine`,`--python` 也必须指向该环境。依赖安装命令为 `conda run -n ai-spine python -m pip install -r requirements.txt`,完整说明见 README。背景预处理无法获得可用 Alpha 时在模型请求前失败。边界连通白底去除是一种保守启发式,贴到画布边缘的白色角色区域仍需人工检查。 - -校验失败保存原始响应、validation 和报告,退出码为非零,不继续分割。网络/API 失败保存失败 manifest。拒绝、截断和不完整 Responses 都不会被当作成功。 - -HTTP/SSE/网络失败还保存 `response.error.json`:状态码、请求 ID、耗时、尝试次数、响应体(最多 2 MB)或网络错误代码,密钥会脱敏。若服务端返回 overloaded,使用新目录稍后重跑;这不表示 schema 或分割模型出错。 - -## 独立测试图片编辑接口 - -先准备一个局部部件 PNG 和任务文本 `task.txt`,例如: - -```text -The input canvas contains the screen-left forearm. Complete the hidden elbow -connection behind the sleeve. Keep the visible hand and forearm in their exact -positions. Preserve the original outline and shading. Do not add other parts. -``` - -调用 Qwen: - -```powershell -node .\tools\model-check.mjs --stage completion --image .\local-part.png --prompt-file .\task.txt --out-dir .\output\qwen-edit-test --completion-model qwen-image-3.0 -``` - -改 `--completion-model` 即可对比另一个兼容的图片编辑模型。此命令直接调用图片接口并可能计费,不调用结构理解。 - -结果保存 `candidate-1.png`(或服务端实际返回的 JPEG/WebP 扩展名)、输入图、任务提示词、原始响应和运行记录。PNG 输出会记录是否与输入画布同尺寸;尺寸相同不代表内容对齐。 - -默认图片适配器只发送一张图。若中转站确认支持多图,在配置中启用 `capabilities.multiple_images`,并使用重复 `--image`:第一张是局部画布,其余是原图/标注图参考。字段名通过 `image_field` 选择 `image` 或 `image[]`。 - -若确认支持编辑 mask,再启用 `capabilities.mask` 并使用 `--mask edit-mask.png`。当前适配器约定透明像素可编辑,要求 mask 与第一张图同尺寸、包含 alpha 通道。SAM 的普通黑白 mask 不能直接当作编辑 alpha mask。未启用能力时参数会明确报错,不静默忽略。 - -本轮没有恢复原始可见像素,也没有生成隐藏区域的透明掩码;因此候选始终标记 `raw_completion_probe` 和 `needs_review`,不能直接接入最终 atlas。 - -## 配置与切换规则 - -`configs/astra-qwen.json` 分离 `providers` 和 `stages`: - -- provider:协议、base URL/key 的环境变量名、超时、重试次数、多图和 mask 声明。 -- stage:provider 名称、模型、提示词文件、输出模式和模型特定参数。 -- 提示词路径相对于配置 JSON 所在目录解析;命令行输入/输出路径相对于当前目录。 -- 模型优先级:CLI > 阶段显式 `model` > `model_env` 环境变量 > `default_model`。 -- shell 环境覆盖 `.env`。实验 JSON 不应存放密钥,仅引用密钥环境变量名。 -- 不同服务可配置各自的 base URL/key 环境变量。 -- 模型 ID 原样发送,不再把 `gpt-image-2.5` 映射成其他模型。 -- `params` 允许模型特定参数,但不能覆盖 model、prompt、messages、input 等适配器保留字段。 -- 新模式的超时/重试来自 provider 配置;旧模式的图片超时仍用 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`。 - -例如把理解阶段改为固定模型: - -```json -{ - "provider": "relay-vision", - "model": "YOUR_EXACT_MODEL_ID", - "prompt": "../prompts/understand-v1.txt", - "output_mode": "text-json", - "params": {} -} -``` - -## 重跑与对比 - -同一命令增加 `--resume`,仅当上次完整结束,且模型、协议、参数、提示词、Schema、源图、适配器代码和所有产物校验一致时复用。模型变化时要求新的输出目录,防止覆盖对照组。失败任务也保留原目录,使用新目录重跑。 - -理解、SAM、部件补全和补全探针各自记录独立缓存。SAM 额外校验输入计划、候选提示、本地源码和权重哈希;部件补全校验语义计划、所有输入 mask、画布参数、源码及离线候选哈希。对比补全模型时,固定相同局部画布、任务文本与掩码。 - -显式 429/5xx 最多按配置重试,超时或网络断开不自动重试,因为服务端可能已经执行任务。完整请求不保证模型内容可复现;seed 只在提供方确认支持时放入 params,usage 不存在时记录 null,不估造价格或 token 数。 - -## SAM 路径 - -默认根目录 `F:/Study/SAM3`:源码位于 `sam3/`,权重位于 `sam3.1checkpoint/sam3.1_multiplex.pt`。可通过 `--sam-dir`、`--sam-code-dir`、`--sam-checkpoint` 覆盖。独立分割无需中转站凭据,在 `ai-spine` Conda 临时子进程加载 GPU 模型,结束即退出。命令、权重适配及当前质量限制见[第二阶段文档](2-segmentation-stage.md)。 - -## 测试 - -```powershell -conda run -n ai-spine npm test -``` - -测试使用本地 mock HTTP 服务或注入响应,不调用真实付费模型。覆盖模型优先级、协议请求/响应、multipart、能力限制、数值/引用/环校验、错误响应、重试、缓存和 CLI 全链路。 - -2026-09-17 的集成检查:模型列表请求成功;Astra 要求 Responses + stream=true,切换后服务端返回 overloaded,尚未得到成功的真实角色标注。Qwen 适配器通过 mock 请求/响应测试,本轮未执行真实图片编辑生成。此状态不等于视觉质量已验证。