メインコンテンツへスキップ

検索パイプライン

search_memories が呼び出されると、クエリは多段階パイプラインを通過します:
Query text
  ├── Embedding model → 384d vector
  │     └── sqlite-vec cosine search → semantic results
  ├── FTS5 MATCH → BM25 ranked results
  └── Merge candidates
        └── 4-component hybrid scoring
              └── Sorted results

セマンティック検索

sqlite-vec を使用して vec_memories テーブルに対するコサイン距離検索を実行します。ベクトル類似度順にメモリを返します。 距離は 0-1 の類似度スコアに変換されます:
similarity = 1 / (1 + distance)

全文検索(BM25)

Porter ステミングトークナイザーを使用した FTS5 を利用します。FTS インデックスは contenttags フィールドをカバーします。 BM25 ランクは 0-1 に正規化されます:
score = 1 / (1 + |rank|)
FTS5 のランクは負の値(低いほど関連性が高い)のため、正規化の前に abs() が適用されます。

ハイブリッドスコアリング

各候補メモリは4つの要素から重み付きスコアを受け取ります:
score = semantic × w_s + bm25 × w_b + recency × w_r + salience × w_a

デフォルトの重み

要素重み説明
Semantic0.4ベクトル類似度
BM250.3全文検索の関連性
Recency0.2最近アクセスされたかどうか
Salience0.1時間経過で減衰する重要度
重みはクエリごとにオーバーライド可能です:
{
  "query": "authentication",
  "weights": { "semantic": 0.6, "bm25": 0.1, "recency": 0.2, "salience": 0.1 }
}

Recency スコア

設定可能な半減期(デフォルト:24時間)による指数減衰:
recency = exp(-ln(2) / halfLife × ageInHours)
24時間前にアクセスされたメモリのスコアは約0.5、直前にアクセスされたメモリのスコアは約1.0になります。

Salience スコア

メモリの importance 値と時間減衰を組み合わせます:
salience = importance × exp(-rate × ageInHours)
減衰率のデフォルトは1時間あたり0.01です。

フィルタリング

スコアリングの前に、候補は以下でフィルタリングされます:
  • レイヤーフィルター — 指定されたレイヤーのメモリのみを含む
  • スコープフィルター — プロジェクトまたはグローバルスコープでフィルタ
  • TTL フィルターexpiresAt を過ぎたメモリを除外
  • ソフトデリートフィルター — 削除済みメモリを常に除外