Files
FastGPT/src/service/events/generateVector.ts

108 lines
2.9 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 (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);
throw new Error(error?.message);
}
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),
'rawVector',
JSON.stringify(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?.data?.error?.type === 'insufficient_quota') {
console.log('api 余额不足,删除 redis 模型数据');
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);
}, 4000);
}
}