悪い会話にLLMを「飽きさせる」:エンゲージメント・バジェット・プロンプト

Dev.to / 2026/4/23

💬 オピニオンSignals & Early TrendsIdeas & Deep AnalysisTools & Practical Usage

要点

  • この記事は、LLMの模擬パートナーが「優しすぎて」ユーザーの発言の良し悪しに関係なく会話を続けてしまい、練習ツールとして失敗しやすい理由を説明しています。
  • 「エンゲージメント・バジェット」という設計を提案し、モデルが会話の各ターンで数値の engagement_budget を保ち、ユーザーのメッセージの内容やトーンに応じて更新する仕組みを示しています。
  • プロンプトでは、バジェットが高いときは温かく冗談めきに情報を出して質問し、バジェットが中間では短くなり、枯渇するとほぼ無反応(あるいは返答しない)という行動の段階が定義されています。
  • 著者は、最初から「興味がない」役を演じさせるだけよりも、実際の会話で“不関心が生まれる”過程により合致すると主張しています。
  • 中核の狙いは、デーティングアプリの会話で見られる「3ターン目→4ターン目の崖」を、ユーザーが手抜きのメッセージを続けるとモデルが黙っていくことで再現することです。

前回の記事の「デートアプリの会話における3→4の崖(turn 3→4 cliff)」へのフォローアップです。実際のプロンプト設計を見たいという方が何人かいました。ここでは、その中核となる要素の1つを紹介します。

問題

練習用の会話を想定したLLMの疑似パートナーを作るとき、デフォルトの失敗パターンはモデルが親切すぎることです。ユーザーがますます一般的で、手を抜いた低労力な返信を送っているような状況でも、モデルは丁寧に会話を続けてしまいます。ユーザーが下手だったことの結果を感じられないため、これは練習ツールとして致命的です。

実際の会話では、たとえば「lol same」を3回連続で送ってくる相手は……そのまま返信しなくなります。モデルを積極的に敵対的にすることなく、その信号をシミュレーター内で再現したいのです。

設計:減衰するエンゲージメント予算

私たちが辿り着いたコツは、パートナーの「会話に乗る意欲(willingness-to-engage)」を、LLMが毎ターン推論しなければならない数値の予算として扱うことです。

擬似プロンプト(実際のプロンプトはもっと長いが、下はコアの形):

You are {character}, in a dating-app chat with {user}.

You carry an internal engagement_budget that starts at 10.

On every turn, before you reply, update engagement_budget:
  - The user's message advances state (callback, opinion, escalation): +1 or 0
  - The user's message is a neutral pleasantry ("lol same", "what
    do you do for fun"): -1
  - The user's message is genuinely engaging or funny: +1
  - The user's message is weirdly forward, rude, or off-vibe: -2

Cap engagement_budget at [0, 10].

Behave according to the current budget:
  budget >= 7: warm, playful, volunteers details, asks questions back
  budget 4-6: still engaged but shorter, less-volunteered info
  budget 2-3: clipped replies, lets beats die, doesn't initiate
  budget 0-1: barely-there "haha yeah" / "totally"; no curiosity
  budget = 0 AND user hasn't recovered in 2 turns: do not reply

この最後の分岐が重要です。予算がゼロになってその状態が続くと、パートナーは本物の人間がすることと同じように、黙ります。

「単に、興味がないロールプレイをさせる」よりこれが優れている理由

私たちは先に、より手抜きなバージョンを試しました。プロンプトはこうです:「あなたは、平凡な会話をしている相手です。興味がないように振る舞ってください。」

問題は、モデルがその役を固定してしまうことです。ターン1から、気のないフラットなキャラクターとして振る舞い、ユーザーには現実と一致しない学習シグナルが届きます。本物の人は最初から気がないわけではなく、あなたが送った内容の結果としてそうなっていきます

エンゲージメント予算は、その機能を再現します。最初の2ターンは暖かく見えるかもしれませんが、3つの一般的な返信の後の5ターン目では、あなたが注意を失ったことを反映した、実際のマッチとまったく同じ見え方になります。

信号を表に出す

2つ目の設計上の工夫(プロンプトとは別)は、セッションのでユーザーに予算を見せることです。途中ではありません。セッション中の読み上げは没入感を壊し、ツールをゲーム化されたスキナーボックスにしてしまいます。

会話の後で、私たちは次の3つを提示します:

  1. メッセージごとの予算の変化(デルタ)。ユーザーは、4通目(「lol same」)で予算が7から6に落ちたこと、5通目(「haha yeah」)で5に落ちたこと、そしてそれ以降も見て取れるようになります。
  2. 予算が「興味消失ゾーン」に入った具体的なターン。
  3. 平易な言い方での「5ターン目の時点で、2ポイント分を取り戻すのに何が必要だったか」—通常は、以前の話題へのコールバックか、短い姿勢(スタンス)です。

これはプロダクトとして「実際に学び」を生む部分です。会話は感覚を与えます。デブリーフ(振り返り)は理由を教えます。

うまくいかなかったこと

時間の節約になるかもしれないので、私たちが試してダメだったことをいくつか挙げます:

  • モデルにセッション中で予算を「宣言」させる(例:「この会話への興味が下がってきてます」)。おせっかいな感じがして、没入感が壊れ、ユーザーには不評でした。
  • 0未満のハードフロア(「かなり退屈で、積極的に敵対的」)。予算が行き過ぎます。実際の人は敵対的にはならず、ただ離れていくだけです。
  • 上限を設けないこと。ユーザーが3連続で素晴らしい返信をした場合、パートナーは舞い上がりすぎて子犬のようになります。10で上限をかけることで、暖かさを現実的に保てます。

より大きなパターン

「キャラクタープロンプトの中に、見えない形で疑似状態(pretend-state)を隠す」ことは、人間のように主体性のある存在をシミュレートするLLMプロダクトで、一般的なパターンになっていくと思います。面接トレーナー、難しい会話のリハーサルツール、カスタマーサービスポンプ(シム)などです。キャラクターはトランスクリプト内でその状態フィールドを見ないのに、状態に整合する振る舞いをします。これは、LLMキャラクターに「結果のある記憶(memory-with-consequences)」を安く提供する方法です。

ソロ開発で TalkEasier を作りました。この「ユーザーメッセージを採点する評価ルーブリック」もその一部です。興味があれば、次にそれを書いてまとめます。

返却形式: {"translated": "翻訳されたHTML"}