Databricks Apps + Vector Search + AI関数で作る「名言レコメンダー」(第4回:発展編)
はじめに
前回は、アプリをDatabricks Appsにデプロイする方法を解説しました。
最終回となる今回は、アプリをさらに良くするための発展的なトピックを扱います。検索タイプの比較とフィルタ機能の活用について解説します。

アプリの左サイドバーは「設定」と「フィルター」の2つのセクションに分かれています。
設定セクション:
| 設定項目 | 説明 |
|---|---|
| 検索タイプ | ann / hybrid / FULL_TEXT から選択(デフォルト: ann) |
| 表示件数 | 最終的に画面に表示する件数(1〜50) |
| 取得列 | 取得するカラムをカンマ区切りで指定 |
フィルターセクション:
| 設定項目 | 説明 |
|---|---|
| helpful下限 | いいね数でフィルタリング(この数以上の名言のみ表示) |
| ドラマで絞り込み | 特定のドラマの名言のみ表示(複数選択可、未選択ですべて表示) |
その他のオプション:
| 設定項目 | 説明 |
|---|---|
| 結果を表で表示 | ONにすると検索結果をDataFrame形式のテーブルで表示。データ全体を俯瞰したい場合に便利 |
| 生レスポンス表示 | ONにするとVector Search APIの生レスポンスを表示。デバッグやスコア確認に使用 |
1. 検索タイプの比較
Vector Searchには3つの検索タイプがあります。アプリのサイドバーにある「検索タイプ」ドロップダウンから切り替えられます。それぞれの特性を理解し、ユースケースに応じて使い分けましょう。
1.1 各検索タイプの特徴
| タイプ | 検索方式 | 特徴 |
|---|---|---|
ann |
ベクトル類似度検索 | 意味的な類似性を重視。「疲れた」→「休息」「癒し」系の名言がヒット |
hybrid |
ベクトル + キーワード | 両方のスコアを組み合わせ。バランスの取れた結果 |
FULL_TEXT |
キーワード全文検索 | 特定の単語を含む結果を優先。「love」→「love」を含む名言 |
1.2 実際の検索結果比較
同じクエリ「友情について」で検索した場合の違いを見てみましょう。
ann(ベクトル検索)の結果:

→ 「友情」という単語がなくても、意味的に関連する名言がヒット
FULL_TEXT(全文検索)の結果:

→ 「friend」「friendship」を含む名言が優先的にヒット
hybrid(ハイブリッド)の結果:

→ 両方の特性を兼ね備えた結果
1.3 検索タイプの選び方
| ユーザーの入力パターン | 推奨タイプ |
|---|---|
| 感情・気分(「疲れた」「嬉しい」) | ann |
| 特定キーワード(「love」「勝利」) | FULL_TEXT |
| 両方混在 or 不明 | hybrid |
2. フィルタ機能の活用
Vector Searchのフィルタ機能を使うと、ベクトル検索にメタデータ条件を追加できます。アプリのサイドバーにある「フィルター」セクションで、いいね数やドラマ名による絞り込みが可能です。
2.1 アプリでの処理フロー
アプリでは以下の順序でフィルタと絞り込みを行っています:
1. Vector Searchから多めに取得(200件)
↓
2. helpful >= 指定値 でフィルタ
↓
3. series_name でフィルタ(選択時のみ)
↓
4. スコア順にソート
↓
5. 表示件数に絞り込んで表示
この処理は以下のようなコードで実装されています:
# 1. Vector Searchから多めに取得(フィルタなし)
INTERNAL_FETCH_K = 200
resp = query_vector_search(
w=w,
index_name=INDEX_NAME,
query_text=q,
num_results=INTERNAL_FETCH_K,
columns=columns,
query_type=query_type,
filters_json=None,
)
df = response_to_df(resp)
# 2. クライアント側でフィルタを適用
# helpful フィルタ
if "helpful" in df.columns and int(min_helpful) > 0:
df = df[df["helpful"] >= int(min_helpful)]
# series_name フィルタ
if selected_series and "series_name" in df.columns:
df = df[df["series_name"].isin(selected_series)]
# 3. スコア順にソート
df = df.sort_values(by=["score", "helpful"], ascending=[False, False])
# 4. 表示件数に絞り込む
df = df.head(int(num_results))
この順序にすることで、フィルタ条件を厳しくしても十分な検索結果を確保できます。
なお、ドラマ名の選択肢はソーステーブルから動的に取得しています。初回読み込み時に1時間キャッシュされるため、パフォーマンスへの影響は最小限です。
@st.cache_data(ttl=3600) # 1時間キャッシュ
def get_series_names() -> List[str]:
"""ソーステーブルからドラマ名一覧を取得"""
sql_text = f"""
SELECT DISTINCT series_name
FROM {VS_SOURCE_TABLE}
WHERE series_name IS NOT NULL
ORDER BY series_name
"""
# ...
2.2 アプリでの活用例
サイドバーのフィルター設定を使うことで、様々な絞り込みが可能です:
- 人気の名言だけ見たい → 「helpful下限」を上げる
- 好きなドラマから探したい → 「ドラマで絞り込み」で選択
- 組み合わせ → 「Friendsの人気名言だけ」など
まとめ
全4回にわたり、Databricks Apps + Vector Search + AI関数を使った名言レコメンダーアプリの構築を解説しました。
シリーズ振り返り:
| 回 | 内容 |
|---|---|
| 第1回 | データ準備、Vector Searchインデックス作成 |
| 第2回 | Streamlitアプリの実装、認証処理、API呼び出し |
| 第3回 | Databricks Appsへのデプロイ、Asset Bundles設定 |
| 第4回 | 検索タイプ比較、フィルタ活用 |
このシリーズで学んだこと:
- Mosaic AI Vector Searchによるセマンティック検索
- AI関数(ai_gen)による動的コンテンツ生成
- Databricks Appsでのアプリホスティング
- Asset Bundlesによるデプロイ管理
ぜひ、この構成をベースに独自のレコメンダーアプリを作ってみてください!
参考リンク
リポジトリ
本シリーズで作成したコードは以下のリポジトリで公開しています。
(リポジトリURL)
Discussion