add answer quote number (#4658)

This commit is contained in:
heheer 2025-04-25 10:34:37 +08:00 committed by GitHub
parent 2a54be4d91
commit 25dc8984be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 215 additions and 42 deletions

View File

@ -7,6 +7,13 @@ export const Prompt_QuoteTemplateList: PromptTemplateItem[] = [
title: i18nT('app:template.standard_template'), title: i18nT('app:template.standard_template'),
desc: i18nT('app:template.standard_template_des'), desc: i18nT('app:template.standard_template_des'),
value: { value: {
['4.9.7']: `{
"sourceIndex": "{{sourceIndex}}",
"id": "{{id}}",
"sourceName": "{{source}}",
"content": "{{q}}\n{{a}}"
}
`,
['4.9.2']: `{ ['4.9.2']: `{
"sourceName": "{{source}}", "sourceName": "{{source}}",
"updateTime": "{{updateTime}}", "updateTime": "{{updateTime}}",
@ -31,6 +38,13 @@ export const Prompt_QuoteTemplateList: PromptTemplateItem[] = [
title: i18nT('app:template.standard_strict'), title: i18nT('app:template.standard_strict'),
desc: i18nT('app:template.standard_strict_des'), desc: i18nT('app:template.standard_strict_des'),
value: { value: {
['4.9.7']: `{
"sourceIndex": "{{sourceIndex}}",
"id": "{{id}}",
"sourceName": "{{source}}",
"content": "{{q}}\n{{a}}"
}
`,
['4.9.2']: `{ ['4.9.2']: `{
"sourceName": "{{source}}", "sourceName": "{{source}}",
"updateTime": "{{updateTime}}", "updateTime": "{{updateTime}}",
@ -64,6 +78,21 @@ export const Prompt_userQuotePromptList: PromptTemplateItem[] = [
title: i18nT('app:template.standard_template'), title: i18nT('app:template.standard_template'),
desc: '', desc: '',
value: { 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> 标记中的内容作为本次对话的参考: ['4.9.2']: `使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Reference> <Reference>
@ -103,6 +132,27 @@ export const Prompt_userQuotePromptList: PromptTemplateItem[] = [
title: i18nT('app:template.standard_strict'), title: i18nT('app:template.standard_strict'),
desc: '', desc: '',
value: { 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> 标记中的内容作为本次对话的参考: ['4.9.2']: `忘记你已有的知识,仅使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Reference> <Reference>
@ -157,6 +207,21 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [
title: i18nT('app:template.standard_template'), title: i18nT('app:template.standard_template'),
desc: '', desc: '',
value: { 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> 标记中的内容作为本次对话的参考: ['4.9.2']: `使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Reference> <Reference>
@ -192,6 +257,27 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [
title: i18nT('app:template.standard_strict'), title: i18nT('app:template.standard_strict'),
desc: '', desc: '',
value: { 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> 标记中的内容作为本次对话的参考: ['4.9.2']: `忘记你已有的知识,仅使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Reference> <Reference>

View File

@ -55,7 +55,7 @@ export const AiChatModule: FlowNodeTemplateType = {
showStatus: true, showStatus: true,
isTool: true, isTool: true,
courseUrl: '/docs/guide/workbench/workflow/ai_chat/', courseUrl: '/docs/guide/workbench/workflow/ai_chat/',
version: '4.9.0', version: '4.9.7',
inputs: [ inputs: [
Input_Template_SettingAiModel, Input_Template_SettingAiModel,
// --- settings modal // --- settings modal

View File

@ -338,7 +338,17 @@ async function filterDatasetQuote({
model: LLMModelItemType; model: LLMModelItemType;
quoteTemplate: string; 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, { return replaceVariable(quoteTemplate, {
id: item.id, id: item.id,
q: item.q, q: item.q,
@ -346,6 +356,7 @@ async function filterDatasetQuote({
updateTime: formatTime2YMDHM(item.updateTime), updateTime: formatTime2YMDHM(item.updateTime),
source: item.sourceName, source: item.sourceName,
sourceId: String(item.sourceId || ''), sourceId: String(item.sourceId || ''),
sourceIndex: source?.sourceIndex || 1,
index: index + 1 index: index + 1
}); });
} }
@ -353,9 +364,24 @@ async function filterDatasetQuote({
// slice filterSearch // slice filterSearch
const filterQuoteQA = await filterSearchResultsByMaxChars(quoteQA, model.quoteMaxToken); 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 = const datasetQuoteText =
filterQuoteQA.length > 0 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 { return {

View File

@ -617,6 +617,7 @@
"core.dataset.search.ReRank": "Result Re-rank", "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.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 id": "Source ID",
"core.dataset.search.Source index": "What sources",
"core.dataset.search.Source name": "Quote Source Name", "core.dataset.search.Source name": "Quote Source Name",
"core.dataset.search.Using query extension": "Use Question Optimization", "core.dataset.search.Using query extension": "Use Question Optimization",
"core.dataset.search.mode.embedding": "Semantic Search", "core.dataset.search.mode.embedding": "Semantic Search",

View File

@ -617,6 +617,7 @@
"core.dataset.search.ReRank": "结果重排", "core.dataset.search.ReRank": "结果重排",
"core.dataset.search.ReRank desc": "使用重排模型来进行二次排序,可增强综合排名。", "core.dataset.search.ReRank desc": "使用重排模型来进行二次排序,可增强综合排名。",
"core.dataset.search.Source id": "来源 ID", "core.dataset.search.Source id": "来源 ID",
"core.dataset.search.Source index": "第几个来源",
"core.dataset.search.Source name": "引用来源名", "core.dataset.search.Source name": "引用来源名",
"core.dataset.search.Using query extension": "使用问题优化", "core.dataset.search.Using query extension": "使用问题优化",
"core.dataset.search.mode.embedding": "语义检索", "core.dataset.search.mode.embedding": "语义检索",

View File

@ -616,6 +616,7 @@
"core.dataset.search.ReRank": "結果重新排名", "core.dataset.search.ReRank": "結果重新排名",
"core.dataset.search.ReRank desc": "使用重新排名模型來進行二次排序,可加強綜合排名。", "core.dataset.search.ReRank desc": "使用重新排名模型來進行二次排序,可加強綜合排名。",
"core.dataset.search.Source id": "來源 ID", "core.dataset.search.Source id": "來源 ID",
"core.dataset.search.Source index": "第幾個來源",
"core.dataset.search.Source name": "引用來源名稱", "core.dataset.search.Source name": "引用來源名稱",
"core.dataset.search.Using query extension": "使用問題最佳化", "core.dataset.search.Using query extension": "使用問題最佳化",
"core.dataset.search.mode.embedding": "語意搜尋", "core.dataset.search.mode.embedding": "語意搜尋",

View File

@ -5,10 +5,10 @@ import {
Popover, Popover,
PopoverTrigger, PopoverTrigger,
PopoverContent, PopoverContent,
PopoverHeader,
PopoverBody, PopoverBody,
PopoverArrow, PopoverArrow,
PopoverCloseButton Box,
Flex
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import MyIcon from '@fastgpt/web/components/common/Icon'; import MyIcon from '@fastgpt/web/components/common/Icon';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
@ -17,9 +17,9 @@ import { useTranslation } from 'next-i18next';
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import { getQuoteData } from '@/web/core/dataset/api'; import { getQuoteData } from '@/web/core/dataset/api';
import MyBox from '@fastgpt/web/components/common/MyBox'; import MyBox from '@fastgpt/web/components/common/MyBox';
import RawSourceBox from '../core/dataset/RawSourceBox';
import { getCollectionSourceData } from '@fastgpt/global/core/dataset/collection/utils'; import { getCollectionSourceData } from '@fastgpt/global/core/dataset/collection/utils';
import Markdown from '.'; import Markdown from '.';
import { getSourceNameIcon } from '@fastgpt/global/core/dataset/utils';
const A = ({ children, ...props }: any) => { const A = ({ children, ...props }: any) => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -52,46 +52,99 @@ const A = ({ children, ...props }: any) => {
} }
// Quote // 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 ( return (
<Popover <Popover
direction="rtl"
isLazy isLazy
placement="auto" direction="rtl"
placement="bottom"
strategy={'fixed'} strategy={'fixed'}
onOpen={() => runAsync(String(children))} onOpen={() => runAsync(String(children))}
> >
<PopoverTrigger> <PopoverTrigger>
<Button variant={'unstyled'} minH={0} minW={0} h={'auto'}> <Button variant={'unstyled'} minH={0} minW={0} h={'auto'}>
<MyTooltip label={t('common:read_quote')}> <MyTooltip label={t('common:read_quote')}>
<MyIcon <Box
name={'core/chat/quoteSign'} w={5}
w={'1rem'} h={5}
color={'primary.700'} border={'1px solid'}
cursor={'pointer'} borderRadius={'full'}
transform={'translateY(-3px)'} borderColor={'myGray.200'}
/> color={'myGray.500'}
fontSize={'10px'}
display={'flex'}
alignItems={'center'}
justifyContent={'center'}
ml={0.5}
transform={'translateY(-2px)'}
>
{index}
</Box>
</MyTooltip> </MyTooltip>
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent boxShadow={'lg'} w={'400px'}> <PopoverContent boxShadow={'lg'} w={'400px'} py={4}>
<MyBox isLoading={loading} minH={'300px'}> <MyBox isLoading={loading} minH={'224px'}>
<PopoverArrow /> <PopoverArrow />
<PopoverHeader h={'40px'} display={'flex'} alignItems={'center'}> <PopoverBody
{quoteData?.collection && ( px={4}
<RawSourceBox py={0}
collectionId={quoteData?.collection._id}
{...getCollectionSourceData(quoteData?.collection)}
fontSize={'sm'} fontSize={'sm'}
color={'black'} maxW={'400px'}
textDecoration={'none'} maxH={'224px'}
/> overflow={'auto'}
)} >
<PopoverCloseButton /> <Box
</PopoverHeader> alignItems={'center'}
<PopoverBody fontSize={'sm'} maxH={'400px'} overflow={'auto'}> 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} /> <Markdown source={quoteData?.q} />
<Markdown source={quoteData?.a} /> {quoteData?.a && <Markdown source={quoteData?.a} />}
</Box>
</PopoverBody> </PopoverBody>
</MyBox> </MyBox>
</PopoverContent> </PopoverContent>

View File

@ -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) => { return processedData.sort((a, b) => {

View File

@ -93,6 +93,11 @@ const EditModal = ({ onClose, ...props }: RenderInputProps & { onClose: () => vo
label: t('common:core.dataset.search.Source name'), label: t('common:core.dataset.search.Source name'),
icon: 'core/app/simpleMode/variable' icon: 'core/app/simpleMode/variable'
}, },
{
key: 'sourceIndex',
label: t('common:core.dataset.search.Source index'),
icon: 'core/app/simpleMode/variable'
},
{ {
key: 'q', key: 'q',
label: 'q', label: 'q',
@ -218,14 +223,14 @@ const EditModal = ({ onClose, ...props }: RenderInputProps & { onClose: () => vo
</Box> </Box>
</Flex> </Flex>
<Box mt={4}> <Box mt={4}>
<Flex {...LabelStyles} mb={1}> <Flex {...LabelStyles} mb={1} alignItems={'center'}>
<FormLabel>{t('common:core.app.Quote templates')}</FormLabel> <FormLabel>{t('common:core.app.Quote templates')}</FormLabel>
<QuestionTip <QuestionTip
ml={1} ml={1}
label={t('workflow:quote_content_tip', { label={t('workflow:quote_content_tip', {
default: getQuoteTemplate(nodeVersion) default: getQuoteTemplate(nodeVersion)
})} })}
></QuestionTip> />
<Box flex={1} /> <Box flex={1} />
<Box <Box
{...selectTemplateBtn} {...selectTemplateBtn}
@ -253,14 +258,14 @@ const EditModal = ({ onClose, ...props }: RenderInputProps & { onClose: () => vo
/> />
</Box> </Box>
<Box mt={4}> <Box mt={4}>
<Flex {...LabelStyles} mb={1}> <Flex {...LabelStyles} mb={1} alignItems={'center'}>
<FormLabel>{t('common:core.app.Quote prompt')}</FormLabel> <FormLabel>{t('common:core.app.Quote prompt')}</FormLabel>
<QuestionTip <QuestionTip
ml={1} ml={1}
label={t('workflow:quote_prompt_tip', { label={t('workflow:quote_prompt_tip', {
default: getQuotePrompt(nodeVersion, aiChatQuoteRole) default: getQuotePrompt(nodeVersion, aiChatQuoteRole)
})} })}
></QuestionTip> />
</Flex> </Flex>
<PromptEditor <PromptEditor
variables={quotePromptVariables} variables={quotePromptVariables}