ベクトルデータベースを、できるだけやさしく理解する
最近、ローカルLLMに過去の会話を記憶させられないかと考えるようになった。
一見すると、過去の会話をすべて読み込ませれば済みそうに見える。しかし会話が増えるほど文章量も増え、処理時間とトークン消費が膨らんでいく。
必要なときに、必要な部分だけを取り出したい。そこで登場するのがベクトルデータベースである。
ひと言でいうと
文章を「言葉」ではなく「意味の近さ」で探すためのデータベース
通常の検索は、入力した文字と同じ文字が含まれているかを探す。
例えば、会話ログに次の文章が保存されているとする。
- 遠くの物を取ろうとすると肩が痛い
- 五十肩のリハビリに通っている
- 腕を伸ばす動作がつらい
ここで「手を伸ばすと肩が痛む」と検索しても、まったく同じ言葉は存在しない。キーワード検索では見つけにくい。
しかしベクトル検索なら、「腕を伸ばす」「遠くの物を取る」「肩が痛む」といった意味の近さを判断し、関連する会話を拾い出せる。
扱えるのは文章だけではない。画像や音声も、同じように数値へ変換して検索できる。
厨房にたとえてみる
ベクトルデータベースは、大きな厨房の食材棚のようなものだと考えると分かりやすい。
この棚は、名前や品番順ではなく、味や使い道が近いものが自然と隣り合うように並んでいる。
そこへ注文が入る。担当者は注文票を読み、内容に合いそうな食材をいくつか選んで調理台に並べる。料理人は、その調理台に並んだものだけを見て一皿を作る。
役割を整理すると、こうなる。
- LLM:調理台の材料を使って一皿を仕上げる料理人
- ベクトルデータベース:食材を保管する棚
- Embeddingモデル:食材を「味の近さ」で並べ替える仕組み
- RAG:注文から材料を集め、料理人へ渡すまでの一連の流れ
大切なのは、棚も担当者も料理をしないという点だ。ベクトルデータベースはAIの脳ではなく、材料を出してくる仕組みにすぎない。
そしてこの棚の強みは、バジルが切れていても大葉を出せることにある。名前が一致しなくても、近いものを選べる。これがそのまま意味検索の性質である。
文章を数値に変換するEmbedding
コンピューターは、文章の意味をそのまま理解しているわけではない。
文章をEmbeddingモデルに渡すと、次のような数値の並びに変換される。
[0.023, -0.184, 0.771, 0.092, ...]
これをベクトル、またはEmbeddingと呼ぶ。
似た意味の文章は、ベクトル空間の中でも近い位置に配置される。
今日は大雨で帰るのが大変だった
激しい雨のため帰宅に苦労した
この二つは単語が違っても意味が近いため、比較的近いベクトルになる。
検索時には質問も同じモデルで数値化し、保存済みのベクトルとの距離を計算する。距離の測り方はユークリッド距離や内積などで、コサイン類似度も正規化したベクトルの内積として扱える。
過去の会話を思い出す流れ
過去の会話を保存する
↓
話題ごとに小さく分割する
↓
Embeddingモデルで数値化する
↓
ベクトルデータベースに保存する
↓
新しい質問を同じように数値化する
↓
意味の近い過去の会話を検索する
↓
検索結果だけをLLMへ渡す
↓
それを踏まえて回答する
例えば「前に検討していた外付けGPUは何だった?」と尋ねたとする。
ベクトルデータベースが「OCuLink接続のeGPUを検討していた」「NVIDIAのRTX系が候補」「MINISFORUM DEG1 Dockについて話した」といった断片を探し出し、LLMはそれだけを読んで答える。膨大なログを毎回すべて読ませる必要はない。
この構成が、一般に**RAG(Retrieval-Augmented Generation/検索拡張生成)**と呼ばれるものである。LLMを再学習させなくても、社内資料や商品データ、マニュアル、過去の会話を回答材料として渡せる。
チャンクとメタデータ
会話ログを一つの巨大な文章として保存すると、検索精度が落ちやすい。そこで適度な大きさに分割する。この単位をチャンクと呼ぶ。
ただし機械的に500文字で切ればよいわけではない。外付けGPUの話、CSV処理の話、英語学習の話——話題ごとに区切った方が探しやすい。
さらに各チャンクにはメタデータを付けられる。
{
"date": "2026-08-05",
"category": "AI",
"topic": "vector_database",
"source": "chat_log"
}
「categoryがAIのものだけ」「2026年以降だけ」といった絞り込みが可能になる。Chromaでは、こうしたメタデータによるフィルタリングとベクトル検索を組み合わせられる。
「記憶する」だけでは足りない
AIに記憶を持たせるとき、本当に難しいのは保存する部分ではない。
- 何を記憶し、何を記憶しないのか
- いつ思い出すのか
- 古い情報をどう更新するのか
- どの情報を忘れさせるのか
例えば過去に「Go言語を中心に学習する」と話していても、後から「Rustを中心にする」と方針が変わることがある。両方を同じ強さで保存していれば、AIは古い方針を取り出しかねない。
そのため、個人向けAIの記憶は二層構造が扱いやすい。
元の会話ログ(証拠として残す)
+
現在の方針や好みをまとめた長期記憶
保存・検索・要約・更新・忘却まで含めて、初めて記憶システムになる。
通常のデータベースとの使い分け
厨房でいえば、食材棚とは別に在庫台帳がある。個数や原価や賞味期限は、味の近さで並べても意味がない。
Yahooショッピングの商品管理でいえば、商品コード、在庫数、仕入れ価格、廃盤フラグといった正確な値がそれにあたる。こうしたデータはCSVやSQLite、PostgreSQLの方が向いている。
正確な値を探す → 通常のデータベース
意味が近い情報を探す → ベクトルデータベース
すでにPostgreSQLを使っているなら、pgvectorを追加することで両方を同じデータベース内に置ける。pgvectorは正確な最近傍検索と近似最近傍検索の両方に対応している。
代表的なソフト
- Chroma:Pythonから手軽に試せる。最初の学習用に向く
- Qdrant:サーバー型。Dockerで動かしやすく、Rustやgoのクライアントもある
- PostgreSQL+pgvector:既存システムへ意味検索を足したい場合に便利
- Faiss:厳密にはライブラリ。検索アルゴリズムを学びたい場合に向く
ほかにMilvus、Weaviate、Pinecone、LanceDBなどもある。ただし製品比較に時間をかけるより、少量のデータを実際に検索してみた方が理解は早い。
まずは小さく試す
いきなり何万件も入れる必要はない。20件から50件程度の短いメモで十分である。
PythonでCSVの価格差を確認している
Go言語のポインタを勉強している
Rustの所有権に興味がある
STRiDAで琵琶湖を走った
ローカルLLMをUbuntuで動かしている
これに対して「最近勉強しているプログラミング言語は?」と検索してみる。GoやRustのメモが上位に来れば、意味検索の感覚がつかめる。
構成はこの程度でよい。
Python + Chroma + ローカルのEmbeddingモデル + 20〜50件のメモ
重要なのはプログラムを完成させることではない。質問を少しずつ言い換えながら、
どの文章が検索されたか
なぜその文章が選ばれたか
関係のない文章が混ざっていないか
を眺めること。この作業が一番の近道になる。
弱点も知っておく
ベクトル検索は意味の近さを探す仕組みであって、正しさを保証する仕組みではない。似ているが無関係な文章が混ざることもある。
精度は、Embeddingモデル、チャンクの分け方、保存する文章の品質、検索件数、メタデータ、質問文の書き方に左右される。LLMへ渡す前に関連度を評価したり、日付やカテゴリで絞り込んだりする工夫が要る。
魔法の記憶装置ではない。それでも、キーワードが一致しなくても関連情報を探せる点は、従来の検索にはない強みである。
今から学ぶ意味
将来、ベクトル検索やRAGはAIシステムの標準機能になり、直接触る機会は減るかもしれない。
それでも、
- AIに記憶を持たせる技術
- 意味の近さで検索される
- 必要な情報だけLLMへ渡される
- チャンクやメタデータで精度が変わる
- 記憶には更新や忘却も必要になる
という原理を知っていれば、「なぜ関係のない記憶を取り出したのか」「なぜ必要な会話を思い出せなかったのか」を考えられる。
ベクトルデータベースの知識自体はいずれ一般化する。しかし、AIに何を覚えさせ、何を忘れさせ、いつ思い出させるかを設計する力は、これからも残るはずだ。
まとめ
ベクトルデータベースとは、文章や画像を数値に変換し、意味の近さで情報を探す仕組みである。LLMと組み合わせれば、過去の会話や資料を必要なときだけ取り出して回答に使える。
ただし目的は、ベクトルデータベースを使うことではない。
AIが必要な情報を、必要な場面で思い出せるようにすること
まずは少量のメモを保存し、言葉を変えて検索してみる。その小さな実験から、Embedding、類似検索、RAG、そしてAIの記憶という仕組みが、少しずつつながって見えてくるはずだ