mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 21:13:50 +00:00
perf: 知识库录入
This commit is contained in:
@@ -119,20 +119,20 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
.select('text q')
|
||||
.then((res) => {
|
||||
if (!res) return '';
|
||||
const questions = res.q.map((item) => item.text).join(' ');
|
||||
// const questions = res.q.map((item) => item.text).join(' ');
|
||||
const answer = res.text;
|
||||
return `${questions} ${answer}`;
|
||||
return `${answer}`;
|
||||
});
|
||||
})
|
||||
)
|
||||
).filter((item) => item);
|
||||
|
||||
// textArr 筛选,最多 3000 tokens
|
||||
const systemPrompt = systemPromptFilter(textArr, 2800);
|
||||
const systemPrompt = systemPromptFilter(textArr, 3400);
|
||||
|
||||
prompts.unshift({
|
||||
obj: 'SYSTEM',
|
||||
value: `根据下面的知识回答问题: ${systemPrompt}`
|
||||
value: `${model.systemPrompt}。 我的知识库: "${systemPrompt}"`
|
||||
});
|
||||
|
||||
// 控制在 tokens 数量,防止超出
|
||||
|
@@ -190,91 +190,97 @@ const Chat = ({ chatId }: { chatId: string }) => {
|
||||
/**
|
||||
* 发送一个内容
|
||||
*/
|
||||
const sendPrompt = useCallback(async () => {
|
||||
const storeInput = inputVal;
|
||||
// 去除空行
|
||||
const val = inputVal
|
||||
.trim()
|
||||
.split('\n')
|
||||
.filter((val) => val)
|
||||
.join('\n');
|
||||
if (!chatData?.modelId || !val || !ChatBox.current || isChatting) {
|
||||
return;
|
||||
}
|
||||
const sendPrompt = useCallback(
|
||||
async (e?: React.MouseEvent<HTMLDivElement>) => {
|
||||
e?.stopPropagation();
|
||||
e?.preventDefault();
|
||||
|
||||
// 长度校验
|
||||
const tokens = encode(val).length;
|
||||
const model = modelList.find((item) => item.model === chatData.modelName);
|
||||
|
||||
if (model && tokens >= model.maxToken) {
|
||||
toast({
|
||||
title: '单次输入超出 4000 tokens',
|
||||
status: 'warning'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const newChatList: ChatSiteItemType[] = [
|
||||
...chatData.history,
|
||||
{
|
||||
obj: 'Human',
|
||||
value: val,
|
||||
status: 'finish'
|
||||
},
|
||||
{
|
||||
obj: 'AI',
|
||||
value: '',
|
||||
status: 'loading'
|
||||
const storeInput = inputVal;
|
||||
// 去除空行
|
||||
const val = inputVal
|
||||
.trim()
|
||||
.split('\n')
|
||||
.filter((val) => val)
|
||||
.join('\n');
|
||||
if (!chatData?.modelId || !val || !ChatBox.current || isChatting) {
|
||||
return;
|
||||
}
|
||||
];
|
||||
|
||||
// 插入内容
|
||||
setChatData((state) => ({
|
||||
...state,
|
||||
history: newChatList
|
||||
}));
|
||||
// 长度校验
|
||||
const tokens = encode(val).length;
|
||||
const model = modelList.find((item) => item.model === chatData.modelName);
|
||||
|
||||
// 清空输入内容
|
||||
resetInputVal('');
|
||||
scrollToBottom();
|
||||
|
||||
try {
|
||||
await gptChatPrompt(newChatList[newChatList.length - 2]);
|
||||
|
||||
// 如果是 Human 第一次发送,插入历史记录
|
||||
const humanChat = newChatList.filter((item) => item.obj === 'Human');
|
||||
if (humanChat.length === 1) {
|
||||
pushChatHistory({
|
||||
chatId,
|
||||
title: humanChat[0].value
|
||||
if (model && tokens >= model.maxToken) {
|
||||
toast({
|
||||
title: '单次输入超出 4000 tokens',
|
||||
status: 'warning'
|
||||
});
|
||||
return;
|
||||
}
|
||||
} catch (err: any) {
|
||||
toast({
|
||||
title: typeof err === 'string' ? err : err?.message || '聊天出错了~',
|
||||
status: 'warning',
|
||||
duration: 5000,
|
||||
isClosable: true
|
||||
});
|
||||
|
||||
resetInputVal(storeInput);
|
||||
const newChatList: ChatSiteItemType[] = [
|
||||
...chatData.history,
|
||||
{
|
||||
obj: 'Human',
|
||||
value: val,
|
||||
status: 'finish'
|
||||
},
|
||||
{
|
||||
obj: 'AI',
|
||||
value: '',
|
||||
status: 'loading'
|
||||
}
|
||||
];
|
||||
|
||||
// 插入内容
|
||||
setChatData((state) => ({
|
||||
...state,
|
||||
history: newChatList.slice(0, newChatList.length - 2)
|
||||
history: newChatList
|
||||
}));
|
||||
}
|
||||
}, [
|
||||
inputVal,
|
||||
chatData,
|
||||
isChatting,
|
||||
resetInputVal,
|
||||
scrollToBottom,
|
||||
toast,
|
||||
gptChatPrompt,
|
||||
pushChatHistory,
|
||||
chatId
|
||||
]);
|
||||
|
||||
// 清空输入内容
|
||||
resetInputVal('');
|
||||
scrollToBottom();
|
||||
|
||||
try {
|
||||
await gptChatPrompt(newChatList[newChatList.length - 2]);
|
||||
|
||||
// 如果是 Human 第一次发送,插入历史记录
|
||||
const humanChat = newChatList.filter((item) => item.obj === 'Human');
|
||||
if (humanChat.length === 1) {
|
||||
pushChatHistory({
|
||||
chatId,
|
||||
title: humanChat[0].value
|
||||
});
|
||||
}
|
||||
} catch (err: any) {
|
||||
toast({
|
||||
title: typeof err === 'string' ? err : err?.message || '聊天出错了~',
|
||||
status: 'warning',
|
||||
duration: 5000,
|
||||
isClosable: true
|
||||
});
|
||||
|
||||
resetInputVal(storeInput);
|
||||
|
||||
setChatData((state) => ({
|
||||
...state,
|
||||
history: newChatList.slice(0, newChatList.length - 2)
|
||||
}));
|
||||
}
|
||||
},
|
||||
[
|
||||
inputVal,
|
||||
chatData,
|
||||
isChatting,
|
||||
resetInputVal,
|
||||
scrollToBottom,
|
||||
toast,
|
||||
gptChatPrompt,
|
||||
pushChatHistory,
|
||||
chatId
|
||||
]
|
||||
);
|
||||
|
||||
// 删除一句话
|
||||
const delChatRecord = useCallback(
|
||||
|
@@ -19,7 +19,7 @@ import { DeleteIcon } from '@chakra-ui/icons';
|
||||
import { customAlphabet } from 'nanoid';
|
||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 12);
|
||||
|
||||
type FormData = { text: string; q: { val: string }[] };
|
||||
type FormData = { text: string; q: string };
|
||||
|
||||
const InputDataModal = ({
|
||||
onClose,
|
||||
@@ -36,17 +36,9 @@ const InputDataModal = ({
|
||||
const { register, handleSubmit, control } = useForm<FormData>({
|
||||
defaultValues: {
|
||||
text: '',
|
||||
q: [{ val: '' }]
|
||||
q: ''
|
||||
}
|
||||
});
|
||||
const {
|
||||
fields: inputQ,
|
||||
append: appendQ,
|
||||
remove: removeQ
|
||||
} = useFieldArray({
|
||||
control,
|
||||
name: 'q'
|
||||
});
|
||||
|
||||
const sureImportData = useCallback(
|
||||
async (e: FormData) => {
|
||||
@@ -58,10 +50,12 @@ const InputDataModal = ({
|
||||
data: [
|
||||
{
|
||||
text: e.text,
|
||||
q: e.q.map((item) => ({
|
||||
id: nanoid(),
|
||||
text: item.val
|
||||
}))
|
||||
q: [
|
||||
{
|
||||
id: nanoid(),
|
||||
text: e.q
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -81,50 +75,46 @@ const InputDataModal = ({
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal isOpen={true} onClose={onClose}>
|
||||
<Modal isOpen={true} onClose={onClose} isCentered>
|
||||
<ModalOverlay />
|
||||
<ModalContent maxW={'min(900px, 90vw)'} maxH={'80vh'} position={'relative'}>
|
||||
<ModalContent
|
||||
m={0}
|
||||
display={'flex'}
|
||||
flexDirection={'column'}
|
||||
h={'90vh'}
|
||||
maxW={'90vw'}
|
||||
position={'relative'}
|
||||
>
|
||||
<ModalHeader>手动导入</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<Box px={6} pb={2} overflowY={'auto'}>
|
||||
<Box mb={2}>知识点:</Box>
|
||||
<Textarea
|
||||
mb={4}
|
||||
placeholder="知识点"
|
||||
rows={3}
|
||||
maxH={'200px'}
|
||||
{...register(`text`, {
|
||||
required: '知识点'
|
||||
})}
|
||||
/>
|
||||
{inputQ.map((item, index) => (
|
||||
<Box key={item.id} mb={5}>
|
||||
<Box mb={2}>问法{index + 1}:</Box>
|
||||
<Flex>
|
||||
<Input
|
||||
placeholder="问法"
|
||||
{...register(`q.${index}.val`, {
|
||||
required: '问法不能为空'
|
||||
})}
|
||||
></Input>
|
||||
{inputQ.length > 1 && (
|
||||
<IconButton
|
||||
icon={<DeleteIcon />}
|
||||
aria-label={'delete'}
|
||||
colorScheme={'gray'}
|
||||
variant={'unstyled'}
|
||||
onClick={() => removeQ(index)}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
|
||||
<Flex flex={'1 0 0'} h={0} px={6} pb={2}>
|
||||
<Box flex={2} mr={4} h={'100%'}>
|
||||
<Box h={'30px'}>问题</Box>
|
||||
<Textarea
|
||||
placeholder="相关问题,可以回车输入多个问法, 最多500字"
|
||||
maxLength={500}
|
||||
resize={'none'}
|
||||
h={'calc(100% - 30px)'}
|
||||
{...register(`q`, {
|
||||
required: '相关问题,可以回车输入多个问法'
|
||||
})}
|
||||
/>
|
||||
</Box>
|
||||
<Box flex={3} h={'100%'}>
|
||||
<Box h={'30px'}>知识点</Box>
|
||||
<Textarea
|
||||
placeholder="知识点"
|
||||
resize={'none'}
|
||||
h={'calc(100% - 30px)'}
|
||||
{...register(`text`, {
|
||||
required: '知识点'
|
||||
})}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
|
||||
<Flex px={6} pt={2} pb={4}>
|
||||
<Button alignSelf={'flex-start'} variant={'outline'} onClick={() => appendQ({ val: '' })}>
|
||||
增加问法
|
||||
</Button>
|
||||
<Box flex={1}></Box>
|
||||
<Button variant={'outline'} mr={3} onClick={onClose}>
|
||||
取消
|
||||
|
@@ -50,7 +50,7 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => {
|
||||
pageNum
|
||||
} = usePagination<ModelDataSchema>({
|
||||
api: getModelDataList,
|
||||
pageSize: 10,
|
||||
pageSize: 8,
|
||||
params: {
|
||||
modelId: model._id
|
||||
}
|
||||
@@ -119,7 +119,7 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => {
|
||||
</Flex>
|
||||
{data && data.length > 0 && <Box fontSize={'xs'}>{data.length}条数据正在拆分中...</Box>}
|
||||
<Box mt={4}>
|
||||
<TableContainer h={'600px'} overflowY={'auto'}>
|
||||
<TableContainer>
|
||||
<Table variant={'simple'}>
|
||||
<Thead>
|
||||
<Tr>
|
||||
@@ -141,10 +141,7 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => {
|
||||
whiteSpace={'pre-wrap'}
|
||||
_notLast={{ mb: 1 }}
|
||||
>
|
||||
Q{i + 1}:{' '}
|
||||
<Box as={'span'} userSelect={'all'}>
|
||||
{item.text}
|
||||
</Box>
|
||||
{item.text}
|
||||
</Box>
|
||||
))}
|
||||
</Td>
|
||||
|
@@ -108,7 +108,7 @@ const ModelEditForm = ({
|
||||
|
||||
<Slider
|
||||
aria-label="slider-ex-1"
|
||||
min={1}
|
||||
min={0}
|
||||
max={10}
|
||||
step={1}
|
||||
value={getValues('temperature')}
|
||||
@@ -138,24 +138,17 @@ const ModelEditForm = ({
|
||||
</Flex>
|
||||
</FormControl>
|
||||
<Box mt={4}>
|
||||
{canTrain ? (
|
||||
<Box fontWeight={'bold'}>
|
||||
训练的模型会自动根据知识库内容回答,无法设置系统prompt。注意:
|
||||
使用该模型,在对话时需要消耗等多的 tokens
|
||||
</Box>
|
||||
) : (
|
||||
<>
|
||||
<Box mb={1}>系统提示词</Box>
|
||||
<Textarea
|
||||
rows={6}
|
||||
maxLength={-1}
|
||||
{...register('systemPrompt')}
|
||||
placeholder={
|
||||
'模型默认的 prompt 词,通过调整该内容,可以生成一个限定范围的模型。\n\n注意,改功能会影响对话的整体朝向!'
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<Box mb={1}>系统提示词</Box>
|
||||
<Textarea
|
||||
rows={6}
|
||||
maxLength={-1}
|
||||
{...register('systemPrompt')}
|
||||
placeholder={
|
||||
canTrain
|
||||
? '训练的模型会根据知识库内容,生成一部分系统提示词,因此在对话时需要消耗更多的 tokens。你仍可以增加一些提示词,让其效果更精确。'
|
||||
: '模型默认的 prompt 词,通过调整该内容,可以生成一个限定范围的模型。\n\n注意,改功能会影响对话的整体朝向!'
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
</Card>
|
||||
{/* <Card p={4}>
|
||||
|
Reference in New Issue
Block a user