世界を動かす技術を、日本語で。

LLMは多ターン会話で迷子になる

概要

  • Large Language Models(LLMs)は会話型インターフェースとして機能することを強調する研究。
  • 単一ターンよりもマルチターン会話でLLMの性能が大きく低下することを大規模シミュレーションで確認。
  • 6つの生成タスクで平均39%の性能低下を記録。
  • 性能低下の要因は適性のわずかな低下と信頼性の大幅な低下に分解。
  • LLMは会話の早い段階で誤った仮定をし、その後の回復が困難であることを発見。

LLMにおけるマルチターン会話の課題と性能劣化の要因

  • Large Language Models(LLMs) は、ユーザーがタスクを完全に指定できない場合でも、会話を通じてニーズの定義・探索・洗練を支援することが可能であることを強調すること。
  • LLMの会話ログ分析により、 ユーザー指示の過少特定(underspecification) が頻繁に発生することを確認すること。
  • しかし、これまでのLLM評価は主に 単一ターンかつ完全指定の指示 に焦点を当てていたことを指摘すること。

実験の概要と主な発見

  • 大規模シミュレーション実験を実施し、 単一ターンマルチターン の設定でLLMの性能を比較すること。
  • オープンウェイト・クローズドウェイト両方の 主要LLM を対象に調査すること。
  • 6つの生成タスク全体で 平均39%の性能低下 を記録すること。
  • 200,000件を超えるシミュレーション会話を分析し、 性能劣化の要因 を2つに分解すること。
    • 適性のわずかな低下(aptitude loss)を特定すること。
    • 信頼性の大幅な減少(unreliability increase)を特定すること。

LLMの会話中の問題行動

  • LLMは会話の初期ターンで 仮定を行いがち であり、最終解決策を早期に生成しようとする傾向があること。
  • 一度誤った方向に進むと、その後も 誤った解決策に固執しやすい こと。
  • つまり、 LLMは会話中に誤った判断をすると、迷子になり回復できない ことを明らかにすること。

今後の提案・示唆

  • マルチターン会話における 信頼性向上 のためのアプローチ検討。
  • 過少特定への対応や 段階的な意図把握 の強化を提案すること。
  • LLMの評価基準を マルチターン・不完全指示 に拡張する重要性を確認すること。

Hackerたちの意見

LLMツールを使っている人なら誰でも知っていることを確認する論文を見るのはいいね。コンテキストをきれいに保つことが大事で、「会話」ってのは製品インターフェースの構造に過ぎないから、LLM自体の応答の質を損なうんだ。コンテキストが「汚染」されると元には戻らないから、新しいチャットでやり直さないといけない。

そうだね。メモリをオンにしておいたのは後悔してる。無関係なゴミで会話が汚染されちゃったから。

まさに私の経験と一致してる。「汚染された」って表現がぴったりだね。何かがうまくいかなくなると、その後の応答が全部悪くなる気がする。だから、ChatGPTのメモリ機能にはちょっと疑問を持ってる。大きな問題を引き起こしているとは感じないけど、よくわからない方法で私のコンテキストを汚染するのは好きじゃないな。

私の経験はこれらの観察をある程度裏付けているけど、ちょっと違ったこともあった。GeminiでIPSECの問題を2週間デバッグしたんだ。最初は、OPNsenseとpfSenseからIPSECのドキュメントを全部Geminiにインポートして、私が操作している一般的なコンテキストを伝えた(「コンテキストをきれいに保つ」っていうのに関連して)。その後、両側の初期設定を追加した(敏感な情報は削除!)。その後、長いフィードバックループに入って、ログを投稿したり、質問したり答えたりしていた。2週間の終わりに観察したのは、LLMが気を散らす可能性がかなり低くなったこと。時々、フォーラムのスレッドやSOの投稿を全部ぶち込んで、「これは私たちが見ているものじゃない、[以前のコンテキストや発見]のせいだ」と言われたこともあった。論理的に行き止まりを排除して、これを伝えた(そう、反省には役立つけど、決定は自分でしなきゃいけなかった)。最終的に、私の問題の原因を見つけた。これは、数日前にHNで誰かが言っていたことをある程度裏付けている。LLMは複雑な情報をシンプルに圧縮するのが得意だけど、シンプルなアイデアを複雑に広げるのは苦手だ。私の入力が出力よりも大きい限り(複雑さや長さ)、結果には満足していた。LLMなしでもできたかもしれないけど、最初から忘れていたり、新しいコンテキストで迅速に取り出せなかった事実を保存してくれたのは助かった。大きなログファイルの時間パターンを特定するのも簡単になって、サイト間接続のデバッグに役立った。他にも多くの設定を最適化して、最も問題のある問題だけでなく解決した。これによって、問題を解決するだけでなく、かなりのことを学んだ。状態は私の現在のパラメータ設定について時々間違っていたけど、これはいつも簡単に修正できた。他の人がすでに見たことを確認することになるけど、行きたい場所を知っていて、それをツールとして扱えば役立つ。ただし、決定をオフロードしたり、間違った方向に導かれないようにしないとね。全体で350kトークン使用(約300kワード)。これに関連するブログ投稿 [1] があるけど、特定の問題には直接関係していない。(ワイヤーガードは勧めないでね、知ってるから) [1]: https://du.nkel.dev/blog/2021-11-19_pfsense_opnsense_ipsec_cgnat/

どのインターフェースも、会話のデッドエンドや無関係な詳細を掃除するメカニズムを実装してる?つまり、各チャットメッセージで会話のデッドエンドを掃除することに焦点を当てるみたいな?要約みたいだけど、話題に沿ったオーガニックな感じで?ほとんどの履歴は残るけど、正確に要約しようとはせず、会話の流れに関連して履歴を整理したり剪定したりする感じ?

同意、"poisoned"っていうのはいい表現だね。APIやUIを通じて会話の「バージョン管理」ができて、以前の場所に戻ったり、その地点から新しい会話にクローンしたりできるといいな。ちょっとしたタイプミスや前のメッセージを明確にする必要があるだけで、未来のレスポンスの確率が歪んじゃうから。

この問題の面白い例が初期のプロンプトなんだけど、これは実質的に消せない永久的な隠れたコンテキストなんだ。今、Twitterでは「Grok」ボットが「ホワイトジェノサイド」について頻繁に言及し始めたんだけど、これってちょっと変だよね。おそらく最近、誰かがそのプロンプトを調整して、ホワイトジェノサイドに対する意見を教えたからだと思うんだけど、完璧なチャットボットなら他のトピックについて聞いても関係ないはずなのに、実際には関係あるんだよね。それがコンテキストの一部だから、今後はその話をすることになる。

ずっと言ってるんだけど、会話をフォークできるようにしたいんだよね。そうすれば、 promisingなやり取りを壊さずに実験できるから。ChatGPTではできないんだけど、これを機能として提供してるサービス知ってる人いる?

同意だね。コンテキストが「毒される」と、回復するのが難しいよね。改善策としては、LLMが定期的にコンテキストの特定の部分をクリーンアップしたりリセットしたりすることが考えられるけど、ゼロからやり直す必要はない。でも、どの部分をリセットするべきかを判断するのが難しいし、重要な情報を失わないようにしないといけない。賢いコンテキスト管理があれば、長い会話の一貫性を保つのに役立つかもしれないけど、バランスを取るのが難しいよね。別のエージェントを使うのもアリかも?

私が教える一番のコツは、ChatGPTやClaudeのほとんど隠れている小さな「編集」ボタンをたくさん使うことだよ。悪いレスポンスが来たら、止まって編集してより良いものを得るようにするんだ。そうしないと、クソがクソを増やすことになっちゃうからね。

だからこそ、FileKittyを作ったんだ。これを使えば、複数のソースコードファイルをすぐにマークダウン形式のコピペにまとめられるよ: https://github.com/banagale/FileKitty ソフトウェア開発のサポートを受けるときに、LLM製品に頼ってコードベースを検索するのは、エラーが出る余地が大きすぎる。サービス提供者のトークンコストを抑えるために、そのコンテキストが実質的にロスのある圧縮をされると、LLMは薄められた結果を出すことになる。最初から特定のコンテキストを正しく把握し、会話が進むにつれてそのコンテキストを更新することで、より良い結果が得られるんだ。それでも、会話の長さには気をつける必要があるよ。会話のコンテキストをキャッチして、新しいセッションに転送するためのプロンプトを用意している。新しい初期プロンプトに含めるべきファイルを特定するんだ。これについてもう少し話したいなら、このスレッドとその系譜を見てみて: https://news.ycombinator.com/item?id=43711216

これって、彼らの知られた過信や自己反省の欠如の一面だと思う。もっと詳細を求める必要があるって認識できないのは、彼らの前提が低すぎるから。推論モデルの出力を見ると、明確さを求めるアイデアがほとんど思いつかないことがわかる。混乱しているときは、ユーザーが何を意味しているのかを延々と推測するだけ。これは「人間のプログラマーを置き換える」アイデアの賢明さに対して、ある意味で影響を与えるよね。というのも、この仕事の難しい部分の一つは、あいまいでしばしば混乱したアイデアを、株主とやり取りしながら正確な仕様に変えることだから。

自己反省できないっていうのがIMOの一つの変なトリックなんだけど、LLMは実体がないことを認識することだと思う。ユーザーは一時的に信じ込ませられるストーリーに騙されてるんだよね。ほとんどの場合、映画の脚本ドキュメントの中のキャラクターのためにテキストラインを提供していて、LLMアルゴリズムはチャットボットキャラクターのために不完全なラインを自動補完するために定期的にトリガーされる。吸血鬼のドラキュラボットとのインタビューもできるけど、そのキャラクターは「血を渇望する」や「コウモリの雲に変わる」みたいに、同じ浅い/フィクション的な方法でしか「自己反省」できないんだ。

自己反省できないし、事前の知識が低すぎるからもっと詳細を求める必要があるってこと。Gemini 2.5 ProやChatGPT-o3は、リクエストされたタスクを実行する前に、よく追加の詳細を提供するように求めてくる。Geminiは時々複数のオプションを提示して、タスクを実行する前に私の意見を求めることもある。

これって比較的簡単に修正できるんじゃない?思考の連鎖推論が「うーん」で終端トークンを置き換えるように、ユーザーも「多分彼らは言っているのは」って言い始めたら、何か「進む前に明確化の質問をさせて」みたいなもので置き換えればいいんじゃない?

自己反省や詳細をもっと聞く必要があることを認識できないのが問題なんだ。彼らはその2つのタスクが得意なんだけど、頼む必要があるだけなんだよね。

LLMが明確化を求めることができないのは、あいまいに表現されたオープンエンドの問題をテストしたときに遭遇したまさにその欠陥だったんだ。これは逆説的な状況の文脈で、DeepSeek-R1とClaude-3.7-Sonnetでテストしたものだよ。実験についてのブログ記事はこちら: https://pankajpansari.github.io/posts/paradoxes/

本当のプログラマーは、人々が実際に何を求めているのかを理解するのにたくさんの時間を使うんだ。LLMはまだ推測を機能として扱ってる。

もちろん、これは「人間のプログラマーを置き換える」というアイデアの賢さに関する特定の意味合いを持っている。皮肉なことに、ジュニア開発者と一緒に働くのはまさにこんな感じだよね。タスクを与えて、後で犬や懐中電灯を持って戻ってきて、彼らが進んでいくうちに迷子になってしまった深い森から引き戻すみたいな。

これは、彼らのよく知られた過信と自己反省の欠如、つまり自分たちの前提が低すぎるからもっと詳細を聞く必要があることを認識できないことの一側面のようだね。これを読むと、賢い人たちがより優れたEmacsのドクターに騙されているのを目撃している気分になる。反省していないし、自信もない。ただ「テキスト補完」を提案しているだけなんだ。だから、補完が悪くなり始めたら、最初からやり直さなきゃいけない。何かの概念を持っているわけではなく、ただ単に言葉の塊と、訓練に使われたテキストから示される可能性のあるフォローアップがあるだけなんだ。

これを解決するためにかなりの成功を収めているんだけど、もう少し詳しく共有する予定だよ。2つのシステムを使っていて、1つはLLM自体、もう1つは「考えのキュレーター」みたいな役割を果たすシステムなんだ。コンテキストの一部を動的に入れ替えるんだ。このシステムは明示的な定義に基づいているわけじゃなくて、LLMが「ギャップを埋める」ことに頼っている。これによって、LLMが問題を小さなタスクに分解して、最終的には全体のタスクに集約できるんだ。

何を作ってるのかもっと情報が知りたいな - 面白そうだね!

ワクワクするアイデアだね。提案なんだけど、たとえそれがほんの数個のプロンプトしかなくても、今持ってるものを世の中に出してみて。人々がそれを見て改善してくれれば、いいアイデアなら他の人たちに拾われて発展するかもしれないし、自分の命を持つことになるかも!

これは「エモーションマシン」からのメンタルクリティックのクラスだね。

じゃあ、思考のマップ・リデュースってこと?

いいアイデアだね。君がやってるのはチャットのRAGだ。将来的には、メモリ階層の区別がもっと明確になると思うよ - トレーニングデータのプライマリメモリ - コンテキストのセカンダリメモリ - RAGのターシャリメモリ。

今のところ、LLMの領域は同じ問題を何度も解決しようとしている人たちで溢れている気がする。

みんな自分のプロンプトエンジニアリングの腕前を披露したがるよね。

猫を集めるようなもので、「学習」じゃないんだよね。これはワークフローの一部にはいい状況だと思う。

マルチターン会話のLLMと同じだね。

TSCE(Two-Step Contextual Enrichment)を思いついた理由だよ。300タスクのミックスでGPT-35-turboを使った時に+30ppの向上があった。無料のオープンフレームワークだから、リポジトリをチェックして自分で試してみてね https://github.com/AutomationOptimization/tsce_demo これをgpt-4.1で300回テストして、みんなが嫌がる「エムダッシュ」を取り除いたよ。単一パスのベースラインとTSCEをテストしたけど、同じ指示とプロンプト「私のLinkedIn投稿からエムダッシュを取り除いて…」で。300回のテストのうち、ベースラインは149回もエムダッシュを取り除けなかったけど、TSCEは18回しか失敗しなかった。ちゃんと機能してるよ、テストに使ったデータやスクリプトはリポジトリに全部あるから。

君の基本のエムダッシュの例を少し修正したら、追加の呼び出しやトークン消費、テクノバブルなしでGPT-4.1で100%の成功率が出たよ。システムプロンプト: "以下のテキストからエムダッシュ(—)をすべて取り除き、他の文字はそのままにしてください。\n\nクリーンなテキストだけを返してください。" ユーザープロンプト: 温度: 0.0

置換操作にしては、無駄にしたキロワットアワーが多いね。text.replace("—", "-")って聞いたことある?

分岐やフォークが主要なチャットツールのコアな要素じゃないのが驚きだよね。返答を編集することはできるけど、そうすると他のコンテキストが失われちゃうんだ。私の流れは基本的にこうだね: 1. 計画 2. 構築 3. 分岐(ある機能や難解な依存関係の問題に) 4. #2に戻る。プロンプトのプルーニングや分岐は、どんなLLMの使用にも一級のツールであるべきだよ。

これを作ろうと思ってたんだ。BetterChatGPTは、履歴を削除するのに結構使いやすいけど、分岐が次のステップだと思う。

Google AIスタジオには少なくともこれがあるよ。ただ、その実装はかなり混乱することがあったから、もっと「消費者向け」のツールには実装されてない理由かもしれないね。

「プロンプトエンジニアリング」という言葉に対する軽蔑が、初期プロンプトの重要性を過大評価し、進行中のコンテキストの管理の重要性を過小評価しているせいだとずっと感じてたんだ。モデルをどう操るかや新しい会話を始めるコツは、経験を通じて身につけるものだよ。システムや初期プロンプトは重要だけど、会話を長く続けすぎると何も助けにならないからね。

そうそう、プロンプトエンジニアリングって完璧なオープナーを作るだけじゃなくて、会話の管理みたいなもんだよね。いつ物事が脱線しそうか、リセットするタイミングを感じ取れるようになってくる。

シングルターン会話を基にしたLLMのインターフェースを作ると、明らかに問題があるよ。大多数の人はリニアな会話を期待してるから。俺は、http://t.me/experai_bot っていうテレグラムボットを作ったんだけど、これは「非返信メッセージは新しい会話を意味する」ってアイデアに基づいて、LLMのユニバーサルUIとして機能してる(機能は少し制限されてるけど)。パワーユーザーじゃない人はこのアイデアに苦労してるみたい。-- それに、OpenAIのモデルが同じ質問に答えるとき、パフォーマンスが悪くなるのを観察したよ(例えば、返信の選択肢が短くなったり)。3.5や4の時はそうだったけど、現代のものはどうなのかはわからない。だから、デフォルトでシステムメッセージを含めないことに決めたんだ。でも、必要なら追加するオプションは用意してるよ。混ぜ合わせるためにトグルもできる。

これが、私がpromptdownを書いた主な理由だよ。毎ターン、全チャット履歴を編集できるようにしたいんだけど、追加のみの標準チャットインターフェースじゃそれが簡単じゃないんだ。https://github.com/t-kalinowski/promptdown

私はよくLLMにこれまでの議論の簡潔な要約をプロンプト形式で求めるんだ。それを適切に編集して、新しい会話を始めるのに使うんだけど、余計なものを持ち込まずに済むからね。これはすごく効果的なテクニックだと思うけど、近いうちに自動化されるんじゃないかな。

[死んでる]

Claude Codeには、これまでの会話を要約してコンテキストトークンを節約するための/compactコマンドがあるよ。

Cursorはこれを自動でやろうとしたんだけど、今もそうかもしれないね。大きなコンテキストモデル(例えばgemini 2.5 pro)を使っていないなら。でも、要約があまりにも多くの詳細を欠いていて、そのまま使うのは難しいと感じたよ。