目次
ブラウザーエージェントが本をショッピングカートに追加する。ページには指定された商品が表示され、タスクは完了している。それでもエージェントはクリックを続ける。同じ本がもう1冊、カートに入る。
次の操作自体は有効だった。誤っていたのは、さらに操作を行うという判断だった。
Jevの設計パターンの一つは、独立した確認を設けることでこの問題に対処する。主判断の質問や回答を確認側に見せず、ページにすでに要求された結果が表示されているかを尋ねる。そして、実行を停止すべきかどうかはコードで決める。
この例は、Jevの16の設計パターン ↗の魅力をよく表している。これらのパターンが対象とするのは、文章ではなく確率を返すモデルだ。質問をどう定義し、不確かな回答をどう解釈し、アプリケーションの動作をどうコードの制御下に置くかを説明している。
従来型のLLMを分類器、検証器、操作の選択器として使う場合にも役立つ。中心となる問いは同じだ。モデルの不確かな評価を、どうすれば信頼できる動作につなげられるのか。
確率は判断への入力である#
JevはTypeSafe AIのSystem Oneモデルだ。ドキュメントによると、状態と型付きの質問を受け取り、およそ300ミリ秒で確率を返す。アプリケーションが必要とする文章を生成することはない。
質問の型には、次のものがある。
- noul:「はい」の確率。0.5に近い値は、その性質が中程度に存在することではなく、モデルが選択肢を区別できないことを意味する。
- choice: 提示された候補からの選択。どの候補にも当てはまらない場合の逃げ道として、
otherという選択肢がある。 - score: 特定の状況に合わせて定義した段階の、確率で重み付けした平均値。
判断を担うのは、引き続きアプリケーションだ。何を尋ねるか、どの回答なら操作を実行してよいか、回答が欠けていたらどうするかを決める。
以下の数値は、Jevの各パターンの解説ページに掲載されたものだ。それぞれのプロジェクトにおける例であり、別のアプリケーションでの性能を保証するものではない。
1. モデルに何を判断させるかを決める#
最初の4つのパターンは、モデルによる評価とアプリケーションのロジックとの境界を定める。その多くは、確率が返ってくる前に問題を防ぐものだ。
1. Viewfinder(ファインダー):状態を必要最小限にする#
何が起きるか: 会話全体を送ると、判断が難しくなる。ドキュメントの例では、200回目の編集までに入力が40,000トークンに達し、正解率は1回目の編集時の0.84から0.52に低下した。
どう防ぐか: まず判断の対象となる単位を定義し、その判断に必要な文脈だけを添える。編集内容を確認するなら、編集履歴全体ではなく、該当する変更と必要な周辺テキストを送る。
2. Menu(メニュー):候補を列挙する#
何が起きるか: モデルにCSSセレクターを生成させると、存在しないID、複数の要素への一致、無効な構文が返ることがある。アプリケーションは、提案された対象を受け取るまで検証できない。
どう防ぐか: 有効な対象をコードで列挙し、識別子を割り当てる。モデルには識別子を選ばせ、候補が不十分な場合に拒否できるよう「どれにも当てはまらない」を含める。
3. Question bank(質問集):ルールを質問にする#
何が起きるか: 大規模モデルにポリシー全体の解釈を繰り返し求めると、時間がかかり、判断も一貫しない。ドキュメントの例では、編集1回あたり約2秒と1セントがかかった。
どう防ぐか: 各ルールを、観察可能な事実についての具体的な質問に変換する。「これは良いか?」ではなく、「これにはXが含まれているか?」と尋ねる。件数の集計や日付の比較はコードに任せる。
4. Ghostwriter(ゴーストライター):判断と生成を分ける#
何が起きるか: 確率しか返さないモデルは、フォームに入力する文章を書けない。ワークフロー全体を、文章生成を行う大規模モデルに移すと、この例では1ステップの所要時間が約300ミリ秒から2秒に増えた。
どう防ぐか: 操作と対象の選択にはJevを使う。選ばれた操作に文章が必要な場合だけ文章生成モデルを呼び出し、その出力を確認してから使う。
これらのパターンは、有用な区別を示している。既存の選択肢を選ぶことと、新しい内容を作ることは別の仕事だ。それぞれに独立したインターフェースを設ければ、どちらも確認しやすくなる。
2. 質問と確認の構造を整える#
短い質問でも、設計が悪いことはある。次の4つのパターンは、問題が平均化されて見えなくなること、不要な逐次呼び出し、停止条件の不足に対処する。
5. Questionnaire(質問票):独立した質問をまとめて投げる#
何が起きるか:「これは機械が書いた文章に見えるか?」のような広い質問では、明確な欠点が一つあっても、それ以外の問題のない部分に埋もれてしまうことがある。ある例では、判別可能な問題を含む段落に対して0.52が返された。
どう防ぐか: 具体的な欠点について、独立した質問を1回のリクエストで尋ねる。確認を5種類の欠点に分けたところ、80件の例における検出数が58件から63件に増え、その評価では誤検出も増えなかった。
6. Prefetch(先読み):分岐先の質問を先に投げる#
何が起きるか: 操作を尋ねてから、その対象を尋ねるためにもう一度呼び出すと、避けられる待ち時間が生じる。約300ミリ秒の呼び出しを2回行えば、1ステップあたりのモデル待ち時間は約600ミリ秒になる。
どう防ぐか: 起こりうる分岐の質問をまとめて送る。操作を選んだ後は、その分岐に対応する回答だけを読む。使わなかった回答を、追加の操作を許可する根拠にしてはいけない。
7. Blind review(ブラインドレビュー):独立した照合#
何が起きるか: エージェントはタスクを完了した後も操作を続けることがある。もう一度クリックして、同じ本を2冊目としてカートに追加してしまう例がそれだ。
どう防ぐか: リクエストに独立した検証用の質問を含める。ページ上で観察できる事実を渡しつつ、主判断の質問と回答は伏せ、完了したかどうかを独立して確認させる。
8. Funnel(漏斗):段階的に振り分ける#
何が起きるか: すべてのケースを大規模モデルに送ると、簡単な判断にまでリソースを浪費する。ドキュメントの例では、200ファイルの確認に5分と数ドルがかかったが、190ファイルには問題がなかった。
どう防ぐか: コードのルール、Jev、大規模モデルまたは人間の順に処理する。ある段階で判断がついたらそこで止め、高コストな確認は不確かさが残るケースに限定する。
実践上の教訓は、結果を変えうるところにモデルの処理を使うことだ。確定的に判定できる事実は、確定的なチェックで処理する。難しい判断は、段階的にコストの高い確認へ回せばよい。
3. 確率に明確な意味を与える#
確率だけでは、取るべき操作は決まらない。0.62という値は、コメントを付ける根拠としては十分でも、自動で書き換える根拠としては不十分かもしれない。
次の4つのパターンは、その解釈を明確にする。
9. Traffic light(信号機):操作ごとにしきい値を設ける#
何が起きるか: 一つのしきい値を異なる操作に使うと、トレードオフが適切でなくなる。0.5を超えたらブロックする設定では、検出された14件のうち12件が誤検出だった。一方、しきい値を0.9に上げると、0.62と評価された実際の問題を見逃した。
どう防ぐか: 操作とその影響に応じて、しきい値を設定する。この例では、書き換えには0.8、コメントには0.5を使い、元に戻しにくい操作ほど強い根拠を求めている。
10. Grey zone(グレーゾーン):判断を保留する範囲#
何が起きるか: 入力によっては、判断に使えるほどの差が得られない。入力にスクリーンショットを混ぜたある例では、10個の回答すべてが0.48〜0.53に収まった。
どう防ぐか: 0.4〜0.6などの中央の範囲を「判断保留」として扱う。監視のために件数は記録するが、しきい値を動かして無理に「はい」か「いいえ」の分岐へ押し込まない。
11. Thermostat(サーモスタット):ヒステリシス#
何が起きるか: しきい値が一つだけだと、確率のわずかな変動で状態が揺れる。戦闘状態の検出でしきい値を0.7にしたところ、0.68、0.72、0.69、0.71という値に応じて状態が何度も切り替わった。
どう防ぐか: 状態に入るときと抜けるときで、異なるしきい値を使う。たとえば、0.8を超えたらその状態に入り、0.6を下回ったら抜け、その間では直前の状態を維持する。
12. Scorecard(スコアカード):複数の評価を組み合わせる#
何が起きるか: コマンドのリスクを0〜2の尺度で大まかに尋ねると、回答がほぼ常に1になってしまうことがある。その結果からは、どの動作がリスクを生んでいるのかほとんど分からない。
どう防ぐか: 削除、外部への送信、コンテンツのダウンロードと実行など、個別の事実を尋ねる。アプリケーションの責任者が確認できるルールを使い、コードで回答を組み合わせる。
確率のしきい値が、異なる質問でも同じ意味を持つと考えてはいけない。質問ごとに代表的な入力から得た根拠が必要であり、操作ごとに不確かさを扱う方針が必要だ。
4. 失敗に対処し、運用で機能しているかを測る#
適切に設計した質問でも、不正な形式の応答が返ってくることはある。有用だった質問が、入力の変化によって役に立たなくなることもある。
最後の4つのパターンは、こうした運用上の問題を扱う。
13. Inspection(検査):契約の検証#
何が起きるか: 欠けた回答をゼロで埋めると、壊れた応答が無害に見えてしまう。ドキュメントの事例では、不完全な応答がそのまま通過し、監視でも障害を検出できなかった。
どう防ぐか: 回答数、確率の範囲、選択結果の整合性を検証する。不正な出力は「回答なし」として表し、有効な低確率の回答とは区別する。
14. Fail open, fail closed(障害時に通すか止めるか):障害時の動作を設定する#
何が起きるか: 障害によって保護が失われることも、作業が完全に止まることもある。30分間の障害中、エディターのフックは検査せずに操作を通し、ビルドサーバーはすべてのコマンドを拒否した。
どう防ぐか: 作業の中断と未確認の操作のどちらが高くつくかを、事前に決める。その動作を例外処理の偶然の結果にせず、明示的な設定項目にする。
15. Flight recorder(フライトレコーダー):記録と再実行#
何が起きるか: ログに最終判断しか残っていなければ、しきい値を変更した効果を評価できない。削除のしきい値を0.8から0.9に変える影響を調べるには、元の確率が必要だ。
どう防ぐか: 判断ロジックを純粋関数にする。生の確率、判断結果、直前の判断結果、入力のフィンガープリントを記録し、別のポリシーで判断を再実行できるようにする。
16. Check-up(定期点検):実測による校正#
何が起きるか: 精度の低い質問が、何か月も使われ続けることがある。14個の質問のうち、コメント量に関する一つは的中率が約20%しかなく、3か月間見過ごされていた。
どう防ぐか: 各質問を少なくとも20件の実際の入力で評価し、発火率、確率の中央値と最大値を測定する。実際の正しさも確認し、ほとんどノイズしか生まない質問は廃止する。
再実行と校正は、目的が異なる。再実行は、記録された回答に対してポリシーを変えると何が起きるかを示す。校正は、そもそもその回答が有用だったかを確認する。
LLMによる判定で、私なら最初に取り入れる3つのパターン#
すでにLLMで入力を承認、拒否、分類している人には、次の3つを優先して勧めたい。
1. Question bank(質問集)。「準拠しているか確認して」という大まかな依頼を、特定できる条件についての質問に置き換える。そうすれば、どの部分をコードで処理し、どの部分にモデルの判断が必要かが明らかになる。 2. Grey zone(グレーゾーン)。 不確かさを、アプリケーション上の正式な状態として扱う。二択を強制すると不確かさが隠れる。明示的な「判断保留」という結果があれば、確認に回したり、操作を延期したりできる。 3. Flight recorder(フライトレコーダー)。 判断を見直すために必要な根拠を保存する。生の回答と再実行可能なロジックがなければ、しきい値の調整は当て推量になる。
Menuは、既知の操作や対象から選ぶときに特に役立つ。Question bankと合わせると、候補ごとに「はい/いいえ」で答える質問を一つずつ設けることが、なぜ妥当な設計になりうるかが分かる。コードが選択肢を定義し、モデルがそれらを評価するのだ。
ただし、個別の「はい/いいえ」の回答が、自動的に相互排他的な選択になるわけではない点には注意が必要だ。複数の候補に高い確率が付くことも、条件を満たす候補が一つもないこともある。どちらの場合も、コードで扱い方を定義しなければならない。
今週、アプリケーション内の判断を一つ選んでみよう。それを観察可能な事実についての質問に書き換え、回答が不確かな場合や欠けた場合の動作を定義し、生の確率を記録する。そして、その判断で重大な影響を伴う操作を制御する前に、少なくとも20件の実際の入力をJevのパターン ↗に照らして確認しよう。
目次
