文档整理
This commit is contained in:
@@ -0,0 +1,344 @@
|
||||
# 第一阶段:视觉 LLM 角色结构理解
|
||||
|
||||
第一阶段把单张角色参考图转换为结构化的语义部件计划,供后续 SAM 分割、遮挡补全和 Spine 骨骼生成使用。
|
||||
|
||||
本阶段只做角色结构理解和粗标注,不生成精确 mask、透明拆件 PNG 或补全后的隐藏部件。
|
||||
|
||||
## 1. 输入、输出与执行链路
|
||||
|
||||
输入是一张完整的 PNG 角色参考图。核心输出是 <code>semantic-parts.json</code>,其中记录:
|
||||
|
||||
- 角色由哪些可动部件组成;
|
||||
- 每个部件的语义名称;
|
||||
- 部件之间的运动父子关系;
|
||||
- 部件之间的视觉遮挡关系;
|
||||
- 可见、部分可见或完全隐藏状态;
|
||||
- 可见区域粗框、预计关节位置和 SAM 提示点;
|
||||
- 是否需要在第三阶段补全;
|
||||
- 模型对判断结果的自报置信度。
|
||||
|
||||
整体执行链路:
|
||||
|
||||
~~~text
|
||||
角色原图
|
||||
↓
|
||||
读取模型配置、提示词和输出 Schema
|
||||
↓
|
||||
构造视觉 LLM 请求
|
||||
↓
|
||||
DeepSeek Flash / GPT-6 Astra
|
||||
↓
|
||||
提取模型返回的 JSON 文本
|
||||
↓
|
||||
Schema 校验和部件关系校验
|
||||
↓
|
||||
semantic-parts.json
|
||||
↓
|
||||
生成 annotated.svg 和 report.html
|
||||
↓
|
||||
人工复核后交给 SAM 分割阶段
|
||||
~~~
|
||||
|
||||
## 2. 命令入口
|
||||
|
||||
示例:
|
||||
|
||||
~~~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
|
||||
~~~
|
||||
|
||||
第一步由以下两个文件负责:
|
||||
|
||||
1. [pipeline.mjs](../pipeline.mjs) 检测 <code>--mode annotated-parts</code>,把命令转交给新管线,不进入旧版“生成拆件图 → CV 定位”流程。
|
||||
2. [tools/model-check.mjs](../tools/model-check.mjs) 解析参数、加载配置、应用命令行覆盖、检查输入并调用 <code>runUnderstanding()</code>。
|
||||
|
||||
## 3. 配置解析
|
||||
|
||||
当前提供两组实验配置:
|
||||
|
||||
| 配置 | 理解模型 | 协议 | 流式 |
|
||||
| --- | --- | --- | --- |
|
||||
| [configs/deepseek-qwen.json](../configs/deepseek-qwen.json) | <code>deepseek-flash</code> | <code>chat-completions</code> | <code>false</code> |
|
||||
| [configs/astra-qwen.json](../configs/astra-qwen.json) | <code>gpt-6-astra</code> | <code>responses</code> | <code>true</code> |
|
||||
|
||||
[lib/config.mjs](../lib/config.mjs) 负责读取:
|
||||
|
||||
- JSON 配置文件;
|
||||
- 项目 <code>.env</code> 或 <code>--env-file</code>;
|
||||
- 当前 shell 环境变量;
|
||||
- 模型、协议、输出模式、超时和重试设置;
|
||||
- 阶段提示词;
|
||||
- SAM checkpoint 路径。
|
||||
|
||||
模型选择优先级:
|
||||
|
||||
~~~text
|
||||
命令行 --understanding-model
|
||||
> stage.model
|
||||
> SPINE_UNDERSTANDING_MODEL
|
||||
> stage.default_model
|
||||
~~~
|
||||
|
||||
Shell 环境变量优先于 <code>.env</code>。模型 ID 会原样传给中转站,不做隐式别名转换。
|
||||
|
||||
配置中的 <code>params</code> 不能覆盖模型、消息体、输入、流式选项和认证字段,避免实验配置改变基础请求语义或泄漏密钥。
|
||||
|
||||
## 4. 读取参考图
|
||||
|
||||
[lib/images.mjs](../lib/images.mjs) 读取参考图,并得到:
|
||||
|
||||
- 原始文件字节;
|
||||
- MIME 类型;
|
||||
- 图片宽高;
|
||||
- SHA-256;
|
||||
- 模型请求使用的 Base64 Data URL。
|
||||
|
||||
本阶段要求参考图为 PNG。实际提交给模型的输入会原样复制为输出目录中的 <code>source.png</code>,不缩放、不裁剪。
|
||||
|
||||
## 5. 理解提示词
|
||||
|
||||
提示词位于 [prompts/understand-v1.txt](../prompts/understand-v1.txt),要求视觉 LLM:
|
||||
|
||||
- 保留角色原始姿势、朝向和不对称性;
|
||||
- 仅在独立运动有意义且图像支持时拆分部件;
|
||||
- 区分运动父子关系和视觉遮挡关系;
|
||||
- 使用完整画布的归一化坐标;
|
||||
- 输出粗框、预计关节和 SAM 提示点;
|
||||
- 不把粗框声称为像素级 mask;
|
||||
- 不凭空创造没有视觉证据的隐藏肢体或附件;
|
||||
- 将不确定性和假设写入 <code>notes</code>。
|
||||
|
||||
请求适配器还会附加原图画布尺寸和完整 JSON Schema,并要求模型只返回符合 Schema 的 JSON。最终提示词副本保存在 <code>prompt.txt</code>。
|
||||
|
||||
## 6. 输出数据契约
|
||||
|
||||
结构定义位于 [schemas/semantic-parts.schema.json](../schemas/semantic-parts.schema.json)。顶层格式:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"schema_version": 1,
|
||||
"coordinate_space": "normalized_xy_top_left",
|
||||
"parts": [],
|
||||
"notes": []
|
||||
}
|
||||
~~~
|
||||
|
||||
每个部件包含:
|
||||
|
||||
| 字段 | 含义 |
|
||||
| --- | --- |
|
||||
| <code>id</code> | 稳定、唯一的小写 ASCII 部件 ID |
|
||||
| <code>semantic</code> | 部件语义说明 |
|
||||
| <code>parent</code> | 运动层级中的父部件;<code>null</code> 表示未来挂到 root |
|
||||
| <code>visibility</code> | <code>visible</code>、<code>partial</code> 或 <code>hidden</code> |
|
||||
| <code>bbox_norm_xyxy</code> | 可见区域粗框 <code>[xmin, ymin, xmax, ymax]</code> |
|
||||
| <code>pivot_norm</code> | 预计的关节或连接点 |
|
||||
| <code>positive_points_norm</code> | 后续 SAM 的正提示点 |
|
||||
| <code>negative_points_norm</code> | 后续 SAM 的负提示点 |
|
||||
| <code>occluded_by</code> | 视觉上遮挡当前部件的其他部件 |
|
||||
| <code>needs_completion</code> | 是否需要补全不可见区域 |
|
||||
| <code>confidence</code> | LLM 自报置信度,范围 0~1 |
|
||||
|
||||
所有坐标都以完整画布左上角为原点并归一化到 0~1。例如:
|
||||
|
||||
~~~json
|
||||
"bbox_norm_xyxy": [0.36, 0.36, 0.70, 0.62]
|
||||
~~~
|
||||
|
||||
对应像素坐标:
|
||||
|
||||
~~~text
|
||||
xmin = canvas_width × 0.36
|
||||
ymin = canvas_height × 0.36
|
||||
xmax = canvas_width × 0.70
|
||||
ymax = canvas_height × 0.62
|
||||
~~~
|
||||
|
||||
## 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
|
||||
~~~
|
||||
|
||||
适配器把同一任务转换成 <code>input_text</code> 和 <code>input_image</code> 格式,因此模型业务逻辑与具体 API 协议保持分离。
|
||||
|
||||
<code>output_mode</code> 支持:
|
||||
|
||||
- <code>text-json</code>:通过提示词约束 JSON,再在本地严格校验;
|
||||
- <code>json-object</code>:中转站确认支持后使用 JSON Object 模式;
|
||||
- <code>json-schema</code>:中转站确认支持后使用 Structured Outputs。
|
||||
|
||||
当前已验证的 DeepSeek 配置使用 <code>text-json</code>。
|
||||
|
||||
## 8. 中转站通信
|
||||
|
||||
[providers/http.mjs](../providers/http.mjs) 负责:
|
||||
|
||||
- 拼接 base URL 和协议路由;
|
||||
- 添加 Bearer Authorization;
|
||||
- 控制请求超时;
|
||||
- 对明确的 HTTP 429 和 5xx 有限重试;
|
||||
- 解析普通 JSON 或完整 SSE;
|
||||
- 拒绝被截断的流式响应;
|
||||
- 记录请求 ID、模型、token、耗时和尝试次数;
|
||||
- 从错误信息和落盘文件中脱敏 API Key。
|
||||
|
||||
超时或网络中断不会自动重试,因为服务端可能已经执行并计费。失败时会尽量生成 <code>response.error.json</code>,保存脱敏后的状态码、响应片段或网络错误码。
|
||||
|
||||
## 9. 提取与校验模型结果
|
||||
|
||||
[providers/vision.mjs](../providers/vision.mjs) 从不同协议的响应中提取模型文本,并拒绝:
|
||||
|
||||
- 模型 refusal;
|
||||
- 非正常 <code>finish_reason</code>;
|
||||
- 未完成的 Responses 状态;
|
||||
- 没有结构理解文本的响应。
|
||||
|
||||
提取后的内容保存在 <code>response.txt</code>。
|
||||
|
||||
[lib/validate-parts.mjs](../lib/validate-parts.mjs) 首先去掉模型可能添加的 Markdown JSON 代码块,然后执行 JSON 解析和两层本地校验。
|
||||
|
||||
### Schema 校验
|
||||
|
||||
- 必填字段是否齐全;
|
||||
- 类型与枚举是否正确;
|
||||
- ID 格式是否合法;
|
||||
- 坐标和置信度是否在 0~1;
|
||||
- 部件数量是否在 1~64;
|
||||
- 是否出现未知字段。
|
||||
|
||||
### 结构语义校验
|
||||
|
||||
- 部件 ID 不能重复;
|
||||
- <code>parent</code> 和 <code>occluded_by</code> 必须引用已有部件;
|
||||
- 部件不能引用自己;
|
||||
- 父子关系和遮挡关系不能形成环;
|
||||
- 可见部件必须具有正面积 bbox;
|
||||
- 可见部件必须至少有一个正提示点;
|
||||
- 正提示点必须位于 bbox 内;
|
||||
- 完全隐藏部件必须没有可见框和正点,并设置 <code>needs_completion=true</code>;
|
||||
- 自报置信度低于 0.6 时产生人工复核警告。
|
||||
|
||||
校验结果写入 <code>validation.json</code>。只有校验通过时才会写出正式的 <code>semantic-parts.json</code>。
|
||||
|
||||
## 10. 可视化与人工复核
|
||||
|
||||
[lib/report.mjs](../lib/report.mjs) 将结构理解结果叠加到原图:
|
||||
|
||||
- 彩色矩形:模型预测的可见区域粗框;
|
||||
- 实心圆:SAM 正提示点;
|
||||
- 空心圆:部件 pivot;
|
||||
- 虚线:当前部件到父部件的关系;
|
||||
- 文本:部件 ID。
|
||||
|
||||
它会生成:
|
||||
|
||||
- <code>annotated.svg</code>:可缩放的原图标注;
|
||||
- <code>report.html</code>:包含标注图、校验结果、部件表、模型说明和请求元数据的自包含检查页。
|
||||
|
||||
<code>status=completed</code> 只表示请求、解析和本地校验完成。成功结果仍设置 <code>quality_status=needs_review</code>,因为结构合法不等于语义和框位置一定正确。
|
||||
|
||||
人工复核至少应检查:
|
||||
|
||||
1. 是否遗漏身体、头部或关键肢体;
|
||||
2. 左右肢体是否符合画面方向;
|
||||
3. 是否过度拆分面部或服饰细节;
|
||||
4. 父子关系能否支持预期动画;
|
||||
5. 遮挡关系是否与原图一致;
|
||||
6. bbox 和提示点是否落在正确部件上;
|
||||
7. <code>needs_completion</code> 是否覆盖确实需要补全的部分。
|
||||
|
||||
## 11. 阶段调度与实验留档
|
||||
|
||||
[stages/model-stage.mjs](../stages/model-stage.mjs) 是第一阶段总调度器:
|
||||
|
||||
~~~text
|
||||
读取图片
|
||||
→ 计算输入、Schema、配置和代码指纹
|
||||
→ 创建运行目录
|
||||
→ 保存输入、提示词和请求摘要
|
||||
→ 调用视觉 LLM
|
||||
→ 保存原始响应和请求元数据
|
||||
→ 提取并校验 JSON
|
||||
→ 保存正式语义结果
|
||||
→ 生成标注和检查报告
|
||||
→ 更新 manifest
|
||||
~~~
|
||||
|
||||
[lib/run-artifacts.mjs](../lib/run-artifacts.mjs) 负责输出目录、恢复校验、产物哈希和最终状态。
|
||||
|
||||
<code>--resume</code> 只在原图、模型、协议、参数、提示词、Schema、相关源代码和已有产物全部一致时复用结果。不同模型或提示词实验应使用不同输出目录。
|
||||
|
||||
## 12. 输出文件
|
||||
|
||||
| 文件 | 作用 |
|
||||
| --- | --- |
|
||||
| <code>source.png</code> | 模型实际看到的原始输入副本 |
|
||||
| <code>prompt.txt</code> | 本次解析后的阶段提示词 |
|
||||
| <code>request.json</code> | 可复现实验的请求摘要,不包含 API Key 或完整 Base64 请求体 |
|
||||
| <code>response.raw.json</code> | 中转站原始成功响应 |
|
||||
| <code>response.txt</code> | 从协议响应中提取的模型文本 |
|
||||
| <code>request-metadata.json</code> | 请求模型、返回模型、request ID、usage、耗时、次数和 wire format |
|
||||
| <code>validation.json</code> | Schema 与结构语义校验结果 |
|
||||
| <code>semantic-parts.json</code> | 校验通过后的正式结构理解结果 |
|
||||
| <code>annotated.svg</code> | 原图上的粗框、pivot、提示点和父子连线 |
|
||||
| <code>report.html</code> | 用于人工语义复核的综合页面 |
|
||||
| <code>manifest.json</code> | 状态、配置、输入哈希、代码版本、SAM 信息和全部产物哈希 |
|
||||
| <code>response.error.json</code> | HTTP、SSE 或网络失败时的脱敏诊断信息;成功时不存在 |
|
||||
|
||||
<code>request.json</code> 是请求身份摘要,不等同于线上发送的完整 HTTP body。图片内容单独保存在 <code>source.png</code>,密钥不会写入产物。
|
||||
|
||||
## 13. 代码职责索引
|
||||
|
||||
| 文件 | 职责 |
|
||||
| --- | --- |
|
||||
| [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/report.mjs](../lib/report.mjs) | SVG 标注和 HTML 检查报告 |
|
||||
| [lib/run-artifacts.mjs](../lib/run-artifacts.mjs) | 输出目录、恢复校验、状态和产物哈希 |
|
||||
| [stages/model-stage.mjs](../stages/model-stage.mjs) | 第一阶段总调度与失败处理 |
|
||||
|
||||
## 14. 当前边界与下一阶段接口
|
||||
|
||||
第一阶段输出的是语义计划,而不是分割结果:
|
||||
|
||||
~~~text
|
||||
视觉 LLM 输出
|
||||
= 部件语义 + 层级 + 遮挡 + 粗框 + 提示点
|
||||
|
||||
视觉 LLM 不输出
|
||||
= 可信的像素 mask + 透明拆件 + 隐藏区域补全 + 最终骨骼
|
||||
~~~
|
||||
|
||||
下一阶段应读取 <code>semantic-parts.json</code>,把每个可见或部分可见部件的粗框和正负提示点转换为像素坐标,再交给 SAM 3.1 生成候选 mask。
|
||||
|
||||
<code>manifest.json</code> 当前只记录 SAM checkpoint 是否存在,<code>runtime_status</code> 仍为 <code>not_integrated</code>,不会加载权重或占用 GPU。
|
||||
Reference in New Issue
Block a user