mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 21:13:50 +00:00
feat: csv导入去重;文档说明
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
接受一个csv文件,表格头包含 question 和 answer。question 代表问题,answer 代表答案。
|
接受一个csv文件,表格头包含 question 和 answer。question 代表问题,answer 代表答案。
|
||||||
|
导入前会进行去重,如果问题和答案完全相同,则不会被导入,所以最终导入的内容可能会比文件的内容少。
|
||||||
| question | answer |
|
| question | answer |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 什么是 laf | laf 是一个云函数开发平台…… |
|
| 什么是 laf | laf 是一个云函数开发平台…… |
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
## Fast GPT V2.5
|
## Fast GPT V2.7
|
||||||
* 内容压缩,替换中文标点符号和多余符号,减少一些上下文tokens。
|
* FastGpt Api 允许你将 Fast Gpt 的部分功能通过 api 的形式,将知识库接入到自己的应用中,例如:飞书、企业微信、客服助手.
|
||||||
* 优化 QA 拆分记账。
|
* 通过 csv 文件导入和导出你的问答对。你可以将你的 csv 文件放置在飞书文档上,以便团队共享。
|
@@ -91,7 +91,7 @@ export const postModelDataSplitData = (data: { modelId: string; text: string; pr
|
|||||||
* json导入数据
|
* json导入数据
|
||||||
*/
|
*/
|
||||||
export const postModelDataCsvData = (modelId: string, data: string[][]) =>
|
export const postModelDataCsvData = (modelId: string, data: string[][]) =>
|
||||||
POST(`/model/data/pushModelDataCsv`, { modelId, data: data });
|
POST<number>(`/model/data/pushModelDataCsv`, { modelId, data: data });
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新模型数据
|
* 更新模型数据
|
||||||
|
@@ -3,9 +3,9 @@ import { jsonRes } from '@/service/response';
|
|||||||
import { connectToDatabase, Model } from '@/service/mongo';
|
import { connectToDatabase, Model } from '@/service/mongo';
|
||||||
import { authToken } from '@/service/utils/tools';
|
import { authToken } from '@/service/utils/tools';
|
||||||
import { generateVector } from '@/service/events/generateVector';
|
import { generateVector } from '@/service/events/generateVector';
|
||||||
import { vectorToBuffer, formatVector } from '@/utils/tools';
|
|
||||||
import { connectRedis } from '@/service/redis';
|
import { connectRedis } from '@/service/redis';
|
||||||
import { VecModelDataPrefix, ModelDataStatusEnum } from '@/constants/redis';
|
import { VecModelDataPrefix, ModelDataStatusEnum } from '@/constants/redis';
|
||||||
|
import { VecModelDataIdx } from '@/constants/redis';
|
||||||
import { customAlphabet } from 'nanoid';
|
import { customAlphabet } from 'nanoid';
|
||||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 12);
|
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 12);
|
||||||
|
|
||||||
@@ -41,9 +41,35 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
throw new Error('无权操作该模型');
|
throw new Error('无权操作该模型');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 去重
|
||||||
|
const searchRes = await Promise.allSettled(
|
||||||
|
data.map(async ([q, a]) => {
|
||||||
|
try {
|
||||||
|
q = q.replace(/\\n/g, '\n');
|
||||||
|
a = a.replace(/\\n/g, '\n');
|
||||||
|
const redisSearch = await redis.ft.search(VecModelDataIdx, `@q:${q} @text:${a}`, {
|
||||||
|
RETURN: ['q', 'text']
|
||||||
|
});
|
||||||
|
if (redisSearch.total > 0) {
|
||||||
|
return Promise.reject('已经存在');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
error;
|
||||||
|
}
|
||||||
|
return Promise.resolve({
|
||||||
|
q,
|
||||||
|
a
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const filterData = searchRes
|
||||||
|
.filter((item) => item.status === 'fulfilled')
|
||||||
|
.map<{ q: string; a: string }>((item: any) => item.value);
|
||||||
|
|
||||||
// 插入 redis
|
// 插入 redis
|
||||||
const insertRedisRes = await Promise.allSettled(
|
const insertRedisRes = await Promise.allSettled(
|
||||||
data.map((item) => {
|
filterData.map((item) => {
|
||||||
return redis.sendCommand([
|
return redis.sendCommand([
|
||||||
'HMSET',
|
'HMSET',
|
||||||
`${VecModelDataPrefix}:${nanoid()}`,
|
`${VecModelDataPrefix}:${nanoid()}`,
|
||||||
@@ -52,9 +78,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
'modelId',
|
'modelId',
|
||||||
String(modelId),
|
String(modelId),
|
||||||
'q',
|
'q',
|
||||||
item[0],
|
item.q,
|
||||||
'text',
|
'text',
|
||||||
item[1],
|
item.a,
|
||||||
'status',
|
'status',
|
||||||
ModelDataStatusEnum.waiting
|
ModelDataStatusEnum.waiting
|
||||||
]);
|
]);
|
||||||
@@ -64,7 +90,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
generateVector();
|
generateVector();
|
||||||
|
|
||||||
jsonRes(res, {
|
jsonRes(res, {
|
||||||
data: insertRedisRes.filter((item) => item.status === 'rejected').length
|
data: insertRedisRes.filter((item) => item.status === 'fulfilled').length
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
jsonRes(res, {
|
jsonRes(res, {
|
||||||
|
@@ -64,10 +64,11 @@ const SelectJsonModal = ({
|
|||||||
const { mutate, isLoading } = useMutation({
|
const { mutate, isLoading } = useMutation({
|
||||||
mutationFn: async () => {
|
mutationFn: async () => {
|
||||||
if (!fileData) return;
|
if (!fileData) return;
|
||||||
await postModelDataCsvData(modelId, fileData);
|
const res = await postModelDataCsvData(modelId, fileData);
|
||||||
toast({
|
toast({
|
||||||
title: '导入数据成功,需要一段时间训练',
|
title: `导入数据成功,最终导入: ${res || 0} 条数据。需要一段时间训练`,
|
||||||
status: 'success'
|
status: 'success',
|
||||||
|
duration: 4000
|
||||||
});
|
});
|
||||||
onClose();
|
onClose();
|
||||||
onSuccess();
|
onSuccess();
|
||||||
@@ -90,7 +91,7 @@ const SelectJsonModal = ({
|
|||||||
<ModalCloseButton />
|
<ModalCloseButton />
|
||||||
|
|
||||||
<ModalBody h={'100%'} display={['block', 'flex']} fontSize={'sm'} overflowY={'auto'}>
|
<ModalBody h={'100%'} display={['block', 'flex']} fontSize={'sm'} overflowY={'auto'}>
|
||||||
<Box flex={'1 0 0'} w={['100%', 0]} mr={[0, 4]} mb={[4, 0]}>
|
<Box flex={'2 0 0'} w={['100%', 0]} mr={[0, 4]} mb={[4, 0]}>
|
||||||
<Markdown source={intro} />
|
<Markdown source={intro} />
|
||||||
<Box
|
<Box
|
||||||
my={3}
|
my={3}
|
||||||
@@ -115,7 +116,7 @@ const SelectJsonModal = ({
|
|||||||
<Box ml={4}>一共 {fileData.length} 组数据</Box>
|
<Box ml={4}>一共 {fileData.length} 组数据</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
<Box flex={'2 0 0'} h={'100%'} overflow={'auto'} p={2} backgroundColor={'blackAlpha.50'}>
|
<Box flex={'3 0 0'} h={'100%'} overflow={'auto'} p={2} backgroundColor={'blackAlpha.50'}>
|
||||||
{fileData.map((item, index) => (
|
{fileData.map((item, index) => (
|
||||||
<Box key={index}>
|
<Box key={index}>
|
||||||
<Box>
|
<Box>
|
||||||
|
@@ -55,10 +55,11 @@ const OpenApi = () => {
|
|||||||
<>
|
<>
|
||||||
<Card px={6} py={4} position={'relative'}>
|
<Card px={6} py={4} position={'relative'}>
|
||||||
<Box fontSize={'xl'} fontWeight={'bold'}>
|
<Box fontSize={'xl'} fontWeight={'bold'}>
|
||||||
Open Api
|
FastGpt Api
|
||||||
</Box>
|
</Box>
|
||||||
<Box fontSize={'sm'} mt={2}>
|
<Box fontSize={'sm'} mt={2}>
|
||||||
Open Api 允许你将 Fast Gpt 的部分功能通过 api 的形式接入到自己的应用中。请注意保管你的 Api
|
FastGpt Api 允许你将 Fast Gpt 的部分功能通过 api
|
||||||
|
的形式接入到自己的应用中,例如:飞书、企业微信、客服助手。请注意保管你的 Api
|
||||||
Key,不要泄露!
|
Key,不要泄露!
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
|
Reference in New Issue
Block a user