🌙
「告白のセリフ」で検索すると「月が綺麗ですね」がヒットする検索機能を実装したい🌙
はじめに
「告白のセリフ」で検索したら、「月が綺麗ですね」がヒットするような機能を、今開発中のアプリに実装したいと思って調べてみました!
普通のキーワード検索では、「月が綺麗ですね」という言葉には「告白」という文字が一切含まれていないのでヒットしません。
でも、「月が綺麗ですね」=夏目漱石が「I love you」と訳した有名なエピソードを知っている我々の脳内では、簡単に結びつけることができますよね。
これをどうやってアプリの検索機能として実装できるのか、検索技術を4つ調べて比較してみました!
検索技術の比較をしてみた
検索の方法を「図書館で本を探す」イメージで説明しつつ、裏側のアルゴリズムも調べてみました。
手法 | 例えると… | 技術的な中身 | 強み | 弱み |
---|---|---|---|---|
キーワード検索(BM25など) | 「"告白"って書いてある本を持ってきて!」 | TF-IDF / BM25 アルゴリズムで単語の出現頻度をスコア化 | 速くてシンプル、導入容易 | 「月が綺麗ですね」はスルー(単語が無いから) |
同義語展開検索 | 「告白=愛の言葉=プロポーズ も探して!」 | シノニム辞書でクエリを展開、全文検索に流す | 言い換え表現に強い | 辞書の網羅性次第。文化的婉曲表現は難しい |
ベクトル検索(埋め込み検索) | 「"愛してるっぽい雰囲気"の本を探して!」 | 文章を埋め込みベクトル化し、類似度(コサイン距離など)で検索 | 言い回しや表記揺れに強い。最新モデルなら文化的文脈もある程度理解できる! | 短文はブレやすい。モデル依存性あり |
タグ検索(AIラベル付け) | 本を登録する時に「これは告白!」シールを貼っておく | 登録時にLLMで「告白/皮肉/説教/感謝」などのタグを生成しDBに保存 | 意味で検索可能。文化的背景も確実に反映できる! | タグ付けの精度が命。大規模だと運用コスト高い… |
実際の挙動を試してみたイメージ
キーワード検索(BM25)
SELECT * FROM phrases WHERE content @@ to_tsquery('告白');
- ✅ 「好きです」「告白します」はヒット
- ❌ 「月が綺麗ですね」は出ない(当然ですよね…)
同義語検索
-- "告白"を"愛の言葉 OR プロポーズ OR 告白"に展開
SELECT * FROM phrases WHERE content @@ to_tsquery('告白 | 愛の言葉 | プロポーズ');
- ✅ 「愛してる」「結婚してください」はヒット
- ❌ それでも「月が綺麗ですね」は出ない(婉曲表現までは無理でした)
ベクトル検索(pgvector)
SELECT content
FROM phrases
ORDER BY embedding <-> embedding('告白のセリフ')
LIMIT 5;
- ✅ 「好き」「愛してる」は近いので出る
- ⚠️ 「月が綺麗ですね」は、GPT-4以降の大規模埋め込みモデルならある程度捉えられるみたい!(でも100%確実ではないですね)
タグ検索(AIラベル付け)
登録時にAIでタグ付けしておく:
{
"speech_act": "告白",
"tone": "ロマンチック",
"style": "婉曲表現"
}
検索時はタグに基づいて検索:
SELECT * FROM phrases WHERE ai_tags @> '{"speech_act":"告白"}';
- ✅ 「月が綺麗ですね」が確実に出る!(これは強い)
- ⚠️ 大量コンテンツでは初期コスト+継続的な精度管理が必要みたいです
さらに調べたら「ハイブリッド検索」というのがあった!
実際の本番環境では、単一の手法に頼るのではなく、複数の検索技術を組み合わせるハイブリッド検索が主流らしいです!
ハイブリッド検索の実装例を見つけました
def hybrid_search(query, weights={'vector': 0.5, 'tag': 0.3, 'keyword': 0.2}):
# 1. ベクトル検索でセマンティックな類似度を計算
vector_results = vector_search(query)
# 2. タグ検索で意味的に正確なマッチを取得
tag_results = tag_search(query)
# 3. キーワード検索で直接的な一致を補完
keyword_results = keyword_search(query)
# 重み付けして統合
return merge_results(vector_results, tag_results, keyword_results, weights)
ハイブリッド検索のメリットがすごかった
- 精度向上:各手法の長所を活かし、短所を補完できる
- 安定性:単一手法の失敗に対してロバスト
- 柔軟性:コンテンツやユースケースに応じて重みを調整可能
段階的に実装する戦略も調べてみた!
Phase 1: タグ検索でスタート(確実性重視)
- AIによるタグ付けで文化的文脈も確実に捉える
- 「月が綺麗ですね」を確実に「告白」として検索可能に
- 初期の品質を最優先
Phase 2: スケール対応
- コンテンツ量が増えてきたらベクトル検索を追加
- 新規コンテンツはベクトル検索メイン+重要なものだけタグ付け
Phase 3: ハイブリッド最適化
- タグ検索+ベクトル検索を組み合わせて精度と効率を両立
- ユーザーのフィードバックを元に重みを調整
調べた結果わかったこと!
「月が綺麗ですね」を「告白のセリフ」で検索できるようにするには…
👉 タグ検索(AIによる意味ラベル付け)から始めるのがベスト!
👉 スケールが必要になったらベクトル検索を追加してハイブリッド化
とのことでした!
各手法をまとめると:
- キーワード検索 → 文字が無いのでNG(ただし直接的な表現には強い)
- 同義語検索 → 辞書を作っても"婉曲表現"までは難しかった
- ベクトル検索 → 最新モデルなら文化的文脈もある程度理解できるみたい!ただし100%ではない
- タグ検索 → 「これは告白」と最初にAIが理解してシールを貼るから最も確実! ← これから始める!
- ハイブリッド検索 → タグ検索が軌道に乗ったら、ベクトル検索を追加して進化させる 🎯
おわりに
検索技術は「文字」から「意味」へ進化していることがわかりました!
特に日本語は遠回しや文化的背景が多いため、まずはタグ検索で意味を確実に捉えるところから始めて、必要に応じてベクトル検索を追加してハイブリッド化していくのが良さそうです。
「まず動くものを作る」という意味でも、確実性の高いタグ検索から始めるのが正解っぽいですね!
早速タグ検索の実装から開発を始めます!🚀
Discussion