Neo4j は v5.13 で Vector search index を実装した。使い方は他の VectorDB と同様で、ベクタライズしたデータを Vector Index に格納する。Cypher クエリを通じて近似解を導出する。
この記事では、Vector Index の使い方について紹介する。具体例では、ノートアプリのバックエンドとして Neo4j を VectorDB として利用する想定で紹介する。"Note" ノードはそれぞれのノートの ID やメタデータを持つ。ノートのタイトルは "Title" ノードに保存する。今回の目玉となる Vector Index を "Abstract" ノードに担当させる。
CREATE
(note:Note)-[:HAS]->(title:Title {text="Hello, world!"})
, (note)-[:HAS]->(abstract:Abstract)
RETURN
note, title, abstract
まずは下準備について。db.index.vector.createNodeIndex
命令を利用して、Vector Index を作成する。例えば、ノートアプリの要約を保存する "Abstract" インデックスを、ベクター数 768 で作成するコマンドは以下の通り。embedding
プロパティにベクタライズしたデータを保存していく。Similarity Search のアルゴリズムとしては Euclidean と Cosine が現時点では使え、以下の例では Cosine Similarity を指定している。
CALL db.index.vector.createNodeIndex(
'abstract-embeddings',
'Abstract',
'embedding',
768,
'cosine'
)
次は書き込みについて。db.create.setNodeVectorProperty
命令を利用して、ベクターデータを格納する。これで読み込みの準備は完了だ。
MATCH
(abstract:Abstract)<-[:HAS]-(note:Note)-[:HAS]->(title:Title{text="Hello, world!"})
CALL
db.create.setNodeVectorProperty(
abstract,
'embedding',
[0.312, 0.234, -0.456, ...]
)
RETURN
abstract, note, title
ベクターデータをすべての Vector Index に格納したら、最後は読み込みだ。db.index.vector.queryNodes
命令を利用して、Vector Index から近似スコアを導出する。例えば以下の例では、Hello world! I'm LLM app!
というタイトルを持つ "Note" ノードに近似した別の "Note" ノードを、Vector Index である "Abstract" ノードのスコア上位三件を取得している。
MATCH (title:Title)<--(:Note)-->(abstract:Abstract)
WHERE title.text = "Hello world! I'm LLM app!"
CALL db.index.vector.queryNodes(
'abstract-embeddings',
3,
abstract.embedding
)
YIELD node AS similarAbstract, score
MATCH (similarAbstract)<--(:Note)-->(similarTitle:Title)
RETURN similarTitle.text AS title, score
以下がクエリ結果の例だ。"Hello world!" を含んだノートが上位スコアで返却されていることがわかる。これは "title" プロパティに格納されたベクターデータの Cosine Similarity を計算し、最もベクトル座標上近い上位三件を取得した結果である。
╒══════════════════════════════════════════════════════════════════╤══════════════════╕
│title │score │
╞══════════════════════════════════════════════════════════════════╪══════════════════╡
│"Hello world! I'm LLM app!" │1.0 │
├──────────────────────────────────────────────────────────────────┼──────────────────┤
│"Hello world! Here is a RAG demo." │0.8671051263809204│
├──────────────────────────────────────────────────────────────────┼──────────────────┤
│"Here is a RAG demo. I'm going to show you how to create the app."│0.8667137622833252│
└──────────────────────────────────────────────────────────────────┴──────────────────┘