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
5bf95bd8
authored
May 17, 2023
by
archer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: model related kb
parent
a79429fd
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
178 additions
and
117 deletions
+178
-117
src/api/model.ts
+0
-1
src/constants/model.ts
+2
-9
src/constants/theme.ts
+3
-1
src/pages/api/chat/chat.ts
+1
-1
src/pages/api/chat/shareChat/chat.ts
+1
-1
src/pages/api/model/update.ts
+3
-4
src/pages/api/openapi/chat/chat.ts
+1
-1
src/pages/model/components/detail/components/ModelEditForm.tsx
+110
-21
src/pages/model/components/detail/index.tsx
+35
-30
src/service/models/model.ts
+4
-31
src/service/plugins/searchKb.ts
+1
-1
src/service/utils/auth.ts
+8
-1
src/service/utils/chat/openai.ts
+2
-1
src/store/user.ts
+4
-4
src/types/model.d.ts
+2
-2
src/types/mongoSchema.d.ts
+1
-8
No files found.
src/api/model.ts
View file @
5bf95bd8
...
@@ -2,7 +2,6 @@ import { GET, POST, DELETE, PUT } from './request';
...
@@ -2,7 +2,6 @@ import { GET, POST, DELETE, PUT } from './request';
import
type
{
ModelSchema
}
from
'@/types/mongoSchema'
;
import
type
{
ModelSchema
}
from
'@/types/mongoSchema'
;
import
type
{
ModelUpdateParams
,
ShareModelItem
}
from
'@/types/model'
;
import
type
{
ModelUpdateParams
,
ShareModelItem
}
from
'@/types/model'
;
import
{
RequestPaging
}
from
'../types/index'
;
import
{
RequestPaging
}
from
'../types/index'
;
import
{
Obj2Query
}
from
'@/utils/tools'
;
import
type
{
ModelListResponse
}
from
'./response/model'
;
import
type
{
ModelListResponse
}
from
'./response/model'
;
/**
/**
...
...
src/constants/model.ts
View file @
5bf95bd8
import
{
getSystemModelList
}
from
'@/api/system'
;
import
{
getSystemModelList
}
from
'@/api/system'
;
import
type
{
ModelSchema
}
from
'@/types/mongoSchema'
;
import
type
{
ShareChatEditType
}
from
'@/types/model'
;
import
type
{
ShareChatEditType
}
from
'@/types/model'
;
import
type
{
ModelSchema
}
from
'@/types/mongoSchema'
;
export
const
embeddingModel
=
'text-embedding-ada-002'
;
export
const
embeddingModel
=
'text-embedding-ada-002'
;
export
type
EmbeddingModelType
=
'text-embedding-ada-002'
;
export
type
EmbeddingModelType
=
'text-embedding-ada-002'
;
...
@@ -142,7 +142,7 @@ export const defaultModel: ModelSchema = {
...
@@ -142,7 +142,7 @@ export const defaultModel: ModelSchema = {
status
:
ModelStatusEnum
.
pending
,
status
:
ModelStatusEnum
.
pending
,
updateTime
:
Date
.
now
(),
updateTime
:
Date
.
now
(),
chat
:
{
chat
:
{
useKb
:
false
,
relatedKbs
:
[]
,
searchMode
:
ModelVectorSearchModeEnum
.
hightSimilarity
,
searchMode
:
ModelVectorSearchModeEnum
.
hightSimilarity
,
systemPrompt
:
''
,
systemPrompt
:
''
,
temperature
:
0
,
temperature
:
0
,
...
@@ -153,13 +153,6 @@ export const defaultModel: ModelSchema = {
...
@@ -153,13 +153,6 @@ export const defaultModel: ModelSchema = {
isShareDetail
:
false
,
isShareDetail
:
false
,
intro
:
''
,
intro
:
''
,
collection
:
0
collection
:
0
},
security
:
{
domain
:
[
'*'
],
contextMaxLen
:
1
,
contentMaxLen
:
1
,
expiredTime
:
9999
,
maxLoadAmount
:
1
}
}
};
};
...
...
src/constants/theme.ts
View file @
5bf95bd8
import
{
extendTheme
,
defineStyleConfig
,
ComponentStyleConfig
}
from
'@chakra-ui/react'
;
import
{
extendTheme
,
defineStyleConfig
,
ComponentStyleConfig
}
from
'@chakra-ui/react'
;
// @ts-ignore
// @ts-ignore
import
{
modalAnatomy
,
switchAnatomy
,
selectAnatomy
}
from
'@chakra-ui/anatomy'
;
import
{
modalAnatomy
,
switchAnatomy
,
selectAnatomy
,
checkboxAnatomy
}
from
'@chakra-ui/anatomy'
;
// @ts-ignore
// @ts-ignore
import
{
createMultiStyleConfigHelpers
}
from
'@chakra-ui/styled-system'
;
import
{
createMultiStyleConfigHelpers
}
from
'@chakra-ui/styled-system'
;
...
@@ -11,6 +11,8 @@ const { definePartsStyle: switchPart, defineMultiStyleConfig: switchMultiStyle }
...
@@ -11,6 +11,8 @@ const { definePartsStyle: switchPart, defineMultiStyleConfig: switchMultiStyle }
createMultiStyleConfigHelpers
(
switchAnatomy
.
keys
);
createMultiStyleConfigHelpers
(
switchAnatomy
.
keys
);
const
{
definePartsStyle
:
selectPart
,
defineMultiStyleConfig
:
selectMultiStyle
}
=
const
{
definePartsStyle
:
selectPart
,
defineMultiStyleConfig
:
selectMultiStyle
}
=
createMultiStyleConfigHelpers
(
selectAnatomy
.
keys
);
createMultiStyleConfigHelpers
(
selectAnatomy
.
keys
);
const
{
definePartsStyle
:
checkboxPart
,
defineMultiStyleConfig
:
checkboxMultiStyle
}
=
createMultiStyleConfigHelpers
(
checkboxAnatomy
.
keys
);
// modal 弹窗
// modal 弹窗
const
ModalTheme
=
defineMultiStyleConfig
({
const
ModalTheme
=
defineMultiStyleConfig
({
...
...
src/pages/api/chat/chat.ts
View file @
5bf95bd8
...
@@ -54,7 +54,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -54,7 +54,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const
prompts
=
[...
content
,
prompt
];
const
prompts
=
[...
content
,
prompt
];
// 使用了知识库搜索
// 使用了知识库搜索
if
(
model
.
chat
.
useKb
)
{
if
(
model
.
chat
.
relatedKbs
.
length
>
0
)
{
const
{
code
,
searchPrompts
}
=
await
searchKb
({
const
{
code
,
searchPrompts
}
=
await
searchKb
({
userOpenAiKey
,
userOpenAiKey
,
prompts
,
prompts
,
...
...
src/pages/api/chat/shareChat/chat.ts
View file @
5bf95bd8
...
@@ -50,7 +50,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -50,7 +50,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const
modelConstantsData
=
ChatModelMap
[
model
.
chat
.
chatModel
];
const
modelConstantsData
=
ChatModelMap
[
model
.
chat
.
chatModel
];
// 使用了知识库搜索
// 使用了知识库搜索
if
(
model
.
chat
.
useKb
)
{
if
(
model
.
chat
.
relatedKbs
.
length
>
0
)
{
const
{
code
,
searchPrompts
}
=
await
searchKb
({
const
{
code
,
searchPrompts
}
=
await
searchKb
({
userOpenAiKey
,
userOpenAiKey
,
prompts
,
prompts
,
...
...
src/pages/api/model/update.ts
View file @
5bf95bd8
...
@@ -9,10 +9,10 @@ import { authModel } from '@/service/utils/auth';
...
@@ -9,10 +9,10 @@ import { authModel } from '@/service/utils/auth';
/* 获取我的模型 */
/* 获取我的模型 */
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
try
{
try
{
const
{
name
,
avatar
,
chat
,
share
,
security
}
=
req
.
body
as
ModelUpdateParams
;
const
{
name
,
avatar
,
chat
,
share
}
=
req
.
body
as
ModelUpdateParams
;
const
{
modelId
}
=
req
.
query
as
{
modelId
:
string
};
const
{
modelId
}
=
req
.
query
as
{
modelId
:
string
};
if
(
!
name
||
!
chat
||
!
security
||
!
modelId
)
{
if
(
!
name
||
!
chat
||
!
modelId
)
{
throw
new
Error
(
'参数错误'
);
throw
new
Error
(
'参数错误'
);
}
}
...
@@ -38,8 +38,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
...
@@ -38,8 +38,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
chat
,
chat
,
'share.isShare'
:
share
.
isShare
,
'share.isShare'
:
share
.
isShare
,
'share.isShareDetail'
:
share
.
isShareDetail
,
'share.isShareDetail'
:
share
.
isShareDetail
,
'share.intro'
:
share
.
intro
,
'share.intro'
:
share
.
intro
security
}
}
);
);
...
...
src/pages/api/openapi/chat/chat.ts
View file @
5bf95bd8
...
@@ -70,7 +70,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -70,7 +70,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const
modelConstantsData
=
ChatModelMap
[
model
.
chat
.
chatModel
];
const
modelConstantsData
=
ChatModelMap
[
model
.
chat
.
chatModel
];
// 使用了知识库搜索
// 使用了知识库搜索
if
(
model
.
chat
.
useKb
)
{
if
(
model
.
chat
.
relatedKbs
.
length
>
0
)
{
const
similarity
=
ModelVectorSearchModeMap
[
model
.
chat
.
searchMode
]?.
similarity
||
0.22
;
const
similarity
=
ModelVectorSearchModeMap
[
model
.
chat
.
searchMode
]?.
similarity
||
0.22
;
const
{
code
,
searchPrompts
}
=
await
searchKb
({
const
{
code
,
searchPrompts
}
=
await
searchKb
({
...
...
src/pages/model/components/detail/components/ModelEditForm.tsx
View file @
5bf95bd8
...
@@ -32,11 +32,9 @@ import {
...
@@ -32,11 +32,9 @@ import {
Th
,
Th
,
Td
,
Td
,
TableContainer
,
TableContainer
,
IconButton
Checkbox
}
from
'@chakra-ui/react'
;
}
from
'@chakra-ui/react'
;
import
{
DeleteIcon
}
from
'@chakra-ui/icons'
;
import
{
QuestionOutlineIcon
}
from
'@chakra-ui/icons'
;
import
{
QuestionOutlineIcon
}
from
'@chakra-ui/icons'
;
import
type
{
ModelSchema
}
from
'@/types/mongoSchema'
;
import
{
useForm
,
UseFormReturn
}
from
'react-hook-form'
;
import
{
useForm
,
UseFormReturn
}
from
'react-hook-form'
;
import
{
ChatModelMap
,
ModelVectorSearchModeMap
,
getChatModelList
}
from
'@/constants/model'
;
import
{
ChatModelMap
,
ModelVectorSearchModeMap
,
getChatModelList
}
from
'@/constants/model'
;
import
{
formatPrice
}
from
'@/utils/user'
;
import
{
formatPrice
}
from
'@/utils/user'
;
...
@@ -49,9 +47,12 @@ import { getShareChatList, createShareChat, delShareChatById } from '@/api/chat'
...
@@ -49,9 +47,12 @@ import { getShareChatList, createShareChat, delShareChatById } from '@/api/chat'
import
{
useRouter
}
from
'next/router'
;
import
{
useRouter
}
from
'next/router'
;
import
{
defaultShareChat
}
from
'@/constants/model'
;
import
{
defaultShareChat
}
from
'@/constants/model'
;
import
type
{
ShareChatEditType
}
from
'@/types/model'
;
import
type
{
ShareChatEditType
}
from
'@/types/model'
;
import
type
{
ModelSchema
}
from
'@/types/mongoSchema'
;
import
{
formatTimeToChatTime
,
useCopyData
}
from
'@/utils/tools'
;
import
{
formatTimeToChatTime
,
useCopyData
}
from
'@/utils/tools'
;
import
MyIcon
from
'@/components/Icon'
;
import
MyIcon
from
'@/components/Icon'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
import
{
useUserStore
}
from
'@/store/user'
;
import
type
{
KbItemType
}
from
'@/types/plugin'
;
const
ModelEditForm
=
({
const
ModelEditForm
=
({
formHooks
,
formHooks
,
...
@@ -62,10 +63,11 @@ const ModelEditForm = ({
...
@@ -62,10 +63,11 @@ const ModelEditForm = ({
isOwner
:
boolean
;
isOwner
:
boolean
;
handleDelModel
:
()
=>
void
;
handleDelModel
:
()
=>
void
;
})
=>
{
})
=>
{
const
{
toast
}
=
useToast
();
const
{
modelId
}
=
useRouter
().
query
as
{
modelId
:
string
};
const
{
modelId
}
=
useRouter
().
query
as
{
modelId
:
string
};
const
{
setLoading
}
=
useGlobalStore
();
const
[
refresh
,
setRefresh
]
=
useState
(
false
);
const
[
refresh
,
setRefresh
]
=
useState
(
false
);
const
{
toast
}
=
useToast
();
const
{
setLoading
}
=
useGlobalStore
();
const
{
loadKbList
}
=
useUserStore
();
const
{
openConfirm
,
ConfirmChild
}
=
useConfirm
({
const
{
openConfirm
,
ConfirmChild
}
=
useConfirm
({
content
:
'确认删除该AI助手?'
content
:
'确认删除该AI助手?'
...
@@ -86,6 +88,11 @@ const ModelEditForm = ({
...
@@ -86,6 +88,11 @@ const ModelEditForm = ({
onOpen
:
onOpenCreateShareChat
,
onOpen
:
onOpenCreateShareChat
,
onClose
:
onCloseCreateShareChat
onClose
:
onCloseCreateShareChat
}
=
useDisclosure
();
}
=
useDisclosure
();
const
{
isOpen
:
isOpenKbSelect
,
onOpen
:
onOpenKbSelect
,
onClose
:
onCloseKbSelect
}
=
useDisclosure
();
const
{
File
,
onOpen
:
onOpenSelectFile
}
=
useSelectFile
({
const
{
File
,
onOpen
:
onOpenSelectFile
}
=
useSelectFile
({
fileType
:
'.jpg,.png'
,
fileType
:
'.jpg,.png'
,
multiple
:
false
multiple
:
false
...
@@ -153,11 +160,41 @@ ${e.password ? `密码为: ${e.password}` : ''}`;
...
@@ -153,11 +160,41 @@ ${e.password ? `密码为: ${e.password}` : ''}`;
]
]
);
);
// format share used token
const
formatTokens
=
(
tokens
:
number
)
=>
{
const
formatTokens
=
(
tokens
:
number
)
=>
{
if
(
tokens
<
10000
)
return
tokens
;
if
(
tokens
<
10000
)
return
tokens
;
return
`
${(
tokens
/
10000
).
toFixed
(
2
)}
万`
;
return
`
${(
tokens
/
10000
).
toFixed
(
2
)}
万`
;
};
};
// init kb select list
const
{
data
:
kbList
=
[]
}
=
useQuery
([
'loadKbList'
],
()
=>
loadKbList
());
const
RenderSelectedKbList
=
useCallback
(()
=>
{
const
kbs
=
getValues
(
'chat.relatedKbs'
).
map
((
id
)
=>
kbList
.
find
((
kb
)
=>
kb
.
_id
===
id
));
return
(
<>
{
kbs
.
map
((
item
)
=>
item
?
(
<
Card
key=
{
item
.
_id
}
p=
{
3
}
mt=
{
3
}
>
<
Flex
alignItems=
{
'center'
}
>
<
Image
src=
{
item
.
avatar
}
fallbackSrc=
"/icon/logo.png"
w=
{
'20px'
}
h=
{
'20px'
}
alt=
""
></
Image
>
<
Box
ml=
{
3
}
fontWeight=
{
'bold'
}
>
{
item
.
name
}
</
Box
>
</
Flex
>
</
Card
>
)
:
null
)
}
</>
);
},
[
getValues
,
kbList
]);
return
(
return
(
<>
<>
{
/* basic info */
}
{
/* basic info */
}
...
@@ -292,18 +329,7 @@ ${e.password ? `密码为: ${e.password}` : ''}`;
...
@@ -292,18 +329,7 @@ ${e.password ? `密码为: ${e.password}` : ''}`;
</
Slider
>
</
Slider
>
</
Flex
>
</
Flex
>
</
FormControl
>
</
FormControl
>
<
Flex
mt=
{
4
}
alignItems=
{
'center'
}
>
{
getValues
(
'chat.relatedKbs'
).
length
>
0
&&
(
<
Box
mr=
{
4
}
>
知识库搜索
</
Box
>
<
Switch
isDisabled=
{
!
isOwner
}
isChecked=
{
getValues
(
'chat.useKb'
)
}
onChange=
{
()
=>
{
setValue
(
'chat.useKb'
,
!
getValues
(
'chat.useKb'
));
setRefresh
(
!
refresh
);
}
}
/>
</
Flex
>
{
getValues
(
'chat.useKb'
)
&&
(
<
Flex
mt=
{
4
}
alignItems=
{
'center'
}
>
<
Flex
mt=
{
4
}
alignItems=
{
'center'
}
>
<
Box
mr=
{
4
}
whiteSpace=
{
'nowrap'
}
>
<
Box
mr=
{
4
}
whiteSpace=
{
'nowrap'
}
>
搜索模式
 
搜索模式
 
...
@@ -339,7 +365,9 @@ ${e.password ? `密码为: ${e.password}` : ''}`;
...
@@ -339,7 +365,9 @@ ${e.password ? `密码为: ${e.password}` : ''}`;
<
Box
fontWeight=
{
'bold'
}
>
分享设置
</
Box
>
<
Box
fontWeight=
{
'bold'
}
>
分享设置
</
Box
>
<
Box
>
<
Box
>
<
Flex
mt=
{
5
}
alignItems=
{
'center'
}
>
<
Flex
mt=
{
5
}
alignItems=
{
'center'
}
>
<
Box
mr=
{
1
}
>
模型分享:
</
Box
>
<
Box
mr=
{
1
}
fontSize=
{
[
'sm'
,
'md'
]
}
>
模型分享:
</
Box
>
<
Tooltip
label=
"开启模型分享后,你的模型将会出现在共享市场,可供 FastGpt 所有用户使用。用户使用时不会消耗你的 tokens,而是消耗使用者的 tokens。"
>
<
Tooltip
label=
"开启模型分享后,你的模型将会出现在共享市场,可供 FastGpt 所有用户使用。用户使用时不会消耗你的 tokens,而是消耗使用者的 tokens。"
>
<
QuestionOutlineIcon
mr=
{
3
}
/>
<
QuestionOutlineIcon
mr=
{
3
}
/>
</
Tooltip
>
</
Tooltip
>
...
@@ -350,7 +378,8 @@ ${e.password ? `密码为: ${e.password}` : ''}`;
...
@@ -350,7 +378,8 @@ ${e.password ? `密码为: ${e.password}` : ''}`;
setRefresh
(
!
refresh
);
setRefresh
(
!
refresh
);
}
}
}
}
/>
/>
<
Box
ml=
{
12
}
mr=
{
1
}
>
<
Box
ml=
{
12
}
mr=
{
1
}
fontSize=
{
[
'sm'
,
'md'
]
}
>
分享模型细节:
分享模型细节:
</
Box
>
</
Box
>
<
Tooltip
label=
"开启分享详情后,其他用户可以查看该模型的特有数据:温度、提示词和数据集。"
>
<
Tooltip
label=
"开启分享详情后,其他用户可以查看该模型的特有数据:温度、提示词和数据集。"
>
...
@@ -376,9 +405,23 @@ ${e.password ? `密码为: ${e.password}` : ''}`;
...
@@ -376,9 +405,23 @@ ${e.password ? `密码为: ${e.password}` : ''}`;
</
Box
>
</
Box
>
</
Box
>
</
Box
>
</
Card
>
</
Card
>
{
/* shareChat */
}
<
Card
p=
{
4
}
>
<
Card
p=
{
4
}
>
<
Flex
justifyContent=
{
'space-between'
}
>
<
Flex
justifyContent=
{
'space-between'
}
>
<
Box
fontWeight=
{
'bold'
}
>
关联的知识库
</
Box
>
<
Button
size=
{
'sm'
}
variant=
{
'outline'
}
colorScheme=
{
'myBlue'
}
onClick=
{
onOpenKbSelect
}
>
选择
</
Button
>
</
Flex
>
<
RenderSelectedKbList
/>
</
Card
>
{
/* shareChat */
}
<
Card
p=
{
4
}
gridColumnStart=
{
1
}
gridColumnEnd=
{
[
2
,
3
]
}
>
<
Flex
justifyContent=
{
'space-between'
}
>
<
Box
fontWeight=
{
'bold'
}
>
<
Box
fontWeight=
{
'bold'
}
>
免登录聊天窗口
免登录聊天窗口
<
Tooltip
label=
"可以直接分享该模型给其他用户去进行对话,对方无需登录即可直接进行对话。注意,这个功能会消耗你账号的tokens。请保管好链接和密码。"
>
<
Tooltip
label=
"可以直接分享该模型给其他用户去进行对话,对方无需登录即可直接进行对话。注意,这个功能会消耗你账号的tokens。请保管好链接和密码。"
>
...
@@ -410,7 +453,7 @@ ${e.password ? `密码为: ${e.password}` : ''}`;
...
@@ -410,7 +453,7 @@ ${e.password ? `密码为: ${e.password}` : ''}`;
<
Th
>
最大上下文
</
Th
>
<
Th
>
最大上下文
</
Th
>
<
Th
>
tokens消耗
</
Th
>
<
Th
>
tokens消耗
</
Th
>
<
Th
>
最后使用时间
</
Th
>
<
Th
>
最后使用时间
</
Th
>
<
Th
></
Th
>
<
Th
>
操作
</
Th
>
</
Tr
>
</
Tr
>
</
Thead
>
</
Thead
>
<
Tbody
>
<
Tbody
>
...
@@ -539,6 +582,52 @@ ${e.password ? `密码为: ${e.password}` : ''}`;
...
@@ -539,6 +582,52 @@ ${e.password ? `密码为: ${e.password}` : ''}`;
</
ModalFooter
>
</
ModalFooter
>
</
ModalContent
>
</
ModalContent
>
</
Modal
>
</
Modal
>
{
/* select kb modal */
}
<
Modal
isOpen=
{
isOpenKbSelect
}
onClose=
{
onCloseKbSelect
}
>
<
ModalOverlay
/>
<
ModalContent
>
<
ModalHeader
>
选择关联的知识库
</
ModalHeader
>
<
ModalCloseButton
/>
<
ModalBody
>
{
kbList
.
map
((
item
)
=>
(
<
Card
key=
{
item
.
_id
}
p=
{
3
}
mb=
{
3
}
>
<
Checkbox
isChecked=
{
getValues
(
'chat.relatedKbs'
).
includes
(
item
.
_id
)
}
onChange=
{
(
e
)
=>
{
const
ids
=
getValues
(
'chat.relatedKbs'
);
// toggle to true
if
(
e
.
target
.
checked
)
{
setValue
(
'chat.relatedKbs'
,
ids
.
concat
(
item
.
_id
));
}
else
{
const
i
=
ids
.
findIndex
((
id
)
=>
id
===
item
.
_id
);
ids
.
splice
(
i
,
1
);
setValue
(
'chat.relatedKbs'
,
ids
);
}
setRefresh
(
!
refresh
);
}
}
>
<
Flex
alignItems=
{
'center'
}
>
<
Image
src=
{
item
.
avatar
}
fallbackSrc=
"/icon/logo.png"
w=
{
'20px'
}
h=
{
'20px'
}
alt=
""
></
Image
>
<
Box
ml=
{
3
}
fontWeight=
{
'bold'
}
>
{
item
.
name
}
</
Box
>
</
Flex
>
</
Checkbox
>
</
Card
>
))
}
</
ModalBody
>
<
ModalFooter
>
<
Button
onClick=
{
onCloseKbSelect
}
>
完成,记得点保存修改
</
Button
>
</
ModalFooter
>
</
ModalContent
>
</
Modal
>
<
File
onSelect=
{
onSelectFile
}
/>
<
File
onSelect=
{
onSelectFile
}
/>
<
ConfirmChild
/>
<
ConfirmChild
/>
</>
</>
...
...
src/pages/model/components/detail/index.tsx
View file @
5bf95bd8
...
@@ -2,10 +2,9 @@ import React, { useCallback, useState, useMemo, useEffect } from 'react';
...
@@ -2,10 +2,9 @@ import React, { useCallback, useState, useMemo, useEffect } from 'react';
import
{
useRouter
}
from
'next/router'
;
import
{
useRouter
}
from
'next/router'
;
import
{
delModelById
,
putModelById
}
from
'@/api/model'
;
import
{
delModelById
,
putModelById
}
from
'@/api/model'
;
import
type
{
ModelSchema
}
from
'@/types/mongoSchema'
;
import
type
{
ModelSchema
}
from
'@/types/mongoSchema'
;
import
{
Card
,
Box
,
Flex
,
Button
,
Tag
,
Grid
}
from
'@chakra-ui/react'
;
import
{
Card
,
Box
,
Flex
,
Button
,
Grid
}
from
'@chakra-ui/react'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
useForm
}
from
'react-hook-form'
;
import
{
useForm
}
from
'react-hook-form'
;
import
{
formatModelStatus
}
from
'@/constants/model'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
useUserStore
}
from
'@/store/user'
;
import
{
useUserStore
}
from
'@/store/user'
;
import
{
useLoading
}
from
'@/hooks/useLoading'
;
import
{
useLoading
}
from
'@/hooks/useLoading'
;
...
@@ -18,7 +17,7 @@ const ModelDetail = ({ modelId, isPc }: { modelId: string; isPc: boolean }) => {
...
@@ -18,7 +17,7 @@ const ModelDetail = ({ modelId, isPc }: { modelId: string; isPc: boolean }) => {
const
{
Loading
,
setIsLoading
}
=
useLoading
();
const
{
Loading
,
setIsLoading
}
=
useLoading
();
const
[
btnLoading
,
setBtnLoading
]
=
useState
(
false
);
const
[
btnLoading
,
setBtnLoading
]
=
useState
(
false
);
const
formHooks
=
useForm
<
ModelSchema
>
({
const
formHooks
=
useForm
({
defaultValues
:
modelDetail
defaultValues
:
modelDetail
});
});
...
@@ -84,13 +83,9 @@ const ModelDetail = ({ modelId, isPc }: { modelId: string; isPc: boolean }) => {
...
@@ -84,13 +83,9 @@ const ModelDetail = ({ modelId, isPc }: { modelId: string; isPc: boolean }) => {
name
:
data
.
name
,
name
:
data
.
name
,
avatar
:
data
.
avatar
||
'/icon/logo.png'
,
avatar
:
data
.
avatar
||
'/icon/logo.png'
,
chat
:
data
.
chat
,
chat
:
data
.
chat
,
share
:
data
.
share
,
share
:
data
.
share
security
:
data
.
security
});
toast
({
title
:
'更新成功'
,
status
:
'success'
});
});
refreshModel
.
updateModelDetail
(
data
);
refreshModel
.
updateModelDetail
(
data
);
}
catch
(
err
:
any
)
{
}
catch
(
err
:
any
)
{
toast
({
toast
({
...
@@ -120,18 +115,16 @@ const ModelDetail = ({ modelId, isPc }: { modelId: string; isPc: boolean }) => {
...
@@ -120,18 +115,16 @@ const ModelDetail = ({ modelId, isPc }: { modelId: string; isPc: boolean }) => {
});
});
},
[
formHooks
.
formState
.
errors
,
toast
]);
},
[
formHooks
.
formState
.
errors
,
toast
]);
useEffect
(()
=>
{
const
saveUpdateModel
=
useCallback
(
router
.
prefetch
(
'/chat'
);
()
=>
formHooks
.
handleSubmit
(
saveSubmitSuccess
,
saveSubmitError
)(),
[
formHooks
,
saveSubmitError
,
saveSubmitSuccess
]
window
.
onbeforeunload
=
(
e
)
=>
{
);
e
.
preventDefault
();
e
.
returnValue
=
'内容已修改,确认离开页面吗?'
;
};
useEffect
(()
=>
{
return
()
=>
{
return
()
=>
{
window
.
onbeforeunload
=
null
;
saveUpdateModel
()
;
};
};
},
[
router
]);
},
[]);
return
canRead
?
(
return
canRead
?
(
<
Box
h=
{
'100%'
}
p=
{
5
}
overflow=
{
'overlay'
}
position=
{
'relative'
}
>
<
Box
h=
{
'100%'
}
p=
{
5
}
overflow=
{
'overlay'
}
position=
{
'relative'
}
>
...
@@ -142,13 +135,6 @@ const ModelDetail = ({ modelId, isPc }: { modelId: string; isPc: boolean }) => {
...
@@ -142,13 +135,6 @@ const ModelDetail = ({ modelId, isPc }: { modelId: string; isPc: boolean }) => {
<
Box
fontSize=
{
'xl'
}
fontWeight=
{
'bold'
}
>
<
Box
fontSize=
{
'xl'
}
fontWeight=
{
'bold'
}
>
{
modelDetail
.
name
}
{
modelDetail
.
name
}
</
Box
>
</
Box
>
<
Tag
ml=
{
2
}
variant=
"solid"
colorScheme=
{
formatModelStatus
[
modelDetail
.
status
].
colorTheme
}
>
{
formatModelStatus
[
modelDetail
.
status
].
text
}
</
Tag
>
<
Box
flex=
{
1
}
/>
<
Box
flex=
{
1
}
/>
<
Button
variant=
{
'outline'
}
onClick=
{
handlePreviewChat
}
>
<
Button
variant=
{
'outline'
}
onClick=
{
handlePreviewChat
}
>
开始对话
开始对话
...
@@ -157,7 +143,18 @@ const ModelDetail = ({ modelId, isPc }: { modelId: string; isPc: boolean }) => {
...
@@ -157,7 +143,18 @@ const ModelDetail = ({ modelId, isPc }: { modelId: string; isPc: boolean }) => {
<
Button
<
Button
isLoading=
{
btnLoading
}
isLoading=
{
btnLoading
}
ml=
{
4
}
ml=
{
4
}
onClick=
{
formHooks
.
handleSubmit
(
saveSubmitSuccess
,
saveSubmitError
)
}
onClick=
{
async
()
=>
{
try
{
await
saveUpdateModel
();
toast
({
title
:
'更新成功'
,
status
:
'success'
});
}
catch
(
error
)
{
console
.
log
(
error
);
error
;
}
}
}
>
>
保存修改
保存修改
</
Button
>
</
Button
>
...
@@ -169,9 +166,6 @@ const ModelDetail = ({ modelId, isPc }: { modelId: string; isPc: boolean }) => {
...
@@ -169,9 +166,6 @@ const ModelDetail = ({ modelId, isPc }: { modelId: string; isPc: boolean }) => {
<
Box
as=
{
'h3'
}
fontSize=
{
'xl'
}
fontWeight=
{
'bold'
}
flex=
{
1
}
>
<
Box
as=
{
'h3'
}
fontSize=
{
'xl'
}
fontWeight=
{
'bold'
}
flex=
{
1
}
>
{
modelDetail
.
name
}
{
modelDetail
.
name
}
</
Box
>
</
Box
>
<
Tag
ml=
{
2
}
colorScheme=
{
formatModelStatus
[
modelDetail
.
status
].
colorTheme
}
>
{
formatModelStatus
[
modelDetail
.
status
].
text
}
</
Tag
>
</
Flex
>
</
Flex
>
<
Box
mt=
{
4
}
textAlign=
{
'right'
}
>
<
Box
mt=
{
4
}
textAlign=
{
'right'
}
>
<
Button
variant=
{
'outline'
}
size=
{
'sm'
}
onClick=
{
handlePreviewChat
}
>
<
Button
variant=
{
'outline'
}
size=
{
'sm'
}
onClick=
{
handlePreviewChat
}
>
...
@@ -182,7 +176,18 @@ const ModelDetail = ({ modelId, isPc }: { modelId: string; isPc: boolean }) => {
...
@@ -182,7 +176,18 @@ const ModelDetail = ({ modelId, isPc }: { modelId: string; isPc: boolean }) => {
ml=
{
4
}
ml=
{
4
}
size=
{
'sm'
}
size=
{
'sm'
}
isLoading=
{
btnLoading
}
isLoading=
{
btnLoading
}
onClick=
{
formHooks
.
handleSubmit
(
saveSubmitSuccess
,
saveSubmitError
)
}
onClick=
{
async
()
=>
{
try
{
await
saveUpdateModel
();
toast
({
title
:
'更新成功'
,
status
:
'success'
});
}
catch
(
error
)
{
console
.
log
(
error
);
error
;
}
}
}
>
>
保存修改
保存修改
</
Button
>
</
Button
>
...
...
src/service/models/model.ts
View file @
5bf95bd8
...
@@ -31,10 +31,10 @@ const ModelSchema = new Schema({
...
@@ -31,10 +31,10 @@ const ModelSchema = new Schema({
default
:
()
=>
new
Date
()
default
:
()
=>
new
Date
()
},
},
chat
:
{
chat
:
{
useKb
:
{
relatedKbs
:
{
// use knowledge base to search
type
:
[
Schema
.
Types
.
ObjectId
],
type
:
Boolean
,
ref
:
'kb'
,
default
:
false
default
:
[]
},
},
searchMode
:
{
searchMode
:
{
// knowledge base search mode
// knowledge base search mode
...
@@ -79,33 +79,6 @@ const ModelSchema = new Schema({
...
@@ -79,33 +79,6 @@ const ModelSchema = new Schema({
type
:
Number
,
type
:
Number
,
default
:
0
default
:
0
}
}
},
security
:
{
type
:
{
domain
:
{
type
:
[
String
],
default
:
[
'*'
]
},
contextMaxLen
:
{
type
:
Number
,
default
:
20
},
contentMaxLen
:
{
type
:
Number
,
default
:
4000
},
expiredTime
:
{
type
:
Number
,
default
:
1
,
set
:
(
val
:
number
)
=>
val
*
(
60
*
60
*
1000
)
},
maxLoadAmount
:
{
// 负数代表不限制
type
:
Number
,
default
:
-
1
}
},
default
:
{}
}
}
});
});
...
...
src/service/plugins/searchKb.ts
View file @
5bf95bd8
...
@@ -48,7 +48,7 @@ export const searchKb = async ({
...
@@ -48,7 +48,7 @@ export const searchKb = async ({
where
:
[
where
:
[
[
'status'
,
ModelDataStatusEnum
.
ready
],
[
'status'
,
ModelDataStatusEnum
.
ready
],
'AND'
,
'AND'
,
[
'model_id'
,
model
.
_id
]
,
`kb_id IN (
${
model
.
chat
.
relatedKbs
.
map
((
item
)
=>
`'
${
item
}
'`
).
join
(
','
)}
)`
,
'AND'
,
'AND'
,
`vector <=> '[
${
promptVector
}
]' <
${
similarity
}
`
`vector <=> '[
${
promptVector
}
]' <
${
similarity
}
`
],
],
...
...
src/service/utils/auth.ts
View file @
5bf95bd8
...
@@ -34,6 +34,13 @@ export const authToken = (req: NextApiRequest): Promise<string> => {
...
@@ -34,6 +34,13 @@ export const authToken = (req: NextApiRequest): Promise<string> => {
});
});
};
};
export
const
getOpenAiKey
=
()
=>
{
// 纯字符串类型
const
keys
=
process
.
env
.
OPENAIKEY
?.
split
(
','
)
||
[];
const
i
=
Math
.
floor
(
Math
.
random
()
*
keys
.
length
);
return
keys
[
i
]
||
(
process
.
env
.
OPENAIKEY
as
string
);
};
/* 获取 api 请求的 key */
/* 获取 api 请求的 key */
export
const
getApiKey
=
async
({
export
const
getApiKey
=
async
({
model
,
model
,
...
@@ -52,7 +59,7 @@ export const getApiKey = async ({
...
@@ -52,7 +59,7 @@ export const getApiKey = async ({
const
keyMap
=
{
const
keyMap
=
{
[
OpenAiChatEnum
.
GPT35
]:
{
[
OpenAiChatEnum
.
GPT35
]:
{
userOpenAiKey
:
user
.
openaiKey
||
''
,
userOpenAiKey
:
user
.
openaiKey
||
''
,
systemAuthKey
:
process
.
env
.
OPENAIKEY
as
string
systemAuthKey
:
getOpenAiKey
()
as
string
},
},
[
OpenAiChatEnum
.
GPT4
]:
{
[
OpenAiChatEnum
.
GPT4
]:
{
userOpenAiKey
:
user
.
openaiKey
||
''
,
userOpenAiKey
:
user
.
openaiKey
||
''
,
...
...
src/service/utils/chat/openai.ts
View file @
5bf95bd8
...
@@ -7,6 +7,7 @@ import { adaptChatItem_openAI } from '@/utils/chat/openai';
...
@@ -7,6 +7,7 @@ import { adaptChatItem_openAI } from '@/utils/chat/openai';
import
{
modelToolMap
}
from
'@/utils/chat'
;
import
{
modelToolMap
}
from
'@/utils/chat'
;
import
{
ChatCompletionType
,
ChatContextFilter
,
StreamResponseType
}
from
'./index'
;
import
{
ChatCompletionType
,
ChatContextFilter
,
StreamResponseType
}
from
'./index'
;
import
{
ChatRoleEnum
}
from
'@/constants/chat'
;
import
{
ChatRoleEnum
}
from
'@/constants/chat'
;
import
{
getOpenAiKey
}
from
'../auth'
;
export
const
getOpenAIApi
=
(
apiKey
:
string
)
=>
{
export
const
getOpenAIApi
=
(
apiKey
:
string
)
=>
{
const
configuration
=
new
Configuration
({
const
configuration
=
new
Configuration
({
...
@@ -27,7 +28,7 @@ export const openaiCreateEmbedding = async ({
...
@@ -27,7 +28,7 @@ export const openaiCreateEmbedding = async ({
userId
:
string
;
userId
:
string
;
textArr
:
string
[];
textArr
:
string
[];
})
=>
{
})
=>
{
const
systemAuthKey
=
process
.
env
.
OPENAIKEY
as
string
;
const
systemAuthKey
=
getOpenAiKey
()
;
// 获取 chatAPI
// 获取 chatAPI
const
chatAPI
=
getOpenAIApi
(
userOpenAiKey
||
systemAuthKey
);
const
chatAPI
=
getOpenAIApi
(
userOpenAiKey
||
systemAuthKey
);
...
...
src/store/user.ts
View file @
5bf95bd8
...
@@ -2,7 +2,6 @@ import { create } from 'zustand';
...
@@ -2,7 +2,6 @@ import { create } from 'zustand';
import
{
devtools
,
persist
}
from
'zustand/middleware'
;
import
{
devtools
,
persist
}
from
'zustand/middleware'
;
import
{
immer
}
from
'zustand/middleware/immer'
;
import
{
immer
}
from
'zustand/middleware/immer'
;
import
type
{
UserType
,
UserUpdateParams
}
from
'@/types/user'
;
import
type
{
UserType
,
UserUpdateParams
}
from
'@/types/user'
;
import
type
{
ModelSchema
}
from
'@/types/mongoSchema'
;
import
{
getMyModels
,
getModelById
}
from
'@/api/model'
;
import
{
getMyModels
,
getModelById
}
from
'@/api/model'
;
import
{
formatPrice
}
from
'@/utils/user'
;
import
{
formatPrice
}
from
'@/utils/user'
;
import
{
getTokenLogin
}
from
'@/api/user'
;
import
{
getTokenLogin
}
from
'@/api/user'
;
...
@@ -11,6 +10,7 @@ import { ModelListItemType } from '@/types/model';
...
@@ -11,6 +10,7 @@ import { ModelListItemType } from '@/types/model';
import
{
KbItemType
}
from
'@/types/plugin'
;
import
{
KbItemType
}
from
'@/types/plugin'
;
import
{
getKbList
}
from
'@/api/plugins/kb'
;
import
{
getKbList
}
from
'@/api/plugins/kb'
;
import
{
defaultKbDetail
}
from
'@/constants/kb'
;
import
{
defaultKbDetail
}
from
'@/constants/kb'
;
import
type
{
ModelSchema
}
from
'@/types/mongoSchema'
;
type
State
=
{
type
State
=
{
userInfo
:
UserType
|
null
;
userInfo
:
UserType
|
null
;
...
@@ -34,7 +34,7 @@ type State = {
...
@@ -34,7 +34,7 @@ type State = {
lastKbId
:
string
;
lastKbId
:
string
;
setLastKbId
:
(
id
:
string
)
=>
void
;
setLastKbId
:
(
id
:
string
)
=>
void
;
myKbList
:
KbItemType
[];
myKbList
:
KbItemType
[];
loadKbList
:
(
init
?:
boolean
)
=>
Promise
<
null
>
;
loadKbList
:
(
init
?:
boolean
)
=>
Promise
<
KbItemType
[]
>
;
KbDetail
:
KbItemType
;
KbDetail
:
KbItemType
;
getKbDetail
:
(
id
:
string
)
=>
KbItemType
;
getKbDetail
:
(
id
:
string
)
=>
KbItemType
;
};
};
...
@@ -123,12 +123,12 @@ export const useUserStore = create<State>()(
...
@@ -123,12 +123,12 @@ export const useUserStore = create<State>()(
},
},
myKbList
:
[],
myKbList
:
[],
async
loadKbList
(
init
=
false
)
{
async
loadKbList
(
init
=
false
)
{
if
(
get
().
myKbList
.
length
>
0
&&
!
init
)
return
null
;
if
(
get
().
myKbList
.
length
>
0
&&
!
init
)
return
get
().
myKbList
;
const
res
=
await
getKbList
();
const
res
=
await
getKbList
();
set
((
state
)
=>
{
set
((
state
)
=>
{
state
.
myKbList
=
res
;
state
.
myKbList
=
res
;
});
});
return
null
;
return
res
;
},
},
KbDetail
:
defaultKbDetail
,
KbDetail
:
defaultKbDetail
,
getKbDetail
(
id
:
string
)
{
getKbDetail
(
id
:
string
)
{
...
...
src/types/model.d.ts
View file @
5bf95bd8
import
{
ModelStatusEnum
}
from
'@/constants/model'
;
import
{
ModelStatusEnum
}
from
'@/constants/model'
;
import
type
{
ModelSchema
}
from
'./mongoSchema'
;
import
type
{
ModelSchema
,
kbSchema
}
from
'./mongoSchema'
;
import
{
ChatModelType
,
ModelVectorSearchModeEnum
}
from
'@/constants/model'
;
export
type
ModelListItemType
=
{
export
type
ModelListItemType
=
{
_id
:
string
;
_id
:
string
;
...
@@ -13,7 +14,6 @@ export interface ModelUpdateParams {
...
@@ -13,7 +14,6 @@ export interface ModelUpdateParams {
avatar
:
string
;
avatar
:
string
;
chat
:
ModelSchema
[
'chat'
];
chat
:
ModelSchema
[
'chat'
];
share
:
ModelSchema
[
'share'
];
share
:
ModelSchema
[
'share'
];
security
:
ModelSchema
[
'security'
];
}
}
export
interface
ShareModelItem
{
export
interface
ShareModelItem
{
...
...
src/types/mongoSchema.d.ts
View file @
5bf95bd8
...
@@ -38,7 +38,7 @@ export interface ModelSchema {
...
@@ -38,7 +38,7 @@ export interface ModelSchema {
status
:
`
${
ModelStatusEnum
}
`
;
status
:
`
${
ModelStatusEnum
}
`
;
updateTime
:
number
;
updateTime
:
number
;
chat
:
{
chat
:
{
useKb
:
boolean
;
relatedKbs
:
string
[]
;
searchMode
:
`
${
ModelVectorSearchModeEnum
}
`
;
searchMode
:
`
${
ModelVectorSearchModeEnum
}
`
;
systemPrompt
:
string
;
systemPrompt
:
string
;
temperature
:
number
;
temperature
:
number
;
...
@@ -50,13 +50,6 @@ export interface ModelSchema {
...
@@ -50,13 +50,6 @@ export interface ModelSchema {
intro
:
string
;
intro
:
string
;
collection
:
number
;
collection
:
number
;
};
};
security
:
{
domain
:
string
[];
contextMaxLen
:
number
;
contentMaxLen
:
number
;
expiredTime
:
number
;
maxLoadAmount
:
number
;
};
}
}
export
interface
ModelPopulate
extends
ModelSchema
{
export
interface
ModelPopulate
extends
ModelSchema
{
...
...
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