使用LangChain和Neo4j快速创建RAG应用

大家好,Neo4j 通过集成原生的向量搜索功能,增强了其对检索增强生成(RAG)应用的支持,这标志着一个重要的里程碑。这项新功能通过向量索引搜索处理非结构化文本,增强了 Neo4j 在存储和分析结构化数据方面的现有优势,进一步巩固了其在存储和分析结构化数据方面的领先地位。

本文将详细介绍如何利用 Neo4j Desktop(本地版)和 Neo4j Aura(云服务版)来存储向量索引,并构建一个基于纯文本数据的 RAG 应用。

1.云服务部署

要使用基于云的 Neo4j Aura,需要按照以下步骤操作:

首先,点击链接创建一个实例(https://neo4j.com)。在设置过程中,系统会提示输入默认的用户名(neo4j)和实例的密码。请务必记下这个密码,因为设置后将无法再次查看。

创建账户后,会看到这样的界面:

图片

实例启动并运行后,接下来的任务是生成嵌入向量并将其存储。这里采用OpenAI的嵌入技术,这需要一个OPENAI_API_KEY。

为了将这些嵌入向量上传到Neo4j Aura实例,需要准备好以下环境变量:NEO4J_URI(Neo4j实例的URI)、NEO4J_USERNAME(用户名)和NEO4J_PASSWORD(密码)。

使用LangChain的WikipediaLoader功能,直接从Wikipedia网页中导入文章内容。

然后,将文章拆分成多个段落,并去除所有元数据,因为我们不需要存储这些信息。

import os
from langchain.vectorstores import Neo4jVector
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.document_loaders import WikipediaLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough

# OPENAI API 密钥
os.environ["OPENAI_API_KEY"] = "sk-G7F8rdGxxXOWegj5nxxx3BlbkFJj7AuFUP5yyyAKKxSVTGQw"
# neo4j 凭证
NEO4J_URI="neo4j+s://9cb33544.databases.neo4j.io"
NEO4J_USERNAME="neo4j"
NEO4J_PASSWORD="rexxxJJOzDt4kjaaKgM_VyWUdT9GE4hNBXXGMNubg"

# 加载数据和分块
# 读取 Wikipedia 文章
raw_documents = WikipediaLoader(query="Leonhard Euler").load()
# 定义分块策略
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(
    chunk_size=1000, chunk_overlap=20
)
# 分块文档
documents = text_splitter.split_documents(raw_documents)

# 从元数据中移除摘要
for d in documents:
    del d.metadata['summary']

以下代码片段可将嵌入向量导入 Neo4j 实例:

# 实例化 Neo4j 向量
neo4j_vector = Neo4jVector.from_documents(
    documents,
    OpenAIEmbeddings(),
    url=NEO4J_URI,
    username=NEO4J_USERNAME,
    password=NEO4J_PASSWORD
)

要在 Neo4j Aura 中访问和检查嵌入向量,需点击界面上的打开图标,会在浏览器中新开一个标签页。在这个新标签页中,可以查看到块和向量索引的详细信息。我们共有56个块,在系统中被识别为节点。此外,还可以在这个标签页中查看每个块对应的嵌入向量及其具体细节。

图片

向量检索

这段代码片段通过使用 Neo4jVector 对象并进行相似性搜索,帮助检索与查询“Euler 在哪里长大?”相关的前 4 个相关块。这段代码默认采用余弦相似性方法来识别和排序向量之间的相似度。

query = "Where did Euler grow up?"
results = neo4j_vector.similarity_search(query=query, k=4)
print(results)

# 检索到的四个文档
# [Document(page_content='== Early life ==\nLeonhard Euler was born on 15 April 1707, in Basel to Paul III Euler, a pastor of the Reformed Church, and Marguerite (née Brucker), whose ancestors include a number of well-known scholars in the classics. He was the oldest of four children, having two younger sisters, Anna Maria', metadata={'title': 'Leonhard Euler', 'source': 'https://en.wikipedia.org/wiki/Leonhard_Euler'}), ...]

创建链

我们构建了一个名为final_chain的处理链,旨在高效地处理问题并生成答案。这个链的工作原理是:首先,它接收并传递上下文信息给Neo4jVector retriever,以便从Neo4j数据库中检索相关的向量。随后,链会利用一个OpenAI模型(版本为gpt-4-1106-preview)处理接收到的提示。最终,通过一个解析器对模型的输出进行处理,以提炼出精确的答案。final_chain的设计实现了在特定上下文中对问题的智能处理和答案生成,提高了整个操作的自动化和效率。

prompt = ChatPromptTemplate.from_template(
    """Answer the question based only on the context provided.
    
    Context: {context}
    
    Question: {question}"""
)

# 创建一个 lambda 函数将上下文传递给 Neo4jVector retriever
context_to_retriever = lambda x: x["question"]

# 创建链,将上下文赋值给 Neo4jVector retriever
final_chain = (
    RunnablePassthrough.assign(context=context_to_retriever, target=lambda x: neo4j_vector)
    | prompt
    | ChatOpenAI(model="gpt-4-1106-preview")
    | StrOutputParser()
)

result = final_chain.invoke({'question': query})

# 最终结果
print(result)
# Euler 在瑞士巴塞尔长大。

2.本地部署

如果想在本地的Neo4j Desktop中存储嵌入向量,可以直接在本地环境中运行该应用。操作起来非常简单,只需对凭证信息进行更新,其余的步骤则无需更改。

具体来说,需要分别为数据库和数据库管理系统设置用户名和密码。完成这些设置后,就可以在本地的Neo4j Desktop上顺利地执行应用程序了。

NEO4J_URI="bolt://localhost:7687"
NEO4J_USERNAME="neo4j"
NEO4J_PASSWORD="newpassword"

其余部分与上述相同。

3.总结

综上所述,Neo4j 通过整合其内置的向量搜索功能,显著提升了对检索增强生成(RAG)应用的支持能力。这不仅加强了其在传统结构化数据分析方面的优势,还使其能够更有效地处理非结构化文本数据。本文详细介绍了如何利用Neo4j Aura和Neo4j Desktop来存储向量索引,并在LangChain框架的辅助下,构建出高效的RAG应用。

使用Spring Data Neo4j可以通过以下步骤快速实时插入大量节点数据: 1. 配置Neo4j数据库连接:在application.properties文件中添加Neo4j数据库连接信息。 2. 创建节点实体类:使用@NodeEntity注解创建节点实体类,并在类中定义节点属性。 3. 创建节点仓库:使用@NodeRepository注解创建节点仓库,并继承Neo4jRepository接口。 4. 使用Neo4jTemplate插入数据:使用Neo4jTemplate的save方法插入节点数据。可以使用batch方法批量插入数据。 示例代码如下: ```java // 配置Neo4j数据库连接 @Configuration @EnableNeo4jRepositories(basePackages = "com.example.repository") public class Neo4jConfig extends Neo4jConfiguration { @Bean public SessionFactory getSessionFactory() { return new SessionFactory(configuration(), "com.example.entity"); } @Bean public org.neo4j.ogm.config.Configuration configuration() { org.neo4j.ogm.config.Configuration configuration = new org.neo4j.ogm.config.Configuration.Builder() .uri("bolt://localhost") .credentials("neo4j", "password") .build(); return configuration; } } // 创建节点实体类 @NodeEntity public class Person { @Id @GeneratedValue private Long id; private String name; // getters and setters } // 创建节点仓库 @Repository public interface PersonRepository extends Neo4jRepository<Person, Long> { } // 插入数据 @Service public class PersonService { @Autowired private Neo4jTemplate neo4jTemplate; @Autowired private PersonRepository personRepository; public void savePerson(Person person) { // 使用Neo4jTemplate插入数据 neo4jTemplate.save(person); // 批量插入数据 List<Person> persons = new ArrayList<>(); for (int i = 0; i < 10000; i++) { Person p = new Person(); p.setName("person" + i); persons.add(p); } neo4jTemplate.batchSave(persons); } } ``` 以上是一个简单的示例,你可以按照自己的需求进行适当的修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

python慕遥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值