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
25dc8984
authored
Apr 25, 2025
by
heheer
Committed by
GitHub
Apr 25, 2025
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add answer quote number (#4658)
parent
2a54be4d
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
215 additions
and
42 deletions
+215
-42
packages/global/core/ai/prompt/AIChat.ts
+90
-4
packages/global/core/workflow/template/system/aiChat/index.ts
+1
-1
packages/service/core/workflow/dispatch/chat/oneapi.ts
+28
-2
packages/web/i18n/en/common.json
+1
-0
packages/web/i18n/zh-CN/common.json
+1
-0
packages/web/i18n/zh-Hant/common.json
+1
-0
projects/app/src/components/Markdown/A.tsx
+83
-30
projects/app/src/components/core/chat/ChatContainer/ChatBox/components/QuoteList.tsx
+1
-1
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingQuotePrompt.tsx
+9
-4
No files found.
packages/global/core/ai/prompt/AIChat.ts
View file @
25dc8984
...
...
@@ -7,6 +7,13 @@ export const Prompt_QuoteTemplateList: PromptTemplateItem[] = [
title
:
i18nT
(
'app:template.standard_template'
),
desc
:
i18nT
(
'app:template.standard_template_des'
),
value
:
{
[
'4.9.7'
]:
`{
"sourceIndex": "{{sourceIndex}}",
"id": "{{id}}",
"sourceName": "{{source}}",
"content": "{{q}}\n{{a}}"
}
`
,
[
'4.9.2'
]:
`{
"sourceName": "{{source}}",
"updateTime": "{{updateTime}}",
...
...
@@ -31,6 +38,13 @@ export const Prompt_QuoteTemplateList: PromptTemplateItem[] = [
title
:
i18nT
(
'app:template.standard_strict'
),
desc
:
i18nT
(
'app:template.standard_strict_des'
),
value
:
{
[
'4.9.7'
]:
`{
"sourceIndex": "{{sourceIndex}}",
"id": "{{id}}",
"sourceName": "{{source}}",
"content": "{{q}}\n{{a}}"
}
`
,
[
'4.9.2'
]:
`{
"sourceName": "{{source}}",
"updateTime": "{{updateTime}}",
...
...
@@ -64,6 +78,21 @@ export const Prompt_userQuotePromptList: PromptTemplateItem[] = [
title
:
i18nT
(
'app:template.standard_template'
),
desc
:
''
,
value
:
{
[
'4.9.7'
]:
`使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Reference>
{{quote}}
</Reference>
回答要求:
- 如果你不清楚答案,你需要澄清。
- 避免提及你是从 <Reference></Reference> 获取的知识。
- 保持答案与 <Reference></Reference> 中描述的一致。
- 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。
- 使用 [id](QUOTE{{sourceIndex}}) 格式来引用<Reference></Reference>中的知识,其中 QUOTE 是固定常量, id 和 sourceIndex 分别为引文中的值。
- 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE1)。"
- 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。`
,
[
'4.9.2'
]:
`使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Reference>
...
...
@@ -103,6 +132,27 @@ export const Prompt_userQuotePromptList: PromptTemplateItem[] = [
title
:
i18nT
(
'app:template.standard_strict'
),
desc
:
''
,
value
:
{
[
'4.9.7'
]:
`忘记你已有的知识,仅使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Reference>
{{quote}}
</Reference>
思考流程:
1. 判断问题是否与 <Reference></Reference> 标记中的内容有关。
2. 如果有关,你按下面的要求回答。
3. 如果无关,你直接拒绝回答本次问题。
回答要求:
- 避免提及你是从 <Reference></Reference> 获取的知识。
- 保持答案与 <Reference></Reference> 中描述的一致。
- 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。
- 使用 [id](QUOTE{{sourceIndex}}) 格式来引用<Reference></Reference>中的知识,其中 QUOTE 是固定常量, id 和 sourceIndex 分别为引文中的值。
- 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE1)。"
- 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。
问题:"""{{question}}"""`
,
[
'4.9.2'
]:
`忘记你已有的知识,仅使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Reference>
...
...
@@ -157,6 +207,21 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [
title
:
i18nT
(
'app:template.standard_template'
),
desc
:
''
,
value
:
{
[
'4.9.7'
]:
`使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Reference>
{{quote}}
</Reference>
回答要求:
- 如果你不清楚答案,你需要澄清。
- 避免提及你是从 <Reference></Reference> 获取的知识。
- 保持答案与 <Reference></Reference> 中描述的一致。
- 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。
- 使用 [id](QUOTE{{sourceIndex}}) 格式来引用<Reference></Reference>中的知识,其中 QUOTE 是固定常量, id 和 sourceIndex 分别为引文中的值。
- 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE1)。"
- 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。`
,
[
'4.9.2'
]:
`使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Reference>
...
...
@@ -192,6 +257,27 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [
title
:
i18nT
(
'app:template.standard_strict'
),
desc
:
''
,
value
:
{
[
'4.9.7'
]:
`忘记你已有的知识,仅使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Reference>
{{quote}}
</Reference>
思考流程:
1. 判断问题是否与 <Reference></Reference> 标记中的内容有关。
2. 如果有关,你按下面的要求回答。
3. 如果无关,你直接拒绝回答本次问题。
回答要求:
- 避免提及你是从 <Reference></Reference> 获取的知识。
- 保持答案与 <Reference></Reference> 中描述的一致。
- 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。
- 使用 [id](QUOTE{{sourceIndex}}) 格式来引用<Reference></Reference>中的知识,其中 QUOTE 是固定常量, id 和 sourceIndex 分别为引文中的值。
- 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE1)。"
- 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。
问题:"""{{question}}"""`
,
[
'4.9.2'
]:
`忘记你已有的知识,仅使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Reference>
...
...
@@ -250,10 +336,10 @@ export const getQuotePrompt = (version?: string, role: 'user' | 'system' = 'user
export
const
getDocumentQuotePrompt
=
(
version
:
string
)
=>
{
const
promptMap
=
{
[
'4.9.2'
]:
`将 <FilesContent></FilesContent> 中的内容作为本次对话的参考:
<FilesContent>
{{quote}}
</FilesContent>
`
<FilesContent>
{{quote}}
</FilesContent>
`
};
return
getPromptByVersion
(
version
,
promptMap
);
...
...
packages/global/core/workflow/template/system/aiChat/index.ts
View file @
25dc8984
...
...
@@ -55,7 +55,7 @@ export const AiChatModule: FlowNodeTemplateType = {
showStatus
:
true
,
isTool
:
true
,
courseUrl
:
'/docs/guide/workbench/workflow/ai_chat/'
,
version
:
'4.9.
0
'
,
version
:
'4.9.
7
'
,
inputs
:
[
Input_Template_SettingAiModel
,
// --- settings modal
...
...
packages/service/core/workflow/dispatch/chat/oneapi.ts
View file @
25dc8984
...
...
@@ -338,7 +338,17 @@ async function filterDatasetQuote({
model
:
LLMModelItemType
;
quoteTemplate
:
string
;
})
{
function
getValue
(
item
:
SearchDataResponseItemType
,
index
:
number
)
{
function
getValue
({
item
,
index
,
sourceList
}:
{
item
:
SearchDataResponseItemType
;
index
:
number
;
sourceList
:
{
sourceName
:
string
;
sourceId
:
string
;
sourceIndex
:
number
}[];
})
{
const
source
=
sourceList
.
find
((
source
)
=>
source
.
sourceId
===
item
.
sourceId
);
return
replaceVariable
(
quoteTemplate
,
{
id
:
item
.
id
,
q
:
item
.
q
,
...
...
@@ -346,6 +356,7 @@ async function filterDatasetQuote({
updateTime
:
formatTime2YMDHM
(
item
.
updateTime
),
source
:
item
.
sourceName
,
sourceId
:
String
(
item
.
sourceId
||
''
),
sourceIndex
:
source
?.
sourceIndex
||
1
,
index
:
index
+
1
});
}
...
...
@@ -353,9 +364,24 @@ async function filterDatasetQuote({
// slice filterSearch
const
filterQuoteQA
=
await
filterSearchResultsByMaxChars
(
quoteQA
,
model
.
quoteMaxToken
);
const
sourceList
=
Object
.
values
(
filterQuoteQA
.
reduce
((
acc
:
Record
<
string
,
SearchDataResponseItemType
[]
>
,
cur
)
=>
{
if
(
!
acc
[
cur
.
collectionId
])
{
acc
[
cur
.
collectionId
]
=
[
cur
];
}
return
acc
;
},
{})
)
.
flat
()
.
map
((
item
,
index
)
=>
({
sourceName
:
item
.
sourceName
||
''
,
sourceId
:
item
.
sourceId
||
''
,
sourceIndex
:
index
+
1
}));
const
datasetQuoteText
=
filterQuoteQA
.
length
>
0
?
`
${
filterQuoteQA
.
map
((
item
,
index
)
=>
getValue
(
item
,
index
).
trim
()).
join
(
'\n------\n'
)}
`
?
`
${
filterQuoteQA
.
map
((
item
,
index
)
=>
getValue
(
{
item
,
index
,
sourceList
}
).
trim
()).
join
(
'\n------\n'
)}
`
:
''
;
return
{
...
...
packages/web/i18n/en/common.json
View file @
25dc8984
...
...
@@ -617,6 +617,7 @@
"core.dataset.search.ReRank"
:
"Result Re-rank"
,
"core.dataset.search.ReRank desc"
:
"Use the re-rank model for secondary sorting to enhance the comprehensive ranking."
,
"core.dataset.search.Source id"
:
"Source ID"
,
"core.dataset.search.Source index"
:
"What sources"
,
"core.dataset.search.Source name"
:
"Quote Source Name"
,
"core.dataset.search.Using query extension"
:
"Use Question Optimization"
,
"core.dataset.search.mode.embedding"
:
"Semantic Search"
,
...
...
packages/web/i18n/zh-CN/common.json
View file @
25dc8984
...
...
@@ -617,6 +617,7 @@
"core.dataset.search.ReRank"
:
"结果重排"
,
"core.dataset.search.ReRank desc"
:
"使用重排模型来进行二次排序,可增强综合排名。"
,
"core.dataset.search.Source id"
:
"来源 ID"
,
"core.dataset.search.Source index"
:
"第几个来源"
,
"core.dataset.search.Source name"
:
"引用来源名"
,
"core.dataset.search.Using query extension"
:
"使用问题优化"
,
"core.dataset.search.mode.embedding"
:
"语义检索"
,
...
...
packages/web/i18n/zh-Hant/common.json
View file @
25dc8984
...
...
@@ -616,6 +616,7 @@
"core.dataset.search.ReRank"
:
"結果重新排名"
,
"core.dataset.search.ReRank desc"
:
"使用重新排名模型來進行二次排序,可加強綜合排名。"
,
"core.dataset.search.Source id"
:
"來源 ID"
,
"core.dataset.search.Source index"
:
"第幾個來源"
,
"core.dataset.search.Source name"
:
"引用來源名稱"
,
"core.dataset.search.Using query extension"
:
"使用問題最佳化"
,
"core.dataset.search.mode.embedding"
:
"語意搜尋"
,
...
...
projects/app/src/components/Markdown/A.tsx
View file @
25dc8984
...
...
@@ -5,10 +5,10 @@ import {
Popover
,
PopoverTrigger
,
PopoverContent
,
PopoverHeader
,
PopoverBody
,
PopoverArrow
,
PopoverCloseButton
Box
,
Flex
}
from
'@chakra-ui/react'
;
import
MyIcon
from
'@fastgpt/web/components/common/Icon'
;
import
MyTooltip
from
'@fastgpt/web/components/common/MyTooltip'
;
...
...
@@ -17,9 +17,9 @@ import { useTranslation } from 'next-i18next';
import
React
,
{
useMemo
}
from
'react'
;
import
{
getQuoteData
}
from
'@/web/core/dataset/api'
;
import
MyBox
from
'@fastgpt/web/components/common/MyBox'
;
import
RawSourceBox
from
'../core/dataset/RawSourceBox'
;
import
{
getCollectionSourceData
}
from
'@fastgpt/global/core/dataset/collection/utils'
;
import
Markdown
from
'.'
;
import
{
getSourceNameIcon
}
from
'@fastgpt/global/core/dataset/utils'
;
const
A
=
({
children
,
...
props
}:
any
)
=>
{
const
{
t
}
=
useTranslation
();
...
...
@@ -52,46 +52,99 @@ const A = ({ children, ...props }: any) => {
}
// Quote
if
(
props
.
href
===
'QUOTE'
&&
typeof
children
?.[
0
]
===
'string'
)
{
if
(
props
.
href
?.
startsWith
(
'QUOTE'
)
&&
typeof
children
?.[
0
]
===
'string'
)
{
const
indexMatch
=
props
.
href
.
match
(
/QUOTE
(\d
+
)
/
);
const
index
=
indexMatch
?
indexMatch
[
1
]
:
'1'
;
const
sourceData
=
useMemo
(
()
=>
getCollectionSourceData
(
quoteData
?.
collection
),
[
quoteData
?.
collection
]
);
const
icon
=
useMemo
(
()
=>
getSourceNameIcon
({
sourceId
:
sourceData
.
sourceId
,
sourceName
:
sourceData
.
sourceName
}),
[
sourceData
]
);
return
(
<
Popover
direction=
"rtl"
isLazy
placement=
"auto"
direction=
"rtl"
placement=
"bottom"
strategy=
{
'fixed'
}
onOpen=
{
()
=>
runAsync
(
String
(
children
))
}
>
<
PopoverTrigger
>
<
Button
variant=
{
'unstyled'
}
minH=
{
0
}
minW=
{
0
}
h=
{
'auto'
}
>
<
MyTooltip
label=
{
t
(
'common:read_quote'
)
}
>
<
MyIcon
name=
{
'core/chat/quoteSign'
}
w=
{
'1rem'
}
color=
{
'primary.700'
}
cursor=
{
'pointer'
}
transform=
{
'translateY(-3px)'
}
/>
<
Box
w=
{
5
}
h=
{
5
}
border=
{
'1px solid'
}
borderRadius=
{
'full'
}
borderColor=
{
'myGray.200'
}
color=
{
'myGray.500'
}
fontSize=
{
'10px'
}
display=
{
'flex'
}
alignItems=
{
'center'
}
justifyContent=
{
'center'
}
ml=
{
0.5
}
transform=
{
'translateY(-2px)'
}
>
{
index
}
</
Box
>
</
MyTooltip
>
</
Button
>
</
PopoverTrigger
>
<
PopoverContent
boxShadow=
{
'lg'
}
w=
{
'400px'
}
>
<
MyBox
isLoading=
{
loading
}
minH=
{
'
300
px'
}
>
<
PopoverContent
boxShadow=
{
'lg'
}
w=
{
'400px'
}
py=
{
4
}
>
<
MyBox
isLoading=
{
loading
}
minH=
{
'
224
px'
}
>
<
PopoverArrow
/>
<
PopoverHeader
h=
{
'40px'
}
display=
{
'flex'
}
alignItems=
{
'center'
}
>
{
quoteData
?.
collection
&&
(
<
RawSourceBox
collectionId=
{
quoteData
?.
collection
.
_id
}
{
...
getCollectionSourceData
(
quoteData
?
.
collection
)}
fontSize=
{
'sm'
}
color=
{
'black'
}
textDecoration=
{
'none'
}
/>
)
}
<
PopoverCloseButton
/>
</
PopoverHeader
>
<
PopoverBody
fontSize=
{
'sm'
}
maxH=
{
'400px'
}
overflow=
{
'auto'
}
>
<
Markdown
source=
{
quoteData
?.
q
}
/>
<
Markdown
source=
{
quoteData
?.
a
}
/>
<
PopoverBody
px=
{
4
}
py=
{
0
}
fontSize=
{
'sm'
}
maxW=
{
'400px'
}
maxH=
{
'224px'
}
overflow=
{
'auto'
}
>
<
Box
alignItems=
{
'center'
}
fontSize=
{
'xs'
}
border=
{
'sm'
}
borderRadius=
{
'sm'
}
overflow=
{
'hidden'
}
display=
{
'inline-flex'
}
height=
{
6
}
>
<
Flex
color=
{
'myGray.500'
}
bg=
{
'myGray.150'
}
w=
{
4
}
justifyContent=
{
'center'
}
fontSize=
{
'10px'
}
h=
{
'full'
}
alignItems=
{
'center'
}
mr=
{
1
}
flexShrink=
{
0
}
>
{
index
}
</
Flex
>
<
Flex
px=
{
1.5
}
>
<
MyIcon
name=
{
icon
as
any
}
mr=
{
1
}
flexShrink=
{
0
}
w=
{
'12px'
}
/>
<
Box
className=
{
'textEllipsis'
}
wordBreak=
{
'break-all'
}
flex=
{
'1 0 0'
}
fontSize=
{
'mini'
}
color=
{
'myGray.900'
}
>
{
sourceData
.
sourceName
}
</
Box
>
</
Flex
>
</
Box
>
<
Box
>
<
Markdown
source=
{
quoteData
?.
q
}
/>
{
quoteData
?.
a
&&
<
Markdown
source=
{
quoteData
?.
a
}
/>
}
</
Box
>
</
PopoverBody
>
</
MyBox
>
</
PopoverContent
>
...
...
projects/app/src/components/core/chat/ChatContainer/ChatBox/components/QuoteList.tsx
View file @
25dc8984
...
...
@@ -59,7 +59,7 @@ const QuoteList = React.memo(function QuoteList({
};
}
return
item
;
return
{
...
item
,
q
:
item
.
q
||
''
,
a
:
item
.
a
||
''
}
;
});
return
processedData
.
sort
((
a
,
b
)
=>
{
...
...
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingQuotePrompt.tsx
View file @
25dc8984
...
...
@@ -94,6 +94,11 @@ const EditModal = ({ onClose, ...props }: RenderInputProps & { onClose: () => vo
icon
:
'core/app/simpleMode/variable'
},
{
key
:
'sourceIndex'
,
label
:
t
(
'common:core.dataset.search.Source index'
),
icon
:
'core/app/simpleMode/variable'
},
{
key
:
'q'
,
label
:
'q'
,
icon
:
'core/app/simpleMode/variable'
...
...
@@ -218,14 +223,14 @@ const EditModal = ({ onClose, ...props }: RenderInputProps & { onClose: () => vo
</
Box
>
</
Flex
>
<
Box
mt=
{
4
}
>
<
Flex
{
...
LabelStyles
}
mb=
{
1
}
>
<
Flex
{
...
LabelStyles
}
mb=
{
1
}
alignItems=
{
'center'
}
>
<
FormLabel
>
{
t
(
'common:core.app.Quote templates'
)
}
</
FormLabel
>
<
QuestionTip
ml=
{
1
}
label=
{
t
(
'workflow:quote_content_tip'
,
{
default
:
getQuoteTemplate
(
nodeVersion
)
})
}
></
QuestionTip
>
/
>
<
Box
flex=
{
1
}
/>
<
Box
{
...
selectTemplateBtn
}
...
...
@@ -253,14 +258,14 @@ const EditModal = ({ onClose, ...props }: RenderInputProps & { onClose: () => vo
/>
</
Box
>
<
Box
mt=
{
4
}
>
<
Flex
{
...
LabelStyles
}
mb=
{
1
}
>
<
Flex
{
...
LabelStyles
}
mb=
{
1
}
alignItems=
{
'center'
}
>
<
FormLabel
>
{
t
(
'common:core.app.Quote prompt'
)
}
</
FormLabel
>
<
QuestionTip
ml=
{
1
}
label=
{
t
(
'workflow:quote_prompt_tip'
,
{
default
:
getQuotePrompt
(
nodeVersion
,
aiChatQuoteRole
)
})
}
></
QuestionTip
>
/
>
</
Flex
>
<
PromptEditor
variables=
{
quotePromptVariables
}
...
...
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