RAG给回复加上引用

我们希望RAG的幻觉减少,最有力的证明就是关键句子参考的某篇文献或报告。然而,大模型的随机性导致提供的引文可能都不存在,所以直接让大模型输出的方式目前是不可靠的。下面总结下添加引文的常见方法。

个人博客:有效果图片展示

一、外面加上引文

最直接和最简单的方法。当使用检索到的chunk时,就直接把这些chunk的元数据引用。

优点:简单,直接。
缺点:检索到的不一定支持回答。

# 美化参考来源标题console.print(Panel.fit("[bold blue]参考来源:[/bold blue]", style="magenta"))# 美化参考来源列表if rerank_res.file_path.tolist():for idx, file in enumerate(rerank_res.file_path.tolist(), start=1):console.print(f"[yellow]{idx}. [/yellow]{file}")else:console.print("[red]没有找到参考来源。[/red]")

二、提示词方法

在提示词里要求大模型在每个关键陈述后加上相应的引用ID,类似论文一样。

优点:可以提供快速实现的原型。
缺点:依赖于大模型的生成能力,很容易出现乱引用,不引用等情况。

提示词样例

三、函数调用

通过定义特定的函数来处理引用。langchain链接
类似于第一种方式的精细版,毕竟只有真正用到了参考文献才能说引用。
但langchain的代码封装地太厉害,自己实现更好理解。

优点:能保证都有引用。
缺点:需要大模型支持JSON格式。token消耗高。

文档级别的引用

流程:
1.定义格式化输出,既有答案还有引用。
2.传入格式化的文档列表,包含id,content等。
3.调用大模型,解析返回的JSON。

代码实现:

@dataclass
class Document:doc_id: intchunk_content: strimage_text: strsource: str = ""class CitedAnswer(BaseModel):"""基于给定文献回答用户问题,并引用使用的文献。"""answer: str = Field(...,description="基于给定文献的用户问题的回答。",)citations: List[int] = Field(...,description="用于回答的具体文献的整数 ID。",)def create_documents(df: pd.DataFrame) -> List[Document]:"""从df创建Document"""documents = []for idx, row in df.iterrows():documents.append(Document(doc_id=row['文献'],  # 使用 DataFrame 的索引作为唯一 IDchunk_content=row['chunk_content'],image_text=row.get('image_text',''),source=row.get('title', '')  # 假设有 'title' 列,否则为空))return documentsdef format_docs_with_id(docs: List[Document]) -> str:"""转文献列表为str,方便写入提示词"""formatted = [f"文献 ID: {doc.doc_id}\n内容: {doc.chunk_content}\n图片描述: {doc.image_text}"for doc in docs]return "\n\n".join(formatted)def extract_json(response_content: str) -> str:"""从响应内容中提取 JSON 字符串,无论是否包含代码块。"""# 使用正则表达式匹配 JSON 对象json_pattern = re.compile(r'\{.*\}', re.DOTALL)match = json_pattern.search(response_content)if match:return match.group(0)else:return response_content  # 如果没有匹配,返回原始内容def generate_cited_answer(question: str, docs: List[Document]) -> CitedAnswer:formatted_docs = format_docs_with_id(docs)prompt = f"""你是一个基于提供的文献回答用户问题的助手。请仅基于以下文献内容回答问题,并在回答中引用相关文献。请以 JSON 格式输出答案和引用的文献 ID,格式如下:{{"answer": "你的回答。","citations": [引用的文献 ID 列表]}}### 问题:{question}### 文献:{formatted_docs}### 回答:"""client = OpenAI(api_key="", base_url="https://api.deepseek.com")response = client.chat.completions.create(model="deepseek-chat",messages=[{"role": "system", "content": "你是一个有帮助的助手。"},{"role": "user", "content": prompt}],temperature=0,  # 设置为 0 以获得确定性输出max_tokens=500,stop=None)# 提取模型回复的内容response_content = response.choices[0].message.content# 提取 JSONjson_str = extract_json(response_content)try:# 解析 JSONresult = json.loads(json_str)cited_answer = CitedAnswer(**result)return cited_answerexcept json.JSONDecodeError:print("无法解析模型的 JSON 响应。")print("模型响应内容:", response_content)return None

效果展示:

片段级别的引用

与上述相比,增加了一个数据组织结构。要求引用的是片段。

这是个文段,里面有很多条句子。
经过句子级别引用后的结果,可以看到大模型自己识别出了对回答问题有益的片段。

关键代码:

# 片段引用
class Citation(BaseModel):source_id: int = Field(...,description="The integer ID of a SPECIFIC source which justifies the answer.",)quote: str = Field(...,description="The VERBATIM quote from the specified source that justifies the answer.",)class QuotedAnswer(BaseModel):"""Answer the user question based only on the given sources, and cite the sources used."""answer: str = Field(...,description="The answer to the user question, which is based only on the given sources.",)citations: List[Citation] = Field(..., description="Citations from the given sources that justify the answer.")
prompt = f"""你是一个基于提供的文献回答用户问题的助手。请仅基于以下文献内容回答问题,并在回答中引用相关文献。请以 JSON 格式输出答案和引用的文献 ID,格式如下:{{"answer": "你的回答。","citations": [{{"source_id": 1,"quote": "引用内容1。"}},{{"source_id": 2,"quote": "引用内容2。"}}]}}### 问题:{question}### 文献:{formatted_docs}### 回答:"""

四、检索后处理

思想:检索后,对文档进行处理,提取最相关的部分作为引用。
流程:
1.文档拆分:递归文档拆分。
2.文档压缩:使用嵌入模型为每个小块生成嵌入,并选择与查询最相似的前k个小块。
3.生成:将压缩后的文档(最相似的几个小块),拼接起来,作为上下文。
4.引用:这样就能精细化定位到每个小块,直接引用对应文档或者片段。

优点:能更具关键信息支持。
缺点:增加了流程,时间消耗比较高。

五、生成后处理

思想:先生成答案,二次调用大模型添加引用。
流程:
1.生成答案:调用大模型得到纯文本的答案。
2.生成引用:二次调用生成引用。

优点:成功率高,幻觉低。
缺点:时间和token消耗高,依赖大模型,仍然存在幻觉。

六、后挂载处理

来源

思想:大模型生成后处理,但不依赖大模型,而是依赖相似度计算。这是和第四种方法的区别。
思路:
1.生成:大模型生成回答。
2.添加输出:计算回答中每个句子与参考文献的相似度,如果高于阈值,就在这个句子后添加引用。

优点:大模型专注生成回答,可能有助于回答质量提升。减低引用幻觉。
缺点:不能一次生成,增加时间消耗。

参考

https://www.xiaoiluo.com/article/citation-langchain-post-processing
https://python.langchain.com/docs/how_to/qa_citations/#retrieval-post-processing
https://github.com/run-llama/llama_index/blob/main/llama-index-core/llama_index/core/query_engine/citation_query_engine.py

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/63310.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Bootstrap-HTML(三)Bootstrap5列表组全解析

Bootstrap-HTML(三)Bootstrap5列表组全解析 前言(一)HTML 列表基础回顾1.无序列表2.有序列表3.定义列表 二、无样式的有序列表和无序列表内联列表 三、Bootstrap5 列表组1.基础的列表组2.设置禁用和活动项3.链接项的列表组4.移除列…

MongoDB安装|注意事项

《疯狂Spring Boot讲义》是2021年电子工业出版社出版的图书,作者是李刚 《疯狂Spring Boot终极讲义》不是一本介绍类似于PathVariable、MatrixVariable、RequestBody、ResponseBody这些基础注解的图书,它是真正讲解Spring Boot的图书。Spring Boot的核心…

频率分辨率、频率间隔与频率采样密度

频率分辨率 ( F res F_{\text{res}} Fres​): 频率分辨率 F res F_{\text{res}} Fres​ 与采样周期 T T T 和采样点数 N N N 有关,公式为: F res ∼ 1 N T [ Hz ] F_{\text{res}} \sim \frac{1}{NT} \quad [\text{Hz}] Fres​∼NT1​[Hz] 频…

DDR4与DDR3服务器内存的关键区别有哪些?

内存作为服务器性能的关键组件之一,已经经历了从DDR3到DDR4的过渡。DDR4内存相较于DDR3在多个方面有所提升,包括速度、带宽、功耗以及数据传输效率等。然而,尽管DDR4内存在性能上占有优势,DDR3内存依然在一些特定场景中得到了广泛…

Java基础--网络编程

在Java开发中,常见的通信协议有多种,这些协议在不同的应用场景中发挥着各自的优势。 通信协议 1. HTTP/HTTPS HTTP(HyperText Transfer Protocol):是最常用的网络协议之一,用于分布式、协作式、超媒体信…

Lua面向对象 实现 超详细注释 实现构造函数,析构函数,只读类模板等功能

Lua面向对象 实现 超详细注释 实现构造函数,析构函数,只读类模板等功能 源码 -- 注意下面的代码可以拆开成多个文件使用,也可以放一起 -- Class.lualocal _class {}-- 将Source变成只读表并返回 function MakeTableReadOnly(Source)local …

详细解读AEO海关认证

AEO认证,即“Authorized Economic Operator”认证,译为“经认证的经营者”认证,也被称作“综合认证优秀企业”认证。以下是对AEO海关认证的详细解读: 一、背景与意义 背景:AEO制度是世界海关组织(WCO&…

线性回归方程模型

一、项目要求 以个人为单位,实现AI识别的算法: 调查某市出租车使用年限和该年支出维修费用(万元),得到数据如下: 使用年限(x) 2 3 4 5 6 维修费用(y) 2.2 3.8 5.5 6.5 7.0 求线性回归方程由1中结论预测第10年所支出的维修费用 3.说明自己选中预测的原因和过程中的收获 说…

【OpenDRIVE_Python】使用python脚本读取txt指定内容,输出OpenDRIVE数据中对应的信息

示例代码说明: 读取txt指定内容如地物id,输出OpenDRIVE数据中的对应地物id和名称name信息为xml文件 import xml.dom.minidom from xml.dom.minidom import parse from xml.dom import Node import sys import os # 读取OpenDRIVE文件路径 xml_filepath…

什么是DBD设备?

2022年10月,本号文章《北斗优先是对北斗三代的挑衅》中指出:“多系统兼容互操作是北斗三号逐步替代北斗二号的主要原因。北斗优先是对北斗三代的挑衅。”现在想来,当时还是太年轻,格局没有打开。 2023年12月,本号文章…

vscode 折叠范围快捷键

vscode 折叠范围快捷键 问答 原文网址:https://www.n.cn/search/c830b29cb76146d08cae5074acfd4785 VSCode 折叠范围快捷键 在使用Visual Studio Code(VSCode)进行代码编辑时,掌握一些快捷键可以大大提高工作效率。以下是关于VSCode中折叠和…

uviewplus中的时间单选框up-datetime-picker的在uni-app+vue3的使用方法

uviewplus中的时间单选框up-datetime-picker的使用方法 前言 在实际开发中,我们经常需要使用时间选择器来让用户选择特定的时间。本文将详细介绍uviewplus中up-datetime-picker组件的使用方法,特别是在处理年月选择时的一些关键实现,因为官方有很多相关的功能和方法…

高质量翻译在美国推广移动应用中的重要性

美国的移动应用市场是世界上竞争最激烈、利润最高的市场之一,为开发者提供了接触数百万潜在用户的机会。然而,进入这个市场需要的不仅仅是创新技术或令人信服的想法;它要求与目标受众进行有效地沟通和文化契合。在这个过程中,高质…

基于Python的PDF批量转化工具

一、开发的缘由 最近,有网友想让我帮他做一个批量把png, docx, doc, pptx, ppt, xls, xlsx文件转化为PDF格式的软件,完全傻瓜式的操作,把文件拖进去就进行转化那种,简单实用。之前,有过一个vbs的文件,可以…

模型案例:| 手机识别模型!

导读 2023年以ChatGPT为代表的大语言模型横空出世,它的出现标志着自然语言处理领域取得了重大突破。它在文本生成、对话系统和语言理解等方面展现出了强大的能力,为人工智能技术的发展开辟了新的可能性。同时,人工智能技术正在进入各种应用领…

【Copilot 】TAB keybinding not working on JetBrains Client

pycharm ssh 远程到ubuntu24.04 发现tab就是tab,无法输出copilot给出的自动补全到便捷器里。禁用host的copilot插件,重新启动ide就好了。解决办法 参考大神的办法删除主机和客户端插件中的 Copilot插件。 仅在客户端中重新安装 Copilot 插件。 我只是禁用也可以 对比了键盘映…

【Linux】程序的编译过程

程序的翻译过程 预处理(头文件展开,条件编译,宏替换,去注释)编译 :把c变成汇编语言汇编 :把汇编变成二进制(不可执行,二进制目标文件)链接 :把自…

发布订阅者=>fiber=>虚拟dom

文章目录 vue的响应式原理-发布订阅者模式vue3 响应式原理及优化fiberfiber 与 虚拟dom vue的响应式原理-发布订阅者模式 Vue响应式原理概述 Vue.js的响应式原理是其核心特性之一。它使得当数据发生变化时,与之绑定的DOM元素能够自动更新。其主要基于数据劫持和发布…

Trunk链路操作题

Trunk链路操作题 论证:

C# 设计模式--建造者模式 (Builder Pattern)

定义 建造者模式是一种创建型设计模式,它允许你逐步构建复杂对象,而无需使用多个构造函数或重载。建造者模式将对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。 正确写法 假设我们有一个复杂的 Car 对象,需要…