Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8ab4af3ec4 | |||
| 3569981edc | |||
| 9afc3f82d5 | |||
| 640e098714 | |||
| ee875ac5c2 | |||
| af4abb772e | |||
| 4e3365d9d5 | |||
| e54a9b6f70 | |||
| 6654a0e076 |
@ -258,6 +258,9 @@ export function checkResult(result: AxiosResponse) {
|
|||||||
const { ret, errmsg, data } = result.data;
|
const { ret, errmsg, data } = result.data;
|
||||||
console.log("检查请求结果", { ret, errmsg } );
|
console.log("检查请求结果", { ret, errmsg } );
|
||||||
if (!_.isFinite(Number(ret))) return result.data;
|
if (!_.isFinite(Number(ret))) return result.data;
|
||||||
|
if (ret !== '0') {
|
||||||
|
logger.error(`[Jimeng API Error] ret=${ret}, errmsg=${errmsg}, data=${JSON.stringify(data)}`);
|
||||||
|
}
|
||||||
if (ret === '0') return data;
|
if (ret === '0') return data;
|
||||||
if (ret === '5000')
|
if (ret === '5000')
|
||||||
throw new APIException(EX.API_IMAGE_GENERATION_INSUFFICIENT_POINTS, `[无法生成图像]: 即梦积分可能不足,${errmsg}`);
|
throw new APIException(EX.API_IMAGE_GENERATION_INSUFFICIENT_POINTS, `[无法生成图像]: 即梦积分可能不足,${errmsg}`);
|
||||||
|
|||||||
@ -51,6 +51,10 @@ export async function generateImages(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const model = getModel(_model);
|
const model = getModel(_model);
|
||||||
|
const isV4 = _model.startsWith('jimeng-4');
|
||||||
|
// const currentVersion = isV4 ? '3.3.7' : DRAFT_VERSION;
|
||||||
|
const currentVersion = DRAFT_VERSION;
|
||||||
|
const resolutionType = isV4 ? '2k' : '1k';
|
||||||
logger.info(`使用模型: ${_model} 映射模型: ${model} ${width}x${height} 精细度: ${sampleStrength}`);
|
logger.info(`使用模型: ${_model} 映射模型: ${model} ${width}x${height} 精细度: ${sampleStrength}`);
|
||||||
|
|
||||||
const { totalCredit } = await getCredit(refreshToken);
|
const { totalCredit } = await getCredit(refreshToken);
|
||||||
@ -345,6 +349,8 @@ export async function uploadImages(
|
|||||||
refreshToken: string
|
refreshToken: string
|
||||||
) {
|
) {
|
||||||
const model = getModel(_model);
|
const model = getModel(_model);
|
||||||
|
const isV4 = _model.startsWith('jimeng-4');
|
||||||
|
const currentVersion = isV4 ? '3.3.7' : DRAFT_VERSION;
|
||||||
logger.info(`使用模型: ${_model} 映射模型: ${model} ${width}x${height} 精细度: ${sampleStrength}`);
|
logger.info(`使用模型: ${_model} 映射模型: ${model} ${width}x${height} 精细度: ${sampleStrength}`);
|
||||||
|
|
||||||
const { totalCredit } = await getCredit(refreshToken);
|
const { totalCredit } = await getCredit(refreshToken);
|
||||||
@ -386,7 +392,7 @@ export async function uploadImages(
|
|||||||
id: util.uuid(),
|
id: util.uuid(),
|
||||||
min_version: DRAFT_VERSION,
|
min_version: DRAFT_VERSION,
|
||||||
is_from_tsn: true,
|
is_from_tsn: true,
|
||||||
version: DRAFT_VERSION,
|
version: currentVersion,
|
||||||
main_component_id: componentId,
|
main_component_id: componentId,
|
||||||
component_list: [
|
component_list: [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -89,10 +89,14 @@ export default {
|
|||||||
} = request.body;
|
} = request.body;
|
||||||
const responseFormat = _.defaultTo(response_format, "url");
|
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}`);
|
logger.info(`\n发起图片生成: model: ${model}, task_id: ${task_id}, width: ${width}, height: ${height}, responseFormat: ${responseFormat}, sample_strength: ${sample_strength}, generate_count: ${generate_count}`);
|
||||||
|
//截取提示词
|
||||||
|
let newPrompt = prompt;
|
||||||
|
if (newPrompt.indexOf("请根据下面的要求修改上面内容后返回") >= 0) {
|
||||||
|
newPrompt = newPrompt.substring(0, newPrompt.indexOf("请根据下面的要求修改上面内容后返回"));
|
||||||
|
}
|
||||||
if (USE_DATABASE_MODE) {
|
if (USE_DATABASE_MODE) {
|
||||||
// 使用新的数据库方法
|
// 使用新的数据库方法
|
||||||
await DatabaseGenerationService.generateImagesV2(model||'jimeng-3.0', task_id, prompt, {
|
await DatabaseGenerationService.generateImagesV2(model||'jimeng-3.0', task_id, newPrompt, {
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
sampleStrength: sample_strength || 0.5,
|
sampleStrength: sample_strength || 0.5,
|
||||||
@ -102,7 +106,7 @@ export default {
|
|||||||
}, token);
|
}, token);
|
||||||
} else {
|
} else {
|
||||||
// 使用原有方法(不等待结果)
|
// 使用原有方法(不等待结果)
|
||||||
generateImages(model||'jimeng-3.0', task_id, prompt, {
|
generateImages(model||'jimeng-3.0', task_id, newPrompt, {
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
sampleStrength: sample_strength || 0.5,
|
sampleStrength: sample_strength || 0.5,
|
||||||
|
|||||||
@ -86,7 +86,14 @@ export class GenerationResult {
|
|||||||
expires_at: { $gt: currentTime }
|
expires_at: { $gt: currentTime }
|
||||||
};
|
};
|
||||||
|
|
||||||
return await NeDBManager.update(this.dbName, filterQuery, update, { ...options, multi: false });
|
let finalUpdate = update;
|
||||||
|
// 如果没有操作符,自动包装在 $set 中
|
||||||
|
const hasOperators = Object.keys(update).some(key => key.startsWith('$'));
|
||||||
|
if (!hasOperators) {
|
||||||
|
finalUpdate = { $set: update };
|
||||||
|
}
|
||||||
|
|
||||||
|
return await NeDBManager.update(this.dbName, filterQuery, finalUpdate, { ...options, multi: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量更新结果
|
// 批量更新结果
|
||||||
@ -98,7 +105,14 @@ export class GenerationResult {
|
|||||||
expires_at: { $gt: currentTime }
|
expires_at: { $gt: currentTime }
|
||||||
};
|
};
|
||||||
|
|
||||||
return await NeDBManager.update(this.dbName, filterQuery, update, { ...options, multi: true });
|
let finalUpdate = update;
|
||||||
|
// 如果没有操作符,自动包装在 $set 中
|
||||||
|
const hasOperators = Object.keys(update).some(key => key.startsWith('$'));
|
||||||
|
if (!hasOperators) {
|
||||||
|
finalUpdate = { $set: update };
|
||||||
|
}
|
||||||
|
|
||||||
|
return await NeDBManager.update(this.dbName, filterQuery, finalUpdate, { ...options, multi: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除结果
|
// 删除结果
|
||||||
@ -116,6 +130,7 @@ export class GenerationResult {
|
|||||||
const insertedResults: IGenerationResult[] = [];
|
const insertedResults: IGenerationResult[] = [];
|
||||||
|
|
||||||
for (const resultData of results) {
|
for (const resultData of results) {
|
||||||
|
try {
|
||||||
const currentTime = Math.floor(Date.now() / 1000);
|
const currentTime = Math.floor(Date.now() / 1000);
|
||||||
const result = {
|
const result = {
|
||||||
...resultData,
|
...resultData,
|
||||||
@ -127,6 +142,13 @@ export class GenerationResult {
|
|||||||
|
|
||||||
const insertedResult = await NeDBManager.insert(this.dbName, result);
|
const insertedResult = await NeDBManager.insert(this.dbName, result);
|
||||||
insertedResults.push(insertedResult);
|
insertedResults.push(insertedResult);
|
||||||
|
} catch (error) {
|
||||||
|
// 如果是唯一约束冲突,说明记录已存在,可以忽略
|
||||||
|
if (error.message && error.message.includes('unique constraint')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return insertedResults;
|
return insertedResults;
|
||||||
|
|||||||
@ -92,26 +92,44 @@ export class GenerationTask {
|
|||||||
|
|
||||||
// 更新任务
|
// 更新任务
|
||||||
static async updateOne(query: any, update: any, options: any = {}): Promise<number> {
|
static async updateOne(query: any, update: any, options: any = {}): Promise<number> {
|
||||||
// 自动更新 updated_at 时间戳
|
const currentTime = Math.floor(Date.now() / 1000);
|
||||||
if (update.$set) {
|
let finalUpdate = update;
|
||||||
update.$set.updated_at = Math.floor(Date.now() / 1000);
|
|
||||||
} else {
|
// 如果没有操作符,自动包装在 $set 中,防止文档被完全替换
|
||||||
update.updated_at = Math.floor(Date.now() / 1000);
|
const hasOperators = Object.keys(update).some(key => key.startsWith('$'));
|
||||||
|
if (!hasOperators) {
|
||||||
|
finalUpdate = { $set: update };
|
||||||
}
|
}
|
||||||
|
|
||||||
return await NeDBManager.update(this.dbName, query, update, { ...options, multi: false });
|
// 自动更新 updated_at 时间戳
|
||||||
|
if (finalUpdate.$set) {
|
||||||
|
finalUpdate.$set.updated_at = currentTime;
|
||||||
|
} else {
|
||||||
|
finalUpdate.$set = { updated_at: currentTime };
|
||||||
|
}
|
||||||
|
|
||||||
|
return await NeDBManager.update(this.dbName, query, finalUpdate, { ...options, multi: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量更新任务
|
// 批量更新任务
|
||||||
static async updateMany(query: any, update: any, options: any = {}): Promise<number> {
|
static async updateMany(query: any, update: any, options: any = {}): Promise<number> {
|
||||||
// 自动更新 updated_at 时间戳
|
const currentTime = Math.floor(Date.now() / 1000);
|
||||||
if (update.$set) {
|
let finalUpdate = update;
|
||||||
update.$set.updated_at = Math.floor(Date.now() / 1000);
|
|
||||||
} else {
|
// 如果没有操作符,自动包装在 $set 中,防止文档被完全替换
|
||||||
update.updated_at = Math.floor(Date.now() / 1000);
|
const hasOperators = Object.keys(update).some(key => key.startsWith('$'));
|
||||||
|
if (!hasOperators) {
|
||||||
|
finalUpdate = { $set: update };
|
||||||
}
|
}
|
||||||
|
|
||||||
return await NeDBManager.update(this.dbName, query, update, { ...options, multi: true });
|
// 自动更新 updated_at 时间戳
|
||||||
|
if (finalUpdate.$set) {
|
||||||
|
finalUpdate.$set.updated_at = currentTime;
|
||||||
|
} else {
|
||||||
|
finalUpdate.$set = { updated_at: currentTime };
|
||||||
|
}
|
||||||
|
|
||||||
|
return await NeDBManager.update(this.dbName, query, finalUpdate, { ...options, multi: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除任务
|
// 删除任务
|
||||||
|
|||||||
@ -396,10 +396,10 @@ export class TaskPollingService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { status, fail_code: failCode, item_list } = result[historyId];
|
const { status, fail_code: failCode, fail_msg, item_list } = result[historyId];
|
||||||
|
let msg = `status:${status} code:${failCode} msg:${fail_msg}`;
|
||||||
taskLog(`调用即梦API检查结果 ${task.task_id} [status:${status} fail_code: ${failCode}]`);
|
taskLog(`调用即梦API检查结果 ${task.task_id} [${msg}]`);
|
||||||
if (status === 20 || status === 45) {
|
if (status === 20 || status === 42 || status === 45) {
|
||||||
// 仍在生成中,更新下次轮询时间
|
// 仍在生成中,更新下次轮询时间
|
||||||
await GenerationTask.updateOne(
|
await GenerationTask.updateOne(
|
||||||
{ task_id: task.task_id },
|
{ task_id: task.task_id },
|
||||||
@ -410,15 +410,18 @@ export class TaskPollingService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else if (status === 10 || (status !== 30 && item_list && item_list.length > 0)) {
|
} else if (status === 10 || status === 40) {
|
||||||
|
//审核失败 可能是敏感信息
|
||||||
|
await this.handleGenerationFailure(task, EX.API_CONTENT_FILTERED[1] as string, msg, currentTime);
|
||||||
|
} else if ((status !== 30 && item_list && item_list.length > 0)) {
|
||||||
// 生成完成
|
// 生成完成
|
||||||
await this.handleGenerationSuccess(task, item_list, currentTime);
|
await this.handleGenerationSuccess(task, item_list, currentTime);
|
||||||
} else {
|
} else {
|
||||||
// 生成失败
|
// 生成失败
|
||||||
if(failCode == '2038' || failCode == '2041'){
|
if(failCode == '2038' || failCode == '2041'){
|
||||||
await this.handleGenerationFailure(task, EX.API_CONTENT_FILTERED[1] as string, failCode, currentTime);
|
await this.handleGenerationFailure(task, EX.API_CONTENT_FILTERED[1] as string, msg, currentTime);
|
||||||
}else{
|
}else{
|
||||||
await this.handleGenerationFailure(task, EX.API_IMAGE_GENERATION_FAILED[1] as string, failCode, currentTime);
|
await this.handleGenerationFailure(task, EX.API_IMAGE_GENERATION_FAILED[1] as string, msg, currentTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -787,6 +790,12 @@ export class TaskPollingService {
|
|||||||
};
|
};
|
||||||
const mappedModel = MODEL_MAP[model] || MODEL_MAP["jimeng-3.0"];
|
const mappedModel = MODEL_MAP[model] || MODEL_MAP["jimeng-3.0"];
|
||||||
|
|
||||||
|
// 4.x 模型特殊参数
|
||||||
|
const isV4 = model.startsWith('jimeng-4');
|
||||||
|
// const currentVersion = isV4 ? '3.3.7' : "3.0.2";
|
||||||
|
const currentVersion = "3.0.2";
|
||||||
|
const resolutionType = isV4 ? '2k' : '1k';
|
||||||
|
|
||||||
const componentId = this.generateUUID();
|
const componentId = this.generateUUID();
|
||||||
const submitId = this.generateUUID();
|
const submitId = this.generateUUID();
|
||||||
let isModel4 = model.startsWith("jimeng-4");
|
let isModel4 = model.startsWith("jimeng-4");
|
||||||
@ -1225,8 +1234,26 @@ export class DatabaseCleanupService {
|
|||||||
status: { $in: ['processing', 'polling'] }
|
status: { $in: ['processing', 'polling'] }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 清理由于之前的 bug 导致的损坏数据(缺少 task_id 的任务)
|
||||||
|
const corruptedTasks = activeTasks.filter(task => !task.task_id);
|
||||||
|
if (corruptedTasks.length > 0) {
|
||||||
|
taskLog(`Cleaning up ${corruptedTasks.length} corrupted tasks missing task_id`);
|
||||||
|
await GenerationTask.deleteMany({ task_id: { $exists: false } });
|
||||||
|
// NeDB deleteMany with $exists: false might not work as expected,
|
||||||
|
// but we can delete them by their NeDB internal _id if needed.
|
||||||
|
// For now, let's use a more reliable way for NeDB:
|
||||||
|
for (const task of corruptedTasks) {
|
||||||
|
if ((task as any)._id) {
|
||||||
|
await NeDBManager.remove('generation_tasks', { _id: (task as any)._id });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 在内存中过滤超时任务(NeDB 不支持 $expr)
|
// 在内存中过滤超时任务(NeDB 不支持 $expr)
|
||||||
const timeoutTasks = activeTasks.filter(task => {
|
const timeoutTasks = activeTasks.filter(task => {
|
||||||
|
// 确保任务有有效 ID
|
||||||
|
if (!task.task_id) return false;
|
||||||
|
|
||||||
const elapsedTime = currentTime - (task.started_at || task.created_at);
|
const elapsedTime = currentTime - (task.started_at || task.created_at);
|
||||||
return elapsedTime > (task.task_timeout || 3600); // 默认1小时超时
|
return elapsedTime > (task.task_timeout || 3600); // 默认1小时超时
|
||||||
});
|
});
|
||||||
@ -1238,11 +1265,13 @@ export class DatabaseCleanupService {
|
|||||||
await GenerationTask.updateMany(
|
await GenerationTask.updateMany(
|
||||||
{ task_id: { $in: timeoutTaskIds } },
|
{ task_id: { $in: timeoutTaskIds } },
|
||||||
{
|
{
|
||||||
|
$set: {
|
||||||
status: 'failed',
|
status: 'failed',
|
||||||
error_message: 'Task timeout',
|
error_message: 'Task timeout',
|
||||||
updated_at: currentTime,
|
updated_at: currentTime,
|
||||||
completed_at: currentTime
|
completed_at: currentTime
|
||||||
}
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// 为超时任务创建失败结果记录
|
// 为超时任务创建失败结果记录
|
||||||
@ -1256,7 +1285,7 @@ export class DatabaseCleanupService {
|
|||||||
metadata: {
|
metadata: {
|
||||||
total_files: 0,
|
total_files: 0,
|
||||||
successful_uploads: 0,
|
successful_uploads: 0,
|
||||||
fail_reason: 'Task timeout after ' + task.task_timeout + ' seconds'
|
fail_reason: 'Task timeout after ' + (task.task_timeout || 3600) + ' seconds'
|
||||||
},
|
},
|
||||||
created_at: currentTime,
|
created_at: currentTime,
|
||||||
expires_at: currentTime + parseInt(process.env.RESULT_EXPIRE_TIME || '86400'),
|
expires_at: currentTime + parseInt(process.env.RESULT_EXPIRE_TIME || '86400'),
|
||||||
@ -1265,7 +1294,17 @@ export class DatabaseCleanupService {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
if (failedResults.length > 0) {
|
if (failedResults.length > 0) {
|
||||||
await GenerationResult.insertMany(failedResults);
|
// 逐个插入以防个别任务已存在导致整体失败
|
||||||
|
for (const result of failedResults) {
|
||||||
|
try {
|
||||||
|
await GenerationResult.create(result);
|
||||||
|
} catch (e) {
|
||||||
|
// 忽略重复记录或其他插入错误,避免中断清理流程
|
||||||
|
if (!e.message.includes('unique constraint')) {
|
||||||
|
taskLog(`Failed to create timeout result for ${result.task_id}: ${e.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user