はじめに
前回、個人の記憶を概念IDに変換するという考え方を紹介した。
今回は、その概念IDをどう利用するかを考える。
やりたいことは難しくない。
例えば、次のような概念が登録されているとする。
ID1 : 登山日記
ID2 : 食事
ID3 : 満腹感
ID4 : 気分転換
ここで、ユーザーが次のように話したとする。
「最近、気分転換できていない」
LLMはID4に注目する。
そして、ID4と関連する概念を取得する。
登山日記かもしれないし、食事かもしれない。
現在の会話に応じて、参照すべき情報が変わる。
この動きを、TransformerのAttentionに着想を得た仕組みとして考えている。
1. Attentionとは何か
TransformerにおけるAttentionは、入力された情報の中から、現在の文脈に関連する情報へ重みを付けて参照する仕組みである。
今回の構想でも、考え方は似ている。
ただし、Transformer内部のAttentionをそのまま外部データベースへ移植するわけではない。
注目する概念をLLMが決め、その概念に関連する情報をベクトル空間から取得する。
ここでは、その一連の動作を「概念へのAttention」と呼ぶ。
2. ベクトル空間の役割
概念IDには、意味を表すベクトルを対応させる。
例えば、以下のような関連がある。
ID1 登山日記 ────── ID4 気分転換
ID2 食事 ── ID3 満腹感
│
└───────────── ID4 気分転換
線は概念間の関連性を示している。
必ずしも明示的なグラフDBが必要なわけではない。
概念ベクトルの類似度を計算して、関連するIDを探してもよい。
また、個人特有の結合強度を別途保存してもよい。
重要なのは、自然言語の文章を検索対象の中心に置かないことだ。
まず概念IDを検索する。
その後、必要なら関連する日記や会話履歴を取得する。
3. LLMが注目領域を推論する
今回の構想では、検索条件を細かく固定しない。
LLMが現在の会話から、どの概念を参照すればよいかを判断する。
例えば、
「お腹いっぱいで、もう動きたくない」
という発言なら、食事や満腹感が注目候補になる。
一方、
「週末、どこかに出かけたい」
という発言なら、登山や気分転換が注目候補になるかもしれない。
このように、同じ記憶データでも、質問によって参照される領域が変化する。
ここが静的な辞書検索との違いである。
4. 最小のデータモデル
まずは複雑なデータ構造を作らない。
概念ID、概念名、関連ID、元データへの参照を保持する。
{
"concepts": [
{
"id": 1,
"name": "登山日記",
"related": [
{"id": 4, "weight": 0.8}
]
},
{
"id": 2,
"name": "食事",
"related": [
{"id": 3, "weight": 0.9},
{"id": 4, "weight": 0.4}
]
},
{
"id": 3,
"name": "満腹感",
"related": [
{"id": 2, "weight": 0.9}
]
},
{
"id": 4,
"name": "気分転換",
"related": [
{"id": 1, "weight": 0.8},
{"id": 2, "weight": 0.4}
]
}
]
}
数値は説明用の仮値であり、実際の経験から学習したものではない。
ここに、必要に応じて概念ベクトルや日記本文への参照を追加する。
これで、概念間の関係を扱うための最小構造ができる。
5. プロンプトエンジニアリングの役割
このシステムでは、プロンプトエンジニアリングが重要になる。
LLMに対し、単に「過去の情報を検索して」と指示するのではない。
現在の発言から概念を抽出し、注目するIDを決定し、関連する概念を取得させる。
例えば、次のような指示だ。
あなたは個人の概念記憶を利用するAIです。
ユーザーの発言を理解し、
関連する概念IDを推論してください。
概念IDに関連する記憶を取得し、
現在の会話に必要な情報を選択してください。
関係の薄い情報は回答に含めないでください。
取得した記憶と推測を区別してください。
これだけでも、基本的な処理の流れを作ることができる。
実際には、概念IDを返すツール呼び出しと、検索結果をLLMへ返すAPIを用意する。
6. 経験によって関連性が変わる
Personal AIである以上、記憶は固定ではない。
例えば、最初は登山と気分転換の関連性が弱かったとしても、登山を通じて気分転換できた経験が繰り返されれば、その結合を強めることができる。
逆に、以前ほど関連しなくなった概念は、重みを調整できる。
ここで重要なのは、AIが勝手に因果関係を確定しないことだ。
「一緒に登場した概念」と「本人にとって強く結び付いている概念」は、必ずしも同じではない。
したがって、重みの更新方法は今後の実験対象とする。
7. 実装はどこまで簡単にできるか
初期段階では、以下の構成で十分だと考えている。
Telegram / 音声
↓
LLM
概念IDを推論
↓
Concept Store
ID・関連性・重み
↓
関連IDを取得
↓
LLM
推論・回答
概念数が少ないうちは、JSONやSQLiteでも実装できる。
いきなりNeo4jや大規模なベクトルデータベースを導入する必要はない。
もちろん、概念の数が増え、検索条件が複雑になれば、それに合わせてデータベースを変更すればよい。
まずは最小限の構成で、期待した概念が検索されるかを検証したい。
8. まとめ
今回考えたのは、概念IDを中心にした軽量な記憶検索である。
基本構造は、
自然言語 → LLM → 概念ID → 関連概念 → LLM
これだけだ。
概念間の関連性にはベクトル表現や結合重みを利用する。
そして、現在の会話からどの領域に注目するかをLLMが推論する。
記憶の仕組みを複雑に作り込むのではなく、LLMが本来持っている意味理解能力を最大限利用する。
この方式が、従来の文章ベースのRAGと比較して、どれほど軽量で自然な連想を実現できるか。
それをこれから確かめていく。
次回:第3部「概念IDはどう増えるのか ― 記憶の登録・統合・更新」
新しい経験から概念を追加し、既存概念との関連性を更新する仕組みを考える。
タグ:LLM / RAG / Python / Transformer / PersonalAI