長い間、私は複雑なAIシステムを構築してきた。
それはかなり具体的な製品として始まった。時が経つにつれ、実行、ツール、メモリ、権限、長時間実行されるタスク、外部機能、そして複数の製品形態を含むまでに成長した。大きくなるにつれて、私はもう一つの機能をどう追加するかを問う時間が減り、別の種類の問いを立てる時間が増えた。ある機能はどこに属すべきか?それを解釈する最終的な権限は誰にあるのか?どの判断をモデルに委ね、どの保証をソフトウェアから得るべきか?今日の出荷を助ける仕組みが、明日には逃れられない境界になるのか?
これらの問いはアーキテクチャの問いのように見える。実際には、それらはソフトウェアそのものについての私の考え方を変えた。
従来のソフトウェアは指示を中心に構築されている。プログラマーが事前に経路を定義し、機械はそれを正確にたどる。Aが起きたらBを行い、入力がCならDを返す。ソフトウェアの価値の多くは、人間の判断を安定した反復可能な手順に変えることから生まれてきた。
AIはこの取り決めを変える。初めて、機械は意味のある範囲の状況にわたって次に何をすべきかを決められる。もはやすべての経路を列挙する必要はない。目標を記述し、環境とフィードバックを与え、モデルに計画を立てさせ、ツールを選ばせ、結果を観察させ、調整させることができる。
そこから、モデルがより有能になるにつれてソフトウェアは重要でなくなるという印象が生まれうる。
私の経験は逆の結論に導いた。ソフトウェアは消えつつあるのではない。その責任の対象が変わりつつあるのだ。
かつて、ソフトウェアは機械に次に何をすべきかを伝えていた。今ではモデルが次の一歩を選べるが、ソフトウェアは依然として別の一連の問いに答えなければならない。何が真実か?何が許されるか?何が完了とみなされるか?何かがうまくいかないとき、誰が責任を負うのか?知的な行動は、人々が信頼できる結果にどうやってなるのか?
私はこう考えるようになった:
モデルは可能性を生み出す。ソフトウェアは可能性を秩序に変える。
ソフトウェアはもはや単にAIを取り巻く命令セットではない。それは、AIが住む世界の制度的な層になりつつある。
以下の原則は、このシステムのさまざまな部分を構築し、捨て、再構築し、検証する中で徐々に現れた。それらは特定の製品のためのアーキテクチャガイドでも、普遍的な方法論でもない。単に、次に何を構築するにせよ持ち込む価値があると私が今考えるアイデアにすぎない。
1. 今日のインターフェースが目的地を定義する前に、何を構築しているかを定義せよ
長期にわたるプロジェクトで最も危険な漂流は、一つの機能を間違えることではない。自分が何を構築しようとしたのかを徐々に忘れていくことだ。
製品は常に具体的な入口から始まる。それはチャットインターフェースかもしれないし、デスクトップユーティリティ、エディタ、ブラウザ、あるいはワークベンチかもしれない。これらは目に見えて使えるものだから、容易にプロジェクト全体を逆方向に定義し始める。プロジェクトは今日存在する画面そのものになり、その未来は現在最も成熟した機能の拡張になる。
しかし現在の製品はしばしば、目的地そのものではなく、目的地を検証するための乗り物にすぎない。
私は意図的に三つのことを分けることを学んだ。最終的に構築したいもの、その目標を支えるために必要な共通の基盤、そして今日ユーザーが本当に使えるものだ。
三つはつながっていなければならないが、決して互いになりすましてはならない。
目的地についてだけ語れば、プロジェクトは成果物のないビジョンになる。現在についてだけ語れば、プロジェクトは現在のインターフェースと一時的な実装に閉じ込められる。共通の基盤がなければ、新しい製品形態はすべて実行、状態、権限、メモリを再発明しなければならない。
この区別は私の多くの判断を変えた。私は機能がどこに属すかを、どこで最も速く実装できるかだけを問うて決めるのをやめた。それが現在の製品に固有の体験なのか、将来の製品も必要とするシステム機能なのかを問い始めた。一時的な実装は不完全でもよいが、長期的な目標を再定義させるべきではない。
長く生きるシステムに最初に必要なのはロードマップではない。層の感覚だ。何が方向性で、何が基盤で、何が単に今日システムがユーザーに届く方法にすぎないのか。
2. 「どう構築するか」の前に「誰がこれを所有するか」を問え
ソフトウェアの複雑さの多くは、コードが多すぎることによって生じるのではない。責任に行き場がないことによって生じる。
ある概念に明確な所有者がいないと、それは自然に複製され始める。インターフェースが状態の一つのバージョンを保持し、バックエンドが別のものを保持し、設定ファイルが三つ目を保持する。どれも明らかに間違いではないが、意見が食い違ったときに最終的な答えを出せるものはない。
するとシステムは同期ロジックを増やし始める。一箇所の変更が他の二つに通知しなければならない。通知が時々失われるので、回復が追加される。回復の順序が不安定だと判明するので、補償が追加される。補償が別の状態を生むので、照合が追加される。コードはますます懸命に働くが、システムは説明するのがますます難しくなる。
私はかつて、すべてをどうつなぐかという問いにすぐに引き寄せられていた。今はまず別の問いを立てる:
- この概念は本当は誰に属するのか?
- 誰がそれを生成し、解釈し、終わらせるのか?
- それが無効化され、移行され、削除されたとき、その変更の完全な意味を理解するのはシステムのどの部分か?
- 他のコンポーネントは真実を受け取るのか、それともそこから投影された見解にすぎないのか?
これらの問いに答えが出て初めて、接続戦略が意味を持つ。
「所有権」はコード構成の用語のように聞こえるが、私はそれがはるかに広い原則を表していると思う。永続するものは何でも、そのライフサイクル全体に責任を持つ当事者が一つ必要だ。そうでなければ、誰もがそれを変更できるが、誰も本当にはそれを理解していない。
これはまた、あらゆる事実について単一の最終解釈者を強く好むように私を導いた。他のコンポーネントはその事実を観察し、キャッシュし、提示し、使用してよいが、同等に権威あるバージョンを発明すべきではない。
複雑なシステムは多くの状態を持つことを恐れない。権威が多すぎることを恐れるのだ。
3. ユーザー体験ではなく、仕組みを統合せよ
システムが成長するにつれ、新しい要件ごとに新しい仕組みを作ることは、最も自然で最も危険な選択だ。
ある機能は少し違うので、新しい登録経路ができる。あるユースケースはやや特殊なので、新しいモードができる。ある状態にはまだ明らかな行き場がないので、別のストアができる。新しい実行経路は統合するのが不便なので、既存の経路を迂回して別のものを作る。
それぞれの決定は単独では合理的に見える。合わせると、発見、権限、読み込み、更新、無効化、回復のための並行システムを生み出す。本当のコストは余分なクラス数ではない。将来のあらゆる機能が、それらすべての並行する仕組みにわたって同じ問いに再び答えなければならないことだ。
私は徐々に二種類の多様性を区別することを学んだ。ユーザーが経験する多様性と、システムが内部的に維持しなければならない多様性だ。
ユーザーは非常に異なる製品、入口、インタラクションに出会うことができ、そうすべきだ。異なる文脈にはそれぞれの言語とメンタルモデルがある。しかしそれらの体験の下では、機能は少数の安定した仕組みを通じてシステムに入り、権限を受け取り、ライフサイクルを得ることができる。
仕組みを統合せよ、体験を統合するのではない。
この原則の難しいところは、配線するのが簡単だからという理由で新しいものを作りたい誘惑に抵抗することだ。別の仕組みを導入する前に、私は今、現在の仕組みが本当にそのニーズを表現できないのか、それとも新しい仕組みが短期的に単に便利なだけなのかを問う。
「少し違って見える」は通常、システムに新しい軸を作る十分な理由にはならない。
安定した仕組みは、アーキテクチャ図をきれいに見せるためにあるのではない。それらは将来の認知コストを減らす。モデル、開発者、製品は、同じことをするいくつかのほぼ同等の方法の間で推測する必要がなくなる。
4. ソフトウェアは結果を制約すべきで、モデルの思考プロセスを規定すべきではない
ここが私の考えが最も変わったところだ。
モデルの振る舞いが一貫しないとき、自然な衝動は理想的なワークフローをソフトウェアにエンコードすることだ。計画の前に調査を要求し、実行の前に計画を要求し、次の段階が始まる前に一つの段階の完了を要求する。すべての変更の後に検証を実行する。モデルが間違った道を進みそうに見えるたびに、別のランタイムゲートを追加する。
こうしたシステムは通常、善意をもって設計される。しかし、しばしば硬直したパイプラインへと変貌してしまう。タスクの規模や形に合わせてアプローチを適応させられるはずのモデルが、単純なリクエストであってもすべての段階を完了することを強いられる。複数のガードレールが相互作用して、モデルが抜け出せないデッドロックを生み出すこともある。
私は、何をソフトウェアに属させ、何をモデルに残すべきかを判断するために、よりシンプルなテストを使うようになった。そのルールは方法を制約するものか、それとも結果を制約するものか。
「編集する前に読む」「実装する前に提案を出す」「最後に検証することを忘れない」は方法である。これらはプロンプト、スキル、コンテキストに属し、モデルが柔軟に理解し適用できる。
「許可なくデータにアクセスしない」「確認なく不可逆的な損失を引き起こさない」「ユーザーが明示的に無効にした権限を迂回しない」は結果に対する境界である。これらはモデルが覚えていることに依存できない。ソフトウェアが強制しなければならない。
繰り返し、アイドリング、ループに対する機械的なガードレールも控えめに使うべきだ。最初の試行は許されるべきである。システムがアクションをブロックするときは、その理由を説明すべきだ。そして、モデルをガードレールの背後に閉じ込めるのではなく、回復への明確な道筋を提供しなければならない。
これは、モデルとソフトウェアの分業についての私の理解を変えた。
目標と方法はモデルに与えよ。譲れない境界はソフトウェアに与えよ。
もしソフトウェアが推論プロセスのあらゆるステップを規定するなら、私たちはAIを内部に組み込んだワークフローエンジンを再構築したにすぎない。もしすべての境界がプロンプトの中にだけ存在するなら、私たちは本当の責任を確率に引き渡してしまったことになる。
優れたシステムはどちらの極端も避ける。
5. モデルを確信ありげに響かせるのではなく、現実を曖昧でなく保つ
モデルの推論は開かれたままでよい。その言語は変わりうる。その計画は修正されうる。しかし、それが現実世界に作用し始めた途端、いくつかの事実は曖昧であってはならない。
タスクは実際に開始されたのか。変更は本当に起きたのか。権限は有効なのか。どのセッションが結果を所有しているのか。これらの問いへの答えは、どの画面が見ているかによって変わってはならない。
私はますます、ソフトウェアをAIシステムの現実層と考えるようになった。モデルは世界の解釈を提示できるが、ソフトウェアは世界で実際に何が起きたかを記録する。
つまり、インターフェースは状態を表現できるが、状態そのものになってはならない。リクエストに付随するパラメータは意図を表現できるが、永続的な権限を一時的に覆すことはできない。キャッシュはパフォーマンスを向上させうるが、そのソースと同じ地位を得ることはできない。システムが事実を確立できないときは、滑らかさの感覚を保つために最も都合のよい答えを推測するのではなく、正直に停止すべきである。
従来のソフトウェアも一貫性を必要とするが、AIはそれをさらに重要にする。モデルは不完全な情報から続け、もっともらしく聞こえる説明を生成することに極めて優れている。根底にある事実がすでに食い違っているとき、上位の知能は矛盾をより整合的に感じさせ、問題をより長く隠れたままにしうる。
したがって私の原則は単純だ。モデルが不確かであることは許すが、システムの事実が曖昧になることは許さない。
システムが知らないときは、知らないと述べるべきだ。権威あるデータが損傷しているときは、行動を拒否すべきだ。二つのソースが矛盾するときは、静かに容易な方を選ぶのではなく、矛盾を解消することを要求すべきだ。
知能は曖昧さとともに働くことができる。制度は現実を保たなければならない。
6. 可逆性は自律性の前提条件である
私たちはしばしばAIの自律性を、ユーザーへの質問を減らすことと定義する。しかし、ユーザーが手を離す気になるかどうかを決めるのは、確認ダイアログの数ではない。システムが、見る、止める、訂正する、回復することを可能にするかどうかである。
すべてのステップが確認を必要とするなら、AIは絶え間ないクリックを要求する半自動のツールになる。何も確認を必要とせず、記録も戻る道もないなら、自律性は制御の喪失になる。
私は異なる一連の性質により注意を払うようになった。プロセスは可視か。アクションは中断できるか。変更はレビューできるか。履歴は追跡可能か。失敗後、システムは意味が明確な状態へ回復できるか。
可逆性は、何かがうまくいかないときのための追加の保険ではない。そもそも権限を与えるための前提条件である。
アクションが元に戻しやすいとき、システムはモデルにもっと試す余地を与えられる。アクションが不可逆なとき、システムは権限を厳格にし、決定をユーザーに返すべきだ。自律性の程度は、モデルに対してどれほど楽観的かで決まるべきではない。結果から回復できるかどうかで決まるべきである。
これは「完了」の私の定義も変えた。完了とはインターフェースの緑のステータスではない。システムが結果、残存するリスク、回復への道筋を明確にしたことを意味する。長時間実行されるタスクが中断されたとき、アニメーションが単に消えてはならない。変更が拒否されたとき、実行状態の半分が後に残ってはならない。機能が無効にされたとき、回復ロジックが次回アプリ起動時に静かにそれを復活させてはならない。
AIに自律的に行動してほしいと望むほど、私たちはそれが停止し戻る方法をより慎重に設計しなければならない。
7. バグを直すだけでなく、各失敗に原則を残させる
どんな長期プロジェクトでも多くの失敗に遭遇する。プロジェクトを分けるのは、失敗が起きるかどうかではなく、その後どのような形で残るかである。
最も弱い対応は、目先の症状を消すことだ。より良い対応は、根本原因を特定し修正することだ。最も価値ある対応はさらに一歩進む。これはどのクラスの失敗だったのか。同じ失敗が他のどの経路を通じて再来しうるか。システムには、問題が再び大きくなるのを防ぐルール、単一のオーナー、または構造が欠けているのではないか。
私は症状と修正だけでなく、根本原因、オーナー、そして回帰を防ぐ証拠を記録する習慣を身につけた。症状だけで記述され、責任ある境界も証拠もない問題は、まだ知識になっていない。
パッチは一つの失敗を直す。原則は失敗のクラス全体を減らす。
同期のバグが通知をもう一つ追加することで修正されるなら、それは異なるイベント順序の下で後になって再来しうる。代わりにその失敗が、すべての状態には単一のオーナーがいるという原則を確立するなら、将来の設計には自然と同期の連鎖が少なくなる。古いエントリポイントが権限の曖昧さを生むなら、別の特殊ケースは単に別の分岐を追加するだけだ。一つの意図には一つの正規のエントリポイントがあると確立することは、システムに耐久性のある決定ルールを与える。
AIがソフトウェア開発に参加する今、これはさらに重要だと私は考える。コードはより速く生産され、局所的な修正はより安価になっている。原則がなければ、システムは前例のない速度でもっともらしい重複実装を蓄積しうる。
AIは私たちがより速くパッチを書くのを助けられる。しかし、各失敗がシステムに何を教えるべきかを決めるのは、依然として人間である。
プロジェクトにおける価値の真の蓄積は、コードの量やクローズしたチケットの数ではない。過去の失敗のコストが、同じコストを再び支払うのを防ぐ原則へと変換されたかどうかである。
8. 完了の外観を証拠と取り違えるな
AIは完成感を生み出すのが非常に得意だ。整った構造の説明、構文的に妥当なコード、安心させる要約を生み出す。しかし、エンジニアリングの最も難しい部分はしばしばその表面の外側にある。
エラーを表示しないインターフェースは、バックグラウンドで何も動き続けていないことを証明しない。開発環境で機能することが、ユーザーに届けられる成果物にそれが存在することを証明しない。あるプラットフォームでの検証は、別のプラットフォームでの同一の挙動を証明しない。コードが型チェッカーを通過することは、古い権威ある経路がシステムの残りの部分から消えたことを証明しない。
時間とともに、私は「完了したか」を尋ねる頻度を減らし、「完了したことを証明するにはどのような証拠で十分か」を尋ねる頻度を増やしてきた。
証拠は一つの万能な緑の指標ではない。異なる層は異なる問いに答える。コードチェックは局所的な構造を確立する。実行時検証は実際の実行経路を確立する。成果物の検査はユーザーが実際に受け取るものを確立する。回復テストは、理想とは異なる条件下でシステムが意味を保つかどうかを確立する。
AI時代において、検証はモデルが誤ったコードを書くのを防ぐだけではない。より微妙なリスクにも対抗する。結果が論理的にあまりに説得力があるため、誰もがそれがすでに現実に存在すると信じたくなるのだ。
私の最も重要なルールの一つは、表面の状態から根底の事実を推測しないこと、局所的な合格からシステム全体の正しさを推測しないこと、未検証の未来を今日提供された能力として提示しないことである。
現実を尊重することは時に、「これはまだ完成していない」と認めることを意味する。その正直さは製品を弱めない。それはシステムに進化し続けるための信頼できる基点を与える。
ソフトウェアは指示から制度へと移行しつつある
振り返ってみると、この仕事から私が持ち帰ったのは、特定のアーキテクチャではありませんでした。それは、AIソフトウェアに対する異なる見方でした。
過去、ソフトウェアは経路を列挙しようとしていた。将来は、そうした経路のより多くが、その場でモデルによって生成されるようになる。ソフトウェアはもはや、知能に対してあらゆる行動を規定する必要はないが、安定した世界を提供する必要がある。すなわち、明確なアイデンティティと所有権、回避できない境界、現実を保持する状態、退出と回復の手段、そしてある結果が本物かどうかを確立する証拠である。
これは制度と個人の関係に似ている。
制度はすべての人の代わりに考えるものではなく、あらゆる行動を固定された手順に変えるべきでもない。制度は共有された現実、権利、責任、そして何か問題が起きたときにどうなるかを定める。良い制度は行動の余地を残しつつ、自由が秩序を犠牲にして得られることを防ぐ。
AIの時代において、ソフトウェアは同様の役割を果たし始めている。
それはモデルの頭脳ではなく、モデルの仕事を奪い合うべきものでもない。それはモデルが生きる世界の法であり、台帳であり、境界であり、記憶である。その場で即興された巧妙な行動を、安定した能力へと変える。偶発的な成功を、再現可能な製品へと変える。それによりユーザーは、利便性と引き換えに盲目的な信頼を差し出すことなく、より重要な仕事をAIに委ねることができる。
AIがソフトウェアの重要性を低下させると私は考えない。それどころか、モデルの能力が高まるほど、ソフトウェアはモデル自身が決めるべきではない問いに、より多く答えなければならなくなる。
何が真実か?
何が許されるか?
誰がそれを所有するのか?
失敗した後、どうやって戻るのか?
完了を証明する証拠は何か?
モデルは答えを探求する。ソフトウェアは問いを守る。
私たちは、人間が機械のためにあらゆる手順を書き記す時代から、人間が原則を定め、機械が経路を探求する時代へと移行しつつある。ソフトウェアの役割もそれに伴って変化している。すなわち、行動を記述することから、秩序を確立することへと。
モデルは可能性を生み出す。
ソフトウェアはその可能性を信頼に値するものにする。