Files
suixinkan_uikit/docs/AI重新修图接口优化需求.md
T

8.8 KiB
Raw Permalink Blame History

AI 重新修图接口优化需求

1. 背景

图片预览页面支持用户在“原图”Tab 上重新选择修图模板。

用户可能只生成过一种关联图片,例如之前仅生成了“原图精修”,尚未生成“氛围感”图片。此时用户重新修图时,可以同时选择:

  • 原图精修模板
  • 氛围感修图模板

客户端会调用现有 ai-reretouch 接口,并通过 type = 3 提交两个模板,希望一次创建两个修图输出任务。

2. 问题复现

前置状态

  • 原图素材 ID:702
  • 原 AI 修图批次 ID:61
  • 已存在并完成:原图精修
  • 从未生成:氛围感图片

请求

POST /api/yf-handset-app/photog/travel-album/ai-reretouch
{
  "ai_retouch_batch_id": 61,
  "id": 702,
  "type": 3,
  "refined_template_id": 2,
  "atmosphere_template_id": 14
}

字段含义:

字段 值 说明
ai_retouch_batch_id 61 原 AI 修图批次 ID
id 702 原图素材 ID
type 3 同时处理精修和氛围感
refined_template_id 2 本次选择的精修模板
atmosphere_template_id 14 本次选择的氛围感模板

当前响应

{
  "code": 100099,
  "data": [],
  "msg": "仅已完成修图的照片可重新修图",
  "time": "2026-08-14 17:41:17"
}

3. 当前问题

从响应判断,后端可能在 type = 3 时要求精修图和氛围感图都已经存在且完成,才允许重新修图。

但本场景中:

  • 精修图已经存在,本次需要重新生成,并在成功后覆盖旧精修图。
  • 氛围感图从未生成,本次需要创建新的关联图片。

由于氛围感图历史上不存在,接口拒绝了整个请求,导致客户端无法通过一次请求同时完成“覆盖已有精修图”和“新增氛围感图”。

客户端当前请求已经正确传递 type = 3 和两个模板 ID,无需修改请求结构。

4. 期望接口行为

建议将 ai-reretouch 调整为按输出类型分别执行的 upsert(存在则覆盖,不存在则新增) 语义。

对于本次请求:

原图精修

  • 请求传入了 refined_template_id。
  • 旧精修图已经存在。
  • 后端创建新的精修任务。
  • 新任务成功后覆盖旧精修图。
  • 新任务处理中或失败时保留旧精修图。

氛围感修图

  • 请求传入了 atmosphere_template_id。
  • 旧氛围感图不存在。
  • 后端创建新的氛围感任务。
  • 任务成功后,将结果保存为原图的新关联图片。

整体任务

  • 一次请求创建两个输出任务:refined 和 atmosphere。
  • 按两个实际创建的输出预占 2 张修图额度。
  • 两个输出分别执行、分别记录状态、分别结算额度。
  • 单个输出失败不应影响另一个已经成功的输出。

5. 建议的后端处理规则

5.1 基础校验

建议校验:

  • 原图素材存在。
  • 原图素材属于指定相册或批次。
  • 原图当前状态允许提交 AI 修图任务。
  • 请求中至少传入一个与 type 匹配的有效模板 ID。
  • 用户剩余额度满足本次实际创建的输出数量。

不建议校验:

  • type = 3 时要求精修和氛围感历史结果都必须存在。
  • 某一种关联图从未生成时直接拒绝整个请求。

5.2 按模板字段创建任务

后端根据本次实际传入的模板字段创建对应任务:

请求情况 期望处理
只传 refined_template_id 只创建精修任务
只传 atmosphere_template_id 只创建氛围感任务
两个模板 ID 都传 同时创建精修和氛围感任务
某个模板 ID 未传 不处理、不覆盖该类型的已有结果

5.3 按输出类型处理已有结果

对于每个实际提交的输出类型,分别判断:

历史状态 建议处理
已存在成功结果 创建重修任务,新结果成功后替换旧结果
从未生成 创建新任务,成功后新增关联图片
历史任务失败或已取消 允许重新创建任务
当前已有处理中或排队任务 拒绝该类型重复提交,或通过幂等机制复用已有任务

5.4 替换时机

继续采用现有 replace_on_success 语义:

  • 新结果成功后,才替换同类型旧结果。
  • 新任务排队、处理中或失败时,保留旧结果。
  • 精修和氛围感分别替换,互不影响。

6. type 参数建议语义

保持现有请求类型和接口路径不变:

type 语义 模板规则
1 只处理精修 必须传 refined_template_id,忽略氛围感模板
2 只处理氛围感 必须传 atmosphere_template_id,忽略精修模板
3 同时处理精修和氛围感 根据实际传入的两个模板分别创建任务

对于 type = 3:

  • 必须传 refined_template_id。
  • atmosphere_template_id 可以选传。
  • 传入氛围感模板时创建氛围感任务。
  • 未传氛围感模板时,只重修精修图,并保留已有氛围感图。

7. 建议处理伪代码

validateOriginalMaterial(request.id)
validateBatch(request.ai_retouch_batch_id)

outputs = []

if request.refined_template_id is not null:
    outputs.add(
        createTask(
            outputType = refined,
            templateId = request.refined_template_id,
            mode = existingRefinedResult ? replace_on_success : create
        )
    )

if request.atmosphere_template_id is not null:
    outputs.add(
        createTask(
            outputType = atmosphere,
            templateId = request.atmosphere_template_id,
            mode = existingAtmosphereResult ? replace_on_success : create
        )
    )

if outputs is empty:
    return invalid_template_error

reserveQuota(outputs.count)
submitTasks(outputs)

注意:实际是否存在旧结果,应按照各自的 output_type 独立查询,不能用“两个类型都已完成”作为 type = 3 的整体前置条件。

8. 期望响应

接口成功响应建议继续返回任务批次信息,并明确本次创建的输出类型。例如:

{
  "code": 100000,
  "data": {
    "ai_retouch_batch_id": 61,
    "source_material_id": 702,
    "outputs": [
      {
        "type": "refined",
        "mode": "replace_on_success",
        "status": "queued"
      },
      {
        "type": "atmosphere",
        "mode": "create",
        "status": "queued"
      }
    ],
    "reserved_units": 2
  },
  "msg": "AI修图任务已提交"
}

响应结构可沿用现有实现,不强制增加上述字段;关键要求是一次请求能够成功创建两个对应的修图任务。

9. 验收用例

用例一:只有旧精修图,同时提交两个模板

  • 历史状态:精修已完成,氛围感不存在。
  • 请求:type = 3,同时传精修和氛围感模板。
  • 期望:创建两个任务;精修成功后覆盖,氛围感成功后新增。

用例二:只有旧氛围感图,同时提交两个模板

  • 历史状态:精修不存在,氛围感已完成。
  • 请求:type = 3,同时传精修和氛围感模板。
  • 期望:创建两个任务;精修成功后新增,氛围感成功后覆盖。

用例三:两种旧结果都存在

  • 历史状态:精修、氛围感都已完成。
  • 请求:type = 3,同时传两个模板。
  • 期望:创建两个任务,分别在成功后覆盖各自旧结果。

用例四:原图 Tab 只选择精修模板

  • 历史状态:精修、氛围感均可能存在。
  • 请求:type = 3,只传 refined_template_id。
  • 期望:只创建精修任务;不处理、不删除、不覆盖旧氛围感图;预占 1 张额度。

用例五:精修后 Tab 重新修图

  • 请求:type = 1,只传 refined_template_id。
  • 期望:只创建精修任务,新精修成功后覆盖旧精修图。

用例六:氛围感 Tab 重新修图

  • 请求:type = 2,只传 atmosphere_template_id。
  • 期望:只创建氛围感任务,新氛围感成功后覆盖旧氛围感图。

用例七:其中一个输出失败

  • 请求创建精修和氛围感两个任务。
  • 精修成功,氛围感失败。
  • 期望:保留成功的新精修结果;氛围感旧图存在时继续保留旧图,不存在时不生成关联图;额度分别结算。

用例八:防止重复提交

  • 同一原图、同一输出类型已经存在排队中或处理中的任务。
  • 用户再次提交相同任务。
  • 期望:通过幂等机制返回原任务,或仅拒绝重复的输出类型,避免重复扣减额度和重复生成结果。

10. 总结

希望 ai-reretouch 支持以下统一语义:

对本次传入模板对应的每种输出独立处理:已有结果则在新任务成功后覆盖,没有结果则新增;未传模板的类型不处理。不要因为某一种关联图历史上从未生成,就拒绝整个重新修图请求。