Difyチャットボットの品質をシナリオテストで計測する
やったこと
Difyで構築したチャットボットに対して、マルチターンの会話シナリオを設計・自動実行し、応答品質を定量的に計測してみました。
チャットボットを作っていると、"シングルターン(1問1答)では問題なく動いているように見えるけど、マルチターン(3〜4ターンの会話)になると品質が大きく下がる" ということによく遭遇します。そこで、マルチターンのシナリオと期待する回答を作って、DifyのAPIに一気に投げて自動テストを作った、という話です。
背景: 既存ツールの評価機能と、残るギャップ
Difyには複数のオブザーバビリティ・評価ツールが公式に統合されています。これらのツールはトレーシングだけでなく、評価機能も持っています。
| ツール | 評価機能 |
|---|---|
| LangSmith | Datasets + Evaluators、LLM-as-Judge、human feedback |
| Langfuse | Datasets、LLM-as-Judge、human feedback、カスタムスコア |
| Opik | LLM-as-Judge、8種の会話専用メトリクス、データセット評価 |
| Arize AX | LLM-as-Judge、Session Evals、human annotation |
| Phoenix | LLM-as-Judge、Evaluator Hub |
これらのツールは、例えばデータセット({input, expected_output} のペア集合)に対してアプリケーションを実行し、変更前後のスコアを比較する機能を持っています。しかし、どうやらマルチターンの会話シナリオを用意して品質をチェックする機能は、どのツールにもないようでした。
やりたいこと
以下のようなことがやりたいと考えていました。
- マルチターンの会話を評価したい: 複数ターンの会話全体をテスト対象にして、文脈保持や情報の一貫性なども含めて品質を検証したい
- 会話の流れに応じた分岐も設計したい: ユーザーの次の質問が、ボットの前の回答によって変わるようなシナリオも作りたい
- 各ターンの応答をLLM-as-Judgeで評価したい: シナリオを実行した後、各ターンの応答に対して意味的正確性や文脈保持などの評価軸でスコアリングしてほしい
- 自動で何度も実行できるようにしたい: 手動で会話をするのではなく、シナリオを定義しておいて、何度も自動で実行できるようにすることで、単発のテストでは見えない品質の問題を継続的に検出できるようにしたい
- DifyのDSLからシナリオを自動生成したい: 自動テストができてもシナリオを作ることがボトルネックになっては意味がないため、すでに構築済みのDifyアプリのフロー定義(YAML)を貼り付けるだけで、その構造を解析してシナリオを自動生成してほしい
そして、上記を実現できるツールを当初は自分用に作り、ゴリゴリ使っていたのですが、思いのほか使いやすいものになったこと、同じようなニーズを持っている人は他にもいることから、ConvoProbe として公開することにしました。
Difyコミュニティでの品質評価の扱われ方について: 他の人がどうやって品質を担保しているのか、Difyフォーラムと GitHub Discussions を調べてみました。結果は意外なものでした:
調査対象 件数 チャットボット品質評価に関するフォーラム投稿 0件 テスト・検証に関するGitHub Discussions 3件 アップデート後のリグレッションに関するIssues 211件 オブザーバビリティ・トレーシングに関するIssues 524件 オブザーバビリティやリグレッション(品質劣化)の話題は豊富にあるのに対し、「体系的に品質を評価する」という話題はほとんど議論されていません。
ConvoProbeでできること
1. マルチターンの会話を評価できる
ConvoProbeは、複数ターンにわたる会話全体を評価対象にします。
シングルターン(1問1答)のテストでは、個々の回答の正確性は確認できます。しかし実際のチャットボットでは、3〜4ターン目になると文脈を見失ったり、情報が混ざったりする問題が起きます。ConvoProbeでは「ターン4でターン1の内容を正しく参照しているか」といった、会話の流れに依存する品質を検証できます。
2. 会話をシナリオとしてGUIで設計できる
「ユーザーが何を言い、ボットが何を返すべきか」という会話の構造をGUI上で組み立てられます(それこそDifyのように)。各ターンにユーザーの発言と期待する回答を設定していきます。
3. 会話の流れに応じた分岐も設計できる
実際の会話は一直線ではありません。ユーザーの次の質問は、ボットが何を言ったかによって変わります。
ConvoProbeはシナリオ実行時にボットの応答をLLMで判定し、次のターンへの分岐を動的に決定します。
静的なデータセット評価では、このような「ボットの出力に依存する分岐」は表現できません。
4. DifyのDSLからシナリオを自動生成できる
DifyアプリのDSL(YAML形式のフロー定義)をConvoProbeに貼り付けると、そのフロー構造を解析してテストシナリオを自動生成します。
ゼロからシナリオを考える必要がなく、すでに構築済みのDifyアプリに対してすぐにテストを始められます。生成されたシナリオはそのまま実行することも、GUIで編集して使うこともできます。
5. 各ターンの応答をLLM-as-Judgeで評価できる
シナリオを実行すると、各ターンの応答が以下の評価軸で自動的にスコアリングされます。
| 評価軸 | 内容 |
|---|---|
| 意味的一致度 | 実際の回答が期待される意味・情報を伝えているか? |
| 網羅性 | 実際の回答が期待回答で言及されているすべてのキーポイントをカバーしているか? |
| 正確性 | 実際の回答に含まれる情報は事実として正しいか? |
| 関連性 | 実際の回答は質問に対して直接的に関連しているか? |
また、全ターンを総合的な観点で評価し、評価スコアとして表示します。
シナリオテストで見えてくること
ConvoProbeを使ってマルチターンのシナリオテストを実行してみると、以下のような品質の問題が見えるようになります。
マルチターンで品質が落ちる
シングルターンのテストでは問題なく動いているように見えるチャットボットでも、3〜4ターンの会話になると品質が落ちるケースがあります。特にRAGを使ったチャットボットは、会話が進むにつれてどの情報を参照すべきかの判断がブレやすくなります。
シングルターンだけでテストしていると、このような品質劣化を見逃しがちです。
文脈の喪失は無音で起きる
ボットが会話履歴を「忘れた」とき、クラッシュやエラーは発生しません。もっともらしく聞こえるが間違った回答が生成されるだけです。
「ターン4でターン1の内容を正しく参照しているか」を検証するには、そのような会話フローを意図的にシナリオとして設計して実行する必要があります。
ワークフロー更新でリグレッションが起きる
Difyのワークフローを更新した後、それまで問題なく動いていた会話パターンが崩れることがあります。システムプロンプトの変更やRAG検索パラメータの調整は、意図しない動きを生むことがあります。
変更前後で同じシナリオを実行してスコアを比較することで、本番に入れる前に劣化を検知できます。
既存ツールとの使い分け
ConvoProbeはLangfuseやLangSmithの代替ではなく、補完するイメージを持っています。
| フェーズ | ツール | 役割 |
|---|---|---|
| 開発・変更時 | ConvoProbe | シナリオテスト → 本番に入れても安全かを事前検証 |
| リリース前 | ConvoProbe | 変更前後のシナリオスコアを比較(回帰テスト) |
| 本番運用 | Langfuse / LangSmith / Opik | トレーシング、コスト監視、本番会話の事後評価 |
| 本番で問題発見時 | ConvoProbe | 問題を再現するシナリオを作成 → 修正後に再テスト |
Langfuseで問題を「発見」し、ConvoProbeで「再発防止」する形です。
試してみてください
ConvoProbeはDifyのAPIキーと評価用のLLM APIキーを設定するだけで使い始められます。
