perf: 文案;feat: 知识库模糊搜索

This commit is contained in:
archer
2023-04-13 21:34:36 +08:00
parent ff24042df5
commit 56a0b48b97
9 changed files with 62 additions and 43 deletions

View File

@@ -49,6 +49,7 @@ export const getModelTrainings = (id: string) =>
type GetModelDataListProps = RequestPaging & { type GetModelDataListProps = RequestPaging & {
modelId: string; modelId: string;
searchText: string;
}; };
/** /**
* 获取模型的知识库数据 * 获取模型的知识库数据

View File

@@ -4,20 +4,20 @@ import { connectToDatabase } from '@/service/mongo';
import { authToken } from '@/service/utils/tools'; import { authToken } from '@/service/utils/tools';
import { connectRedis } from '@/service/redis'; import { connectRedis } from '@/service/redis';
import { VecModelDataIdx } from '@/constants/redis'; import { VecModelDataIdx } from '@/constants/redis';
import { SearchOptions } from 'redis';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) { export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try { try {
let { let {
modelId, modelId,
pageNum = 1, pageNum = 1,
pageSize = 10 pageSize = 10,
searchText = ''
} = req.query as { } = req.query as {
modelId: string; modelId: string;
pageNum: string; pageNum: string;
pageSize: string; pageSize: string;
searchText: string;
}; };
const { authorization } = req.headers; const { authorization } = req.headers;
pageNum = +pageNum; pageNum = +pageNum;
@@ -40,7 +40,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
// 从 redis 中获取数据 // 从 redis 中获取数据
const searchRes = await redis.ft.search( const searchRes = await redis.ft.search(
VecModelDataIdx, VecModelDataIdx,
`@modelId:{${modelId}} @userId:{${userId}}`, `@modelId:{${modelId}} @userId:{${userId}} ${searchText ? `*${searchText}*` : ''}`,
{ {
RETURN: ['q', 'text', 'status'], RETURN: ['q', 'text', 'status'],
LIMIT: { LIMIT: {

View File

@@ -15,7 +15,8 @@ import {
Menu, Menu,
MenuButton, MenuButton,
MenuList, MenuList,
MenuItem MenuItem,
Input
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import type { ModelSchema } from '@/types/mongoSchema'; import type { ModelSchema } from '@/types/mongoSchema';
import type { RedisModelDataItemType } from '@/types/redis'; import type { RedisModelDataItemType } from '@/types/redis';
@@ -40,9 +41,11 @@ const SelectFileModel = dynamic(() => import('./SelectFileModal'));
const SelectUrlModel = dynamic(() => import('./SelectUrlModal')); const SelectUrlModel = dynamic(() => import('./SelectUrlModal'));
const SelectCsvModal = dynamic(() => import('./SelectCsvModal')); const SelectCsvModal = dynamic(() => import('./SelectCsvModal'));
let lastSearch = '';
const ModelDataCard = ({ model }: { model: ModelSchema }) => { const ModelDataCard = ({ model }: { model: ModelSchema }) => {
const { Loading, setIsLoading } = useLoading(); const { Loading, setIsLoading } = useLoading();
const [searchText, setSearchText] = useState('');
const { const {
data: modelDataList, data: modelDataList,
isLoading, isLoading,
@@ -54,7 +57,8 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => {
api: getModelDataList, api: getModelDataList,
pageSize: 8, pageSize: 8,
params: { params: {
modelId: model._id modelId: model._id,
searchText
} }
}); });
@@ -158,9 +162,33 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => {
</MenuList> </MenuList>
</Menu> </Menu>
</Flex> </Flex>
<Flex mt={4}>
{/* 拆分数据提示 */}
{!!(splitDataLen && splitDataLen > 0) && ( {!!(splitDataLen && splitDataLen > 0) && (
<Box fontSize={'xs'}>{splitDataLen}...</Box> <Box fontSize={'xs'}>{splitDataLen}...</Box>
)} )}
<Box flex={1}></Box>
<Input
maxW={'240px'}
size={'sm'}
value={searchText}
placeholder="搜索相关问题和答案,回车确认"
onChange={(e) => setSearchText(e.target.value)}
onBlur={() => {
if (searchText === lastSearch) return;
getData(1);
lastSearch = searchText;
}}
onKeyDown={(e) => {
if (searchText === lastSearch) return;
if (e.key === 'Enter') {
getData(1);
lastSearch = searchText;
}
}}
/>
</Flex>
<Box mt={4}> <Box mt={4}>
<TableContainer minH={'500px'}> <TableContainer minH={'500px'}>
<Table variant={'simple'}> <Table variant={'simple'}>

View File

@@ -54,20 +54,20 @@ const ModelEditForm = ({
})} })}
></Input> ></Input>
</Flex> </Flex>
<Flex alignItems={'center'} mt={4}> <Flex alignItems={'center'} mt={5}>
<Box flex={'0 0 80px'} w={0}> <Box flex={'0 0 80px'} w={0}>
modelId: modelId:
</Box> </Box>
<Box>{getValues('_id')}</Box> <Box>{getValues('_id')}</Box>
</Flex> </Flex>
</FormControl> </FormControl>
<Flex alignItems={'center'} mt={4}> <Flex alignItems={'center'} mt={5}>
<Box flex={'0 0 80px'} w={0}> <Box flex={'0 0 80px'} w={0}>
: :
</Box> </Box>
<Box>{getValues('service.modelName')}</Box> <Box>{modelList.find((item) => item.model === getValues('service.modelName'))?.name}</Box>
</Flex> </Flex>
<Flex alignItems={'center'} mt={4}> <Flex alignItems={'center'} mt={5}>
<Box flex={'0 0 80px'} w={0}> <Box flex={'0 0 80px'} w={0}>
: :
</Box> </Box>
@@ -80,7 +80,7 @@ const ModelEditForm = ({
</Box> </Box>
</Flex> </Flex>
<Flex mt={5} alignItems={'center'}> <Flex mt={5} alignItems={'center'}>
<Box flex={'0 0 80px'}>:</Box> <Box flex={'0 0 150px'}></Box>
<Button <Button
colorScheme={'gray'} colorScheme={'gray'}
variant={'outline'} variant={'outline'}

View File

@@ -21,7 +21,6 @@ const ModelDetail = ({ modelId }: { modelId: string }) => {
const { isPc, media } = useScreen(); const { isPc, media } = useScreen();
const { setLoading } = useGlobalStore(); const { setLoading } = useGlobalStore();
// const SelectFileDom = useRef<HTMLInputElement>(null);
const [model, setModel] = useState<ModelSchema>(defaultModel); const [model, setModel] = useState<ModelSchema>(defaultModel);
const formHooks = useForm<ModelSchema>({ const formHooks = useForm<ModelSchema>({
defaultValues: model defaultValues: model
@@ -243,11 +242,6 @@ const ModelDetail = ({ modelId }: { modelId: string }) => {
<Grid mt={5} gridTemplateColumns={media('1fr 1fr', '1fr')} gridGap={5}> <Grid mt={5} gridTemplateColumns={media('1fr 1fr', '1fr')} gridGap={5}>
<ModelEditForm formHooks={formHooks} handleDelModel={handleDelModel} canTrain={canTrain} /> <ModelEditForm formHooks={formHooks} handleDelModel={handleDelModel} canTrain={canTrain} />
{/* {canTrain && (
<Card p={4}>
<Training model={model} />
</Card>
)} */}
{canTrain && model._id && ( {canTrain && model._id && (
<Card <Card
p={4} p={4}
@@ -263,11 +257,6 @@ const ModelDetail = ({ modelId }: { modelId: string }) => {
</Card> </Card>
)} )}
</Grid> </Grid>
{/* 文件选择 */}
{/* <Box position={'absolute'} w={0} h={0} overflow={'hidden'}>
<input ref={SelectFileDom} type="file" accept=".jsonl" onChange={startTraining} />
</Box> */}
</> </>
); );
}; };

View File

@@ -16,6 +16,7 @@ import { formatModelStatus } from '@/constants/model';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import type { ModelSchema } from '@/types/mongoSchema'; import type { ModelSchema } from '@/types/mongoSchema';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { modelList } from '@/constants/model';
const ModelTable = ({ const ModelTable = ({
models = [], models = [],
@@ -31,6 +32,15 @@ const ModelTable = ({
key: 'name', key: 'name',
dataIndex: 'name' dataIndex: 'name'
}, },
{
title: '模型类型',
key: 'service',
render: (model: ModelSchema) => (
<Box fontWeight={'bold'} whiteSpace={'pre-wrap'} maxW={'200px'}>
{modelList.find((item) => item.model === model.service.modelName)?.name}
</Box>
)
},
{ {
title: '最后更新时间', title: '最后更新时间',
key: 'updateTime', key: 'updateTime',
@@ -51,29 +61,20 @@ const ModelTable = ({
</Tag> </Tag>
) )
}, },
{
title: 'AI模型',
key: 'service',
render: (item: ModelSchema) => (
<Box wordBreak={'break-all'} whiteSpace={'pre-wrap'} maxW={'200px'}>
{item.service.modelName}
</Box>
)
},
{ {
title: '操作', title: '操作',
key: 'control', key: 'control',
render: (item: ModelSchema) => ( render: (item: ModelSchema) => (
<> <>
<Button mr={3} onClick={() => handlePreviewChat(item._id)}>
</Button>
<Button <Button
colorScheme={'gray'} mr={3}
variant={'outline'}
onClick={() => router.push(`/model/detail?modelId=${item._id}`)} onClick={() => router.push(`/model/detail?modelId=${item._id}`)}
> >
</Button> </Button>
<Button onClick={() => handlePreviewChat(item._id)}></Button>
</> </>
) )
} }

View File

@@ -30,7 +30,7 @@ const BillTable = () => {
<Th></Th> <Th></Th>
<Th></Th> <Th></Th>
<Th>Tokens </Th> <Th>Tokens </Th>
<Th></Th> <Th></Th>
</Tr> </Tr>
</Thead> </Thead>
<Tbody fontSize={'sm'}> <Tbody fontSize={'sm'}>

View File

@@ -77,7 +77,7 @@ const PayRecordTable = () => {
<Th></Th> <Th></Th>
<Th></Th> <Th></Th>
<Th></Th> <Th></Th>
<Th></Th> <Th></Th>
<Th></Th> <Th></Th>
</Tr> </Tr>
</Thead> </Thead>

View File

@@ -21,7 +21,7 @@ export const pushChatBill = async ({
try { try {
// 计算 token 数量 // 计算 token 数量
const tokens = Math.floor(encode(text).length * 0.7); const tokens = Math.floor(encode(text).length * 0.75);
console.log(`chat generate success. text len: ${text.length}. token len: ${tokens}`); console.log(`chat generate success. text len: ${text.length}. token len: ${tokens}`);