This commit is contained in:
Archer
2023-10-24 17:32:36 +08:00
committed by GitHub
parent 1942cb0d67
commit 1dca5edcc6
18 changed files with 142 additions and 73 deletions

View File

@@ -35,8 +35,8 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
## 🛸 在线使用 ## 🛸 在线使用
+ 🌐 国内版:[ai.fastgpt.in](https://ai.fastgpt.in/) - 🌐 国内版:[ai.fastgpt.in](https://ai.fastgpt.in/)
+ 🌍 海外版:[fastgpt.run](https://fastgpt.run/) - 🌍 海外版:[fastgpt.run](https://fastgpt.run/)
| | | | | |
| ---------------------------------- | ---------------------------------- | | ---------------------------------- | ---------------------------------- |
@@ -128,7 +128,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
本仓库遵循 [FastGPT Open Source License](./LICENSE) 开源协议。 本仓库遵循 [FastGPT Open Source License](./LICENSE) 开源协议。
1. 允许作为后台服务直接商用,但不允许直接使用 SaaS 服务商用 1. 允许作为后台服务直接商用,但不允许提供 SaaS 服务。
2. 需保留相关版权信息。 2. 需保留相关版权信息。
3. 完整请查看 [FastGPT Open Source License](./LICENSE) 3. 完整请查看 [FastGPT Open Source License](./LICENSE)
4. 联系方式yujinlong@sealos.io, [点击查看定价策略](https://doc.fastgpt.run/docs/commercial) 4. 联系方式yujinlong@sealos.io, [点击查看定价策略](https://doc.fastgpt.run/docs/commercial)

View File

@@ -31,7 +31,6 @@ select pg_reload_conf();
-- 重构数据库索引和排序 -- 重构数据库索引和排序
REINDEX DATABASE postgres; REINDEX DATABASE postgres;
ALTER DATABASE postgres REFRESH COLLATION VERSION;
-- 开始构建索引,该索引构建时间非常久,直接点击右上角的叉,退出 Terminal 即可 -- 开始构建索引,该索引构建时间非常久,直接点击右上角的叉,退出 Terminal 即可
CREATE INDEX CONCURRENTLY vector_index ON modeldata USING hnsw (vector vector_ip_ops) WITH (m = 16, ef_construction = 64); CREATE INDEX CONCURRENTLY vector_index ON modeldata USING hnsw (vector vector_ip_ops) WITH (m = 16, ef_construction = 64);

View File

@@ -527,7 +527,7 @@ HTTP 模块允许你调用任意 POST 类型的 HTTP 接口,从而实验一些
{ {
"moduleId": "zltb5l", "moduleId": "zltb5l",
"name": "知识库搜索", "name": "知识库搜索",
"flowType": "kbSearchNode", "flowType": "datasetSearchNode",
"showStatus": true, "showStatus": true,
"position": { "position": {
"x": 1634.995464753433, "x": 1634.995464753433,

View File

@@ -97,7 +97,7 @@ weight: 144
{ {
"moduleId": "nkxlso", "moduleId": "nkxlso",
"name": "知识库搜索", "name": "知识库搜索",
"flowType": "kbSearchNode", "flowType": "datasetSearchNode",
"showStatus": true, "showStatus": true,
"position": { "position": {
"x": 1542.6434554710224, "x": 1542.6434554710224,

View File

@@ -2,7 +2,7 @@
"SystemParams": { "SystemParams": {
"vectorMaxProcess": 15, "vectorMaxProcess": 15,
"qaMaxProcess": 15, "qaMaxProcess": 15,
"pgHNSWEfSearch ": 60 "pgHNSWEfSearch": 100
}, },
"ChatModels": [ "ChatModels": [
{ {

View File

@@ -175,10 +175,16 @@
"dataset": { "dataset": {
"Choose Dataset": "Chookse Dataset", "Choose Dataset": "Chookse Dataset",
"Dataset": "Dataset", "Dataset": "Dataset",
"Go Dataset": "To Dataset",
"Quote Length": "Quote Length",
"Read Dataset": "Read Dataset", "Read Dataset": "Read Dataset",
"Search Top K": "Top K", "Search Top K": "Top K",
"Set Empty Result Tip": ",Response empty text", "Set Empty Result Tip": ",Response empty text",
"Similarity": "Similarity" "Similarity": "Similarity",
"data": {
"Edit": "Edit Data",
"id": "Data ID"
}
} }
}, },
"dataset": { "dataset": {

View File

@@ -175,10 +175,16 @@
"dataset": { "dataset": {
"Choose Dataset": "关联知识库", "Choose Dataset": "关联知识库",
"Dataset": "知识库", "Dataset": "知识库",
"Go Dataset": "前往知识库",
"Quote Length": "引用内容长度",
"Read Dataset": "查看知识库详情", "Read Dataset": "查看知识库详情",
"Search Top K": "单次搜索数量", "Search Top K": "单次搜索数量",
"Set Empty Result Tip": ",未搜索到内容时回复指定内容", "Set Empty Result Tip": ",未搜索到内容时回复指定内容",
"Similarity": "相似度" "Similarity": "相似度",
"data": {
"Edit": "编辑数据",
"id": "数据ID"
}
} }
}, },
"dataset": { "dataset": {

View File

@@ -1,5 +1,5 @@
import React, { useCallback, useMemo, useState } from 'react'; import React, { useCallback, useMemo, useState } from 'react';
import { ModalBody, Box, useTheme, Flex, Progress } from '@chakra-ui/react'; import { ModalBody, Box, useTheme, Flex, Progress, Link } from '@chakra-ui/react';
import { getDatasetDataItemById } from '@/web/core/dataset/api'; import { getDatasetDataItemById } from '@/web/core/dataset/api';
import { useLoading } from '@/web/common/hooks/useLoading'; import { useLoading } from '@/web/common/hooks/useLoading';
import { useToast } from '@/web/common/hooks/useToast'; import { useToast } from '@/web/common/hooks/useToast';
@@ -13,6 +13,9 @@ import MyModal from '../MyModal';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type'; import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
import MyTooltip from '../MyTooltip';
import NextLink from 'next/link';
import { useSystemStore } from '@/web/common/system/useSystemStore';
const QuoteModal = ({ const QuoteModal = ({
rawSearch = [], rawSearch = [],
@@ -22,6 +25,7 @@ const QuoteModal = ({
onClose: () => void; onClose: () => void;
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { isPc } = useSystemStore();
const theme = useTheme(); const theme = useTheme();
const router = useRouter(); const router = useRouter();
const { toast } = useToast(); const { toast } = useToast();
@@ -67,7 +71,7 @@ const QuoteModal = ({
title={ title={
<> <>
({rawSearch.length}) ({rawSearch.length})
<Box fontSize={['xs', 'sm']} fontWeight={'normal'}> <Box fontSize={'10px'} color={'myGray.500'} fontWeight={'normal'}>
注意: 修改知识库内容成功后 注意: 修改知识库内容成功后
</Box> </Box>
</> </>
@@ -89,58 +93,83 @@ const QuoteModal = ({
border={theme.borders.base} border={theme.borders.base}
_notLast={{ mb: 2 }} _notLast={{ mb: 2 }}
position={'relative'} position={'relative'}
_hover={{ '& .edit': { display: 'flex' } }}
overflow={'hidden'} overflow={'hidden'}
> >
{!isShare && ( {!isShare && (
<Flex alignItems={'center'} mb={1}> <Flex alignItems={'flex-end'} mb={1}>
<RawSourceText sourceName={item.sourceName} sourceId={item.sourceId} /> <RawSourceText sourceName={item.sourceName} sourceId={item.sourceId} />
<Box flex={'1'} /> <Box flex={1} />
{item.score && ( <Link
<> as={NextLink}
<Progress display={'flex'}
mx={2} alignItems={'center'}
w={['60px', '100px']} color={'myBlue.600'}
value={item.score * 100} href={`/dataset/detail?datasetId=${item.datasetId}&currentTab=dataCard&collectionId=${item.collectionId}`}
size="sm" >
borderRadius={'20px'} {t('core.dataset.Go Dataset')}
colorScheme="gray" <MyIcon name={'rightArrowLight'} w={'10px'} />
border={theme.borders.base} </Link>
/>
<Box>{item.score.toFixed(4)}</Box>
</>
)}
</Flex> </Flex>
)} )}
<Box>{item.q}</Box> <Box>{item.q}</Box>
<Box>{item.a}</Box> <Box>{item.a}</Box>
{item.id && !isShare && ( {!isShare && (
<Box <Flex alignItems={'center'} mt={2} gap={4}>
className="edit" {isPc && (
display={'none'} <MyTooltip label={t('core.dataset.data.id')}>
position={'absolute'} <Flex border={theme.borders.base} px={3} borderRadius={'md'}>
right={0} # {item.id}
top={0} </Flex>
bottom={0} </MyTooltip>
w={'40px'} )}
bg={'rgba(255,255,255,0.9)'} <MyTooltip label={t('core.dataset.Quote Length')}>
alignItems={'center'} <Flex alignItems={'center'}>
justifyContent={'center'} <MyIcon name="common/text/t" w={'14px'} mr={1} color={'myGray.500'} />
boxShadow={'-10px 0 10px rgba(255,255,255,1)'} {item.q.length + item.a.length}
> </Flex>
<MyIcon </MyTooltip>
name={'edit'} {!isShare && item.score && (
w={'18px'} <MyTooltip label={t('core.dataset.Similarity')}>
h={'18px'} <Flex alignItems={'center'}>
cursor={'pointer'} <MyIcon name={'kbTest'} w={'12px'} />
color={'myGray.600'} <Progress
_hover={{ mx={2}
color: 'myBlue.700' w={['60px', '90px']}
}} value={item.score * 100}
onClick={() => onclickEdit(item)} size="sm"
/> borderRadius={'20px'}
</Box> colorScheme="gray"
border={theme.borders.base}
/>
<Box>{item.score.toFixed(4)}</Box>
</Flex>
</MyTooltip>
)}
<Box flex={1} />
{item.id && (
<MyTooltip label={t('core.dataset.data.Edit')}>
<Box
bg={'rgba(255,255,255,0.9)'}
alignItems={'center'}
justifyContent={'center'}
boxShadow={'-10px 0 10px rgba(255,255,255,1)'}
>
<MyIcon
name={'edit'}
w={['16px', '18px']}
h={['16px', '18px']}
cursor={'pointer'}
color={'myGray.600'}
_hover={{
color: 'myBlue.700'
}}
onClick={() => onclickEdit(item)}
/>
</Box>
</MyTooltip>
)}
</Flex>
)} )}
</Box> </Box>
))} ))}

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1698125580538"
class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8233"
xmlns:xlink="http://www.w3.org/1999/xlink">
<path
d="M288.633235 288.699238l446.731484 0L735.364719 421.267533l-13.261025-0.088004c-7.720845-30.709419-16.270569-52.302203-25.91216-65.759703-9.639544-13.458523-22.638603-24.233937-39.127136-32.477692-9.16166-4.03285-25.345248-6.083555-48.682769-6.083555l-51.123354 0-0.611937 336.608388c-1.394766 23.839965 1.394766 18.059308 0 33.261545-0.611937 6.783497 13.173021 20.022009 21.375843 24.733311 8.28878 4.602831 33.500998 5.692652 47.63388 5.692652l19.107173 0 0 18.735713L378.145921 735.890186 378.145921 715.88762l21.98471 0c14.394848 0 31.495318-1.176802 40.045041-6.194072 6.457062-3.533476 26.959002-1.373277 27.176966-24.25338 0.87288-31.494295 2.7486-8.723685 0-31.974225L467.352639 316.857555l-50.906413 0c-33.414017 0-57.537438 6.957459-72.5432 21.00336-21.331841 19.629059-34.767851 47.197952-40.35101 83.491553l-15.485693 0L288.633235 288.699238zM958.709483 244.030899l0 536.025183c0 98.629321-79.960123 178.608887-178.718381 178.608887L243.964896 958.664969c-98.585319 0-178.674379-79.979566-178.674379-178.608887L65.290517 244.030899c0-98.717326 80.090083-178.696892 178.674379-178.696892l536.026206 0C878.74936 65.334008 958.709483 145.314597 958.709483 244.030899zM869.413737 288.699238c0-74.003458-60.067051-134.071532-134.049019-134.071532L288.633235 154.627706c-73.981968 0-133.919059 60.067051-133.919059 134.071532l0 446.601524c0 74.091462 59.937091 134.049019 133.919059 134.049019l446.731484 0c73.981968 0 134.049019-59.957557 134.049019-134.049019L869.413737 288.699238z"
p-id="8234"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,3 +1,8 @@
<svg viewBox="0 0 24 24"> <?xml version="1.0" standalone="no"?>
<path d="M8.3 5.7a1 1 0 011.4-1.4l7.71 7.7-7.7 7.7a1 1 0 11-1.42-1.4l6.3-6.3-6.3-6.3z" fill-rule="nonzero"></path> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1698126616764"
class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2488"
xmlns:xlink="http://www.w3.org/1999/xlink">
<path
d="M334.25863111 23.36199111c-17.64238222-17.49560889-46.24611555-17.49560889-63.88849778 0-16.46705778 16.32824889-17.56501333 42.12736-3.29386666 59.71854222l3.29386666 3.63747556 419.83772445 416.32199111L270.37013333 919.36199111c-16.46705778 16.32824889-17.56501333 42.12736-3.29386666 59.71854222l3.29386666 3.63747556c16.46592 16.32938667 42.48120889 17.41824 60.22030222 3.26542222l3.66819556-3.26542222 451.76490667-448c16.46592-16.32824889 17.56387555-42.12736 3.29272889-59.71854222l-3.29272889-3.63747556-451.76490667-448z"
p-id="2489"></path>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 151 B

After

Width:  |  Height:  |  Size: 897 B

View File

@@ -91,7 +91,8 @@ const iconPaths = {
loading: () => import('./icons/light/loading.svg'), loading: () => import('./icons/light/loading.svg'),
pause: () => import('./icons/common/pause.svg'), pause: () => import('./icons/common/pause.svg'),
'core/app/aiLight': () => import('./icons/core/app/aiLight.svg'), 'core/app/aiLight': () => import('./icons/core/app/aiLight.svg'),
'core/app/aiFill': () => import('./icons/core/app/aiFill.svg') 'core/app/aiFill': () => import('./icons/core/app/aiFill.svg'),
'common/text/t': () => import('./icons/common/text/t.svg')
}; };
export type IconName = keyof typeof iconPaths; export type IconName = keyof typeof iconPaths;

View File

@@ -41,7 +41,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
const results: any = await PgClient.query( const results: any = await PgClient.query(
`BEGIN; `BEGIN;
SET LOCAL hnsw.ef_search = ${global.systemEnv.pgHNSWEfSearch || 60}; SET LOCAL hnsw.ef_search = ${global.systemEnv.pgHNSWEfSearch || 100};
select id, q, a, dataset_id, collection_id, (vector <#> '[${ select id, q, a, dataset_id, collection_id, (vector <#> '[${
vectors[0] vectors[0]
}]') * -1 AS score from ${PgDatasetTableName} where dataset_id='${datasetId}' AND user_id='${userId}' ORDER BY vector <#> '[${ }]') * -1 AS score from ${PgDatasetTableName} where dataset_id='${datasetId}' AND user_id='${userId}' ORDER BY vector <#> '[${

View File

@@ -22,7 +22,6 @@ const NodeCard = (props: Props) => {
name = '未知模块', name = '未知模块',
description, description,
minW = '300px', minW = '300px',
moduleId moduleId
} = props; } = props;
const { onCopyNode, onDelNode } = useFlowStore(); const { onCopyNode, onDelNode } = useFlowStore();
@@ -81,7 +80,14 @@ const NodeCard = (props: Props) => {
); );
return ( return (
<Box minW={minW} bg={'white'} border={theme.borders.md} borderRadius={'md'} boxShadow={'sm'}> <Box
minW={minW}
maxW={'500px'}
bg={'white'}
border={theme.borders.md}
borderRadius={'md'}
boxShadow={'sm'}
>
<Flex className="custom-drag-handle" px={4} py={3} alignItems={'center'}> <Flex className="custom-drag-handle" px={4} py={3} alignItems={'center'}>
<Avatar src={logo} borderRadius={'md'} objectFit={'contain'} w={'30px'} h={'30px'} /> <Avatar src={logo} borderRadius={'md'} objectFit={'contain'} w={'30px'} h={'30px'} />
<Box ml={3} fontSize={'lg'} color={'myGray.600'}> <Box ml={3} fontSize={'lg'} color={'myGray.600'}>

View File

@@ -498,7 +498,7 @@ var SelectDatasetRender = React.memo(function SelectDatasetRender({ item, module
return ( return (
<> <>
<Grid gridTemplateColumns={'1fr 1fr'} gridGap={4}> <Grid gridTemplateColumns={'repeat(2, minmax(0, 1fr))'} gridGap={4} w={'100%'}>
<Button h={'36px'} onClick={onOpenKbSelect}> <Button h={'36px'} onClick={onOpenKbSelect}>
</Button> </Button>
@@ -512,7 +512,14 @@ var SelectDatasetRender = React.memo(function SelectDatasetRender({ item, module
borderRadius={'md'} borderRadius={'md'}
> >
<Avatar src={item.avatar} w={'24px'}></Avatar> <Avatar src={item.avatar} w={'24px'}></Avatar>
<Box ml={3} fontWeight={'bold'} fontSize={['md', 'lg', 'xl']}> <Box
ml={3}
flex={'1 0 0'}
w={0}
className="textEllipsis"
fontWeight={'bold'}
fontSize={['md', 'lg', 'xl']}
>
{item.name} {item.name}
</Box> </Box>
</Flex> </Flex>

View File

@@ -51,7 +51,6 @@ import { getGuideModule } from '@/global/core/app/modules/utils';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import MySelect from '@/components/Select'; import MySelect from '@/components/Select';
import MySlider from '@/components/Slider';
import MyTooltip from '@/components/MyTooltip'; import MyTooltip from '@/components/MyTooltip';
import Avatar from '@/components/Avatar'; import Avatar from '@/components/Avatar';
import MyIcon from '@/components/Icon'; import MyIcon from '@/components/Icon';

View File

@@ -186,7 +186,7 @@ const Test = ({ datasetId }: { datasetId: string }) => {
]} ]}
gridGap={4} gridGap={4}
> >
{datasetTestItem?.results.map((item) => ( {datasetTestItem?.results.map((item, index) => (
<Box <Box
key={item.id} key={item.id}
pb={2} pb={2}
@@ -223,6 +223,15 @@ const Test = ({ datasetId }: { datasetId: string }) => {
}} }}
> >
<Flex p={3} alignItems={'center'} color={'myGray.500'}> <Flex p={3} alignItems={'center'} color={'myGray.500'}>
<Box
border={theme.borders.base}
px={2}
fontSize={'sm'}
mr={1}
borderRadius={'md'}
>
# {index + 1}
</Box>
<MyIcon name={'kbTest'} w={'14px'} /> <MyIcon name={'kbTest'} w={'14px'} />
<Progress <Progress
mx={2} mx={2}
@@ -234,13 +243,7 @@ const Test = ({ datasetId }: { datasetId: string }) => {
/> />
<Box>{item.score.toFixed(4)}</Box> <Box>{item.score.toFixed(4)}</Box>
</Flex> </Flex>
<Box <Box px={2} fontSize={'xs'} color={'myGray.600'}>
px={2}
fontSize={'xs'}
color={'myGray.600'}
maxH={'200px'}
overflow={'overlay'}
>
<Box>{item.q}</Box> <Box>{item.q}</Box>
<Box>{item.a}</Box> <Box>{item.a}</Box>
</Box> </Box>

View File

@@ -52,7 +52,7 @@ export async function dispatchKBSearch(props: Record<string, any>): Promise<KBSe
// search kb // search kb
const results: any = await PgClient.query( const results: any = await PgClient.query(
`BEGIN; `BEGIN;
SET LOCAL hnsw.ef_search = ${global.systemEnv.pgHNSWEfSearch || 60}; SET LOCAL hnsw.ef_search = ${global.systemEnv.pgHNSWEfSearch || 100};
select id, q, a, dataset_id, collection_id, (vector <#> '[${ select id, q, a, dataset_id, collection_id, (vector <#> '[${
vectors[0] vectors[0]
}]') * -1 AS score from ${PgDatasetTableName} where user_id='${ }]') * -1 AS score from ${PgDatasetTableName} where user_id='${

View File

@@ -195,7 +195,7 @@ export async function initPg() {
q TEXT NOT NULL, q TEXT NOT NULL,
a TEXT a TEXT
); );
CREATE INDEX IF NOT EXISTS vector_index ON ${PgDatasetTableName} USING hnsw (vector vector_ip_ops) WITH (m = 16, ef_construction = 64); CREATE INDEX IF NOT EXISTS vector_index ON ${PgDatasetTableName} USING hnsw (vector vector_ip_ops) WITH (m = 24, ef_construction = 48);
`); `);
console.log('init pg successful'); console.log('init pg successful');