fix: chat quote number (#4679)

This commit is contained in:
heheer
2025-04-27 17:54:07 +08:00
committed by GitHub
parent 6763ac60d5
commit 9923a402d9
8 changed files with 42 additions and 81 deletions

View File

@@ -8,7 +8,6 @@ export const Prompt_QuoteTemplateList: PromptTemplateItem[] = [
desc: i18nT('app:template.standard_template_des'), desc: i18nT('app:template.standard_template_des'),
value: { value: {
['4.9.7']: `{ ['4.9.7']: `{
"sourceIndex": "{{sourceIndex}}",
"id": "{{id}}", "id": "{{id}}",
"sourceName": "{{source}}", "sourceName": "{{source}}",
"content": "{{q}}\n{{a}}" "content": "{{q}}\n{{a}}"
@@ -39,7 +38,6 @@ export const Prompt_QuoteTemplateList: PromptTemplateItem[] = [
desc: i18nT('app:template.standard_strict_des'), desc: i18nT('app:template.standard_strict_des'),
value: { value: {
['4.9.7']: `{ ['4.9.7']: `{
"sourceIndex": "{{sourceIndex}}",
"id": "{{id}}", "id": "{{id}}",
"sourceName": "{{source}}", "sourceName": "{{source}}",
"content": "{{q}}\n{{a}}" "content": "{{q}}\n{{a}}"
@@ -90,8 +88,8 @@ export const Prompt_userQuotePromptList: PromptTemplateItem[] = [
- 保持答案与 <Reference></Reference> 中描述的一致。 - 保持答案与 <Reference></Reference> 中描述的一致。
- 使用 Markdown 语法优化回答格式。 - 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。 - 使用与问题相同的语言回答。
- 使用 [id](QUOTE{{sourceIndex}}) 格式来引用<Reference></Reference>中的知识,其中 QUOTE 是固定常量, id 和 sourceIndex 分别为引文中的 - 使用 [id](QUOTE) 格式来引用<Reference></Reference>中的知识,其中 QUOTE 是固定常量, id 为引文中的 id
- 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE1)。" - 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE)。"
- 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。`, - 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。`,
['4.9.2']: `使用 <Reference></Reference> 标记中的内容作为本次对话的参考: ['4.9.2']: `使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
@@ -148,8 +146,8 @@ export const Prompt_userQuotePromptList: PromptTemplateItem[] = [
- 保持答案与 <Reference></Reference> 中描述的一致。 - 保持答案与 <Reference></Reference> 中描述的一致。
- 使用 Markdown 语法优化回答格式。 - 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。 - 使用与问题相同的语言回答。
- 使用 [id](QUOTE{{sourceIndex}}) 格式来引用<Reference></Reference>中的知识,其中 QUOTE 是固定常量, id 和 sourceIndex 分别为引文中的 - 使用 [id](QUOTE) 格式来引用<Reference></Reference>中的知识,其中 QUOTE 是固定常量, id 为引文中的 id
- 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE1)。" - 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE)。"
- 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。 - 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。
问题:"""{{question}}"""`, 问题:"""{{question}}"""`,
@@ -219,8 +217,8 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [
- 保持答案与 <Reference></Reference> 中描述的一致。 - 保持答案与 <Reference></Reference> 中描述的一致。
- 使用 Markdown 语法优化回答格式。 - 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。 - 使用与问题相同的语言回答。
- 使用 [id](QUOTE{{sourceIndex}}) 格式来引用<Reference></Reference>中的知识,其中 QUOTE 是固定常量, id 和 sourceIndex 分别为引文中的 - 使用 [id](QUOTE) 格式来引用<Reference></Reference>中的知识,其中 QUOTE 是固定常量, id 为引文中的 id
- 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE1)。" - 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE)。"
- 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。`, - 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。`,
['4.9.2']: `使用 <Reference></Reference> 标记中的内容作为本次对话的参考: ['4.9.2']: `使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
@@ -273,8 +271,8 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [
- 保持答案与 <Reference></Reference> 中描述的一致。 - 保持答案与 <Reference></Reference> 中描述的一致。
- 使用 Markdown 语法优化回答格式。 - 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。 - 使用与问题相同的语言回答。
- 使用 [id](QUOTE{{sourceIndex}}) 格式来引用<Reference></Reference>中的知识,其中 QUOTE 是固定常量, id 和 sourceIndex 分别为引文中的 - 使用 [id](QUOTE) 格式来引用<Reference></Reference>中的知识,其中 QUOTE 是固定常量, id 为引文中的 id
- 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE1)。" - 在每段结尾自然地整合引用。例如: "FastGPT 是一个基于大语言模型(LLM)的知识库问答系统[67e517e74767063e882d6861](QUOTE)。"
- 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。 - 每段至少包含一个引用,也可根据内容需要加入多个引用,按顺序排列。
问题:"""{{question}}"""`, 问题:"""{{question}}"""`,

View File

@@ -348,17 +348,7 @@ async function filterDatasetQuote({
model: LLMModelItemType; model: LLMModelItemType;
quoteTemplate: string; quoteTemplate: string;
}) { }) {
function getValue({ function getValue({ item, index }: { item: SearchDataResponseItemType; index: number }) {
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,
@@ -366,7 +356,6 @@ 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
}); });
} }
@@ -374,24 +363,9 @@ 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, sourceList }).trim()).join('\n------\n')}` ? `${filterQuoteQA.map((item, index) => getValue({ item, index }).trim()).join('\n------\n')}`
: ''; : '';
return { return {

View File

@@ -56,9 +56,6 @@ const A = ({ children, ...props }: any) => {
// Quote // Quote
if (props.href?.startsWith('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( const sourceData = useMemo(
() => getCollectionSourceData(quoteData?.collection), () => getCollectionSourceData(quoteData?.collection),
[quoteData?.collection] [quoteData?.collection]
@@ -80,27 +77,17 @@ const A = ({ children, ...props }: any) => {
onOpen(); onOpen();
runAsync(String(children)); runAsync(String(children));
}} }}
trigger={'hover'}
gutter={4} gutter={4}
> >
<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')}> <MyIcon
<Box name={'core/chat/quoteSign'}
w={'14px'} w={'1rem'}
h={'14px'} color={'primary.700'}
borderRadius={'full'} cursor={'pointer'}
bg={'rgba(0, 0, 0, 0.08)'} />
color={'myGray.600'}
fontSize={'10px'}
display={'flex'}
alignItems={'center'}
justifyContent={'center'}
ml={0.5}
transform={'translateY(-3px)'}
>
{index}
</Box>
</MyTooltip>
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent boxShadow={'lg'} w={'500px'} py={4}> <PopoverContent boxShadow={'lg'} w={'500px'} py={4}>
@@ -118,19 +105,6 @@ const A = ({ children, ...props }: any) => {
height={6} height={6}
mr={1} mr={1}
> >
<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}> <Flex px={1.5}>
<MyIcon name={icon as any} mr={1} flexShrink={0} w={'12px'} /> <MyIcon name={icon as any} mr={1} flexShrink={0} w={'12px'} />
<Box <Box
@@ -151,7 +125,7 @@ const A = ({ children, ...props }: any) => {
onClick={() => { onClick={() => {
onClose(); onClose();
eventBus.emit(EventNameEnum.openQuoteReader, { eventBus.emit(EventNameEnum.openQuoteReader, {
// quoteId: String(children), quoteId: String(children),
sourceId: sourceData.sourceId, sourceId: sourceData.sourceId,
sourceName: sourceData.sourceName, sourceName: sourceData.sourceName,
datasetId: quoteData?.collection.datasetId, datasetId: quoteData?.collection.datasetId,

View File

@@ -227,12 +227,14 @@ const ChatItem = (props: Props) => {
collectionId, collectionId,
sourceId, sourceId,
sourceName, sourceName,
datasetId datasetId,
quoteId
}: { }: {
collectionId?: string; collectionId?: string;
sourceId?: string; sourceId?: string;
sourceName?: string; sourceName?: string;
datasetId?: string; datasetId?: string;
quoteId?: string;
}) => { }) => {
if (!setQuoteData) return; if (!setQuoteData) return;
@@ -252,7 +254,8 @@ const ChatItem = (props: Props) => {
sourceId: sourceId || '', sourceId: sourceId || '',
sourceName: sourceName || '', sourceName: sourceName || '',
datasetId: datasetId || '', datasetId: datasetId || '',
outLinkAuthData outLinkAuthData,
quoteId
} }
: { : {
appId: appId, appId: appId,

View File

@@ -72,6 +72,7 @@ type RenderHeaderProps = {
onUpdateParentId: (parentId: ParentIdType) => void; onUpdateParentId: (parentId: ParentIdType) => void;
}; };
type RenderListProps = { type RenderListProps = {
templateType: TemplateTypeEnum;
templates: NodeTemplateListItemType[]; templates: NodeTemplateListItemType[];
type: TemplateTypeEnum; type: TemplateTypeEnum;
onClose: () => void; onClose: () => void;
@@ -247,6 +248,7 @@ const NodeTemplatesModal = ({ isOpen, onClose }: ModuleTemplateListProps) => {
setSearchKey={setSearchKey} setSearchKey={setSearchKey}
/> />
<RenderList <RenderList
templateType={templateType}
templates={templates} templates={templates}
type={templateType} type={templateType}
onClose={onClose} onClose={onClose}
@@ -402,6 +404,7 @@ const RenderHeader = React.memo(function RenderHeader({
}); });
const RenderList = React.memo(function RenderList({ const RenderList = React.memo(function RenderList({
templateType,
templates, templates,
type, type,
onClose, onClose,
@@ -712,7 +715,7 @@ const RenderList = React.memo(function RenderList({
{t(template.name as any)} {t(template.name as any)}
</Box> </Box>
{template.isFolder && ( {template.isFolder && templateType === TemplateTypeEnum.teamPlugin && (
<Box <Box
color={'myGray.500'} color={'myGray.500'}
_hover={{ _hover={{

View File

@@ -94,8 +94,8 @@ const EditModal = ({ onClose, ...props }: RenderInputProps & { onClose: () => vo
icon: 'core/app/simpleMode/variable' icon: 'core/app/simpleMode/variable'
}, },
{ {
key: 'sourceIndex', key: 'sourceId',
label: t('common:core.dataset.search.Source index'), label: t('common:core.dataset.search.Source id'),
icon: 'core/app/simpleMode/variable' icon: 'core/app/simpleMode/variable'
}, },
{ {

View File

@@ -35,7 +35,7 @@ const CollectionReader = ({
const router = useRouter(); const router = useRouter();
const { userInfo } = useUserStore(); const { userInfo } = useUserStore();
const { collectionId, datasetId, chatItemDataId, sourceId, sourceName } = metadata; const { collectionId, datasetId, chatItemDataId, sourceId, sourceName, quoteId } = metadata;
const [quoteIndex, setQuoteIndex] = useState(0); const [quoteIndex, setQuoteIndex] = useState(0);
// Get dataset permission // Get dataset permission
@@ -45,11 +45,19 @@ const CollectionReader = ({
}); });
const filterResults = useMemo(() => { const filterResults = useMemo(() => {
setQuoteIndex(0); const res = rawSearch
return rawSearch
.filter((item) => item.collectionId === collectionId) .filter((item) => item.collectionId === collectionId)
.sort((a, b) => (a.chunkIndex || 0) - (b.chunkIndex || 0)); .sort((a, b) => (a.chunkIndex || 0) - (b.chunkIndex || 0));
}, [collectionId, rawSearch]);
if (quoteId) {
setQuoteIndex(res.findIndex((item) => item.id === quoteId));
} else {
setQuoteIndex(0);
}
return res;
}, [collectionId, quoteId, rawSearch]);
const currentQuoteItem = useMemo(() => { const currentQuoteItem = useMemo(() => {
const item = filterResults[quoteIndex]; const item = filterResults[quoteIndex];
if (item) { if (item) {

View File

@@ -41,6 +41,7 @@ export type GetQuoteDataBasicProps = {
}; };
// 获取单个集合引用 // 获取单个集合引用
export type GetCollectionQuoteDataProps = GetQuoteDataBasicProps & { export type GetCollectionQuoteDataProps = GetQuoteDataBasicProps & {
quoteId?: string;
collectionId: string; collectionId: string;
sourceId: string; sourceId: string;
sourceName: string; sourceName: string;