在这篇文章中,我们将深入探讨该包的功能,并展示如何使用其他附带的检索器进一步定制和改进你的应用程序。在这里,我们将演示如何使用 Cypher 查询通过将图遍历作为附加步骤来扩展向量搜索方法。
设置
我们将使用Neo4j 演示数据库。该数据库模拟了一个电影推荐知识图谱。
你可以使用 “recommendations ”作为用户名和密码,通过浏览器访问数据库,网址是 https://demo.neo4jlabs.com:7473/browser/。在应用程序中使用以下代码段连接数据库:
from neo4j import GraphDatabase
# Demo database credentials
URI = "neo4j+s://demo.neo4jlabs.com"
AUTH = ("recommendations", "recommendations")
# Connect to Neo4j database
driver = GraphDatabase.driver(URI, auth=AUTH)
此外,确保导出 OpenAI 密钥:
import os
os.environ["OPENAI_API_KEY"] = "sk-…"
图中的其他节点
在 Neo4j Web UI 中运行以下命令,可视化电影 “Tom and Huck ”及其与其他节点的直接关系:
MATCH (m:Movie {title: 'Tom and Huck'})-[r]-(n) RETURN *;
请注意,我们现在可以看到电影的类型、哪些演员出演了这部电影,以及其他未包含在 “电影 ”节点中的有用信息。
这些电影节点可作为 LLM 生成查询答案的上下文。不过,在这种设置中,只有电影节点本身所包含的信息才能用作上下文,而其他节点所包含的附加信息则与未使用的电影节点相连。因此,如果用户提出有关电影类型或主演演员等问题,LLM 将无法获得适当的上下文来回答这些问题。
检索
幸运的是,我们可以使用 VectorCypherRetriever 类来检索这些附加信息。该检索器首先使用向量搜索从知识图谱中检索一系列初始节点,然后使用 Cypher 查询从每个初始节点开始遍历图谱,并从与之相连的节点中收集附加信息。
要使用这种检索器,我们首先需要编写 Cypher 查询,以明确指定要与通过向量搜索检索到的节点一起获取哪些附加信息。例如,要在检索电影节点的同时检索演员信息,我们可以使用以下查询:
retrieval_query = """
MATCH
(actor:Actor)-[:ACTED_IN]->(node)
RETURN
node.title AS movie_title,
node.plot AS movie_plot,
collect(actor.name) AS actors;
"""
该查询中的节点变量是对通过初始向量搜索步骤检索到的节点的引用,这里的节点是 “电影 ”节点。该查询会找到在每部电影中出演的所有演员,并返回他们的姓名以及电影的名称和情节。
然后,我们将此查询传递给 VectorCypherRetriever,同时传递给 VectorRetriever 的相同信息,如向量索引名称和嵌入式:
from neo4j import GraphDatabase
from neo4j_genai.embeddings.openai import OpenAIEmbeddings
from neo4j_genai.retrievers import VectorCypherRetriever
driver = GraphDatabase.driver(URI, auth=AUTH)
embedder = OpenAIEmbeddings(model="text-embedding-ada-002")
vc_retriever = VectorCypherRetriever(
driver,
index_name="moviePlotsEmbedding",
embedder=embedder,
retrieval_query=retrieval_query,
)
我们再次使用文本嵌入-ada-002 模型,因为演示数据库中的电影情节嵌入最初就是用它生成的。
现在,我们可以使用我们的检索器来搜索数据库中的电影信息以及主演演员的信息:
query_text = "Who were the actors in the movie about the magic jungle board game?"
retriever_result = retriever.search(query_text=query_text, top_k=3)
items=[
RetrieverResultItem(content="<Record
movie_title='Jumanji'
movie_plot='When two kids find and play a magical board game, they release a man trapped for decades in it and a host of dangers that can only be stopped by finishing the game.'
actors=['Robin Williams', 'Bradley Pierce', 'Kirsten Dunst', 'Jonathan Hyde']>",
metadata=None),
RetrieverResultItem(content="<Record
movie_title='Welcome to the Jungle'
movie_plot='A company retreat on a tropical island goes terribly awry.'
actors=['Jean-Claude Van Damme', 'Adam Brody', 'Rob Huebel', 'Kristen Schaal']>",
metadata=None),
RetrieverResultItem(content='<Record
movie_title=\'Last Mimzy, The\'
movie_plot=\'Two siblings begin to develop special talents after they find a mysterious box of toys. Soon the kids, their parents, and even their teacher are drawn into a strange new world and find a task ahead of them that is far more important than any of them could imagine!\'
actors=[\'Joely Richardson\', \'Rhiannon Leigh Wryn\', \'Timothy Hutton\', "Chris O\'Neil"]>',
metadata=None)
]
metadata={'__retriever': 'VectorCypherRetriever'}
请注意,我们在检索每部电影的标题和情节的同时,还检索了出演该电影的演员。如果使用 VectorRetriever,就可以检索到标题和情节,而不是演员,因为这些内容都存储在每个电影节点的演员节点中。
GraphRAG
要建立完整的 GraphRAG 管道,我们只需用 VectorCypherRetriever 代替VectorRetriever 即可:
from neo4j_genai.llm import OpenAILLM
from neo4j_genai.generation import GraphRAG
# LLM
# Note: the OPENAI_API_KEY must be in the env vars
llm = OpenAILLM(model_name="gpt-4o", model_params={"temperature": 0})
# Initialize the RAG pipeline
rag = GraphRAG(retriever=vc_retriever, llm=llm)
# Query the graph
query_text = "Who were the actors in the movie about the magic jungle board game?"
response = rag.search(query=query_text, retriever_config={"top_k": 3})
print(response.answer)
将返回以下响应:
The actors in the movie "Jumanji," which is about a magical board game, are Robin Williams, Bradley Pierce, Kirsten Dunst, and Jonathan Hyde.
总结
在这篇文章中,我们演示了如何使用 Neo4j GenAI Python 包中的 VectorCypherRetriever 类构建一个简单的 GraphRAG 应用程序。我们展示了这个功能强大的类如何在初始向量检索步骤之外加入图遍历步骤,以便从图中获取仅靠向量检索无法获取的信息。然后,我们展示了这是如何让 LLM 回答有关电影数据库的某些问题的,而如果使用 VectorRetriever 类,LLM 是无法回答这些问题的。