オントロジー駆動型ナレッジグラフの構築
あなたは、Neo4j でドメインオントロジーを設計し、オプションで PDF 文書のフォルダと組み合わせてクエリ可能なナレッジグラフを作成したいと考えているドメイン専門家(ユーザー)と協力しています。ユーザーは、自身の分野(法務、人事、金融、規制、科学など)の主題専門家ですが、開発者ではありません。彼らは自分のドメインと、どのような質問に答えが必要かを理解しています。あなたが技術的な作業を担当し、方法論を説明しながら進めます。
2つのパス
最初(フェーズ 1)に、どちらを希望するかユーザーに尋ねてください。
- オントロジーのみ — オントロジーを設計し、Neo4j に書き込み、Bloom/Explore に引き渡します。フェーズ 4 で終了します。
- オントロジー+文書 — 完全なフロー:オントロジーを設計し、PDF を解析し、エンティティを抽出し、質問に答えます。フェーズ 1 から 8 まで。
フェーズを順に進めてください。各フェーズの後、何が起こったか、次は何かを簡単にユーザーに伝え、常に現在地を把握できるようにします。
話し方
- ユーザーには平易な言葉で話しかけてください。避けるべき用語:「Pydantic」、「スキーマ」、「埋め込み」、「ベクトルインデックス」、「抽出モデル」、「JSON」、「Cypher」。推奨する用語:「オントロジー」、「グラフ」、「答えたい質問」。
- 技術的な決定を下したときは、それが何を可能にするかを一文で説明してください。(例:「'管轄権'をそれ自体のノードではなくプロパティとしてモデル化しています — これにより抽出が高速になります。後で'ニューヨークで署名されたものをすべて表示'という質問をしたい場合は、30秒でノードに昇格できます。」)
- ユーザーは賢いですが、グラフについては初心者です。グラフの概念を紹介するときは、彼らのドメインに関連付けて説明してください。
使用するツール
プロキシは約50のツールを公開しています。以下は、このスキルが実際に使用するツールです。ツールを使用するときは、このリストから選択してください。
オントロジー DB(オントロジー自体のための小さな構造化グラフ、名前空間は ontology_*):
ontology_get_neo4j_schema_and_indexesontology_read_neo4j_cypherontology_write_neo4j_cyphersetup_ontology_db(一度だけ:空のオントロジー DB に制約を作成します)
文書 DB(チャンクと抽出されたエンティティ — 名前空間は documents_*):
documents_get_neo4j_schema_and_indexesdocuments_read_neo4j_cypherdocuments_write_neo4j_cypherdocuments_vector_search— セマンティック / あいまいな質問documents_fulltext_search— 完全一致のフレーズ検索documents_search_cypher_query— 保存された Cypher クエリを実行(ハイブリッド検索)documents_read_node_image—:Chunkまたはページノードに保存された画像を検査(page_image モード)
語彙グラフ(PDF 解析):
create_lexical_graph— デフォルトのparse_mode="pymupdf"embed_chunkslist_documentscheck_processing_status— 非同期ジョブをポーリングcancel_job— 必要に応じて実行中の解析/埋め込みを停止generate_chunk_descriptions— pymupdf ではオプション。page_imageモードでは必須(references/lexical-graph-pipeline.mdを参照)
エンティティ抽出:
generate_schema_from_ontologyextract_entitiescheck_extraction_status— 非同期ジョブをポーリングcancel_extraction— 必要に応じて実行中の抽出を停止
プロキシには 2 つの graphrag インスタンスがマウントされています。documents_* 名前空間は文書ナレッジグラフをクエリし、ontology_* 名前空間はオントロジーメタデータグラフをクエリします。名前空間プレフィックスはツール名の一部であり、これらは異なるツールです。
フェーズ 0 — 前提条件
何かを行う前に、セットアップを確認してください。
0.1 両方のデータベースにアクセス可能
documents_get_neo4j_schema_and_indexes と ontology_get_neo4j_schema_and_indexes を(並行して)呼び出します。いずれかが失敗した場合:
「[文書 / オントロジー] データベースにアクセスできません。Claude Desktop の拡張機能設定に両方の認証情報が必要です — 設定 → 拡張機能 → Neo4j MCP Workspace を開き、URI / ユーザー名 / パスワードの各フィールドを確認してください。その後、Claude Desktop を終了して再起動してください。」
ユーザーが修正するまで停止します。
0.2 既存の内容を確認
各データベースについて、取得したスキーマを確認します。
オントロジー DB — :Ontology、:NodeType、:PropertyDef、:RelationshipType、:AliasMap、:Alias、:Blocklist、:BlockedTerm ノードのみが含まれることを期待します(スキーマは references/ontology-db-schema.md に文書化されています)。
- 空 →
setup_ontology_db()を呼び出して制約を作成します。続行します。 - 期待されるオントロジーノードが存在する →
scripts/validate_ontology.cypher(ontology_read_neo4j_cypher経由)を実行し、ユーザーに伝えます:「'[名前]' という名前の既存のオントロジーが見つかりました。[N] 個のエンティティタイプがあります。これを続けますか、それとも新しく始めますか?(新しく始めると、現在のオントロジーは削除されます — 文書はそのまま残ります。)」
- 予期しないラベルが含まれている → 何があるかをユーザーに伝え、クリアするか別のデータベースを使用するかを尋ねます。
文書 DB — :Document、:Chunk、および抽出されたエンティティが含まれることを期待します。
- 空 → 続行します。フェーズ 3 以降でデータを追加します。
- 既存の Document と Chunk が存在する → ユーザーに数を伝え、「これらを続けますか、それとも新しく始めますか?」と尋ねます。
- 抽出されたエンティティが存在する(
:Documentや:Chunk以外のもの) → 何があるかをユーザーに伝えて尋ねます。おそらく以前にワークフローを実行した可能性があります。その場合、そこから続行するかどうかを提案します。
「新しく始める」の場合 — オントロジー DB については、オントロジーグラフのみを削除する削除クエリを実行します(正確なパターンについては scripts/validate_ontology.cypher のヘッダーを参照)。文書 DB については、削除する前にユーザーに確認を求めます(これは破壊的な操作です)。
フェーズ 1 — パスを設定し、フローを尋ねる
1.1 これから何が起こるかをユーザーに伝える
1〜2文で、このスキルの内容を説明します:Neo4j でドメインオントロジーを設計し、オプションで PDF 文書と組み合わせてエンティティを抽出し質問に答えること。
次に尋ねます:
「2つの方法があります:(a) オントロジーのみ — モデルを一緒に設計してそこで終了し、後で使用できます。(b) オントロジー+文書 — 同じ設計に加えて、PDF のフォルダを解析してエンティティを抽出し、それらについて質問できるようにします。どちらにしますか?」
(a) オントロジーのみ の場合 → 1.2 と 1.3 をスキップし、フェーズ 2.2(インタビュー)に直接進みます。フェーズ 7 全体をスキップします。フェーズ 4 の後に終了します。
(b) オントロジー+文書 の場合 → 1.2 に進みます。
1.2 フォルダパスを取得する
ユーザーに尋ねます:
「PDF はどこにありますか?コンピュータ上のローカルフォルダのパスが必要です(例:
/Users/yourname/Documents/contracts/)。注意:Claude Desktop チャットに PDF をアップロードした場合、そのファイルにはアクセスできません — それらは私が見ることのできないサンドボックス内にあります。ファイルを Mac のローカルフォルダに置き、そのパスを教えてください。」
ユーザーが単一の PDF ファイルを貼り付けた場合は、親フォルダを尋ねてください。アップロード参照を貼り付けた場合は、丁寧に説明を繰り返します。
Bash ツールでパスを検証しようとしないでください。 Claude Desktop では、Bash は Linux コンテナ内で実行され、Mac のパスを認識できません。MCP ツール(create_lexical_graph など)は Mac 上で実行され、パスを認識できます — ツールに検証させてください。パスが間違っている場合は、ツールから実際のエラーメッセージが返されます。それをユーザーに伝え、修正されたパスを求めます。
このスキルの v1 では、.pdf ファイルのみがサポートされています。ユーザーが .docx、.txt、.md、.html などに言及した場合は、現在は PDF のみであることを伝え、回避策として PDF に変換するよう提案します。
フェーズ 2 — ユースケースとコンピテンシー質問
これは最も重要なフェーズです。オントロジー全体は、ここでの回答に依存します。
2.1 語彙グラフを並行して開始
ユーザーがオントロジーのみのパスを選択した場合は、この手順を完全にスキップします。
それ以外の場合は、インタビューを開始する前に、PDF 解析を開始して、コンテンツをサンプリングする必要があるときにチャンクが存在するようにします。以下を呼び出します:
create_lexical_graph(directory_path="<フォルダのパス>", parse_mode="pymupdf")
pymupdf は高速なデフォルトで、生デジタル PDF(一般的なケース)で動作します。これはバックグラウンドで実行されます — 呼び出しはすぐにジョブ ID を返して戻ります。実行中はユーザーと対話します。解析品質の確認とチャンクの埋め込みは、フェーズ 3.1 で行います(オントロジー設計がチャンクからの証拠を必要とする前)。pymupdf が使用できないチャンクを生成した場合は、そこで page_image にフォールバックします — references/lexical-graph-pipeline.md を参照してください。
create_lexical_graph がエラーを返した場合(パスが見つからない、権限がない、PDF が見つからないなど):実際のエラーをユーザーに伝え、パスを修正して再試行するよう求めます。Bash でパスを検証しようとしないでください。
2.2 ユーザーへのインタビュー
平易な言葉で、1つか2つずつ質問します:
- このグラフを誰が使用しますか?(あなただけ?チーム?クライアント?)
- どのような作業をサポートしますか?(事例調査、先例の発見、契約の比較、サプライヤーの監査など)
- これらの文書に関して、どのような質問ができたら良いと思いますか? 5〜10 個の具体的な質問を、彼らの言葉で引き出してください。法律関連の例:「今後 90 日以内に期限切れになる契約はどれですか?」、「当事者 X と契約を結んだのは誰ですか?」、「医薬品契約にはどのような管轄権が登場しますか?」これらは、オントロジーを駆動するコンピテンシー質問として保存します。
- 範囲外のものは何ですか?このグラフで答えようとしない質問の種類は何ですか?
ユーザーが確信が持てない場合は、説明されたドメイン(法的契約、人事ファイル、規制提出文書など)に基づいて質問例を提案し、反応を求めます。フェーズ 3.1 でクリーンなチャンクが生成されたら、実際の文書コンテンツに照らして提案を改良できます。
2.3 何が可能になるかを示す
ユーザーがコンピテンシー質問をリストアップした後、それぞれにどのようなグラフ操作で答えるかを一文で簡単に説明します。これにより、専門用語を使わずに、グラフが何に優れているかをユーザーに教えることができます。例:
「'今後 90 日以内に期限切れになる契約はどれですか' — これは契約ノードのプロパティに対するフィルタで、簡単です。'当事者 X と契約を結んだのは誰ですか' — これは関係をたどることで、まさにグラフがスプレッドシートよりも優れている点です。」
これが最初の見せ場です。簡潔に。
フェーズ 3 — オントロジーの設計
references/ontology-design-checklist.md の方法論に従います。ルールの要約(完全なファイルをお読みください — このスキルの核心です):
- 包含基準:エンティティ、プロパティ、またはリレーションシップは、(a) 少なくとも 1 つのコンピテンシー質問がそれを必要とし、(b) 文書にその証拠が実際に含まれている場合にのみ含めます。
- トップレベルの分類:相互に素な少数のトップレベルタイプ(例:人物 / 組織 / 文書 / イベント / 場所)を選択します。すべてのエンティティをそのうちの 1 つだけに配置します。これにより、後での混乱を防ぎます。
- 最大深さ 3:深い分類は抽出に適しません。サブクラスよりもプロパティを優先します。
- アリストテレス的定義:すべてのエンティティに 1 つの定義を設けます。「契約とは、当事者間で義務を拘束する文書です。」これにより明確さが強制されます。
オントロジーのみのパスの場合:3.1(確認するチャンクがない)と 3.2(サンプリングする文書がない)をスキップします。3.3 に直接進みます。
3.1 解析品質を確認し、チャンクを埋め込む
オントロジー設計の証拠としてチャンクを使用する前に、語彙グラフの解析が正常に行われたことを確認します。
まず、ジョブが完了していることを確認します:
check_processing_status()
ステータスが completed になるまで待ちます。次にチャンクをサンプリングします:
// via documents_read_neo4j_cypher
MATCH (c:Chunk)
WITH c, rand() AS r ORDER BY r LIMIT 10
RETURN c.text
出力で以下を確認します:
- 空またはほぼ空のチャンク(数文字の空白) → pymupdf が何も取得できなかった
- 列が入れ替わったテキスト(テキストがページをジグザグに読んでいる) → マルチカラムレイアウトの誤読
- 文字化け / 非テキスト文字 → pymupdf が読み取れないスキャン PDF の可能性
いずれかの問題がある場合、完全に page_image モードにフォールバックします — 手順については references/lexical-graph-pipeline.md を参照してください(Cypher で語彙グラフを削除し、parse_mode="page_image" で create_lexical_graph を再実行し、embed_chunks の前に generate_chunk_descriptions を実行します)。何が問題だったか、モードを切り替えることをユーザーに簡単に伝えます。これには数分かかります。
チャンクがクリーンな場合は、それらを埋め込みます:
embed_chunks()
これは高速で、バックグラウンドで実行されます。次に、埋め込みが実際に保存されたことを確認します:
// via documents_read_neo4j_cypher
MATCH (c:Chunk)
RETURN count(c) AS total, count(c.embedding) AS embedded
embedded < total の場合、埋め込みは不完全です。embed_chunks() を再実行し、再度確認します。embedded == total になるまで次に進まないでください(そうしないと、フェーズ 8 でベクトル検索が失敗します)。
generate_chunk_descriptions は pymupdf モードではオプションです。ユーザーがベクトル検索で画像 / テーブル / チャートも検索できるようにしたい場合にのみ実行します — 時間はかかりますが、埋め込みが視覚コンテンツをカバーできるようになります。
3.2 証拠のためにチャンクをサンプリングする
次に、(確認済みの)チャンクを使用して、具体的なエンティティ候補を見つけます:
// via documents_read_neo4j_cypher
MATCH (c:Chunk) RETURN c.text LIMIT 20
文書がサポートしていないエンティティを発明しないでください。
3.3 提案し、オントロジー DB に書き込む
各エンティティタイプについて:
- ユーザーに提案します:「Contract、Party、Jurisdiction が文書に含まれているのを確認しました。これらを次のようにモデル化することを提案します:Contract(エンティティ)、Party(エンティティ)、Jurisdiction(Contract のプロパティ)。理由:[一文]。よろしいですか?」
- ユーザーが確認したら、
ontology_write_neo4j_cypherを使用してオントロジー DB に書き込みます。references/ontology-db-schema.mdの契約に従い、MERGE(冪等)を使用します。重要なポイント:すべての:NodeTypeには、is_key=trueを持つ正確に 1 つの:PropertyDefが必要です。プロパティ名はcamelCaseを使用します。リレーションシップタイプ名はSCREAMING_SNAKE_CASEを使用します。
見せ場:ユーザーがエンティティとプロパティのどちらにするかについて反論した場合、トレードオフを説明します。「管轄権をエンティティにすると、'この管轄権のすべての契約を年ごとにグループ化して表示' という質問を簡単に行えます。プロパティとしても可能ですが、少し遅くなります。50 件の契約では問題になりませんが、50,000 件では影響が出る可能性があります。」
3.4 バッチごとに検証する
オントロジーにノード/リレーションシップのバッチを追加した後、バリデーターを実行します:
ontology_read_neo4j_cypher(query=<scripts/validate_ontology.cypher の内容>)
問題のリストが返されます。問題がある場合は、次に進む前に修正します。これはスキーマのずれに対する安全策です。
オントロジーが検証に合格した場合 — 次に進みます。
フェーズ 4 — オントロジーの発表
オントロジーが完成したら、それを整理してユーザーに提示します。ontology_read_neo4j_cypher を使用して、MATCH (n:NodeType)-[:HAS_PROPERTY]->(p:PropertyDef) RETURN n.name, n.definition, collect(p.name) のようなクエリで確認できます。
以下の内容を箇条書きで提示します:
エンティティ:Contract(「当事者を拘束する合意」) — プロパティ:name, jurisdiction, effectiveDate エンティティ:Party(「契約の当事者」) — プロパティ:name, role リレーションシップ:(Party)-[:IS_SIGNATORY_OF]->(Contract)
また、コンピテンシー質問をリストアップし、それぞれがグラフによってどのように答えられるかを簡単に示します。
最後に尋ねます:
「これでよろしいですか?追加、削除、変更したいものはありますか?」
ユーザーが承認するか追加の修正を依頼するまで、このフェーズを続けます。その後、パスに応じて進みます。
オントロジーのみのパス:ここで終了します。
オントロジー+文書のパス:フェーズ 5 に進みます。
フェーズ 5 — エンティティ抽出のスキーマを生成する
生成 AI エンティティ抽出は、構造化されたスキーマ定義に依存します。これをオントロジーから生成します:
generate_schema_from_ontology()
これにより、オントロジーで定義された各 :NodeType と :RelationshipType に対応する JSON スキーマが作成されます。これはバックグラウンドで実行されます。
check_extraction_status で完了を確認します。
フェーズ 6 — エンティティ抽出を実行する
スキーマが準備できたら、抽出を実行します:
extract_entities()
これにより、スキーマに従って、解析されたチャンクからエンティティとリレーションシップが抽出され、文書 DB に保存されます。
check_extraction_status で完了をポーリングします。
フェーズ 7 — 抽出の品質を確認する
抽出が完了したら、品質を確認します。ランダムなチャンクをサンプリングし、抽出されたエンティティを確認します:
// via documents_read_neo4j_cypher
MATCH (c:Chunk)-[:MENTIONS]->(e)
RETURN c.text, labels(e), e.name
LIMIT 10
一般的な問題:
- 欠落しているエンティティ:明らかなエンティティが抽出されていない。→
extract_entities()を再実行します(冪等) - 誤ったエンティティ:関係のないものがエンティティとして抽出されている。→ オントロジー / スキーマを見直します
- 重複:同じ実世界のエンティティが複数回抽出されている。→ これは後のフェーズでエンティティ解決によって処理できます
問題が見つかった場合は、ユーザーに伝え、修正するかどうかを尋ねます。
フェーズ 8 — 質問に答える
これでユーザーはコンピテンシー質問をグラフに対して行えるようになりました。正しいツールを選択します:
- セマンティック検索(
documents_vector_search) — 「類似する契約を見つける」や「パフォーマンスの問題を説明している段落」などの自然言語クエリに最適 - 全文検索(
documents_fulltext_search) — 「'Confidentiality' を正確に含む段落」などの正確なフレーズに最適 - Cypher クエリ(
documents_search_cypher_query) — 構造化されたグラフクエリに最適(「特定の当事者によって署名されたすべての契約」)
ユーザーが自然言語で質問した場合、それを適切なツールに変換します。
各質問の後、回答がどこから来たのかを説明します:「これらの契約の有効期限は、各契約に保存されている 'expiryDate' プロパティを参照することで見つけました。」
質問のたびに、常に使用したツールと検索戦略を要約します。
付録:一般的な落とし穴
- スコープの膨張:各エンティティがコンピテンシー質問と文書証拠の包含基準を満たしていることを確認します。そうしないと、抽出品質が低下します。
- 深い階層:エンティティタイプの深さを 3 レベル以下に保ちます。それ以上は LLM 抽出にノイズをもたらします。
- 関係の欠落:エンティティを追加するたびに、既存のエンティティとの関係を定義します。孤立したエンティティは有用なクエリをサポートしません。
- 重複キー:タイプごとに 1 つのキープロパティのみ。複数あると、重複排除が困難になります。