PostgreSQL+pgvector で LlamaIndex の Property Graph Index を試す(序章)

703 Views

June 21, 25

スライド概要

俺の勉強会 #2 2025/6/9 LT
(6/20 一部訂正)

profile-image

Qiita や Zenn でいろいろ書いてます。 https://qiita.com/hmatsu47 https://zenn.dev/hmatsu47 MySQL 8.0 の薄い本 : https://github.com/hmatsu47/mysql80_no_usui_hon Aurora MySQL v1 → v3 移行計画 : https://zenn.dev/hmatsu47/books/aurora-mysql3-plan-book https://speakerdeck.com/hmatsu47

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

ダウンロード

関連スライド

各ページのテキスト
1.

PostgreSQL+pgvector で LlamaIndex の Property Graph Index を試す (序章) 俺の勉強会 #2 2025/6/9 まつひさ(hmatsu47)

2.

自己紹介 松久裕保(@hmatsu47) ● https://qiita.com/hmatsu47 ● 現在: ○ 名古屋で Web インフラのお守り係をしています ○ SRE チームに所属しつつ技術検証の支援をしています ○ 普段カンファレンス・勉強会では DB の話しかしていません (ほぼ) 2

3.

ところで ● 最近の生成 AI 界隈では MCP がブームですが、ちょっと 前までは RAG が流行っていましたね ○ もう見る影もないですが ○ とはいえ、実務では RAG で頑張っている勢のほうが多いかも? 3

4.

RAG といえば ● RAG(Retrieval Augmented Generation:検索拡張生成) ○ 生成 AI が学習していない(弱い)知識について普通に質問する と、生成 AI は正しい答えを返せない ○ 関連知識を DB などから検索して持ってきてコンテキストとして 生成 AI に与えると、正しい答えを返せる ○ 関連知識を DB で検索するときの標準的な方法はベクトル検索 4

5.

ベクトル検索 ● 意味が近い文章などを探すときに使う ○ 最近は生成 AI の埋め込みモデルを使って文章などをベクトル化 するのが主流 ○ 一般的な埋め込みモデルでは長い文章をそのままベクトル化する ことはできないので、文章を分割(チャンク化)してチャンクごと にベクトル化して DB に入れる ○ 質問文もベクトル化して、DB で「距離が近いベクトル」を探す ■ 生成 AI にコンテキストとして渡すのはベクトルではなくて元の文章など 5

6.

詳細は ● BuriKaigi2025 の発表資料 ○ https://www.docswell.com/s/hmatsu47/ZP2LY6-2025-01-19-235645 6

7.

ベクトル検索型 RAG の弱点 ● チャンク化するときの分割方法が難しい ○ 細かく分割してしまうと必要な情報を生成 AI に渡せない ○ 大きすぎると埋め込みモデルで扱えない・検索精度が落ちる ● ソースとなる情報が分散していると取りこぼす ○ 脚注がある文章や図表・添付資料に補足があるケースなど ● 抽出したコンテキストがうまく LLM に伝わらない ○ 複雑・曖昧な文章をベクトル検索して LLM に渡すケースなど 7

8.

ベクトル検索型 RAG の弱点 ● チャンク化するときの分割方法が難しい ○ 細かく分割してしまうと必要な情報を生成 AI に渡せない 今回はこの問題に対処する目的で ○ 大きすぎると埋め込みモデルで扱えない・検索精度が落ちる 「グラフインデックス」を使ってみる ● ソースとなる情報が分散していると取りこぼす ○ 脚注がある文章や図表・添付資料に補足があるケースなど ● 抽出したコンテキストがうまく LLM に伝わらない ○ 複雑・曖昧な文章をベクトル検索して LLM に渡すケースなど 8

9.

グラフ RAG(グラフインデックス) ● 関連知識の格納と検索にグラフ構造を利用 ○ 色々な方法はあるが、LlamaIndex で Property Graph Index をデ フォルト構成で使う場合は、文章チャンクの中からいくつかの 「主語+述語+目的語」(トリプレット)を抽出して文章チャンク そのものと併用する ■ 検索時にはベクトル検索でグラフ構造を指定の深さまで辿り、関連する文章 チャンクと一緒に LLM に対してコンテキストとして渡す 私 パン 食べる 9

10.

やったこと ● LlamaIndex に PostgreSQL+pgcevtor のグラフストア を実装 ○ TiDB 用グラフストア実装を元に Amazon Q Developer GitHub 統合(プレビュー)で PostgreSQL+pgvector 用に書き換え ■ Amazon Q Developer GitHub 統合で実装できなかったところは手作業で ○ Property Graph Index と Streamlit で単答チャットを実装 ○ サンプルデータをインデックス化して実行 ■ LLamaIndex のサンプル文書(エッセイ)を日本語訳したもの(脚注付き) 10

11.

Amazon Q Developer GitHub 統合での作業 ● トークン数の限界、過去作業に関するコンテキスト引き 継ぎなどでそこそこ苦労 11

12.

Property Graph Index でインデックス生成 postgres=# \d List of relations Schema | Name | Type | Owner --------+---------------------+----------+---------public | pg_nodes | table | postgres public | pg_relations | table | postgres public | pg_relations_id_seq | sequence | postgres (3 rows) 12

13.

Property Graph Index でインデックス生成 postgres=# \d pg_nodes Table "public.pg_nodes" Column | Type | Collation | Nullable | Default ------------+-----------------------------+-----------+----------+--------id | character varying(512) | | not null | text | text | | | name | character varying(512) | | | label | character varying(512) | | not null | properties | jsonb | | | embedding | vector(1024) | | | created_at | timestamp without time zone | | not null | now() updated_at | timestamp without time zone | | not null | now() Indexes: "pg_nodes_pkey" PRIMARY KEY, btree (id) Referenced by: TABLE "pg_relations" CONSTRAINT "pg_relations_source_id_fkey" FOREIGN KEY (source_id) REFERENCES pg_nodes(id) TABLE "pg_relations" CONSTRAINT "pg_relations_target_id_fkey" FOREIGN KEY (target_id) REFERENCES pg_nodes(id) 13

14.

Property Graph Index でインデックス生成 postgres=# \d pg_relations Table "public.pg_relations" Column | Type | Collation | Nullable | Default ------------+-----------------------------+-----------+----------+----------------------------------------id | integer | | not null | nextval('pg_relations_id_seq'::regclass) label | character varying(512) | | not null | source_id | character varying(512) | | | target_id | character varying(512) | | | properties | jsonb | | | created_at | timestamp without time zone | | not null | now() updated_at | timestamp without time zone | | not null | now() Indexes: "pg_relations_pkey" PRIMARY KEY, btree (id) Foreign-key constraints: "pg_relations_source_id_fkey" FOREIGN KEY (source_id) REFERENCES pg_nodes(id) "pg_relations_target_id_fkey" FOREIGN KEY (target_id) REFERENCES pg_nodes(id) 14

15.
[beta]
Property Graph Index でインデックス生成
postgres=# SELECT id, text, name, label, properties FROM public.pg_nodes LIMIT 1;
(中略)
id
| 9035ea97-bd3d-449e-a7c6-4905ce223bd2
text
| 私が取り組んできたこと
(中略)
| 大学に入る前、学校以外で私が取り組んでいた主なことは、文章を書くこととプログラミングだった。エッセイは書かなかった。
当時、そして今もおそらく初心者の作家が書くべきとされている短編小説を書いていた。私の小説はひどい出来だった。ほとんど筋がなく、感情
の強い登場人物がいるだけで、それが作品に深みを与えているのだと思い込んでいた
(中略)
name
|
label
| text_chunk
properties | {"doc_id": "4442846b-2d07-41e6-9dab-3cdea250595a", "file_name": "example_ja.txt","file_path":
"/Users/hmatsu47/llama_index_property_graph_test/data/example_ja.txt", "file_size": 44432, "file_type":
"text/plain", "_node_type": "TextNode", "ref_doc_id": "4442846b-2d07-41e6-9dab-3cdea250595a",
"document_id": "4442846b-2d07-41e6-9dab-3cdea250595a",
(中略)
\"metadata_seperator\": \"\\n\", \"text_template\": \"{metadata_str}\\n\\n{content}\", \"class_name\":
\"TextNode\"}", "creation_date": "2025-05-22", "last_modified_date": "2025-05-22"}

15

16.
[beta]
Property Graph Index でインデックス生成
postgres=# SELECT id, label, source_id, target_id, properties FROM public.pg_relations LIMIT 2;
(中略)
id
| 3
label
| 書いていた
source_id | 私
target_id | 短編小説
properties | {"file_name": "example_ja.txt", "file_path":
"/Users/hmatsu47/llama_index_property_graph_test/data/example_ja.txt", "file_size": 44432, "file_type":
"text/plain", "creation_date": "2025-05-22", "triplet_source_id": "559b69a0-8af5-423a-ba32-11256cb578f5",
"last_modified_date": "2025-05-22"}
(中略)
id
| 4
label
| 初めて書いた
source_id | 私
target_id | プログラム
properties | {"file_name": "example_ja.txt", "file_path":
"/Users/hmatsu47/llama_index_property_graph_test/data/example_ja.txt", "file_size": 44432, "file_type":
"text/plain", "creation_date": "2025-05-22", "triplet_source_id": "559b69a0-8af5-423a-ba32-11256cb578f5",
"last_modified_date": "2025-05-22"}

16

17.

Property Graph Index でインデックス生成 17

18.

Streamlit で単答チャットアプリ化 18

19.

以上「序章」でした ● 詳細はこちらで話す予定 ○ 第 53 回 PostgreSQL アンカンファレンス@オンライン(6/24) https://pgunconf.connpass.com/event/355128/ ● GitHub リポジトリ ○ https://github.com/hmatsu47/llama-index-graph-stores-postgres ○ https://github.com/hmatsu47/llama_index_property_graph_test ○ https://github.com/hmatsu47/llama_index/issues?q=is%3Aissue%20state %3Aclosed 19