OpenEvals × Langfuseで始めるAIエージェントのマルチターン評価
AI Shift Tech Blogは、OpenEvalsとLangfuseを組み合わせてAIエージェントのマルチターン対話を評価する実践的なパイプラインを紹介し、データセット準備からシミュレーション、LLM-as-a-judgeによる評価までの具体的な手法をコード付きで解説している。
キーポイント
マルチターン評価の必要性
AIエージェントの評価は一問一答形式では不十分であり、マルチホップ・マルチターンを前提とした評価手法が重要であると指摘している。
評価パイプラインの3ステップ
Langfuseでのデータセット準備、OpenEvalsによる仮想ユーザーとの対話シミュレーション、Langfuseでの実験管理とLLM-as-a-judge評価という3段階の実践的な評価フローを構築している。
具体的な評価観点
Actionability(実行可能性)、Adaptability(適応性)、Coherence(一貫性)の3観点で1-5スケールのルーブリック評価を実施し、対話は最大3ターンに制限している。
実装コードの公開
評価システムの実装コードをGitHubリポジトリで公開しており、読者が実際に試せる実用的な内容となっている。
影響分析・編集コメントを表示
影響分析
この記事は、AIエージェント開発における評価の実践的な課題に具体的な解決策を提供しており、特に中小規模の開発チームが評価インフラを構築する際の参考になる。既存ツールの組み合わせ方や評価観点の設定方法を示すことで、AIエージェントの品質保証プロセスの標準化に貢献する可能性がある。
編集コメント
理論だけでなく実際のコード例まで示した実践的なチュートリアル記事。評価観点の具体例が開発現場で即活用できる内容となっている。
OpenEvals × Langfuseで始めるAIエージェントのマルチターン評価
こんにちは、AIチームの長澤 (@sp_1999N) です。
Claude Codeなどを代表として、さまざまなプロダクトやツールでAIエージェントが提供されています。
AIエージェントを構築する場合、評価が大切になりますが、その挙動はマルチホップ・マルチターンを前提としているため、一問一答的な評価では不十分なことがあります。
本記事では、OpenEvalsを使ったマルチターン対話のシミュレーションと、Langfuseによる実験管理・評価の実践方法を紹介します。
(なおLangfuseについてはすでにデプロイ済みの環境を利用します。セルフホストの仕方などが気になる方は公式ドキュメントをご参照ください。)
本記事で構築するシステムの全体像
まずはじめに、本記事で構築するシステムの全体像を紹介します。
このパイプラインでは、以下の3つのステップで評価を行います。
データセット準備: 評価したいペルソナとシナリオをDatasetとしてLangfuseに登録
シミュレーション準備: OpenEvalsで仮想ユーザーとエージェントのマルチターン対話を自動生成する枠組みを準備
実験・評価: Langfuseで対話全体を追跡し、llm-as-a-judge を使って評価
なお、本記事で利用するコードはこちらのリポジトリで公開しています。
AIエージェントに対するマルチターン評価の方法としては、さまざまなものが研究・提案されています。
いくつかの論文では、エージェントとしてのLLMを部分観測マルコフ過程として定式化し、最終的な出力や対話終了時の系の状態を評価の対象として取り扱っています。
例えば、有名なτ-benchの論文では「対話を通してユーザーに必要な情報を全て提供できていたか」と「最終的な(予約システム)データベースの状態が、正解として事前定義したものと合致しているか」を評価の対象としています。
また他に、TravelAgentなどの論文では、合理性やパーソナライゼーションの観点から人間がスコアリングするという「柔らかな」評価方式を採っています。
今回は問題設定として「ペルソナとシナリオ」を用意し、以下の3つの観点をllm-as-a-judgeで評価する形式にしたいと思います。それぞれの観点でプロンプトにルーブリックを用意し、1-5のスケールでスコアを付けます。詳細については prompt のフォルダをご参照ください。
Actionability: エージェントの提案や回答がユーザーにとって実際に実行可能で、具体的かつ実践的であるかを評価
Adaptability: アシスタントがユーザーの理解度、感情状態、緊急度などに応じて、説明のトーン・詳細度・応答スタイルを適切に調整する能力を評価
Coherence: 複数ターンにわたる対話が論理的に一貫しており、人間同士の自然な会話のように流れているかを評価
対話は最長でも3ターン(エージェントの発話が3回まで)とします。
Step1: 実験データの準備
今回はLangfuseのDatasets機能を使って実験データの作成・管理を行います。SDKを使って作成することもできますし、csvファイルを直接アップロードすることも可能です。今回は前者で行います。
def create_dataset(): try: dataset = langfuse.create_dataset( name='simulated-conversations', description='ペルソナとシナリオを設定した合成データ' ) logger.info(f"Dataset created successfully: {dataset}") except Exception as e: logger.error(f"Error creating dataset: {e}") return None try: langfuse.create_dataset_item( dataset_name="simulated-conversations", input={ "persona": "一人暮らしを始めたばかりの新社会人。料理経験はほぼゼロで、基本的な調理用語も分からないことがある。節約しながら自炊を続けたいと思っている。", "scenario": "スーパーで鶏むね肉が安かったので1kg買ったが、どう保存・調理すればいいか分からない。冷蔵庫は小さく冷凍スペースも限られている。今週中に使い切りたいが、毎日同じ味だと飽きそう。簡単で飽きない調理法のバリエーションを知りたい。" } ) 以下略...
このようにして、簡単にデータセットおよびその中身を作成することができます。
作成がうまくいくと、以下のようにコンソールから確認することもできます。今回は用意していませんが、Gold としての Expected Output やメタデータの付与も可能です。VerifiableなタスクではExpected Outputを、実際のトレースからデータセット化する場合はメタデータなどのフィールドを利用すると良さそうです。
Step2: OpenEvalsを使ったマルチターンシミュレーション
OpenEvalsはLangChainによって開発されているLLM評価用のパッケージになります。LLMやエージェントの評価でよく用いられるものやベストプラクティスをまとめて提供しています。
今回は提供機能の1つであるユーザーシミュレーションを利用します。
def generate_synthetic_conversation( persona: str, scenario: str, max_turns: int=3, config: GenerationConfig | None = None ): app = create_app_wrapper(config=config) # 仮想ユーザー system_prompt_simulated = f"""あなたは以下のシチュエーションにいます: {scenario} あなたの性格は以下の通りです: {persona} 自然に状況を説明し、助けを求めてください。心理状態に基づきながら自然に会話を進めてください。必要に応じてフォローアップの質問をしてください。 課題が解決されたら、感謝を述べて対話を終了してください。""" user = create_llm_simulated_user( system=system_prompt_simulated, model="openai:gpt-4o-mini", ) result = run_multiturn_simulation( app=app, user=user, max_turns=max_turns, ) return result
create_llm_simulated_user
fixed_responses
そして、run_multiturn_simulation
trajectory_evaluators
今回はシナリオに沿うように「料理に悩む人々をサポートする」エージェントを簡単に用意します。
LangfuseではLLMに対するプロンプトをコンソールから管理する機能があります。今回はそれを使ってLangfuseからもプロンプトを取得できるようにします。
それではここまでで準備してきたものを使って実際に実験してみます。
Langfuseのrun_experiment
実行後、Langfuse UIでトレースを確認できます。各対話のターンごとの入出力、使用したモデル、レイテンシなどが可視化されます。
評価は src/eval.py
今回は複数のモデルを比べるように実験してみます。結果はダッシュボードとしても確認することができます。
gpt-5, 5.1 は各指標でパフォーマンスは良いものの、レイテンシが目立つ形となりました。
(チャートは折れ線表示になっていますが、左から右に gpt-4o, gpt-4o-mini, gpt-4.1, gpt-5, gpt-5.1 の順にプロットされています。レイテンシについてはカラムにレスポンス平均値が表示されています。)
スコアの登録はsubmit_score
スコアの横にある吹き出しマークにホバーすると、評価コメントがポップアップします。
「冷凍スペースが限られている条件への踏み込みも弱い」や「初心者ペルソナに対しては火加減...などがなく...」など、設定を踏まえて対話全体をある程度妥当に評価してくれているように見えます。
このようにして、結果を一元的に管理・可視化できるのもLangfuseの便利な使い方です。
この記事ではOpenEvalsとLangfuseを用いて、マルチターン対話実験を総合的に実行・管理してみました。両者をうまく組み合わせることで、シングルショットor最終成果物を対象とするだけでは難しい「対話力」についての実験・評価が手軽に実現できました。
なお、OpenEvalsにはエージェント向けにより踏み込んだ、AgentEvalsという姉妹パッケージ(?)も存在します。今回は対象としませんでしたが、ツールコールなどを含むtrajectoryを評価対象とする場合に便利なので、また別の機会に試してみようと思います。






原文を表示
OpenEvals × Langfuseで始めるAIエージェントのマルチターン評価
こんにちは、AIチームの長澤 (@sp_1999N) です。
Claude Codeなどを代表として、さまざまなプロダクトやツールでAIエージェントが提供されています。
AIエージェントを構築する場合、評価が大切になりますが、その挙動はマルチホップ・マルチターンを前提としているため、一問一答的な評価では不十分なことがあります。
本記事では、OpenEvalsを使ったマルチターン対話のシミュレーションと、Langfuseによる実験管理・評価の実践方法を紹介します。
(なおLangfuseについてはすでにデプロイ済みの環境を利用します。セルフホストの仕方などが気になる方は公式ドキュメントをご参照ください。)
本記事で構築するシステムの全体像
まずはじめに、本記事で構築するシステムの全体像を紹介します。
このパイプラインでは、以下の3つのステップで評価を行います。
データセット準備: 評価したいペルソナとシナリオをDatasetとしてLangfuseに登録
シミュレーション準備: OpenEvalsで仮想ユーザーとエージェントのマルチターン対話を自動生成する枠組みを準備
実験・評価: Langfuseで対話全体を追跡し、llm-as-a-judge を使って評価
なお、本記事で利用するコードはこちらのリポジトリで公開しています。
AIエージェントに対するマルチターン評価の方法としては、さまざまなものが研究・提案されています。
いくつかの論文では、エージェントとしてのLLMを部分観測マルコフ過程として定式化し、最終的な出力や対話終了時の系の状態を評価の対象として取り扱っています。
例えば、有名なτ-benchの論文では「対話を通してユーザーに必要な情報を全て提供できていたか」と「最終的な(予約システム)データベースの状態が、正解として事前定義したものと合致しているか」を評価の対象としています。
また他に、TravelAgentなどの論文では、合理性やパーソナライゼーションの観点から人間がスコアリングするという「柔らかな」評価方式を採っています。
今回は問題設定として「ペルソナとシナリオ」を用意し、以下の3つの観点をllm-as-a-judgeで評価する形式にしたいと思います。それぞれの観点でプロンプトにルーブリックを用意し、1-5のスケールでスコアを付けます。詳細については prompt のフォルダをご参照ください。
Actionability: エージェントの提案や回答がユーザーにとって実際に実行可能で、具体的かつ実践的であるかを評価
Adaptability: アシスタントがユーザーの理解度、感情状態、緊急度などに応じて、説明のトーン・詳細度・応答スタイルを適切に調整する能力を評価
Coherence: 複数ターンにわたる対話が論理的に一貫しており、人間同士の自然な会話のように流れているかを評価
対話は最長でも3ターン(エージェントの発話が3回まで)とします。
Step1: 実験データの準備
今回はLangfuseのDatasets機能を使って実験データの作成・管理を行います。SDKを使って作成することもできますし、csvファイルを直接アップロードすることも可能です。今回は前者で行います。
def create_dataset(): try: dataset = langfuse.create_dataset( name='simulated-conversations', description='ペルソナとシナリオを設定した合成データ' ) logger.info(f"Dataset created successfully: {dataset}") except Exception as e: logger.error(f"Error creating dataset: {e}") return None try: langfuse.create_dataset_item( dataset_name="simulated-conversations", input={ "persona": "一人暮らしを始めたばかりの新社会人。料理経験はほぼゼロで、基本的な調理用語も分からないことがある。節約しながら自炊を続けたいと思っている。", "scenario": "スーパーで鶏むね肉が安かったので1kg買ったが、どう保存・調理すればいいか分からない。冷蔵庫は小さく冷凍スペースも限られている。今週中に使い切りたいが、毎日同じ味だと飽きそう。簡単で飽きない調理法のバリエーションを知りたい。" } ) 以下略...
このようにして、簡単にデータセットおよびその中身を作成することができます。
作成がうまくいくと、以下のようにコンソールから確認することもできます。今回は用意していませんが、Gold としての Expected Output やメタデータの付与も可能です。VerifiableなタスクではExpected Outputを、実際のトレースからデータセット化する場合はメタデータなどのフィールドを利用すると良さそうです。
Step2: OpenEvalsを使ったマルチターンシミュレーション
OpenEvalsはLangChainによって開発されているLLM評価用のパッケージになります。LLMやエージェントの評価でよく用いられるものやベストプラクティスをまとめて提供しています。
今回は提供機能の1つであるユーザーシミュレーションを利用します。
def generate_synthetic_conversation( persona: str, scenario: str, max_turns: int=3, config: GenerationConfig | None = None ): app = create_app_wrapper(config=config) # 仮想ユーザー system_prompt_simulated = f"""あなたは以下のシチュエーションにいます: {scenario} あなたの性格は以下の通りです: {persona} 自然に状況を説明し、助けを求めてください。心理状態に基づきながら自然に会話を進めてください。必要に応じてフォローアップの質問をしてください。 課題が解決されたら、感謝を述べて対話を終了してください。""" user = create_llm_simulated_user( system=system_prompt_simulated, model="openai:gpt-4o-mini", ) result = run_multiturn_simulation( app=app, user=user, max_turns=max_turns, ) return result
create_llm_simulated_user
fixed_responses
そして、run_multiturn_simulation
trajectory_evaluators
今回はシナリオに沿うように「料理に悩む人々をサポートする」エージェントを簡単に用意します。
LangfuseではLLMに対するプロンプトをコンソールから管理する機能があります。今回はそれを使ってLangfuseからもプロンプトを取得できるようにします。
それではここまでで準備してきたものを使って実際に実験してみます。
Langfuseのrun_experiment
実行後、Langfuse UIでトレースを確認できます。各対話のターンごとの入出力、使用したモデル、レイテンシなどが可視化されます。
評価は src/eval.py
今回は複数のモデルを比べるように実験してみます。結果はダッシュボードとしても確認することができます。
gpt-5, 5.1 は各指標でパフォーマンスは良いものの、レイテンシが目立つ形となりました。
(チャートは折れ線表示になっていますが、左から右に gpt-4o, gpt-4o-mini, gpt-4.1, gpt-5, gpt-5.1 の順にプロットされています。レイテンシについてはカラムにレスポンス平均値が表示されています。)
スコアの登録はsubmit_score
スコアの横にある吹き出しマークにホバーすると、評価コメントがポップアップします。
「冷凍スペースが限られている条件への踏み込みも弱い」や「初心者ペルソナに対しては火加減...などがなく...」など、設定を踏まえて対話全体をある程度妥当に評価してくれているように見えます。
このようにして、結果を一元的に管理・可視化できるのもLangfuseの便利な使い方です。
この記事ではOpenEvalsとLangfuseを用いて、マルチターン対話実験を総合的に実行・管理してみました。両者をうまく組み合わせることで、シングルショットor最終成果物を対象とするだけでは難しい「対話力」についての実験・評価が手軽に実現できました。
なお、OpenEvalsにはエージェント向けにより踏み込んだ、AgentEvalsという姉妹パッケージ(?)も存在します。今回は対象としませんでしたが、ツールコールなどを含むtrajectoryを評価対象とする場合に便利なので、また別の機会に試してみようと思います。






関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み