mirror of
https://github.com/vastxie/99AI.git
synced 2025-11-13 20:23:43 +08:00
v2.6.0
This commit is contained in:
93
dist/modules/chatgpt/baidu.js
vendored
93
dist/modules/chatgpt/baidu.js
vendored
@@ -1,93 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.sendMessageFromBaidu = exports.getAccessToken = void 0;
|
||||
const axios = require('axios');
|
||||
const getApiModelMaps = () => {
|
||||
let res = {};
|
||||
const maps = {
|
||||
'ERNIE-Bot': 'completions',
|
||||
'ERNIE-Bot-turbo': 'eb-instant',
|
||||
'BLOOMZ-7B': 'bloomz_7b1',
|
||||
'ERNIE-Bot-4': 'completions_pro',
|
||||
'Llama-2-7b-chat': 'llama_2_7b',
|
||||
'Llama-2-13b-chat': 'llama_2_13b',
|
||||
'ChatGLM2-6B-32K': 'chatglm2_6b_32k',
|
||||
'Qianfan-Chinese-Llama-2-7B': 'qianfan_chinese_llama_2_7b',
|
||||
};
|
||||
Object.keys(maps).map(key => {
|
||||
res[`${key.toLowerCase()}`] = maps[key];
|
||||
});
|
||||
return res;
|
||||
};
|
||||
function getAccessToken(key, secret) {
|
||||
let url = `https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=${key}&client_secret=${secret}`;
|
||||
return new Promise((resolve, reject) => {
|
||||
axios
|
||||
.post(url)
|
||||
.then((response) => {
|
||||
resolve(response.data.access_token);
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.getAccessToken = getAccessToken;
|
||||
function sendMessageFromBaidu(messagesHistory, { onProgress, accessToken, model, temperature = 0.95 }) {
|
||||
const endUrl = getApiModelMaps()[model.trim().toLowerCase()];
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = `https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/${endUrl}?access_token=${accessToken}`;
|
||||
var options = {
|
||||
method: 'POST',
|
||||
url,
|
||||
responseType: 'stream',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
data: {
|
||||
stream: true,
|
||||
messages: messagesHistory,
|
||||
},
|
||||
};
|
||||
axios(options)
|
||||
.then((response) => {
|
||||
const stream = response.data;
|
||||
let resData = {};
|
||||
let cacheChunk = '';
|
||||
let cacheResText = '';
|
||||
stream.on('data', (chunk) => {
|
||||
const lines = chunk
|
||||
.toString()
|
||||
.split('\n\n')
|
||||
.filter((line) => line.trim() !== '');
|
||||
for (const line of lines) {
|
||||
const message = line.replace('data: ', '');
|
||||
try {
|
||||
const msg = cacheChunk + message;
|
||||
const parseData = JSON.parse(msg);
|
||||
cacheChunk = '';
|
||||
const { is_end, result } = parseData;
|
||||
result && (cacheResText += result);
|
||||
if (is_end) {
|
||||
resData = parseData;
|
||||
resData.text = cacheResText;
|
||||
}
|
||||
onProgress(parseData);
|
||||
}
|
||||
catch (error) {
|
||||
cacheChunk = message;
|
||||
}
|
||||
}
|
||||
});
|
||||
stream.on('end', () => {
|
||||
cacheResText = '';
|
||||
cacheChunk = '';
|
||||
resolve(resData);
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(new Error(error));
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.sendMessageFromBaidu = sendMessageFromBaidu;
|
||||
4
dist/modules/chatgpt/chatgpt.module.js
vendored
4
dist/modules/chatgpt/chatgpt.module.js
vendored
@@ -21,7 +21,7 @@ const chatLog_service_1 = require("../chatLog/chatLog.service");
|
||||
const chatLog_entity_1 = require("../chatLog/chatLog.entity");
|
||||
const accountLog_entity_1 = require("../userBalance/accountLog.entity");
|
||||
const config_entity_1 = require("../globalConfig/config.entity");
|
||||
const gptkeys_entity_1 = require("./gptkeys.entity");
|
||||
const gptKeys_entity_1 = require("./gptKeys.entity");
|
||||
const whiteList_entity_1 = require("./whiteList.entity");
|
||||
const cramiPackage_entity_1 = require("../crami/cramiPackage.entity");
|
||||
const chatGroup_entity_1 = require("../chatGroup/chatGroup.entity");
|
||||
@@ -48,7 +48,7 @@ ChatgptModule = __decorate([
|
||||
chatLog_entity_1.ChatLogEntity,
|
||||
accountLog_entity_1.AccountLogEntity,
|
||||
config_entity_1.ConfigEntity,
|
||||
gptkeys_entity_1.GptKeysEntity,
|
||||
gptKeys_entity_1.GptKeysEntity,
|
||||
whiteList_entity_1.WhiteListEntity,
|
||||
user_entity_1.UserEntity,
|
||||
cramiPackage_entity_1.CramiPackageEntity,
|
||||
|
||||
29
dist/modules/chatgpt/chatgpt.service.js
vendored
29
dist/modules/chatgpt/chatgpt.service.js
vendored
@@ -29,7 +29,7 @@ const typeorm_1 = require("typeorm");
|
||||
const typeorm_2 = require("@nestjs/typeorm");
|
||||
const badwords_service_1 = require("../badwords/badwords.service");
|
||||
const autoreply_service_1 = require("../autoreply/autoreply.service");
|
||||
const gptkeys_entity_1 = require("./gptkeys.entity");
|
||||
const gptKeys_entity_1 = require("./gptKeys.entity");
|
||||
const globalConfig_service_1 = require("../globalConfig/globalConfig.service");
|
||||
const fanyi_service_1 = require("../fanyi/fanyi.service");
|
||||
const app_entity_1 = require("../app/app.entity");
|
||||
@@ -127,7 +127,7 @@ let ChatgptService = class ChatgptService {
|
||||
}
|
||||
}
|
||||
async chatProcess(body, req, res) {
|
||||
var _a, _b, _c;
|
||||
var _a, _b, _c, _d;
|
||||
const abortController = req.abortController;
|
||||
const { options = {}, appId, cusromPrompt, systemMessage = '' } = body;
|
||||
let setSystemMessage = systemMessage;
|
||||
@@ -184,7 +184,6 @@ let ChatgptService = class ChatgptService {
|
||||
setSystemMessage = systemPreMessage + `\n Current date: ${currentDate}`;
|
||||
}
|
||||
const mergedOptions = await this.getRequestParams(options, setSystemMessage, currentRequestModelKey, groupConfig.modelInfo);
|
||||
const { maxModelTokens = 8000, maxResponseTokens = 4096, key } = currentRequestModelKey;
|
||||
res && res.status(200);
|
||||
let response = null;
|
||||
let othersInfo = null;
|
||||
@@ -270,6 +269,7 @@ let ChatgptService = class ChatgptService {
|
||||
maxTokenRes,
|
||||
apiKey: modelKey,
|
||||
model,
|
||||
prompt,
|
||||
fileInfo,
|
||||
temperature,
|
||||
proxyUrl: proxyResUrl,
|
||||
@@ -277,8 +277,8 @@ let ChatgptService = class ChatgptService {
|
||||
res.write(firstChunk ? JSON.stringify(chat) : `\n${JSON.stringify(chat)}`);
|
||||
lastChat = chat;
|
||||
firstChunk = false;
|
||||
},
|
||||
});
|
||||
}
|
||||
}, this.uploadService);
|
||||
isSuccess = true;
|
||||
const userMessageData = {
|
||||
id: this.nineStore.getUuid(),
|
||||
@@ -297,7 +297,8 @@ let ChatgptService = class ChatgptService {
|
||||
text: response.text,
|
||||
role: 'assistant',
|
||||
name: undefined,
|
||||
usage: response.usage,
|
||||
usage: response === null || response === void 0 ? void 0 : response.usage,
|
||||
fileInfo: response === null || response === void 0 ? void 0 : response.fileInfo,
|
||||
parentMessageId: userMessageData.id,
|
||||
conversationId: response === null || response === void 0 ? void 0 : response.conversationId,
|
||||
};
|
||||
@@ -319,10 +320,11 @@ let ChatgptService = class ChatgptService {
|
||||
temperature,
|
||||
proxyUrl: proxyResUrl,
|
||||
onProgress: null,
|
||||
prompt,
|
||||
});
|
||||
}
|
||||
let { usage } = response === null || response === void 0 ? void 0 : response.detail;
|
||||
const { prompt_tokens = 0, completion_tokens = 0, total_tokens = 0 } = usage;
|
||||
const usage = ((_a = response.detail) === null || _a === void 0 ? void 0 : _a.usage) || { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 };
|
||||
const { prompt_tokens, completion_tokens, total_tokens } = usage;
|
||||
let charge = deduct;
|
||||
if (isTokenBased === true) {
|
||||
charge = Math.ceil((deduct * total_tokens) / tokenFeeRatio);
|
||||
@@ -355,6 +357,7 @@ let ChatgptService = class ChatgptService {
|
||||
userId: req.user.id,
|
||||
type: balance_constant_1.DeductionKey.CHAT_TYPE,
|
||||
prompt: prompt,
|
||||
fileInfo: response === null || response === void 0 ? void 0 : response.fileInfo,
|
||||
answer: response.text,
|
||||
promptTokens: prompt_tokens,
|
||||
completionTokens: completion_tokens,
|
||||
@@ -376,7 +379,7 @@ let ChatgptService = class ChatgptService {
|
||||
temperature,
|
||||
}),
|
||||
});
|
||||
common_1.Logger.debug(`本次调用: ${req.user.id} model: ${model} key -> ${key}, 模型名称: ${modelName}, 最大回复token: ${maxResponseTokens}`, 'ChatgptService');
|
||||
common_1.Logger.debug(`用户ID: ${req.user.id} 模型名称: ${modelName}-${model}, 消耗token: ${total_tokens}, 消耗积分: ${charge}`, 'ChatgptService');
|
||||
const userBalance = await this.userBalanceService.queryUserBalance(req.user.id);
|
||||
response.userBanance = Object.assign({}, userBalance);
|
||||
response.result && (response.result = '');
|
||||
@@ -391,8 +394,8 @@ let ChatgptService = class ChatgptService {
|
||||
catch (error) {
|
||||
console.log('chat-error <----------------------------------------->', modelKey, error);
|
||||
const code = (error === null || error === void 0 ? void 0 : error.statusCode) || 400;
|
||||
const status = ((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.status) || (error === null || error === void 0 ? void 0 : error.statusCode) || 400;
|
||||
console.log('chat-error-detail <----------------------------------------->', 'code: ', code, 'message', error === null || error === void 0 ? void 0 : error.message, 'statusText:', (_b = error === null || error === void 0 ? void 0 : error.response) === null || _b === void 0 ? void 0 : _b.statusText, 'status', (_c = error === null || error === void 0 ? void 0 : error.response) === null || _c === void 0 ? void 0 : _c.status);
|
||||
const status = ((_b = error === null || error === void 0 ? void 0 : error.response) === null || _b === void 0 ? void 0 : _b.status) || (error === null || error === void 0 ? void 0 : error.statusCode) || 400;
|
||||
console.log('chat-error-detail <----------------------------------------->', 'code: ', code, 'message', error === null || error === void 0 ? void 0 : error.message, 'statusText:', (_c = error === null || error === void 0 ? void 0 : error.response) === null || _c === void 0 ? void 0 : _c.statusText, 'status', (_d = error === null || error === void 0 ? void 0 : error.response) === null || _d === void 0 ? void 0 : _d.status);
|
||||
if (error.status && error.status === 402) {
|
||||
const errMsg = { message: `Catch Error ${error.message}`, code: 402 };
|
||||
if (res) {
|
||||
@@ -452,7 +455,7 @@ let ChatgptService = class ChatgptService {
|
||||
const money = (body === null || body === void 0 ? void 0 : body.quality) === 'hd' ? 4 : 2;
|
||||
await this.userBalanceService.validateBalance(req, 'mjDraw', money);
|
||||
let images = [];
|
||||
const detailKeyInfo = await this.modelsService.getRandomDrawKey();
|
||||
const detailKeyInfo = await this.modelsService.getCurrentModelKeyInfo('dall-e-3');
|
||||
const keyId = detailKeyInfo === null || detailKeyInfo === void 0 ? void 0 : detailKeyInfo.id;
|
||||
const { key, proxyResUrl } = await this.formatModelToken(detailKeyInfo);
|
||||
common_1.Logger.log(`draw paompt info <==**==> ${body.prompt}, key ===> ${key}`, 'DrawService');
|
||||
@@ -795,7 +798,7 @@ let ChatgptService = class ChatgptService {
|
||||
};
|
||||
ChatgptService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__param(0, (0, typeorm_2.InjectRepository)(gptkeys_entity_1.GptKeysEntity)),
|
||||
__param(0, (0, typeorm_2.InjectRepository)(gptKeys_entity_1.GptKeysEntity)),
|
||||
__param(1, (0, typeorm_2.InjectRepository)(config_entity_1.ConfigEntity)),
|
||||
__param(2, (0, typeorm_2.InjectRepository)(chatBoxType_entity_1.ChatBoxTypeEntity)),
|
||||
__param(3, (0, typeorm_2.InjectRepository)(chatBox_entity_1.ChatBoxEntity)),
|
||||
|
||||
245
dist/modules/chatgpt/openai.js
vendored
245
dist/modules/chatgpt/openai.js
vendored
@@ -3,95 +3,168 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getTokenCount = exports.sendMessageFromOpenAi = void 0;
|
||||
const axios_1 = require("axios");
|
||||
const tiktoken_1 = require("@dqbd/tiktoken");
|
||||
const utils_1 = require("../../common/utils");
|
||||
const common_1 = require("@nestjs/common");
|
||||
const uuid = require("uuid");
|
||||
const tokenizer = (0, tiktoken_1.get_encoding)('cl100k_base');
|
||||
function getFullUrl(proxyUrl) {
|
||||
const processedUrl = proxyUrl.endsWith('/') ? proxyUrl.slice(0, -1) : proxyUrl;
|
||||
const baseUrl = processedUrl || 'https://api.openai.com';
|
||||
return `${baseUrl}/v1/chat/completions`;
|
||||
}
|
||||
function sendMessageFromOpenAi(messagesHistory, inputs) {
|
||||
var _a;
|
||||
const { onProgress, maxToken, apiKey, model, temperature = 0.95, proxyUrl } = inputs;
|
||||
const max_tokens = compilerToken(model, maxToken);
|
||||
const options = {
|
||||
method: 'POST',
|
||||
url: getFullUrl(proxyUrl),
|
||||
responseType: 'stream',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${(0, utils_1.removeSpecialCharacters)(apiKey)}`,
|
||||
},
|
||||
data: {
|
||||
max_tokens,
|
||||
stream: true,
|
||||
temperature,
|
||||
model,
|
||||
messages: messagesHistory
|
||||
},
|
||||
};
|
||||
const prompt = (_a = messagesHistory[messagesHistory.length - 1]) === null || _a === void 0 ? void 0 : _a.content;
|
||||
return new Promise(async (resolve, reject) => {
|
||||
async function sendMessageFromOpenAi(messagesHistory, inputs, uploadService) {
|
||||
var _a, _b, _c, _d;
|
||||
const { onProgress, maxToken, apiKey, model, temperature = 0.8, proxyUrl, prompt } = inputs;
|
||||
if (model.includes('dall')) {
|
||||
let result = { text: '', fileInfo: '' };
|
||||
try {
|
||||
const options = {
|
||||
method: 'POST',
|
||||
url: `${proxyUrl}/v1/images/generations`,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${apiKey}`,
|
||||
},
|
||||
data: {
|
||||
prompt: prompt,
|
||||
model: model,
|
||||
response_format: 'b64_json'
|
||||
},
|
||||
};
|
||||
const response = await (0, axios_1.default)(options);
|
||||
const stream = response.data;
|
||||
let result = { text: '' };
|
||||
stream.on('data', (chunk) => {
|
||||
var _a;
|
||||
const splitArr = chunk.toString().split('\n\n').filter((line) => line.trim() !== '');
|
||||
for (const line of splitArr) {
|
||||
const data = line.replace('data:', '');
|
||||
let ISEND = false;
|
||||
try {
|
||||
ISEND = JSON.parse(data).choices[0].finish_reason === 'stop';
|
||||
}
|
||||
catch (error) {
|
||||
ISEND = false;
|
||||
}
|
||||
if (ISEND) {
|
||||
result.text = result.text.trim();
|
||||
return result;
|
||||
}
|
||||
try {
|
||||
const parsedData = JSON.parse(data);
|
||||
if (parsedData.id) {
|
||||
result.id = parsedData.id;
|
||||
}
|
||||
if ((_a = parsedData.choices) === null || _a === void 0 ? void 0 : _a.length) {
|
||||
const delta = parsedData.choices[0].delta;
|
||||
result.delta = delta.content;
|
||||
if (delta === null || delta === void 0 ? void 0 : delta.content)
|
||||
result.text += delta.content;
|
||||
if (delta.role) {
|
||||
result.role = delta.role;
|
||||
}
|
||||
result.detail = parsedData;
|
||||
}
|
||||
onProgress && onProgress({ text: result.text });
|
||||
}
|
||||
catch (error) {
|
||||
console.log('parse Error', data);
|
||||
}
|
||||
}
|
||||
});
|
||||
stream.on('end', () => {
|
||||
if (result.detail && result.text) {
|
||||
const promptTokens = getTokenCount(prompt);
|
||||
const completionTokens = getTokenCount(result.text);
|
||||
result.detail.usage = {
|
||||
prompt_tokens: promptTokens,
|
||||
completion_tokens: completionTokens,
|
||||
total_tokens: promptTokens + completionTokens,
|
||||
estimated: true
|
||||
};
|
||||
}
|
||||
return resolve(result);
|
||||
});
|
||||
const { b64_json, revised_prompt } = response.data.data[0];
|
||||
const buffer = Buffer.from(b64_json, 'base64');
|
||||
let imgUrl = '';
|
||||
try {
|
||||
const filename = uuid.v4().slice(0, 10) + '.png';
|
||||
common_1.Logger.debug(`------> 开始上传图片!!!`, 'MidjourneyService');
|
||||
const buffer = Buffer.from(b64_json, 'base64');
|
||||
imgUrl = await uploadService.uploadFile({ filename, buffer });
|
||||
common_1.Logger.debug(`图片上传成功,URL: ${imgUrl}`, 'MidjourneyService');
|
||||
}
|
||||
catch (error) {
|
||||
common_1.Logger.error(`上传图片过程中出现错误: ${error}`, 'MidjourneyService');
|
||||
}
|
||||
result.fileInfo = imgUrl;
|
||||
result.text = revised_prompt;
|
||||
onProgress && onProgress({ text: result.text });
|
||||
return result;
|
||||
}
|
||||
catch (error) {
|
||||
reject(error);
|
||||
const status = ((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.status) || 500;
|
||||
console.log('openai-draw error: ', JSON.stringify(error), status);
|
||||
const message = (_d = (_c = (_b = error === null || error === void 0 ? void 0 : error.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.error) === null || _d === void 0 ? void 0 : _d.message;
|
||||
if (status === 429) {
|
||||
result.text = '当前请求已过载、请稍等会儿再试试吧!';
|
||||
return result;
|
||||
}
|
||||
if (status === 400 && message.includes('This request has been blocked by our content filters')) {
|
||||
result.text = '您的请求已被系统拒绝。您的提示可能存在一些非法的文本。';
|
||||
return result;
|
||||
}
|
||||
if (status === 400 && message.includes('Billing hard limit has been reached')) {
|
||||
result.text = '当前模型key已被封禁、已冻结当前调用Key、尝试重新对话试试吧!';
|
||||
return result;
|
||||
}
|
||||
if (status === 500) {
|
||||
result.text = '绘制图片失败,请检查你的提示词是否有非法描述!';
|
||||
return result;
|
||||
}
|
||||
if (status === 401) {
|
||||
result.text = '绘制图片失败,此次绘画被拒绝了!';
|
||||
return result;
|
||||
}
|
||||
result.text = '绘制图片失败,请稍后试试吧!';
|
||||
return result;
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
let result = { text: '' };
|
||||
const options = {
|
||||
method: 'POST',
|
||||
url: getFullUrl(proxyUrl),
|
||||
responseType: 'stream',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: "application/json",
|
||||
Authorization: `Bearer ${apiKey}`,
|
||||
},
|
||||
data: {
|
||||
stream: true,
|
||||
temperature,
|
||||
model,
|
||||
messages: messagesHistory,
|
||||
},
|
||||
};
|
||||
if (model === 'gpt-4-vision-preview') {
|
||||
options.data.max_tokens = 2048;
|
||||
}
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const response = await (0, axios_1.default)(options);
|
||||
const stream = response.data;
|
||||
stream.on('data', (chunk) => {
|
||||
var _a;
|
||||
const splitArr = chunk.toString().split('\n\n').filter((line) => line.trim() !== '');
|
||||
for (const line of splitArr) {
|
||||
const data = line.replace('data:', '');
|
||||
let ISEND = false;
|
||||
try {
|
||||
ISEND = JSON.parse(data).choices[0].finish_reason === 'stop';
|
||||
}
|
||||
catch (error) {
|
||||
ISEND = false;
|
||||
}
|
||||
if (ISEND) {
|
||||
result.text = result.text.trim();
|
||||
return result;
|
||||
}
|
||||
try {
|
||||
if (data !== " [DONE]" && data !== "[DONE]" && data != "[DONE] ") {
|
||||
const parsedData = JSON.parse(data);
|
||||
if (parsedData.id) {
|
||||
result.id = parsedData.id;
|
||||
}
|
||||
if ((_a = parsedData.choices) === null || _a === void 0 ? void 0 : _a.length) {
|
||||
const delta = parsedData.choices[0].delta;
|
||||
result.delta = delta.content;
|
||||
if (delta === null || delta === void 0 ? void 0 : delta.content)
|
||||
result.text += delta.content;
|
||||
if (delta.role) {
|
||||
result.role = delta.role;
|
||||
}
|
||||
result.detail = parsedData;
|
||||
}
|
||||
onProgress && onProgress({ text: result.text });
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log('parse Error', data);
|
||||
}
|
||||
}
|
||||
});
|
||||
let totalText = '';
|
||||
messagesHistory.forEach(message => {
|
||||
totalText += message.content + ' ';
|
||||
});
|
||||
stream.on('end', () => {
|
||||
if (result.detail && result.text) {
|
||||
const promptTokens = getTokenCount(totalText);
|
||||
const completionTokens = getTokenCount(result.text);
|
||||
result.detail.usage = {
|
||||
prompt_tokens: promptTokens,
|
||||
completion_tokens: completionTokens,
|
||||
total_tokens: promptTokens + completionTokens,
|
||||
estimated: true
|
||||
};
|
||||
}
|
||||
return resolve(result);
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.sendMessageFromOpenAi = sendMessageFromOpenAi;
|
||||
function getTokenCount(text) {
|
||||
@@ -104,19 +177,3 @@ function getTokenCount(text) {
|
||||
return tokenizer.encode(text).length;
|
||||
}
|
||||
exports.getTokenCount = getTokenCount;
|
||||
function compilerToken(model, maxToken) {
|
||||
let max = 0;
|
||||
if (model.includes(3.5)) {
|
||||
max = maxToken > 4096 ? 4096 : maxToken;
|
||||
}
|
||||
if (model.includes('gpt-4')) {
|
||||
max = maxToken > 8192 ? 8192 : maxToken;
|
||||
}
|
||||
if (model.includes('preview')) {
|
||||
max = maxToken > 4096 ? 4096 : maxToken;
|
||||
}
|
||||
if (model.includes('32k')) {
|
||||
max = maxToken > 32768 ? 32768 : maxToken;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
6
dist/modules/chatgpt/store.js
vendored
6
dist/modules/chatgpt/store.js
vendored
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.NineStore = void 0;
|
||||
const uuid_1 = require("uuid");
|
||||
const tiktoken_1 = require("@dqbd/tiktoken");
|
||||
const common_1 = require("@nestjs/common");
|
||||
const tokenizer = (0, tiktoken_1.get_encoding)('cl100k_base');
|
||||
class NineStore {
|
||||
constructor(options) {
|
||||
@@ -32,7 +31,7 @@ class NineStore {
|
||||
let messages = [];
|
||||
let nextNumTokensEstimate = 0;
|
||||
if (systemMessage) {
|
||||
const specialModels = ['gemini-pro', 'ERNIE', 'qwen', 'SparkDesk', 'hunyuan'];
|
||||
const specialModels = ['gemini-pro', 'ERNIE', 'hunyuan'];
|
||||
const isSpecialModel = model && specialModels.some(specialModel => model.includes(specialModel));
|
||||
if (isSpecialModel) {
|
||||
messages.push({ role: 'user', content: systemMessage, name });
|
||||
@@ -65,7 +64,6 @@ class NineStore {
|
||||
}
|
||||
messages.push({ role: 'user', content: text, name });
|
||||
}
|
||||
common_1.Logger.debug(`发送的参数:${messages}`);
|
||||
let nextMessages = messages;
|
||||
do {
|
||||
if (!parentMessageId) {
|
||||
@@ -77,7 +75,7 @@ class NineStore {
|
||||
}
|
||||
const { text, name, role, fileInfo } = parentMessage;
|
||||
let content = text;
|
||||
if (role === 'user' && fileInfo) {
|
||||
if (fileInfo) {
|
||||
if (model === 'gpt-4-vision-preview') {
|
||||
content = [
|
||||
{ "type": "text", "text": text },
|
||||
|
||||
101
dist/modules/chatgpt/zhipu.js
vendored
101
dist/modules/chatgpt/zhipu.js
vendored
@@ -1,101 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.sendMessageFromZhipu = exports.compilerStream = exports.compilerMetaJsonStr = exports.generateToken = void 0;
|
||||
const axios = require('axios');
|
||||
const jwt = require('jsonwebtoken');
|
||||
function generateToken(apikey, expSeconds = 1000 * 60 * 60 * 24 * 360) {
|
||||
const [id, secret] = apikey.split('.');
|
||||
const payload = {
|
||||
api_key: id,
|
||||
exp: Math.round(Date.now()) + expSeconds * 1000,
|
||||
timestamp: Math.round(Date.now()),
|
||||
};
|
||||
return jwt.sign(payload, secret, { algorithm: 'HS256', header: { alg: 'HS256', sign_type: 'SIGN' } });
|
||||
}
|
||||
exports.generateToken = generateToken;
|
||||
function compilerMetaJsonStr(data) {
|
||||
let jsonStr = {};
|
||||
try {
|
||||
jsonStr = JSON.parse(data);
|
||||
}
|
||||
catch (error) {
|
||||
jsonStr = {
|
||||
usage: {
|
||||
completion_tokens: 49,
|
||||
prompt_tokens: 333,
|
||||
total_tokens: 399
|
||||
},
|
||||
};
|
||||
console.error('json parse error from zhipu!', data);
|
||||
}
|
||||
return jsonStr;
|
||||
}
|
||||
exports.compilerMetaJsonStr = compilerMetaJsonStr;
|
||||
function compilerStream(streamArr) {
|
||||
var _a;
|
||||
if (streamArr.length === 3) {
|
||||
return {
|
||||
event: streamArr[0].replace('event:', ''),
|
||||
id: streamArr[1].replace('id:', ''),
|
||||
is_end: false,
|
||||
result: streamArr[2].replace('data:', '').trim()
|
||||
};
|
||||
}
|
||||
if (streamArr.length === 4) {
|
||||
return {
|
||||
event: streamArr[0].replace('event:', ''),
|
||||
id: streamArr[1].replace('id:', ''),
|
||||
result: streamArr[2].replace('data:', '').trim(),
|
||||
is_end: true,
|
||||
usage: (_a = compilerMetaJsonStr(streamArr[3].replace('meta:', ''))) === null || _a === void 0 ? void 0 : _a.usage
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.compilerStream = compilerStream;
|
||||
async function sendMessageFromZhipu(messagesHistory, { onProgress, key, model, temperature = 0.95 }) {
|
||||
const token = await generateToken(key);
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = `https://open.bigmodel.cn/api/paas/v3/model-api/${model}/sse-invoke`;
|
||||
const options = {
|
||||
method: 'POST',
|
||||
url,
|
||||
responseType: 'stream',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': token
|
||||
},
|
||||
data: {
|
||||
prompt: messagesHistory,
|
||||
temperature
|
||||
}
|
||||
};
|
||||
axios(options)
|
||||
.then(response => {
|
||||
const stream = response.data;
|
||||
let resData;
|
||||
let cacheResText = '';
|
||||
stream.on('data', chunk => {
|
||||
const stramArr = chunk.toString().split("\n").filter((line) => line.trim() !== "");
|
||||
const parseData = compilerStream(stramArr);
|
||||
if (!parseData)
|
||||
return;
|
||||
const { id, result, is_end } = parseData;
|
||||
result && (cacheResText += result.trim());
|
||||
if (is_end) {
|
||||
parseData.is_end = false;
|
||||
resData = parseData;
|
||||
resData.text = cacheResText;
|
||||
}
|
||||
onProgress(parseData);
|
||||
});
|
||||
stream.on('end', () => {
|
||||
resolve(resData);
|
||||
cacheResText = '';
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.log('error: ', error);
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.sendMessageFromZhipu = sendMessageFromZhipu;
|
||||
73
dist/modules/database/database.service.js
vendored
73
dist/modules/database/database.service.js
vendored
@@ -26,10 +26,10 @@ let DatabaseService = class DatabaseService {
|
||||
if (!user || user.length === 0) {
|
||||
const superPassword = bcrypt.hashSync('123456', 10);
|
||||
const adminPassword = bcrypt.hashSync('123456', 10);
|
||||
const superEmail = 'default@cooper.com';
|
||||
const adminEmail = 'defaultAdmin@cooper.com';
|
||||
const superEmail = 'super';
|
||||
const adminEmail = 'admin';
|
||||
const superUserinfo = { username: 'super', password: superPassword, status: 1, email: superEmail, sex: 1, role: 'super' };
|
||||
const adminUserinfo = { username: 'admin', password: adminPassword, status: 1, email: adminEmail, sex: 1, role: 'admin' };
|
||||
const adminUserinfo = { username: 'admin', password: adminPassword, status: 0, email: adminEmail, sex: 1, role: 'admin' };
|
||||
await this.createDefaultUser(superUserinfo);
|
||||
await this.createDefaultUser(adminUserinfo);
|
||||
}
|
||||
@@ -59,83 +59,70 @@ let DatabaseService = class DatabaseService {
|
||||
}
|
||||
async createBaseSiteConfig() {
|
||||
try {
|
||||
const code = `
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?cb8c9a3bcadbc200e950b05f9c61a385";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
`;
|
||||
const code = ``;
|
||||
const noticeInfo = `
|
||||
#### NineAi 欢迎您
|
||||
- NineAi唯一官方网站 https://ai.jiangly.com
|
||||
- NineAi 作者VX: J_longyan
|
||||
- NineAi 作者QQ: 927898639
|
||||
- 欢迎使用Nine
|
||||
- 初始管理员账号密码 super nine-super 【前台后台登录都可以修改】
|
||||
#### AIWeb 欢迎您
|
||||
- 欢迎使用 AIWeb
|
||||
- 初始管理员账号密码 super 123456 【前台后台登录都可以修改】
|
||||
- 初始预览账号密码 admin 123456 【为后台查看账号 仅可查看部分非敏感数据】
|
||||
`;
|
||||
const defaultConfig = [
|
||||
{ configKey: 'siteName', configVal: 'Nine Ai', public: 1, encry: 0 },
|
||||
{ configKey: 'qqNumber', configVal: '840814166', public: 1, encry: 0 },
|
||||
{ configKey: 'vxNumber', configVal: 'wangpanzhu321', public: 1, encry: 0 },
|
||||
{ configKey: 'siteName', configVal: '', public: 1, encry: 0 },
|
||||
{ configKey: 'qqNumber', configVal: '', public: 1, encry: 0 },
|
||||
{ configKey: 'vxNumber', configVal: '', public: 1, encry: 0 },
|
||||
{ configKey: 'robotAvatar', configVal: '', public: 1, encry: 0 },
|
||||
{
|
||||
configKey: 'userDefautlAvatar',
|
||||
configVal: 'https://public-1300678944.cos.ap-shanghai.myqcloud.com/blog/1682571295452image.png',
|
||||
configVal: '',
|
||||
public: 0,
|
||||
encry: 0,
|
||||
},
|
||||
{ configKey: 'baiduCode', configVal: code, public: 1, encry: 0 },
|
||||
{ configKey: 'baiduSiteId', configVal: '19024441', public: 0, encry: 0 },
|
||||
{ configKey: 'baiduSiteId', configVal: '', public: 0, encry: 0 },
|
||||
{
|
||||
configKey: 'baiduToken',
|
||||
configVal: '121.a1600b9b60910feea2ef627ea9776a6f.YGP_CWCOA2lNcIGJ27BwXGxa6nZhBQyLUS4XVaD.TWt9TA',
|
||||
configVal: '',
|
||||
public: 0,
|
||||
encry: 0,
|
||||
},
|
||||
{ configKey: 'buyCramiAddress', configVal: '', public: 1, encry: 0 },
|
||||
{ configKey: 'openaiBaseUrl', configVal: 'https://api.openai.com', public: 0, encry: 0 },
|
||||
{ configKey: 'openaiBaseUrl', configVal: 'https://api.lightai.io', public: 0, encry: 0 },
|
||||
{ configKey: 'noticeInfo', configVal: noticeInfo, public: 1, encry: 0 },
|
||||
{ configKey: 'registerVerifyEmailTitle', configVal: 'NineTeam团队账号验证', public: 0, encry: 0 },
|
||||
{ configKey: 'registerVerifyEmailTitle', configVal: 'AIWeb账号验证', public: 0, encry: 0 },
|
||||
{
|
||||
configKey: 'registerVerifyEmailDesc',
|
||||
configVal: '欢迎使用Nine Team团队的产品服务,请在五分钟内完成你的账号激活,点击以下按钮激活您的账号,',
|
||||
configVal: '欢迎使用AI Web团队的产品服务,请在五分钟内完成你的账号激活,点击以下按钮激活您的账号,',
|
||||
public: 0,
|
||||
encry: 0,
|
||||
},
|
||||
{ configKey: 'registerVerifyEmailFrom', configVal: 'NineTeam团队', public: 0, encry: 0 },
|
||||
{ configKey: 'registerVerifyEmailFrom', configVal: 'AI Web团队', public: 0, encry: 0 },
|
||||
{ configKey: 'registerVerifyExpir', configVal: '1800', public: 0, encry: 0 },
|
||||
{ configKey: 'registerSuccessEmailTitle', configVal: 'NineTeam团队账号激活成功', public: 0, encry: 0 },
|
||||
{ configKey: 'registerSuccessEmailTeamName', configVal: 'NineTeam团队', public: 0, encry: 0 },
|
||||
{ configKey: 'registerSuccessEmailTitle', configVal: 'AIWeb账号激活成功', public: 0, encry: 0 },
|
||||
{ configKey: 'registerSuccessEmailTeamName', configVal: 'AIWeb', public: 0, encry: 0 },
|
||||
{
|
||||
configKey: 'registerSuccessEmaileAppend',
|
||||
configVal: ',请妥善保管您的账号,我们将为您赠送50次对话额度和5次绘画额度、祝您使用愉快',
|
||||
configVal: ',请妥善保管您的账号,祝您使用愉快',
|
||||
public: 0,
|
||||
encry: 0,
|
||||
},
|
||||
{ configKey: 'registerFailEmailTitle', configVal: 'NineTeam账号激活失败', public: 0, encry: 0 },
|
||||
{ configKey: 'registerFailEmailTeamName', configVal: 'NineTeam团队', public: 0, encry: 0 },
|
||||
{ configKey: 'registerFailEmailTitle', configVal: 'AIWeb账号激活失败', public: 0, encry: 0 },
|
||||
{ configKey: 'registerFailEmailTeamName', configVal: 'AIWeb团队', public: 0, encry: 0 },
|
||||
{ configKey: 'registerSendStatus', configVal: '1', public: 1, encry: 0 },
|
||||
{ configKey: 'registerSendModel3Count', configVal: '30', public: 1, encry: 0 },
|
||||
{ configKey: 'registerSendModel4Count', configVal: '3', public: 1, encry: 0 },
|
||||
{ configKey: 'registerSendDrawMjCount', configVal: '3', public: 1, encry: 0 },
|
||||
{ configKey: 'firstRegisterSendStatus', configVal: '1', public: 1, encry: 0 },
|
||||
{ configKey: 'firstRegisterSendRank', configVal: '500', public: 1, encry: 0 },
|
||||
{ configKey: 'firstRregisterSendModel3Count', configVal: '20', public: 1, encry: 0 },
|
||||
{ configKey: 'firstRregisterSendModel4Count', configVal: '2', public: 1, encry: 0 },
|
||||
{ configKey: 'firstRregisterSendDrawMjCount', configVal: '3', public: 1, encry: 0 },
|
||||
{ configKey: 'firstRregisterSendModel3Count', configVal: '10', public: 1, encry: 0 },
|
||||
{ configKey: 'firstRregisterSendModel4Count', configVal: '10', public: 1, encry: 0 },
|
||||
{ configKey: 'firstRregisterSendDrawMjCount', configVal: '10', public: 1, encry: 0 },
|
||||
{ configKey: 'inviteSendStatus', configVal: '1', public: 1, encry: 0 },
|
||||
{ configKey: 'inviteGiveSendModel3Count', configVal: '30', public: 1, encry: 0 },
|
||||
{ configKey: 'inviteGiveSendModel4Count', configVal: '3', public: 1, encry: 0 },
|
||||
{ configKey: 'inviteGiveSendDrawMjCount', configVal: '1', public: 1, encry: 0 },
|
||||
{ configKey: 'inviteGiveSendModel3Count', configVal: '0', public: 1, encry: 0 },
|
||||
{ configKey: 'inviteGiveSendModel4Count', configVal: '0', public: 1, encry: 0 },
|
||||
{ configKey: 'inviteGiveSendDrawMjCount', configVal: '0', public: 1, encry: 0 },
|
||||
{ configKey: 'invitedGuestSendModel3Count', configVal: '10', public: 1, encry: 0 },
|
||||
{ configKey: 'invitedGuestSendModel4Count', configVal: '1', public: 1, encry: 0 },
|
||||
{ configKey: 'invitedGuestSendDrawMjCount', configVal: '1', public: 1, encry: 0 },
|
||||
{ configKey: 'invitedGuestSendModel4Count', configVal: '10', public: 1, encry: 0 },
|
||||
{ configKey: 'invitedGuestSendDrawMjCount', configVal: '10', public: 1, encry: 0 },
|
||||
{ configKey: 'isVerifyEmail', configVal: '1', public: 1, encry: 0 },
|
||||
];
|
||||
const res = await this.connection.query(`INSERT INTO config (configKey, configVal, public, encry) VALUES ${defaultConfig
|
||||
|
||||
20
dist/modules/midjourney/midjourney.entity.js
vendored
20
dist/modules/midjourney/midjourney.entity.js
vendored
@@ -38,10 +38,6 @@ __decorate([
|
||||
(0, typeorm_1.Column)({ comment: '垫图图片 + 绘画描述词 + 额外参数 = 完整的prompt', type: 'text' }),
|
||||
__metadata("design:type", String)
|
||||
], MidjourneyEntity.prototype, "fullPrompt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ comment: '随机产生的绘画ID用于拿取比对结果' }),
|
||||
__metadata("design:type", String)
|
||||
], MidjourneyEntity.prototype, "randomDrawId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ comment: '当前绘制任务的进度', nullable: true }),
|
||||
__metadata("design:type", Number)
|
||||
@@ -56,7 +52,7 @@ __decorate([
|
||||
], MidjourneyEntity.prototype, "status", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ comment: 'mj绘画的动作、绘图、放大、变换、图生图' }),
|
||||
__metadata("design:type", Number)
|
||||
__metadata("design:type", String)
|
||||
], MidjourneyEntity.prototype, "action", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ comment: '一组图片的第几张、放大或者变换的时候需要使用', nullable: true }),
|
||||
@@ -66,18 +62,22 @@ __decorate([
|
||||
(0, typeorm_1.Column)({ comment: '是否推荐0: 默认不推荐 1: 推荐', nullable: true, default: 0 }),
|
||||
__metadata("design:type", Number)
|
||||
], MidjourneyEntity.prototype, "rec", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ comment: '对图片操作的', nullable: true }),
|
||||
__metadata("design:type", String)
|
||||
], MidjourneyEntity.prototype, "customId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ comment: '绘画的ID每条不一样', nullable: true }),
|
||||
__metadata("design:type", String)
|
||||
], MidjourneyEntity.prototype, "message_id", void 0);
|
||||
], MidjourneyEntity.prototype, "drawId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ comment: '对图片放大或者变体的ID', nullable: true }),
|
||||
(0, typeorm_1.Column)({ comment: '图片链接', nullable: true, type: 'text' }),
|
||||
__metadata("design:type", String)
|
||||
], MidjourneyEntity.prototype, "custom_id", void 0);
|
||||
], MidjourneyEntity.prototype, "drawUrl", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ comment: '图片信息尺寸', nullable: true, type: 'text' }),
|
||||
(0, typeorm_1.Column)({ comment: '图片比例', nullable: true, type: 'text' }),
|
||||
__metadata("design:type", String)
|
||||
], MidjourneyEntity.prototype, "fileInfo", void 0);
|
||||
], MidjourneyEntity.prototype, "drawRatio", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ comment: '扩展参数', nullable: true, type: 'text' }),
|
||||
__metadata("design:type", String)
|
||||
|
||||
819
dist/modules/midjourney/midjourney.service.js
vendored
819
dist/modules/midjourney/midjourney.service.js
vendored
@@ -22,19 +22,18 @@ const axios_1 = require("axios");
|
||||
const globalConfig_service_1 = require("../globalConfig/globalConfig.service");
|
||||
const midjourney_constant_1 = require("../../common/constants/midjourney.constant");
|
||||
const upload_service_1 = require("../upload/upload.service");
|
||||
const badwords_service_1 = require("../badwords/badwords.service");
|
||||
const userBalance_service_1 = require("../userBalance/userBalance.service");
|
||||
const utils_1 = require("../../common/utils");
|
||||
const redisCache_service_1 = require("../redisCache/redisCache.service");
|
||||
const prompt_entity_1 = require("./prompt.entity");
|
||||
const image_size_1 = require("image-size");
|
||||
let MidjourneyService = class MidjourneyService {
|
||||
constructor(midjourneyEntity, userEntity, mjPromptsEntity, globalConfigService, uploadService, badwordsService, userBalanceService, redisCacheService) {
|
||||
constructor(midjourneyEntity, userEntity, mjPromptsEntity, globalConfigService, uploadService, userBalanceService, redisCacheService) {
|
||||
this.midjourneyEntity = midjourneyEntity;
|
||||
this.userEntity = userEntity;
|
||||
this.mjPromptsEntity = mjPromptsEntity;
|
||||
this.globalConfigService = globalConfigService;
|
||||
this.uploadService = uploadService;
|
||||
this.badwordsService = badwordsService;
|
||||
this.userBalanceService = userBalanceService;
|
||||
this.redisCacheService = redisCacheService;
|
||||
this.lockPrompt = [];
|
||||
@@ -42,580 +41,191 @@ let MidjourneyService = class MidjourneyService {
|
||||
async sleep(time) {
|
||||
return new Promise((resolve) => setTimeout(resolve, time));
|
||||
}
|
||||
async getImageSizeFromUrl(imageUrl) {
|
||||
try {
|
||||
const response = await axios_1.default.get(imageUrl, { responseType: 'arraybuffer' });
|
||||
const buffer = Buffer.from(response.data, 'binary');
|
||||
const dimensions = (0, image_size_1.default)(buffer);
|
||||
return { width: dimensions.width, height: dimensions.height };
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error fetching image size:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
async draw(jobData, jobId) {
|
||||
const { id, action } = jobData;
|
||||
const { id, action, drawId } = jobData;
|
||||
const drawInfo = await this.midjourneyEntity.findOne({ where: { id } });
|
||||
const { customId } = drawInfo;
|
||||
try {
|
||||
await this.bindJobId(id, jobId);
|
||||
await this.updateDrawStatus(id, midjourney_constant_1.MidjourneyStatusEnum.DRAWING);
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.DRAW || action === midjourney_constant_1.MidjourneyActionEnum.GENERATE) {
|
||||
await this.sendDrawCommand(drawInfo, jobData);
|
||||
const drawRes = await this.pollComparisonResultDraw(drawInfo);
|
||||
await this.updateDrawData(jobData, drawRes);
|
||||
}
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.UPSCALE) {
|
||||
const { message_id, custom_id } = drawInfo;
|
||||
await this.sendSmInteractions({ message_id, custom_id }, jobData);
|
||||
common_1.Logger.debug(`记录${id}已经成功发送了图片放大指令`, 'MidjourneyService');
|
||||
const drawRes = await this.pollComparisonResultUpscale(drawInfo);
|
||||
await this.updateDrawData(jobData, drawRes);
|
||||
}
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.VARIATION) {
|
||||
const { message_id, custom_id } = drawInfo;
|
||||
await this.sendSmInteractions({ message_id, custom_id }, jobData);
|
||||
common_1.Logger.debug(`记录${id}已经成功发送了图片变化指令`, 'MidjourneyService');
|
||||
const drawRes = await this.pollComparisonResultVariation(drawInfo);
|
||||
await this.updateDrawData(jobData, drawRes);
|
||||
this.lockPrompt = this.lockPrompt.filter((item) => item !== drawInfo.randomDrawId);
|
||||
}
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.REGENERATE) {
|
||||
const { message_id, custom_id } = drawInfo;
|
||||
await this.sendReGenerateInteractions({ message_id, custom_id }, jobData);
|
||||
common_1.Logger.debug(`记录${id}已经成功发送了重新生成图片指令`, 'MidjourneyService');
|
||||
const drawRes = await this.pollComparisonResultReGenerate(drawInfo);
|
||||
await this.updateDrawData(jobData, drawRes);
|
||||
this.lockPrompt = this.lockPrompt.filter((item) => item !== drawInfo.randomDrawId);
|
||||
}
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.VARY) {
|
||||
const { message_id, custom_id } = drawInfo;
|
||||
await this.sendVaryInteractions({ message_id, custom_id }, jobData);
|
||||
common_1.Logger.debug(`记录${id}已经成功发送单张图片增强指令`, 'MidjourneyService');
|
||||
const drawRes = await this.pollComparisonResultVary(drawInfo);
|
||||
await this.updateDrawData(jobData, drawRes);
|
||||
this.lockPrompt = this.lockPrompt.filter((item) => item !== drawInfo.randomDrawId);
|
||||
}
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.ZOOM) {
|
||||
const { message_id, custom_id } = drawInfo;
|
||||
await this.sendZoomInteractions({ message_id, custom_id }, jobData);
|
||||
common_1.Logger.debug(`记录${id}已经成功发送单张图片缩放指令`, 'MidjourneyService');
|
||||
const drawRes = await this.pollComparisonResultZoom(drawInfo);
|
||||
await this.updateDrawData(jobData, drawRes);
|
||||
this.lockPrompt = this.lockPrompt.filter((item) => item !== drawInfo.randomDrawId);
|
||||
}
|
||||
const result = await this.sendDrawCommand(drawInfo, action);
|
||||
drawInfo.drawId = result;
|
||||
const drawRes = await this.pollComparisonResultDraw(id, drawInfo);
|
||||
await this.updateDrawData(jobData, drawRes);
|
||||
this.drawSuccess(jobData);
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
this.lockPrompt = this.lockPrompt.filter((item) => item !== drawInfo.randomDrawId);
|
||||
await this.drawFailed(jobData);
|
||||
console.log('error: ', error);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
async addDrawQueue(params) {
|
||||
const { prompt, imgUrl = '', extraParam = '', action = 1, userId, randomDrawId, orderId, custom_id, message_id } = params;
|
||||
const fullPrompt = imgUrl ? `${imgUrl} ${prompt} ${extraParam}` : `${prompt} ${extraParam}`;
|
||||
await this.badwordsService.checkBadWords(fullPrompt, userId);
|
||||
const drawInfo = {
|
||||
userId,
|
||||
extraParam,
|
||||
prompt,
|
||||
imgUrl,
|
||||
fullPrompt,
|
||||
randomDrawId,
|
||||
status: midjourney_constant_1.MidjourneyStatusEnum.WAITING,
|
||||
action: action,
|
||||
orderId,
|
||||
custom_id,
|
||||
message_id,
|
||||
};
|
||||
const res = await this.midjourneyEntity.save(drawInfo);
|
||||
return res;
|
||||
try {
|
||||
const { prompt, imgUrl = '', extraParam = '', action, userId, orderId, customId, drawId } = params;
|
||||
const fullPrompt = imgUrl ? `${imgUrl} ${prompt} ${extraParam}` : `${prompt} ${extraParam}`;
|
||||
const drawInfo = {
|
||||
userId,
|
||||
drawId,
|
||||
extraParam,
|
||||
prompt,
|
||||
imgUrl,
|
||||
fullPrompt,
|
||||
status: midjourney_constant_1.MidjourneyStatusEnum.WAITING,
|
||||
action,
|
||||
orderId,
|
||||
customId,
|
||||
};
|
||||
const res = await this.midjourneyEntity.save(drawInfo);
|
||||
return res;
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error in addDrawQueue:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
async updateDrawStatus(id, status) {
|
||||
await this.midjourneyEntity.update({ id }, { status });
|
||||
}
|
||||
async updateDrawData(jobData, drawRes) {
|
||||
try {
|
||||
const { id, content, channel_id, attachments = [], timestamp, durationSpent } = drawRes;
|
||||
const { filename, url, proxy_url, width, height, size } = attachments[0];
|
||||
const { id, imageUrl, action, submitTime, finishTime, progress } = drawRes;
|
||||
const durationSpent = finishTime - submitTime;
|
||||
let filename = `${Date.now()}-${id}.png`;
|
||||
const mjNotSaveImg = await this.globalConfigService.getConfigs(['mjNotSaveImg']);
|
||||
let cosUrl = '';
|
||||
if (!Number(mjNotSaveImg) || Number(mjNotSaveImg) === 0) {
|
||||
common_1.Logger.debug(`------> 开始上传图片!!!`, 'MidjourneyService');
|
||||
const startDate = new Date();
|
||||
cosUrl = await this.uploadService.uploadFileFromUrl({ filename, url });
|
||||
const endDate = new Date();
|
||||
common_1.Logger.debug(`本次图片上传耗时为${(endDate.getTime() - startDate.getTime()) / 1000}秒`, 'MidjourneyService');
|
||||
let isSaveImg = true;
|
||||
try {
|
||||
if (!Number(mjNotSaveImg) || Number(mjNotSaveImg) === 0) {
|
||||
common_1.Logger.debug(`------> 开始上传图片!!!`, 'MidjourneyService');
|
||||
cosUrl = await this.uploadService.uploadFileFromUrl({ filename, url: imageUrl });
|
||||
}
|
||||
else {
|
||||
cosUrl = imageUrl;
|
||||
isSaveImg = false;
|
||||
common_1.Logger.debug('本次不存图片了', 'MidjourneyService');
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log('本次不存图片了');
|
||||
catch (uploadError) {
|
||||
common_1.Logger.error('存储图片失败,使用原始图片链接', 'MidjourneyService');
|
||||
cosUrl = imageUrl;
|
||||
isSaveImg = false;
|
||||
}
|
||||
const cosType = await this.uploadService.getUploadType();
|
||||
const { width, height } = await this.getImageSizeFromUrl(imageUrl);
|
||||
const drawInfo = {
|
||||
status: midjourney_constant_1.MidjourneyStatusEnum.DRAWED,
|
||||
message_id: id,
|
||||
drawId: id,
|
||||
action: action,
|
||||
drawUrl: cosUrl,
|
||||
drawRatio: `${width}x${height}`,
|
||||
progress: 100,
|
||||
fileInfo: JSON.stringify({ width, height, size, filename, cosUrl, cosType }),
|
||||
extend: this.removeEmoji(JSON.stringify(drawRes)),
|
||||
durationSpent,
|
||||
isSaveImg: !Number(mjNotSaveImg) || Number(mjNotSaveImg) === 0,
|
||||
isSaveImg,
|
||||
};
|
||||
await this.midjourneyEntity.update({ id: jobData.id }, drawInfo);
|
||||
}
|
||||
catch (error) {
|
||||
console.log('TODO->存储图片失败, ', jobData, error);
|
||||
throw new common_1.HttpException('更新绘画数据失败', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async getHistroyMessageIds(randomDrawId) {
|
||||
const res = await this.midjourneyEntity.find({ where: { randomDrawId, status: midjourney_constant_1.MidjourneyStatusEnum.DRAWED } });
|
||||
return res.map((item) => item.message_id);
|
||||
}
|
||||
async sendDrawCommand(drawInfo, jobData) {
|
||||
const { fullPrompt, randomDrawId, imgUrl } = drawInfo;
|
||||
const prompt = imgUrl ? `[${randomDrawId}] ${imgUrl} ${fullPrompt}` : `[${randomDrawId}] ${fullPrompt}`;
|
||||
common_1.Logger.debug(`本次绘图指令为${prompt}`, 'MidjourneyService');
|
||||
const { application_id, guild_id, channel_id, session_id, version, id, authorization, mjProxy } = await this.getMjDefaultParams();
|
||||
const payloadJson = {
|
||||
type: 2,
|
||||
application_id,
|
||||
guild_id,
|
||||
channel_id,
|
||||
session_id,
|
||||
data: { version, id, name: 'imagine', type: 1, options: [{ type: 3, name: 'prompt', value: prompt }], attachments: [] },
|
||||
};
|
||||
try {
|
||||
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl'])) || 'http://172.247.48.137:8000';
|
||||
const url = mjProxy == 1 ? `${mjProxyUrl}/mj/draw` : 'https://discord.com/api/v9/interactions';
|
||||
const headers = { authorization };
|
||||
const res = await axios_1.default.post(url, payloadJson, { headers });
|
||||
return false;
|
||||
}
|
||||
catch (error) {
|
||||
common_1.Logger.error(`发送绘画指令失败`, 'MidjourneyService');
|
||||
throw new common_1.HttpException('发送绘图指令失败、请联系管理员检测绘画配置!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async sendSmInteractions(params, jobData) {
|
||||
const { message_id, custom_id } = params;
|
||||
const { application_id, guild_id, channel_id, session_id, version, id, authorization, mjProxy } = await this.getMjDefaultParams();
|
||||
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl'])) || 'http://172.247.48.137:8000';
|
||||
const url = mjProxy == 1 ? `${mjProxyUrl}/mj/draw` : 'https://discord.com/api/v9/interactions';
|
||||
const headers = { authorization };
|
||||
const body = {
|
||||
type: 3,
|
||||
guild_id,
|
||||
channel_id,
|
||||
message_flags: 0,
|
||||
message_id,
|
||||
application_id,
|
||||
session_id,
|
||||
data: {
|
||||
component_type: 2,
|
||||
custom_id,
|
||||
},
|
||||
};
|
||||
try {
|
||||
await axios_1.default.post(url, body, { headers });
|
||||
}
|
||||
catch (error) {
|
||||
console.log('发送放大变幻指令失败: ', error);
|
||||
common_1.Logger.error(`发送放大变幻指令失败`, 'MidjourneyService');
|
||||
throw new common_1.HttpException('对图片放大变幻失败...', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async sendReGenerateInteractions(params, jobData) {
|
||||
const { message_id, custom_id } = params;
|
||||
const { application_id, guild_id, channel_id, session_id, version, id, authorization, mjProxy } = await this.getMjDefaultParams();
|
||||
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl'])) || 'http://172.247.48.137:8000';
|
||||
const url = mjProxy == 1 ? `${mjProxyUrl}/mj/draw` : 'https://discord.com/api/v9/interactions';
|
||||
const headers = { authorization };
|
||||
const body = {
|
||||
type: 3,
|
||||
guild_id,
|
||||
channel_id,
|
||||
message_id,
|
||||
application_id,
|
||||
session_id,
|
||||
data: {
|
||||
component_type: 2,
|
||||
custom_id,
|
||||
},
|
||||
};
|
||||
try {
|
||||
await axios_1.default.post(url, body, { headers });
|
||||
}
|
||||
catch (error) {
|
||||
console.log('发送重新生成指令失败: ', error);
|
||||
common_1.Logger.error(`发送放大变幻指令失败`, 'MidjourneyService');
|
||||
throw new common_1.HttpException('对图片放大变幻失败...', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async sendVaryInteractions(params, jobData) {
|
||||
const { message_id, custom_id } = params;
|
||||
const { application_id, guild_id, channel_id, session_id, version, id, authorization, mjProxy } = await this.getMjDefaultParams();
|
||||
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl'])) || 'http://172.247.48.137:8000';
|
||||
const url = mjProxy == 1 ? `${mjProxyUrl}/mj/draw` : 'https://discord.com/api/v9/interactions';
|
||||
const headers = { authorization };
|
||||
const body = {
|
||||
type: 3,
|
||||
guild_id,
|
||||
channel_id,
|
||||
message_id,
|
||||
application_id,
|
||||
session_id,
|
||||
data: {
|
||||
component_type: 2,
|
||||
custom_id,
|
||||
},
|
||||
};
|
||||
try {
|
||||
await axios_1.default.post(url, body, { headers });
|
||||
}
|
||||
catch (error) {
|
||||
console.log('发送对单张图片增强指令失败: ', error);
|
||||
common_1.Logger.error(`发送单张图片增强指令失败`, 'MidjourneyService');
|
||||
throw new common_1.HttpException('对图片单张增强失败...', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async sendZoomInteractions(params, jobData) {
|
||||
const { message_id, custom_id } = params;
|
||||
const { application_id, guild_id, channel_id, session_id, version, id, authorization, mjProxy } = await this.getMjDefaultParams();
|
||||
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl'])) || 'http://172.247.48.137:8000';
|
||||
const url = mjProxy == 1 ? `${mjProxyUrl}/mj/draw` : 'https://discord.com/api/v9/interactions';
|
||||
const headers = { authorization };
|
||||
const body = {
|
||||
type: 3,
|
||||
guild_id,
|
||||
channel_id,
|
||||
message_id,
|
||||
application_id,
|
||||
session_id,
|
||||
data: {
|
||||
component_type: 2,
|
||||
custom_id,
|
||||
},
|
||||
};
|
||||
try {
|
||||
await axios_1.default.post(url, body, { headers });
|
||||
}
|
||||
catch (error) {
|
||||
console.log('发送对单张图片增强指令失败: ', error);
|
||||
common_1.Logger.error(`发送单张图片增强指令失败`, 'MidjourneyService');
|
||||
throw new common_1.HttpException('对图片单张增强失败...', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async pollComparisonResultDraw(drawInfo) {
|
||||
common_1.Logger.debug(`开始查询绘画结果`, 'MidjourneyService');
|
||||
const startTime = Date.now();
|
||||
const INTERVAL_BEFORE_90S = 10000;
|
||||
const INTERVAL_AFTER_90S = 30000;
|
||||
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 150000;
|
||||
const TIMEOUT = timeout;
|
||||
let pollingCount = 0;
|
||||
let drawRes = null;
|
||||
let isMatchSuccessful = false;
|
||||
try {
|
||||
while (!isMatchSuccessful && Date.now() - startTime < TIMEOUT) {
|
||||
let interval;
|
||||
if (Date.now() - startTime < 90000) {
|
||||
interval = INTERVAL_BEFORE_90S;
|
||||
async sendDrawCommand(drawInfo, action) {
|
||||
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl']));
|
||||
const mjKey = (await this.globalConfigService.getConfigs(['mjKey']));
|
||||
const { id, fullPrompt, imgUrl, drawId, customId } = drawInfo;
|
||||
const prompt = imgUrl ? `${imgUrl} ${fullPrompt}` : `${fullPrompt}`;
|
||||
let url = '';
|
||||
let payloadJson = {};
|
||||
const MAX_RETRIES = 3;
|
||||
let retryCount = 0;
|
||||
while (retryCount < MAX_RETRIES) {
|
||||
try {
|
||||
if (action === 'IMAGINE') {
|
||||
url = `${mjProxyUrl}/mj/submit/imagine`;
|
||||
payloadJson = { prompt: prompt };
|
||||
}
|
||||
else {
|
||||
interval = INTERVAL_AFTER_90S;
|
||||
url = `${mjProxyUrl}/mj/submit/action`;
|
||||
payloadJson = { taskId: drawId, customId: customId };
|
||||
}
|
||||
await this.sleep(interval);
|
||||
common_1.Logger.debug(`【绘制图片】第 ${pollingCount + 1} 次开始查询`, 'MidjourneyService');
|
||||
drawRes = await this.findCurrentPromptResult(drawInfo.randomDrawId);
|
||||
if (drawRes) {
|
||||
const { content } = drawRes;
|
||||
const progress = await this.parseProgress(content);
|
||||
common_1.Logger.debug(`【绘制图片】第 ${pollingCount + 1} 次、 当前绘画进度为${progress}%`, 'MidjourneyService');
|
||||
await this.midjourneyEntity.update({ id: drawInfo.id }, { progress: progress !== null && progress !== void 0 ? progress : 100 });
|
||||
const headers = { "mj-api-secret": mjKey };
|
||||
const res = await axios_1.default.post(url, payloadJson, { headers });
|
||||
const { result } = res.data;
|
||||
if (result) {
|
||||
common_1.Logger.log(`绘画ID: ${result}`, 'MidjourneyService');
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
throw new Error('未能获取结果数据');
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
retryCount++;
|
||||
if (retryCount >= MAX_RETRIES) {
|
||||
await this.updateDrawStatus(id, midjourney_constant_1.MidjourneyStatusEnum.DRAWFAIL);
|
||||
throw new common_1.HttpException('发送绘图指令失败、请联系管理员检测绘画配置!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
async pollComparisonResultDraw(id, drawInfo) {
|
||||
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl']));
|
||||
const mjKey = (await this.globalConfigService.getConfigs(['mjKey']));
|
||||
const startTime = Date.now();
|
||||
const POLL_INTERVAL = 5000;
|
||||
const TIMEOUT = 150000;
|
||||
let pollingCount = 0;
|
||||
let retryCount = 0;
|
||||
const MAX_RETRIES = 5;
|
||||
const { drawId } = drawInfo;
|
||||
try {
|
||||
while (Date.now() - startTime < TIMEOUT && retryCount < MAX_RETRIES) {
|
||||
await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL));
|
||||
try {
|
||||
const headers = {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"mj-api-secret": mjKey
|
||||
};
|
||||
const url = `${mjProxyUrl}/mj/task/${drawId}/fetch`;
|
||||
const res = await axios_1.default.get(url, { headers });
|
||||
const responses = res.data;
|
||||
const progress = responses.process;
|
||||
await this.midjourneyEntity.update({ id }, { progress: progress });
|
||||
if (responses.status === 'SUCCESS') {
|
||||
common_1.Logger.log(`绘制成功, URL: ${responses.imageUrl}`, 'MidjourneyService');
|
||||
return responses;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
retryCount++;
|
||||
common_1.Logger.error(`轮询过程中发生错误: ${error}`, 'MidjourneyService');
|
||||
}
|
||||
isMatchSuccessful = drawRes && !drawRes.edited_timestamp;
|
||||
pollingCount++;
|
||||
}
|
||||
if (!drawRes) {
|
||||
await this.updateDrawStatus(drawInfo.id, midjourney_constant_1.MidjourneyStatusEnum.DRAWTIMEOUT);
|
||||
throw new common_1.HttpException('绘画超时,请稍后再试!', common_1.HttpStatus.BAD_REQUEST);
|
||||
if (retryCount >= MAX_RETRIES) {
|
||||
await this.updateDrawStatus(id, midjourney_constant_1.MidjourneyStatusEnum.DRAWFAIL);
|
||||
throw new common_1.HttpException('轮询失败次数过多,请稍后再试!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
const endTime = Date.now();
|
||||
return Object.assign(Object.assign({}, drawRes), { durationSpent: Math.floor((endTime - startTime) / 1000) });
|
||||
common_1.Logger.error('绘画超时,请稍后再试!', 'MidjourneyService');
|
||||
await this.updateDrawStatus(id, midjourney_constant_1.MidjourneyStatusEnum.DRAWFAIL);
|
||||
throw new common_1.HttpException('绘画超时,请稍后再试!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
catch (error) {
|
||||
console.log('获取图片列表结果失败: ', error);
|
||||
}
|
||||
}
|
||||
async pollComparisonResultUpscale(drawInfo) {
|
||||
common_1.Logger.debug(`开始查询放大图片信息`, 'MidjourneyService');
|
||||
const startTime = Date.now();
|
||||
const { message_id, custom_id, randomDrawId, orderId } = drawInfo;
|
||||
let enlargeImgDetail = null;
|
||||
let pollingCount = 0;
|
||||
while (!enlargeImgDetail && pollingCount < 10) {
|
||||
common_1.Logger.debug(`开始比对放大图片第${pollingCount + 1}次`, 'MidjourneyService');
|
||||
enlargeImgDetail = await this.findCurrentEnlargeImgResult(randomDrawId, orderId);
|
||||
await new Promise((resolve) => setTimeout(resolve, Math.floor(Math.random() * (5000 - 3000 + 1)) + 3000));
|
||||
pollingCount++;
|
||||
}
|
||||
if (!enlargeImgDetail) {
|
||||
await this.updateDrawStatus(drawInfo.id, midjourney_constant_1.MidjourneyStatusEnum.DRAWTIMEOUT);
|
||||
throw new common_1.HttpException('放大图片超时,请稍后再试!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
const endTime = Date.now();
|
||||
return Object.assign(Object.assign({}, enlargeImgDetail), { durationSpent: Math.floor((endTime - startTime) / 1000) });
|
||||
}
|
||||
async pollComparisonResultReGenerate(drawInfo) {
|
||||
common_1.Logger.debug(`开始查询重复绘制的图片信息`, 'MidjourneyService');
|
||||
const TIMEOUT = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 150000;
|
||||
const startTime = Date.now();
|
||||
const { message_id, custom_id, randomDrawId, orderId } = drawInfo;
|
||||
let reGenerateImgDetail = null;
|
||||
let pollingTime = 0;
|
||||
let count = 0;
|
||||
while (!reGenerateImgDetail && pollingTime < TIMEOUT) {
|
||||
common_1.Logger.debug(`开始比对重新绘制图片第${count + 1}次`, 'MidjourneyService');
|
||||
reGenerateImgDetail = await this.findCurrentReGenerateImgResult(randomDrawId, message_id);
|
||||
const t = Math.floor(Math.random() * (5000 - 3000 + 1)) + 8000;
|
||||
await new Promise((resolve) => setTimeout(resolve, t));
|
||||
pollingTime += t;
|
||||
count++;
|
||||
}
|
||||
if (!reGenerateImgDetail) {
|
||||
await this.updateDrawStatus(drawInfo.id, midjourney_constant_1.MidjourneyStatusEnum.DRAWTIMEOUT);
|
||||
throw new common_1.HttpException('重新绘制图片超时,请稍后再试!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
const endTime = Date.now();
|
||||
return Object.assign(Object.assign({}, reGenerateImgDetail), { durationSpent: Math.floor((endTime - startTime) / 1000) });
|
||||
}
|
||||
async pollComparisonResultVary(drawInfo) {
|
||||
common_1.Logger.debug(`开始查询单张图片增强的图片信息`, 'MidjourneyService');
|
||||
const TIMEOUT = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 150000;
|
||||
const startTime = Date.now();
|
||||
const { message_id, custom_id, randomDrawId, orderId } = drawInfo;
|
||||
let varyImgDetail = null;
|
||||
let pollingTime = 0;
|
||||
let count = 0;
|
||||
while (!varyImgDetail && pollingTime < TIMEOUT) {
|
||||
common_1.Logger.debug(`开始单张图片增强第${count + 1}次`, 'MidjourneyService');
|
||||
varyImgDetail = await this.findCurrentVaryImgResult(randomDrawId, message_id);
|
||||
const t = Math.floor(Math.random() * (5000 - 3000 + 1)) + 8000;
|
||||
await new Promise((resolve) => setTimeout(resolve, t));
|
||||
pollingTime += t;
|
||||
count++;
|
||||
}
|
||||
if (!varyImgDetail) {
|
||||
await this.updateDrawStatus(drawInfo.id, midjourney_constant_1.MidjourneyStatusEnum.DRAWTIMEOUT);
|
||||
throw new common_1.HttpException('单张图片增强超时,请稍后再试!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
const endTime = Date.now();
|
||||
return Object.assign(Object.assign({}, varyImgDetail), { durationSpent: Math.floor((endTime - startTime) / 1000) });
|
||||
}
|
||||
async pollComparisonResultZoom(drawInfo) {
|
||||
common_1.Logger.debug(`开始查询单张图片缩放的图片信息`, 'MidjourneyService');
|
||||
const TIMEOUT = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 150000;
|
||||
const startTime = Date.now();
|
||||
const { message_id, custom_id, randomDrawId, orderId } = drawInfo;
|
||||
let zoomImgDetail = null;
|
||||
let pollingTime = 0;
|
||||
let count = 0;
|
||||
while (!zoomImgDetail && pollingTime < TIMEOUT) {
|
||||
common_1.Logger.debug(`开始单张图片缩放第${count + 1}次`, 'MidjourneyService');
|
||||
zoomImgDetail = await this.findCurrentZoomImgResult(randomDrawId, message_id);
|
||||
const t = Math.floor(Math.random() * (5000 - 3000 + 1)) + 8000;
|
||||
await new Promise((resolve) => setTimeout(resolve, t));
|
||||
pollingTime += t;
|
||||
count++;
|
||||
}
|
||||
if (!zoomImgDetail) {
|
||||
await this.updateDrawStatus(drawInfo.id, midjourney_constant_1.MidjourneyStatusEnum.DRAWTIMEOUT);
|
||||
throw new common_1.HttpException('单张图片缩放超时,请稍后再试!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
const endTime = Date.now();
|
||||
return Object.assign(Object.assign({}, zoomImgDetail), { durationSpent: Math.floor((endTime - startTime) / 1000) });
|
||||
}
|
||||
async pollComparisonResultVariation(drawInfo) {
|
||||
common_1.Logger.debug(`开始轮询单张变换图片结果`, 'MidjourneyService');
|
||||
let variationImgDetail = null;
|
||||
const startTime = Date.now();
|
||||
while (!variationImgDetail) {
|
||||
common_1.Logger.debug(`变换图片获取中------>`, 'MidjourneyService');
|
||||
variationImgDetail = await this.findCurrentVariationImgResult(drawInfo.randomDrawId);
|
||||
const nextPollingDelay = 10000;
|
||||
await this.sleep(nextPollingDelay);
|
||||
const endTime = Date.now();
|
||||
const durationSpent = Math.floor(endTime - startTime);
|
||||
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 150000;
|
||||
const TIMEOUT = timeout;
|
||||
if (durationSpent >= TIMEOUT) {
|
||||
await this.updateDrawStatus(drawInfo.id, midjourney_constant_1.MidjourneyStatusEnum.DRAWTIMEOUT);
|
||||
throw new common_1.HttpException('变换当前图片超时!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
return Object.assign(Object.assign({}, variationImgDetail), { durationSpent: Math.floor(Date.now() - startTime) });
|
||||
}
|
||||
async findCurrentEnlargeImgResult(randomDrawId, orderId) {
|
||||
const messageList = await this.getMessageList();
|
||||
const histroyMessageIds = await this.getHistroyMessageIds(randomDrawId);
|
||||
const enlargeImgDetail = messageList.find((item) => {
|
||||
const { content } = item;
|
||||
if (!this.extractContent(content))
|
||||
return false;
|
||||
const { prompt, order } = this.extractContent(content);
|
||||
return content.includes(randomDrawId) && orderId === order && !histroyMessageIds.includes(item.id);
|
||||
});
|
||||
return enlargeImgDetail;
|
||||
}
|
||||
async findCurrentVariationImgResult(randomDrawId) {
|
||||
const messageList = await this.getMessageList();
|
||||
const histroyMessageIds = await this.getHistroyMessageIds(randomDrawId);
|
||||
const variationImgDetail = messageList.find((item) => {
|
||||
const { content } = item;
|
||||
return content.includes(randomDrawId) && !histroyMessageIds.includes(item.id) && this.isVariationsImage(content);
|
||||
});
|
||||
if (variationImgDetail) {
|
||||
if (this.lockPrompt.includes(randomDrawId)) {
|
||||
common_1.Logger.debug(`【变体图片】当前图片已经被锁定,等待同任务完成`, 'MidjourneyService');
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
this.lockPrompt.push(randomDrawId);
|
||||
}
|
||||
}
|
||||
return variationImgDetail;
|
||||
}
|
||||
async findCurrentReGenerateImgResult(randomDrawId, message_id) {
|
||||
const messageList = await this.getMessageList();
|
||||
const histroyMessageIds = await this.getHistroyMessageIds(randomDrawId);
|
||||
const reGenerateImgDetail = messageList.find((item) => {
|
||||
const { content } = item;
|
||||
return content.includes(randomDrawId) && !histroyMessageIds.includes(item.id) && item.id !== message_id && this.isReGenerateImage(content);
|
||||
});
|
||||
if (reGenerateImgDetail) {
|
||||
if (this.lockPrompt.includes(randomDrawId)) {
|
||||
common_1.Logger.debug(`【重新生成图片】当前图片已经被锁定,等待同任务完成`, 'MidjourneyService');
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
this.lockPrompt.push(randomDrawId);
|
||||
}
|
||||
}
|
||||
return reGenerateImgDetail;
|
||||
}
|
||||
async findCurrentZoomImgResult(randomDrawId, message_id) {
|
||||
const messageList = await this.getMessageList();
|
||||
const histroyMessageIds = await this.getHistroyMessageIds(randomDrawId);
|
||||
const reGenerateImgDetail = messageList.find((item) => {
|
||||
const { content } = item;
|
||||
return content.includes(randomDrawId) && !histroyMessageIds.includes(item.id) && item.id !== message_id && this.isZoomImage(content);
|
||||
});
|
||||
if (reGenerateImgDetail) {
|
||||
if (this.lockPrompt.includes(randomDrawId)) {
|
||||
common_1.Logger.debug(`【重新生成图片】当前图片已经被锁定,等待同任务完成`, 'MidjourneyService');
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
this.lockPrompt.push(randomDrawId);
|
||||
}
|
||||
}
|
||||
return reGenerateImgDetail;
|
||||
}
|
||||
async findCurrentVaryImgResult(randomDrawId, message_id) {
|
||||
const messageList = await this.getMessageList();
|
||||
const histroyMessageIds = await this.getHistroyMessageIds(randomDrawId);
|
||||
const varyImgDetail = messageList.find((item) => {
|
||||
const { content } = item;
|
||||
return content.includes(randomDrawId) && !histroyMessageIds.includes(item.id) && item.id !== message_id && this.isVaryImage(content);
|
||||
});
|
||||
if (varyImgDetail) {
|
||||
if (this.lockPrompt.includes(randomDrawId)) {
|
||||
common_1.Logger.debug(`【单张图片增强】当前图片已经被锁定,等待同任务完成`, 'MidjourneyService');
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
this.lockPrompt.push(randomDrawId);
|
||||
}
|
||||
}
|
||||
return varyImgDetail;
|
||||
}
|
||||
extractContent(str) {
|
||||
const promptMatch = str.match(/\*\*(.+?)\*\*/);
|
||||
const orderMatch = str.match(/- Image #(\d+)/);
|
||||
if (!promptMatch || !orderMatch) {
|
||||
return null;
|
||||
}
|
||||
const prompt = promptMatch[1];
|
||||
const order = parseInt(orderMatch[1]);
|
||||
return { prompt, order };
|
||||
}
|
||||
async findCurrentPromptResult(randomDrawId) {
|
||||
const histroyMessageIds = await this.getHistroyMessageIds(randomDrawId);
|
||||
const messageList = await this.getMessageList();
|
||||
if (!messageList || !messageList.length)
|
||||
return;
|
||||
const matchingItem = messageList.find((item) => {
|
||||
const { attachments = [], content, edited_timestamp } = item;
|
||||
return content.includes(randomDrawId) && attachments.length > 0 && !histroyMessageIds.includes(item === null || item === void 0 ? void 0 : item.id);
|
||||
});
|
||||
return matchingItem || null;
|
||||
}
|
||||
isVariationsImage(str) {
|
||||
const regex = /- Variations/;
|
||||
return regex.test(str);
|
||||
}
|
||||
isSingleImage(str) {
|
||||
const regex = /Image #\d+/;
|
||||
return regex.test(str);
|
||||
}
|
||||
isReGenerateImage(str) {
|
||||
return !this.isVariationsImage(str) && !this.isSingleImage(str);
|
||||
}
|
||||
isVaryImage(str) {
|
||||
const regex = /- Variations \(.*?\)/;
|
||||
return regex.test(str);
|
||||
}
|
||||
isZoomImage(str) {
|
||||
const regex = /- Zoom Out/;
|
||||
return regex.test(str);
|
||||
}
|
||||
async getMjDefaultParams() {
|
||||
const configs = await this.globalConfigService.getConfigs([
|
||||
'mjId',
|
||||
'mjApplicationId',
|
||||
'mjGuildId',
|
||||
'mjChannelId',
|
||||
'mjSessionId',
|
||||
'mjVersion',
|
||||
'mjAuthorization',
|
||||
'mjRateLimit',
|
||||
'mjProxy',
|
||||
]);
|
||||
const params = {
|
||||
application_id: configs.mjApplicationId,
|
||||
guild_id: configs.mjGuildId,
|
||||
channel_id: configs.mjChannelId,
|
||||
session_id: configs.mjSessionId,
|
||||
version: configs.mjVersion,
|
||||
id: configs.mjId,
|
||||
authorization: configs.mjAuthorization,
|
||||
mjRateLimit: configs.mjRateLimit,
|
||||
mjProxy: configs.mjProxy || 0,
|
||||
};
|
||||
return params;
|
||||
}
|
||||
async getMessageList() {
|
||||
try {
|
||||
const { application_id, guild_id, channel_id, session_id, version, id, authorization, mjProxy } = await this.getMjDefaultParams();
|
||||
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl'])) || 'http://172.247.48.137:8000';
|
||||
const url = mjProxy == 1 ? `${mjProxyUrl}/mj/list?channel_id=${channel_id}` : `https://discord.com/api/v9/channels/${channel_id}/messages?limit=50`;
|
||||
const headers = { authorization };
|
||||
const response = await axios_1.default.get(url, { headers });
|
||||
return response.data;
|
||||
}
|
||||
catch (error) {
|
||||
common_1.Logger.error('查询绘制结果失败: getMessageList', error, 'MidjourneyService');
|
||||
return [];
|
||||
}
|
||||
}
|
||||
parseProgress(content) {
|
||||
const regex = /\((\d+)%\)/;
|
||||
const match = content.match(regex);
|
||||
if (match) {
|
||||
return parseInt(match[1], 10);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
common_1.Logger.error('获取图片结果失败: ', error, 'MidjourneyService');
|
||||
await this.updateDrawStatus(id, midjourney_constant_1.MidjourneyStatusEnum.DRAWFAIL);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
removeEmoji(str) {
|
||||
@@ -633,19 +243,7 @@ let MidjourneyService = class MidjourneyService {
|
||||
order: { id: 'DESC' },
|
||||
take: size,
|
||||
skip: (page - 1) * size,
|
||||
});
|
||||
const mjProxyImgUrl = await this.globalConfigService.getConfigs(['mjProxyImgUrl']);
|
||||
rows.forEach((item) => {
|
||||
var _a, _b, _c, _d;
|
||||
try {
|
||||
const { extend, isSaveImg, fileInfo } = item;
|
||||
const originUrl = (_b = (_a = JSON.parse(extend)) === null || _a === void 0 ? void 0 : _a.attachments[0]) === null || _b === void 0 ? void 0 : _b.url;
|
||||
item.fileInfo = this.formatFileInfo(fileInfo, isSaveImg, mjProxyImgUrl, originUrl);
|
||||
item.isGroup = ((_d = (_c = JSON.parse(extend)) === null || _c === void 0 ? void 0 : _c.components[0]) === null || _d === void 0 ? void 0 : _d.components[0].label) === "U1";
|
||||
item.originUrl = originUrl;
|
||||
}
|
||||
catch (error) {
|
||||
}
|
||||
select: ['id', 'userId', 'prompt', 'extraParam', 'fullPrompt', 'rec', 'orderId', 'drawId', 'drawUrl', 'drawRatio', 'isDelete', 'status', 'action']
|
||||
});
|
||||
const countQueue = await this.midjourneyEntity.count({ where: { isDelete: 0, status: (0, typeorm_2.In)([1, 2]) } });
|
||||
const data = { rows: (0, utils_1.formatCreateOrUpdateDate)(rows), count, countQueue };
|
||||
@@ -655,78 +253,40 @@ let MidjourneyService = class MidjourneyService {
|
||||
throw new common_1.HttpException('获取我得绘制列表失败', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
formatFileInfo(fileInfo, isSaveImg, mjProxyImgUrl, originUrl) {
|
||||
if (!fileInfo)
|
||||
return {};
|
||||
let parseFileInfo = null;
|
||||
try {
|
||||
parseFileInfo = JSON.parse(fileInfo);
|
||||
}
|
||||
catch (error) {
|
||||
parseFileInfo = null;
|
||||
}
|
||||
if (!parseFileInfo)
|
||||
return;
|
||||
const { url, filename, size, cosUrl, width, height } = parseFileInfo;
|
||||
const targetSize = 310;
|
||||
const imgType = cosUrl.includes('cos') ? 'tencent' : cosUrl.includes('oss') ? 'ali' : 'chevereto';
|
||||
let compress;
|
||||
let thumbImg;
|
||||
if (imgType === 'tencent') {
|
||||
const ratio = width / height;
|
||||
const targetHeight = Math.round(targetSize / ratio);
|
||||
thumbImg = cosUrl + `?imageView2/1/w/${targetSize}/h/${targetHeight}/q/55`;
|
||||
}
|
||||
if (imgType === 'ali') {
|
||||
const ratio = height / width;
|
||||
const targetWidth = Math.round(targetSize / ratio);
|
||||
thumbImg = cosUrl + `?x-oss-process=image/resize,w_${targetWidth}`;
|
||||
}
|
||||
if (imgType === 'chevereto') {
|
||||
thumbImg = cosUrl.replace(/\.png$/, '.md.png');
|
||||
}
|
||||
parseFileInfo.thumbImg = thumbImg;
|
||||
if (!isSaveImg) {
|
||||
const proxyImgUrl = `${mjProxyImgUrl}/mj/pipe?url=${originUrl}`;
|
||||
parseFileInfo.thumbImg = proxyImgUrl;
|
||||
parseFileInfo.cosUrl = proxyImgUrl;
|
||||
}
|
||||
return parseFileInfo;
|
||||
}
|
||||
async getDrawActionDetail(action, drawId, orderId) {
|
||||
const detailInfo = await this.midjourneyEntity.findOne({ where: { id: drawId } });
|
||||
if (!detailInfo)
|
||||
throw new common_1.HttpException('当前绘画信息不存在!', common_1.HttpStatus.BAD_REQUEST);
|
||||
const { extend, message_id, prompt, imgUrl, extraParam, randomDrawId } = detailInfo;
|
||||
const historyDetailDrawInfo = JSON.parse(extend);
|
||||
const { components = [] } = historyDetailDrawInfo;
|
||||
if (!components.length) {
|
||||
throw new common_1.HttpException('当前图片没有绘画信息、无法放大!', common_1.HttpStatus.BAD_REQUEST);
|
||||
const detailInfo = await this.midjourneyEntity.findOne({ where: { drawId: drawId } });
|
||||
const { extend, prompt, imgUrl, extraParam } = detailInfo;
|
||||
const extendObj = JSON.parse(extend);
|
||||
const buttons = extendObj.buttons || [];
|
||||
let currentButton;
|
||||
if (action === 'UPSCALE') {
|
||||
currentButton = buttons.find(button => {
|
||||
const isStandardUpscale = button.label.startsWith(`U${orderId}`);
|
||||
const isUpscaleUpscale = (orderId === 1 && /(Redo )?Upscale \(Subtle\)/.test(button.label)) ||
|
||||
(orderId === 2 && /(Redo )?Upscale \(Creative\)/.test(button.label));
|
||||
return isStandardUpscale || isUpscaleUpscale;
|
||||
});
|
||||
}
|
||||
let currentImgComponent = {};
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.UPSCALE) {
|
||||
currentImgComponent = components[0]['components'][orderId - 1];
|
||||
if (action === 'VARIATION') {
|
||||
currentButton = buttons.find(button => {
|
||||
const isStandardVariation = button.label.startsWith(`V${orderId}`);
|
||||
const isVaryVariation = (orderId === 1 && /Vary \(Strong\)/.test(button.label)) ||
|
||||
(orderId === 2 && /Vary \(Region\)/.test(button.label));
|
||||
return isStandardVariation || isVaryVariation;
|
||||
});
|
||||
}
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.VARIATION) {
|
||||
currentImgComponent = components[1]['components'][orderId - 1];
|
||||
if (action === 'REGENERATE') {
|
||||
currentButton = buttons.find(button => button.customId.startsWith("MJ::JOB::reroll::0::") && button.label === "");
|
||||
}
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.REGENERATE) {
|
||||
currentImgComponent = components[0]['components'][orderId - 1];
|
||||
if (action === 'ZOOM') {
|
||||
currentButton = buttons.find(button => (orderId === 1 && button.label === "Zoom Out 2x") ||
|
||||
(orderId === 2 && button.label === "Zoom Out 1.5x"));
|
||||
}
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.VARY) {
|
||||
currentImgComponent = components[0]['components'][orderId - 1];
|
||||
}
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.ZOOM) {
|
||||
currentImgComponent = components[1]['components'][orderId - 1];
|
||||
}
|
||||
const { custom_id } = currentImgComponent;
|
||||
return { custom_id, message_id, prompt, imgUrl, extraParam, randomDrawId };
|
||||
}
|
||||
async checkIsUpscale(custom_id) {
|
||||
const count = await this.midjourneyEntity.count({ where: { custom_id, status: midjourney_constant_1.MidjourneyStatusEnum.DRAWED } });
|
||||
if (count > 0) {
|
||||
throw new common_1.HttpException('当前图片已经放大过了!', common_1.HttpStatus.BAD_REQUEST);
|
||||
if (!currentButton) {
|
||||
throw new common_1.HttpException('所需绘画操作信息不存在!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
const { customId } = currentButton;
|
||||
return { customId, prompt, extraParam, drawId };
|
||||
}
|
||||
async deleteDraw(id, req) {
|
||||
const d = await this.midjourneyEntity.findOne({ where: { id, userId: req.user.id, isDelete: 0 } });
|
||||
@@ -759,7 +319,7 @@ let MidjourneyService = class MidjourneyService {
|
||||
}
|
||||
async drawSuccess(jobData) {
|
||||
const { id, userId, action } = jobData;
|
||||
const amount = action === 2 ? 1 : 4;
|
||||
const amount = action === "UPSCALE" ? 1 : 4;
|
||||
common_1.Logger.debug(`绘画完成,执行扣费,扣除费用:${amount}积分。`);
|
||||
await this.userBalanceService.refundMjBalance(userId, -amount);
|
||||
await this.midjourneyEntity.update({ id }, { status: 3 });
|
||||
@@ -786,26 +346,13 @@ let MidjourneyService = class MidjourneyService {
|
||||
order: { id: 'DESC' },
|
||||
take: size,
|
||||
skip: (page - 1) * size,
|
||||
select: ['fileInfo', 'extend', 'prompt', 'createdAt', 'id', 'extend', 'fullPrompt', 'rec', 'isSaveImg'],
|
||||
});
|
||||
const mjProxyImgUrl = await this.globalConfigService.getConfigs(['mjProxyImgUrl']);
|
||||
rows.forEach((item) => {
|
||||
var _a, _b, _c, _d;
|
||||
try {
|
||||
const { extend, isSaveImg, fileInfo } = item;
|
||||
const originUrl = (_b = (_a = JSON.parse(extend)) === null || _a === void 0 ? void 0 : _a.attachments[0]) === null || _b === void 0 ? void 0 : _b.url;
|
||||
item.fileInfo = this.formatFileInfo(fileInfo, isSaveImg, mjProxyImgUrl, originUrl);
|
||||
item.isGroup = ((_d = (_c = JSON.parse(extend)) === null || _c === void 0 ? void 0 : _c.components[0]) === null || _d === void 0 ? void 0 : _d.components[0].label) === "U1";
|
||||
item.originUrl = originUrl;
|
||||
}
|
||||
catch (error) {
|
||||
}
|
||||
select: ['id', 'drawId', 'drawUrl', 'drawRatio', 'prompt', 'fullPrompt', 'rec', 'createdAt', 'action', 'status'],
|
||||
});
|
||||
if (Number(size) === 999) {
|
||||
const data = {
|
||||
rows: rows.map((item) => {
|
||||
const { fileInfo, prompt, createdAt, id, fullPrompt, rec, originUrl } = item;
|
||||
return { fileInfo, prompt, createdAt, id, fullPrompt, rec, originUrl };
|
||||
const { id, drawId, drawUrl, drawRatio, prompt, fullPrompt, createdAt, rec, action, status } = item;
|
||||
return { id, drawId, drawUrl, drawRatio, prompt, fullPrompt, createdAt, rec, action, status };
|
||||
}),
|
||||
count,
|
||||
};
|
||||
@@ -840,19 +387,6 @@ let MidjourneyService = class MidjourneyService {
|
||||
rows.forEach((item) => {
|
||||
item.userInfo = userInfos.find((user) => user.id === item.userId);
|
||||
});
|
||||
const mjProxyImgUrl = await this.globalConfigService.getConfigs(['mjProxyImgUrl']);
|
||||
rows.forEach((item) => {
|
||||
var _a, _b, _c, _d;
|
||||
try {
|
||||
const { extend, isSaveImg, fileInfo } = item;
|
||||
const originUrl = (_b = (_a = JSON.parse(extend)) === null || _a === void 0 ? void 0 : _a.attachments[0]) === null || _b === void 0 ? void 0 : _b.url;
|
||||
item.fileInfo = this.formatFileInfo(fileInfo, isSaveImg, mjProxyImgUrl, originUrl);
|
||||
item.isGroup = ((_d = (_c = JSON.parse(extend)) === null || _c === void 0 ? void 0 : _c.components[0]) === null || _d === void 0 ? void 0 : _d.components[0].label) === "U1";
|
||||
item.originUrl = originUrl;
|
||||
}
|
||||
catch (error) {
|
||||
}
|
||||
});
|
||||
if (req.user.role !== 'super') {
|
||||
rows.forEach((item) => {
|
||||
if (item.userInfo && item.userInfo.email) {
|
||||
@@ -944,7 +478,6 @@ MidjourneyService = __decorate([
|
||||
typeorm_2.Repository,
|
||||
globalConfig_service_1.GlobalConfigService,
|
||||
upload_service_1.UploadService,
|
||||
badwords_service_1.BadwordsService,
|
||||
userBalance_service_1.UserBalanceService,
|
||||
redisCache_service_1.RedisCacheService])
|
||||
], MidjourneyService);
|
||||
|
||||
4
dist/modules/models/dto/setModel.dto.js
vendored
4
dist/modules/models/dto/setModel.dto.js
vendored
@@ -45,6 +45,10 @@ __decorate([
|
||||
(0, swagger_1.ApiProperty)({ example: 1, description: 'key的权重' }),
|
||||
__metadata("design:type", Number)
|
||||
], SetModelDto.prototype, "keyWeight", void 0);
|
||||
__decorate([
|
||||
(0, swagger_1.ApiProperty)({ example: 1, description: '模型排序' }),
|
||||
__metadata("design:type", Number)
|
||||
], SetModelDto.prototype, "modelOrder", void 0);
|
||||
__decorate([
|
||||
(0, swagger_1.ApiProperty)({ example: 4096, description: '模型支持的最大TOken数量', required: true }),
|
||||
__metadata("design:type", Number)
|
||||
|
||||
4
dist/modules/models/modelType.entity.js
vendored
4
dist/modules/models/modelType.entity.js
vendored
@@ -42,6 +42,10 @@ __decorate([
|
||||
(0, typeorm_1.Column)({ comment: '模型总计使用的token数量', default: 0 }),
|
||||
__metadata("design:type", Number)
|
||||
], ModelsTypeEntity.prototype, "useToken", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ comment: '模型排序', default: 1 }),
|
||||
__metadata("design:type", Number)
|
||||
], ModelsTypeEntity.prototype, "modelOrder", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ comment: '单词调用扣除的次数', default: 1 }),
|
||||
__metadata("design:type", Number)
|
||||
|
||||
4
dist/modules/models/models.entity.js
vendored
4
dist/modules/models/models.entity.js
vendored
@@ -50,6 +50,10 @@ __decorate([
|
||||
(0, typeorm_1.Column)({ comment: 'key权重', default: 1 }),
|
||||
__metadata("design:type", Number)
|
||||
], ModelsEntity.prototype, "keyWeight", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ comment: 'key权重', default: 1 }),
|
||||
__metadata("design:type", Number)
|
||||
], ModelsEntity.prototype, "modelOrder", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ comment: 'key的使用次数', default: 0 }),
|
||||
__metadata("design:type", Number)
|
||||
|
||||
36
dist/modules/models/models.service.js
vendored
36
dist/modules/models/models.service.js
vendored
@@ -18,7 +18,6 @@ const typeorm_1 = require("@nestjs/typeorm");
|
||||
const typeorm_2 = require("typeorm");
|
||||
const models_entity_1 = require("./models.entity");
|
||||
const status_constant_1 = require("../../common/constants/status.constant");
|
||||
const baidu_1 = require("../chatgpt/baidu");
|
||||
const utils_1 = require("../../common/utils");
|
||||
const modelType_entity_1 = require("./modelType.entity");
|
||||
let ModelsService = class ModelsService {
|
||||
@@ -33,7 +32,6 @@ let ModelsService = class ModelsService {
|
||||
}
|
||||
async onModuleInit() {
|
||||
await this.initCalcKey();
|
||||
this.refreshBaiduAccesstoken();
|
||||
}
|
||||
async initCalcKey() {
|
||||
this.keyPoolMap = {};
|
||||
@@ -114,9 +112,6 @@ let ModelsService = class ModelsService {
|
||||
if (Number(keyType !== 1)) {
|
||||
const res = await this.modelsEntity.save(params);
|
||||
await this.initCalcKey();
|
||||
if (keyType === 2) {
|
||||
this.refreshBaiduAccesstoken();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
else {
|
||||
@@ -162,6 +157,9 @@ let ModelsService = class ModelsService {
|
||||
key && (where.key = (0, typeorm_2.Like)(`%${key}%`));
|
||||
const [rows, count] = await this.modelsEntity.findAndCount({
|
||||
where: where,
|
||||
order: {
|
||||
modelOrder: 'ASC'
|
||||
},
|
||||
skip: (page - 1) * size,
|
||||
take: size,
|
||||
});
|
||||
@@ -176,10 +174,13 @@ let ModelsService = class ModelsService {
|
||||
async modelsList() {
|
||||
const cloneModelMaps = JSON.parse(JSON.stringify(this.modelMaps));
|
||||
Object.keys(cloneModelMaps).forEach(key => {
|
||||
cloneModelMaps[key] = Array.from(cloneModelMaps[key].map(t => {
|
||||
cloneModelMaps[key] = cloneModelMaps[key].sort((a, b) => a.modelOrder - b.modelOrder);
|
||||
cloneModelMaps[key] = Array.from(cloneModelMaps[key]
|
||||
.map(t => {
|
||||
const { modelName, model, deduct, deductType, maxRounds } = t;
|
||||
return { modelName, model, deduct, deductType, maxRounds };
|
||||
}).reduce((map, obj) => map.set(obj.modelName, obj), new Map()).values());
|
||||
})
|
||||
.reduce((map, obj) => map.set(obj.modelName, obj), new Map()).values());
|
||||
});
|
||||
return {
|
||||
modelTypeList: this.modelTypes,
|
||||
@@ -194,27 +195,6 @@ let ModelsService = class ModelsService {
|
||||
.where('id = :id', { id })
|
||||
.execute();
|
||||
}
|
||||
async refreshBaiduAccesstoken() {
|
||||
const allKeys = await this.modelsEntity.find({ where: { keyType: 2 } });
|
||||
const keysMap = {};
|
||||
allKeys.forEach(keyInfo => {
|
||||
const { key, secret } = keyInfo;
|
||||
if (!keysMap.key) {
|
||||
keysMap[key] = [{ keyInfo }];
|
||||
}
|
||||
else {
|
||||
keysMap[key].push(keyInfo);
|
||||
}
|
||||
});
|
||||
Object.keys(keysMap).forEach(async (key) => {
|
||||
const { secret, id } = keysMap[key][0]['keyInfo'];
|
||||
const accessToken = await (0, baidu_1.getAccessToken)(key, secret);
|
||||
await this.modelsEntity.update({ key }, { accessToken });
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.initCalcKey();
|
||||
}, 1000);
|
||||
}
|
||||
async getRandomDrawKey() {
|
||||
const drawkeys = await this.modelsEntity.find({ where: { isDraw: true, status: true } });
|
||||
if (!drawkeys.length) {
|
||||
|
||||
9
dist/modules/queue/dto/mjDraw.dto.js
vendored
9
dist/modules/queue/dto/mjDraw.dto.js
vendored
@@ -34,9 +34,9 @@ __decorate([
|
||||
__metadata("design:type", String)
|
||||
], MjDrawDto.prototype, "imgUrl", void 0);
|
||||
__decorate([
|
||||
(0, swagger_1.ApiProperty)({ example: 1, description: '绘画动作 绘图、放大、变换、图生图' }),
|
||||
(0, swagger_1.ApiProperty)({ example: 'IMAGINE', description: '任务类型,可用值:IMAGINE,UPSCALE,VARIATION,ZOOM,PAN,DESCRIBE,BLEND,SHORTEN,SWAP_FACE' }),
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
__metadata("design:type", Number)
|
||||
__metadata("design:type", String)
|
||||
], MjDrawDto.prototype, "action", void 0);
|
||||
__decorate([
|
||||
(0, swagger_1.ApiProperty)({ example: 1, description: '变体或者放大的序号' }),
|
||||
@@ -48,4 +48,9 @@ __decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
__metadata("design:type", Number)
|
||||
], MjDrawDto.prototype, "drawId", void 0);
|
||||
__decorate([
|
||||
(0, swagger_1.ApiProperty)({ example: 1, description: '任务ID' }),
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
__metadata("design:type", Number)
|
||||
], MjDrawDto.prototype, "taskId", void 0);
|
||||
exports.MjDrawDto = MjDrawDto;
|
||||
|
||||
66
dist/modules/queue/queue.service.js
vendored
66
dist/modules/queue/queue.service.js
vendored
@@ -17,7 +17,6 @@ const common_1 = require("@nestjs/common");
|
||||
const bull_1 = require("@nestjs/bull");
|
||||
const utils_1 = require("../../common/utils");
|
||||
const midjourney_service_1 = require("../midjourney/midjourney.service");
|
||||
const midjourney_constant_1 = require("../../common/constants/midjourney.constant");
|
||||
const userBalance_service_1 = require("../userBalance/userBalance.service");
|
||||
const globalConfig_service_1 = require("../globalConfig/globalConfig.service");
|
||||
let QueueService = class QueueService {
|
||||
@@ -33,68 +32,31 @@ let QueueService = class QueueService {
|
||||
await this.midjourneyService.cleanQueue();
|
||||
}
|
||||
async addMjDrawQueue(body, req) {
|
||||
const { prompt, imgUrl, extraParam, orderId, action = 1, drawId } = body;
|
||||
const { imgUrl, orderId, action, drawId } = body;
|
||||
await this.midjourneyService.checkLimit(req);
|
||||
await this.userBalanceService.validateBalance(req, 'mjDraw', action === 2 ? 1 : 4);
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.DRAW || action === midjourney_constant_1.MidjourneyActionEnum.GENERATE) {
|
||||
await this.userBalanceService.validateBalance(req, 'mjDraw', action === 'UPSCALE' ? 1 : 4);
|
||||
if (action === 'IMAGINE') {
|
||||
const randomDrawId = `${(0, utils_1.createRandomUid)()}`;
|
||||
const params = Object.assign(Object.assign({}, body), { userId: req.user.id, randomDrawId });
|
||||
const res = await this.midjourneyService.addDrawQueue(params);
|
||||
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 200000;
|
||||
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action: imgUrl ? 4 : 1, userId: req.user.id }, { delay: 1000, timeout: +timeout });
|
||||
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action: action, userId: req.user.id }, { delay: 1000, timeout: +timeout });
|
||||
this.jobIds.push(job.id);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
const { orderId, action, drawId } = body;
|
||||
const actionDetail = await this.midjourneyService.getDrawActionDetail(action, drawId, orderId);
|
||||
const params = Object.assign(Object.assign(Object.assign({}, body), { userId: req.user.id }), actionDetail);
|
||||
const res = await this.midjourneyService.addDrawQueue(params);
|
||||
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 200000;
|
||||
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action, userId: req.user.id }, { delay: 1000, timeout: +timeout });
|
||||
this.jobIds.push(job.id);
|
||||
return;
|
||||
}
|
||||
if (!drawId || !orderId) {
|
||||
throw new common_1.HttpException('缺少必要参数!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.UPSCALE) {
|
||||
const actionDetail = await this.midjourneyService.getDrawActionDetail(action, drawId, orderId);
|
||||
const { custom_id } = actionDetail;
|
||||
await this.midjourneyService.checkIsUpscale(custom_id);
|
||||
const params = Object.assign(Object.assign(Object.assign({}, body), { userId: req.user.id }), actionDetail);
|
||||
const res = await this.midjourneyService.addDrawQueue(params);
|
||||
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 200000;
|
||||
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action, userId: req.user.id }, { delay: 1000, timeout: +timeout });
|
||||
this.jobIds.push(job.id);
|
||||
return;
|
||||
}
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.VARIATION) {
|
||||
const actionDetail = await this.midjourneyService.getDrawActionDetail(action, drawId, orderId);
|
||||
const params = Object.assign(Object.assign(Object.assign({}, body), { userId: req.user.id }), actionDetail);
|
||||
const res = await this.midjourneyService.addDrawQueue(params);
|
||||
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 200000;
|
||||
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action, userId: req.user.id }, { delay: 1000, timeout: +timeout });
|
||||
this.jobIds.push(job.id);
|
||||
return;
|
||||
}
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.REGENERATE) {
|
||||
const actionDetail = await this.midjourneyService.getDrawActionDetail(action, drawId, orderId);
|
||||
const params = Object.assign(Object.assign(Object.assign({}, body), { userId: req.user.id }), actionDetail);
|
||||
const res = await this.midjourneyService.addDrawQueue(params);
|
||||
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 200000;
|
||||
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action, userId: req.user.id }, { delay: 1000, timeout: +timeout });
|
||||
this.jobIds.push(job.id);
|
||||
return;
|
||||
}
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.VARY) {
|
||||
const actionDetail = await this.midjourneyService.getDrawActionDetail(action, drawId, orderId);
|
||||
const params = Object.assign(Object.assign(Object.assign({}, body), { userId: req.user.id }), actionDetail);
|
||||
const res = await this.midjourneyService.addDrawQueue(params);
|
||||
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 200000;
|
||||
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action, userId: req.user.id }, { delay: 1000, timeout: +timeout });
|
||||
this.jobIds.push(job.id);
|
||||
return;
|
||||
}
|
||||
if (action === midjourney_constant_1.MidjourneyActionEnum.ZOOM) {
|
||||
const actionDetail = await this.midjourneyService.getDrawActionDetail(action, drawId, orderId);
|
||||
const params = Object.assign(Object.assign(Object.assign({}, body), { userId: req.user.id }), actionDetail);
|
||||
const res = await this.midjourneyService.addDrawQueue(params);
|
||||
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 200000;
|
||||
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action, userId: req.user.id }, { delay: 1000, timeout: +timeout });
|
||||
this.jobIds.push(job.id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
async getQueue() {
|
||||
return { jobIds: this.jobIds };
|
||||
|
||||
9
dist/modules/task/task.service.js
vendored
9
dist/modules/task/task.service.js
vendored
@@ -44,9 +44,6 @@ let TaskService = class TaskService {
|
||||
});
|
||||
});
|
||||
}
|
||||
refreshBaiduAccesstoken() {
|
||||
this.modelsService.refreshBaiduAccesstoken();
|
||||
}
|
||||
};
|
||||
__decorate([
|
||||
(0, schedule_1.Cron)(schedule_1.CronExpression.EVERY_HOUR),
|
||||
@@ -60,12 +57,6 @@ __decorate([
|
||||
__metadata("design:paramtypes", []),
|
||||
__metadata("design:returntype", Promise)
|
||||
], TaskService.prototype, "checkUserMemerExpire", null);
|
||||
__decorate([
|
||||
(0, schedule_1.Cron)('0 0 */5 * *'),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", []),
|
||||
__metadata("design:returntype", void 0)
|
||||
], TaskService.prototype, "refreshBaiduAccesstoken", null);
|
||||
TaskService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__param(0, (0, typeorm_1.InjectRepository)(userBalance_entity_1.UserBalanceEntity)),
|
||||
|
||||
47
dist/modules/upload/upload.service.js
vendored
47
dist/modules/upload/upload.service.js
vendored
@@ -27,19 +27,30 @@ let UploadService = class UploadService {
|
||||
const { filename: name, originalname, buffer, dir = 'ai', mimetype } = file;
|
||||
const fileTyle = mimetype ? mimetype.split('/')[1] : '';
|
||||
const filename = originalname || name;
|
||||
common_1.Logger.debug(`准备上传文件: ${filename}, 类型: ${fileTyle}`, 'UploadService');
|
||||
const { tencentCosStatus = 0, aliOssStatus = 0, cheveretoStatus = 0, } = await this.globalConfigService.getConfigs(['tencentCosStatus', 'aliOssStatus', 'cheveretoStatus']);
|
||||
common_1.Logger.debug(`上传配置状态 - 腾讯云: ${tencentCosStatus}, 阿里云: ${aliOssStatus}, Chevereto: ${cheveretoStatus}`, 'UploadService');
|
||||
if (!Number(tencentCosStatus) && !Number(aliOssStatus) && !Number(cheveretoStatus)) {
|
||||
throw new common_1.HttpException('请先前往后台配置上传图片的方式', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (Number(tencentCosStatus)) {
|
||||
return this.uploadFileByTencentCos({ filename, buffer, dir, fileTyle });
|
||||
try {
|
||||
if (Number(tencentCosStatus)) {
|
||||
common_1.Logger.debug(`使用腾讯云COS上传`, 'UploadService');
|
||||
return await this.uploadFileByTencentCos({ filename, buffer, dir, fileTyle });
|
||||
}
|
||||
if (Number(aliOssStatus)) {
|
||||
common_1.Logger.debug(`使用阿里云OSS上传`, 'UploadService');
|
||||
return await this.uploadFileByAliOss({ filename, buffer, dir, fileTyle });
|
||||
}
|
||||
if (Number(cheveretoStatus)) {
|
||||
common_1.Logger.debug(`使用Chevereto上传`, 'UploadService');
|
||||
const { filename, buffer: fromBuffer, dir } = file;
|
||||
return await this.uploadFileByChevereto({ filename, buffer: fromBuffer.toString('base64'), dir, fileTyle });
|
||||
}
|
||||
}
|
||||
if (Number(aliOssStatus)) {
|
||||
return await this.uploadFileByAliOss({ filename, buffer, dir, fileTyle });
|
||||
}
|
||||
if (Number(cheveretoStatus)) {
|
||||
const { filename, buffer: fromBuffer, dir } = file;
|
||||
return await this.uploadFileByChevereto({ filename, buffer: fromBuffer.toString('base64'), dir, fileTyle });
|
||||
catch (error) {
|
||||
common_1.Logger.error(`上传失败: ${error.message}`, 'UploadService');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
async getUploadType() {
|
||||
@@ -108,24 +119,8 @@ let UploadService = class UploadService {
|
||||
this.tencentCos = new TENCENTCOS({ SecretId, SecretKey, FileParallelLimit: 10 });
|
||||
try {
|
||||
const proxyMj = (await this.globalConfigService.getConfigs(['mjProxy'])) || 0;
|
||||
if (Number(proxyMj) === 1) {
|
||||
const data = { cosType: 'tencent', url, cosParams: { Bucket, Region, SecretId, SecretKey } };
|
||||
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl'])) || 'http://172.247.48.137:8000';
|
||||
const res = await axios_1.default.post(`${mjProxyUrl}/mj/replaceUpload`, data);
|
||||
if (!res.data)
|
||||
throw new common_1.HttpException('上传图片失败[ten][url]', common_1.HttpStatus.BAD_REQUEST);
|
||||
let locationUrl = res.data.replace(/^(http:\/\/|https:\/\/|\/\/|)(.*)/, 'https://$2');
|
||||
const { acceleratedDomain } = await this.getUploadConfig('tencent');
|
||||
if (acceleratedDomain) {
|
||||
locationUrl = locationUrl.replace(/^(https:\/\/[^/]+)(\/.*)$/, `https://${acceleratedDomain}$2`);
|
||||
console.log('当前已开启全球加速----------------->');
|
||||
}
|
||||
return locationUrl;
|
||||
}
|
||||
else {
|
||||
const buffer = await this.getBufferFromUrl(url);
|
||||
return await this.uploadFileByTencentCos({ filename, buffer, dir, fileTyle: '' });
|
||||
}
|
||||
const buffer = await this.getBufferFromUrl(url);
|
||||
return await this.uploadFileByTencentCos({ filename, buffer, dir, fileTyle: '' });
|
||||
}
|
||||
catch (error) {
|
||||
console.log('TODO->error: ', error);
|
||||
|
||||
Reference in New Issue
Block a user