feat(plugin): AI 审美批改 - 增加结构化视觉分析与精准标注 (#387)

* feat(portrait-clearance): 肖像排查 - 增加画布插件与本机检测链路

* fix(web): 插件中心 - 修复应用插件筛选与自动定位

* feat(plugin): AI审美批改 - 完成分析报告与问题标注闭环
This commit is contained in:
QAyong
2026-09-02 20:32:58 +08:00
committed by GitHub
parent c69320f325
commit 6d0e7a5228
29 changed files with 4909 additions and 15 deletions

View File

@@ -0,0 +1,448 @@
---
title: AI 审美批改画布插件
description: 面向图片创作的 AI 视觉分析、问题定位和修改建议插件设计。
---
# AI 审美批改画布插件
> 状态:MVP 已实现,当前审美标准为 `2026-08-v1`。
## 1. 先说结论
这个节点的定位不是“图片生成器”,而是一个视觉老师:用户把图片接进来,它负责看图、指出问题、解释原因,并给出可以执行的修改方向。
它的核心输出是一个结构化的 `CritiqueReport`(批改报告),不是另一张图片。
| 输出层 | 内容 | 是否是默认产物 |
| -------- | ---------------------------------------------- | ---------------------- |
| 逻辑输出 | 总结、优点、问题、问题位置、严重程度、修改建议 | 是 |
| 展示输出 | 在原图上叠加的框、点、箭头和高亮 | 是,但只是报告的可视化 |
| 图片输出 | 导出的标注图或按建议生成的修正版 | 否,作为后续操作 |
因此,第一版可以把它设计成画布中的“分析终点”:图片节点连入批改节点,批改节点打开报告面板;暂时不要求它再连接到下游图片节点。
## 2. 与原始架构文档的关系
用户提供的 `ai-art-critique-architecture.md` 是产品和技术方案参考,不是本仓库的强制实现指令。它描述的能力方向可以保留,但工程落点需要适配当前项目:
- 使用当前 `web/` 的 Vite、React、画布和插件系统。
- 复用现有图片资源、模型渠道中转和 `ai.text` 能力。
- 不另起一个 Next.js、Fastify、Postgres、Drizzle 或 R2 子项目。
- 第一版不把第三方插件代码直接当作主应用 React 代码运行。
- 先做一个受信任的内置插件,等协议稳定后再考虑开放给外部插件。
## 3. 用户怎么使用
典型流程如下:
```text
图片节点
-> 创建或连接“AI 审美批改”节点
-> 点击“开始批改”
-> AI 看图并返回结构化结果
-> 本地校验和整理结果
-> 在原图上绘制标注
-> 用户查看问题、原因和修改建议
-> 重新分析,或执行后续动作
```
第一版只支持一张输入图片。图片必须已经能被当前画布资源系统读取;如果输入节点没有可用图片,节点显示明确的空态和修复提示,不发起模型请求。
## 4. 输入和输出合同
### 4.1 输入
输入是画布中一个可读取的图片资源,至少需要包含:
- 图片资源引用或本地资源 ID。
- 图片的宽高,或者能够在运行时读取到宽高。
- 可读取的图片数据,例如资源 URL、blob 或 data URL。
- 图片版本指纹,用于判断报告是否已经过期。
输入不应该直接把任意网页 URL 原样交给模型。资源读取要继续遵守现有资源权限和媒体读取边界。
### 4.2 核心输出:`CritiqueReport`
建议把报告控制在一个适合保存到节点的大小,第一版最多保留 5 个重点问题;`0` 个问题是合法结果,可选的风格方向单独保存:
```ts
type CritiqueReport = {
schemaVersion: 1;
rubricVersion?: "2026-08-v1";
summary: string;
strengths: string[];
issues: CritiqueIssue[];
options?: CritiqueOption[];
sourceFingerprint: string;
createdAt: string;
modelLabel?: string;
scene?: SceneUnderstanding;
pipelineWarnings?: string[];
verificationSummary?: {
checked: number;
confirmed: number;
uncertain: number;
rejected: number;
};
};
type CritiqueIssue = {
id: string;
category: "composition" | "color" | "lighting" | "proportion" | "other";
title: string;
explanation: string;
severity: "low" | "medium" | "high";
confidence: number; // 0..1,表示模型对判断的把握
target: {
type: "box" | "point" | "points" | "polygon" | "global";
// 所有坐标都使用相对于原图的 0..1 归一化坐标
points?: Array<{ x: number; y: number }>;
};
targetDescription?: string; // Reviewer 给出的自然语言位置描述
targetSource?: "model" | "reference" | "global";
suggestion: {
goal: string;
actions: string[];
preserve: string[];
expectedEffect: string;
};
editPrompt?: string; // AI Prompt Writer 生成的局部编辑提示词
sourceCandidateIds?: string[];
groundingConfidence?: number;
verification?: {
verdict: "confirmed" | "uncertain" | "rejected";
confidence: number;
reason: string;
};
};
type CritiqueOption = {
id: string;
category: "composition" | "color" | "lighting" | "proportion" | "other";
title: string;
explanation: string;
confidence: number;
suggestion: CritiqueIssue["suggestion"];
sourceCandidateIds?: string[];
};
```
这里要把两个概念分开:
- `severity` 是问题有多严重。
- `confidence` 是模型有多确定。
不能用一个总分代替这两个字段。第一版也不把“审美分数”作为核心功能,避免用户把模型的主观判断误认为客观评分。
### 4.3 标注图不是第二张原图
报告里的 `target` 只描述“问题大概在哪里”。前端根据这些坐标生成 SVG overlay,叠加到原图预览上:
- 原图像素不被改写。
- 标注可以开关、筛选和重新布局。
- SVG 可以根据窗口尺寸重新绘制。
- 报告变更时,标注可以重新生成。
如果用户点击“导出标注图”,才把原图和 SVG 合成为新的图片资源。这个动作应当是显式的,不能把查看报告自动变成生成图片。
### 4.4 第一版不默认输出修正版图片
“按建议生成修正版”属于下一阶段的图像编辑动作,需要用户确认并消耗图片生成额度。当前问题详情已提供“复制提示词”,内容由独立 AI Prompt Writer 根据问题和定位区域生成;生成中或生成失败时不使用本地拼接替代。未来可以继续扩展为三种显式出口:
1. 复制修改提示词,粘贴到现有的图片生成/编辑流程。
2. 导出标注图,创建一个新的图片资源或图片节点。
3. 按建议生成修正版,进入现有图片生成/编辑流程。
这些出口都不能覆盖输入原图。
## 5. 处理流程
当前实现采用“场景路由与四个窄 Reviewer 并行 + 保守聚合 + 报告初稿提前展示”的流程。场景路由只用于后续本地过滤和聚合;初稿只展示文字问题与建议,Grounding 和 Verification 完成后才显示最终矩形框。每个阶段都可以独立失败并降级继续,且不会为了凑数量制造问题:
### 阶段 A:场景路由
使用现有多模态文本模型能力,把图片作为 `image_url` 内容传入,只判断:
- 图片类型、主体、视觉重点、可能的创作意图和空间深度。
- 不输出问题,不输出批改候选。
### 阶段 B:分维度 Reviewer
场景路由与四个 Reviewer 同时启动;Reviewer 先依据原图和默认场景上下文工作,场景结果返回后再由本地过滤不适用的候选。四个 Reviewer 使用各自的 Rubric 子集:
- Composition / Narrative:主体位置、视觉平衡、留白、动线、裁切和景深。
- Color / Palette:主辅色、冷暖、明度、饱和度和色彩分离。
- Lighting / Exposure:光源方向、曝光、局部对比、体积和主体光线分离。
- Structure / Anatomy / Geometry:人物比例、物体尺寸、透视、遮挡和细节一致性;先并行检查,再依据场景类型、规则适用性和可见证据过滤候选。
每个 Reviewer 只返回有证据的候选,允许返回空数组;候选必须明确区分 `issue`(确实值得修改的问题)和 `option`(可选的风格方向)。
### 阶段 C:聚合和建议
Aggregator 只能引用真实候选,负责去重、合并和排序,最多保留 5 个 `issue` 和 4 个 `option`。本地还会按来源和同根因关键词再做一次保守合并,避免“脸部受光不足”和“主体分离不足”这类重复问题同时占据名额。它不能凭空新增一个 Reviewer 没有支持的问题。每个 `issue` 生成:
- 为什么这是问题。
- 建议用户先做什么。
- 哪些优点应该保留。
- 修改后预期会有什么变化。
`option` 不使用错误语气,也不计入问题数量。
### 阶段 D:位置校准
单独让 Grounding Reviewer 检查问题位置是否与图片内容匹配。连续的一块局部区域优先使用 `box`,单一离散位置使用 `point`,分散在多个位置的问题才使用多个 `points`。本地会拒绝零宽或零高的退化框,并根据问题描述改用带“参考区域”标记的矩形或参考点。如果定位服务不可用,先根据问题描述中的方位和对象词映射到固定的原图参考区域;没有足够线索时才降级为 `global`,不把参考坐标伪装成精确检测框。
### 阶段 E:独立复核
让没有参与前面判断的 fresh reviewer 查看全图和问题区域,返回 `confirmed`、`uncertain` 或 `rejected`。高置信度的 `rejected` 问题会从最终报告中过滤,复核失败则保留聚合结果并显示降级说明。
### 阶段 F:AI 修改提示词
Grounding 完成后,独立 Prompt Writer 与 Verification 并行,为每个已有问题生成 `editPrompt`。它只把最终问题、定位区域、修改建议和必须保留的内容转成可直接粘贴到图片编辑模型的提示词,不重新判断审美、不新增问题、不生成坐标。提示词生成完成后,详情页才允许复制;该阶段失败时保留问题和标注,但明确提示需要重新批改。
### 阶段 G:本地绘制
前端根据校验后的结构化数据绘制 SVG。`box` 使用矩形框,`point` / `points` 使用关键点,`polygon` 使用不规则边界;历史报告中的退化目标也会在显示时修复。碰撞处理、标签偏移、颜色和箭头位置由程序完成,不依赖模型返回 SVG 字符串。
### 调用次数
当前管线最多进行 9 次模型调用:1 次场景路由、4 次窄 Reviewer、1 次聚合、1 次定位、1 次复核和 1 次 AI 修改提示词生成。其中场景路由与四个 Reviewer 组成第一轮并行请求;Grounding 完成后,Verification 与 Prompt Writer 并行请求。聚合结束后先展示不带矩形框的报告初稿,定位与后续并行阶段完成后再替换为最终报告。如果没有候选,聚合、定位、复核和提示词生成会跳过。阶段调用共享同一个取消信号;任一 Reviewer、定位、复核或提示词生成失败时会保留已有结果并在报告中记录降级原因。
### 当前审美 Rubric
当前实现先把参考项目落成一套版本化的内部标准,而不是部署这些项目的模型或数据集:
- 构图参考 CADB / SAMP-Net、CG-IAA 和 PhotoFramer,检查主体位置、视觉平衡、留白、视觉动线、构图模式、裁切和景深。
- 色彩和光线参考 CG-IAA、AesExpert,检查色彩关系、冷暖、明度、饱和度、光源方向、曝光、体积和主体分离。
- 人物与结构参考 HumanAesExpert,并结合 PhotoFramer 的构图判断,检查人物比例、物体相对尺寸、透视、遮挡和细节一致性。
- 修改建议参考 PhotoFramer 的 shift、zoom/crop、view change 思路;问题定位参考 Grounding-IQA,无法可靠定位时使用 `global`。
Rubric 会先要求模型判断画面意图,再应用规则。例如,居中构图或非三分构图本身不是错误,只有当它与画面意图冲突并造成可解释的表达问题时才应被报告。每次生成的报告会记录 Rubric 版本,方便后续比较规则变化带来的结果差异。
当前 MVP 已使用分阶段结构化多模态调用完成“场景路由 → 四路并行批改 → 保守聚合 → 定位 →(复核 || AI 修改提示词)”,本地负责校验 JSON、规则适用性、候选来源、置信度、坐标、优先级和降级逻辑;定位服务不可用时使用参考区域坐标,并用 SVG 绘制标注。复制动作只读取报告中 AI 返回的 `editPrompt`。
## 6. 画布节点形态
节点建议名称为“AI 审美批改”,内部 ID 使用稳定的小写标识,例如 `ai-art-critique`。
### 节点图标语义
节点使用 `ScanSearch`(扫描并查找视觉问题的 Lucide 图标),不再使用通用的 AI 闪光图标。它表达的是“读取图片、扫描画面并定位问题”,而不是“生成图片”或“自动修改图片”。同一图标在以下三个位置保持一致:
- 节点外层标题栏,帮助用户在画布上快速识别分析节点。
- 添加节点菜单,避免插件入口仍显示为通用插件图标。
- 节点卡片内部,和输入图片、报告摘要放在同一视觉语义下。
图标由宿主前端静态渲染,使用现有主题色和节点尺寸;它不由模型返回,也不承担问题坐标、矩形框或 SVG 标注的生成。问题标注仍只来自结构化报告中的定位数据,并由前端绘制。
### 节点状态
- 未连接图片:提示“请连接图片”。
- 已连接未运行:显示图片缩略图和“开始批改”。
- 分析中:显示阶段和取消入口。
- 已完成:显示问题数量或可选方向数量、最近分析时间和“查看报告”;没有可靠问题时明确显示干净状态。
- 输入已变化:显示“报告已过期,需要重新分析”。
- 失败:显示可读错误和“重试”。
### 报告面板
打开节点后使用“图片 + 报告”的双栏结构:
- 左侧:原图、标注开关、问题类别筛选。
- 右侧:总结、优点、重点问题、可选方向、严重程度和修改建议。
- 点击问题列表中的一项,左侧聚焦对应标注。
- 低置信度问题要明确显示“AI 不太确定”,不能和高置信度问题使用完全相同的视觉权重。
建议默认显示“原图 / 批改标注”切换,不直接修改原图。面板关闭后,节点只保留摘要和状态,避免占满画布。
## 7. 插件边界和当前项目的适配
### 7.1 为什么先做内置插件
当前通用插件节点主要适合声明式节点。AI 审美批改需要:
- 读取连接的图片并处理资源引用。
- 运行多阶段模型调用。
- 保存和恢复报告状态。
- 打开带 SVG 标注和交互问题列表的面板。
所以第一版应采用类似肖像权排查插件的受信任内置实现,由宿主明确挂载节点和面板。不要把一段远程 React 代码直接注入主应用。
### 7.2 建议的插件权限
概念上需要以下权限:
- `canvas.read`:读取当前节点和输入连接。
- `canvas.write`:保存报告状态、创建后续节点或导出资源时使用。
- `media.read`:读取输入图片内容。
- `ai.text`:调用现有多模态文本模型。
第一版只申请实际使用的权限。导出图片和创建后续节点可以放到后续版本,再增加对应写入能力。
### 7.3 需要补强的通用协议
当前画布插件节点协议对“输入类型”和“是否有输出端口”的表达还不够明确。为了支持这个分析节点,建议增加两个可选声明:
```ts
type PluginCanvasNodeContribution = {
// 现有字段略
acceptsInputKind?: "image" | "video" | "audio" | "text";
showOutputConnection?: boolean;
};
```
`ai-art-critique` 设置 `acceptsInputKind: "image"`,第一版设置 `showOutputConnection: false`。这样用户能看出它只能接图片,而且不会误以为它默认产出另一张图片。
如果暂时不扩展通用协议,也可以先像现有受信任内置节点一样做定向接入,但不建议长期依赖越来越多的节点类型硬编码。
## 8. 数据保存和过期判断
节点的 `pluginData` 保存当前可恢复状态,建议包含:
```ts
type ArtCritiqueNodeState = {
schemaVersion: 1;
status: "idle" | "running" | "completed" | "failed" | "stale";
analysisStage?:
| "preparing"
| "scene"
| "reviewing"
| "aggregating"
| "grounding"
| "verifying"
| "annotating"
| "completed"
| "failed";
sourceFingerprint?: string;
report?: CritiqueReport;
lastRunId?: string;
errorCode?: string;
};
```
保存原则:
- 节点保存当前报告和必要摘要,保证刷新后仍能查看。
- 历史报告放到带用户 scope 的插件存储中,不把无限历史塞进画布节点。
- 不保存图片二进制,不保存 API Key,不保存带敏感信息的临时 URL。
- 原始模型响应只在调试需要时短暂保留,默认不落盘。
- 输入图片指纹变化后,旧报告标记为 `stale`,不能静默当成最新结果。
## 9. 建议的代码落点
以下是预计的实现拆分,实际文件名可以随现有代码演进调整:
```text
web/src/lib/plugins/builtin/ai-art-critique.ts
内置插件清单、节点注册和能力入口
web/src/lib/art-critique/contracts.ts
报告、问题、坐标和节点状态类型
web/src/lib/art-critique/review.ts
批改入口、单阶段结构化解析和管线适配
web/src/lib/art-critique/pipeline.ts
Scene / Reviewer / Aggregator / Grounding / Verification 多阶段编排
web/src/lib/art-critique/annotation.ts
坐标转换、SVG 标注和标签碰撞处理
web/src/components/canvas/nodes/ai-art-critique-node.tsx
画布节点外观和状态展示
web/src/components/canvas/art-critique/ai-art-critique-modal.tsx
图片预览、SVG overlay、问题列表和操作按钮
web/src/pages/canvas/project.tsx
弹窗挂载、输入连接解析、运行状态和报告保存
```
预计需要接入的现有位置包括:
- 内置插件索引。
- 画布节点内容分发和节点操作。
- 图片节点的快捷操作或连接入口。
- 画布项目页中的节点状态协调。
- 插件宿主的媒体读取适配。
- 现有 AI 请求和资源存储服务。
模型请求应继续走现有渠道中转和模型协议适配,不在节点组件里新增一套 `fetch` 或直接拼装第三方密钥。
## 10. MVP 范围
### 必须有
- 一张图片作为输入。
- 场景理解、分维度 Reviewer、聚合、独立定位和独立复核。
- 构图、色彩、光线、比例四类基础问题。
- 0~5 个重点问题(5 是上限,不是目标);可选风格方向单独展示。
- 结构化报告、优点、修改建议和 AI 生成的局部编辑提示词。
- 问题位置的 SVG 标注。
- 报告保存、刷新恢复和输入变化后的过期提示。
- 失败、取消和重试状态。
### 暂不做
- 自动修改输入图。
- 默认生成修正版图片。
- 把审美判断压缩成一个总分。
- 无限 reviewer 或复杂后台编排。
- 一开始就接入新的任务队列、SSE 或数据库表。
- 把它做成可上传的任意第三方 React 插件。
- 把 Codex MCP 插件当成画布节点的核心实现。
## 11. 分阶段实现
### P0:合同和节点壳
先确定 `CritiqueReport`、坐标规范、节点状态、过期规则和权限;让节点能正确显示输入、空态和错误态。
### P1:可用的批改闭环
接入现有多模态模型能力,完成场景路由、四路并行 Reviewer、保守聚合、结构化校验、报告保存、独立复核和 SVG 标注。此阶段完成后,用户可以真正完成“图片 -> 批改报告”。
### P2:可靠性和体验
补充历史报告、局部重跑、低置信度处理、取消请求、耗时较长时的任务化执行和更完整的观测信息。
### P3:后续动作
继续加入“导出标注图”“按建议生成修正版”和重新分析对比。当前的“复制提示词”以及未来新增的动作都只创建新结果或复制文本,不覆盖输入。
## 12. 验收标准
一个用户拿到图片后,应该能在不阅读实现细节的情况下回答:
1. 这张图整体有什么优点?
2. 有没有需要优先修改的问题?如果有,最多是哪 5 个?
3. 每个问题在图上的大概位置在哪里?
4. 为什么这是问题?
5. 我下一步可以怎么改?
工程上还要满足:
- 无图片时不发起模型调用。
- 模型返回非法结构时不会把原始响应直接渲染到 UI。
- 坐标始终限制在 0..1 范围,越界值要校验或裁剪;矩形还要满足最小宽高,退化坐标改用参考区域。
- 原图不会因查看报告而被修改。
- 刷新页面后,已完成报告仍可恢复。
- 输入图片发生变化时,旧报告不会继续显示为最新。
- 报告失败时保留可读错误,不吞掉底层失败原因。
## 13. 关键风险
- 模型的视觉能力和审美判断有主观性,因此需要同时展示解释和置信度。
- 模型定位可能不准,位置校准失败时优先使用带明确提示的参考区域;没有位置线索时才降级为全局建议或不显示局部标注。
- 模型可能把同一根因拆成多个问题;聚合后会按来源和语义主题做保守合并,避免重复占用问题名额。
- 图片中的文字可能包含提示注入内容,必须把图片文字当作被分析的内容,而不是系统指令。
- 多模态请求可能消耗较多额度,节点状态和重试策略必须清楚。
- 标注图是派生视图,不应和原图混用资源 ID,也不应覆盖用户素材。
## 14. 最终产品定义
可以用一句话固定这个插件的边界:
> 输入是图片,核心输出是结构化批改报告;标注图是报告的展示层,修正版图片是用户确认后的后续动作。
这个定义能让节点的连接关系、数据结构、UI 和后续的生成能力保持一致,也能避免用户把“分析节点”误解成“图片生成节点”。