mcpField
N
neo4j-graphrag-skill

neo4j-graphrag-skill

github.com/neo4j-contribデータ・データベース1181.1k 回インストール1 週間前に更新
リポジトリ

neo4j-graphrag-skill について

neo4j-graphrag-skillは、neo4j-graphrag Pythonパッケージを使ったNeo4j GraphRAG検索パイプラインの構築を支援します。リトリーバーの選択、Cypherによるグラフ拡張、LLM連携、検索の問題解決を扱います。

主な機能

  1. 01ベクトル・ハイブリッド・Cypherリトリーバーの選択
  2. 02GraphRAGとLLMの構成
  3. 03検索用Cypherフラグメントの作成
  4. 04複数リトリーバーへのクエリ振り分け
  5. 05ベクトル・全文検索インデックスの設定

活用シーン

  1. 01Neo4j GraphRAG検索パイプラインの構築
  2. 02グラフ走査の要件に応じたリトリーバー選択
  3. 03検索品質の問題の調査
  4. 04自然言語によるNeo4jグラフ検索

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/neo4j-contrib/neo4j-skills --skill neo4j-graphrag-skill

インストール後、Claude Code で/neo4j-graphrag-skillを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

README.md
references/
kg-builder.md
knowledge-graph-construction.md
pipeline-dsl.md
providers.md
retrievers.md

詳細

Neo4j GraphRAG スキル

使用する場合

  • neo4j-graphrag Python パッケージで GraphRAG 検索パイプラインを構築する
  • VectorRetriever、HybridRetriever、VectorCypherRetriever、HybridCypherRetriever のいずれかを選ぶ
  • グラフで拡張したコンテキストを取得するための retrieval_query Cypher フラグメントを記述する
  • リトリーバーと LLM を GraphRAG パイプラインに接続する
  • ToolsRetriever で LLM が振り分けるマルチリトリーバーを使用する
  • 検索品質が低い場合の問題をデバッグする
  • Neo4j を LangChain、LlamaIndex、または Haystack と統合する

使用しない場合

  • ドキュメントからの KG 構築 → neo4j-document-import-skill
  • グラフ走査を伴わない単純なベクトル/セマンティック検索 → neo4j-vector-index-skill
  • ベクトル検索と全文検索、またはその他のランキング済みソースを組み合わせるハイブリッド検索 → neo4j-vector-index-skill
  • GDS アルゴリズム(PageRank、Louvain、ノード埋め込み) → neo4j-gds-skill
  • エージェントの長期メモリ → neo4j-agent-memory-skill
  • 生の Cypher クエリの記述 → neo4j-cypher-skill

リトリーバーの選択

Has fulltext index?
  YES → Hybrid variants (HybridRetriever / HybridCypherRetriever)
  NO  → Vector variants (VectorRetriever / VectorCypherRetriever)

Need graph traversal after vector lookup?
  YES → Cypher variants (VectorCypherRetriever / HybridCypherRetriever)
  NO  → plain variants

Natural-language-to-Cypher?        → Text2CypherRetriever (no embedder needed)
LLM should route between retrievers? → ToolsRetriever
Vectors stored in external DB?      → WeaviateNeo4jRetriever / PineconeNeo4jRetriever / QdrantNeo4jRetriever
リトリーバーベクトル全文検索グラフ最適な用途
VectorRetriever✓——ベースラインとなるセマンティック検索
HybridRetriever✓✓—グラフ拡張を伴わない、より高い再現率
VectorCypherRetriever✓—✓全文検索を使わない GraphRAG
HybridCypherRetriever✓✓✓本番環境の GraphRAG — デフォルト
Text2CypherRetriever——✓NL→Cypher、埋め込みモデル不要
ToolsRetrieverさまざまさまざまさまざまLLM が振り分けるマルチリトリーバー
WeaviateNeo4jRetriever✓—✓Weaviate 内のベクトル
PineconeNeo4jRetriever✓—✓Pinecone 内のベクトル
QdrantNeo4jRetriever✓—✓Qdrant 内のベクトル

インストール

pip install neo4j-graphrag[openai]        # OpenAI LLM + embeddings
pip install neo4j-graphrag[anthropic]     # Anthropic Claude
pip install neo4j-graphrag[google]        # Vertex AI / Gemini
pip install neo4j-graphrag[bedrock]       # Amazon Bedrock (boto3)
pip install neo4j-graphrag[cohere]        # Cohere
pip install neo4j-graphrag[mistralai]     # MistralAI
pip install neo4j-graphrag[ollama]        # Ollama (local)
pip install neo4j-graphrag[weaviate]      # Weaviate external retriever
pip install neo4j-graphrag[pinecone]      # Pinecone external retriever
pip install neo4j-graphrag[qdrant]        # Qdrant external retriever

必要条件:Python >= 3.10、neo4j >= 5.17.0(ドライバー 6.x に対応)。


ステップ 2 — リトリーバーを選ぶ

上記のリトリーバーの選択表から選んでください。

neo4j-graphrag のリトリーバー API を使わずにカスタム Cypher ハイブリッド検索を行う場合は、neo4j-vector-index-skill を使用してください。

ベクトルバックエンドの選択 [v1.16+, 自動]:Neo4j 2026.01+ では、フィルターが SEARCH に対応しており(単純な AND 比較)、すべてのフィルタープロパティがインデックスの WITH [n.prop] リストで宣言されている場合、4 種類すべてのベクトル/ハイブリッドリトリーバーが Cypher 25 の SEARCH ... WHERE 句を経由するよう自動的にルーティングされます。$or、$in、$like、または宣言されていないプロパティを使う場合は、db.index.vector.queryNodes() プロシージャのパスに自動的にフォールバックします(警告ログが記録されます)。create_vector_index() の filterable_properties=[...] でフィルター可能なプロパティを宣言してください。


ステップ 3 — インデックスを作成する(一度だけ実行)

// Vector index (all retrievers need this)
CREATE VECTOR INDEX chunk_embedding IF NOT EXISTS
FOR (c:Chunk) ON (c.embedding)
OPTIONS { indexConfig: {
  `vector.dimensions`: 1536,
  `vector.similarity_function`: 'cosine'
} };

// Fulltext index (Hybrid retrievers only)
CREATE FULLTEXT INDEX chunk_fulltext IF NOT EXISTS
FOR (c:Chunk) ON EACH [c.text];

// Confirm ONLINE before ingesting:
SHOW INDEXES YIELD name, state
WHERE name IN ['chunk_embedding', 'chunk_fulltext']
RETURN name, state;
// Both must show state = 'ONLINE'

インデックスが ONLINE でない場合は、待機して 5 秒ごとに確認してください。ONLINE になるまで取り込みを開始しないでください。


ステップ 4 — 基本パターン(HybridCypherRetriever)

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

driver = GraphDatabase.driver(NEO4J_URI, auth=(NEO4J_USERNAME, NEO4J_PASSWORD))
embedder = OpenAIEmbeddings(model="text-embedding-3-large")  # OPENAI_API_KEY from env

# retrieval_query: Cypher fragment executed after the vector/fulltext lookup.
# Auto-injected variables:  node  (matched node)   score  (similarity float)
# MUST include a RETURN clause.  score must appear in RETURN.
retrieval_query = """
MATCH (node)<-[:HAS_CHUNK]-(article:Article)
OPTIONAL MATCH (article)-[:MENTIONS]->(org:Organization)
RETURN node.text AS chunk_text,
       article.title AS article_title,
       collect(DISTINCT org.name) AS mentioned_organizations,
       score
"""

retriever = HybridCypherRetriever(
    driver=driver,
    vector_index_name="chunk_embedding",
    fulltext_index_name="chunk_fulltext",
    retrieval_query=retrieval_query,
    embedder=embedder,
)

llm = OpenAILLM(model_name="gpt-4.1", model_params={"temperature": 0})

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

response = rag.search(
    query_text="Who does Alice work for?",
    retriever_config={"top_k": 5},
)
print(response.answer)
driver.close()

VectorCypherRetriever

from neo4j_graphrag.retrievers import VectorCypherRetriever

retriever = VectorCypherRetriever(
    driver=driver,
    index_name="chunk_embedding",
    retrieval_query=retrieval_query,
    embedder=embedder,
)

response = rag.search(
    query_text="What happened at Apple?",
    retriever_config={"top_k": 10},
)

Text2CypherRetriever

LLM を使って自然言語を Cypher に変換します。埋め込みモデルは不要です。

セキュリティ(v1.16.0+): LLM が生成した Cypher はすべて、最初に EXPLAIN を通して実行されます。 書き込み/破壊的操作に分類された文は実行されず、代わりに Text2CypherRetrievalError が発生します。 これにより、プロンプトインジェクション攻撃を防ぎます。

from neo4j_graphrag.retrievers import Text2CypherRetriever

retriever = Text2CypherRetriever(
    driver=driver,
    llm=OpenAILLM(model_name="gpt-4.1"),
    neo4j_schema=None,       # None = auto-fetch schema from DB; pass string to trim
    examples=[
        "Q: Who works at Neo4j? A: MATCH (p:Person)-[:WORKS_AT]->(c:Company {name:'Neo4j'}) RETURN p.name"
    ],
)
results = retriever.search(query_text="Which people work at Neo4j?")

ToolsRetriever(LLM が振り分けるマルチリトリーバー)

from neo4j_graphrag.retrievers import ToolsRetriever

tools_retriever = ToolsRetriever(
    llm=llm,
    retrievers=[vector_retriever, text2cypher_retriever],
)
# LLM decides which retriever(s) to invoke per query

# Convert any retriever to a standalone Tool:
tool = vector_retriever.convert_to_tool()

フィルター(ベクトル検索前の事前フィルタリング)

results = retriever.search(
    query_text="quarterly earnings",
    top_k=5,
    filters={
        "date": {"$gte": "2024-01-01"},
        "source": {"$eq": "10-K"},
    },
)
# Operators: $eq  $ne  $lt  $lte  $gt  $gte  $between  $in  $like  $ilike

query_params(パラメーター化された retrieval_query)

retrieval_query = """
MATCH (node)<-[:HAS_CHUNK]-(a:Article)-[:MENTIONS]->(org:Organization {name: $entity_name})
RETURN node.text, a.title, score
"""

# Pass via retriever.search directly:
results = retriever.search(
    query_text="What happened at Apple?",
    top_k=10,
    query_params={"entity_name": "Apple"},
)

# Or via GraphRAG.search:
response = rag.search(
    query_text="What happened at Apple?",
    retriever_config={"top_k": 10, "query_params": {"entity_name": "Apple"}},
)

Cypher 25 SEARCH 句(v1.16.0、Neo4j 2026.x+)

# Enable SEARCH clause syntax in vector/hybrid retrievers (requires Neo4j 2026+)
retriever = VectorRetriever(
    driver=driver,
    index_name="chunk_embedding",
    embedder=embedder,
    use_search_clause=True,
)

v1.19 以降、ベクトルリトリーバーとベクトル Cypher リトリーバーは、SEARCH クエリに自動的に CYPHER 25 を付加し、SEARCH がサポートされていない場合、または失敗した場合は、プロシージャベースのベクトル検索にフォールバックします。


コンポーネントのインポート(v1.19 — 破壊的変更、2.0 に向けた準備)

すべてのコンポーネントが experimental 名前空間の外に移動しました。古いインポートも引き続き機能しますが、DeprecationWarning が発生し、2.0 で削除されます。

# v1.19+ — preferred
from neo4j_graphrag.components.text_splitters.fixed_size_splitter import FixedSizeSplitter

# deprecated (removed in 2.0)
from neo4j_graphrag.experimental.components.text_splitters.fixed_size_splitter import FixedSizeSplitter

# SimpleKGPipeline did NOT move — only valid path:
from neo4j_graphrag.experimental.pipeline.kg_builder import SimpleKGPipeline

neo4j_graphrag.pipeline(v1.21 以降)は新しい遅延評価型データフロー DSL(Pipeline、LocalInterpreter、Sink)です。SimpleKGPipeline が使用する実験的なタスクグラフの Pipeline とは無関係です。neo4j_graphrag.pipeline.kg_builder は存在しないため、ModuleNotFoundError が発生します。

また v1.19 以降、Component/RunContext/TaskProgressNotifierProtocol は neo4j_graphrag.components.base にあります。また、不正なコンポーネントを指定すると PipelineDefinitionError ではなく ComponentDefinitionError が発生します。


データフローパイプライン DSL とオブザーバー(v1.21)

遅延評価型の neo4j_graphrag.pipeline.Pipeline と LocalInterpreter(observers=[...])、および TextSplitter.iter_chunks() を使用します。API の詳細 → references/pipeline-dsl.md。


Cypher リトリーバーでの ORDER BY(v1.16.0)

results = retriever.search(
    query_text="...",
    top_k=10,
    order_by="score DESC",
)

neo4j_schema=None の場合、リトリーバーがスキーマを自動で取得します。大規模なスキーマの場合は、LLM のプロンプトサイズを抑えるため、短縮した文字列を渡してください。

破壊的クエリのガード[v1.16 以降]:Text2CypherRetriever は、生成された Cypher を実行前に EXPLAIN で検証し、書き込みを行うクエリ(CREATE、MERGE、DELETE、SET、REMOVE など)を拒否します。LLM が生成した書き込みクエリがグラフに対して実行されることはありません。


カスタムプロンプトテンプレート

from neo4j_graphrag.generation.prompts import RagTemplate

template = RagTemplate(
    template="""Answer using ONLY the context below.
Context: {context}
Question: {query_text}
Answer:""",
    expected_inputs=["context", "query_text"],
)

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

return_context と response_fallback

response = rag.search(
    query_text="...",
    retriever_config={"top_k": 5},
    return_context=True,                        # include raw retrieved chunks
    response_fallback="No relevant context.",   # skip LLM call if retriever returns nothing
)
print(response.answer)
print(response.retriever_result)    # RawSearchResult when return_context=True

メッセージ履歴(複数ターン)

from neo4j_graphrag.message_history import InMemoryMessageHistory

history = InMemoryMessageHistory()
r1 = rag.search(query_text="Who is Alice?", message_history=history)
r2 = rag.search(query_text="Where does she work?", message_history=history)

外部リトリーバー、LLM とエンベッダープロバイダー

  • Weaviate/Pinecone/Qdrant のコンストラクター → references/retrievers.md
  • LLM クラス(OpenAILLM、AnthropicLLM、GeminiLLM、VertexAILLM、BedrockLLM、…)、base_url、トークン使用量、close();エンベッダークラスと次元数 → references/providers.md

インデックスのセットアップ

from neo4j_graphrag.indexes import create_vector_index

# Vector index — adjust dimensions to match your embedding model
create_vector_index(
    driver,
    name="chunk_embedding",
    label="Chunk",
    embedding_property="embedding",
    dimensions=1536,
    similarity_fn="cosine",       # or "euclidean"
)

# Fulltext index (run as Cypher)
# CREATE FULLTEXT INDEX chunk_fulltext IF NOT EXISTS
#   FOR (c:Chunk) ON EACH [c.text]

スキーマの検査

from neo4j_graphrag.schema import get_schema, get_structured_schema

schema_str = get_schema(driver, sample=1000)           # human-readable string
schema_dict = get_structured_schema(driver, sample=1000)  # dict with labels/rels/props

よくあるエラー

エラー原因対処法
ModuleNotFoundError: neo4j_genai古いパッケージ名pip uninstall neo4j-genai && pip install neo4j-graphrag
retrieval_query が 0 行を返すMATCH がない、またはリレーションの方向が誤っているフラグメントに EXPLAIN を実行し、CALL db.schema.visualization() を確認する
結果で KeyError: 'score' が発生するretrieval_query の RETURN に score がないすべての retrieval_query の RETURN 句に score を追加する
score 変数が見つからないretrieval_query で score を再宣言しているscore を再宣言しないでください。自動的に挿入されます
Text2CypherRetrievalErrorLLM が書き込みステートメントを生成した仕様どおりのセキュリティ動作です(v1.16.0 以降)。プロンプトまたはスキーマを見直してください
TypeError: coroutineawait/asyncio.run() がない非同期呼び出しを asyncio.run(pipeline.run_async(...)) で囲む
HybridRetriever の結果が空全文検索インデックスが ONLINE ではないSHOW INDEXES YIELD name, state WHERE state <> 'ONLINE'
VectorCypherRetriever と filters の併用で「requires: node_label, embedding_node_property, …」が発生する(v1.19 の名前不一致バグ)_fetch_index_infos は self._embedding_node_property を設定する一方、コンストラクターは _node_embedding_property を設定する構築後にシムを適用する:r._node_embedding_property = r._embedding_node_property or "embedding";フィルタープロパティを r._filterable_properties に追加する
エンベッダーの次元数の不一致インデックスの次元数とモデルの次元数が異なる正しい dimensions= 値でインデックスを再作成する

検証チェックリスト

  • neo4j-genai ではなく neo4j-graphrag がインストールされていること。ドライバーは neo4j >= 5.17.0 であること
  • 埋め込みの取り込みまたはリトリーバーの実行前に、ベクトルインデックスが ONLINE であること
  • Hybrid バリアントを使用する場合、全文検索インデックスが ONLINE であること
  • create_vector_index の埋め込み次元が、エンベッダーの出力と一致していること
  • retrieval_query の RETURN で node と score を返していること(再宣言していないこと)
  • query_params はリトリーバーのコンストラクターではなく、rag.search() の retriever_config 経由で渡すこと
  • API キーは環境変数に設定し、ハードコードしないこと
  • リソースを解放するため、処理が終わったら llm.close() を呼び出すこと

参考資料

必要に応じて読み込んでください:

コメント