技術ブログ

RAG Engineering

ハイブリッド検索:RRFの実装と検索品質の検証

Pythonで順位を統合するRRFを実行し、製品コード、アクセス範囲、根拠不足を検証する方法を説明します。

RAGO-X公開 更新
#RAG#Retrieval#LLM
用語検索と意味検索を組み合わせる概念図

「X17のフィルター交換」と「吸入圧力が低下したとき、何を確認するか」は、同じマニュアルを必要とする場合があります。前者では製品コード、後者では原文と異なる表現の理解が重要です。ハイブリッド検索は複数の検索方式の候補を統合して、この両方に対応する設計です。

この解説はPython 3の標準ライブラリだけで実行できます。質問と候補順位は架空の教材であり、RAGO-Xの本番設定や測定済みの性能ではありません。

統合する情報を決める

キーワード検索は語の一致を利用しますが、トークン化やフィールド設定によって挙動が変わります。製品コードの完全一致が必須なら、専用フィールドやフィルターも検討します。ベクトル検索は埋め込み空間の類似度を使いますが、似た型番や否定表現を取り違える可能性があります。

検索方式によってスコアの尺度が異なるため、単純な加算では一方が過度に影響する場合があります。RRFは順位rに対して1 / (k + r)を加算します。順位は1から始まり、候補がないリストからの寄与は0です。ElasticのRRF文書に数式があります。

順位統合を実行する

以下をrrf_demo.pyとして保存し、python3 rrf_demo.pyを実行します。同じ文書版の同じチャンクには、検索方式間で共通のIDを使います。

python
from collections import defaultdict


def rrf(rankings, k=60):
    if k <= 0:
        raise ValueError("k must be positive")
    scores = defaultdict(float)
    for ranking in rankings:
        # Count an ID only once per retriever, preserving order.
        unique = list(dict.fromkeys(ranking))
        for rank, chunk_id in enumerate(unique, start=1):
            scores[chunk_id] += 1.0 / (k + rank)
    return sorted(scores.items(), key=lambda item: (-item[1], item[0]))


keyword = ["manual-A", "manual-B", "manual-C"]
semantic = ["manual-C", "manual-A", "manual-D"]
result = rrf([keyword, semantic])
print([(key, round(score, 6)) for key, score in result])
assert [key for key, _ in result] == ["manual-A", "manual-C", "manual-B", "manual-D"]
assert rrf([["A", "A", "B"]]) == rrf([["A", "B"]])
assert rrf([]) == []

実行結果:

text
[('manual-A', 0.032522), ('manual-C', 0.032266), ('manual-B', 0.016129), ('manual-D', 0.015873)]

AとCは両方のリストに現れるため順位が上がります。一つのリスト内の重複IDは一度だけ数え、同点はID順で処理します。k=60は例の設定であり、常に最適とは限りません。このコードは既存の順位を統合するもので、検索エンジンや埋め込み自体は実装していません。

検索前にアクセス範囲をそろえる

両方の検索で組織、キャビネット、閲覧権限、文書版の範囲をそろえます。権限外の本文をモデルに渡してから画面で隠しても、アクセス制御にはなりません。許可範囲はサーバーで決定し、各検索に適用します。出典を開く際にも権限を確認します。

候補数と最終的に渡す件数は別の設定です。各方式で20件を取得して統合後に5件を選ぶ、といった実験ができます。これは実験条件の例であり製品の既定値ではありません。候補を増やす場合は、根拠の発見率と遅延の両方を測定します。

同じ質問で比較する

質問の種類 想定される失敗 確認方法
正確な型番 別製品の説明書を選択 上位候補の型番一致
言い換え 表現の違いで根拠が欠落 上位5件に正しい根拠があるか
文書にない質問 無関係な本文から回答 根拠不足を示すか
制限文書 他グループの情報が混入 権限外の候補本文を渡さないか

先に質問と正解の根拠を固定し、キーワードのみ、ベクトルのみ、統合の3方式を比較します。少なくとも一つの正解チャンクが上位5件に入った質問の割合を測れます。実測せず改善率を主張しないでください。RRFスコアは正答確率ではなく、再ランキングも候補に入らなかった根拠を復元できません。

検索結果が途中で切れて意味を失う場合は、チャンク境界と原文位置を確認します。全体像は文書から回答までの設計で説明します。

LinkedInで共有