Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
be33794a
authored
Aug 26, 2023
by
archer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: self vector search
parent
13439c51
Show whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
133 additions
and
53 deletions
+133
-53
client/src/constants/flow/ModuleTemplate.ts
+2
-2
client/src/constants/kb.ts
+7
-1
client/src/pages/api/openapi/kb/searchTest.ts
+9
-6
client/src/pages/api/openapi/kb/updateData.ts
+2
-5
client/src/pages/api/plugins/kb/detail.ts
+2
-2
client/src/pages/api/plugins/kb/list.ts
+2
-2
client/src/pages/app/detail/components/BasicEdit/index.tsx
+4
-1
client/src/pages/app/detail/components/KBSelectModal.tsx
+31
-3
client/src/pages/kb/detail/components/Import/Chunk.tsx
+19
-7
client/src/pages/kb/detail/components/Import/Csv.tsx
+14
-3
client/src/pages/kb/detail/components/Import/Manual.tsx
+15
-5
client/src/pages/kb/detail/components/Info.tsx
+1
-1
client/src/pages/kb/detail/components/Test.tsx
+10
-4
client/src/pages/kb/detail/index.tsx
+2
-0
client/src/pages/kb/list/index.tsx
+1
-1
client/src/service/events/generateVector.ts
+0
-1
client/src/service/models/app.ts
+1
-1
client/src/service/moduleDispatch/kb/search.ts
+3
-3
client/src/service/utils/data.ts
+1
-1
client/src/types/model.d.ts
+2
-0
client/src/types/plugin.d.ts
+4
-3
client/src/utils/app.ts
+1
-1
No files found.
client/src/constants/flow/ModuleTemplate.ts
View file @
be33794a
...
@@ -218,7 +218,7 @@ export const KBSearchModule: FlowModuleTemplateType = {
...
@@ -218,7 +218,7 @@ export const KBSearchModule: FlowModuleTemplateType = {
key: 'similarity',
key: 'similarity',
type: FlowInputItemTypeEnum.slider,
type: FlowInputItemTypeEnum.slider,
label: '相似度',
label: '相似度',
value: 0.
8
,
value: 0.
4
,
min: 0,
min: 0,
max: 1,
max: 1,
step: 0.01,
step: 0.01,
...
@@ -845,7 +845,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
...
@@ -845,7 +845,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
key: 'similarity',
key: 'similarity',
type: 'slider',
type: 'slider',
label: '相似度',
label: '相似度',
value: 0.
8
,
value: 0.
4
,
min: 0,
min: 0,
max: 1,
max: 1,
step: 0.01,
step: 0.01,
...
...
client/src/constants/kb.ts
View file @
be33794a
...
@@ -6,5 +6,11 @@ export const defaultKbDetail: KbItemType = {
...
@@ -6,5 +6,11 @@ export const defaultKbDetail: KbItemType = {
avatar
:
'/icon/logo.svg'
,
avatar
:
'/icon/logo.svg'
,
name
:
''
,
name
:
''
,
tags
:
''
,
tags
:
''
,
vectorModelName
:
'text-embedding-ada-002'
vectorModel
:
{
model
:
'text-embedding-ada-002'
,
name
:
'Embedding-2'
,
price
:
0.2
,
defaultToken
:
500
,
maxToken
:
8000
}
};
};
client/src/pages/api/openapi/kb/searchTest.ts
View file @
be33794a
...
@@ -6,9 +6,9 @@ import { withNextCors } from '@/service/utils/tools';
...
@@ -6,9 +6,9 @@ import { withNextCors } from '@/service/utils/tools';
import
{
getVector
}
from
'../plugin/vector'
;
import
{
getVector
}
from
'../plugin/vector'
;
import
type
{
KbTestItemType
}
from
'@/types/plugin'
;
import
type
{
KbTestItemType
}
from
'@/types/plugin'
;
import
{
PgTrainingTableName
}
from
'@/constants/plugin'
;
import
{
PgTrainingTableName
}
from
'@/constants/plugin'
;
import
{
KB
}
from
'@/service/mongo'
;
export
type
Props
=
{
export
type
Props
=
{
model
:
string
;
kbId
:
string
;
kbId
:
string
;
text
:
string
;
text
:
string
;
};
};
...
@@ -16,21 +16,24 @@ export type Response = KbTestItemType['results'];
...
@@ -16,21 +16,24 @@ export type Response = KbTestItemType['results'];
export
default
withNextCors
(
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
export
default
withNextCors
(
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
try
{
try
{
const
{
kbId
,
text
,
model
}
=
req
.
body
as
Props
;
const
{
kbId
,
text
}
=
req
.
body
as
Props
;
if
(
!
kbId
||
!
text
||
!
model
)
{
if
(
!
kbId
||
!
text
)
{
throw
new
Error
(
'缺少参数'
);
throw
new
Error
(
'缺少参数'
);
}
}
// 凭证校验
// 凭证校验
const
{
userId
}
=
await
authUser
({
req
});
const
[{
userId
},
kb
]
=
await
Promise
.
all
([
authUser
({
req
}),
KB
.
findById
(
kbId
,
'vectorModel'
)
]);
if
(
!
userId
)
{
if
(
!
userId
||
!
kb
)
{
throw
new
Error
(
'缺少用户ID'
);
throw
new
Error
(
'缺少用户ID'
);
}
}
const
{
vectors
}
=
await
getVector
({
const
{
vectors
}
=
await
getVector
({
model
,
model
:
kb
.
vectorModel
,
userId
,
userId
,
input
:
[
text
]
input
:
[
text
]
});
});
...
...
client/src/pages/api/openapi/kb/updateData.ts
View file @
be33794a
...
@@ -24,11 +24,8 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
...
@@ -24,11 +24,8 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
await
connectToDatabase
();
await
connectToDatabase
();
// 凭证校验
// auth user and get kb
const
{
userId
}
=
await
authUser
({
req
});
const
[{
userId
},
kb
]
=
await
Promise
.
all
([
authUser
({
req
}),
KB
.
findById
(
kbId
,
'model'
)]);
// find model
const
kb
=
await
KB
.
findById
(
kbId
,
'model'
);
if
(
!
kb
)
{
if
(
!
kb
)
{
throw
new
Error
(
"Can't find database"
);
throw
new
Error
(
"Can't find database"
);
...
...
client/src/pages/api/plugins/kb/detail.ts
View file @
be33794a
...
@@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
...
@@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import
{
jsonRes
}
from
'@/service/response'
;
import
{
jsonRes
}
from
'@/service/response'
;
import
{
connectToDatabase
,
KB
}
from
'@/service/mongo'
;
import
{
connectToDatabase
,
KB
}
from
'@/service/mongo'
;
import
{
authUser
}
from
'@/service/utils/auth'
;
import
{
authUser
}
from
'@/service/utils/auth'
;
import
{
getModel
}
from
'@/service/utils/data'
;
import
{
get
Vector
Model
}
from
'@/service/utils/data'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
try
{
try
{
...
@@ -34,7 +34,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
...
@@ -34,7 +34,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
avatar
:
data
.
avatar
,
avatar
:
data
.
avatar
,
name
:
data
.
name
,
name
:
data
.
name
,
userId
:
data
.
userId
,
userId
:
data
.
userId
,
vectorModel
Name
:
getModel
(
data
.
vectorModel
)?.
name
||
'Unknown'
,
vectorModel
:
getVectorModel
(
data
.
vectorModel
)
,
tags
:
data
.
tags
.
join
(
' '
)
tags
:
data
.
tags
.
join
(
' '
)
}
}
});
});
...
...
client/src/pages/api/plugins/kb/list.ts
View file @
be33794a
...
@@ -3,7 +3,7 @@ import { jsonRes } from '@/service/response';
...
@@ -3,7 +3,7 @@ import { jsonRes } from '@/service/response';
import
{
connectToDatabase
,
KB
}
from
'@/service/mongo'
;
import
{
connectToDatabase
,
KB
}
from
'@/service/mongo'
;
import
{
authUser
}
from
'@/service/utils/auth'
;
import
{
authUser
}
from
'@/service/utils/auth'
;
import
{
KbListItemType
}
from
'@/types/plugin'
;
import
{
KbListItemType
}
from
'@/types/plugin'
;
import
{
getModel
}
from
'@/service/utils/data'
;
import
{
get
Vector
Model
}
from
'@/service/utils/data'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
try
{
try
{
...
@@ -25,7 +25,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
...
@@ -25,7 +25,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
avatar
:
item
.
avatar
,
avatar
:
item
.
avatar
,
name
:
item
.
name
,
name
:
item
.
name
,
tags
:
item
.
tags
,
tags
:
item
.
tags
,
vectorModel
Name
:
getModel
(
item
.
vectorModel
)?.
name
||
'UnKnow'
vectorModel
:
getVectorModel
(
item
.
vectorModel
)
}))
}))
);
);
...
...
client/src/pages/app/detail/components/BasicEdit/index.tsx
View file @
be33794a
...
@@ -542,7 +542,10 @@ const Settings = ({ appId }: { appId: string }) => {
...
@@ -542,7 +542,10 @@ const Settings = ({ appId }: { appId: string }) => {
{
isOpenKbSelect
&&
(
{
isOpenKbSelect
&&
(
<
KBSelectModal
<
KBSelectModal
kbList=
{
myKbList
}
kbList=
{
myKbList
}
activeKbs=
{
selectedKbList
.
map
((
item
)
=>
({
kbId
:
item
.
_id
}))
}
activeKbs=
{
selectedKbList
.
map
((
item
)
=>
({
kbId
:
item
.
_id
,
vectorModel
:
item
.
vectorModel
}))
}
onClose=
{
onCloseKbSelect
}
onClose=
{
onCloseKbSelect
}
onChange=
{
replaceKbList
}
onChange=
{
replaceKbList
}
/>
/>
...
...
client/src/pages/app/detail/components/KBSelectModal.tsx
View file @
be33794a
...
@@ -16,9 +16,11 @@ import { useForm } from 'react-hook-form';
...
@@ -16,9 +16,11 @@ import { useForm } from 'react-hook-form';
import
{
QuestionOutlineIcon
}
from
'@chakra-ui/icons'
;
import
{
QuestionOutlineIcon
}
from
'@chakra-ui/icons'
;
import
type
{
SelectedKbType
}
from
'@/types/plugin'
;
import
type
{
SelectedKbType
}
from
'@/types/plugin'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
MySlider
from
'@/components/Slider'
;
import
MySlider
from
'@/components/Slider'
;
import
MyTooltip
from
'@/components/MyTooltip'
;
import
MyTooltip
from
'@/components/MyTooltip'
;
import
MyModal
from
'@/components/MyModal'
;
import
MyModal
from
'@/components/MyModal'
;
import
MyIcon
from
'@/components/Icon'
;
export
type
KbParamsType
=
{
export
type
KbParamsType
=
{
searchSimilarity
:
number
;
searchSimilarity
:
number
;
...
@@ -40,6 +42,7 @@ export const KBSelectModal = ({
...
@@ -40,6 +42,7 @@ export const KBSelectModal = ({
const
theme
=
useTheme
();
const
theme
=
useTheme
();
const
[
selectedKbList
,
setSelectedKbList
]
=
useState
<
SelectedKbType
>
(
activeKbs
);
const
[
selectedKbList
,
setSelectedKbList
]
=
useState
<
SelectedKbType
>
(
activeKbs
);
const
{
isPc
}
=
useGlobalStore
();
const
{
isPc
}
=
useGlobalStore
();
const
{
toast
}
=
useToast
();
return
(
return
(
<
MyModal
<
MyModal
...
@@ -50,7 +53,13 @@ export const KBSelectModal = ({
...
@@ -50,7 +53,13 @@ export const KBSelectModal = ({
onClose=
{
onClose
}
onClose=
{
onClose
}
>
>
<
Flex
flexDirection=
{
'column'
}
h=
{
[
'90vh'
,
'auto'
]
}
>
<
Flex
flexDirection=
{
'column'
}
h=
{
[
'90vh'
,
'auto'
]
}
>
<
ModalHeader
>
关联的知识库(
{
selectedKbList
.
length
}
)
</
ModalHeader
>
<
ModalHeader
>
<
Box
>
关联的知识库(
{
selectedKbList
.
length
}
)
</
Box
>
<
Box
fontSize=
{
'sm'
}
color=
{
'myGray.500'
}
fontWeight=
{
'normal'
}
>
仅能选择同一个索引模型的知识库
</
Box
>
</
ModalHeader
>
<
ModalBody
<
ModalBody
flex=
{
[
'1 0 0'
,
'0 0 auto'
]
}
flex=
{
[
'1 0 0'
,
'0 0 auto'
]
}
maxH=
{
'80vh'
}
maxH=
{
'80vh'
}
...
@@ -58,6 +67,7 @@ export const KBSelectModal = ({
...
@@ -58,6 +67,7 @@ export const KBSelectModal = ({
display=
{
'grid'
}
display=
{
'grid'
}
gridTemplateColumns=
{
[
'repeat(1,1fr)'
,
'repeat(2,1fr)'
,
'repeat(3,1fr)'
]
}
gridTemplateColumns=
{
[
'repeat(1,1fr)'
,
'repeat(2,1fr)'
,
'repeat(3,1fr)'
]
}
gridGap=
{
3
}
gridGap=
{
3
}
userSelect=
{
'none'
}
>
>
{
kbList
.
map
((
item
)
=>
{
kbList
.
map
((
item
)
=>
(()
=>
{
(()
=>
{
...
@@ -84,7 +94,18 @@ export const KBSelectModal = ({
...
@@ -84,7 +94,18 @@ export const KBSelectModal = ({
if
(
selected
)
{
if
(
selected
)
{
setSelectedKbList
((
state
)
=>
state
.
filter
((
kb
)
=>
kb
.
kbId
!==
item
.
_id
));
setSelectedKbList
((
state
)
=>
state
.
filter
((
kb
)
=>
kb
.
kbId
!==
item
.
_id
));
}
else
{
}
else
{
setSelectedKbList
((
state
)
=>
[...
state
,
{
kbId
:
item
.
_id
}]);
const
vectorModel
=
selectedKbList
[
0
]?.
vectorModel
?.
model
;
if
(
vectorModel
&&
vectorModel
!==
item
.
vectorModel
.
model
)
{
return
toast
({
status
:
'warning'
,
title
:
'仅能选择同一个索引模型的知识库'
});
}
setSelectedKbList
((
state
)
=>
[
...
state
,
{
kbId
:
item
.
_id
,
vectorModel
:
item
.
vectorModel
}
]);
}
}
}
}
}
}
>
>
...
@@ -94,6 +115,10 @@ export const KBSelectModal = ({
...
@@ -94,6 +115,10 @@ export const KBSelectModal = ({
{
item
.
name
}
{
item
.
name
}
</
Box
>
</
Box
>
</
Flex
>
</
Flex
>
<
Flex
justifyContent=
{
'flex-end'
}
alignItems=
{
'center'
}
fontSize=
{
'sm'
}
>
<
MyIcon
mr=
{
1
}
name=
"kbTest"
w=
{
'12px'
}
/>
<
Box
color=
{
'myGray.500'
}
>
{
item
.
vectorModel
.
name
}
</
Box
>
</
Flex
>
</
Card
>
</
Card
>
);
);
})()
})()
...
@@ -138,7 +163,10 @@ export const KbParamsModal = ({
...
@@ -138,7 +163,10 @@ export const KbParamsModal = ({
<
Box
display=
{
[
'block'
,
'flex'
]
}
py=
{
5
}
pt=
{
[
0
,
5
]
}
>
<
Box
display=
{
[
'block'
,
'flex'
]
}
py=
{
5
}
pt=
{
[
0
,
5
]
}
>
<
Box
flex=
{
'0 0 100px'
}
mb=
{
[
8
,
0
]
}
>
<
Box
flex=
{
'0 0 100px'
}
mb=
{
[
8
,
0
]
}
>
相似度
相似度
<
MyTooltip
label=
{
'高相似度推荐0.8及以上。'
}
forceShow
>
<
MyTooltip
label=
{
'不同索引模型的相似度有区别,请通过搜索测试来选择合适的数值'
}
forceShow
>
<
QuestionOutlineIcon
ml=
{
1
}
/>
<
QuestionOutlineIcon
ml=
{
1
}
/>
</
MyTooltip
>
</
MyTooltip
>
</
Box
>
</
Box
>
...
...
client/src/pages/kb/detail/components/Import/Chunk.tsx
View file @
be33794a
...
@@ -19,7 +19,6 @@ import { postKbDataFromList } from '@/api/plugins/kb';
...
@@ -19,7 +19,6 @@ import { postKbDataFromList } from '@/api/plugins/kb';
import
{
splitText2Chunks
}
from
'@/utils/file'
;
import
{
splitText2Chunks
}
from
'@/utils/file'
;
import
{
getErrText
}
from
'@/utils/tools'
;
import
{
getErrText
}
from
'@/utils/tools'
;
import
{
formatPrice
}
from
'@/utils/user'
;
import
{
formatPrice
}
from
'@/utils/user'
;
import
{
vectorModelList
}
from
'@/store/static'
;
import
MyIcon
from
'@/components/Icon'
;
import
MyIcon
from
'@/components/Icon'
;
import
CloseIcon
from
'@/components/Icon/close'
;
import
CloseIcon
from
'@/components/Icon/close'
;
import
DeleteIcon
,
{
hoverDeleteStyles
}
from
'@/components/Icon/delete'
;
import
DeleteIcon
,
{
hoverDeleteStyles
}
from
'@/components/Icon/delete'
;
...
@@ -27,17 +26,20 @@ import MyTooltip from '@/components/MyTooltip';
...
@@ -27,17 +26,20 @@ import MyTooltip from '@/components/MyTooltip';
import
{
QuestionOutlineIcon
}
from
'@chakra-ui/icons'
;
import
{
QuestionOutlineIcon
}
from
'@chakra-ui/icons'
;
import
{
TrainingModeEnum
}
from
'@/constants/plugin'
;
import
{
TrainingModeEnum
}
from
'@/constants/plugin'
;
import
FileSelect
,
{
type
FileItemType
}
from
'./FileSelect'
;
import
FileSelect
,
{
type
FileItemType
}
from
'./FileSelect'
;
import
{
useUserStore
}
from
'@/store/user'
;
const
fileExtension
=
'.txt, .doc, .docx, .pdf, .md'
;
const
fileExtension
=
'.txt, .doc, .docx, .pdf, .md'
;
const
ChunkImport
=
({
kbId
}:
{
kbId
:
string
})
=>
{
const
ChunkImport
=
({
kbId
}:
{
kbId
:
string
})
=>
{
const
model
=
vectorModelList
[
0
]?.
model
||
'text-embedding-ada-002'
;
const
{
kbDetail
}
=
useUserStore
();
const
unitPrice
=
vectorModelList
[
0
]?.
price
||
0.2
;
const
vectorModel
=
kbDetail
.
vectorModel
;
const
unitPrice
=
vectorModel
?.
price
||
0.2
;
const
theme
=
useTheme
();
const
theme
=
useTheme
();
const
router
=
useRouter
();
const
router
=
useRouter
();
const
{
toast
}
=
useToast
();
const
{
toast
}
=
useToast
();
const
[
chunkLen
,
setChunkLen
]
=
useState
(
5
00
);
const
[
chunkLen
,
setChunkLen
]
=
useState
(
vectorModel
?.
defaultToken
||
3
00
);
const
[
showRePreview
,
setShowRePreview
]
=
useState
(
false
);
const
[
showRePreview
,
setShowRePreview
]
=
useState
(
false
);
const
[
files
,
setFiles
]
=
useState
<
FileItemType
[]
>
([]);
const
[
files
,
setFiles
]
=
useState
<
FileItemType
[]
>
([]);
const
[
previewFile
,
setPreviewFile
]
=
useState
<
FileItemType
>
();
const
[
previewFile
,
setPreviewFile
]
=
useState
<
FileItemType
>
();
...
@@ -205,12 +207,20 @@ const ChunkImport = ({ kbId }: { kbId: string }) => {
...
@@ -205,12 +207,20 @@ const ChunkImport = ({ kbId }: { kbId: string }) => {
<
QuestionOutlineIcon
ml=
{
1
}
/>
<
QuestionOutlineIcon
ml=
{
1
}
/>
</
MyTooltip
>
</
MyTooltip
>
</
Box
>
</
Box
>
<
Box
flex=
{
1
}
css=
{
{
'& > span'
:
{
display
:
'block'
}
}
}
>
<
MyTooltip
label=
{
`范围: 100~${kbDetail.vectorModel.maxToken}`
}
>
<
NumberInput
<
NumberInput
ml=
{
4
}
ml=
{
4
}
flex=
{
1
}
defaultValue=
{
chunkLen
}
defaultValue=
{
chunkLen
}
min=
{
3
00
}
min=
{
1
00
}
max=
{
2000
}
max=
{
kbDetail
.
vectorModel
.
maxToken
}
step=
{
10
}
step=
{
10
}
onChange=
{
(
e
)
=>
{
onChange=
{
(
e
)
=>
{
setChunkLen
(
+
e
);
setChunkLen
(
+
e
);
...
@@ -223,6 +233,8 @@ const ChunkImport = ({ kbId }: { kbId: string }) => {
...
@@ -223,6 +233,8 @@ const ChunkImport = ({ kbId }: { kbId: string }) => {
<
NumberDecrementStepper
/>
<
NumberDecrementStepper
/>
</
NumberInputStepper
>
</
NumberInputStepper
>
</
NumberInput
>
</
NumberInput
>
</
MyTooltip
>
</
Box
>
</
Flex
>
</
Flex
>
{
/* price */
}
{
/* price */
}
<
Flex
py=
{
5
}
alignItems=
{
'center'
}
>
<
Flex
py=
{
5
}
alignItems=
{
'center'
}
>
...
...
client/src/pages/kb/detail/components/Import/Csv.tsx
View file @
be33794a
...
@@ -11,11 +11,13 @@ import DeleteIcon, { hoverDeleteStyles } from '@/components/Icon/delete';
...
@@ -11,11 +11,13 @@ import DeleteIcon, { hoverDeleteStyles } from '@/components/Icon/delete';
import
{
TrainingModeEnum
}
from
'@/constants/plugin'
;
import
{
TrainingModeEnum
}
from
'@/constants/plugin'
;
import
FileSelect
,
{
type
FileItemType
}
from
'./FileSelect'
;
import
FileSelect
,
{
type
FileItemType
}
from
'./FileSelect'
;
import
{
useRouter
}
from
'next/router'
;
import
{
useRouter
}
from
'next/router'
;
import
{
useUserStore
}
from
'@/store/user'
;
const
fileExtension
=
'.csv'
;
const
fileExtension
=
'.csv'
;
const
CsvImport
=
({
kbId
}:
{
kbId
:
string
})
=>
{
const
CsvImport
=
({
kbId
}:
{
kbId
:
string
})
=>
{
const
model
=
vectorModelList
[
0
]?.
model
;
const
{
kbDetail
}
=
useUserStore
();
const
theme
=
useTheme
();
const
theme
=
useTheme
();
const
router
=
useRouter
();
const
router
=
useRouter
();
const
{
toast
}
=
useToast
();
const
{
toast
}
=
useToast
();
...
@@ -37,13 +39,22 @@ const CsvImport = ({ kbId }: { kbId: string }) => {
...
@@ -37,13 +39,22 @@ const CsvImport = ({ kbId }: { kbId: string }) => {
mutationFn
:
async
()
=>
{
mutationFn
:
async
()
=>
{
const
chunks
=
files
.
map
((
file
)
=>
file
.
chunks
).
flat
();
const
chunks
=
files
.
map
((
file
)
=>
file
.
chunks
).
flat
();
const
filterChunks
=
chunks
.
filter
((
item
)
=>
item
.
q
.
length
<
kbDetail
.
vectorModel
.
maxToken
);
if
(
filterChunks
.
length
!==
chunks
.
length
)
{
toast
({
title
:
`
${
chunks
.
length
-
filterChunks
.
length
}
条数据超出长度,已被过滤`
,
status
:
'info'
});
}
// subsection import
// subsection import
let
success
=
0
;
let
success
=
0
;
const
step
=
500
;
const
step
=
500
;
for
(
let
i
=
0
;
i
<
c
hunks
.
length
;
i
+=
step
)
{
for
(
let
i
=
0
;
i
<
filterC
hunks
.
length
;
i
+=
step
)
{
const
{
insertLen
}
=
await
postKbDataFromList
({
const
{
insertLen
}
=
await
postKbDataFromList
({
kbId
,
kbId
,
data
:
c
hunks
.
slice
(
i
,
i
+
step
),
data
:
filterC
hunks
.
slice
(
i
,
i
+
step
),
mode
:
TrainingModeEnum
.
index
mode
:
TrainingModeEnum
.
index
});
});
...
...
client/src/pages/kb/detail/components/Import/Manual.tsx
View file @
be33794a
import
React
from
'react'
;
import
React
,
{
useState
}
from
'react'
;
import
{
Box
,
Textarea
,
Button
}
from
'@chakra-ui/react'
;
import
{
Box
,
Textarea
,
Button
}
from
'@chakra-ui/react'
;
import
{
useForm
}
from
'react-hook-form'
;
import
{
useForm
}
from
'react-hook-form'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
...
@@ -6,14 +6,18 @@ import { useRequest } from '@/hooks/useRequest';
...
@@ -6,14 +6,18 @@ import { useRequest } from '@/hooks/useRequest';
import
{
getErrText
}
from
'@/utils/tools'
;
import
{
getErrText
}
from
'@/utils/tools'
;
import
{
postKbDataFromList
}
from
'@/api/plugins/kb'
;
import
{
postKbDataFromList
}
from
'@/api/plugins/kb'
;
import
{
TrainingModeEnum
}
from
'@/constants/plugin'
;
import
{
TrainingModeEnum
}
from
'@/constants/plugin'
;
import
{
useUserStore
}
from
'@/store/user'
;
type
ManualFormType
=
{
q
:
string
;
a
:
string
};
type
ManualFormType
=
{
q
:
string
;
a
:
string
};
const
ManualImport
=
({
kbId
}:
{
kbId
:
string
})
=>
{
const
ManualImport
=
({
kbId
}:
{
kbId
:
string
})
=>
{
const
{
kbDetail
}
=
useUserStore
();
const
{
register
,
handleSubmit
,
reset
}
=
useForm
({
const
{
register
,
handleSubmit
,
reset
}
=
useForm
({
defaultValues
:
{
q
:
''
,
a
:
''
}
defaultValues
:
{
q
:
''
,
a
:
''
}
});
});
const
{
toast
}
=
useToast
();
const
{
toast
}
=
useToast
();
const
[
qLen
,
setQLen
]
=
useState
(
0
);
const
{
mutate
:
onImportData
,
isLoading
}
=
useRequest
({
const
{
mutate
:
onImportData
,
isLoading
}
=
useRequest
({
mutationFn
:
async
(
e
:
ManualFormType
)
=>
{
mutationFn
:
async
(
e
:
ManualFormType
)
=>
{
...
@@ -64,16 +68,22 @@ const ManualImport = ({ kbId }: { kbId: string }) => {
...
@@ -64,16 +68,22 @@ const ManualImport = ({ kbId }: { kbId: string }) => {
return
(
return
(
<
Box
p=
{
[
4
,
8
]
}
h=
{
'100%'
}
overflow=
{
'overlay'
}
>
<
Box
p=
{
[
4
,
8
]
}
h=
{
'100%'
}
overflow=
{
'overlay'
}
>
<
Box
display=
{
'flex'
}
flexDirection=
{
[
'column'
,
'row'
]
}
>
<
Box
display=
{
'flex'
}
flexDirection=
{
[
'column'
,
'row'
]
}
>
<
Box
flex=
{
1
}
mr=
{
[
0
,
4
]
}
mb=
{
[
4
,
0
]
}
h=
{
[
'50%'
,
'100%'
]
}
>
<
Box
flex=
{
1
}
mr=
{
[
0
,
4
]
}
mb=
{
[
4
,
0
]
}
h=
{
[
'50%'
,
'100%'
]
}
position=
{
'relative'
}
>
<
Box
h=
{
'30px'
}
>
{
'匹配的知识点'
}
</
Box
>
<
Box
h=
{
'30px'
}
>
{
'匹配的知识点'
}
</
Box
>
<
Textarea
<
Textarea
placeholder=
{
'匹配的知识点。这部分内容会被搜索,请把控内容的质量。总和最多 3000 字。'
}
placeholder=
{
`匹配的知识点。这部分内容会被搜索,请把控内容的质量。最多 ${kbDetail.vectorModel.maxToken} 字。`
}
maxLength=
{
3000
}
maxLength=
{
kbDetail
.
vectorModel
.
maxToken
}
h=
{
[
'250px'
,
'500px'
]
}
h=
{
[
'250px'
,
'500px'
]
}
{
...
register
(`
q
`,
{
{
...
register
(`
q
`,
{
required
:
true
required
:
true
,
onChange
(
e
)
{
setQLen
(
e
.
target
.
value
.
length
);
}
})}
})}
/>
/>
<
Box
position=
{
'absolute'
}
color=
{
'myGray.500'
}
right=
{
5
}
bottom=
{
3
}
zIndex=
{
99
}
>
{
qLen
}
</
Box
>
</
Box
>
</
Box
>
<
Box
flex=
{
1
}
h=
{
[
'50%'
,
'100%'
]
}
>
<
Box
flex=
{
1
}
h=
{
[
'50%'
,
'100%'
]
}
>
<
Box
h=
{
'30px'
}
>
补充知识
</
Box
>
<
Box
h=
{
'30px'
}
>
补充知识
</
Box
>
...
...
client/src/pages/kb/detail/components/Info.tsx
View file @
be33794a
...
@@ -154,7 +154,7 @@ const Info = (
...
@@ -154,7 +154,7 @@ const Info = (
<
Box
flex=
{
[
'0 0 90px'
,
'0 0 160px'
]
}
w=
{
0
}
>
<
Box
flex=
{
[
'0 0 90px'
,
'0 0 160px'
]
}
w=
{
0
}
>
索引模型
索引模型
</
Box
>
</
Box
>
<
Box
flex=
{
[
1
,
'0 0 300px'
]
}
>
{
getValues
(
'vectorModel
Name'
)
}
</
Box
>
<
Box
flex=
{
[
1
,
'0 0 300px'
]
}
>
{
getValues
(
'vectorModel
'
).
name
}
</
Box
>
</
Flex
>
</
Flex
>
<
Flex
mt=
{
5
}
w=
{
'100%'
}
alignItems=
{
'center'
}
>
<
Flex
mt=
{
5
}
w=
{
'100%'
}
alignItems=
{
'center'
}
>
<
Box
flex=
{
[
'0 0 90px'
,
'0 0 160px'
]
}
w=
{
0
}
>
<
Box
flex=
{
[
'0 0 90px'
,
'0 0 160px'
]
}
w=
{
0
}
>
...
...
client/src/pages/kb/detail/components/Test.tsx
View file @
be33794a
...
@@ -10,13 +10,15 @@ import InputDataModal, { type FormData } from './InputDataModal';
...
@@ -10,13 +10,15 @@ import InputDataModal, { type FormData } from './InputDataModal';
import
{
useGlobalStore
}
from
'@/store/global'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
import
{
getErrText
}
from
'@/utils/tools'
;
import
{
getErrText
}
from
'@/utils/tools'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
vectorModelList
}
from
'@/store/static'
;
import
{
customAlphabet
}
from
'nanoid'
;
import
{
customAlphabet
}
from
'nanoid'
;
import
MyTooltip
from
'@/components/MyTooltip'
;
import
MyTooltip
from
'@/components/MyTooltip'
;
import
{
QuestionOutlineIcon
}
from
'@chakra-ui/icons'
;
import
{
QuestionOutlineIcon
}
from
'@chakra-ui/icons'
;
import
{
useUserStore
}
from
'@/store/user'
;
const
nanoid
=
customAlphabet
(
'abcdefghijklmnopqrstuvwxyz1234567890'
,
12
);
const
nanoid
=
customAlphabet
(
'abcdefghijklmnopqrstuvwxyz1234567890'
,
12
);
const
Test
=
({
kbId
}:
{
kbId
:
string
})
=>
{
const
Test
=
({
kbId
}:
{
kbId
:
string
})
=>
{
const
{
kbDetail
}
=
useUserStore
();
const
theme
=
useTheme
();
const
theme
=
useTheme
();
const
{
toast
}
=
useToast
();
const
{
toast
}
=
useToast
();
const
{
setLoading
}
=
useGlobalStore
();
const
{
setLoading
}
=
useGlobalStore
();
...
@@ -31,7 +33,7 @@ const Test = ({ kbId }: { kbId: string }) => {
...
@@ -31,7 +33,7 @@ const Test = ({ kbId }: { kbId: string }) => {
);
);
const
{
mutate
,
isLoading
}
=
useRequest
({
const
{
mutate
,
isLoading
}
=
useRequest
({
mutationFn
:
()
=>
searchText
({
model
:
vectorModelList
[
0
].
model
,
kbId
,
text
:
inputText
.
trim
()
}),
mutationFn
:
()
=>
searchText
({
kbId
,
text
:
inputText
.
trim
()
}),
onSuccess
(
res
)
{
onSuccess
(
res
)
{
const
testItem
=
{
const
testItem
=
{
id
:
nanoid
(),
id
:
nanoid
(),
...
@@ -75,12 +77,15 @@ const Test = ({ kbId }: { kbId: string }) => {
...
@@ -75,12 +77,15 @@ const Test = ({ kbId }: { kbId: string }) => {
rows=
{
6
}
rows=
{
6
}
resize=
{
'none'
}
resize=
{
'none'
}
variant=
{
'unstyled'
}
variant=
{
'unstyled'
}
maxLength=
{
1000
}
maxLength=
{
kbDetail
.
vectorModel
.
maxToken
}
placeholder=
"输入需要测试的文本"
placeholder=
"输入需要测试的文本"
value=
{
inputText
}
value=
{
inputText
}
onChange=
{
(
e
)
=>
setInputText
(
e
.
target
.
value
)
}
onChange=
{
(
e
)
=>
setInputText
(
e
.
target
.
value
)
}
/>
/>
<
Flex
justifyContent=
{
'flex-end'
}
>
<
Flex
alignItems=
{
'center'
}
justifyContent=
{
'flex-end'
}
>
<
Box
mr=
{
3
}
color=
{
'myGray.500'
}
>
{
inputText
.
length
}
</
Box
>
<
Button
isDisabled=
{
inputText
===
''
}
isLoading=
{
isLoading
}
onClick=
{
mutate
}
>
<
Button
isDisabled=
{
inputText
===
''
}
isLoading=
{
isLoading
}
onClick=
{
mutate
}
>
测试
测试
</
Button
>
</
Button
>
...
@@ -177,6 +182,7 @@ const Test = ({ kbId }: { kbId: string }) => {
...
@@ -177,6 +182,7 @@ const Test = ({ kbId }: { kbId: string }) => {
'repeat(1,1fr)'
,
'repeat(1,1fr)'
,
'repeat(1,1fr)'
,
'repeat(1,1fr)'
,
'repeat(1,1fr)'
,
'repeat(1,1fr)'
,
'repeat(1,1fr)'
,
'repeat(2,1fr)'
'repeat(2,1fr)'
]
}
]
}
gridGap=
{
4
}
gridGap=
{
4
}
...
...
client/src/pages/kb/detail/index.tsx
View file @
be33794a
...
@@ -165,12 +165,14 @@ const Detail = ({ kbId, currentTab }: { kbId: string; currentTab: `${TabEnum}` }
...
@@ -165,12 +165,14 @@ const Detail = ({ kbId, currentTab }: { kbId: string; currentTab: `${TabEnum}` }
</
Box
>
</
Box
>
)
}
)
}
{
!!
kbDetail
.
_id
&&
(
<
Box
flex=
{
'1 0 0'
}
h=
{
'100%'
}
pb=
{
[
4
,
0
]
}
>
<
Box
flex=
{
'1 0 0'
}
h=
{
'100%'
}
pb=
{
[
4
,
0
]
}
>
{
currentTab
===
TabEnum
.
data
&&
<
DataCard
kbId=
{
kbId
}
/>
}
{
currentTab
===
TabEnum
.
data
&&
<
DataCard
kbId=
{
kbId
}
/>
}
{
currentTab
===
TabEnum
.
import
&&
<
ImportData
kbId=
{
kbId
}
/>
}
{
currentTab
===
TabEnum
.
import
&&
<
ImportData
kbId=
{
kbId
}
/>
}
{
currentTab
===
TabEnum
.
test
&&
<
Test
kbId=
{
kbId
}
/>
}
{
currentTab
===
TabEnum
.
test
&&
<
Test
kbId=
{
kbId
}
/>
}
{
currentTab
===
TabEnum
.
info
&&
<
Info
ref=
{
InfoRef
}
kbId=
{
kbId
}
form=
{
form
}
/>
}
{
currentTab
===
TabEnum
.
info
&&
<
Info
ref=
{
InfoRef
}
kbId=
{
kbId
}
form=
{
form
}
/>
}
</
Box
>
</
Box
>
)
}
</
Box
>
</
Box
>
</
PageContainer
>
</
PageContainer
>
);
);
...
...
client/src/pages/kb/list/index.tsx
View file @
be33794a
...
@@ -141,7 +141,7 @@ const Kb = () => {
...
@@ -141,7 +141,7 @@ const Kb = () => {
</
Box
>
</
Box
>
<
Flex
justifyContent=
{
'flex-end'
}
alignItems=
{
'center'
}
fontSize=
{
'sm'
}
>
<
Flex
justifyContent=
{
'flex-end'
}
alignItems=
{
'center'
}
fontSize=
{
'sm'
}
>
<
MyIcon
mr=
{
1
}
name=
"kbTest"
w=
{
'12px'
}
/>
<
MyIcon
mr=
{
1
}
name=
"kbTest"
w=
{
'12px'
}
/>
<
Box
color=
{
'myGray.500'
}
>
{
kb
.
vectorModel
N
ame
}
</
Box
>
<
Box
color=
{
'myGray.500'
}
>
{
kb
.
vectorModel
.
n
ame
}
</
Box
>
</
Flex
>
</
Flex
>
</
Card
>
</
Card
>
))
}
))
}
...
...
client/src/service/events/generateVector.ts
View file @
be33794a
import
{
openaiAccountError
}
from
'../errorCode'
;
import
{
insertKbItem
}
from
'@/service/pg'
;
import
{
insertKbItem
}
from
'@/service/pg'
;
import
{
getVector
}
from
'@/pages/api/openapi/plugin/vector'
;
import
{
getVector
}
from
'@/pages/api/openapi/plugin/vector'
;
import
{
TrainingData
}
from
'../models/trainingData'
;
import
{
TrainingData
}
from
'../models/trainingData'
;
...
...
client/src/service/models/app.ts
View file @
be33794a
...
@@ -65,7 +65,7 @@ const AppSchema = new Schema({
...
@@ -65,7 +65,7 @@ const AppSchema = new Schema({
},
},
searchSimilarity
:
{
searchSimilarity
:
{
type
:
Number
,
type
:
Number
,
default
:
0.
8
default
:
0.
4
},
},
searchLimit
:
{
searchLimit
:
{
type
:
Number
,
type
:
Number
,
...
...
client/src/service/moduleDispatch/kb/search.ts
View file @
be33794a
import
{
PgClient
}
from
'@/service/pg'
;
import
{
PgClient
}
from
'@/service/pg'
;
import
type
{
ChatHistoryItemResType
,
ChatItemType
}
from
'@/types/chat'
;
import
type
{
ChatHistoryItemResType
}
from
'@/types/chat'
;
import
{
ChatModuleEnum
,
TaskResponseKeyEnum
}
from
'@/constants/chat'
;
import
{
ChatModuleEnum
,
TaskResponseKeyEnum
}
from
'@/constants/chat'
;
import
{
getVector
}
from
'@/pages/api/openapi/plugin/vector'
;
import
{
getVector
}
from
'@/pages/api/openapi/plugin/vector'
;
import
{
countModelPrice
}
from
'@/service/events/pushBill'
;
import
{
countModelPrice
}
from
'@/service/events/pushBill'
;
...
@@ -21,7 +21,7 @@ export type KBSearchResponse = {
...
@@ -21,7 +21,7 @@ export type KBSearchResponse = {
};
};
export
async
function
dispatchKBSearch
(
props
:
Record
<
string
,
any
>
):
Promise
<
KBSearchResponse
>
{
export
async
function
dispatchKBSearch
(
props
:
Record
<
string
,
any
>
):
Promise
<
KBSearchResponse
>
{
const
{
kbList
=
[],
similarity
=
0.
8
,
limit
=
5
,
userChatInput
}
=
props
as
KBSearchProps
;
const
{
kbList
=
[],
similarity
=
0.
4
,
limit
=
5
,
userChatInput
}
=
props
as
KBSearchProps
;
if
(
kbList
.
length
===
0
)
{
if
(
kbList
.
length
===
0
)
{
return
Promise
.
reject
(
"You didn't choose the knowledge base"
);
return
Promise
.
reject
(
"You didn't choose the knowledge base"
);
...
@@ -32,7 +32,7 @@ export async function dispatchKBSearch(props: Record<string, any>): Promise<KBSe
...
@@ -32,7 +32,7 @@ export async function dispatchKBSearch(props: Record<string, any>): Promise<KBSe
}
}
// get vector
// get vector
const
vectorModel
=
global
.
vectorModels
[
0
]
;
const
vectorModel
=
kbList
[
0
]?.
vectorModel
;
const
{
vectors
,
tokenLen
}
=
await
getVector
({
const
{
vectors
,
tokenLen
}
=
await
getVector
({
model
:
vectorModel
.
model
,
model
:
vectorModel
.
model
,
input
:
[
userChatInput
]
input
:
[
userChatInput
]
...
...
client/src/service/utils/data.ts
View file @
be33794a
...
@@ -2,7 +2,7 @@ export const getChatModel = (model?: string) => {
...
@@ -2,7 +2,7 @@ export const getChatModel = (model?: string) => {
return
global
.
chatModels
.
find
((
item
)
=>
item
.
model
===
model
);
return
global
.
chatModels
.
find
((
item
)
=>
item
.
model
===
model
);
};
};
export
const
getVectorModel
=
(
model
?:
string
)
=>
{
export
const
getVectorModel
=
(
model
?:
string
)
=>
{
return
global
.
vectorModels
.
find
((
item
)
=>
item
.
model
===
model
);
return
global
.
vectorModels
.
find
((
item
)
=>
item
.
model
===
model
)
||
global
.
vectorModels
[
0
]
;
};
};
export
const
getModel
=
(
model
?:
string
)
=>
{
export
const
getModel
=
(
model
?:
string
)
=>
{
...
...
client/src/types/model.d.ts
View file @
be33794a
...
@@ -17,5 +17,7 @@ export type QAModelItemType = {
...
@@ -17,5 +17,7 @@ export type QAModelItemType = {
export
type
VectorModelItemType
=
{
export
type
VectorModelItemType
=
{
model
:
string
;
model
:
string
;
name
:
string
;
name
:
string
;
defaultToken
:
number
;
price
:
number
;
price
:
number
;
maxToken
:
number
;
};
};
client/src/types/plugin.d.ts
View file @
be33794a
import
{
VectorModelItemType
}
from
'./model'
;
import
type
{
kbSchema
}
from
'./mongoSchema'
;
import
type
{
kbSchema
}
from
'./mongoSchema'
;
export
type
SelectedKbType
=
{
kbId
:
string
}[];
export
type
SelectedKbType
=
{
kbId
:
string
;
vectorModel
:
VectorModelItemType
}[];
export
type
KbListItemType
=
{
export
type
KbListItemType
=
{
_id
:
string
;
_id
:
string
;
avatar
:
string
;
avatar
:
string
;
name
:
string
;
name
:
string
;
tags
:
string
[];
tags
:
string
[];
vectorModel
Name
:
string
;
vectorModel
:
VectorModelItemType
;
};
};
/* kb type */
/* kb type */
export
interface
KbItemType
{
export
interface
KbItemType
{
...
@@ -15,7 +16,7 @@ export interface KbItemType {
...
@@ -15,7 +16,7 @@ export interface KbItemType {
avatar
:
string
;
avatar
:
string
;
name
:
string
;
name
:
string
;
userId
:
string
;
userId
:
string
;
vectorModel
Name
:
string
;
vectorModel
:
VectorModelItemType
;
tags
:
string
;
tags
:
string
;
}
}
...
...
client/src/utils/app.ts
View file @
be33794a
...
@@ -49,7 +49,7 @@ export const getDefaultAppForm = (): EditFormType => {
...
@@ -49,7 +49,7 @@ export const getDefaultAppForm = (): EditFormType => {
},
},
kb
:
{
kb
:
{
list
:
[],
list
:
[],
searchSimilarity
:
0.
8
,
searchSimilarity
:
0.
4
,
searchLimit
:
5
,
searchLimit
:
5
,
searchEmptyText
:
''
searchEmptyText
:
''
},
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment