本文へスキップ

ガイド

模擬ユーザー

台本どおりの会話は、決して反応しないユーザーに対してアシスタントをテストします。模擬ユーザーは反応します。モデルが各ケースの記述する人物を演じ、アシスタントが直前に言ったことから次の各メッセージを書き、目標が達成されるか諦めたときに止まります。Oloproof は両者の間でやり取りされたものを記録し、ほかの会話と同じように測定し、人がその模擬ユーザーを現実的だと認めてからはじめて、ゲートがそれにもとづいて判断できるようにします。チュートリアルでは、模擬された顧客と話すサポートデスクを順に見ていきます。

ペルソナ

各ケースの入力はペルソナを持ちます。ユーザーが誰か、何を望むか、何を知っているかです。

{"id": "c25", "input": {"persona": {
  "description": "A retired teacher who ordered a cookbook last week. Writes short, polite messages.",
  "goal": "Have the order of a cookbook delivered to my new address.",
  "facts": {"order": "B-35", "postcode": "10275"}
}}}
  • description と goal は必須です。読み手が会話だけから確かめられる目標を書いてください。「店に返金を開始させる」はアシスタントの発言から判断できますが、「返金を受け取る」は判断できません。お金が届くのは後になるからです。
  • facts は、ユーザーが知っていて、会話が必要とするときにだけ伝えることです。たとえば注文番号です。アシスタントがペルソナを見ることはありません。
  • opening は、ユーザーの最初のメッセージを一字一句そのまま記したもので、どのシステムも同じように話しかけられるべきときに使います。
  • max_turns はこのユーザーのメッセージ数の上限で、プロジェクトの設定を上書きします。

ペルソナはデータセットの内容です。スイートのダイジェストに含まれ、それに対して測定されるどのシステムにとっても同じです。

模擬ユーザーを宣言する

すべてのペルソナを演じるモデルは、ジャッジと同じようにシステムに宣言します:

system:
  name: support-desk
  callable: desk:talk
  simulated_user:
    provider: openai_compatible
    base_url: http://localhost:11434/v1
    model: qwen2.5vl
    max_turns: 6

すべてのフィールドは設定リファレンスにあります。ローカルモデルには費用がかかりません。ホストされたモデルは書くメッセージごとに課金され、そのトークンは会話と並べて記録され、あなたのシステムのコストとして数えられることはありません。

システムが自分のループを保つ

Oloproof は会話を駆動しません。あなたのシステムがユーザーの最初のメッセージを求め、ユーザーにいつも答えるとおりにそれに答え、次のメッセージを得るために各回答を返します:

from oloproof import current_case

def talk(case):
    user = current_case().simulated_user()
    message = user.opening()
    while message is not None:
        message = user.reply(my_assistant.answer(message))
    return {}

ユーザーが止まると、reply は None を返します。人への引き継ぎのように、システム自身が user.end(answer) で会話を終えることもできます。async def のシステムは aopening()、areply(answer)、aend(answer) を await します。Oloproof はハンドルを通過したものを conversation/v1 として、会話がどう終わったかを simulated_user/v1 として記録し、どちらもあなたのシステムからは受け付けません(SDK リファレンス)。

会話の終わり方

システムが回答するたびに、模擬ユーザーのモデルに、その回答で目標が達成されたかどうかを、温度 0 で、ロールプレイを伴わない別の質問として尋ねます。達成されていれば、会話は goal_reached で終わります。そうでなければ、ユーザーは次のメッセージを書くか、去る(user_left)かし、max_turns 件のメッセージを送るまで続けます(turn_limit)。最後のメッセージに答えずに止まるシステムは、会話を unanswered のまま切り詰めて残します。

別に尋ねることで、小さなローカルモデルが使えるようになります。ペルソナを演じることと、目標が達成されたかを判断することは別の作業であり、1 つの応答で両方を求められたモデルは、目標が達成された後も話し続けたり、満足しているのに去ると言ったりしがちです。

会話を測定する

単位は会話です。各評価器は会話ごとに 1 つの判定を出すので、すべての区間、比較、ゲートがそのまま適用されます。

型合格する条件
conversation_completedシステムがすべてのメッセージに回答した
goal_reached目標チェックで目標が達成されたとわかった
turns_to_goalそれがユーザーのメッセージ max_turns 件以内に起きた
every_turnすべての回答が宣言された条件を満たす。含まなければならない語、含んではならない語、パターン、長さ
conversation_judgeトランスクリプト全体を判定するモデルジャッジが合格とする。人のラベルに対して検証されてから

反復(replicates:)では異なるシードのユーザーに出会うので、1 つのペルソナが複数の会話になります。模擬ユーザーのバージョン(そのモデル、プロンプト、温度、予算)は各実行のキャッシュキーに含まれるので、別の模擬ユーザーはあなたのシステムを改めて測定します。

模擬ユーザーを検証する

模擬ユーザーにもとづく結果が実際のユーザーに当てはまるのは、模擬ユーザーが実際のユーザーに似ている範囲に限られます。そのため、ユーザーが模擬された実行にもとづくすべてのルールは、人がその会話を現実的だと認めるまで、simulated_user_not_validated とともに INSUFFICIENT_EVIDENCE になります:

oloproof labels export RUN_ID --criterion simulated_user_realistic --sample 30 --local --out realism.csv
oloproof labels import realism.csv
oloproof simulated-users RUN_ID

シートには、抽出された各会話がペルソナと会話の終わり方とともに表示されます。実際の顧客がユーザー側を書き、そこで、そのように会話を終えることがありえたなら、人は passed を yes にします。これは目標チェックも対象にします。目標が達成されていないのに goal_reached で終わった会話は現実的ではありません。現実的な割合の正確な下限が release.yaml の minimum_simulated_user_realism を上回ると、模擬ユーザーはそのスイートで検証されます。抽出された会話のうちラベルのないものは非現実的として数えられ、会話が現実的とされるのは、それにラベルを付けた全員がそう述べたときだけです。

1 つの検証は、1 つのスイートにおける 1 つの模擬ユーザーのバージョンを、それがどのシステムと話したかにかかわらず対象とします。そのため、同じペルソナに対して測定された候補は、ベースラインのラベルにもとづいて判断されます。新しいモデル、プロンプトの設定、ペルソナの集合には新しいラベルが必要です。require_validated_evaluators: false を設定すると、承知のうえで、ラベルなしで模擬ユーザーにもとづいて判断します。

模擬と実際を並べる

oloproof simulated-users RUN_ID --real REAL_RUN_ID は、模擬された会話の形を実際の会話の実行(conversation/v1 として再生されたログ上のチャット)と並べて示します。ユーザーが送ったメッセージの数、その長さ、回答の長さ、会話が途中で打ち切られた頻度、そして模擬された会話がどう終わったかです。これは記述的なもので、判断することはありません。対応のない 2 つのサンプルを比較するには、Oloproof がまだ認めていない手法が必要です。現実性のラベルが見落とすものを知るために読んでください。たとえば、実際のユーザーが 3 つに分けて書くことを、きれいな 1 文で書く模擬ユーザーです。

未対応のもの

  • ホストされたワークスペースで模擬ユーザーにもとづいて判断すること。そのレビューキューが自ら現実性のラベルを抽出して封印できるようになるまで、その判断は保留されたままです。
  • 模擬された会話が実際の会話とどう比べられるかにもとづくゲート。
  • 会話の中のターン単位の率と、あるターンからの会話の再生。
  • HTTP システムのための模擬ユーザー。ループを実行するのはあなたのシステム自身のコードなので、システムは呼び出し可能でなければなりません。