实现RAG:使用LangChain实现图检索查询

你是不是有时会遇到这样的问题:你可能遇到的任何主题或问题,都有大量的文档,但是当尝试将某些内容应用于自己的用途时,突然发现很难找到所需的内容。
在这篇博文中,我们将看一下LangChain是如何实现RAG的,这样你就可以将相同的原理应用到任何带有LangChain和LLM的应用程序中。

什么是RAG

该术语在当今的技术领域中使用得很多,但它的实际含义是什么呢?以下是来自不同来源的一些定义:

“检索增强生成(RAG)是优化大型语言模型输出的过程,因此在生成响应之前,它会参考训练数据源之外的权威知识库。” — AWS

“检索增强生成(RAG)是一种利用从外部来源获取的事实,提高生成式人工智能模型的准确性和可靠性的技术。” — 英伟达

“检索增强生成(RAG)是一个人工智能框架,通过将模型建立在外部知识来源上,以补充法学硕士对信息的内部表示,从而提高法学硕士生成的响应的质量。” — IBM研究院

在本篇博文中,我们将关注如何编写检索查询来补充或支撑LLM的答案。我们将使用Python和LangChain,一个用于编写与llm交互的生成式AI应用程序的框架。

数据集

首先,让我们快速浏览一下我们的数据集。我们将处理来自EDGAR(电子数据收集、分析和检索系统)数据库的SEC(证券交易委员会)文件。美国证券交易委员会提交的文件是一个信息宝库,包含财务报表、披露信息和其他有关上市公司的重要信息。

the data set

这些数据包含已向SEC提交财务报表(10k、13等)的公司。不同的经理持有这些公司的股票,这些公司属于不同的行业。在财务表格本身中,文本中提到了各种各样的人,我们将文本分解为更小的块,以便向量搜索查询处理。我们将每个文本块放在一个表单中,并创建了一个向量嵌入,该向量嵌入也存储在chunk节点上。当我们运行向量搜索查询时,我们将查询的向量与CHUNK节点的向量进行比较,以找到最相似的文本。 

检索查询示例

我使用了一些资源来帮助我理解如何在LangChain中编写检索查询。第一篇是Tomaz Bratanic的博客文章,他写了一篇关于如何使用维基百科文章数据在LangChain中使用Neo4j矢量索引的文章。第二个是来自GenAI Stack的查询,它是使用Docker构建的演示应用程序的集合,并利用包含技术问题和答案的StackOverflow数据集。

所有查询都包含在下面:

# Tomaz's blog post retrieval query
retrieval_query = """OPTIONAL MATCH (node)<-[:EDITED_BY]-(p)WITH node, score, collect(p) AS editorsRETURN node.info AS text,score, node {.*, vector: Null, info: Null, editors: editors} AS metadata
"""# GenAI Stack retrieval query
retrieval_query="""WITH node AS question, score AS similarityCALL  { with questionMATCH (question)<-[:ANSWERS]-(answer)WITH answerORDER BY answer.is_accepted DESC, answer.score DESCWITH collect(answer)[..2] as answersRETURN reduce(str='', answer IN answers | str + '\n### Answer (Accepted: '+ answer.is_accepted +' Score: ' + answer.score+ '): '+  answer.body + '\n') as answerTexts}RETURN '##Question: ' + question.title + '\n' + question.body + '\n' + answerTexts AS text, similarity as score, {source: question.link} AS metadataORDER BY similarity ASC // so that best answers are the last
"""

现在,请注意,这些查询看起来并不完整。我们不会用可选的MATCH或with子句启动Cypher查询。这是因为检索查询被添加到向量搜索查询的末尾。

read_query = ("CALL db.index.vector.queryNodes($index, $k, $embedding) ""YIELD node, score "
) + retrieval_query

因此,LangChain首先调用db.index.vector.queryNodes()(更多信息见文档)来查找最相似的节点,并传递(YIELD)相似节点和相似度分数,然后将检索查询添加到向量搜索查询的末尾,以提取额外的上下文。了解这一点非常有帮助,特别是当我们构造检索查询时,以及当我们开始测试结果时!

第二件要注意的事情是,这两个查询都返回相同的三个变量:文本、分数和元数据。这是LangChain所期望的,所以如果没有返回,您将得到错误。文本变量包含相关文本,分数是块与搜索文本的相似度分数,元数据可以包含我们想要的上下文的任何其他信息。

构造检索查询

让我们构建检索查询!我们知道相似性搜索查询将返回节点和分数变量,因此我们可以将这些变量传递到检索查询中,以提取这些相似节点的连接数据。我们还必须返回文本、分数和元数据变量。

retrieval_query = """WITH node AS doc, score as similarity# some more query hereRETURN <something> as text, similarity as score, {<something>: <something>} AS metadata
"""

好了,这就是我们的骨架。现在我们想要中间的是什么?我们知道我们的数据模型将在相似性搜索中提取CHUNK节点(这些将是上面WITH子句中的节点AS文档值)。文本块不能提供大量上下文,因此我们想要拉入连接到CHUNK节点的Form、Person、Company、Manager和Industry节点。我们还在NEXT关系中包含一系列文本块,因此我们可以将下一个和上一个文本块拉到相似的文本块周围。我们还将提取所有具有相似分数的块,我们希望缩小范围。

retrieval_query = """WITH node AS doc, score as similarityORDER BY similarity DESC LIMIT 5CALL { WITH docOPTIONAL MATCH (prevDoc:Chunk)-[:NEXT]->(doc)OPTIONAL MATCH (doc)-[:NEXT]->(nextDoc:Chunk)RETURN prevDoc, doc AS result, nextDoc}# some more query hereRETURN coalesce(prevDoc.text,'') + coalesce(document.text,'') + coalesce(nextDoc.text,'') as text,similarity as score, {<something>: <something>} AS metadata
"""

现在我们保留5个最相似的块,然后在CALL{}子查询中提取前一个和下一个文本块。我们还更改了RETURN,将前一个、当前和下一个块的文本都连接到文本变量中。coalesce()函数用于处理空值,因此如果没有前一个块或下一个块,它将只返回一个空字符串。

让我们添加更多的上下文来拉入图中的其他相关实体。

retrieval_query = """WITH node AS doc, score as similarityORDER BY similarity DESC LIMIT 5CALL { WITH docOPTIONAL MATCH (prevDoc:Chunk)-[:NEXT]->(doc)OPTIONAL MATCH (doc)-[:NEXT]->(nextDoc:Chunk)RETURN prevDoc, doc AS result, nextDoc}WITH result, prevDoc, nextDoc, similarityCALL {WITH resultOPTIONAL MATCH (result)-[:PART_OF]->(:Form)<-[:FILED]-(company:Company), (company)<-[:OWNS_STOCK_IN]-(manager:Manager)WITH result, company.name as companyName, apoc.text.join(collect(manager.managerName),';') as managersWHERE companyName IS NOT NULL OR managers > ""WITH result, companyName, managersORDER BY result.score DESCRETURN result as document, result.score as popularity, companyName, managers}RETURN coalesce(prevDoc.text,'') + coalesce(document.text,'') + coalesce(nextDoc.text,'') as text,similarity as score, {documentId: coalesce(document.chunkId,''), company: coalesce(companyName,''), managers: coalesce(managers,''), source: document.source} AS metadata
"""

第二个CALL{}子查询拉入任何相关的Form、Company和Manager节点(如果存在,则为OPTIONAL MATCH)。我们将经理收集到一个列表中,并确保公司名称和经理列表不为空或空。然后我们按分数对结果排序(目前不提供价值,但可以跟踪文档被检索了多少次)。

由于只返回文本、分数和元数据属性,因此我们需要在元数据字典字段中映射这些额外的值(documentId、company和managers)。这意味着要更新最终的RETURN语句以包含这些语句。

总结

本文中,我们了解了RAG是什么,以及在LangChain中检索查询是如何工作的。我们还查看了一些用于Neo4j的Cypher检索查询示例,并构建了我们自己的示例。我们在查询中使用了SEC文件数据集,并了解了如何提取额外的上下文并将其映射到LangChain期望的三个属性。

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

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

相关文章

C++ | Leetcode C++题解之第19题删除链表的倒数第N个结点

题目&#xff1a; 题解&#xff1a; class Solution { public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode* dummy new ListNode(0, head);ListNode* first head;ListNode* second dummy;for (int i 0; i < n; i) {first first->next;}while (fi…

什么是CSGO搬砖即游戏搬砖注意事项?

CSGO市场是指《反恐精英&#xff1a;全球攻势》游戏内的物品交易市场。玩家可以在这个市场上买卖各类虚拟物品&#xff0c;包括武器皮肤、刀具、手套等。CSGO市场的价格是由供需关系、稀有度、流行度等多个因素影响的。 一般来说&#xff0c;稀有度较高或者比较受欢迎的物品价…

Java安全管理器-SecurityManager

定义&#xff1a; SecurityManager是Java中的一个类&#xff0c;用于实现安全管理功能。它允许应用程序在运行时对安全策略进行动态管理&#xff0c;并控制哪些操作可以执行&#xff0c;哪些应该被拒绝。主要功能包括&#xff1a; 安全策略管理&#xff1a;SecurityManager允许…

注意力机制篇 | YOLOv8改进之清华开源ACmix:自注意力和CNN的融合 | 性能速度全面提升

前言:Hello大家好,我是小哥谈。混合模型ACmix将自注意力机制和卷积神经网络进行整合,使其同时具有自注意力机制和卷积神经网络的优点。这是清华大学、华为和北京人工智能研究院共同发布在2022年CVPR中的论文。ACmix结合了自注意力机制和卷积神经网络的优势,以提高模型的性能…

【Java+Springboot】------ 通过JDBC+GetMapping方法进行数据select查询、多种方式传参、最简单的基本示例!

一、JDBC如何使用、PostGresql数据库 1、在pom.xml 先引用jdbc组件。 <!--jdbc--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency> 2、在pom.xml 再引用p…

为什么在学校很难真正学好嵌入式?

10几年前,我是读电气工程专业,学了很多东西,结构,电机、绘图,plc等等.. 其实,都没什么鸟用,出来还是像个废物。 后面我自学转了单片机开发,说句难听点,自己买个开发板都比在学校学得深。 可能是这个专业的问题,主攻不是嵌入式方向,老师用汇编点个流水灯,这门课就…

Vue结合el-table实现合并单元格(以及高亮单元表头和指定行)

实现效果如下&#xff1a; 思路&#xff1a; 1.首先使用动态表头表格。 2.其次实现动态计算合并单元格。&#xff08;计算规则 传递需要合并的字段&#xff09; 3.然后封装公共的计算单元格方法 export导出供多个页面使用。 4.同时需要封装成公共的组件供多个页面使用。 5…

代码随想录算法训练营第五十一天 |309. 买卖股票的最佳时机含冷冻期、714. 买卖股票的最佳时机含手续费

代码随想录算法训练营第五十一天 |309. 买卖股票的最佳时机含冷冻期、714. 买卖股票的最佳时机含手续费 309. 买卖股票的最佳时机含冷冻期题目解法 714. 买卖股票的最佳时机含手续费题目解法 感悟 309. 买卖股票的最佳时机含冷冻期 题目 解法 题解链接 1. class Solution { …

国内低代码平台盘点:专家推荐值得收藏

随着数字化转型的浪潮不断推进&#xff0c;企业对快速构建和部署应用系统的需求日益迫切。在这样的背景下&#xff0c;低代码平台应运而生&#xff0c;成为企业实现快速应用开发的利器。近几年&#xff0c;低代码行业软件市场蓬勃发展&#xff0c;涌现出了一批优秀的软件产品&a…

贪心算法|763.划分字母区间

力扣题目链接 class Solution { public:vector<int> partitionLabels(string S) {int hash[27] {0}; // i为字符&#xff0c;hash[i]为字符出现的最后位置for (int i 0; i < S.size(); i) { // 统计每一个字符最后出现的位置hash[S[i] - a] i;}vector<int> …

SAP HCM get pernr无法查询到主数据

今天遇到一个比较奇怪的问题&#xff0c;就是ger pernr在2月的时候能找到员工主数据&#xff0c;但是在3月的时候无法找到员工主数据。首先SE36&#xff1a;逻辑数据库页面&#xff0c;看看标准逻辑数据库执行&#xff0c;是否能获取数据。 从上述标准的逻辑书而言&#xff0c;…

防火墙用户管理技术——AAA

目录 一.AAA功能 (1).认证方式 (2).授权方式 (3).计费方式 二.RADUIUS协议 三.用户组织架构及管理 管理员认证登录方式 1.console 2.web 3.telnet 4.ssh 5.ftp 四.认证方式 五.AAA远程登录 1.端口添加IP地址达到互通 2.AAA视图进行配置 3.结果​编辑 一.AAA功能…