🙆

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)


前回:第3回 デプロイ編
シリーズ一覧:第1回 | 第2回 | 第3回 | 第4回(本記事)

Discussion