Home 論文解説: Recursive Language Models — REPL環境による再帰的推論でコンテキストウィンドウの100倍超を処理
投稿
キャンセル

📄 論文解説: Recursive Language Models — REPL環境による再帰的推論でコンテキストウィンドウの100倍超を処理

論文概要(Abstract)

本記事は Recursive Language Models (arXiv:2512.24601) の解説記事です。

Recursive Language Models(RLM)は、LLMのコンテキストウィンドウを超える入力をプログラム的に分解・再帰処理する推論フレームワークである。著者らは、入力をREPL(Read-Eval-Print Loop)環境の変数として保持し、LLMがメタデータのみを受け取ることでコンテキスト汚染を回避する設計を提案している。論文のベンチマークでは、RLM(GPT-5)がBrowseComp+(約10Mトークン)で91.3%を達成し、ベースモデル単体(0%)を大幅に上回る結果が報告されている。

この記事は Zenn記事: Recursive Language Models コンテキスト100倍超を実現する推論手法 の深掘りです。

情報源

背景と動機(Background & Motivation)

現在のフロンティアLLM(GPT-5、Claude 4.x、Gemini 2.xなど)はコンテキストウィンドウの拡大が進んでいるが、入力長の増加に伴い性能が劣化する「コンテキスト腐敗(Context Rot)」が知られている。論文のFigure 1によると、GPT-5はタスク複雑度の増加に伴い劣化が加速し、$2^{14}$トークン(約16K)を超えると急激に性能が落ちることが示されている。

既存の長文処理アプローチには以下の限界がある。コンテキスト拡張はアーキテクチャ改良でウィンドウを広げるが性能劣化は解消されない。RAGは検索漏れと文脈の断片化が問題になる。要約エージェントは情報損失が不可避であり、論文ではSummary AgentがOOLONG-Pairsで0.1%に崩壊する事例が報告されている。タスク分解エージェントは入力自体がウィンドウを超えると動作不能になる。RLMはこれらの制約を根本的に回避するために設計された。

主要な貢献(Key Contributions)

  • 貢献1: LLMが自分自身をサブルーチンとして呼び出すREPL環境ベースの再帰的推論フレームワーク(RLM)の提案
  • 貢献2: 4つの多様なタスク(S-NIAH, BrowseComp+, OOLONG, OOLONG-Pairs)にわたる体系的なベンチマーク評価
  • 貢献3: 48 H100時間の学習でRLM-Qwen3-8Bを構築し、小規模モデルでもRLMの恩恵を得られることの実証
  • 貢献4: pip install rlmsとして利用可能なオープンソース実装の公開(MITライセンス)

技術的詳細(Technical Details)

3つの設計原則

RLMの設計は以下の3原則に基づいている。

原則1: プロンプトへのシンボリックハンドル

ユーザー入力はREPL環境の文字列変数としてロードされ、LLMには直接渡されない。LLMが受け取るのは入力の長さ、短いプレフィックス、アクセス方法の指示のみである。これはCPUがレジスタだけで処理するのではなくRAMにデータを保持してアドレス指定でアクセスする概念と類似している。

原則2: 変数を介した無制限出力

通常のLLMは自己回帰的に応答を生成するため出力長もコンテキストウィンドウに制約される。RLMでは応答をREPL変数として構築し、FINAL(answer) または FINAL_VAR(variable_name) タグで返却する。

原則3: プログラム的再帰

REPL内で実行されるコードから llm_query() 関数を呼び出し、LLMを任意の入力スライスに対して再帰的に適用できる。これにより入力全体に対して $\Omega(|P|)$ や $\Omega(|P|^2)$ のセマンティック操作が可能になる。

実行ループアルゴリズム(Algorithm 1)

論文のAlgorithm 1に対応する実行ループの構造は以下の通りである。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def rlm_execute(prompt: str) -> str:
    """RLMの実行ループ(論文 Algorithm 1 に対応)

    Args:
        prompt: ユーザーからの入力(任意長)

    Returns:
        最終回答の文字列
    """
    state = init_repl(prompt=prompt)
    state = add_function(state, sub_rlm)
    history = [metadata(state)]

    while True:
        code = llm_generate(history)
        state, stdout = repl_execute(state, code)
        history = history + [code, metadata(stdout)]

        if state.final is not None:
            return state.final

このループの重要な点は、各イテレーションでLLMが生成したコードを実行し、その出力のメタデータのみを履歴に追加することである。フルテキストを履歴に含めないことで、ルートLLMのコンテキストウィンドウが汚染されることを防いでいる。

LLMが自律的に獲得する戦略

論文によると、RLMを使用するとLLMは明示的な指示なしに以下の戦略を自律的に発見する。

  1. Peeking: 入力の先頭セグメントを確認して構造を把握する
  2. Grepping: re.findall() で関連チャンクを絞り込む
  3. Partition + Map: 入力をチャンクに分割し、各チャンクにサブLLMを適用する
  4. Variable Stitching: サブLLMの出力をREPL変数に蓄積し、最終回答を組み立てる

著者らはこれらの戦略がモデルに教示されたものではなく、RLMフレームワークの制約下でLLMが自然に発見したものだと述べている。ただし、モデルごとに戦略の選択傾向は異なり、GPT-5は正規表現フィルタリングを多用する一方、Qwen3-Coderは均等チャンキングを好む傾向が報告されている。

実験結果(Results)

評価タスクの設計

論文では情報複雑度の異なる4タスクで評価を行っている。

タスク入力長複雑度内容
S-NIAH〜$2^{18}$トークン$O(1)$テキスト中の特定フレーズ検索
BrowseComp+6M〜11Mトークン$O(1)$(文書数固定)1,000文書からのマルチホップQA
OOLONG131Kトークン$O(|P|)$チャンクごとのセマンティック変換+集約
OOLONG-Pairs32Kトークン$O(|P|^2)$ペアワイズ集約(二次的複雑度)

主要スコア(論文Table 1より)

モデルCodeQABrowseComp+OOLONGOOLONG-Pairs
GPT-5(ベース)24.0%0.0%44.0%0.1%
RLM(GPT-5)62.0%91.3%56.5%58.0%
Qwen3-Coder-480B20.0%36.0%0.1%
RLM(Qwen3-Coder)56.0%48.0%23.1%
Summary Agent70.5%0.1%

BrowseComp+では、ベースGPT-5はコンテキストウィンドウ(272Kトークン)を超える約10Mトークンの入力を処理できず0%であった。RLMはこれを91.3%まで引き上げている。OOLONG-Pairsでは、要約ベースのアプローチ(0.1%)が完全に崩壊する一方、RLMは58.0%を達成しており、ペアワイズ情報を保持したまま処理できるRLMの強みが現れている。

アブレーション: 再帰の有無

再帰なし(REPL環境は維持、サブLLM呼び出し無効化)の結果も報告されている。

タスクRLM(再帰あり)RLM(再帰なし)
CodeQA(Qwen3)56.0%66.0%
OOLONG(Qwen3)48.0%43.5%
OOLONG-Pairs23.1%17.3%

CodeQAでは再帰なしの方が高いスコアを記録している。著者らは、コードリポジトリの理解タスクではREPL環境によるコード実行だけで十分であり、再帰のオーバーヘッドがむしろ精度を下げるケースがあると分析している。この結果は、RLMの効果がREPL環境と再帰の2要素に分解可能であることを示唆している。

コスト分析

BrowseComp+(1,000文書)におけるコスト比較は以下の通りである(論文記載値)。

手法スコア平均コスト/クエリ
GPT-5(直接入力、推定)ウィンドウ超過$1.50〜$2.75
RLM(GPT-5)91.3%$0.99
Summary Agent70.5%$2.97(推定)

中央値ではRLMがコスト効率でも優位だが、95パーセンタイルでは長い軌道により急増する可能性があるため、本番環境ではタイムアウトやコスト上限の設定が不可欠である。

RLM-Qwen3-8Bの学習

著者らは大規模モデルの軌道データを用いてRLM-Qwen3-8Bをファインチューニングしている。

  • 軌道生成: Qwen3-Coder-480B-A35Bで750のLongBenchProタスクに対しRLM軌道を生成
  • フィルタリング: 2,250候補から1,072に絞り込み(ゼロスコア・1ターン軌道除外)
  • データ修正: 16%のターンでFINALタグ誤用を修正、13%でREPL変数誤用を修正
  • 学習条件: バッチサイズ64、300ステップ、48 H100時間
タスクRLM-Qwen3-8BPrompted RLM(Qwen3-8B)改善率
CodeQA32.0%26.0%+23.1%
OOLONG32.0%24.0%+33.3%
OOLONG-Pairs5.2%4.3%+20.9%

48 H100時間というリソースでプロンプトベースのRLMを一貫して上回る結果だが、GPT-5レベルの性能には距離があり、8Bモデルの能力限界も見える結果となっている。

実装のポイント(Implementation)

RLMはpip install rlmsでインストール可能なPythonライブラリとして公開されている(GitHub: 3.8kスター、MITライセンス、2026年4月時点)。

1
2
3
4
5
6
7
8
9
10
11
12
13
from rlm import RLM

rlm = RLM(
    backend="openai",
    backend_kwargs={"model_name": "gpt-5-nano"},
    verbose=True,
)

response = rlm.completion(
    "この長大なテキストの中から、2025年Q4の売上数値を"
    "すべて抽出してください。\n"
    + very_long_document
)

サポートされるバックエンドはOpenAI、Anthropic、OpenRouter、Portkey、ローカルモデル(vLLM経由)である。REPL環境はlocal(デフォルト、ホストプロセス内exec)、dockermodale2b等が選択可能である。

localモードはホストプロセス内でexecを実行するため、悪意あるコード生成のリスクがある。本番環境ではdockerやクラウドサンドボックスの使用が著者らにより推奨されている。

Production Deployment Guide

AWS実装パターン(コスト最適化重視)

RLMはLLMへの再帰的なAPI呼び出しとREPL環境(Python実行サンドボックス)の2要素を必要とする。以下にトラフィック量別の推奨構成を示す。

規模月間リクエスト推奨構成月額コスト目安主要サービス
Small~3,000Serverless$50-150Lambda + Bedrock + DynamoDB
Medium~30,000Hybrid$300-800Lambda + ECS Fargate + ElastiCache
Large300,000+Container$2,000-5,000EKS + Karpenter + EC2 Spot

Small構成(月額$50-150): Lambda(1GB RAM、60秒タイムアウト)でリクエスト受付、BedrockでLLM推論、DynamoDB(On-Demand)でプロンプトキャッシュを管理する。REPL実行はLambda内のサブプロセスで処理し、NAT Gatewayを使用しないことでコストを削減する。

コスト試算の注意事項: 上記は2026年4月時点のAWS ap-northeast-1(東京)リージョン料金に基づく概算値である。実際のコストはトラフィックパターン、リージョン、バースト使用量により変動する。最新料金はAWS料金計算ツールで確認を推奨する。

Terraformインフラコード(Small構成)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"

  name = "rlm-vpc"
  cidr = "10.0.0.0/16"
  azs  = ["ap-northeast-1a", "ap-northeast-1c"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
  enable_nat_gateway   = false
  enable_dns_hostnames = true
}

resource "aws_iam_role" "lambda_rlm" {
  name = "lambda-rlm-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action    = "sts:AssumeRole"
      Effect    = "Allow"
      Principal = { Service = "lambda.amazonaws.com" }
    }]
  })
}

resource "aws_iam_role_policy" "bedrock_invoke" {
  role = aws_iam_role.lambda_rlm.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect   = "Allow"
      Action   = ["bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream"]
      Resource = "arn:aws:bedrock:ap-northeast-1::foundation-model/anthropic.claude-*"
    }]
  })
}

resource "aws_lambda_function" "rlm_handler" {
  filename      = "lambda.zip"
  function_name = "rlm-inference-handler"
  role          = aws_iam_role.lambda_rlm.arn
  handler       = "index.handler"
  runtime       = "python3.12"
  timeout       = 120
  memory_size   = 1024
  environment {
    variables = {
      BEDROCK_MODEL_ID    = "anthropic.claude-sonnet-4-6-20260414"
      DYNAMODB_TABLE      = aws_dynamodb_table.cache.name
      ENABLE_PROMPT_CACHE = "true"
      RLM_MAX_DEPTH       = "1"
      RLM_REPL_TIMEOUT    = "30"
    }
  }
}

resource "aws_dynamodb_table" "cache" {
  name         = "rlm-prompt-cache"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "prompt_hash"
  attribute {
    name = "prompt_hash"
    type = "S"
  }
  ttl {
    attribute_name = "expire_at"
    enabled        = true
  }
}

運用・監視設定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import boto3

cloudwatch = boto3.client('cloudwatch')

cloudwatch.put_metric_alarm(
    AlarmName='rlm-bedrock-token-spike',
    ComparisonOperator='GreaterThanThreshold',
    EvaluationPeriods=1,
    MetricName='TokenUsage',
    Namespace='AWS/Bedrock',
    Period=3600,
    Statistic='Sum',
    Threshold=500000,
    AlarmActions=['arn:aws:sns:ap-northeast-1:123456789:cost-alerts'],
    AlarmDescription='RLM Bedrockトークン使用量異常'
)

コスト最適化チェックリスト

  • ~100 req/日 → Lambda + Bedrock (Serverless) $50-150/月
  • ~1000 req/日 → ECS Fargate + Bedrock (Hybrid) $300-800/月
  • 10000+ req/日 → EKS + Spot Instances (Container) $2,000-5,000/月
  • Bedrock Batch API使用で50%削減(非リアルタイム処理)
  • Prompt Caching有効化で30-90%削減
  • RLM再帰深度を1に制限(depth-1が最もコスト効率的)
  • REPL実行タイムアウト設定(30秒推奨)
  • 95パーセンタイルのコストスパイクに対するアラート設定
  • AWS Budgets月額予算設定(80%警告、100%アラート)

実運用への応用(Practical Applications)

RLMの効果がタスクの情報複雑度に依存する点は、実運用でのタスク選定において重要な判断基準となる。

適したユースケース: 大量の文書を横断的に分析する法務レビュー、セキュリティ監査ログの全件分析、大規模コードベースの脆弱性スキャンなど、入力がコンテキストウィンドウを超え、かつ入力全体にわたるセマンティック処理が必要なタスクである。

適さないユースケース: 論文で報告されている通り、数学タスクではREPLオーバーヘッドにより15〜25%の性能低下が観測されている。短い入力や単純な集約タスクでは再帰のオーバーヘッドが無駄になる。

実務では「入力がコンテキストウィンドウに収まるか」を最初に判定し、収まる場合はベースモデルを直接使用する設計が推奨される。

関連研究(Related Work)

  • Leave-No-Context-Behind Attention (Munkhdalai et al., 2024): アーキテクチャレベルでの無限コンテキスト拡張。RLMとは異なりモデル内部の改変が必要
  • MemGPT (Packer et al., 2023): OS的な仮想コンテキスト管理。RLMの「外部メモリ」概念の先行研究に位置づけられる
  • THREAD, ReDel, Context Folding, AgentFold: 再帰的委譲を可能にするが、入力がベースモデルのウィンドウを超える場合に動作しない点がRLMとの差異

まとめと今後の展望

RLMはREPL環境による入力のプログラム的分解と再帰的サブLLM呼び出しにより、コンテキストウィンドウの制約を根本的に回避する。BrowseComp+での91.3%(ベース0%)という結果は、従来の要約やRAGベースのアプローチでは到達困難な水準である。一方で、depth-1再帰のみの検証、非同期実行未対応、テールコストのリスクなど、課題も明確に残されている。著者らは今後、深い再帰の効果検証と非同期サブLLM並列実行を課題として挙げている。

参考文献

この投稿は CC BY 4.0 でライセンスされています。