大模型RAG实战|生成带有引用来源的回答


在企业级应用场景,我们通常采用检索增强生成(RAG,Retrieval-Augmented Generation)技术,要求大语言模型(LLM)严格基于从知识库检索到的信息生成内容,而不得编造任何内容。


此时,在LLM生成的内容中,准确地标注来源,并在其后列出所有引用来源,将极大地提升回答的可信度和透明性。


本文将介绍一种“混合方案”。


一、核心思路


系统通过LLM在生成内容时,同步标注来源(内联引用,inline citations)。但在生成的内容中不包含引用来源列表,而是由系统动态生成和展示。这种方案较为灵活,且使得引用来源的管理更为可控。


  • 分层结构管理:首先,将检索到的内容和元数据(如标题、作者 等)结构化存储,确保引用的准确性和易用性。

  • 内联引用生成:通过提示词,让LLM生成带有内联引用的回答,例如 [1]、[2] 等,指向数据来源。

  • 动态管理引用列表:引用来源列表不由 LLM 直接生成,而是根据回答中的引用标记动态生成。


这样,引用来源列表可以灵活地以多种方式展示,例如:可折叠的列表、工具提示(tooltip)或直接链接到原始文档。


二、实现步骤


我们可以按照以下4个步骤,实现生成带有引用来源的回答,包括:结构化检索内容、提示词工程、动态管理引用列表和用户界面集成。


1. 结构化检索内容


使用检索系统(如向量搜索或关键词搜索)获取与用户问题相关的文档片段(Chunk)。确保每个片段都带有原始文档的元数据。


将检索到的内容保存为结构化格式。每条内容应包含以下字段:

  • ID:唯一标识符,例如 1、2、3

  • 内容:与用户问题相关的精确片段

  • 元数据:包括原文档的标题、作者、日期、URL等


示例 JSON 数据结构:

[  {    "id": 1,    "content": "太阳通过核心的核聚变产生能量。",    "metadata": {      "title": "太阳的核聚变原理",      "author": "NASA",      "url": "https://www.nasa.gov/sun"    }  },  {    "id": 2,    "content": "太阳主要由氢和氦组成。",    "metadata": {      "title": "太阳的成分",      "author": "维基百科",      "url": "https://zh.wikipedia.org/wiki/太阳"    }  }]


如果多个片段来自相同的来源,建议将它们合并。这样可以减少重复引用并提供更完整的上下文。


2. 提示词工程


为 LLM 提供清晰的指令(Prompt),要求生成带有内联引用的回答,同时不要生成引用来源列表。


示例 Prompt:


你是一名智能助手,请根据以下检索到的信息回答用户的问题。在回答中添加内联引用,格式为 [n],其中 n 是来源的编号,例如:[1],[2],或[1][2],[1][3][4]。请不要生成引用来源列表。检索到的信息:1. "太阳通过核心的核聚变产生能量。" (来源: "太阳的核聚变原理", NASA, https://www.nasa.gov/sun)2. "太阳主要由氢和氦组成。" (来源: "太阳的成分", 维基百科, https://zh.wikipedia.org/wiki/太阳)用户问题:太阳是由什么组成的?它是如何产生能量的?回答:


请注意这里给出的仅为示例。由于不同的LLM理解与生成能力不一样,请基于你使用的LLM,对提示词进行进一步调试和优化,使之能稳定地输出期望的效果。


3. 动态管理引用列表


在第一步中,我们已经将检索到的内容和元数据存储为结构化数据,方便后续动态生成引用列表。


当LLM生成回答时,不会使用所有检索到的信息,而是仅使用和用户问题相关的信息进行回答。所以,我们需要解析 LLM 生成内容中的内联引用标记(如 [1]、[2]),并从此前存储的元数据中提取对应的引用信息。


提取内联引用标记

citations = re.findall(r"[(d+)]", answer)


动态生成引用列表

citation_list = []for citation in sorted(set(citations)):    source = metadata.get(citation, {})    if source:        citation_list.append(f"{citation}. [{source['title']}]({source['url']}) - {source['author']}")


输出引用列表

print("引用来源:")print("n".join(citation_list))


输出示例:

引用来源:1. [太阳的核聚变原理](https://www.nasa.gov/sun) - NASA2. [太阳的成分](https://zh.wikipedia.org/wiki/太阳) - 维基百科


4. 用户界面集成


通过流式传输技术,将 LLM 生成的回答逐字显示给用户,同时在输出的文字中附带内联引用,如[1], [2]。


在回答输出完成后,在输出的内容中,根据引用标记,动态提取和生成引用列表,可选择以下方式展示:


  • 展开列表:回答下方显示完整的引用来源列表

  • 工具提示:用户悬停或点击内联引用时显示来源信息

  • 直接链接:内联引用直接跳转到对应的来源页面


UI 示例:

回答:太阳主要由氢和氦组成[2]。它通过核心的核聚变产生能量[1]。[展开引用来源]引用来源:1. [太阳的核聚变原理](https://www.nasa.gov/sun) - NASA2. [太阳的成分](https://zh.wikipedia.org/wiki/太阳) - 维基百科


三、持续优化


通过上述方案,我们可以通过对检索数据的结构化处理,提示词工程和LLM的理解与生成能力,自动生成带有引用来源的回答。


结合应用场景,我们还可以进一步做如下优化:


  • 确保引用准确性:校验内联引用标记和引用列表的一致性,避免遗漏或错误。

  • 管理长回答:对于引用较多的回答,优先展示重要参考文献,其余可折叠或单独列出。

  • 提升用户体验:根据用户需求,提供多种引用展示方式,如工具提示或链接。


使用这个方案,我们可以高效生成带有引用来源的回答,既保证生成过程的透明性,又提供了灵活的用户交互方式。这种实现方法简单易用,可广泛应用于问答系统、知识库助手等场景。

RAG技术前沿技术新闻资讯

三路检索+多模态融合!深度解析RAG 2.0如何攻克大模型落地难题

2025-5-23 15:46:21

RAG技术前沿技术新闻资讯

RAG架构综述:探寻最适配RAG方案

2025-5-23 17:37:45

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
购物车
优惠劵
搜索