用户指南:RAG

本指南为使用 Neo4j GraphRAG 包并根据特定需求进行配置提供了起点。

快速入门

要使用 neo4j-graphrag 包执行 GraphRAG 查询,需要几个组件:

  1. Neo4j 驱动程序:用于查询您的 Neo4j 数据库。

  2. 检索器:neo4j-graphrag 包提供了一些实现(请参阅专门章节),如果所提供的实现无法满足您的需求,您也可以自行编写(请参阅如何编写自定义检索器)。

  3. LLM:为了生成答案,我们需要调用 LLM 模型。neo4j-graphrag 包的 LLM 接口与 LangChain 兼容。如果需要,开发人员也可以编写自己的接口。

在实践中,只需几行代码即可完成:

from neo4j import GraphDatabase
from neo4j_graphrag.retrievers import VectorRetriever
from neo4j_graphrag.llm import OpenAILLM
from neo4j_graphrag.generation import GraphRAG
from neo4j_graphrag.embeddings import OpenAIEmbeddings

# 1. Neo4j driver
URI = "neo4j://:7687"
AUTH = ("neo4j", "password")

INDEX_NAME = "index-name"

# Connect to Neo4j database
driver = GraphDatabase.driver(URI, auth=AUTH)

# 2. Retriever
# Create Embedder object, needed to convert the user question (text) to a vector
embedder = OpenAIEmbeddings(model="text-embedding-3-large")

# Initialize the retriever
retriever = VectorRetriever(driver, INDEX_NAME, embedder)

# 3. LLM
# Note: the OPENAI_API_KEY must be in the env vars
llm = OpenAILLM(model_name="gpt-5", model_params={"temperature": 0})

# Initialize the RAG pipeline
rag = GraphRAG(retriever=retriever, llm=llm)

# Query the graph
query_text = "How do I do similarity search in Neo4j?"
response = rag.search(query_text=query_text, retriever_config={"top_k": 5})
print(response.answer)

警告

使用 OpenAILLM 需要 openai Python 客户端。您可以使用 pip install “neo4j_graphrag[openai]” 安装它。

以下各节提供了有关如何自定义此代码的更多详细信息。

GraphRAG 配置

每个组件都可以单独配置:LLM 和提示词。

使用其他 LLM 模型

如果不能直接使用 OpenAI,还有一些可用的替代方案:

  • 使用 Azure OpenAI (GPT…)。

  • 使用 Google VertexAI (Gemini…)。

  • 使用 Anthropic LLM (Claude…)。

  • 使用 Mistral LLM。

  • 使用 Cohere。

  • 使用本地 Ollama 模型。

  • 实现自定义接口。

  • 利用任何 LangChain 聊天模型。

下面展示了所有选项。

使用 Azure Open AI LLM

可以通过切换到 AzureOpenAILLM 类来使用 Azure OpenAI:

from neo4j_graphrag.llm import AzureOpenAILLM
llm = AzureOpenAILLM(
    model_name="gpt-5",
    azure_endpoint="https://example-endpoint.openai.azure.com/",  # update with your endpoint
    api_version="2024-06-01",  # update appropriate version
    api_key="...",  # api_key is optional and can also be set with OPENAI_API_KEY env var
)
llm.invoke("say something")

查看 OpenAI Python 客户端 文档 以了解有关配置的更多信息。

注意

为了运行此代码,需要安装 openai Python 包:pip install “neo4j_graphrag[openai]”

请参阅 AzureOpenAILLM

使用 VertexAI LLM

要使用 VertexAI,请实例化 VertexAILLM 类:

from neo4j_graphrag.llm import VertexAILLM
from vertexai.generative_models import GenerationConfig

generation_config = GenerationConfig(temperature=0.0)
llm = VertexAILLM(
    model_name="gemini-2.5-flash", generation_config=generation_config
)
llm.invoke("say something")

注意

为了运行此代码,需要安装 google-cloud-aiplatform Python 包:pip install “neo4j_graphrag[google]”

请参阅 VertexAILLM

使用 Anthropic LLM

要使用 Anthropic,请实例化 AnthropicLLM 类:

from neo4j_graphrag.llm import AnthropicLLM

llm = AnthropicLLM(
    model_name="claude-3-opus-20240229",
    model_params={"max_tokens": 1000},  # max_tokens must be specified
    api_key=api_key,  # can also set `ANTHROPIC_API_KEY` in env vars
)
llm.invoke("say something")

注意

为了运行此代码,需要安装 anthropic Python 包:pip install “neo4j_graphrag[anthropic]”

请参阅 AnthropicLLM

使用 MistralAI LLM

要使用 MistralAI,请实例化 MistralAILLM 类:

from neo4j_graphrag.llm import MistralAILLM

llm = MistralAILLM(
    model_name="mistral-small-latest",
    api_key=api_key,  # can also set `MISTRAL_API_KEY` in env vars
)
llm.invoke("say something")

注意

为了运行此代码,需要安装 mistralai Python 包:pip install “neo4j_graphrag[mistralai]”

请参阅 MistralAILLM

使用 Cohere LLM

要使用 Cohere,请实例化 CohereLLM 类:

from neo4j_graphrag.llm import CohereLLM

llm = CohereLLM(
    model_name="command-r",
    api_key=api_key,  # can also set `CO_API_KEY` in env vars
)
llm.invoke("say something")

注意

为了运行此代码,需要安装 cohere Python 包:pip install “neo4j_graphrag[cohere]”

请参阅 CohereLLM

通过 Ollama 使用本地模型

假设 Ollama 在默认地址 127.0.0.1:11434 上运行,可以使用以下方式进行查询:

from neo4j_graphrag.llm import OllamaLLM
llm = OllamaLLM(
    model_name="orca-mini",
    # model_params={"options": {"temperature": 0}, "format": "json"},
    # host="...",  # when using a remote server
)
llm.invoke("say something")

使用来自 LangChain 的模型

LangChain Python 包包含各种 LLM 和提供程序的实现。其接口与我们的 GraphRAG 接口兼容,便于集成。

from neo4j_graphrag.generation import GraphRAG
from langchain_community.chat_models import ChatOllama

# retriever = ...

llm = ChatOllama(model="llama3:8b")
rag = GraphRAG(retriever=retriever, llm=llm)
query_text = "How do I do similarity search in Neo4j?"
response = rag.search(query_text=query_text, retriever_config={"top_k": 5})
print(response.answer)

但是,并不强制要求使用 LangChain。

使用自定义模型

如果提供的实现不符合需求,开发人员可以通过子类化 LLMInterface 来创建自定义 LLM 类。以下是使用 Python Ollama 客户端的示例:

import ollama
from neo4j_graphrag.llm import LLMInterface, LLMResponse

class OllamaLLM(LLMInterface):

    def invoke(self, input: str) -> LLMResponse:
        response = ollama.chat(model=self.model_name, messages=[
          {
            'role': 'user',
            'content': input,
          },
        ])
        return LLMResponse(
            content=response["message"]["content"]
        )

    async def ainvoke(self, input: str) -> LLMResponse:
        return self.invoke(input)  # TODO: implement async with ollama.AsyncClient


# retriever = ...

llm = OllamaLLM("llama3:8b")

rag = GraphRAG(retriever=retriever, llm=llm)
query_text = "How do I do similarity search in Neo4j?"
response = rag.search(query_text=query_text, retriever_config={"top_k": 5})
print(response.answer)

请参阅 LLMInterface

LLM 的结构化输出

结构化输出使 LLM 能够返回符合预定义模式(Pydantic 模型或 JSON 模式)的响应,从而确保类型安全且一致的数据结构。这对于提取实体、关系或任何需要自动验证的结构化数据非常有用。

V2 接口(推荐):对于 OpenAILLMVertexAILLM,在使用 V2 接口(LLMMessage 列表)时,将 response_format 作为参数传递给 invoke() 方法。response_format 接受 Pydantic 模型类或 JSON 模式字典。如果使用 response_format,其他 LLM 提供程序将引发 NotImplementedError

V1 接口(遗留):使用 V1 接口(字符串输入)时,仅通过构造函数参数(OpenAI 使用 model_params,VertexAI 使用 generation_config)支持标准 JSON 模式。在 V1 中,不允许在 invoke() 中使用 response_format 参数。

from pydantic import BaseModel, ConfigDict
from neo4j_graphrag.llm import OpenAILLM
from neo4j_graphrag.types import LLMMessage

class Person(BaseModel):
    model_config = ConfigDict(extra="forbid")  # Required for OpenAI structured output

    name: str
    age: int
    occupation: str

llm = OpenAILLM(model_name="gpt-5-mini")

# V2: Pass response_format to invoke()
messages = [LLMMessage(role="user", content="Extract: John is a 30 year old engineer.")]
response = llm.invoke(messages, response_format=Person, temperature=0)
person = Person.model_validate_json(response.content)  # {"name": "John", "age": 30, ...}

# V1: Use constructor parameters for standard JSON mode
llm_v1 = OpenAILLM(
    model_name="gpt-5-mini",
    model_params={"response_format": {"type": "json_object"}, "temperature": 0}
)
response_v1 = llm_v1.invoke("Extract person in JSON format: John is 30 years old.")

OpenAI 结构化输出

OpenAI 支持 Pydantic 模型、JSON 模式和 JSON 对象模式。重要:Pydantic 模型必须包含 ConfigDict(extra=”forbid”) 以生成带有 additionalProperties: false 的模式,这是 OpenAI 严格模式所必需的。

from neo4j_graphrag.llm import OpenAILLM
from neo4j_graphrag.types import LLMMessage

llm = OpenAILLM(model_name="gpt-5-mini")

# JSON schema
json_schema = {
    "type": "object",
    "properties": {"name": {"type": "string"}, "age": {"type": "integer"}},
    "required": ["name", "age"]
}
messages = [LLMMessage(role="user", content="Extract: John is 30.")]
response = llm.invoke(messages, response_format=json_schema, temperature=0)

# JSON object mode (no schema enforcement)
response = llm.invoke(messages, response_format={"type": "json_object"}, temperature=0.5)

VertexAI 结构化输出

当将 response_format 传递给 invoke() 时,VertexAI 在内部使用带有 response_mime_typeresponse_schemaGenerationConfig。支持 Pydantic 模型和 JSON 模式。重要:额外的 GenerationConfig 参数(例如 temperaturemax_output_tokens)可以作为 kwargs 传递给 invoke()。 .. code:: python

from pydantic import BaseModel, ConfigDict from neo4j_graphrag.llm import VertexAILLM from neo4j_graphrag.types import LLMMessage

class Person(BaseModel):

model_config = ConfigDict(extra=”forbid”)

name: str age: int

llm = VertexAILLM(model_name=”gemini-1.5-pro”) messages = [LLMMessage(role=”user”, content=”Extract: John is 30.”)] response = llm.invoke(messages, response_format=Person, temperature=0) person = Person.model_validate_json(response.content)

速率限制处理

所有 LLM 实现都包含自动速率限制,默认情况下使用带有指数退避 (exponential backoff) 的重试逻辑。此功能通过在尝试之间自动重试失败的请求并增加等待时间,有助于妥善处理来自 LLM 提供商的 API 速率限制。

默认速率限制处理程序

所有 LLM 实例默认启用速率限制,配置如下:

  • 最大尝试次数: 3

  • 最小等待时间:1.0 秒

  • 最大等待时间:60.0 秒

  • 乘数:2.0(指数退避)

from neo4j_graphrag.llm import OpenAILLM

# Rate limiting is automatically enabled
llm = OpenAILLM(model_name="gpt-5")

# The LLM will automatically retry on rate limit errors
response = llm.invoke("Hello, world!")

注意

要更改 RetryRateLimitHandler 的默认配置:

from neo4j_graphrag.llm import OpenAILLM
from neo4j_graphrag.utils.rate_limit import RetryRateLimitHandler

# Customize rate limiting parameters
llm = OpenAILLM(
    model_name="gpt-5",
    rate_limit_handler=RetryRateLimitHandler(
        max_attempts=10,    # Increase max retry attempts
        min_wait=2.0,       # Increase minimum wait time
        max_wait=120.0,     # Increase maximum wait time
        multiplier=3.0      # More aggressive backoff
    )
)

自定义速率限制

您可以通过创建自己的速率限制处理程序来自定义速率限制行为:

from neo4j_graphrag.llm import AnthropicLLM
from neo4j_graphrag.utils.rate_limit import RateLimitHandler

class CustomRateLimitHandler(RateLimitHandler):
    """Implement your custom rate limiting strategy."""
    # Implement required methods: handle_sync, handle_async
    # and optionally override is_retryable_exception and to_retryable_error
    # to classify additional exception types as retryable or convert them to retryable errors
    pass

# Create custom rate limit handler and pass it to the LLM interface
custom_handler = CustomRateLimitHandler()

llm = AnthropicLLM(
    model_name="claude-3-sonnet-20240229",
    rate_limit_handler=custom_handler,
)

禁用速率限制

对于高吞吐量应用程序或当您在外部处理速率限制时,可以将其禁用:

from neo4j_graphrag.llm import CohereLLM, NoOpRateLimitHandler

# Disable rate limiting completely
llm = CohereLLM(
    model_name="command-r-plus",
    rate_limit_handler=NoOpRateLimitHandler(),
)
llm.invoke("Hello, world!")

提示词配置

提示词通过 PromptTemplate 类进行管理。具体而言,GraphRAG 管道使用 RagTemplate,其默认提示词可通过 rag.prompt_template.template 访问。要使用不同的提示词,请子类化 RagTemplate 类,并在初始化期间将其传递给 GraphRAG 管道对象:

from neo4j_graphrag.generation import RagTemplate, GraphRAG

# retriever = ...
# llm = ...

prompt_template = RagTemplate(
    prompt="Answer the question {question} using context {context} and examples {examples}",
    expected_inputs=["context", "question", "examples"]
)

rag = GraphRAG(retriever=retriever, llm=llm, prompt_template=prompt_template)

# ...

请参阅 PromptTemplate

GraphRAG 管道中最后一个可配置的组件是检索器。下面介绍了各种可用的选项。

检索器配置

我们为以下检索器提供了实现:

检索器列表

检索器

描述

VectorRetriever

基于 Neo4j 向量索引和查询文本或向量执行相似性搜索。返回匹配的 node 和相似度 score

VectorCypherRetriever

基于 Neo4j 向量索引和查询文本或向量执行相似性搜索。返回的结果可以通过在索引搜索后执行的检索查询参数进行配置。它可用于获取匹配节点周围的更多上下文。

HybridRetriever

使用 Neo4j 中的向量和全文索引。

HybridCypherRetriever

与 HybridRetriever 相同,但具有类似于 VectorCypherRetriever 的检索查询。

ToolsRetriever

使用 LLM 根据用户查询智能选择和执行适当的工具。结合来自多个工具的结果并进行适当归因。

Text2Cypher

将用户问题转换为 Cypher 查询,以便针对 Neo4j 数据库(或知识图谱)运行。查询结果随后传递给 LLM 以生成最终答案。

WeaviateNeo4jRetriever

当向量保存在 Weaviate 向量数据库中时,使用此检索器。

PineconeNeo4jRetriever

当向量保存在 Pinecone 向量数据库中时,使用此检索器。

QdrantNeo4jRetriever

当向量保存在 Qdrant 向量数据库中时,使用此检索器。

检索器都公开了一个我们将在后续章节中讨论的 search 方法。

向量检索器

实例化向量检索器最简单的方法是:

from neo4j_graphrag.retrievers import VectorRetriever

retriever = VectorRetriever(
    driver,
    index_name=POSTER_INDEX_NAME,
)

index_name 是将用于相似性搜索的 Neo4j 向量索引的名称。

警告

向量索引使用近似最近邻算法。请参阅 Neo4j 文档 以了解其局限性。

搜索相似向量

要识别最相似的前 3 个节点,请按向量执行搜索:

vector = []  # a list of floats, same size as the vectors in the Neo4j vector index
retriever_result = retriever.search(query_vector=vector, top_k=3)

然而,在大多数情况下,将提供文本(来自用户)而不是向量。在这种情况下,需要一个 Embedder

搜索相似文本

搜索文本时,需要指定检索器如何将文本转换(嵌入)为向量。因此,检索器需要了解嵌入器 (Embedder)。

embedder = OpenAIEmbeddings(model="text-embedding-3-large")

# Initialize the retriever
retriever = VectorRetriever(
    driver,
    index_name=POSTER_INDEX_NAME,
    embedder=embedder,
)

query_text = "How do I do similarity search in Neo4j?"
retriever_result = retriever.search(query_text=query_text, top_k=3)

嵌入器

目前,此包支持以下嵌入器:

之前已经展示了 OpenAIEmbeddings。以下是如何使用 SentenceTransformerEmbeddings

from neo4j_graphrag.embeddings import SentenceTransformerEmbeddings

embedder = SentenceTransformerEmbeddings(model="all-MiniLM-L6-v2")  # Note: this is the default model

如果需要其他嵌入器,可以使用 Embedder 接口创建自定义嵌入器。

嵌入器速率限制

所有嵌入器实现都包含自动速率限制,默认情况下使用带有指数退避的重试逻辑,类似于 LLM 实现。此功能有助于妥善处理来自嵌入提供商的 API 速率限制。

from neo4j_graphrag.embeddings import OpenAIEmbeddings
from neo4j_graphrag.utils.rate_limit import RetryRateLimitHandler, NoOpRateLimitHandler

# Default rate limiting (automatically enabled)
embedder = OpenAIEmbeddings(model="text-embedding-3-large")

# Custom rate limiting configuration
embedder = OpenAIEmbeddings(
    model="text-embedding-3-large",
    rate_limit_handler=RetryRateLimitHandler(
        max_attempts=5,
        min_wait=2.0,
        max_wait=120.0
    )
)

# Disable rate limiting
embedder = OpenAIEmbeddings(
    model="text-embedding-3-large",
    rate_limit_handler=NoOpRateLimitHandler()
)

速率限制配置的工作方式与 LLM 相同。有关自定义选项的更多详细信息,请参阅上面的 速率限制处理 一节。

其他向量检索器配置

通常,并非所有节点属性都与 RAG 上下文相关;只有少数选定的属性适合包含在 LLM 提示词上下文中。您可以使用 return_properties 参数指定要返回的属性:

from neo4j_graphrag.retrievers import VectorRetriever

retriever = VectorRetriever(
    driver,
    index_name=POSTER_INDEX_NAME,
    embedder=embedder,
    return_properties=["title"],
)

预过滤器

执行相似性搜索时,可能会有需要应用的约束。例如,过滤掉 2000 年之前发行的电影。这可以使用 filters 来实现。

注意

过滤器适用于除混合检索器之外的所有检索器。下面的文档不适用于外部检索器,它们使用自己的过滤器语法(请参阅 向量数据库)。

from neo4j_graphrag.retrievers import VectorRetriever

retriever = VectorRetriever(
    driver,
    index_name=POSTER_INDEX_NAME,
)

filters = {
    "year": {
        "$gte": 2000,
    }
}

query_text = "How do I do similarity search in Neo4j?"
retriever_result = retriever.search(query_text=query_text, filters=filters)

警告

使用过滤器时,相似性搜索会绕过向量索引,转而使用精确匹配算法。确保预过滤足够严格,以防止查询过载。

目前支持的操作符有:

  • $eq:等于。

  • $ne:不等于。

  • $lt:小于。

  • $lte:小于或等于。

  • $gt:大于。

  • $gte:大于或等于。

  • $between:在两者之间。

  • $in:值在给定列表中。

  • $nin:不在列表中。

  • $like:LIKE 操作符,区分大小写。

  • $ilike:LIKE 操作符,不区分大小写。

以下是有效过滤器语法及其含义的示例:

过滤器语法

Filter

含义

{“year”: 1999}

year = 1999

{“year”: {“$eq”: 1999}}

year = 1999

{“year”: 2000, “title”: “The Matrix”}

year = 1999 AND title = “The Matrix”

{“$and”: [{“year”: 2000}, {“title”: “The Matrix”}]}

year = 1999 AND title = “The Matrix”

{“$or”: [{“title”: “The Matrix Revolution”}, {“title”: “The Matrix”}]}

title = “The Matrix” OR title = “The Matrix Revolution”

{“title”: {“$like”: “The Matrix”}}

title CONTAINS “The Matrix”

{“title”: {“$ilike”: “the matrix”}}

toLower(title) CONTAINS “The Matrix”

另请参阅 VectorRetriever

向量 Cypher 检索器

VectorCypherRetriever 通过结合基于向量的相似性搜索和图遍历技术,充分利用了 Neo4j 的图能力。它处理查询嵌入以针对指定的向量索引执行相似性搜索,检索相关节点变量,然后执行 Cypher 查询以根据这些节点遍历图。这种集成确保了检索既具有语义意义,又由底层图结构进行了上下文丰富。

检索查询

在构建检索查询时,需要注意查询范围内有两个可用变量:

  • node:表示从向量索引搜索中检索到的节点。

  • score:表示相似度得分。

例如,在包含演员的电影图中,其中向量索引涉及某些电影属性,检索查询可以构建如下:

retrieval_query = """
RETURN  node.title as movieTitle,
        node.plot as moviePlot,
        collect { MATCH (actor:Actor)-[:ACTED_IN]->(node) RETURN actor.name } AS actors
"""
retriever = VectorCypherRetriever(
    driver,
    index_name=INDEX_NAME,
    retrieval_query=retrieval_query,
)

建议检索查询返回节点属性,而不是节点本身。

格式化结果

警告

此 API 目前处于 beta 模式,未来可能会发生变化。

result_formatter 函数自定义 Cypher 检索器的输出,以改进提示词工程和可读性。它将每条 Neo4j 记录转换为具有两个字段的 RetrieverResultItem:contentmetadata

content 字段是一个格式化的字符串,包含旨在提供给语言模型的关键信息,例如电影标题或描述。metadata 字段包含额外详细信息,对于调试或提供额外上下文(如得分或节点属性)非常有用。

def result_formatter(record: neo4j.Record) -> RetrieverResultItem:
    content=f"Movie title: {record.get('movieTitle')}, description: {record.get('movieDescription')}, actors: {record.get('actors')}",
    return RetrieverResultItem(
        metadata={
            "title": record.get('movieTitle'),
            "score": record.get("score"),
        }
    )

retriever = VectorCypherRetriever(
    driver,
    index_name=INDEX_NAME,
    retrieval_query="OPTIONAL MATCH (node)<-[:ACTED_IN]-(p:Person) RETURN node.title as movieTitle, node.plot as movieDescription, collect(p.name) as actors, score",
    result_formatter=result_formatter,
)

另请参阅 VectorCypherRetriever

向量数据库

注意

对于外部检索器,过滤器语法取决于提供商。有关详细信息,请参阅每个提供商的 Python 客户端文档。

Weaviate 检索器

注意

为了导入此检索器,必须安装 Weaviate Python 客户端:pip install “neo4j_graphrag[weaviate]”

from weaviate.connect.helpers import connect_to_local
from neo4j_graphrag.retrievers import WeaviateNeo4jRetriever

client = connect_to_local()
retriever = WeaviateNeo4jRetriever(
    driver=driver,
    client=client,
    embedder=embedder,
    collection="Movies",
    id_property_external="neo4j_id",
    id_property_neo4j="id",
    node_label_neo4j="Document",  # optional
)

在内部,此检索器在 Weaviate 中执行向量搜索,通过将 Weaviate 元数据 id_property_external 与 Neo4j node.id_property_neo4j 匹配来查找相应的节点,并返回匹配的节点。

return_propertiesretrieval_query 参数的操作方式与其他检索器类似。

请参阅 WeaviateNeo4jRetriever

Pinecone 检索器

注意

为了导入此检索器,必须安装 Pinecone Python 客户端:pip install “neo4j_graphrag[pinecone]”

from pinecone import Pinecone
from neo4j_graphrag.retrievers import PineconeNeo4jRetriever

client = Pinecone()  # ... create your Pinecone client

retriever = PineconeNeo4jRetriever(
    driver=driver,
    client=client,
    index_name="Movies",
    id_property_neo4j="id",
    embedder=embedder,
    node_label_neo4j="Document",  # optional
)

另请参阅 PineconeNeo4jRetriever

Qdrant 检索器

注意

为了导入此检索器,必须安装 Qdrant Python 客户端:pip install “neo4j_graphrag[qdrant]”

from qdrant_client import QdrantClient
from neo4j_graphrag.retrievers import QdrantNeo4jRetriever

client = QdrantClient(...)  # construct the Qdrant client instance

retriever = QdrantNeo4jRetriever(
    driver=driver,
    client=client,
    collection_name="my-collection",
    using="my-vector",
    id_property_external="neo4j_id",    # The payload field that contains identifier to a corresponding Neo4j node id property
    id_property_neo4j="id",
    embedder=embedder,
    node_label_neo4j="Document",  # optional
)

请参阅 QdrantNeo4jRetriever

其他检索器

混合检索器

在混合检索器中,结果在向量索引和全文索引中同时搜索。因此,数据库中也必须存在全文索引,并且在实例化检索器时必须提供其名称。

from neo4j_graphrag.retrievers import HybridRetriever

INDEX_NAME = "embedding-name"
FULLTEXT_INDEX_NAME = "fulltext-index-name"

retriever = HybridRetriever(
    driver,
    INDEX_NAME,
    FULLTEXT_INDEX_NAME,
    embedder,
)

请参阅 HybridRetriever

另请注意,有一个用于创建全文索引的辅助函数(请参阅 API 文档)。

混合 Cypher 检索器

在混合 Cypher 检索器中,结果在向量索引和全文索引中同时搜索。一旦识别出相似节点,检索查询就可以遍历图并返回更多上下文。

from neo4j_graphrag.retrievers import HybridCypherRetriever

INDEX_NAME = "embedding-name"
FULLTEXT_INDEX_NAME = "fulltext-index-name"

retriever = HybridCypherRetriever(
    driver,
    INDEX_NAME,
    FULLTEXT_INDEX_NAME,
    retrieval_query="MATCH (node)-[:AUTHORED_BY]->(author:Author) RETURN author.name"
    embedder=embedder,
)

请参阅 HybridCypherRetriever

Text2Cypher 检索器

此检索器首先要求 LLM 生成 Cypher 查询,以从数据库中获取回答问题所需的确切信息。然后执行该查询,并将结果记录添加到上下文中,供 LLM 编写对初始用户问题的答案。Cypher 生成 LLM 和答案生成 LLM 可以是不同的。

from neo4j import GraphDatabase
from neo4j_graphrag.retrievers import Text2CypherRetriever
from neo4j_graphrag.llm import OpenAILLM

URI = "neo4j://:7687"
AUTH = ("neo4j", "password")

# Connect to Neo4j database
driver = GraphDatabase.driver(URI, auth=AUTH)

# Create LLM object
llm = OpenAILLM(model_name="gpt-5")

# (Optional) Specify your own Neo4j schema
neo4j_schema = """
Node properties:
Person {name: STRING, born: INTEGER}
Movie {tagline: STRING, title: STRING, released: INTEGER}
Relationship properties:
ACTED_IN {roles: LIST}
REVIEWED {summary: STRING, rating: INTEGER}
The relationships:
(:Person)-[:ACTED_IN]->(:Movie)
(:Person)-[:DIRECTED]->(:Movie)
(:Person)-[:PRODUCED]->(:Movie)
(:Person)-[:WROTE]->(:Movie)
(:Person)-[:FOLLOWS]->(:Person)
(:Person)-[:REVIEWED]->(:Movie)
"""

# (Optional) Provide user input/query pairs for the LLM to use as examples
examples = [
    "USER INPUT: 'Which actors starred in the Matrix?' QUERY: MATCH (p:Person)-[:ACTED_IN]->(m:Movie) WHERE m.title = 'The Matrix' RETURN p.name"
]

# Initialize the retriever
retriever = Text2CypherRetriever(
    driver=driver,
    llm=llm,  # type: ignore
    neo4j_schema=neo4j_schema,
    examples=examples,
)

# Generate a Cypher query using the LLM, send it to the Neo4j database, and return the results
query_text = "Which movies did Hugo Weaving star in?"
print(retriever.search(query_text=query_text))

警告

使用 OpenAILLM 需要 openai Python 客户端。您可以使用 pip install “neo4j_graphrag[openai]” 安装它。

注意

由于我们不执行任何相似性搜索(向量索引),Text2Cypher 检索器不需要任何嵌入器。

警告

LLM 生成的查询不保证语法正确。如果无法执行,则会引发 Text2CypherRetrievalError

请参阅 Text2CypherRetriever

ToolsRetriever

ToolsRetriever 使用 LLM 根据用户查询智能选择和执行适当的工具。此检索器使用 LLM 分析用户的问题,以确定提供的工具集中的哪些工具对于检索相关信息最有帮助。如果需要,它可以选择多个工具,或者如果没有任何工具适合该查询,则不选择任何工具,然后将执行工具的结果与适当的归因结合起来。当复杂查询可能需要不同类型的信息检索时,这特别有用。

from neo4j import GraphDatabase
from neo4j_graphrag.retrievers import ToolsRetriever, VectorRetriever, Text2CypherRetriever
from neo4j_graphrag.llm import OpenAILLM
from neo4j_graphrag.embeddings import OpenAIEmbeddings

URI = "neo4j://:7687"
AUTH = ("neo4j", "password")

# Connect to Neo4j database
driver = GraphDatabase.driver(URI, auth=AUTH)

# Create LLM object
llm = OpenAILLM(model_name="gpt-5")

# Create embedder
embedder = OpenAIEmbeddings(model="text-embedding-3-large")

# Create individual retrievers to use as tools
vector_retriever = VectorRetriever(
    driver=driver,
    index_name="embedding-index",
    embedder=embedder,
)

text2cypher_retriever = Text2CypherRetriever(
    driver=driver,
    llm=llm,
)

# Convert retrievers to tools
vector_tool = vector_retriever.convert_to_tool(
    name="vector_search",
    description="Search for similar documents using vector similarity",
)

cypher_tool = text2cypher_retriever.convert_to_tool(
    name="cypher_search",
    description="Generate and execute Cypher queries for structured data retrieval",
)

# Initialize ToolsRetriever with the tools
tools_retriever = ToolsRetriever(
    driver=driver,
    llm=llm,
    tools=[vector_tool, cypher_tool],
)

# Use the retriever - the LLM will automatically select appropriate tools
result = tools_retriever.search("What movies did Tom Hanks act in and what are their plots?")
工具创建模式

ToolsRetriever 支持两种主要的工具创建方法:

1. 将检索器转换为工具

任何检索器都可以使用 convert_to_tool() 方法转换为工具:

# Convert retriever with custom parameter descriptions
tool = retriever.convert_to_tool(
    name="search_tool",
    description="Custom tool description",
    parameter_descriptions={
        "query_text": "Search query for finding relevant information",
        "top_k": "Maximum number of results to return",
    }
)

convert_to_tool() 方法会自动从检索器的 get_search_results() 方法签名中推断参数,将 Python 类型映射到工具参数类型(str → StringParameter,int → IntegerParameter 等)。

2. 创建自定义工具

通过从 Tool 类继承来创建自定义工具:

from neo4j_graphrag.tool import Tool, ObjectParameter, StringParameter

class CustomTool(Tool):
    def __init__(self):
        parameters = ObjectParameter(
            description="Parameters for custom tool",
            properties={
                "input": StringParameter(
                    description="Input parameter description",
                ),
            },
            required_properties=["input"],
        )

        super().__init__(
            name="custom_tool",
            description="Tool description for LLM selection",
            parameters=parameters,
            execute_func=self.execute_custom_logic,
        )

    def execute_custom_logic(self, **kwargs):
        # Custom implementation
        return f"Processed: {kwargs.get('input')}"

工具配置

参数类型和验证

工具支持具有自动验证功能的各种参数类型:

from neo4j_graphrag.tool import (
    ObjectParameter, StringParameter, IntegerParameter,
    NumberParameter, BooleanParameter, ArrayParameter
)

parameters = ObjectParameter(
    properties={
        "text": StringParameter(description="Text input"),
        "count": IntegerParameter(description="Count", minimum=1, maximum=100),
        "threshold": NumberParameter(description="Threshold", minimum=0.0, maximum=1.0),
        "enabled": BooleanParameter(description="Enable feature"),
        "items": ArrayParameter(
            description="List of items",
            items=StringParameter(description="String item")
        ),
    },
    required_properties=["text", "count"]
)

系统指令自定义

通过提供自定义系统指令来自定义 LLM 如何选择工具:

custom_instruction = """
You are a specialized assistant for movie database queries.
Select tools based on query type: use vector_search for plot similarity,
cypher_search for specific actor/director queries, and both for complex requests.
"""

tools_retriever = ToolsRetriever(
    driver=driver,
    llm=llm,
    tools=[vector_tool, cypher_tool],
    system_instruction=custom_instruction,
)

系统指令指导 LLM 的工具选择逻辑,并可根据您的特定领域或用例进行量身定制。

错误处理模式

工具应针对常见的故障场景实现适当的错误处理:

def execute_custom_logic(self, **kwargs):
    try:
        # Tool parameter validation
        required_param = kwargs.get('required_param')
        if not required_param:
            raise ValueError("Required parameter 'required_param' is missing")

        # Tool execution logic
        result = perform_operation(required_param)
        return result

    except ValueError as e:
        # Parameter validation errors
        return f"Parameter error: {str(e)}"
    except Exception as e:
        # Tool execution errors
        return f"Execution error: {str(e)}"

ToolsRetriever 在内部处理 LLM 选择错误,并且在工具无法成功执行时将重试工具选择或返回适当的错误消息。

与 GraphRAG 集成

ToolsRetriever 与 GraphRAG 管道无缝集成,用于自动问答:

from neo4j import GraphDatabase
from neo4j_graphrag.retrievers import ToolsRetriever, VectorRetriever, Text2CypherRetriever
from neo4j_graphrag.llm import OpenAILLM
from neo4j_graphrag.embeddings import OpenAIEmbeddings
from neo4j_graphrag.generation import GraphRAG

URI = "neo4j://:7687"
AUTH = ("neo4j", "password")

# Connect to Neo4j database
driver = GraphDatabase.driver(URI, auth=AUTH)

# Create LLM and embedder
llm = OpenAILLM(model_name="gpt-5", model_params={"temperature": 0})
embedder = OpenAIEmbeddings(model="text-embedding-3-large")

# Create retrievers to use as tools
vector_retriever = VectorRetriever(
    driver=driver,
    index_name="vector-index",
    embedder=embedder,
)

text2cypher_retriever = Text2CypherRetriever(
    driver=driver,
    llm=llm,
)

# Convert to tools
vector_tool = vector_retriever.convert_to_tool(
    name="vector_search",
    description="Search for similar documents using vector similarity",
)

cypher_tool = text2cypher_retriever.convert_to_tool(
    name="cypher_search",
    description="Generate and execute Cypher queries for structured data retrieval",
)

# Initialize ToolsRetriever
tools_retriever = ToolsRetriever(
    driver=driver,
    llm=llm,
    tools=[vector_tool, cypher_tool],
)

# Initialize GraphRAG pipeline with ToolsRetriever
rag = GraphRAG(retriever=tools_retriever, llm=llm)

# Query the pipeline - the LLM will automatically select appropriate tools
query_text = "What movies did Tom Hanks act in and what are their plots?"
response = rag.search(query_text=query_text, retriever_config={"top_k": 5})
print(response.answer)

警告

ToolsRetriever 需要 LLM 实例才能工作。使用 OpenAI 等 LLM 提供商需要安装其各自的 Python 包:pip install “neo4j_graphrag[openai]”

请参阅 ToolsRetriever

自定义检索器

如果应用程序需要非常特定的检索策略,则可以使用 Retriever 接口实现自定义检索器:

from neo4j_graphrag.retrievers.base import Retriever

class MyCustomRetriever(Retriever):
    def __init__(
        self,
        driver: neo4j.Driver,
        # any other required parameters
    ) -> None:
        super().__init__(driver)

    def get_search_results(
        self,
        query_vector: Optional[list[float]] = None,
        query_text: Optional[str] = None,
        top_k: int = 5,
        filters: Optional[dict[str, Any]] = None,
    ) -> RawSearchResult:
        pass

有关返回类型的描述,请参阅 RawSearchResult

GraphRAG 搜索选项

返回上下文

默认情况下,search 方法仅返回最终答案。可以通过设置 return_context=True 来查看作为上下文的一部分检索到的内容:

rag.search("my question", return_context=True)

如果上下文为空,则返回自定义消息

如果检索器无法找到任何上下文,LLM 仍然会返回一个答案。如果上下文为空,则可以跳过 LLM 调用,并返回用户定义的消息:

rag.search(
    "my question",
    response_fallback="I can not answer this question because I have no relevant context."
)

将配置传递给检索器搜索方法

检索器搜索方法有一堆配置选项(见上文),也可以通过使用 retriever_config 参数的 GraphRAG 搜索方法进行配置。例如,以下代码片段说明了如何为检索器定义 top_k 参数:

rag.search(
    "my question",
    retriever_config={"top_k": 2}
)

数据库操作

请参阅 数据库交互

创建向量索引

from neo4j import GraphDatabase
from neo4j_graphrag.indexes import create_vector_index

URI = "neo4j://:7687"
AUTH = ("neo4j", "password")

INDEX_NAME = "chunk-index"
DIMENSION=1536

# Connect to Neo4j database
driver = GraphDatabase.driver(URI, auth=AUTH)

# Creating the index
create_vector_index(
    driver,
    INDEX_NAME,
    label="Document",
    embedding_property="vectorProperty",
    dimensions=DIMENSION,
    similarity_fn="euclidean",
)

填充向量索引

from random import random

from neo4j import GraphDatabase
from neo4j_graphrag.indexes import upsert_vectors
from neo4j_graphrag.types import EntityType

URI = "neo4j://:7687"
AUTH = ("neo4j", "password")

# Connect to Neo4j database
driver = GraphDatabase.driver(URI, auth=AUTH)

# Upsert the vector
DIMENSION = 1536
vector = [random() for _ in range(DIMENSION)]
upsert_vectors(
    driver,
    ids=["1234"],
    embedding_property="vectorProperty",
    embeddings=[vector],
    entity_type=EntityType.NODE,
)

这将更新 id(node)=1234 的节点以添加(或更新)node.vectorProperty 属性。此属性也将添加到向量索引中。

删除向量索引

警告

此操作是不可逆的,应谨慎使用。

from neo4j import GraphDatabase

URI = "neo4j://:7687"
AUTH = ("neo4j", "password")

# Connect to Neo4j database
driver = GraphDatabase.driver(URI, auth=AUTH)
drop_index_if_exists(driver, INDEX_NAME)

© . This site is unofficial and not affiliated with Neo4j, Inc.