Commit 56a0b48b by archer

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

parent ff24042d
...@@ -49,6 +49,7 @@ export const getModelTrainings = (id: string) => ...@@ -49,6 +49,7 @@ export const getModelTrainings = (id: string) =>
type GetModelDataListProps = RequestPaging & { type GetModelDataListProps = RequestPaging & {
modelId: string; modelId: string;
searchText: string;
}; };
/** /**
* 获取模型的知识库数据 * 获取模型的知识库数据
......
...@@ -4,20 +4,20 @@ import { connectToDatabase } from '@/service/mongo'; ...@@ -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< ...@@ -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: {
......
...@@ -15,7 +15,8 @@ import { ...@@ -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')); ...@@ -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 }) => { ...@@ -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 }) => { ...@@ -158,9 +162,33 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => {
</MenuList> </MenuList>
</Menu> </Menu>
</Flex> </Flex>
{!!(splitDataLen && splitDataLen > 0) && ( <Flex mt={4}>
<Box fontSize={'xs'}>{splitDataLen}条数据正在拆分...</Box> {/* 拆分数据提示 */}
)} {!!(splitDataLen && splitDataLen > 0) && (
<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'}>
......
...@@ -54,20 +54,20 @@ const ModelEditForm = ({ ...@@ -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 = ({ ...@@ -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'}
......
...@@ -21,7 +21,6 @@ const ModelDetail = ({ modelId }: { modelId: string }) => { ...@@ -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 }) => { ...@@ -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 }) => { ...@@ -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> */}
</> </>
); );
}; };
......
...@@ -16,6 +16,7 @@ import { formatModelStatus } from '@/constants/model'; ...@@ -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 = [],
...@@ -32,6 +33,15 @@ const ModelTable = ({ ...@@ -32,6 +33,15 @@ const ModelTable = ({
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',
render: (item: ModelSchema) => dayjs(item.updateTime).format('YYYY-MM-DD HH:mm') render: (item: ModelSchema) => dayjs(item.updateTime).format('YYYY-MM-DD HH:mm')
...@@ -51,29 +61,20 @@ const ModelTable = ({ ...@@ -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>
</> </>
) )
} }
......
...@@ -30,7 +30,7 @@ const BillTable = () => { ...@@ -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'}>
......
...@@ -77,7 +77,7 @@ const PayRecordTable = () => { ...@@ -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>
......
...@@ -21,7 +21,7 @@ export const pushChatBill = async ({ ...@@ -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}`);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment