LLMにコードを書かせて1000万トークンを読ませる?RLMの仕組み
コンテキストウィンドウを大きくしてもAIは賢くなりません。RLMはLLMにコードを書かせ、巨大な文書から必要な部分だけを選択的に読み取る新しいアプローチです。
「コンテキストウィンドウが128Kになった」「Geminiは100万トークンだ」――こうしたニュースが飛び交うたびに、まるでLLMがどんどん賢くなっているかのような印象を受けます。しかし現実はそう単純ではありません。コンテキストウィンドウを広げれば広げるほど、モデルの精度は確実に下がっていきます。
RLM(Recursive Language Model)は、この根本的な問題に対してまったく異なるアプローチを提案する研究です。コンテキストを大きくするのではなく、LLM自身にコードを書かせて、必要な情報だけを取りに行かせる。この発想が、なぜ重要なのかを掘り下げていきます。
Context Rot:なぜコンテキストを広げても解決しないのか
LLMは入力トークンの確率分布を計算して次のトークンを予測します。入力が短ければ、各トークン間の関係を正確に把握できます。しかし入力が長くなると、本当に重要な情報がノイズに埋もれていきます。関連性の薄いテキストの中から必要な事実を見つけ出す計算は、指数的に難しくなるのです。
実際のベンチマークでも、128Kや100万トークンをサポートするモデルであっても、最も正確に回答できるのは約1万トークンまでの範囲です。10万トークンを超えると性能は急激に低下します。これが「Context Rot(コンテキスト腐敗)」と呼ばれる現象です。
つまり、1000万トークンの文書を丸ごとLLMに渡すのは、百科事典を丸暗記させてから一つの質問に答えさせるようなもの。人間でもそんなことをしたら混乱するのと同じです。
RLMの核心:「全部読むな、必要な部分を取りに行け」
RLMの基本的なアイデアは驚くほどシンプルです。1000万トークンのテキストをLLMに直接渡す代わりに、テキストをPythonの変数に格納し、LLMにコードを書かせて必要な部分だけを読み取らせます。
これをコンピュータのアーキテクチャに例えるとわかりやすい。LLMをCPU、巨大なテキストをハードドライブと考えてください。CPUがハードドライブの全データを一度にメモリに載せることはしません。必要なセクタだけを読み込んで処理します。RLMはまさにこの原理をLLMに適用したものです。
一度に処理するのは約5万トークン。それでいて、1000万トークン以上の文書群から正確な回答を引き出せます。
3つのコアコンポーネント
RLMのアーキテクチャは3つの要素で構成されています。
RLM Orchestrator(オーケストレーター)
全体を統括するコントローラーです。メッセージの履歴管理、イテレーションループの制御、最終回答の判定を担います。LLMが「もう十分な情報が集まった」と判断するまでループを回し続けます。
LMHandler(LMハンドラー)
LLM APIへのリクエストを中継するソケットサーバーです。重要なのは、コード実行中にもLLMを呼び出せるようにする点です。通常のコード実行とLLMの推論を同じパイプラインの中でシームレスにつなげます。
Environment / REPL(実行環境)
Pythonのサンドボックス環境です。ここに巨大なテキストがcontextという変数に格納されます。そしてこの環境にはllm_query()という特別な関数が用意されています。コード実行中にこの関数を呼ぶと、サブクエリをLLMに投げることができます。
これこそが「Recursive(再帰的)」の名前の由来です。LLMがコードを書き、そのコード内でさらにLLMを呼び出す。必要に応じて何層にも再帰できるのです。
実行フロー:Explore、Decompose、Aggregateのループ
RLMの実行は、3つのフェーズを繰り返すループとして動きます。
Explore(探索)
まずデータの全体像を把握します。LLMは例えばprint(context[:500])のようなコードを書いて、テキストの先頭部分を確認します。どんな構造のデータなのか、どこに何がありそうか、当たりをつける段階です。
Decompose(分解)
全体像を把握したら、テキストをチャンクに分割し、それぞれに対してllm_query()でサブクエリを投げます。例えば1000万トークンの文書を200チャンクに分割し、各チャンクに対して「この部分に〇〇に関する情報はあるか?」と問い合わせます。
Aggregate(集約)
サブクエリの回答が集まったら、Pythonのコードで整理するか、LLMに統合・要約を依頼します。部分的な回答を一つの包括的な回答にまとめる段階です。
Terminate(終了)
十分な回答が得られたと判断したら、FINAL(answer)を呼び出して最終回答を返します。探索が足りなければ、再びExploreフェーズに戻ります。
このループが自律的に回る点がポイントです。人間が「次はここを読め」と指示する必要はありません。LLM自身が何を読むべきかを判断し、コードを書いて実行します。
Ralph Wiggumとの接点
Claude Codeのプラグインとして知られるRalph Wiggumは、RLMと設計思想を共有しつつも、解決する問題は異なります。
Ralph WiggumはStop Hookを使ってClaudeの終了を傍受し、プロンプトを再注入することで、開発タスクを自律的に継続させます。RLMと共通するのは、イテレーティブなループ構造と、失敗をデータとして扱う姿勢です。一度で正解にたどり着けなくても、その結果を次のイテレーションへの入力として活用します。
ただし、RLMが超大規模テキストの処理に特化しているのに対し、Ralph Wiggumは開発タスクの自律的な実行に焦点を当てています。両者は「エージェント的なループで問題を解決する」という同じ原理の、異なる応用形態だと言えるでしょう。
実践的なヒント
RLMの考え方を自分のワークフローに取り入れるなら、いくつかのポイントがあります。
バッチ処理を意識する。 1000行を一度にLLMに渡すのではなく、50行ずつ20回に分けて処理する方が精度は高くなります。1000行 x 1000回のような無駄な組み合わせも避けるべきです。
正規表現でフィルタリングしてからLLMに渡す。 llm_query()を呼ぶ前に、正規表現やキーワード検索で候補を絞り込む。LLMの呼び出しはコストが高いので、事前にノイズを除去するだけで効率が劇的に改善します。
再帰の深さを制限する。 再帰は強力ですが、深くなりすぎると制御が難しくなります。実用上は再帰の深さを1に制限するのが安全です。つまり、メインのLLMがサブクエリを投げるまでで、サブクエリがさらにサブクエリを投げることは避けます。
履歴管理にはローリングウィンドウを使う。 イテレーションが増えるほどメッセージ履歴も膨らみます。古い履歴を要約して圧縮するか、直近N回分だけを保持するローリングウィンドウ方式で、コンテキストの肥大化を防ぎましょう。
コンテキストを大きくする時代から、読み方を賢くする時代へ
RLMが示しているのは、コンテキストウィンドウの拡大競争とは異なる方向性です。100万トークン、1000万トークンとコンテキストを広げるのではなく、5万トークンの窓でいかに賢くデータを読むかを設計する。
LLM自身がコードを書き、実行し、必要な情報を自律的に見つけに行く。このエージェント的な推論パターンは、RLMに限らず、今後のAIアプリケーション設計の中心的なパラダイムになっていくでしょう。コンテキストウィンドウのサイズを競うフェーズは終わりつつあります。次の勝負は、限られた窓からいかに効率的に世界を読み取るか、その設計力にかかっています。
ニュースレターに登録
最新のプロジェクト、記事、AIとWeb開発の実験に関する情報をお届けします。