4 changed files with 322 additions and 11 deletions
@ -0,0 +1,279 @@ |
|||||
|
# createGenTaskPayload 梳理 |
||||
|
|
||||
|
本文只说明 `src/layouts/globalPromptPanel/globalPromptPanel.tsx` 里的 `createGenTaskPayload`。 |
||||
|
它是创建任务接口 `createGenTask()` 的请求体。 |
||||
|
它也会传给 `useGenerateCost()`,作为普通任务价格计算的同源参数。 |
||||
|
|
||||
|
## 1. 它解决什么问题 |
||||
|
|
||||
|
`createGenTaskPayload` 把创作面板当前状态整理成后端需要的任务参数。 |
||||
|
|
||||
|
它主要合并 4 类数据: |
||||
|
|
||||
|
- 当前任务类型:`activeTaskSubType` |
||||
|
- 当前模型:`activeModelItem` |
||||
|
- 当前参数:`modelParamFields` 和 `selectedParamValues` |
||||
|
- 当前输入内容:`chatPrompt`、上传媒体、音色、动作模仿示例、参考主体 |
||||
|
|
||||
|
最终结果会用于两个地方: |
||||
|
|
||||
|
- `useGenerateCost({ taskPayload: createGenTaskPayload })` |
||||
|
- `createGenTask(createGenTaskPayload)` |
||||
|
|
||||
|
## 2. 整体流程 |
||||
|
|
||||
|
```txt |
||||
|
mediaItems |
||||
|
└─ splitUploadMediaItems() |
||||
|
├─ uploadImages |
||||
|
├─ uploadVideos |
||||
|
└─ uploadVoice |
||||
|
|
||||
|
activeModelItem + activeTaskSubType + modelParamFields + selectedParamValues |
||||
|
└─ buildComposerTaskSubmitPayload() |
||||
|
├─ subType |
||||
|
├─ type |
||||
|
├─ 模型字段 |
||||
|
├─ 普通参数 |
||||
|
└─ extraTaskParams |
||||
|
|
||||
|
createGenTaskPayload |
||||
|
├─ 基础任务参数 |
||||
|
├─ chatPrompt |
||||
|
├─ images / videos / voices |
||||
|
├─ voiceId |
||||
|
├─ templateVideoMaterialId |
||||
|
└─ referenceSubjectList |
||||
|
``` |
||||
|
|
||||
|
## 3. 基础任务参数从哪里来 |
||||
|
|
||||
|
基础参数来自 `buildComposerTaskSubmitPayload()`。 |
||||
|
|
||||
|
这个函数会返回: |
||||
|
|
||||
|
- `subType`:当前任务子类型 |
||||
|
- `type`:任务大类。当前代码里 `1` 是图片类,`2` 是视频类,`3` 是音频类 |
||||
|
- 模型字段:来自 `buildGenTaskModelPayload(activeModelItem)` |
||||
|
- 普通参数:来自模型参数和固定参数 |
||||
|
- `extraTaskParams`:滑块参数,比如 `speed / vol / pitch` |
||||
|
|
||||
|
### 3.1 模型字段 |
||||
|
|
||||
|
`buildGenTaskModelPayload()` 会把同一个模型信息写成多个字段。 |
||||
|
这是后端接口约定,不是前端重复写错。 |
||||
|
|
||||
|
当前会写入: |
||||
|
|
||||
|
- `aiModelName` |
||||
|
- `aiPlatform` |
||||
|
- `aiModelId` |
||||
|
- `model` |
||||
|
- `aiModelCode` |
||||
|
- `aiModelCodeAlias` |
||||
|
|
||||
|
其中 `aiPlatform`、`model`、`aiModelCode` 都来自 `activeModelItem.code`。 |
||||
|
|
||||
|
### 3.2 参数字段 |
||||
|
|
||||
|
参数字段来自 `buildComposerTaskParamPayload()`。 |
||||
|
|
||||
|
它会做这些事: |
||||
|
|
||||
|
- 用 `buildPreferredParamValues()` 给缺失参数补默认值 |
||||
|
- 找到比例字段,比如 `ratio` |
||||
|
- 找到分辨率字段,比如 `resolution` |
||||
|
- 根据比例和分辨率推导 `width / height` |
||||
|
- 保证请求体里有接口约定的 `ratio` 字段 |
||||
|
|
||||
|
### 3.3 滑块参数 |
||||
|
|
||||
|
`splitRangeParamsForTaskSubmit()` 会把滑块参数从顶层移到 `extraTaskParams`。 |
||||
|
|
||||
|
例子: |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"resolution": "2K", |
||||
|
"ratio": "9:16", |
||||
|
"extraTaskParams": { |
||||
|
"speed": 1, |
||||
|
"vol": 0.8, |
||||
|
"pitch": 0 |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
这样做是为了让普通参数留在顶层,同时让 `speed / vol / pitch` 这类范围值走 `extraTaskParams`。 |
||||
|
|
||||
|
## 4. 媒体字段怎么来 |
||||
|
|
||||
|
上传媒体来自 `splitUploadMediaItems(mediaItems, composerUploadLimits)`。 |
||||
|
|
||||
|
它会按类型拆成三列: |
||||
|
|
||||
|
- 图片:`uploadImages`,最后写入 `images` |
||||
|
- 视频:`uploadVideos`,最后写入 `videos` |
||||
|
- 音频:`uploadVoice`,最后写入 `voices` |
||||
|
|
||||
|
它也会按模型上传上限截断对应类型。 |
||||
|
例如模型最多只收 1 个视频时,后面的上传视频不会进入请求体。 |
||||
|
|
||||
|
空数组不会提交。 |
||||
|
所以代码最后会删除这些空字段: |
||||
|
|
||||
|
- `images` |
||||
|
- `videos` |
||||
|
- `voices` |
||||
|
|
||||
|
## 5. 不同任务的额外处理 |
||||
|
|
||||
|
`createGenTaskPayload` 在基础参数之外,会按任务类型补几个字段。 |
||||
|
|
||||
|
### 5.1 通用任务 |
||||
|
|
||||
|
所有任务都会写入: |
||||
|
|
||||
|
- `chatPrompt: chatPrompt.trim()` |
||||
|
- `images` |
||||
|
- `videos` |
||||
|
- `voices` |
||||
|
|
||||
|
如果 `chatPrompt` 为空,创建任务前会有校验。 |
||||
|
动作模仿任务例外,因为它可以只依赖动作示例。 |
||||
|
|
||||
|
### 5.2 文本转语音任务 |
||||
|
|
||||
|
当 `isVoiceTask` 为 `true` 时,会写入: |
||||
|
|
||||
|
- `voiceId` |
||||
|
|
||||
|
取值优先级是: |
||||
|
|
||||
|
```txt |
||||
|
selectedVoiceItem?.voiceId > voiceId |
||||
|
``` |
||||
|
|
||||
|
如果最终值为空,代码会删除 `voiceId`。 |
||||
|
创建任务前也会再校验一次,确保文本转语音必须有音色。 |
||||
|
|
||||
|
### 5.3 动作模仿任务 |
||||
|
|
||||
|
当 `isActionMimicTask` 为 `true` 时,`videos` 会特殊处理。 |
||||
|
|
||||
|
如果用户选了动作模仿示例,代码会把示例视频放到 `videos` 第一位: |
||||
|
|
||||
|
```txt |
||||
|
[selectedActionMimicItem.url, ...uploadMediaPayload.uploadVideos] |
||||
|
``` |
||||
|
|
||||
|
如果选中的是官方示例,还会写入: |
||||
|
|
||||
|
- `templateVideoMaterialId` |
||||
|
|
||||
|
它来自 `selectedActionMimicItem.id`。 |
||||
|
如果不是官方示例,这个字段会被删除。 |
||||
|
|
||||
|
### 5.4 参考生视频任务 |
||||
|
|
||||
|
当 `isReferenceTask` 为 `true` 时,会写入: |
||||
|
|
||||
|
- `referenceSubjectList` |
||||
|
|
||||
|
这个字段来自 `referenceStructure.referenceSubjectList`。 |
||||
|
它保存参考主体列表,不只是普通上传图片。 |
||||
|
|
||||
|
## 6. 当前请求体大概长什么样 |
||||
|
|
||||
|
一个普通图像或视频任务的请求体大概是: |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"subType": 102, |
||||
|
"type": 1, |
||||
|
"aiModelName": "模型名", |
||||
|
"aiPlatform": "模型 code", |
||||
|
"aiModelId": 123, |
||||
|
"model": "模型 code", |
||||
|
"aiModelCode": "模型 code", |
||||
|
"aiModelCodeAlias": "别名", |
||||
|
"resolution": "2K", |
||||
|
"ratio": "9:16", |
||||
|
"width": 720, |
||||
|
"height": 1280, |
||||
|
"batchSize": 1, |
||||
|
"chatPrompt": "用户输入的提示词", |
||||
|
"images": ["https://example.com/a.png"], |
||||
|
"videos": ["https://example.com/a.mp4"], |
||||
|
"voices": ["https://example.com/a.mp3"], |
||||
|
"extraTaskParams": { |
||||
|
"speed": 1 |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
实际字段会根据任务类型、模型参数、上传内容变化。 |
||||
|
空的 `images / videos / voices` 不会出现在最终请求体里。 |
||||
|
|
||||
|
## 7. 创建任务前还有哪些校验 |
||||
|
|
||||
|
`createGenTaskPayload` 只负责组装请求体。 |
||||
|
它不负责全部业务校验。 |
||||
|
|
||||
|
点击创建任务时,`handleCreateGenTaskClick()` 还会检查: |
||||
|
|
||||
|
- 非动作模仿任务必须有提示词 |
||||
|
- 当前任务是否满足最少上传数量 |
||||
|
- 音频素材不能单独提交,必须搭配图片或视频 |
||||
|
- 动作模仿任务必须选择示例 |
||||
|
- 文本转语音任务必须选择音色 |
||||
|
- 用户积分是否足够 |
||||
|
|
||||
|
这些校验通过后,才会调用: |
||||
|
|
||||
|
```ts |
||||
|
await createGenTask(createGenTaskPayload); |
||||
|
``` |
||||
|
|
||||
|
## 8. 阅读这段代码时的顺序 |
||||
|
|
||||
|
建议按这个顺序看: |
||||
|
|
||||
|
1. 先看 `createGenTaskPayload` 本体,知道最终字段有哪些。 |
||||
|
2. 再看 `buildComposerTaskSubmitPayload()`,理解模型和参数怎么进请求体。 |
||||
|
3. 再看 `buildComposerTaskParamPayload()`,理解默认参数、比例、分辨率、尺寸。 |
||||
|
4. 再看 `splitRangeParamsForTaskSubmit()`,理解滑块参数为什么进 `extraTaskParams`。 |
||||
|
5. 最后看 `handleCreateGenTaskClick()`,理解请求体提交前的校验。 |
||||
|
|
||||
|
## 9. 为什么现在看起来杂乱 |
||||
|
|
||||
|
这段逻辑承担了两个职责: |
||||
|
|
||||
|
- 生成创建任务的请求体 |
||||
|
- 给价格计算提供同一份任务参数 |
||||
|
|
||||
|
同时它还要兼容多种任务类型。 |
||||
|
所以它会同时碰到模型、参数、媒体、音色、动作示例、参考主体。 |
||||
|
|
||||
|
如果后续要继续整理,可以把它拆成一个纯函数,例如: |
||||
|
|
||||
|
```ts |
||||
|
buildCreateGenTaskPayload({ |
||||
|
activeTaskSubType, |
||||
|
activeModelItem, |
||||
|
modelParamFields, |
||||
|
selectedParamValues, |
||||
|
chatPrompt, |
||||
|
uploadMediaPayload, |
||||
|
selectedVoiceItem, |
||||
|
voiceId, |
||||
|
selectedActionMimicItem, |
||||
|
referenceSubjectList, |
||||
|
isVoiceTask, |
||||
|
isActionMimicTask, |
||||
|
isReferenceTask, |
||||
|
}) |
||||
|
``` |
||||
|
|
||||
|
这样 `globalPromptPanel.tsx` 只负责传状态。 |
||||
|
请求体规则可以放到 `utils.ts` 或单独文件里测试。 |
||||
Loading…
Reference in new issue