Files
FastGPT/src/service/events/generateVector.ts
2023-04-17 10:41:35 +08:00

118 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { connectRedis } from '../redis';
import { VecModelDataIdx } from '@/constants/redis';
import { vectorToBuffer } from '@/utils/tools';
import { ModelDataStatusEnum } from '@/constants/redis';
import { openaiCreateEmbedding, getOpenApiKey } from '../utils/openai';
export async function generateVector(next = false): Promise<any> {
if (process.env.queueTask !== '1') {
fetch(process.env.parentUrl || '');
return;
}
if (global.generatingVector && !next) return;
global.generatingVector = true;
let dataId = null;
try {
const redis = await connectRedis();
// 从找出一个 status = waiting 的数据
const searchRes = await redis.ft.search(
VecModelDataIdx,
`@status:{${ModelDataStatusEnum.waiting}}`,
{
RETURN: ['q', 'userId'],
LIMIT: {
from: 0,
size: 1
}
}
);
if (searchRes.total === 0) {
console.log('没有需要生成 【向量】 的数据');
global.generatingVector = false;
return;
}
const dataItem: { id: string; q: string; userId: string } = {
id: searchRes.documents[0].id,
q: String(searchRes.documents[0]?.value?.q || ''),
userId: String(searchRes.documents[0]?.value?.userId || '')
};
dataId = dataItem.id;
// 获取 openapi Key
let userApiKey, systemKey;
try {
const res = await getOpenApiKey(dataItem.userId);
userApiKey = res.userApiKey;
systemKey = res.systemKey;
} catch (error: any) {
if (error?.code === 501) {
await redis.del(dataItem.id);
generateVector(true);
return;
}
throw new Error('获取 openai key 失败');
}
// 生成词向量
const { vector } = await openaiCreateEmbedding({
text: dataItem.q,
userId: dataItem.userId,
isPay: !userApiKey,
apiKey: userApiKey || systemKey
});
// 更新 redis 向量和状态数据
await redis.sendCommand([
'HMSET',
dataItem.id,
'vector',
vectorToBuffer(vector),
'status',
ModelDataStatusEnum.ready
]);
console.log(`生成向量成功: ${dataItem.id}`);
generateVector(true);
} catch (error: any) {
// log
if (error?.response) {
console.log('openai error: 生成向量错误');
console.log(error.response?.status, error.response?.statusText, error.response?.data);
} else {
console.log('生成向量错误:', error);
}
// 没有余额或者凭证错误时,拒绝任务
if (
dataId &&
(+error.response?.status === 401 ||
error?.response?.data?.error?.type === 'insufficient_quota')
) {
console.log('删除向量生成任务记录');
const redis = await connectRedis();
redis.del(dataId);
generateVector(true);
return;
}
if (error?.response?.statusText === 'Too Many Requests') {
console.log('生成向量次数限制1分钟后尝试');
// 限制次数1分钟后再试
setTimeout(() => {
generateVector(true);
}, 60000);
return;
}
setTimeout(() => {
generateVector(true);
}, 2000);
}
}