---
title: 音楽ストリーミングの DJ
sidebarTitle: 音楽 DJ
description: 音楽ストリーミングアプリの新規かつ低リスクな DJ 機能を、ほぼ即座に本番投入し、リスナーの視聴行動から改善していく例です。
translatedAt: 2026-08-19
---

# 音楽ストリーミングの DJ

  これは [Langfuse Academy](/academy/japan) の概念を説明するための例です。

## 背景

ある音楽ストリーミングアプリが、DJ 機能をベータとして追加します。
DJ は、ユーザーがこれまでに再生した曲と、アルゴリズムがユーザーの好みだと判断したものをもとに、キューを途切れさせずに回し続けます。
数曲おきに、次にかかる曲とその選曲理由について短くコメントします。
リスナーはマイクボタンを押して話しかけることで、DJ に方向性を指示することもできます。

AI エンジニアリングの構成をどう組むかは、2 つの特徴から決まります。

1. **出力が悪かったときのリスクが低い。** 最悪でも曲がスキップされるか、DJ のコメントがぎこちない程度で、機能はベータと明示されています。
2. 新機能なので **出発点となる過去データがない。** チームはリスナーの実際の行動から学んでいく必要があります。

このため、できるだけ早く本番に出し、[最初からライブのフィードバックをもとに反復する](/academy/japan/ai-engineering-loop#you-dont-have-to-close-the-full-loop-on-day-one) のが理にかなっています。

## DJ のトレーシング

2 種類の [トレース](/academy/japan/tracing#anatomy-of-a-trace) があり、これらが合わさって [1 つのセッションを構成](/academy/japan/tracing#traces-vs-sessions) します。

| トレース名          | 詳細                                                                                                                                                                                                                       |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `plan-next-set`     | 次にかける曲のセットを組み立て、コメントを書きます。数曲おきに DJ 自身が開始するか、DJ への依頼をきっかけに開始します。<br />**入力:** 視聴コンテキストと、あれば指示<br />**出力:** キューに入れた次の曲と、コメント 1 行 |
| `handle-dj-request` | リスナーからの音声依頼を処理します。マイクボタンで開始します。<br />**入力:** 音声クリップと現在のキュー<br />**出力:** 短い返答と、これが起動する `plan-next-set` への指示                                                |

視聴セッションと、2 種類のトレースを近くで見てみます。

<Tabs
  items={[
    "セッションの例",
    "plan-next-set トレースの例",
    "handle-dj-request トレースの例",
  ]}
>
<Tab>

**セッション listen_7f3e · ユーザー u_8841**

- [Trace] `plan-next-set` (2.8s)
  - 「今週よく聴いた 2 曲から始めます。」
- [Trace] `plan-next-set` (2.4s)
  - 「この流れのまま、少し落ち着いたエレクトロニカで。」
- [Trace] `handle-dj-request` (1.6s)
  - 「もう少し落ち着いた曲をかけて。」
- [Trace] `plan-next-set` (dj-request 起点, 1.5s)
  - 「少し落ち着いた流れにします。アンビエントピアノをどうぞ。」

</Tab>
<Tab>

**plan-next-set トレースの中にあるオブザベーション**

- [Trace] `plan-next-set` (session: listen_7f3e, user: u_8841, 1.5s)
  - 入力: 好み: エレクトロニカ, ダウンテンポ · 直近の再生: アーティストA「曲名1」, アーティストB「曲名2」 · 指示: "もっと落ち着いた曲"
  - 出力: 4 曲をキューに追加 · コメント: 「少し落ち着いた流れにします。アンビエントピアノをどうぞ。」
  - [Tool] `select-tracks` (0.6s)
    - 入力: 好み: エレクトロニカ, ダウンテンポ · 直近の再生: アーティストA「曲名1」, アーティストB「曲名2」 · 指示: "もっと落ち着いた曲"
    - 出力: アーティストD「曲名4」· アーティストE「曲名5」· アーティストF「曲名6」· アーティストG「曲名7」
  - [Gen] `write-commentary` (gpt-4.1-mini, 120 tok, $0.0002, 0.9s)
    - 入力: 選ばれた 4 曲 · 指示: "もっと落ち着いた曲"
    - 出力: 「少し落ち着いた流れにします。アンビエントピアノをどうぞ。」

</Tab>
<Tab>

**handle-dj-request トレースの中にあるオブザベーション**

- [Trace] `handle-dj-request` (session: listen_7f3e, user: u_8841, 1.6s)
  - 入力: 音声クリップ (2 秒)
  - 出力: 返答: 「了解です、落ち着いた流れにしますね。」 · 指示: "もっと落ち着いた曲"
  - [Tool] `transcribe-request` (0.4s)
    - 入力: 音声クリップ (2 秒)
    - 出力: 「もう少し落ち着いた曲をかけて。」
  - [Gen] `interpret-request` (gpt-4.1-mini, 210 tok, $0.0004, 1.2s)
    - 入力: 「もう少し落ち着いた曲をかけて。」 · 現在のキュー
    - 出力: 返答: 「了解です、落ち着いた流れにしますね。」 · 指示: "もっと落ち着いた曲"
  - [Event] `trigger-plan-next-set` (@ 1.6s)
    - 入力: 指示: "もっと落ち着いた曲"

</Tab>
</Tabs>

## ユーザーの行動を捕捉する

ユーザーから学ぶために、[注目すべき行動](/academy/japan/monitoring#user-feedback) を該当するトレースに記録します。

**評価者**

- `track_skipped` — プレイヤーのイベント, 二値とコメント。plan-next-set トレースに付与
  - DJ が選んだ曲を、再生開始直後にリスナーがスキップした
  - 評価器は不要で、プレイヤーがスコアを書き込みます。スコアは常に、その瞬間に再生されていたセットの `plan-next-set` トレースに付きます。コメントにはどの曲がスキップされたかが入るため、 外しの多いセットには複数のスコアが集まります。
- `dj_replaced` — プレイヤーのイベント, 二値。セッションに付与
  - リスナーが DJ をオフにしたが、視聴自体は続けている
  - 単にセッションが終わったことは、ほとんど何も語りません。リスナーは目的地に着いただけかもしれないからです。DJ なしで聴き続けたことがシグナルになります。リスナーが DJ ではなく音楽を選んだということです。
- `message_type` — LLM-as-a-Judge, カテゴリ。handle-dj-request トレースに付与
  - 音声依頼を `steering`、`correction`、 `repeated_instruction`、`positive_reaction`、 `negative_reaction` のいずれかに分類します
  - `steering` はこの機能の通常の使い方であり、失敗の集計には含めません。 `correction` は DJ の直前の動作が外したことを意味します。 `repeated_instruction` は、すでに受け取った指示に DJ が従えなかったことを意味します。好みの読み違いではなく指示違反であり、 [必要な手当ても変わってきます](/academy/japan/evaluate/choosing-what-to-evaluate#tie-every-metric-to-a-decision) 。またここで唯一 LLM のコストがかかるシグナルでもありますが、音声依頼はトラフィックのごく一部なので、 [評価器のコスト](/academy/japan/evaluate/choosing-what-to-evaluate#mind-the-budget) は小さく収まります。

原理的には、これだけあればチームはもう反復を始められます。
トレーシングと [モニタリング](/academy/japan/monitoring#metrics-and-signals) だけで、それ自体が小さなループを形成するからです。
最初のうちは、DJ 機能をすばやく改善していくにはおそらくこれで十分です。

**AI エンジニアリング・ループ**

- **トレース** — すべてのセットとすべての依頼
- **モニタリング** — スキップ、dj_replaced、message_type
- **データセット構築** — まだ使わない
- **実験** — まだ使わない
- **評価** — まだ使わない

構成が成熟し、より体系的なテストを整えたくなったら、これらのシグナルの上にデータセットと実験を組み立てていけます。

## 体系的なテスト

ライブのシグナルだけの状態では、変更をテストするということはリリースしてスコアを見ることを意味します。
チームはさらに 2 つの意図的なテスト方法を追加できます。[データセットに対する実験](/academy/japan/experiments#how-experiments-are-used) と、実ユーザーに対する A/B テストです。

### データセットに対する実験

このユースケースでは、エンドツーエンドをオフラインでテストするのは非常に困難です。
セッションが良かったかどうかは実際の視聴行動にしか現れず、好みはユーザーごとに違うため、全員に当てはまる期待出力が存在しないからです。
一方で `select-tracks` のような [単一のステップ](/academy/japan/datasets#what-makes-a-good-dataset) はテストできます。期待値として、正確な曲目ではなくセットの方向性を記述します。

**データセット: selection-directions**

視聴コンテキストと、次のセットとして良い方向性・悪い方向性を組にしたもの。select-tracks ステップだけをテストします。

| 入力 | 期待される出力 |
| --- | --- |
| 好み: インディーフォーク · 直近の再生: アーティストH「曲名8」, アーティストI「曲名9」 · 指示: なし | 良い方向性: 近接するインディーフォーク、ソフトロック。悪い方向性: 高テンポの EDM、ヒップホップ。 |
| 好み: エレクトロニカ, ハウス · 直近の再生: アップテンポなハウスのセット · 指示: 「もう少し落ち着いた曲を」 | 良い方向性: ダウンテンポ、アンビエント・エレクトロニカ。悪い方向性: さらにアップテンポなハウス、指示の無視。 |

**評価者**

- `direction_match` — LLM-as-a-Judge, 二値。データセットアイテムごと
  - 選ばれたセットは、良い方向性のいずれかに沿っていて、悪い方向性を避けているか?
  - [参照あり](/academy/japan/evaluate#reference-based-vs-reference-free) の評価器です。期待出力が、採点の基準となる方向性を与えます。DJ 全体ではなく `select-tracks` ステップだけで動くため、1 回の実行が安く、失敗したときは選曲が原因だとすぐ分かります。

### 実ユーザーに対する A/B テスト

コメントのトーンのように、オフラインでは採点しにくい変更もあります。
リスクが低いので、チームは一部のリスナーに新バージョンを提供し、スキップ率や `message_type` の分布といったシグナルのスコアをグループ間で比較できます。
新バージョンのほうが良ければ、全体に展開します。

ここまでそろうと、ループ全体が回っている状態になります。

**AI エンジニアリング・ループ**

- **トレース** — すべてのセットとすべての依頼
- **モニタリング** — スキップ、dj_replaced、message_type、A/B 比較
- **データセット構築** — 本番のモニタリングで見えたものから
- **実験** — 選曲アルゴリズム、DJ のプロンプト、…
- **評価** — ステップの出力を期待値に照らして採点

## まとめ

これは、リスクが低く、学習に使える過去データもない機能の例です。
こうした場合に取れる最善の手は、できるだけ早くトレースを取り始め、それをモニタリングすることです。
データセット、実験、A/B テストといった残りは、その上に時間をかけて積み上げていけます。

[他の例](/academy/japan/examples) や [Academy](/academy/japan) も参照してみてください。

<!-- agent-instructions -->

---

## Agent Instructions

This page is part of the [Langfuse](https://langfuse.com) documentation, published as plain Markdown for AI agents. Every page is available as Markdown by appending `.md` to its URL, or by sending an `Accept: text/markdown` header. This page: `https://langfuse.com/academy/japan/examples/music-streaming-dj.md`.

### Querying these docs

If the answer is not on this page, query the documentation instead of guessing:

- **Semantic search** across all Langfuse docs, returning an answer with the relevant pages and excerpts. Ask a specific, self-contained question:

  ```bash
  curl -sG "https://langfuse.com/api/search-docs" --data-urlencode "query=How do I trace a LangGraph agent?"
  ```

- **Index of every page**: <https://langfuse.com/llms.txt>, with per-section indexes [llms-docs.txt](https://langfuse.com/llms-docs.txt), [llms-integrations.txt](https://langfuse.com/llms-integrations.txt), and [llms-self-hosting.txt](https://langfuse.com/llms-self-hosting.txt).

### Before writing Langfuse code

- **Install the [Langfuse Agent Skill](https://langfuse.com/docs/api-and-data-platform/features/agent-skill).** It encodes Langfuse's own best practices for instrumentation, prompt management, and evaluation, and materially improves results.
- **Read [What does a good trace look like?](https://langfuse.com/docs/observability/best-practices.md)** before instrumenting an application.
- **Verify endpoints, parameters, and response fields** against the [API reference](https://api.reference.langfuse.com) instead of inferring them from code examples.
- **Use the [Langfuse CLI](https://langfuse.com/docs/api-and-data-platform/features/cli)** (`npx langfuse-cli api <resource> <action>`) to read or write traces, prompts, datasets, and scores from the terminal.

Found an error in these docs? Please open an issue at <https://github.com/langfuse/langfuse-docs/issues>.
