perf: search prompt, upload step and psw len

This commit is contained in:
archer
2023-08-10 11:49:32 +08:00
parent 9ea19b8eaa
commit 63c832d883
14 changed files with 113 additions and 58 deletions

View File

@@ -22,6 +22,9 @@
"New Chat": "New Chat", "New Chat": "New Chat",
"You need to a chat app": "You need to a chat app" "You need to a chat app": "You need to a chat app"
}, },
"commom": {
"Password inconsistency": "Password inconsistency"
},
"common": { "common": {
"Add": "Add", "Add": "Add",
"Cancel": "Cancel", "Cancel": "Cancel",

View File

@@ -22,11 +22,15 @@
"New Chat": "新对话", "New Chat": "新对话",
"You need to a chat app": "你需要创建一个应用" "You need to a chat app": "你需要创建一个应用"
}, },
"commom": {
"Password inconsistency": "两次密码不一致"
},
"common": { "common": {
"Add": "添加", "Add": "添加",
"Cancel": "取消", "Cancel": "取消",
"Collect": "收藏", "Collect": "收藏",
"Copy": "复制", "Copy": "复制",
"Course": "",
"Delete": "删除", "Delete": "删除",
"Filed is repeat": "", "Filed is repeat": "",
"Filed is repeated": "字段重复了", "Filed is repeated": "字段重复了",

View File

@@ -1,5 +1,5 @@
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import { ModalBody, ModalCloseButton, ModalHeader, Box, useTheme } from '@chakra-ui/react'; import { ModalBody, Box, useTheme } from '@chakra-ui/react';
import { getKbDataItemById } from '@/api/plugins/kb'; import { getKbDataItemById } from '@/api/plugins/kb';
import { useLoading } from '@/hooks/useLoading'; import { useLoading } from '@/hooks/useLoading';
import { useToast } from '@/hooks/useToast'; import { useToast } from '@/hooks/useToast';
@@ -9,13 +9,21 @@ import MyIcon from '@/components/Icon';
import InputDataModal from '@/pages/kb/detail/components/InputDataModal'; import InputDataModal from '@/pages/kb/detail/components/InputDataModal';
import MyModal from '../MyModal'; import MyModal from '../MyModal';
type SearchType = {
kb_id?: string;
id?: string;
q: string;
a?: string;
source?: string | undefined;
};
const QuoteModal = ({ const QuoteModal = ({
onUpdateQuote, onUpdateQuote,
rawSearch = [], rawSearch = [],
onClose onClose
}: { }: {
onUpdateQuote: (quoteId: string, sourceText: string) => Promise<void>; onUpdateQuote: (quoteId: string, sourceText: string) => Promise<void>;
rawSearch: QuoteItemType[]; rawSearch: SearchType[];
onClose: () => void; onClose: () => void;
}) => { }) => {
const theme = useTheme(); const theme = useTheme();
@@ -32,7 +40,8 @@ const QuoteModal = ({
* click edit, get new kbDataItem * click edit, get new kbDataItem
*/ */
const onclickEdit = useCallback( const onclickEdit = useCallback(
async (item: QuoteItemType) => { async (item: SearchType) => {
if (!item.id) return;
try { try {
setIsLoading(true); setIsLoading(true);
const data = (await getKbDataItemById(item.id)) as QuoteItemType; const data = (await getKbDataItemById(item.id)) as QuoteItemType;
@@ -77,9 +86,9 @@ const QuoteModal = ({
} }
> >
<ModalBody pt={0} whiteSpace={'pre-wrap'} textAlign={'justify'} fontSize={'sm'}> <ModalBody pt={0} whiteSpace={'pre-wrap'} textAlign={'justify'} fontSize={'sm'}>
{rawSearch.map((item) => ( {rawSearch.map((item, i) => (
<Box <Box
key={item.id} key={i}
flex={'1 0 0'} flex={'1 0 0'}
p={2} p={2}
borderRadius={'lg'} borderRadius={'lg'}
@@ -91,31 +100,33 @@ const QuoteModal = ({
{item.source && <Box color={'myGray.600'}>({item.source})</Box>} {item.source && <Box color={'myGray.600'}>({item.source})</Box>}
<Box>{item.q}</Box> <Box>{item.q}</Box>
<Box>{item.a}</Box> <Box>{item.a}</Box>
<Box {item.id && (
className="edit" <Box
display={'none'} className="edit"
position={'absolute'} display={'none'}
right={0} position={'absolute'}
top={0} right={0}
bottom={0} top={0}
w={'40px'} bottom={0}
bg={'rgba(255,255,255,0.9)'} w={'40px'}
alignItems={'center'} bg={'rgba(255,255,255,0.9)'}
justifyContent={'center'} alignItems={'center'}
boxShadow={'-10px 0 10px rgba(255,255,255,1)'} justifyContent={'center'}
> boxShadow={'-10px 0 10px rgba(255,255,255,1)'}
<MyIcon >
name={'edit'} <MyIcon
w={'18px'} name={'edit'}
h={'18px'} w={'18px'}
cursor={'pointer'} h={'18px'}
color={'myGray.600'} cursor={'pointer'}
_hover={{ color={'myGray.600'}
color: 'myBlue.700' _hover={{
}} color: 'myBlue.700'
onClick={() => onclickEdit(item)} }}
/> onClick={() => onclickEdit(item)}
</Box> />
</Box>
)}
</Box> </Box>
))} ))}
</ModalBody> </ModalBody>

View File

@@ -6,9 +6,15 @@ import { useForm } from 'react-hook-form';
import { useRequest } from '@/hooks/useRequest'; import { useRequest } from '@/hooks/useRequest';
import { updatePasswordByOld } from '@/api/user'; import { updatePasswordByOld } from '@/api/user';
type FormType = {
oldPsw: string;
newPsw: string;
confirmPsw: string;
};
const UpdatePswModal = ({ onClose }: { onClose: () => void }) => { const UpdatePswModal = ({ onClose }: { onClose: () => void }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { register, handleSubmit } = useForm({ const { register, handleSubmit } = useForm<FormType>({
defaultValues: { defaultValues: {
oldPsw: '', oldPsw: '',
newPsw: '', newPsw: '',
@@ -17,7 +23,10 @@ const UpdatePswModal = ({ onClose }: { onClose: () => void }) => {
}); });
const { mutate: onSubmit, isLoading } = useRequest({ const { mutate: onSubmit, isLoading } = useRequest({
mutationFn: (data) => { mutationFn: (data: FormType) => {
if (data.newPsw !== data.confirmPsw) {
return Promise.reject(t('commom.Password inconsistency'));
}
return updatePasswordByOld(data); return updatePasswordByOld(data);
}, },
onSuccess() { onSuccess() {
@@ -36,11 +45,31 @@ const UpdatePswModal = ({ onClose }: { onClose: () => void }) => {
</Flex> </Flex>
<Flex alignItems={'center'} mt={5}> <Flex alignItems={'center'} mt={5}>
<Box flex={'0 0 70px'}>:</Box> <Box flex={'0 0 70px'}>:</Box>
<Input flex={1} type={'password'} {...register('newPsw', { required: true })}></Input> <Input
flex={1}
type={'password'}
{...register('newPsw', {
required: true,
maxLength: {
value: 20,
message: '密码最少 4 位最多 20 位'
}
})}
></Input>
</Flex> </Flex>
<Flex alignItems={'center'} mt={5}> <Flex alignItems={'center'} mt={5}>
<Box flex={'0 0 70px'}>:</Box> <Box flex={'0 0 70px'}>:</Box>
<Input flex={1} type={'password'} {...register('confirmPsw', { required: true })}></Input> <Input
flex={1}
type={'password'}
{...register('confirmPsw', {
required: true,
maxLength: {
value: 20,
message: '密码最少 4 位最多 20 位'
}
})}
></Input>
</Flex> </Flex>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>

View File

@@ -90,15 +90,14 @@ export async function pushDataToKb({
data.forEach((item) => { data.forEach((item) => {
const text = item.q + item.a; const text = item.q + item.a;
if (mode === TrainingModeEnum.qa) { // count token
// count token const token = modelToolMap.countTokens({
const token = modelToolMap.countTokens({ model: 'gpt-3.5-turbo',
model: 'gpt-3.5-turbo-16k', messages: [{ obj: 'System', value: item.q }]
messages: [{ obj: 'System', value: item.q }] });
});
if (token > modeMaxToken[TrainingModeEnum.qa]) { if (token > modeMaxToken[TrainingModeEnum.qa]) {
return; return;
}
} }
if (!set.has(text)) { if (!set.has(text)) {

View File

@@ -142,7 +142,7 @@ const ChunkImport = ({ kbId }: { kbId: string }) => {
// subsection import // subsection import
let success = 0; let success = 0;
const step = 100; const step = 500;
for (let i = 0; i < chunks.length; i += step) { for (let i = 0; i < chunks.length; i += step) {
const { insertLen } = await postKbDataFromList({ const { insertLen } = await postKbDataFromList({
kbId, kbId,

View File

@@ -13,7 +13,7 @@ import { TrainingModeEnum } from '@/constants/plugin';
import FileSelect from './FileSelect'; import FileSelect from './FileSelect';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 12); const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 12);
import { fileDownload, readCsvContent } from '@/utils/file'; import { readCsvContent } from '@/utils/file';
const fileExtension = '.csv'; const fileExtension = '.csv';
@@ -98,7 +98,7 @@ const CsvImport = ({ kbId }: { kbId: string }) => {
// subsection import // subsection import
let success = 0; let success = 0;
const step = 100; const step = 500;
for (let i = 0; i < chunks.length; i += step) { for (let i = 0; i < chunks.length; i += step) {
const { insertLen } = await postKbDataFromList({ const { insertLen } = await postKbDataFromList({
kbId, kbId,

View File

@@ -132,7 +132,7 @@ const QAImport = ({ kbId }: { kbId: string }) => {
// subsection import // subsection import
let success = 0; let success = 0;
const step = 100; const step = 500;
for (let i = 0; i < chunks.length; i += step) { for (let i = 0; i < chunks.length; i += step) {
const { insertLen } = await postKbDataFromList({ const { insertLen } = await postKbDataFromList({
kbId, kbId,

View File

@@ -129,11 +129,11 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
required: '密码不能为空', required: '密码不能为空',
minLength: { minLength: {
value: 4, value: 4,
message: '密码最少4位最多12位' message: '密码最少 4 位最多 20 位'
}, },
maxLength: { maxLength: {
value: 12, value: 20,
message: '密码最少4位最多12位' message: '密码最少 4 位最多 20 位'
} }
})} })}
></Input> ></Input>

View File

@@ -97,8 +97,8 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
{...register('password', { {...register('password', {
required: '密码不能为空', required: '密码不能为空',
maxLength: { maxLength: {
value: 12, value: 20,
message: '密码最多12位' message: '密码最多 20 位'
} }
})} })}
></Input> ></Input>

View File

@@ -142,11 +142,11 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
required: '密码不能为空', required: '密码不能为空',
minLength: { minLength: {
value: 4, value: 4,
message: '密码最少4位最多12位' message: '密码最少 4 位最多 20 位'
}, },
maxLength: { maxLength: {
value: 12, value: 20,
message: '密码最少4位最多12位' message: '密码最少 4 位最多 20 位'
} }
})} })}
></Input> ></Input>

View File

@@ -30,6 +30,10 @@ const maxTokens = 3000;
export const dispatchClassifyQuestion = async (props: Record<string, any>): Promise<CQResponse> => { export const dispatchClassifyQuestion = async (props: Record<string, any>): Promise<CQResponse> => {
const { agents, systemPrompt, history = [], userChatInput, userOpenaiAccount } = props as CQProps; const { agents, systemPrompt, history = [], userChatInput, userOpenaiAccount } = props as CQProps;
if (!userChatInput) {
return Promise.reject('Input is empty');
}
const messages: ChatItemType[] = [ const messages: ChatItemType[] = [
...(systemPrompt ...(systemPrompt
? [ ? [

View File

@@ -192,7 +192,7 @@ function filterQuote({
maxToken: model.quoteMaxToken, maxToken: model.quoteMaxToken,
messages: quoteQA.map((item, i) => ({ messages: quoteQA.map((item, i) => ({
obj: ChatRoleEnum.System, obj: ChatRoleEnum.System,
value: `${i + 1}. [${item.q}\n${item.a}]` value: item.a ? `{instruction:${item.q},output:${item.a}}` : `{instruction:${item.q}}`
})) }))
}); });
@@ -202,7 +202,9 @@ function filterQuote({
const quotePrompt = const quotePrompt =
filterQuoteQA.length > 0 filterQuoteQA.length > 0
? `下面是知识库内容: ? `下面是知识库内容:
${filterQuoteQA.map((item) => `{Q:${item.q},A:${item.a}}`).join('\n')} ${filterQuoteQA
.map((item) => (item.a ? `{instruction:${item.q},output:${item.a}}` : `{instruction:${item.q}}`))
.join('\n')}
` `
: ''; : '';

View File

@@ -21,13 +21,16 @@ export type StreamResponseType = {
/* slice chat context by tokens */ /* slice chat context by tokens */
export const ChatContextFilter = ({ export const ChatContextFilter = ({
model, model,
prompts, prompts = [],
maxTokens maxTokens
}: { }: {
model: string; model: string;
prompts: ChatItemType[]; prompts: ChatItemType[];
maxTokens: number; maxTokens: number;
}) => { }) => {
if (!Array.isArray(prompts)) {
return [];
}
const rawTextLen = prompts.reduce((sum, item) => sum + item.value.length, 0); const rawTextLen = prompts.reduce((sum, item) => sum + item.value.length, 0);
// If the text length is less than half of the maximum token, no calculation is required // If the text length is less than half of the maximum token, no calculation is required