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
5759cbea
authored
Mar 31, 2023
by
archer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
perf: 知识库录入
parent
a3d74ec4
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
143 additions
and
157 deletions
+143
-157
src/pages/api/chat/vectorGpt.ts
+4
-4
src/pages/chat/index.tsx
+81
-75
src/pages/model/detail/components/InputDataModal.tsx
+43
-53
src/pages/model/detail/components/ModelDataCard.tsx
+3
-6
src/pages/model/detail/components/ModelEditForm.tsx
+12
-19
No files found.
src/pages/api/chat/vectorGpt.ts
View file @
5759cbea
...
...
@@ -119,20 +119,20 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
.
select
(
'text q'
)
.
then
((
res
)
=>
{
if
(
!
res
)
return
''
;
const
questions
=
res
.
q
.
map
((
item
)
=>
item
.
text
).
join
(
' '
);
//
const questions = res.q.map((item) => item.text).join(' ');
const
answer
=
res
.
text
;
return
`
${
questions
}
${
answer
}
`
;
return
`
${
answer
}
`
;
});
})
)
).
filter
((
item
)
=>
item
);
// textArr 筛选,最多 3000 tokens
const
systemPrompt
=
systemPromptFilter
(
textArr
,
28
00
);
const
systemPrompt
=
systemPromptFilter
(
textArr
,
34
00
);
prompts
.
unshift
({
obj
:
'SYSTEM'
,
value
:
`
根据下面的知识回答问题:
${
systemPrompt
}
`
value
:
`
${
model
.
systemPrompt
}
。 我的知识库: "
${
systemPrompt
}
"
`
});
// 控制在 tokens 数量,防止超出
...
...
src/pages/chat/index.tsx
View file @
5759cbea
...
...
@@ -190,91 +190,97 @@ const Chat = ({ chatId }: { chatId: string }) => {
/**
* 发送一个内容
*/
const
sendPrompt
=
useCallback
(
async
()
=>
{
const
storeInput
=
inputVal
;
// 去除空行
const
val
=
inputVal
.
trim
()
.
split
(
'\n'
)
.
filter
((
val
)
=>
val
)
.
join
(
'\n'
);
if
(
!
chatData
?.
modelId
||
!
val
||
!
ChatBox
.
current
||
isChatting
)
{
return
;
}
// 长度校验
const
tokens
=
encode
(
val
).
length
;
const
model
=
modelList
.
find
((
item
)
=>
item
.
model
===
chatData
.
modelName
);
if
(
model
&&
tokens
>=
model
.
maxToken
)
{
toast
({
title
:
'单次输入超出 4000 tokens'
,
status
:
'warning'
});
return
;
}
const
newChatList
:
ChatSiteItemType
[]
=
[
...
chatData
.
history
,
{
obj
:
'Human'
,
value
:
val
,
status
:
'finish'
},
{
obj
:
'AI'
,
value
:
''
,
status
:
'loading'
const
sendPrompt
=
useCallback
(
async
(
e
?:
React
.
MouseEvent
<
HTMLDivElement
>
)
=>
{
e
?.
stopPropagation
();
e
?.
preventDefault
();
const
storeInput
=
inputVal
;
// 去除空行
const
val
=
inputVal
.
trim
()
.
split
(
'\n'
)
.
filter
((
val
)
=>
val
)
.
join
(
'\n'
);
if
(
!
chatData
?.
modelId
||
!
val
||
!
ChatBox
.
current
||
isChatting
)
{
return
;
}
];
// 插入内容
setChatData
((
state
)
=>
({
...
state
,
history
:
newChatList
}));
// 长度校验
const
tokens
=
encode
(
val
).
length
;
const
model
=
modelList
.
find
((
item
)
=>
item
.
model
===
chatData
.
modelName
);
// 清空输入内容
resetInputVal
(
''
);
scrollToBottom
();
try
{
await
gptChatPrompt
(
newChatList
[
newChatList
.
length
-
2
]);
// 如果是 Human 第一次发送,插入历史记录
const
humanChat
=
newChatList
.
filter
((
item
)
=>
item
.
obj
===
'Human'
);
if
(
humanChat
.
length
===
1
)
{
pushChatHistory
({
chatId
,
title
:
humanChat
[
0
].
value
if
(
model
&&
tokens
>=
model
.
maxToken
)
{
toast
({
title
:
'单次输入超出 4000 tokens'
,
status
:
'warning'
});
return
;
}
}
catch
(
err
:
any
)
{
toast
({
title
:
typeof
err
===
'string'
?
err
:
err
?.
message
||
'聊天出错了~'
,
status
:
'warning'
,
duration
:
5000
,
isClosable
:
true
});
resetInputVal
(
storeInput
);
const
newChatList
:
ChatSiteItemType
[]
=
[
...
chatData
.
history
,
{
obj
:
'Human'
,
value
:
val
,
status
:
'finish'
},
{
obj
:
'AI'
,
value
:
''
,
status
:
'loading'
}
];
// 插入内容
setChatData
((
state
)
=>
({
...
state
,
history
:
newChatList
.
slice
(
0
,
newChatList
.
length
-
2
)
history
:
newChatList
}));
}
},
[
inputVal
,
chatData
,
isChatting
,
resetInputVal
,
scrollToBottom
,
toast
,
gptChatPrompt
,
pushChatHistory
,
chatId
]);
// 清空输入内容
resetInputVal
(
''
);
scrollToBottom
();
try
{
await
gptChatPrompt
(
newChatList
[
newChatList
.
length
-
2
]);
// 如果是 Human 第一次发送,插入历史记录
const
humanChat
=
newChatList
.
filter
((
item
)
=>
item
.
obj
===
'Human'
);
if
(
humanChat
.
length
===
1
)
{
pushChatHistory
({
chatId
,
title
:
humanChat
[
0
].
value
});
}
}
catch
(
err
:
any
)
{
toast
({
title
:
typeof
err
===
'string'
?
err
:
err
?.
message
||
'聊天出错了~'
,
status
:
'warning'
,
duration
:
5000
,
isClosable
:
true
});
resetInputVal
(
storeInput
);
setChatData
((
state
)
=>
({
...
state
,
history
:
newChatList
.
slice
(
0
,
newChatList
.
length
-
2
)
}));
}
},
[
inputVal
,
chatData
,
isChatting
,
resetInputVal
,
scrollToBottom
,
toast
,
gptChatPrompt
,
pushChatHistory
,
chatId
]
);
// 删除一句话
const
delChatRecord
=
useCallback
(
...
...
src/pages/model/detail/components/InputDataModal.tsx
View file @
5759cbea
...
...
@@ -19,7 +19,7 @@ import { DeleteIcon } from '@chakra-ui/icons';
import
{
customAlphabet
}
from
'nanoid'
;
const
nanoid
=
customAlphabet
(
'abcdefghijklmnopqrstuvwxyz1234567890'
,
12
);
type
FormData
=
{
text
:
string
;
q
:
{
val
:
string
}[]
};
type
FormData
=
{
text
:
string
;
q
:
string
};
const
InputDataModal
=
({
onClose
,
...
...
@@ -36,17 +36,9 @@ const InputDataModal = ({
const
{
register
,
handleSubmit
,
control
}
=
useForm
<
FormData
>
({
defaultValues
:
{
text
:
''
,
q
:
[{
val
:
''
}]
q
:
''
}
});
const
{
fields
:
inputQ
,
append
:
appendQ
,
remove
:
removeQ
}
=
useFieldArray
({
control
,
name
:
'q'
});
const
sureImportData
=
useCallback
(
async
(
e
:
FormData
)
=>
{
...
...
@@ -58,10 +50,12 @@ const InputDataModal = ({
data
:
[
{
text
:
e
.
text
,
q
:
e
.
q
.
map
((
item
)
=>
({
id
:
nanoid
(),
text
:
item
.
val
}))
q
:
[
{
id
:
nanoid
(),
text
:
e
.
q
}
]
}
]
});
...
...
@@ -81,50 +75,46 @@ const InputDataModal = ({
);
return
(
<
Modal
isOpen=
{
true
}
onClose=
{
onClose
}
>
<
Modal
isOpen=
{
true
}
onClose=
{
onClose
}
isCentered
>
<
ModalOverlay
/>
<
ModalContent
maxW=
{
'min(900px, 90vw)'
}
maxH=
{
'80vh'
}
position=
{
'relative'
}
>
<
ModalContent
m=
{
0
}
display=
{
'flex'
}
flexDirection=
{
'column'
}
h=
{
'90vh'
}
maxW=
{
'90vw'
}
position=
{
'relative'
}
>
<
ModalHeader
>
手动导入
</
ModalHeader
>
<
ModalCloseButton
/>
<
Box
px=
{
6
}
pb=
{
2
}
overflowY=
{
'auto'
}
>
<
Box
mb=
{
2
}
>
知识点:
</
Box
>
<
Textarea
mb=
{
4
}
placeholder=
"知识点"
rows=
{
3
}
maxH=
{
'200px'
}
{
...
register
(`
text
`,
{
required
:
'知识点'
})}
/>
{
inputQ
.
map
((
item
,
index
)
=>
(
<
Box
key=
{
item
.
id
}
mb=
{
5
}
>
<
Box
mb=
{
2
}
>
问法
{
index
+
1
}
:
</
Box
>
<
Flex
>
<
Input
placeholder=
"问法"
{
...
register
(`
q
.
$
{
index
}
.
val
`,
{
required
:
'问法不能为空'
})}
></
Input
>
{
inputQ
.
length
>
1
&&
(
<
IconButton
icon=
{
<
DeleteIcon
/>
}
aria
-
label=
{
'delete'
}
colorScheme=
{
'gray'
}
variant=
{
'unstyled'
}
onClick=
{
()
=>
removeQ
(
index
)
}
/>
)
}
</
Flex
>
</
Box
>
))
}
</
Box
>
<
Flex
flex=
{
'1 0 0'
}
h=
{
0
}
px=
{
6
}
pb=
{
2
}
>
<
Box
flex=
{
2
}
mr=
{
4
}
h=
{
'100%'
}
>
<
Box
h=
{
'30px'
}
>
问题
</
Box
>
<
Textarea
placeholder=
"相关问题,可以回车输入多个问法, 最多500字"
maxLength=
{
500
}
resize=
{
'none'
}
h=
{
'calc(100% - 30px)'
}
{
...
register
(`
q
`,
{
required
:
'相关问题,可以回车输入多个问法'
})}
/>
</
Box
>
<
Box
flex=
{
3
}
h=
{
'100%'
}
>
<
Box
h=
{
'30px'
}
>
知识点
</
Box
>
<
Textarea
placeholder=
"知识点"
resize=
{
'none'
}
h=
{
'calc(100% - 30px)'
}
{
...
register
(`
text
`,
{
required
:
'知识点'
})}
/>
</
Box
>
</
Flex
>
<
Flex
px=
{
6
}
pt=
{
2
}
pb=
{
4
}
>
<
Button
alignSelf=
{
'flex-start'
}
variant=
{
'outline'
}
onClick=
{
()
=>
appendQ
({
val
:
''
})
}
>
增加问法
</
Button
>
<
Box
flex=
{
1
}
></
Box
>
<
Button
variant=
{
'outline'
}
mr=
{
3
}
onClick=
{
onClose
}
>
取消
...
...
src/pages/model/detail/components/ModelDataCard.tsx
View file @
5759cbea
...
...
@@ -50,7 +50,7 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => {
pageNum
}
=
usePagination
<
ModelDataSchema
>
({
api
:
getModelDataList
,
pageSize
:
10
,
pageSize
:
8
,
params
:
{
modelId
:
model
.
_id
}
...
...
@@ -119,7 +119,7 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => {
</
Flex
>
{
data
&&
data
.
length
>
0
&&
<
Box
fontSize=
{
'xs'
}
>
{
data
.
length
}
条数据正在拆分中...
</
Box
>
}
<
Box
mt=
{
4
}
>
<
TableContainer
h=
{
'600px'
}
overflowY=
{
'auto'
}
>
<
TableContainer
>
<
Table
variant=
{
'simple'
}
>
<
Thead
>
<
Tr
>
...
...
@@ -141,10 +141,7 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => {
whiteSpace=
{
'pre-wrap'
}
_notLast=
{
{
mb
:
1
}
}
>
Q
{
i
+
1
}
:
{
' '
}
<
Box
as=
{
'span'
}
userSelect=
{
'all'
}
>
{
item
.
text
}
</
Box
>
{
item
.
text
}
</
Box
>
))
}
</
Td
>
...
...
src/pages/model/detail/components/ModelEditForm.tsx
View file @
5759cbea
...
...
@@ -108,7 +108,7 @@ const ModelEditForm = ({
<
Slider
aria
-
label=
"slider-ex-1"
min=
{
1
}
min=
{
0
}
max=
{
10
}
step=
{
1
}
value=
{
getValues
(
'temperature'
)
}
...
...
@@ -138,24 +138,17 @@ const ModelEditForm = ({
</
Flex
>
</
FormControl
>
<
Box
mt=
{
4
}
>
{
canTrain
?
(
<
Box
fontWeight=
{
'bold'
}
>
训练的模型会自动根据知识库内容回答,无法设置系统prompt。注意:
使用该模型,在对话时需要消耗等多的 tokens
</
Box
>
)
:
(
<>
<
Box
mb=
{
1
}
>
系统提示词
</
Box
>
<
Textarea
rows=
{
6
}
maxLength=
{
-
1
}
{
...
register
('
systemPrompt
')}
placeholder=
{
'模型默认的 prompt 词,通过调整该内容,可以生成一个限定范围的模型。\n\n注意,改功能会影响对话的整体朝向!'
}
/>
</>
)
}
<
Box
mb=
{
1
}
>
系统提示词
</
Box
>
<
Textarea
rows=
{
6
}
maxLength=
{
-
1
}
{
...
register
('
systemPrompt
')}
placeholder=
{
canTrain
?
'训练的模型会根据知识库内容,生成一部分系统提示词,因此在对话时需要消耗更多的 tokens。你仍可以增加一些提示词,让其效果更精确。'
:
'模型默认的 prompt 词,通过调整该内容,可以生成一个限定范围的模型。\n\n注意,改功能会影响对话的整体朝向!'
}
/>
</
Box
>
</
Card
>
{
/* <Card p={4}>
...
...
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