作品詳細を「行き止まり」にしない — 「この作品が好きな人へ」で、次の一本へ送る
はじめに
自作の映像・音楽プラットフォームで、作品の詳細ページに「この作品が好きな人へ」という似た作品の一覧を足した。今見ている作品に近いものを、詳細の下に並べる機能だ。
技術の芯は、意味検索のために作った索引の使い回しにすぎない。専用のベクトルDBを足さずに意味検索を実装した話は 「字面」でなく「意味」で探す に書いた。この記事はそこではなく、その索引を「詳細ページの回遊」にどう効かせ、かつ本体を壊さずに足したかという設計の話だ。

作品詳細は、行き止まりになりやすい
カタログを見て回る体験では、利用者は一覧から詳細へ入り、そこで「借りるか、やめるか」を決める。問題は、「これは違うかな」となったときだ。詳細ページに次の手がかりが無ければ、利用者は一覧まで戻るか、そのまま離脱する。
詳細ページは、放っておくと行き止まりになる。せっかく一作に興味を持って踏み込んでくれた人を、次の候補に出会わせないまま帰してしまう。
【行き止まり】一覧 ─▶ 詳細 ─(刺さらない)─▶ 戻る/離脱 … 次に出会わない
【回遊】 一覧 ─▶ 詳細 ─(刺さらない)─▶ 似た作品 ─▶ 次の詳細 ─▶ …
└───────── 回遊が続く
やりたいのは、詳細の一番下に「じゃあ、これはどう?」を必ず置くこと。次の一本を、目の前に差し出すことだ。
同じ索引を、「この作品に似た作品」の顔で引く
ここで、意味検索のために作った索引がそのまま効く。全作品はすでに 意味ベクトル(作品の内容を数値の並びにしたもの。近い内容どうしはベクトルも近い)になっている。意味検索は「クエリ文のベクトル」に近い作品を返した。似た作品は、クエリが文ではなく”今見ている作品そのもの”になるだけだ。今の作品のベクトルを索引に問い合わせ、近い順に返す。入口が違うだけで、走る仕組みは意味検索と同じ一つの関数だ。
そして、ただ並べるのではなく 類似度(%) を各作品に添えた。「なぜこれを薦めるのか」を、数字で見せる。推薦がブラックボックスだと「なぜこれ?」と不信を招くが、近さを見せれば納得して次へ進める。
// 基準作品のベクトルに近い作品を、近い順に返す(この作品が好きな人へ)
List<Map.Entry<Integer, Double>> ranked = index.topSimilar(baseVector, limit * 4 + 1);
for (var entry : ranked) {
if (entry.getKey() == filmId) continue; // 自分自身は除外
var film = filmMapper.selectById(entry.getKey());
if (film == null) continue;
if (baseIsCd != (film.artist() != null)) continue; // 同じメディア種別だけ(後述)
items.add(Map.of("film", film, "score", round(entry.getValue()))); // 類似度つき
}
意味検索・おすすめ・この機能は、同じ索引の三つの顔だ。同じ索引を「履歴の重心」で引けば「あなたへのおすすめ」になる話は 視聴履歴の「重心ベクトル」で、おすすめを作る に書いた。
推薦は、本体を壊してはいけない
ここが、この機能で一番気をつけたところだ。推薦はあくまで付加情報であって、詳細ページの主役ではない。
似た作品の計算は、失敗しうる。作品のベクトルがまだ生成されていなければ結果は0件になるし、内部の呼び出しがエラーを返すこともある。このとき、推薦の失敗が詳細ページ本体を巻き込んで壊すのは最悪だ。利用者は作品を見に来たのであって、推薦を見に来たのではない。
だから、推薦セクションは「あれば嬉しい、無くても困らない」に徹させた。0件やエラーのときは、セクションごと黙って消える。詳細ページ本体(あらすじ・レンタル情報・予約ボタン)は、推薦が出ても出なくても常に無傷だ。
詳細ページ本体(あらすじ・レンタル情報・予約) ← 常に表示・推薦の成否に依存しない
└─ この作品が好きな人へ(付加情報)
├─ 結果あり ─▶ 出す
├─ 0件(ベクトル未生成)─▶ セクションごと非表示
└─ API失敗 ─▶ セクションごと非表示(本体は壊さない)
もう一つ、同じメディア種別のものだけを出すようにした(映像の詳細に映像、CDの詳細にCD)。意味の近さだけで引くと、映像を見ているのに音楽CDが「似ている」として紛れ込む。この「意味が近い=出してよい、ではない」という埋め込みの素直さの罠は ベクトル検索は「意味が近い」を勝手に混ぜてくる にまとめた。付加情報だからこそ、余計なものを出して詳細ページの筋を濁さない。
推薦は主役ではなく、次への橋
作ってみて腹落ちしたのは、この機能の価値は「賢い推薦」そのものではない、ということだ。価値は、行き止まりだった詳細ページに、次への橋を一本架けたことにある。
- 回遊は、賢いアルゴリズムより先に、「次を置く」という一手で生まれる。目の前に候補があるかどうかが、戻るか進むかを分ける。
- そして橋は、渡れなくても本体を壊さない。推薦が0件でも失敗でも、詳細ページはそのまま立っている。付加情報は、主役の邪魔をしない範囲でだけ足す。
同じ索引を、検索にも、おすすめにも、この回遊にも使い回せた。だが機能ごとに違ったのは、アルゴリズムではなく置き方の作法だった。検索は主役として前に出し、この推薦は脇役として詳細の邪魔をしない。同じ道具でも、主役か脇役かで設計は変わる——それが、この機能で学んだことだった。
関連する記事
- この推薦が使い回している意味ベクトルの索引そのものは 「字面」でなく「意味」で探す — 専用のベクトルDBを足さずに意味検索を実装する に書いた。
- 同じ索引を「履歴の重心」で引く三つ目の顔(あなたへのおすすめ)は 視聴履歴の「重心ベクトル」で、おすすめを作る にまとめた。
- 意味が近いだけの別メディアが紛れ込む罠と、出口での塞ぎ方は ベクトル検索は「意味が近い」を勝手に混ぜてくる — 種類の違うカタログが推薦に紛れ込む罠 に書いた。