diff --git a/src/api/controllers/core.ts b/src/api/controllers/core.ts index 8caece3..0bb99d6 100644 --- a/src/api/controllers/core.ts +++ b/src/api/controllers/core.ts @@ -256,6 +256,7 @@ export async function uploadFile( */ export function checkResult(result: AxiosResponse) { const { ret, errmsg, data } = result.data; + console.log("检查请求结果", { ret, errmsg } ); if (!_.isFinite(Number(ret))) return result.data; if (ret !== '0') { logger.error(`[Jimeng API Error] ret=${ret}, errmsg=${errmsg}, data=${JSON.stringify(data)}`); @@ -295,4 +296,340 @@ export async function getTokenLiveStatus(refreshToken: string) { } catch (err) { return false; } +} + + +export function image3Options( + model, + componentId, + prompt, + sampleStrength, + height, + width, + negativePrompt = '', + resolutionType = "1k", + generateCount = 4 +){ + const min_version = "3.0.2" + const version = "3.0.2" + return { + params: { + babi_param: encodeURIComponent( + JSON.stringify({ + scenario: "image_video_generation", + feature_key: "aigc_to_image", + feature_entrance: "to_image", + feature_entrance_detail: "to_image-" + model, + }) + ), + }, + data: { + extend: { + root_model: model, + template_id: "", + }, + submit_id: util.uuid(), + metrics_extra: JSON.stringify({ + templateId: "", + generateCount: generateCount, + promptSource: "custom", + templateSource: "", + lastRequestId: "", + originRequestId: "", + }), + draft_content: JSON.stringify({ + type: "draft", + id: util.uuid(), + min_version: min_version, + is_from_tsn: true, + version: version, + main_component_id: componentId, + component_list: [ + { + type: "image_base_component", + id: componentId, + min_version: min_version, + generate_type: "generate", + aigc_mode: "workbench", + abilities: { + type: "", + id: util.uuid(), + generate: { + type: "", + id: util.uuid(), + core_param: { + type: "", + id: util.uuid(), + model, + prompt:prompt, + negative_prompt: negativePrompt, + seed: Math.floor(Math.random() * 100000000) + 2500000000, + sample_strength: sampleStrength, + image_ratio: 1, + large_image_info: { + type: "", + id: util.uuid(), + height, + width, + resolution_type: resolutionType, + }, + }, + history_option: { + type: "", + id: util.uuid(), + }, + }, + }, + }, + ], + }), + http_common_info: { + aid: Number(DEFAULT_ASSISTANT_ID), + }, + }, + } +} + + +export function image4Options_0302( + model, + componentId, + prompt, + sampleStrength, + height, + width, + negativePrompt = '', + resolutionType = "2k", + generateCount = 4 +){ + const min_version = "3.0.2" + const version = "3.0.2" + const submit_id = util.uuid() + return { + params: { + babi_param: encodeURIComponent( + JSON.stringify({ + scenario: "image_video_generation", + feature_key: "aigc_to_image", + feature_entrance: "to_image", + feature_entrance_detail: "to_image-" + model, + }) + ), + }, + data: { + extend: { + root_model: model, + }, + submit_id: submit_id, + metrics_extra: JSON.stringify({ + promptSource: "custom", + generateCount: generateCount, + enterFrom: "click", + sceneOptions:JSON.stringify([ + { + "type": "image", + "scene": "ImageBasicGenerate", + "modelReqKey": model, + "resolutionType": resolutionType, + "abilityList": [], + "benefitCount": 4, + "reportParams": { + "enterSource": "generate", + "vipSource": "generate", + "extraVipFunctionKey": model+"-"+resolutionType, + "useVipFunctionDetailsReporterHoc": true + } + } + ]), + isBoxSelect: false, + isCutout: false, + generateId: submit_id, + isRegenerate: false + }), + draft_content: JSON.stringify({ + type: "draft", + id: util.uuid(), + min_version: min_version, + is_from_tsn: true, + version: version, + main_component_id: componentId, + component_list: [ + { + type: "image_base_component", + id: componentId, + min_version: min_version, + generate_type: "generate", + aigc_mode: "workbench", + metadata: { + "type": "", + "id": util.uuid(), + "created_platform": 3, + "created_platform_version": "", + "created_time_in_ms": Math.floor(Date.now()/1000), + "created_did": "" + }, + abilities: { + type: "", + id: util.uuid(), + generate: { + type: "", + id: util.uuid(), + core_param: { + type: "", + id: util.uuid(), + model, + prompt, + negative_prompt: negativePrompt, + seed: Math.floor(Math.random() * 100000000) + 2500000000, + sample_strength: sampleStrength, + image_ratio: 5, + large_image_info: { + type: "", + id: util.uuid(), + height, + width, + resolution_type: resolutionType, + }, + intelligent_ratio: false + }, + }, + gen_option: { + "type": "", + "id": util.uuid(), + "gen_count": generateCount, + "generate_all": false + } + }, + }, + ], + }), + http_common_info: { + aid: Number(DEFAULT_ASSISTANT_ID), + }, + }, + } +} + + +export function image4Options_0337( + model, + componentId, + prompt, + sampleStrength, + height, + width, + negativePrompt = '', + resolutionType = "2k", + generateCount = 4 +){ + const min_version = "3.0.2" + const version = "3.3.7" + const submit_id = util.uuid() + return { + params: { + da_version: version, + web_component_open_flag:1, + web_version:'7.5.0', + aigc_features:'app_lip_sync', + babi_param: encodeURIComponent( + JSON.stringify({ + scenario: "image_video_generation", + feature_key: "aigc_to_image", + feature_entrance: "to_image", + feature_entrance_detail: "to_image-" + model, + }) + ), + }, + data: { + extend: { + root_model: model, + }, + submit_id: submit_id, + metrics_extra: JSON.stringify({ + promptSource: "custom", + generateCount: generateCount, + enterFrom: "click", + sceneOptions:JSON.stringify([ + { + "type": "image", + "scene": "ImageBasicGenerate", + "modelReqKey": model, + "resolutionType": resolutionType, + "abilityList": [], + "benefitCount": 4, + "reportParams": { + "enterSource": "generate", + "vipSource": "generate", + "extraVipFunctionKey": model+"-"+resolutionType, + "useVipFunctionDetailsReporterHoc": true + } + } + ]), + isBoxSelect: false, + isCutout: false, + generateId: submit_id, + isRegenerate: false + }), + draft_content: JSON.stringify({ + type: "draft", + id: util.uuid(), + min_version: min_version, + is_from_tsn: true, + version: version, + main_component_id: componentId, + component_list: [ + { + type: "image_base_component", + id: componentId, + min_version: min_version, + generate_type: "generate", + aigc_mode: "workbench", + metadata: { + "type": "", + "id": util.uuid(), + "created_platform": 3, + "created_platform_version": "", + "created_time_in_ms": Math.floor(Date.now()/1000), + "created_did": "" + }, + abilities: { + type: "", + id: util.uuid(), + generate: { + type: "", + id: util.uuid(), + core_param: { + type: "", + id: util.uuid(), + model, + prompt, + negative_prompt: negativePrompt, + seed: Math.floor(Math.random() * 100000000) + 2500000000, + sample_strength: sampleStrength, + image_ratio: 5, + large_image_info: { + type: "", + id: util.uuid(), + height, + width, + resolution_type: resolutionType, + }, + intelligent_ratio: false + }, + }, + gen_option: { + "type": "", + "id": util.uuid(), + "gen_count": generateCount, + "generate_all": false + } + }, + }, + ], + }), + http_common_info: { + aid: Number(DEFAULT_ASSISTANT_ID), + }, + }, + } } \ No newline at end of file diff --git a/src/api/controllers/images.ts b/src/api/controllers/images.ts index 860cf65..a324dad 100644 --- a/src/api/controllers/images.ts +++ b/src/api/controllers/images.ts @@ -3,7 +3,7 @@ import _ from "lodash"; import APIException from "@/lib/exceptions/APIException.ts"; import EX from "@/api/consts/exceptions.ts"; import util from "@/lib/util.ts"; -import { getCredit, receiveCredit, request } from "./core.ts"; +import { getCredit, receiveCredit, request, image3Options, image4Options_0302 } from "./core.ts"; import logger from "@/lib/logger.ts"; import { ImagesTaskCache } from '@/api/ImagesTaskCache.ts'; @@ -36,11 +36,13 @@ export async function generateImages( height = 1024, sampleStrength = 0.5, negativePrompt = "", + generateCount = 4, }: { width?: number; height?: number; sampleStrength?: number; negativePrompt?: string; + generateCount?: number; }, refreshToken: string ) { @@ -60,86 +62,114 @@ export async function generateImages( await receiveCredit(refreshToken); const componentId = util.uuid(); + let isModel4 = model.startsWith("jimeng-4"); + let options = {}; + if(isModel4){ + options = image4Options_0302( + model, + componentId, + prompt, + sampleStrength, + height, + width, + negativePrompt, + '2k', + generateCount, + ); + }else{ + options = image3Options( + model, + componentId, + prompt, + sampleStrength, + height, + width, + negativePrompt, + '1k', + generateCount, + ); + } const { aigc_data } = await request( "post", "/mweb/v1/aigc_draft/generate", refreshToken, - { - params: { - babi_param: encodeURIComponent( - JSON.stringify({ - scenario: "image_video_generation", - feature_key: "aigc_to_image", - feature_entrance: "to_image", - feature_entrance_detail: "to_image-" + model, - }) - ), - }, - data: { - extend: { - root_model: model, - template_id: "", - }, - submit_id: util.uuid(), - metrics_extra: JSON.stringify({ - templateId: "", - generateCount: 1, - promptSource: "custom", - templateSource: "", - lastRequestId: "", - originRequestId: "", - }), - draft_content: JSON.stringify({ - type: "draft", - id: util.uuid(), - min_version: DRAFT_VERSION, - is_from_tsn: true, - version: currentVersion, - main_component_id: componentId, - component_list: [ - { - type: "image_base_component", - id: componentId, - min_version: DRAFT_VERSION, - generate_type: "generate", - aigc_mode: "workbench", - abilities: { - type: "", - id: util.uuid(), - generate: { - type: "", - id: util.uuid(), - core_param: { - type: "", - id: util.uuid(), - model, - prompt, - negative_prompt: negativePrompt, - seed: Math.floor(Math.random() * 100000000) + 2500000000, - sample_strength: sampleStrength, - image_ratio: 1, - large_image_info: { - type: "", - id: util.uuid(), - height, - width, - resolution_type: resolutionType, - }, - }, - history_option: { - type: "", - id: util.uuid(), - }, - }, - }, - }, - ], - }), - http_common_info: { - aid: Number(DEFAULT_ASSISTANT_ID), - }, - }, - } + options, + // { + // params: { + // babi_param: encodeURIComponent( + // JSON.stringify({ + // scenario: "image_video_generation", + // feature_key: "aigc_to_image", + // feature_entrance: "to_image", + // feature_entrance_detail: "to_image-" + model, + // }) + // ), + // }, + // data: { + // extend: { + // root_model: model, + // template_id: "", + // }, + // submit_id: util.uuid(), + // metrics_extra: JSON.stringify({ + // templateId: "", + // generateCount: 1, + // promptSource: "custom", + // templateSource: "", + // lastRequestId: "", + // originRequestId: "", + // }), + // draft_content: JSON.stringify({ + // type: "draft", + // id: util.uuid(), + // min_version: DRAFT_VERSION, + // is_from_tsn: true, + // version: DRAFT_VERSION, + // main_component_id: componentId, + // component_list: [ + // { + // type: "image_base_component", + // id: componentId, + // min_version: DRAFT_VERSION, + // generate_type: "generate", + // aigc_mode: "workbench", + // abilities: { + // type: "", + // id: util.uuid(), + // generate: { + // type: "", + // id: util.uuid(), + // core_param: { + // type: "", + // id: util.uuid(), + // model, + // prompt, + // negative_prompt: negativePrompt, + // seed: Math.floor(Math.random() * 100000000) + 2500000000, + // sample_strength: sampleStrength, + // image_ratio: 1, + // large_image_info: { + // type: "", + // id: util.uuid(), + // height, + // width, + // resolution_type: "1k", + // }, + // }, + // history_option: { + // type: "", + // id: util.uuid(), + // }, + // }, + // }, + // }, + // ], + // }), + // http_common_info: { + // aid: Number(DEFAULT_ASSISTANT_ID), + // }, + // }, + // } ); const historyId = aigc_data.history_record_id; if (!historyId) diff --git a/src/api/routes/images.ts b/src/api/routes/images.ts index 4988a14..205ec27 100644 --- a/src/api/routes/images.ts +++ b/src/api/routes/images.ts @@ -4,6 +4,7 @@ import Request from "@/lib/request/Request.ts"; import { generateImages } from "@/api/controllers/images.ts"; import { tokenSplit } from "@/api/controllers/core.ts"; import util from "@/lib/util.ts"; +import logger from "@/lib/logger.ts"; import { ImagesTaskCache } from '@/api/ImagesTaskCache.ts'; import DatabaseGenerationService from '@/lib/services/DatabaseGenerationService.js'; @@ -65,9 +66,10 @@ export default { .validate("body.task_id", _.isString) .validate("body.prompt", _.isString) // .validate("body.negative_prompt", v => _.isUndefined(v) || _.isString(v)) - .validate("body.width", v => _.isUndefined(v) || _.isFinite(v) || _.isString(v)) - .validate("body.height", v => _.isUndefined(v) || _.isFinite(v) || _.isString(v)) - // .validate("body.sample_strength", v => _.isUndefined(v) || _.isFinite(v)) + .validate("body.width", v => _.isUndefined(v) || _.isFinite(v)) + .validate("body.height", v => _.isUndefined(v) || _.isFinite(v)) + .validate("body.sample_strength", v => _.isUndefined(v) || _.isFinite(v)) + .validate("body.generate_count", v => _.isUndefined(v) || _.isFinite(v)) .validate("body.response_format", v => _.isUndefined(v) || _.isString(v)) .validate("headers.authorization", _.isString); // refresh_token切分 @@ -81,27 +83,31 @@ export default { // negative_prompt: negativePrompt, width, height, - // sample_strength: sampleStrength, + sample_strength, + generate_count, response_format, } = request.body; const responseFormat = _.defaultTo(response_format, "url"); - + logger.info(`\n发起图片生成: model: ${model}, task_id: ${task_id}, width: ${width}, height: ${height}, responseFormat: ${responseFormat}, sample_strength: ${sample_strength}, generate_count: ${generate_count}`); + if (USE_DATABASE_MODE) { // 使用新的数据库方法 - await DatabaseGenerationService.generateImagesV2(model || 'jimeng-3.0', task_id, prompt, { + await DatabaseGenerationService.generateImagesV2(model||'jimeng-3.0', task_id, prompt, { width, height, - sampleStrength: 0.5, + sampleStrength: sample_strength || 0.5, negativePrompt: "", - response_format: responseFormat + response_format: responseFormat, + generateCount: generate_count || 4, }, token); } else { // 使用原有方法(不等待结果) - generateImages(model || 'jimeng-3.0', task_id, prompt, { + generateImages(model||'jimeng-3.0', task_id, prompt, { width, height, - sampleStrength: 0.5, + sampleStrength: sample_strength || 0.5, negativePrompt: "", + generateCount: generate_count || 4, }, token); } diff --git a/src/lib/database/models/GenerationTask.ts b/src/lib/database/models/GenerationTask.ts index e1295a0..16a0fc2 100644 --- a/src/lib/database/models/GenerationTask.ts +++ b/src/lib/database/models/GenerationTask.ts @@ -23,6 +23,7 @@ export interface IGenerationTask { duration?: number; // 时长(毫秒) ratio?: string; // 比例 response_format?: string; // 响应格式 + generate_count?: number; // 生成数量 }; // 生成过程中的内部参数 diff --git a/src/lib/services/DatabaseGenerationService.ts b/src/lib/services/DatabaseGenerationService.ts index 49ba3cf..e3d28f1 100644 --- a/src/lib/services/DatabaseGenerationService.ts +++ b/src/lib/services/DatabaseGenerationService.ts @@ -45,6 +45,7 @@ export class DatabaseGenerationService { sampleStrength?: number; negativePrompt?: string; response_format?: string; + generateCount?: number; }, refreshToken: string ): Promise { @@ -74,7 +75,8 @@ export class DatabaseGenerationService { height: params.height || 1024, sample_strength: params.sampleStrength || 0.5, negative_prompt: params.negativePrompt || "", - response_format: params.response_format + response_format: params.response_format, + generate_count: params.generateCount || 4, }, internal_params: { refresh_token: refreshToken diff --git a/src/lib/services/TaskPollingService.ts b/src/lib/services/TaskPollingService.ts index 030c414..98ca484 100644 --- a/src/lib/services/TaskPollingService.ts +++ b/src/lib/services/TaskPollingService.ts @@ -8,7 +8,7 @@ import logger from '@/lib/logger.js'; import TOSService from '@/lib/tos/tos-service.js'; import { generateImages as originalGenerateImages } from '@/api/controllers/images.js'; import { generateVideo as originalGenerateVideo } from '@/api/controllers/video.js'; -import { request } from '@/api/controllers/core.js'; +import { request, image4Options_0302, image4Options_0337, image3Options } from '@/api/controllers/core.js'; import EX from "@/api/consts/exceptions.ts"; const timeZone = 'Asia/Shanghai'; @@ -327,6 +327,7 @@ export class TaskPollingService { } taskLog(`Starting task: ${task.task_id} (${task.task_type})`); + // taskLog(`original_params: ${JSON.stringify(task.original_params)}`); // 调用原有生成方法获取historyId let historyId: string; @@ -396,8 +397,9 @@ export class TaskPollingService { } const { status, fail_code: failCode, item_list } = result[historyId]; - - if (status === 20) { + + taskLog(`调用即梦API检查结果 ${task.task_id} [status:${status} fail_code: ${failCode}]`); + if (status === 20 || status === 45) { // 仍在生成中,更新下次轮询时间 await GenerationTask.updateOne( { task_id: task.task_id }, @@ -766,7 +768,8 @@ export class TaskPollingService { * 调用图片生成API */ private async callImageGeneration(task: IGenerationTask): Promise { - const { model, prompt, width = 1024, height = 1024, sample_strength = 0.5, negative_prompt = "" } = task.original_params; + const { model, prompt, width = 1024, height = 1024, sample_strength = 0.5, + negative_prompt = "", generate_count = 4 } = task.original_params; const refreshToken = task.internal_params.refresh_token; // 映射模型 @@ -792,89 +795,126 @@ export class TaskPollingService { const componentId = this.generateUUID(); const submitId = this.generateUUID(); - - const { aigc_data } = await request( + let isModel4 = model.startsWith("jimeng-4"); + let options:any = image3Options( + mappedModel, + componentId, + prompt, + sample_strength, + height, + width, + negative_prompt, + '1k', + generate_count, + ); + if(isModel4){ + options = image4Options_0337( + mappedModel, + componentId, + prompt, + sample_strength, + height, + width, + negative_prompt, + '2k', + generate_count, + ); + // options = image4Options_0302( + // mappedModel, + // componentId, + // prompt, + // sample_strength, + // height, + // width, + // negative_prompt, + // '2k', + // generate_count, + // ); + } + taskLog(`生成图片 发起请求 isModel4 ${isModel4}`); + const res = await request( "post", "/mweb/v1/aigc_draft/generate", refreshToken, - { - params: { - babi_param: encodeURIComponent( - JSON.stringify({ - scenario: "image_video_generation", - feature_key: "aigc_to_image", - feature_entrance: "to_image", - feature_entrance_detail: "to_image-" + mappedModel, - }) - ), - }, - data: { - extend: { - root_model: mappedModel, - template_id: "", - }, - submit_id: submitId, - metrics_extra: JSON.stringify({ - templateId: "", - generateCount: 1, - promptSource: "custom", - templateSource: "", - lastRequestId: "", - originRequestId: "", - }), - draft_content: JSON.stringify({ - type: "draft", - id: this.generateUUID(), - min_version: "3.0.2", - is_from_tsn: true, - version: currentVersion, - main_component_id: componentId, - component_list: [ - { - type: "image_base_component", - id: componentId, - min_version: "3.0.2", - generate_type: "generate", - aigc_mode: "workbench", - abilities: { - type: "", - id: this.generateUUID(), - generate: { - type: "", - id: this.generateUUID(), - core_param: { - type: "", - id: this.generateUUID(), - model: mappedModel, - prompt, - negative_prompt, - seed: Math.floor(Math.random() * 100000000) + 2500000000, - sample_strength, - image_ratio: 1, - large_image_info: { - type: "", - id: this.generateUUID(), - height, - width, - resolution_type: resolutionType, - }, - }, - history_option: { - type: "", - id: this.generateUUID(), - }, - }, - }, - }, - ], - }), - http_common_info: { - aid: Number(process.env.DEFAULT_ASSISTANT_ID || "513695"), - }, - }, - } + options, + // { + // params: { + // babi_param: encodeURIComponent( + // JSON.stringify({ + // scenario: "image_video_generation", + // feature_key: "aigc_to_image", + // feature_entrance: "to_image", + // feature_entrance_detail: "to_image-" + mappedModel, + // }) + // ), + // }, + // data: { + // extend: { + // root_model: mappedModel, + // template_id: "", + // }, + // submit_id: submitId, + // metrics_extra: JSON.stringify({ + // templateId: "", + // generateCount: 1, + // promptSource: "custom", + // templateSource: "", + // lastRequestId: "", + // originRequestId: "", + // }), + // draft_content: JSON.stringify({ + // type: "draft", + // id: this.generateUUID(), + // min_version: "3.0.2", + // is_from_tsn: true, + // version: "3.0.2", + // main_component_id: componentId, + // component_list: [ + // { + // type: "image_base_component", + // id: componentId, + // min_version: "3.0.2", + // generate_type: "generate", + // aigc_mode: "workbench", + // abilities: { + // type: "", + // id: this.generateUUID(), + // generate: { + // type: "", + // id: this.generateUUID(), + // core_param: { + // type: "", + // id: this.generateUUID(), + // model: mappedModel, + // prompt, + // negative_prompt, + // seed: Math.floor(Math.random() * 100000000) + 2500000000, + // sample_strength, + // image_ratio: 1, + // large_image_info: { + // type: "", + // id: this.generateUUID(), + // height, + // width, + // resolution_type: "1k", + // }, + // }, + // history_option: { + // type: "", + // id: this.generateUUID(), + // }, + // }, + // }, + // }, + // ], + // }), + // http_common_info: { + // aid: Number(process.env.DEFAULT_ASSISTANT_ID || "513695"), + // }, + // }, + // } ); - + const { aigc_data } = res; const historyId = aigc_data.history_record_id; if (!historyId) { throw new Error('Failed to get history_record_id from image generation API');