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
83d755ad
authored
Jun 24, 2023
by
archer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: limit prompt
parent
ec9852fc
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
110 additions
and
52 deletions
+110
-52
client/src/api/response/chat.d.ts
+1
-0
client/src/components/Select/index.tsx
+1
-1
client/src/constants/model.ts
+1
-0
client/src/pages/api/chat/init.ts
+1
-0
client/src/pages/api/openapi/kb/appKbSearch.ts
+22
-10
client/src/pages/api/openapi/v1/chat/completions.ts
+31
-16
client/src/pages/chat/index.tsx
+7
-6
client/src/pages/model/components/detail/components/Settings.tsx
+41
-18
client/src/service/models/model.ts
+4
-1
client/src/types/mongoSchema.d.ts
+1
-0
No files found.
client/src/api/response/chat.d.ts
View file @
83d755ad
...
@@ -5,6 +5,7 @@ export interface InitChatResponse {
...
@@ -5,6 +5,7 @@ export interface InitChatResponse {
chatId
:
string
;
chatId
:
string
;
modelId
:
string
;
modelId
:
string
;
systemPrompt
?:
string
;
systemPrompt
?:
string
;
limitPrompt
?:
string
;
model
:
{
model
:
{
name
:
string
;
name
:
string
;
avatar
:
string
;
avatar
:
string
;
...
...
client/src/components/Select/index.tsx
View file @
83d755ad
...
@@ -26,7 +26,7 @@ const MySelect = ({ placeholder, value, width = 'auto', list, onchange, ...props
...
@@ -26,7 +26,7 @@ const MySelect = ({ placeholder, value, width = 'auto', list, onchange, ...props
return
(
return
(
<
Menu
autoSelect=
{
false
}
onOpen=
{
onOpen
}
onClose=
{
onClose
}
>
<
Menu
autoSelect=
{
false
}
onOpen=
{
onOpen
}
onClose=
{
onClose
}
>
<
MenuButton
as=
{
'span'
}
>
<
MenuButton
style=
{
{
width
:
'100%'
}
}
as=
{
'span'
}
>
<
Button
<
Button
width=
{
width
}
width=
{
width
}
px=
{
3
}
px=
{
3
}
...
...
client/src/constants/model.ts
View file @
83d755ad
...
@@ -82,6 +82,7 @@ export const defaultModel: ModelSchema = {
...
@@ -82,6 +82,7 @@ export const defaultModel: ModelSchema = {
searchLimit
:
5
,
searchLimit
:
5
,
searchEmptyText
:
''
,
searchEmptyText
:
''
,
systemPrompt
:
''
,
systemPrompt
:
''
,
limitPrompt
:
''
,
temperature
:
0
,
temperature
:
0
,
maxToken
:
4000
,
maxToken
:
4000
,
chatModel
:
OpenAiChatEnum
.
GPT35
chatModel
:
OpenAiChatEnum
.
GPT35
...
...
client/src/pages/api/chat/init.ts
View file @
83d755ad
...
@@ -101,6 +101,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -101,6 +101,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
},
},
chatModel
:
model
.
chat
.
chatModel
,
chatModel
:
model
.
chat
.
chatModel
,
systemPrompt
:
isOwner
?
model
.
chat
.
systemPrompt
:
''
,
systemPrompt
:
isOwner
?
model
.
chat
.
systemPrompt
:
''
,
limitPrompt
:
isOwner
?
model
.
chat
.
limitPrompt
:
''
,
history
history
}
}
});
});
...
...
client/src/pages/api/openapi/kb/appKbSearch.ts
View file @
83d755ad
...
@@ -28,7 +28,11 @@ type Response = {
...
@@ -28,7 +28,11 @@ type Response = {
userSystemPrompt
:
{
userSystemPrompt
:
{
obj
:
ChatRoleEnum
;
obj
:
ChatRoleEnum
;
value
:
string
;
value
:
string
;
};
}[];
userLimitPrompt
:
{
obj
:
ChatRoleEnum
;
value
:
string
;
}[];
quotePrompt
:
{
quotePrompt
:
{
obj
:
ChatRoleEnum
;
obj
:
ChatRoleEnum
;
value
:
string
;
value
:
string
;
...
@@ -130,17 +134,24 @@ export async function appKbSearch({
...
@@ -130,17 +134,24 @@ export async function appKbSearch({
// 计算固定提示词的 token 数量
// 计算固定提示词的 token 数量
const
userSystemPrompt
=
model
.
chat
.
systemPrompt
// user system prompt
const
userSystemPrompt
=
model
.
chat
.
systemPrompt
// user system prompt
?
{
?
[
obj
:
ChatRoleEnum
.
Human
,
{
value
:
model
.
chat
.
systemPrompt
obj
:
ChatRoleEnum
.
System
,
}
value
:
model
.
chat
.
systemPrompt
:
{
}
obj
:
ChatRoleEnum
.
Human
,
]
value
:
`知识库是关于
${
model
.
name
}
的内容,参考知识库回答问题。与 "
${
model
.
name
}
" 无关内容,直接回复: "我不知道"。`
:
[];
};
const
userLimitPrompt
=
[
{
obj
:
ChatRoleEnum
.
Human
,
value
:
model
.
chat
.
limitPrompt
?
model
.
chat
.
limitPrompt
:
`知识库是关于
${
model
.
name
}
的内容,参考知识库回答问题。与 "
${
model
.
name
}
" 无关内容,直接回复: "我不知道"。`
}
];
const
fixedSystemTokens
=
modelToolMap
[
model
.
chat
.
chatModel
].
countTokens
({
const
fixedSystemTokens
=
modelToolMap
[
model
.
chat
.
chatModel
].
countTokens
({
messages
:
[
userSystem
Prompt
]
messages
:
[
...
userSystemPrompt
,
...
userLimit
Prompt
]
});
});
// filter part quote by maxToken
// filter part quote by maxToken
...
@@ -164,6 +175,7 @@ export async function appKbSearch({
...
@@ -164,6 +175,7 @@ export async function appKbSearch({
return
{
return
{
rawSearch
,
rawSearch
,
userSystemPrompt
,
userSystemPrompt
,
userLimitPrompt
,
quotePrompt
:
{
quotePrompt
:
{
obj
:
ChatRoleEnum
.
System
,
obj
:
ChatRoleEnum
.
System
,
value
:
quoteText
value
:
quoteText
...
...
client/src/pages/api/openapi/v1/chat/completions.ts
View file @
83d755ad
...
@@ -108,11 +108,12 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
...
@@ -108,11 +108,12 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
const
{
const
{
rawSearch
=
[],
rawSearch
=
[],
userSystemPrompt
=
[],
userSystemPrompt
=
[],
userLimitPrompt
=
[],
quotePrompt
=
[]
quotePrompt
=
[]
}
=
await
(
async
()
=>
{
}
=
await
(
async
()
=>
{
// 使用了知识库搜索
// 使用了知识库搜索
if
(
model
.
chat
.
relatedKbs
?.
length
>
0
)
{
if
(
model
.
chat
.
relatedKbs
?.
length
>
0
)
{
const
{
rawSearch
,
userSystemPrompt
,
quote
Prompt
}
=
await
appKbSearch
({
const
{
rawSearch
,
quotePrompt
,
userSystemPrompt
,
userLimit
Prompt
}
=
await
appKbSearch
({
model
,
model
,
userId
,
userId
,
fixedQuote
:
history
[
history
.
length
-
1
]?.
quote
,
fixedQuote
:
history
[
history
.
length
-
1
]?.
quote
,
...
@@ -123,21 +124,29 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
...
@@ -123,21 +124,29 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
return
{
return
{
rawSearch
,
rawSearch
,
userSystemPrompt
:
userSystemPrompt
?
[
userSystemPrompt
]
:
[],
userSystemPrompt
,
userLimitPrompt
,
quotePrompt
:
[
quotePrompt
]
quotePrompt
:
[
quotePrompt
]
};
};
}
}
if
(
model
.
chat
.
systemPrompt
)
{
return
{
return
{
userSystemPrompt
:
model
.
chat
.
systemPrompt
userSystemPrompt
:
[
?
[
{
{
obj
:
ChatRoleEnum
.
System
,
obj
:
ChatRoleEnum
.
System
,
value
:
model
.
chat
.
systemPrompt
value
:
model
.
chat
.
systemPrompt
}
}
]
]
};
:
[],
}
userLimitPrompt
:
model
.
chat
.
limitPrompt
return
{};
?
[
{
obj
:
ChatRoleEnum
.
Human
,
value
:
model
.
chat
.
limitPrompt
}
]
:
[]
};
})();
})();
// search result is empty
// search result is empty
...
@@ -167,7 +176,13 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
...
@@ -167,7 +176,13 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
}
}
// api messages. [quote,context,systemPrompt,question]
// api messages. [quote,context,systemPrompt,question]
const
completePrompts
=
[...
quotePrompt
,
...
prompts
.
slice
(
0
,
-
1
),
...
userSystemPrompt
,
prompt
];
const
completePrompts
=
[
...
quotePrompt
,
...
userSystemPrompt
,
...
prompts
.
slice
(
0
,
-
1
),
...
userLimitPrompt
,
prompt
];
// chat temperature
// chat temperature
const
modelConstantsData
=
ChatModelMap
[
model
.
chat
.
chatModel
];
const
modelConstantsData
=
ChatModelMap
[
model
.
chat
.
chatModel
];
// FastGpt temperature range: 1~10
// FastGpt temperature range: 1~10
...
@@ -176,7 +191,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
...
@@ -176,7 +191,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
);
);
await
sensitiveCheck
({
await
sensitiveCheck
({
input
:
`
${
prompt
.
value
}
`
input
:
`
${
userSystemPrompt
[
0
]?.
value
}
\
n$
{
userLimitPrompt
[
0
]?.
value
}
\
n$
{
prompt
.
value
}
`
});
});
// start model api. responseText and totalTokens: valid only if stream = false
// start model api. responseText and totalTokens: valid only if stream = false
...
@@ -259,7 +274,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
...
@@ -259,7 +274,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
...(showAppDetail
...(showAppDetail
? {
? {
quote: rawSearch,
quote: rawSearch,
systemPrompt
:
userSystemPrompt
?.[
0
]?.
value
systemPrompt:
`
$
{
userSystemPrompt
[
0
]?.
value
}
\
n
\
n$
{
userLimitPrompt
[
0
]?.
value
}
`
}
}
: {})
: {})
}
}
...
...
client/src/pages/chat/index.tsx
View file @
83d755ad
...
@@ -219,7 +219,7 @@ const Chat = ({ modelId, chatId }: { modelId: string; chatId: string }) => {
...
@@ -219,7 +219,7 @@ const Chat = ({ modelId, chatId }: { modelId: string; chatId: string }) => {
...
item
,
...
item
,
status
:
'finish'
,
status
:
'finish'
,
quoteLen
,
quoteLen
,
systemPrompt
:
chatData
.
systemPrompt
systemPrompt
:
`
${
chatData
.
systemPrompt
}
\n\n
${
chatData
.
limitPrompt
}
`
};
};
})
})
}));
}));
...
@@ -234,13 +234,14 @@ const Chat = ({ modelId, chatId }: { modelId: string; chatId: string }) => {
...
@@ -234,13 +234,14 @@ const Chat = ({ modelId, chatId }: { modelId: string; chatId: string }) => {
[
[
chatId
,
chatId
,
modelId
,
modelId
,
chatData
.
systemPrompt
,
setChatData
,
setChatData
,
loadHistory
,
loadMyModels
,
generatingMessage
,
generatingMessage
,
setForbidLoadChatData
,
setForbidLoadChatData
,
router
router
,
chatData
.
systemPrompt
,
chatData
.
limitPrompt
,
loadHistory
,
loadMyModels
]
]
);
);
...
@@ -749,7 +750,7 @@ const Chat = ({ modelId, chatId }: { modelId: string; chatId: string }) => {
...
@@ -749,7 +750,7 @@ const Chat = ({ modelId, chatId }: { modelId: string; chatId: string }) => {
px={[2, 4]}
px={[2, 4]}
onClick={() => setShowSystemPrompt(item.systemPrompt || '')}
onClick={() => setShowSystemPrompt(item.systemPrompt || '')}
>
>
提示词
提示词
& 限定词
</Button>
</Button>
)}
)}
{!!item.quoteLen && (
{!!item.quoteLen && (
...
...
client/src/pages/model/components/detail/components/Settings.tsx
View file @
83d755ad
import
React
,
{
useCallback
,
useState
,
useMemo
}
from
'react'
;
import
React
,
{
useCallback
,
useState
,
useMemo
}
from
'react'
;
import
{
Box
,
Flex
,
Button
,
FormControl
,
Input
,
Textarea
,
Divider
}
from
'@chakra-ui/react'
;
import
{
Box
,
Flex
,
Button
,
FormControl
,
Input
,
Textarea
,
Divider
,
Tooltip
}
from
'@chakra-ui/react'
;
import
{
QuestionOutlineIcon
}
from
'@chakra-ui/icons'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
useForm
}
from
'react-hook-form'
;
import
{
useForm
}
from
'react-hook-form'
;
import
{
useRouter
}
from
'next/router'
;
import
{
useRouter
}
from
'next/router'
;
...
@@ -20,6 +30,11 @@ import Avatar from '@/components/Avatar';
...
@@ -20,6 +30,11 @@ import Avatar from '@/components/Avatar';
import
MySelect
from
'@/components/Select'
;
import
MySelect
from
'@/components/Select'
;
import
MySlider
from
'@/components/Slider'
;
import
MySlider
from
'@/components/Slider'
;
const
systemPromptTip
=
'模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。'
;
const
limitPromptTip
=
'限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。例如:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 "Laf" 无关内容,直接回复: "我不知道"。\n2. 你仅回答关于 "xxx" 的问题,其他问题回复: "xxxx"'
;
const
Settings
=
({
modelId
}:
{
modelId
:
string
})
=>
{
const
Settings
=
({
modelId
}:
{
modelId
:
string
})
=>
{
const
{
toast
}
=
useToast
();
const
{
toast
}
=
useToast
();
const
router
=
useRouter
();
const
router
=
useRouter
();
...
@@ -60,7 +75,7 @@ const Settings = ({ modelId }: { modelId: string }) => {
...
@@ -60,7 +75,7 @@ const Settings = ({ modelId }: { modelId: string }) => {
}
}
return
max
;
return
max
;
},
[
getValues
,
setValue
,
refresh
]);
},
[
getValues
,
setValue
]);
// 提交保存模型修改
// 提交保存模型修改
const
saveSubmitSuccess
=
useCallback
(
const
saveSubmitSuccess
=
useCallback
(
...
@@ -211,7 +226,7 @@ const Settings = ({ modelId }: { modelId: string }) => {
...
@@ -211,7 +226,7 @@ const Settings = ({ modelId }: { modelId: string }) => {
介绍
介绍
</Box>
</Box>
<Textarea
<Textarea
rows={
5
}
rows={
4
}
maxLength={500}
maxLength={500}
placeholder={'给你的 AI 应用一个介绍'}
placeholder={'给你的 AI 应用一个介绍'}
{...register('intro')}
{...register('intro')}
...
@@ -225,11 +240,14 @@ const Settings = ({ modelId }: { modelId: string }) => {
...
@@ -225,11 +240,14 @@ const Settings = ({ modelId }: { modelId: string }) => {
对话模型
对话模型
</Box>
</Box>
<MySelect
<MySelect
width={['
200px', '24
0px']}
width={['
100%', '28
0px']}
value={getValues('chat.chatModel')}
value={getValues('chat.chatModel')}
list={chatModelList.map((item) => ({
list={chatModelList.map((item) => ({
id: item.chatModel,
id: item.chatModel,
label: item.name
label: `
$
{
item
.
name
}
(
$
{
formatPrice
(
ChatModelMap
[
getValues
(
'chat.chatModel'
)]?.
price
,
1000
)}
元
/
1
k
tokens
)
`
}))}
}))}
onchange={(val: any) => {
onchange={(val: any) => {
setValue('chat.chatModel', val);
setValue('chat.chatModel', val);
...
@@ -237,15 +255,6 @@ const Settings = ({ modelId }: { modelId: string }) => {
...
@@ -237,15 +255,6 @@ const Settings = ({ modelId }: { modelId: string }) => {
}}
}}
/>
/>
</Flex>
</Flex>
<Flex alignItems={'center'} mt={5}>
<Box w={['60px', '100px', '140px']} flexShrink={0}>
价格
</Box>
<Box fontSize={['sm', 'md']}>
{formatPrice(ChatModelMap[getValues('chat.chatModel')]?.price, 1000)}
元/1K tokens(包括上下文和回答)
</Box>
</Flex>
<Flex alignItems={'center'} my={10}>
<Flex alignItems={'center'} my={10}>
<Box w={['60px', '100px', '140px']} flexShrink={0}>
<Box w={['60px', '100px', '140px']} flexShrink={0}>
温度
温度
...
@@ -269,7 +278,7 @@ const Settings = ({ modelId }: { modelId: string }) => {
...
@@ -269,7 +278,7 @@ const Settings = ({ modelId }: { modelId: string }) => {
</Flex>
</Flex>
<Flex alignItems={'center'} mt={12} mb={10}>
<Flex alignItems={'center'} mt={12} mb={10}>
<Box w={['60px', '100px', '140px']} flexShrink={0}>
<Box w={['60px', '100px', '140px']} flexShrink={0}>
最大长度
回复上限
</Box>
</Box>
<Box flex={1} ml={'10px'}>
<Box flex={1} ml={'10px'}>
<MySlider
<MySlider
...
@@ -292,15 +301,29 @@ const Settings = ({ modelId }: { modelId: string }) => {
...
@@ -292,15 +301,29 @@ const Settings = ({ modelId }: { modelId: string }) => {
<Flex mt={10} alignItems={'flex-start'}>
<Flex mt={10} alignItems={'flex-start'}>
<Box w={['60px', '100px', '140px']} flexShrink={0}>
<Box w={['60px', '100px', '140px']} flexShrink={0}>
提示词
提示词
<Tooltip label={systemPromptTip}>
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
</Tooltip>
</Box>
</Box>
<Textarea
<Textarea
rows={8}
rows={8}
placeholder={
placeholder={systemPromptTip}
'模型默认的 prompt 词,通过调整该内容,可以引导模型聊天方向。\n\n如果使用了知识库搜索,没有填写该内容时,系统会自动补充提示词;如果填写了内容,则以填写的内容为准。'
}
{...register('chat.systemPrompt')}
{...register('chat.systemPrompt')}
></Textarea>
></Textarea>
</Flex>
</Flex>
<Flex mt={5} alignItems={'flex-start'}>
<Box w={['60px', '100px', '140px']} flexShrink={0}>
限定词
<Tooltip label={limitPromptTip}>
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
</Tooltip>
</Box>
<Textarea
rows={5}
placeholder={limitPromptTip}
{...register('chat.limitPrompt')}
></Textarea>
</Flex>
<Flex mt={5} alignItems={'center'}>
<Flex mt={5} alignItems={'center'}>
<Box w={['60px', '100px', '140px']} flexShrink={0}></Box>
<Box w={['60px', '100px', '140px']} flexShrink={0}></Box>
...
...
client/src/service/models/model.ts
View file @
83d755ad
...
@@ -43,7 +43,10 @@ const ModelSchema = new Schema({
...
@@ -43,7 +43,10 @@ const ModelSchema = new Schema({
default
:
''
default
:
''
},
},
systemPrompt
:
{
systemPrompt
:
{
// 系统提示词
type
:
String
,
default
:
''
},
limitPrompt
:
{
type
:
String
,
type
:
String
,
default
:
''
default
:
''
},
},
...
...
client/src/types/mongoSchema.d.ts
View file @
83d755ad
...
@@ -43,6 +43,7 @@ export interface ModelSchema {
...
@@ -43,6 +43,7 @@ export interface ModelSchema {
searchLimit
:
number
;
searchLimit
:
number
;
searchEmptyText
:
string
;
searchEmptyText
:
string
;
systemPrompt
:
string
;
systemPrompt
:
string
;
limitPrompt
:
string
;
temperature
:
number
;
temperature
:
number
;
maxToken
:
number
;
maxToken
:
number
;
chatModel
:
ChatModelType
;
// 聊天时用的模型,训练后就是训练的模型
chatModel
:
ChatModelType
;
// 聊天时用的模型,训练后就是训练的模型
...
...
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