ベクトル検索とテキスト処理
PRX にはセマンティックメモリ検索を支えるテキスト処理パイプラインが含まれています。このパイプラインはテキストチャンキング、ベクトルエンベディング、トピック抽出、コンテンツフィルタリングを処理し、生の会話テキストを検索可能で整理されたメモリエントリに変換します。
アーキテクチャ
テキスト処理パイプラインは 4 つのステージで構成され、それぞれ独立して設定可能です:
Raw Text
│
▼
┌──────────┐ ┌───────────┐ ┌───────────┐ ┌──────────┐
│ Chunker │───►│ Embedder │───►│ Topic │───►│ Filter │
│ │ │ │ │ Extractor │ │ │
└──────────┘ └───────────┘ └───────────┘ └──────────┘
テキストを 各チャンクを トピックで 保存する価値が
チャンクに分割 ベクトル化 分類 あるか判定ベクトル検索
ベクトル検索はセマンティック類似度検索を可能にします -- 正確な単語が異なっていても、概念的に関連するメモリを見つけます。
仕組み
- インデックス作成 -- 各メモリチャンクが密なベクトル(例: 768 次元)にエンベッドされる
- 保存 -- ベクトルがベクトルインデックス(sqlite-vec、pgvector、またはインメモリ)に保存される
- クエリ -- 検索クエリが同じモデルでエンベッドされる
- 検索 -- インデックスがコサイン類似度で Top-K のベクトルを返す
- リランキング -- オプションで、クロスエンコーダーを使用して結果をリランキングし、精度を向上
設定
[memory.vector]
enabled = true
index_type = "sqlite-vec" # "sqlite-vec", "pgvector", or "memory"
similarity_metric = "cosine" # "cosine", "dot_product", or "euclidean"
top_k = 10
similarity_threshold = 0.5
rerank = false
rerank_model = "cross-encoder/ms-marco-MiniLM-L-6-v2"インデックスタイプ
| インデックスタイプ | ストレージ | 永続化 | 最適な用途 |
|---|---|---|---|
sqlite-vec | ローカルファイル | あり | シングルユーザー、ローカルデプロイメント |
pgvector | PostgreSQL | あり | マルチユーザー、本番デプロイメント |
memory | インプロセス | なし(セッションのみ) | テストとエフェメラルセッション |
設定リファレンス
| フィールド | 型 | デフォルト | 説明 |
|---|---|---|---|
enabled | bool | true | ベクトル検索の有効化/無効化 |
index_type | String | "sqlite-vec" | ベクトルインデックスバックエンド |
similarity_metric | String | "cosine" | 類似度比較の距離メトリック |
top_k | usize | 10 | クエリあたりの返却結果数 |
similarity_threshold | f64 | 0.5 | 結果に含める最小類似度スコア(0.0--1.0) |
rerank | bool | false | 精度向上のためのクロスエンコーダーリランキングの有効化 |
rerank_model | String | "" | クロスエンコーダーモデル名(rerank = true の場合のみ使用) |
ef_search | usize | 64 | HNSW 検索パラメータ(高いほど正確だが低速) |
テキストチャンキング
エンベディングの前に、長いテキストを小さなチャンクに分割する必要があります。PRX は 2 つのチャンキング戦略を提供します: トークン認識とセマンティック。
トークン認識チャンキング
トークン認識チャンキングはトークン境界でテキストを分割し、各チャンクがエンベディングモデルのコンテキストウィンドウに収まるようにします。単語や文の境界を尊重し、単語の途中での分割を避けます。
[memory.chunker]
strategy = "token"
max_tokens = 512
overlap_tokens = 64
tokenizer = "cl100k_base" # OpenAI 互換トークナイザーアルゴリズム:
- 設定されたトークナイザーで入力テキストをトークン化
- 最大
max_tokensトークンのチャンクに分割 - 各チャンクは前のチャンクと
overlap_tokens分オーバーラップし、境界でのコンテキストを保持 - 可能な場合、チャンク境界を文や段落の区切りに合わせて調整
セマンティックチャンキング
セマンティックチャンキングはエンベディング類似度を使用してテキスト内の自然なトピック境界を見つけます。固定トークン数での分割の代わりに、トピックが変わる場所を検出します。
[memory.chunker]
strategy = "semantic"
max_tokens = 1024
min_tokens = 64
breakpoint_threshold = 0.3アルゴリズム:
- テキストを文に分割
- 各文のエンベディングを計算
- 連続する文間のコサイン類似度を計算
- 類似度が
breakpoint_thresholdを下回った場合、チャンク境界を挿入 - 小さなチャンク(
min_tokens未満)を隣接チャンクとマージ
チャンキング設定リファレンス
| フィールド | 型 | デフォルト | 説明 |
|---|---|---|---|
strategy | String | "token" | チャンキング戦略: "token" または "semantic" |
max_tokens | usize | 512 | チャンクあたりの最大トークン数 |
overlap_tokens | usize | 64 | 連続チャンク間のオーバーラップ(token 戦略のみ) |
tokenizer | String | "cl100k_base" | トークンカウント用のトークナイザー名 |
min_tokens | usize | 64 | チャンクあたりの最小トークン数(semantic 戦略のみ) |
breakpoint_threshold | f64 | 0.3 | トピック境界の類似度低下閾値(semantic 戦略のみ) |
戦略の選択
| 基準 | トークン認識 | セマンティック |
|---|---|---|
| 速度 | 高速(チャンキング時にエンベディング呼び出しなし) | 低速(文ごとのエンベディングが必要) |
| 品質 | 均一なコンテンツに良好 | マルチトピックドキュメントに優れる |
| 予測可能性 | 一定のチャンクサイズ | 可変のチャンクサイズ |
| ユースケース | チャットログ、短いメッセージ | 長いドキュメント、ミーティングノート |
トピック抽出
PRX はメモリエントリからトピックを自動抽出し、カテゴリに整理します。トピックは特定のドメイン内でのフィルタ検索を可能にし、検索精度を向上させます。
仕組み
- チャンキング後、各チャンクのトピックキーワードとセマンティック内容が分析される
- トピック抽出器が設定可能な分類体系から 1 つ以上のトピックラベルを割り当てる
- トピックはメモリエントリと共にメタデータとして保存される
- リコール時に、クエリはオプションでトピックによるフィルタで結果を絞り込める
設定
[memory.topics]
enabled = true
max_topics_per_entry = 3
taxonomy = "auto" # "auto", "fixed", or "hybrid"
custom_topics = [] # taxonomy = "fixed" or "hybrid" の場合のみ使用
min_confidence = 0.6分類体系モード
| モード | 説明 |
|---|---|
auto | トピックはコンテンツから動的に生成される。必要に応じて新しいトピックが作成される |
fixed | custom_topics のトピックのみが割り当てられる。一致しないコンテンツは未分類のまま |
hybrid | custom_topics を優先するが、既存のラベルに一致しないコンテンツには新しいトピックを作成 |
トピック設定リファレンス
| フィールド | 型 | デフォルト | 説明 |
|---|---|---|---|
enabled | bool | true | トピック抽出の有効化/無効化 |
max_topics_per_entry | usize | 3 | メモリエントリあたりの最大トピックラベル数 |
taxonomy | String | "auto" | 分類体系モード: "auto"、"fixed"、"hybrid" |
custom_topics | [String] | [] | fixed/hybrid 分類体系のカスタムトピックラベル |
min_confidence | f64 | 0.6 | トピック割り当ての最小信頼度スコア(0.0--1.0) |
コンテンツフィルタリング
すべてのメッセージが長期メモリに保存する価値があるわけではありません。コンテンツフィルターは自動保存ヒューリスティックを適用して、どのコンテンツを永続化し、どれを破棄するかを決定します。
自動保存ヒューリスティック
フィルターは各候補メモリエントリを複数の基準で評価します:
| ヒューリスティック | 説明 | 重み |
|---|---|---|
| 情報密度 | 一意のトークンと総トークンの比率。低密度テキスト(例: 「ok」、「thanks」)はフィルタされる | 高 |
| 新規性 | 既存メモリとの類似度。既に保存されているものと類似しすぎるコンテンツはスキップ | 高 |
| 関連性 | ユーザーの既知の関心事やアクティブなトピックとのセマンティック類似度 | 中 |
| 実行可能性 | アクションアイテム、決定、コミットメントの存在(例: 「...します」、「...しましょう」) | 中 |
| 新しさバイアス | 短期的な関連性のために最近のコンテキストが高く重み付け | 低 |
重み付き合計として複合スコアが計算されます。autosave_threshold 未満のエントリは永続化されません。
設定
[memory.filter]
enabled = true
autosave_threshold = 0.4
novelty_threshold = 0.85 # 既存メモリと85%以上類似している場合スキップ
min_length = 20 # 20文字未満のエントリをスキップ
max_length = 10000 # 10,000文字を超えるエントリを切り捨て
exclude_patterns = [
"^(ok|thanks|got it|sure)$",
"^\\s*$",
]フィルター設定リファレンス
| フィールド | 型 | デフォルト | 説明 |
|---|---|---|---|
enabled | bool | true | コンテンツフィルタリングの有効化/無効化 |
autosave_threshold | f64 | 0.4 | メモリを永続化する最小複合スコア(0.0--1.0) |
novelty_threshold | f64 | 0.85 | 重複排除前の既存メモリとの最大類似度 |
min_length | usize | 20 | メモリエントリの最小文字数 |
max_length | usize | 10000 | 最大文字数(超過エントリは切り捨て) |
exclude_patterns | [String] | [] | 保存すべきでないコンテンツの正規表現パターン |
完全なパイプライン例
4 つのステージすべてを組み合わせた完全な設定:
[memory]
backend = "embeddings"
[memory.embeddings]
provider = "ollama"
model = "nomic-embed-text"
dimension = 768
[memory.vector]
enabled = true
index_type = "sqlite-vec"
top_k = 10
similarity_threshold = 0.5
[memory.chunker]
strategy = "semantic"
max_tokens = 1024
min_tokens = 64
breakpoint_threshold = 0.3
[memory.topics]
enabled = true
taxonomy = "hybrid"
custom_topics = ["coding", "architecture", "debugging", "planning"]
[memory.filter]
enabled = true
autosave_threshold = 0.4
novelty_threshold = 0.85関連ページ
- メモリシステム概要
- エンベディングバックエンド -- エンベディングプロバイダーの設定
- SQLite バックエンド -- sqlite-vec インデックスのローカルストレージ
- PostgreSQL バックエンド -- pgvector インデックスのストレージ
- メモリハイジーン -- コンパクションとクリーンアップ戦略