📘 **TELUS Agriculture & Consumer Goods** 如何通过 **Haystack Agents** 转变促销交易

集成:Neo4j

将 Neo4j 数据库与 Haystack 一起使用

作者
Sergey Bondarenco

目录

概述

这是一个集成 Neo4j 图数据库与 Haystack v2.0deepset 开发。在 Neo4j 中,向量搜索索引用于存储文档嵌入和进行稠密检索。

该库允许使用 Neo4j 作为 DocumentStore,并实现了必需的 协议 方法。你可以通过从 neo4j_haystack 包导入来开始使用该实现。

from neo4j_haystack import Neo4jDocumentStore

除了 Neo4jDocumentStore,该库还包含以下 Haystack 组件,它们可以在管道中使用。

  • Neo4jEmbeddingRetriever - 一个典型的 检索器组件,可用于查询向量存储索引并查找相关文档。该组件使用 Neo4jDocumentStore 来查询嵌入。
  • Neo4jDynamicDocumentRetriever 也是一个检索器组件,因为它可用于查询 Neo4j 中的文档。然而,它与 Neo4jDocumentStore 解耦,并允许运行任意 Cypher 查询 来提取文档。实际上,可以像 Neo4jDocumentStore 一样查询 Neo4j,包括向量搜索。

neo4j-haystack 库使用 Python 驱动程序Cypher 查询 来与 Neo4j 数据库交互,并将所有复杂性隐藏在底层。

Neo4jDocumentStore 将文档存储为 Neo4j 中的图节点。嵌入作为节点的一部分存储,但使用 ANN 进行向量嵌入的索引和查询由专门的 向量索引 管理。

                                   +-----------------------------+
                                   |       Neo4j Database        |
                                   +-----------------------------+
                                   |                             |
                                   |      +----------------+     |
                                   |      |    Document    |     |
                write_documents    |      +----------------+     |
          +------------------------+----->|   properties   |     |
          |                        |      |                |     |
+---------+----------+             |      |   embedding    |     |
|                    |             |      +--------+-------+     |
| Neo4jDocumentStore |             |               |             |
|                    |             |               |index/query  |
+---------+----------+             |               |             |
          |                        |      +--------+--------+    |
          |                        |      |  Vector Index   |    |
          +----------------------->|      |                 |    |
               query_embeddings    |      | (for embedding) |    |
                                   |      +-----------------+    |
                                   |                             |
                                   +-----------------------------+

在上图中

  • Document 是一个 Neo4j 节点(带有“Document”标签)。
  • properties 是作为节点一部分存储的文档 属性
  • embedding 也是文档节点的属性(在图中为了清晰而单独显示),它是一个类型为 LIST[FLOAT] 的向量。
  • Vector Index 是 Neo4j 在文档节点更新后对其进行索引的地方。

安装

neo4j-haystack 可以像其他 Python 库一样使用 pip 安装。

pip install --upgrade pip # optional
pip install sentence-transformers # required in order to run pipeline examples given below
pip install neo4j-haystack

使用

安装后,你可以像使用其他支持嵌入的文档存储一样开始使用 Neo4jDocumentStore

from neo4j_haystack import Neo4jDocumentStore

document_store = Neo4jDocumentStore(
    url="bolt://:7687",
    username="neo4j",
    password="passw0rd",
    database="neo4j",
    embedding_dim=384,
    embedding_field="embedding",
    index="document-embeddings", # The name of the Vector Index in Neo4j
    node_label="Document", # Providing a label to Neo4j nodes which store Documents
)

假设有一系列文档可用,你可以将它们写入/索引到 Neo4j,例如:

documents: List[Document] = ...
document_store.write_documents(documents)

Neo4jDocumentStore 接受的参数的完整列表可以在 API 文档 中找到。

请注意,你需要有一个正在运行的 Neo4j 数据库实例(不支持内存版 Neo4j)。有几种选项可用:

  • Docker,在同一操作手册中还有其他选项。
  • AuraDB - Neo4j 的完全托管云实例。
  • Neo4j Desktop 客户端应用程序。

最简单的在本地启动数据库的方法是使用 Docker 容器。

docker run \
    --restart always \
    --publish=7474:7474 --publish=7687:7687 \
    --env NEO4J_AUTH=neo4j/passw0rd \
    neo4j:5.15.0

检索文档

Neo4jEmbeddingRetriever 组件可用于通过查询嵌入来从 Neo4j 检索文档。下面是一个管道,它使用查询嵌入和 元数据过滤 来查找文档。

from typing import List

from haystack import Document, Pipeline
from haystack.components.embedders import SentenceTransformersTextEmbedder, SentenceTransformersDocumentEmbedder
from neo4j_haystack import Neo4jEmbeddingRetriever, Neo4jDocumentStore

document_store = Neo4jDocumentStore(
    url="bolt://:7687",
    username="neo4j",
    password="passw0rd",
    database="neo4j",
    embedding_dim=384,
    index="document-embeddings",
)
documents = [
    Document(content="My name is Morgan and I live in Paris.", meta={"release_date": "2018-12-09"})]

document_embedder = SentenceTransformersDocumentEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")  
document_embedder.warm_up()
documents_with_embeddings = document_embedder.run(documents)

document_store.write_documents(documents_with_embeddings.get("documents"))

print(document_store.count_documents())
pipeline = Pipeline()
pipeline.add_component("text_embedder", SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2"))
pipeline.add_component("retriever", Neo4jEmbeddingRetriever(document_store=document_store))
pipeline.connect("text_embedder.embedding", "retriever.query_embedding")

result = pipeline.run(
    data={
        "text_embedder": {"text": "What cities do people live in?"},
        "retriever": {
            "top_k": 5,
            "filters": {"field": "release_date", "operator": "==", "value": "2018-12-09"},
        },
    }
)

documents: List[Document] = result["retriever"]["documents"]
>>> output:
`[Document(id=e765764ab700b231db1eeae208d6a59047b4b93712d1a9e379ae9599128ffdbd, content: 'My name is Morgan and I live in Paris.', meta: {'release_date': '2018-12-09'}, score: 0.8416308164596558)]`

使用 Cypher 检索文档

Neo4jDynamicDocumentRetriever 是一个灵活的检索器组件,它可以运行 Cypher 查询来获取文档。上面 Neo4jEmbeddingRetriever 的示例可以在不使用 Neo4jDocumentStore 的情况下重写。

from haystack import Document, Pipeline
from haystack.components.embedders import SentenceTransformersTextEmbedder

from neo4j_haystack import Neo4jClientConfig, Neo4jDynamicDocumentRetriever

client_config = Neo4jClientConfig(
    url="bolt://:7687",
    username="neo4j",
    password="passw0rd",
    database="neo4j",
)

cypher_query = """
            CALL db.index.vector.queryNodes($index, $top_k, $query_embedding)
            YIELD node as doc, score
            MATCH (doc) WHERE doc.release_date = $release_date
            RETURN doc{.*, score}, score
            ORDER BY score DESC LIMIT $top_k
        """

embedder = SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")
retriever = Neo4jDynamicDocumentRetriever(
    client_config=client_config, runtime_parameters=["query_embedding"], doc_node_name="doc"
)

pipeline = Pipeline()
pipeline.add_component("text_embedder", embedder)
pipeline.add_component("retriever", retriever)
pipeline.connect("text_embedder.embedding", "retriever.query_embedding")

result = pipeline.run(
    data={
        "text_embedder": {"text": "What cities do people live in?"},
        "retriever": {
            "query": cypher_query,
            "parameters": {"index": "document-embeddings", "top_k": 5, "release_date": "2018-12-09"},
        },
    }
)

documents: List[Document] = result["retriever"]["documents"]

请注意,查询参数如何在 cypher_query 中使用。

  • runtime_parameters 是参数名称的列表,在管道中连接组件时,它们将成为输入槽。在我们的例子中,query_embedding 输入连接到 text_embedder.embedding 输出。
  • pipeline.run 指定了 retriever 组件的其他参数,这些参数可以在 cypher_query 中引用,例如 top_k

更多示例

你可以在实现 存储库 中找到更多示例。

你可能在 代码参考 文档中找到更多技术细节。例如,在实际场景中,可能需要调整到 Neo4j 数据库的连接设置(例如,请求超时)。Neo4jDocumentStore 使用 Neo4jClientConfig 类接受扩展的客户端配置。

许可证

neo4j-haystackMIT 许可证下分发。