Replit Agent: LLMの内部動作に関するテックトーク(文字起こし日本語訳)
[拍手]
ありがとうございます、スコット。これまでで最も興味深い紹介の一つでしたね。
こんにちは、私はVaibhavで、AIチームのエンジニアです。今日は、Replitエージェント内のLLMの仕組み、その動作方法、そして今後の改善点について少しお話しさせていただきます。
まずは大まかな概要から始めましょう。コンテキスト管理と情報入力の観点から、今日は3つのレベルでReplitを見ていきます:
プロジェクトレベルのコード生成
その場でのプログラムの編集と実行
コンテキスト管理と新規セッション
私たちは限られたコンテキストを扱っています。あるいは、限られたコンテキストまでしか性能を発揮できないモデルを使っているとも言えます。そのため、このコンテキストをどう管理するか、そして新しいセッションでどう対応するかを賢く考える必要があります。
プロジェクトレベルのコード生成について
エージェントを使用すると、最初に「初期プロトタイプを構築する」というステップが必ずあります。ここでプロジェクトレベルのコード生成が始まります。システムはこの段階で、ユーザーが要求した機能のほとんどを実現しようとします。これは長形式のコード生成タスクです。
要件はユーザーから来ますが、実際のコード生成にはそれ以上の要素があります。スタック情報からの制約があります。ReactやFlaskを使用する場合、モデルが正しく動作しない場合を特定しており、それらのルールをモデルに組み込む必要があります。そうしないと、貴重なトークン予算を無駄にしてしまいます。
また、様々な統合の問題もあります。例えば、モデルの学習時期よりも後にリリースされたライブラリを使用したい場合、正しく動作しません。これらの統合を考慮した上で、最終的にリポジトリレベル、あるいはプロジェクトレベルのコード生成を開始します。
これは長文脈推論の問題としても捉えることができます。本質的には、事前に定義されたルールという形で自然言語による制約があり、長形式のコードを生成する際には、それまでのファイルで設定されたルールや制約に従う必要があります。そうでないとコードが動作しないからです。
Googleから最近興味深い研究結果が出ました。複数ラウンドのコード参照解決における合成長文脈推論タスクについてです。彼らは、コンテキストが増えるにつれてモデルの性能が低下することを発見しました。プロジェクトレベルのコード生成でも同様の並行関係が見られます。
私たちも、非常に複雑なアプリケーションをうまく扱えないことを確認しています。そのため、計画段階でトークンを使用することは価値があります。モデルの性能を効果的に活用しながら、実用的なものを作るためには、これは重要です。
これを改善できるでしょうか?私たちが有用だと見出した一つの方法は、与えられた目的に合わせて、持っているすべての情報とルールを二次的にアンカリングすることです。これにより、プロジェクト開発中にルールに従うことがより確実になります。
ここで面白い点を2つ紹介します:
現在のSonnetは直接shadcnを使いたがらず、常にshadcn-uiをインストールしようとします。しかし、そのようなものは存在しません。
gpt-4oをタイプミスだと考え、常にgpt-4に修正しようとします。
プログラムのリアルタイム編集と実行について
編集は非常にシンプルな問題に見えますが、実はそうではありません。多くの人が、システムを使って全体を書き直したり、「このコードを取って、この修正を加えて」というような形で書き直したりしています。
確かにそれは機能しますが、エージェントを大規模に運用する場合、それは非常にコストがかかり、遅くなります。最大の問題は、リファクタリングできるファイルサイズに制限があることです。そのため、完全なファイル書き換えは最適な選択ではありません。
もう一つの問題があります。きっと多くの人が見たことがあると思いますが、「残りのコードは省略」という状況です。LLMは怠け者で、更新が必要だと考える部分だけを編集しようとし、残りはユーザーに任せようとします。私たちのシステムでもこれをよく目にします。実際、出力トークンを本当に影響のある方法で使おうとしています。
これが問題な理由は、最終的な更新ファイルの推論が難しくなるからです。この対策は講じていますが、この問題のために完全なファイル書き換えはこの種のタスクには不向きです。
他のフォーマットについてはどうでしょうか。unified diffやline diff、その他のフォーマットもありますが、そのままでは十分な性能が得られません。
そこで私たちは独自のカスタマイズされたフォーマットとパース処理を開発しました。これにより、より良い性能が得られ、より高速で、より良い結果を出せています。これが現在のReplit Agentで使用しているものです。
評価方法について簡単にお話しします。SBCHのリファクタリングバージョンを使用してベンチマークを作成しました。自然言語による指示から、元のファイル、そして編集までのシステムを作り、何がシステムを改善するのかを調べました。
結果として、少数の例示、編集しようとしているコードを見つけるための文字列マッチングの工夫、前回の呼び出しで何が間違っていたかをより良く伝えるコンテキストを考慮した再試行の適切な組み合わせが、非常に効果的だとわかりました。
最終コードと初期コードの等価性を判断するこのASTマッチングベンチマークでは、単一のハンク置換のような単純な手法と比較して、私たちのベンチマークはかなり良い性能を示しています。
コンテキスト管理と新規セッションについて
なぜこれが重要なのでしょうか。現在のエージェントは新規セッションをサポートしています。単一のセッションで作業を進め、かなり長いステップまでエージェントを使用することができます。
ただし、これはお勧めしません。失敗する可能性が高くなるからです。常に新しいエージェントセッションを使用することをお勧めしています。しかし、新規セッションを開始すると、開いているファイルがない状態から始まります。そのため、与えられた要求に対して、このプロジェクトで何を探索すべきかをエージェントが賢く判断する必要があります。
単一ホップのRAGでは不十分です。なぜなら、コードベースの場合、単一のRAGクエリが返す可能性のあるコードファイルの関連性を理解し、それがコードベースの残りの部分とどのように接続されているかを理解する必要があるからです。
これは、機能を追加する場合には、単なるリファクタリングや削除の場合と比べてうまく機能しません。そのため、複数の反復を通じて賢く対応する必要があります。
現在のエージェントは反復的な検索をサポートしています。少し複雑な要求や、複数の反復が必要な作業を依頼された場合、要求を満たせると確信できるまで、ヒューリスティックに基づいて複数回の検索を行います。これにより、シンプルなRAG検索と比べて、コードベースをより良く理解することができます。
検索は以下の技術によって支えられています:
a. シンボル検索用のAST
b. バイナリ埋め込み
c. コード検索用のRipGrep
今後の展開
次に何が来るのか、どんな問題に取り組もうとしているのか、お話ししましょう。
プロトタイプ段階でのファイル生成順序から恩恵を得られないか
プロンプトのガベージコレクションのような仕組みが考えられないか
長くなった履歴をどうやって性能を落とさずに整理するか
LLMは怠け者だとわかっているので、常に怠け者にして、その上で編集を改善する技術を開発できないか
ドラフトモデルによる投機的デコーディング
プロンプトルックアップデコーディングのような技術
高度なヒューリスティックベースの検索技術
コードベースにより深く入り込んで理解する
要求に基づいて、いつ止めるべきかをより制御された方法で判断できるシステム
外部のコード知識ベースの検索
URLの追加
コンテキストの読み込み
ドキュメントの読み取り