diff --git a/packages/global/core/ai/prompt/AIChat.ts b/packages/global/core/ai/prompt/AIChat.ts index 99100b916..1715081b3 100644 --- a/packages/global/core/ai/prompt/AIChat.ts +++ b/packages/global/core/ai/prompt/AIChat.ts @@ -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']: `使用 标记中的内容作为本次对话的参考: + + +{{quote}} + + +回答要求: +- 如果你不清楚答案,你需要澄清。 +- 避免提及你是从 获取的知识。 +- 保持答案与 中描述的一致。 +- 使用 Markdown 语法优化回答格式。 +- 使用与问题相同的语言回答。 +- 使用 [id](QUOTE{{sourceIndex}}) 格式来引用中的知识,其中 QUOTE 是固定常量, id 和 sourceIndex 分别为引文中的值。 +- 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE1)。" +- 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。`, ['4.9.2']: `使用 标记中的内容作为本次对话的参考: @@ -103,6 +132,27 @@ export const Prompt_userQuotePromptList: PromptTemplateItem[] = [ title: i18nT('app:template.standard_strict'), desc: '', value: { + ['4.9.7']: `忘记你已有的知识,仅使用 标记中的内容作为本次对话的参考: + + +{{quote}} + + +思考流程: +1. 判断问题是否与 标记中的内容有关。 +2. 如果有关,你按下面的要求回答。 +3. 如果无关,你直接拒绝回答本次问题。 + +回答要求: +- 避免提及你是从 获取的知识。 +- 保持答案与 中描述的一致。 +- 使用 Markdown 语法优化回答格式。 +- 使用与问题相同的语言回答。 +- 使用 [id](QUOTE{{sourceIndex}}) 格式来引用中的知识,其中 QUOTE 是固定常量, id 和 sourceIndex 分别为引文中的值。 +- 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE1)。" +- 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。 + +问题:"""{{question}}"""`, ['4.9.2']: `忘记你已有的知识,仅使用 标记中的内容作为本次对话的参考: @@ -157,6 +207,21 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [ title: i18nT('app:template.standard_template'), desc: '', value: { + ['4.9.7']: `使用 标记中的内容作为本次对话的参考: + + +{{quote}} + + +回答要求: +- 如果你不清楚答案,你需要澄清。 +- 避免提及你是从 获取的知识。 +- 保持答案与 中描述的一致。 +- 使用 Markdown 语法优化回答格式。 +- 使用与问题相同的语言回答。 +- 使用 [id](QUOTE{{sourceIndex}}) 格式来引用中的知识,其中 QUOTE 是固定常量, id 和 sourceIndex 分别为引文中的值。 +- 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE1)。" +- 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。`, ['4.9.2']: `使用 标记中的内容作为本次对话的参考: @@ -192,6 +257,27 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [ title: i18nT('app:template.standard_strict'), desc: '', value: { + ['4.9.7']: `忘记你已有的知识,仅使用 标记中的内容作为本次对话的参考: + + +{{quote}} + + +思考流程: +1. 判断问题是否与 标记中的内容有关。 +2. 如果有关,你按下面的要求回答。 +3. 如果无关,你直接拒绝回答本次问题。 + +回答要求: +- 避免提及你是从 获取的知识。 +- 保持答案与 中描述的一致。 +- 使用 Markdown 语法优化回答格式。 +- 使用与问题相同的语言回答。 +- 使用 [id](QUOTE{{sourceIndex}}) 格式来引用中的知识,其中 QUOTE 是固定常量, id 和 sourceIndex 分别为引文中的值。 +- 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE1)。" +- 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。 + +问题:"""{{question}}"""`, ['4.9.2']: `忘记你已有的知识,仅使用 标记中的内容作为本次对话的参考: @@ -250,10 +336,10 @@ export const getQuotePrompt = (version?: string, role: 'user' | 'system' = 'user export const getDocumentQuotePrompt = (version: string) => { const promptMap = { ['4.9.2']: `将 中的内容作为本次对话的参考: - - {{quote}} - - ` + +{{quote}} + +` }; return getPromptByVersion(version, promptMap); diff --git a/packages/global/core/workflow/template/system/aiChat/index.ts b/packages/global/core/workflow/template/system/aiChat/index.ts index b7cd68f65..38eff383b 100644 --- a/packages/global/core/workflow/template/system/aiChat/index.ts +++ b/packages/global/core/workflow/template/system/aiChat/index.ts @@ -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 diff --git a/packages/service/core/workflow/dispatch/chat/oneapi.ts b/packages/service/core/workflow/dispatch/chat/oneapi.ts index babbae42e..a96356ced 100644 --- a/packages/service/core/workflow/dispatch/chat/oneapi.ts +++ b/packages/service/core/workflow/dispatch/chat/oneapi.ts @@ -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, 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 { diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json index 026d866c6..bb90ae8a4 100644 --- a/packages/web/i18n/en/common.json +++ b/packages/web/i18n/en/common.json @@ -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", diff --git a/packages/web/i18n/zh-CN/common.json b/packages/web/i18n/zh-CN/common.json index 0473462c9..81c815794 100644 --- a/packages/web/i18n/zh-CN/common.json +++ b/packages/web/i18n/zh-CN/common.json @@ -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": "语义检索", diff --git a/packages/web/i18n/zh-Hant/common.json b/packages/web/i18n/zh-Hant/common.json index 576a72eca..88e1eaf33 100644 --- a/packages/web/i18n/zh-Hant/common.json +++ b/packages/web/i18n/zh-Hant/common.json @@ -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": "語意搜尋", diff --git a/projects/app/src/components/Markdown/A.tsx b/projects/app/src/components/Markdown/A.tsx index 2d1609ecf..14bb9d110 100644 --- a/projects/app/src/components/Markdown/A.tsx +++ b/projects/app/src/components/Markdown/A.tsx @@ -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 ( runAsync(String(children))} > - - + + - - {quoteData?.collection && ( - - )} - - - - - + + + + {index} + + + + + {sourceData.sourceName} + + + + + + {quoteData?.a && } + diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/QuoteList.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/QuoteList.tsx index 61578d1bb..ae8ee12ee 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/QuoteList.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/QuoteList.tsx @@ -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) => { diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingQuotePrompt.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingQuotePrompt.tsx index 1a95e5105..3589e2bcd 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingQuotePrompt.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SettingQuotePrompt.tsx @@ -93,6 +93,11 @@ const EditModal = ({ onClose, ...props }: RenderInputProps & { onClose: () => vo label: t('common:core.dataset.search.Source name'), icon: 'core/app/simpleMode/variable' }, + { + key: 'sourceIndex', + label: t('common:core.dataset.search.Source index'), + icon: 'core/app/simpleMode/variable' + }, { key: 'q', label: 'q', @@ -218,14 +223,14 @@ const EditModal = ({ onClose, ...props }: RenderInputProps & { onClose: () => vo - + {t('common:core.app.Quote templates')} + /> vo /> - + {t('common:core.app.Quote prompt')} + />