通过使用LangChain库,您可以方便地生成Cypher查询,从而高效地从Neo4j中检索信息。

如果您已经开发或计划实施任何使用大型语言模型的解决方案,您很可能听说过LangChain库。LangChain库是最广为人知的Python库,用于开发使用LLM的应用程序,具备各种功能。它被设计为模块化,允许我们在可用的模块中使用任何LLM,例如链式结构、工具、内存或代理。

一个月前,我花了一周的时间研究和实施了一个解决方案,使任何人都可以直接从LangChain库中检索Neo4j的信息,并在他们的LLM应用程序中使用它。我对LangChain库的内部有了很多了解,并在博客文章中记录了我的经验。

我的一位同事给我看了一个LangChain的功能请求,用户要求将我从Neo4j数据库中检索信息的工作作为一个模块直接添加到LangChain库中,这样就不需要额外的代码或外部模块来集成Neo4j到LangChain应用程序中。由于我已经熟悉LangChain的内部结构,我决定尝试自己实现Cypher搜索功能。我花了一个周末进行研究和编码解决方案,并确保它符合贡献标准,以便将其添加到库中。幸运的是,LangChain的维护者非常积极和开放,Cypher搜索已经在最新版本的LangChain库中添加了。感谢非常感谢您维护这个出色的图书馆,并且对新想法非常积极响应。

在这篇博客文章中,我将向您展示如何使用LangChain库中新增的Cypher搜索功能从Neo4j数据库中检索信息。

什么是知识图谱

LangChain已经与Vector和SQL数据库进行了集成,那么为什么我们还需要与Neo4j这样的图数据库进行集成呢?

知识图谱非常适合存储异构且高度连接的数据。例如,上面的图像包含有关人物、组织、电影、网站等的信息。虽然直观地建模和存储各种数据集的能力令人难以置信,但我认为使用图形的主要好处是能够通过它们之间的关系分析数据点。图形使我们能够发现传统数据库和分析方法往往忽视的个别数据点周围的上下文中的连接和相关性。

图数据库的威力在处理复杂系统时真正展现出来,其中相互依赖和交互对于理解系统至关重要。

它们使我们能够超越个别数据点,深入探索定义其背景的复杂关系。这提供了对数据的更深入、更全面的视角,促进了更好的决策和知识发现。

搭建Neo4j环境

如果您已经有一个现有的Neo4j数据库,您可以使用它来尝试新添加的Cypher搜索功能。Cypher搜索模块利用图模式信息生成Cypher语句,这意味着您可以将其插入到任何Neo4j数据库中。

如果您还没有任何Neo4j数据库,您可以使用Neo4j Sandbox,它提供了一个免费的Neo4j数据库的云实例。您需要注册并实例化任何可用的预填充数据库。在本博客文章中,我将使用ICIJ Paradise Papers数据集,但您也可以使用其他任何数据集。该数据集是由国际调查记者合作组织作为其离岸泄漏数据库的一部分提供的。

图中包含四种类型的节点:

  • **Entity** - 离岸法律实体。这可以是在低税收管辖区创建的公司、信托、基金会或其他法律实体。
  • **Officer** - 一个在离岸实体中扮演角色的个人或公司,例如受益人、董事或股东。图表中显示的关系只是现有关系的一部分样本。
  • **Intermediary** - 一个为寻求离岸公司和离岸服务提供商之间牵线搭桥的中间人 — 通常是律师事务所或中介机构,他们会要求离岸服务提供商创建一个离岸公司。
  • **Address** - ICIJ所获得的原始数据库中显示的注册地址。

知识图谱Cypher搜索

Cypher Search这个名字来源于Cypher,它是一种用于与Neo4j等图数据库进行交互的查询语言。

知识图谱Cypher链工作流程

为了让LangChain能够从图数据库中检索信息,我实现了一个模块,可以将自然语言转换为Cypher语句,用它来从Neo4j中检索数据,并以自然语言形式将检索到的信息返回给用户。这种自然语言和数据库语言之间的双向转换过程不仅增强了数据检索的整体可访问性,还极大地提升了用户体验。

LangChain库的美妙之处在于其简洁性。我们只需要几行代码,就能够使用自然语言从Neo4j中获取信息。

from langchain.chat_models import ChatOpenAI
from langchain.chains import GraphCypherQAChain
from langchain.graphs import Neo4jGraph
graph = Neo4jGraph(
    url="bolt://54.172.172.36:7687",
    username="neo4j",
    password="steel-foreheads-examples")
chain = GraphCypherQAChain.from_llm(
    ChatOpenAI(temperature=0), 
    graph=graph, verbose=True,)

在这里,我们使用OpenAI的gpt-3.5-turbo模型来生成Cypher语句。这些Cypher语句是基于图模式生成的,这意味着理论上你可以将Cypher链插入任何Neo4j实例中,它应该能够回答自然语言问题。不幸的是,我还没有测试其他LLM提供商生成Cypher语句的能力,因为我无法访问它们中的任何一个。不过,如果你愿意尝试一下,我很想听听你对其他LLM生成Cypher语句的评价。当然,如果你想摆脱对LLM云服务提供商的依赖,你也可以通过对开源LLM进行微调来生成Cypher语句。

让我们从一个简单的测试开始。

chain.run("""Which intermediary is connected to most entites?""")

结果

生成的答案

我们可以观察生成的Cypher语句和从Neo4j检索到的信息,用于形成答案。这是一个非常简单的设置。让我们继续下一个例子。

chain.run("""Who are the officers of ZZZ-MILI COMPANY LTD.?""")

结果

生成的答案

既然我们正在使用图形,那么让我们构建一个能够充分利用图形数据库优势的问题。

chain.run("""How are entities SOUTHWEST LAND DEVELOPMENT LTD. and Dragon Capital Markets Limited related?""")

一开始看起来,生成的Cypher语句似乎没问题。然而,问题在于Cypher语句使用了变长路径查找语法,并且将关系视为无向的。结果,这种类型的查询非常不优化,会导致行数爆炸增长。

gpt-3.5-turbo的好处在于它能够根据我们在输入中提供的提示和指示进行操作。例如,我们可以要求它只找到最短的路径。

chain.run("""How are entities SOUTHWEST LAND DEVELOPMENT LTD. and Dragon Capital Markets Limited connected?Find a shortest path.""")

生成的答案

现在我们暗示只应该检索最短路径,这样就不会再遇到基数爆炸的问题了。然而,我注意到一个问题,就是如果返回了一个路径对象,LLM有时候并不能提供最佳结果。生成的Cypher语句在Neo4j浏览器中返回以下可视化结果。

图形可视化

生成的自然语言回复并没有真正提到这两家公司在同一地址注册,而是根据节点属性自己生成了最短路径。然而,我们也可以通过指示模型使用哪些信息来修复这个问题。

chain.run("""How are entities SOUTHWEST LAND DEVELOPMENT LTD. and Dragon Capital Markets Limited connected?Find a shortest path.Return only name properties of nodes and relationship types""")

结果

生成的答案

现在我们可以得到更好的响应和更恰当的响应。你给LLM提供的线索越多,你可以期望得到的结果就越好。例如,你还可以指示它可以遍历哪些关系。

chain.run("""How are entities SOUTHWEST LAND DEVELOPMENT LTD. and Dragon Capital Markets Limited connected?Find a shortest path and use only officer, intermediary, and connected relationships.Return only name properties of nodes and relationship types""")

结果

生成的答案

你可以看到生成的Cypher语句只允许遍历OFFICER\_OF、INTERMEDIARY\_OF和CONNECTED_TO关系。同样的Cypher语句会生成以下图形可视化。

图形可视化

摘要

图形数据库是检索或分析人与组织等各种实体之间连接的绝佳工具。在这篇博客文章中,我们看了一个简单的最短路径用例,其中关系的数量和关系类型的顺序事先是未知的。这些类型的查询在向量数据库中几乎是不可能的,而在SQL数据库中也可能非常复杂。

我对将Cypher Search添加到LangChain库中感到非常兴奋。请测试一下,并告诉我它对你来说效果如何,特别是如果你在其他LLM模型上进行测试或有令人兴奋的用例。另外,请记得关注,因为我已经准备好了一些博客文章,将探索LangChain库中的Cypher Search功能。