recursive-llm 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. recursive_llm-0.5.0/.github/assets/benchmark-100k.svg +39 -0
  2. recursive_llm-0.5.0/BENCHMARK_RESULTS.md +268 -0
  3. recursive_llm-0.5.0/CHANGELOG.md +146 -0
  4. recursive_llm-0.5.0/CODEX_COMPARISON.md +89 -0
  5. recursive_llm-0.5.0/DOCUMENT_EVALUATION.md +190 -0
  6. recursive_llm-0.5.0/LICENSE +21 -0
  7. recursive_llm-0.5.0/MANIFEST.in +10 -0
  8. recursive_llm-0.5.0/PKG-INFO +733 -0
  9. recursive_llm-0.5.0/README.md +695 -0
  10. recursive_llm-0.5.0/SECURITY.md +38 -0
  11. recursive_llm-0.5.0/benchmarks/codex_evaluation.schema.json +26 -0
  12. recursive_llm-0.5.0/benchmarks/compare_same_model.py +587 -0
  13. recursive_llm-0.5.0/benchmarks/document_formats.py +400 -0
  14. recursive_llm-0.5.0/benchmarks/generated_long_context.py +126 -0
  15. recursive_llm-0.5.0/benchmarks/multi_document.py +297 -0
  16. recursive_llm-0.5.0/benchmarks/repl_snapshot.py +56 -0
  17. recursive_llm-0.5.0/benchmarks/war_and_peace.py +235 -0
  18. recursive_llm-0.5.0/examples/basic_usage.py +92 -0
  19. recursive_llm-0.5.0/examples/capture_codex_comparison.py +681 -0
  20. recursive_llm-0.5.0/examples/custom_config.py +173 -0
  21. recursive_llm-0.5.0/examples/data_extraction.py +75 -0
  22. recursive_llm-0.5.0/examples/demo.py +85 -0
  23. recursive_llm-0.5.0/examples/document_presets.json +70 -0
  24. recursive_llm-0.5.0/examples/long_document.py +102 -0
  25. recursive_llm-0.5.0/examples/multi_file.py +118 -0
  26. recursive_llm-0.5.0/examples/ollama_local.py +70 -0
  27. recursive_llm-0.5.0/examples/serve_codex_comparison.py +677 -0
  28. recursive_llm-0.5.0/examples/setup_env.py +122 -0
  29. recursive_llm-0.5.0/examples/two_models.py +82 -0
  30. recursive_llm-0.5.0/pyproject.toml +94 -0
  31. recursive_llm-0.5.0/setup.cfg +4 -0
  32. recursive_llm-0.5.0/src/recursive_llm.egg-info/PKG-INFO +733 -0
  33. recursive_llm-0.5.0/src/recursive_llm.egg-info/SOURCES.txt +66 -0
  34. recursive_llm-0.5.0/src/recursive_llm.egg-info/dependency_links.txt +1 -0
  35. recursive_llm-0.5.0/src/recursive_llm.egg-info/requires.txt +16 -0
  36. recursive_llm-0.5.0/src/recursive_llm.egg-info/top_level.txt +1 -0
  37. recursive_llm-0.5.0/src/rlm/__init__.py +51 -0
  38. recursive_llm-0.5.0/src/rlm/budget.py +115 -0
  39. recursive_llm-0.5.0/src/rlm/codex.py +312 -0
  40. recursive_llm-0.5.0/src/rlm/core.py +1149 -0
  41. recursive_llm-0.5.0/src/rlm/errors.py +36 -0
  42. recursive_llm-0.5.0/src/rlm/parser.py +102 -0
  43. recursive_llm-0.5.0/src/rlm/prompts.py +54 -0
  44. recursive_llm-0.5.0/src/rlm/repl.py +684 -0
  45. recursive_llm-0.5.0/src/rlm/results.py +126 -0
  46. recursive_llm-0.5.0/src/rlm/run_state.py +192 -0
  47. recursive_llm-0.5.0/src/rlm/stats.py +162 -0
  48. recursive_llm-0.5.0/src/rlm/types.py +53 -0
  49. recursive_llm-0.5.0/tests/test_benchmark.py +242 -0
  50. recursive_llm-0.5.0/tests/test_budget.py +187 -0
  51. recursive_llm-0.5.0/tests/test_budget_lifecycle.py +152 -0
  52. recursive_llm-0.5.0/tests/test_codex.py +404 -0
  53. recursive_llm-0.5.0/tests/test_concurrency.py +71 -0
  54. recursive_llm-0.5.0/tests/test_core.py +612 -0
  55. recursive_llm-0.5.0/tests/test_document_formats_benchmark.py +101 -0
  56. recursive_llm-0.5.0/tests/test_document_runner.py +508 -0
  57. recursive_llm-0.5.0/tests/test_examples.py +22 -0
  58. recursive_llm-0.5.0/tests/test_generated_benchmark.py +92 -0
  59. recursive_llm-0.5.0/tests/test_integration.py +162 -0
  60. recursive_llm-0.5.0/tests/test_multi_document_benchmark.py +155 -0
  61. recursive_llm-0.5.0/tests/test_package_imports.py +69 -0
  62. recursive_llm-0.5.0/tests/test_parser.py +92 -0
  63. recursive_llm-0.5.0/tests/test_repl.py +416 -0
  64. recursive_llm-0.5.0/tests/test_repl_cancellation.py +159 -0
  65. recursive_llm-0.5.0/tests/test_repl_recovery.py +44 -0
  66. recursive_llm-0.5.0/tests/test_resilience.py +209 -0
  67. recursive_llm-0.5.0/tests/test_results.py +303 -0
  68. recursive_llm-0.5.0/tests/test_war_and_peace_benchmark.py +127 -0
@@ -0,0 +1,39 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="1200" height="630" viewBox="0 0 1200 630" role="img" aria-labelledby="title description">
2
+ <title id="title">Direct versus RLM on a 100k-character exact aggregation task</title>
3
+ <desc id="description">GPT-5 mini direct used 37,928 tokens and passed zero of three runs, while RLM used 8,224 tokens and passed three of three. DeepSeek V4 Flash direct used 39,364 tokens and passed zero of three, while RLM used 15,209 tokens and passed two of three.</desc>
4
+ <rect width="1200" height="630" rx="28" fill="#0b1020"/>
5
+ <text x="72" y="82" fill="#f8fafc" font-family="Inter, Arial, sans-serif" font-size="38" font-weight="700">100k-character exact aggregation</text>
6
+ <text x="72" y="122" fill="#94a3b8" font-family="Inter, Arial, sans-serif" font-size="20">Mean model tokens, with exact pass count from 3 live runs</text>
7
+
8
+ <line x1="300" y1="178" x2="1080" y2="178" stroke="#334155" stroke-width="2"/>
9
+ <line x1="300" y1="178" x2="300" y2="524" stroke="#334155" stroke-width="2"/>
10
+ <line x1="690" y1="178" x2="690" y2="524" stroke="#1e293b" stroke-width="1"/>
11
+ <line x1="1080" y1="178" x2="1080" y2="524" stroke="#1e293b" stroke-width="1"/>
12
+ <text x="300" y="160" text-anchor="middle" fill="#64748b" font-family="Inter, Arial, sans-serif" font-size="15">0</text>
13
+ <text x="690" y="160" text-anchor="middle" fill="#64748b" font-family="Inter, Arial, sans-serif" font-size="15">20k</text>
14
+ <text x="1080" y="160" text-anchor="middle" fill="#64748b" font-family="Inter, Arial, sans-serif" font-size="15">40k tokens</text>
15
+
16
+ <text x="72" y="232" fill="#e2e8f0" font-family="Inter, Arial, sans-serif" font-size="20">GPT-5 mini direct</text>
17
+ <rect x="300" y="202" width="740" height="42" rx="8" fill="#475569"/>
18
+ <text x="1024" y="230" text-anchor="end" fill="#ffffff" font-family="Inter, Arial, sans-serif" font-size="17" font-weight="700">37,928</text>
19
+ <text x="1094" y="230" fill="#f87171" font-family="Inter, Arial, sans-serif" font-size="17" font-weight="700">0/3</text>
20
+
21
+ <text x="72" y="310" fill="#e2e8f0" font-family="Inter, Arial, sans-serif" font-size="20">GPT-5 mini RLM</text>
22
+ <rect x="300" y="280" width="160" height="42" rx="8" fill="#22c55e"/>
23
+ <text x="474" y="308" fill="#bbf7d0" font-family="Inter, Arial, sans-serif" font-size="17" font-weight="700">8,224</text>
24
+ <text x="1094" y="308" fill="#4ade80" font-family="Inter, Arial, sans-serif" font-size="17" font-weight="700">3/3</text>
25
+ <text x="474" y="332" fill="#86efac" font-family="Inter, Arial, sans-serif" font-size="15">78% fewer tokens</text>
26
+
27
+ <text x="72" y="410" fill="#e2e8f0" font-family="Inter, Arial, sans-serif" font-size="20">DeepSeek direct</text>
28
+ <rect x="300" y="380" width="768" height="42" rx="8" fill="#475569"/>
29
+ <text x="1052" y="408" text-anchor="end" fill="#ffffff" font-family="Inter, Arial, sans-serif" font-size="17" font-weight="700">39,364</text>
30
+ <text x="1094" y="408" fill="#f87171" font-family="Inter, Arial, sans-serif" font-size="17" font-weight="700">0/3</text>
31
+
32
+ <text x="72" y="488" fill="#e2e8f0" font-family="Inter, Arial, sans-serif" font-size="20">DeepSeek RLM</text>
33
+ <rect x="300" y="458" width="297" height="42" rx="8" fill="#38bdf8"/>
34
+ <text x="611" y="486" fill="#bae6fd" font-family="Inter, Arial, sans-serif" font-size="17" font-weight="700">15,209</text>
35
+ <text x="1094" y="486" fill="#4ade80" font-family="Inter, Arial, sans-serif" font-size="17" font-weight="700">2/3</text>
36
+ <text x="611" y="510" fill="#7dd3fc" font-family="Inter, Arial, sans-serif" font-size="15">61% fewer tokens</text>
37
+
38
+ <text x="72" y="578" fill="#64748b" font-family="Inter, Arial, sans-serif" font-size="16">One generated corpus seed. Exact grader. July 15, 2026. Not a paper reproduction.</text>
39
+ </svg>
@@ -0,0 +1,268 @@
1
+ # Benchmark Results
2
+
3
+ These live measurements were collected on July 15, 2026 with Python 3.12.13. They are a small
4
+ engineering check, not a paper reproduction. Provider behavior is stochastic, only one generated
5
+ corpus seed was used, and prices are LiteLLM estimates.
6
+
7
+ **Grading-version note (October 2, 2026):** the historical generated-transaction,
8
+ literary, and multi-document scores below used legacy graders. Those graders could accept duplicate
9
+ contradictory labels or expected words assigned to the wrong facts. Current graders reject
10
+ these cases, and the literary tasks now request explicit fact fields. The original scores
11
+ remain historical measurements; they have not been regraded without the original raw
12
+ answers. The four available September transaction responses also pass the new grader; this
13
+ does not revalidate the older July/August runs. New runs record their grader version and must
14
+ be reported separately.
15
+
16
+ ## TXT, PDF, CSV, and HTML evaluation
17
+
18
+ An August 31, 2026 evaluation added a SHA-pinned four-format corpus, exact graders, a direct-model
19
+ comparison, staged regression runs, and independent Codex CLI verification. GPT-5 mini passed all
20
+ four baseline tasks in both modes. RLM used 78.2% fewer model tokens and 38.2% less estimated cost,
21
+ while direct completion had 5.24x lower median latency. Two isolated implementation changes were
22
+ retained: tree-wide deadline enforcement and a bounded REPL parent snapshot. Each primary live
23
+ post-change run had one model-dependent failure, and each targeted retry passed; these single runs
24
+ are therefore compatibility checks, not evidence of a quality improvement.
25
+
26
+ See [DOCUMENT_EVALUATION.md](DOCUMENT_EVALUATION.md) for sources, hashes, commands, stage-by-stage
27
+ results, rejected interpretations, and the implementation roadmap.
28
+
29
+ ## Unreleased Reliability Validation
30
+
31
+ The provider-retry, JSONL-export, and final-answer-validation changes were checked on July 16, 2026
32
+ against commit `71a5e43` and the updated working tree.
33
+
34
+ Deterministic fault injection changed the intended failure paths without changing defaults:
35
+
36
+ | Scenario | `71a5e43` | Updated behavior |
37
+ | --- | --- | --- |
38
+ | HTTP 429 followed by success | Run aborted on the 429 | Recovered with two counted calls and one retry |
39
+ | Invalid final answer followed by a correction | Invalid answer was accepted | Validator feedback produced the corrected answer in two calls |
40
+ | Structured run persistence | No result exporter | One versioned, redacted JSONL record per completed run |
41
+
42
+ With retries and validation left at their defaults, a mocked healthy-provider microbenchmark took
43
+ 111.499 microseconds per completion on `71a5e43` and 115.053 microseconds after the changes. The
44
+ 3.2% relative increase is 3.554 microseconds per completion and is negligible beside provider
45
+ latency.
46
+
47
+ One live exact-grader smoke run per previously tested model also passed without retries:
48
+
49
+ | Model | Passed | Latency | Calls | Retries | Tokens | Estimated cost |
50
+ | --- | ---: | ---: | ---: | ---: | ---: | ---: |
51
+ | GPT-5 mini | 1/1 | 29.712 s | 4 | 0 | 3,472 | $0.00362075 |
52
+ | DeepSeek V4 Flash | 1/1 | 17.883 s | 7 | 0 | 4,237 | $0.000466816 |
53
+
54
+ These smoke runs verify provider integration after retry accounting changed; they are not a new
55
+ quality comparison because model trajectories are stochastic and each model ran only once.
56
+
57
+ ## Multi-document candidate experiments
58
+
59
+ Three proposed changes were evaluated on July 17, 2026 with DeepSeek V4 Flash. The two model-facing
60
+ candidates used the same three tasks, model, `max_depth=2`, 20-iteration limit, 24-call tree limit,
61
+ 300-second limit, and three repetitions per task. The baseline and each model-facing candidate
62
+ therefore contain nine exact-graded runs. This sample is useful for rejecting clear regressions; it
63
+ is not large enough to claim a universal model-quality improvement. The non-raising result API was
64
+ evaluated separately because it does not change model behavior.
65
+
66
+ The corpora were independently sourced and distributed the required evidence across each document:
67
+
68
+ | Corpus | Prepared size | DeepSeek tokens | Task |
69
+ | --- | ---: | ---: | --- |
70
+ | Project Gutenberg *War and Peace* | 3,227,519 characters | 777,114 | Five facts from Petya's final-night sequence |
71
+ | Official 9/11 Commission Report | 1,986,811 characters | 472,370 | Six facts split between the preface and intelligence reform section |
72
+ | Official Python 3.14 text documentation | 14,626,944 characters | 3,479,078 | Four API facts from separate documentation files |
73
+
74
+ | Configuration | Passed | p50 latency | Mean calls | Mean tokens | Mean cost | Verdict |
75
+ | --- | ---: | ---: | ---: | ---: | ---: | --- |
76
+ | Existing baseline | 6/9 | 62.686 s | 16.11 | 59,033 | $0.0024388 | Retained |
77
+ | Bounded Unicode-aware search helper | 4/9 | 53.602 s | 16.33 | 70,741 | $0.0022753 | Reverted |
78
+ | Repetition and near-budget progress guard | 4/9 | 65.269 s | 16.22 | 60,898 | $0.0024707 | Reverted |
79
+
80
+ The search helper cut median latency but reduced the exact pass count from six to four and increased
81
+ mean model-token use by 19.8%. A content-bearing diagnostic trace showed that the model first guessed
82
+ the helper's result keys incorrectly, then replaced compact REPL searches with many small helper
83
+ calls. The API was computationally fast after indexing: repeat searches took 0.4 to 5.8
84
+ milliseconds, but the model interaction was worse, so the feature was not retained.
85
+
86
+ The progress guard occasionally shortened successful runs to five or six calls, but it reduced the
87
+ overall pass count from six to four, increased median latency by 4.1%, and increased mean token use
88
+ by 3.2%. It was also reverted. These results argue for improving task planning or training data
89
+ before adding generic model-facing controls.
90
+
91
+ The third proposal, structured failed-run results, does not alter prompts, tools, or model control
92
+ flow. It was retained because it turns the same failure into inspectable data without changing the
93
+ quality path. Twenty paired samples of 5,000 mocked successful runs measured a median difference of
94
+ -0.149 microseconds per run between `atry_complete_result` and `acomplete_result`, inside a measured
95
+ noise range of -3.543 to +6.509 microseconds. Three live, deliberately one-iteration runs, one per
96
+ corpus, each returned a typed `MaxIterationsError` record with exactly one counted provider call and
97
+ continued to the next task.
98
+
99
+ ### Multi-document reproduction
100
+
101
+ The inputs were fetched on July 17, 2026. The benchmark refuses artifacts whose hashes do not match
102
+ the pinned values in `benchmarks/multi_document.py`.
103
+
104
+ ```bash
105
+ mkdir -p /tmp/rlm-multi-document
106
+
107
+ curl -L https://www.gutenberg.org/files/2600/2600-0.txt \
108
+ -o /tmp/rlm-multi-document/war-and-peace.txt
109
+
110
+ curl -L https://www.govinfo.gov/content/pkg/GPO-911REPORT/pdf/GPO-911REPORT.pdf \
111
+ -o /tmp/rlm-multi-document/911-commission-report.pdf
112
+ pdftotext -layout /tmp/rlm-multi-document/911-commission-report.pdf \
113
+ /tmp/rlm-multi-document/911-commission-report.txt
114
+
115
+ curl -L https://docs.python.org/3.14/archives/python-3.14-docs-text.zip \
116
+ -o /tmp/rlm-multi-document/python-3.14-docs-text.zip
117
+
118
+ python benchmarks/multi_document.py deepseek/deepseek-v4-flash \
119
+ /tmp/rlm-multi-document --runs 3 --label baseline --jsonl results.jsonl
120
+ ```
121
+
122
+ Pinned prepared-artifact hashes are:
123
+
124
+ ```text
125
+ war-and-peace.txt e4bcf9042609b62c7de72a6f1b311f54c412943a9d641b7efcf79a464b5f31c8
126
+ 911-commission-report.pdf 657d41475eb3a9a5e3e87a6c7c51ac1dfbe1af7566d1abff7bf7286e7e1c0e1b
127
+ 911-commission-report.txt 33e5f373e542c58a872dde753caaf80e3c60c2b98c29c18898ae4590c9f4cfbe
128
+ python-3.14-docs-text.zip c8ee0347f282f97e5a57f0b010cecd441464db9fe679862f51aeda0dad12ab47
129
+ ```
130
+
131
+ The PDF has 585 pages. Pages 1, 15, 429, and 432 were rendered and visually compared with the
132
+ extracted text used by the grader. Poppler versions can produce different whitespace; if the text
133
+ hash differs, inspect the extraction before deliberately updating the pin.
134
+
135
+ ## Reproduction
136
+
137
+ ```bash
138
+ # Small deterministic tasks, three repetitions each
139
+ python benchmarks/compare_same_model.py MODEL --full --runs 3 --mode direct
140
+ python benchmarks/compare_same_model.py MODEL --full --runs 3 --mode rlm --max-depth 2
141
+
142
+ # One 100k-character deterministic task, three repetitions
143
+ python benchmarks/compare_same_model.py MODEL --generated-chars 100000 --seed 2026 --runs 3 --mode direct
144
+ python benchmarks/compare_same_model.py MODEL --generated-chars 100000 --seed 2026 --runs 3 --mode rlm --max-depth 2
145
+
146
+ # A larger RLM-only scale check
147
+ python benchmarks/compare_same_model.py MODEL --generated-chars 1000000 --seed 2026 --runs 3 --mode rlm --max-depth 2
148
+
149
+ # A SHA-pinned public-domain real document
150
+ curl -L https://www.gutenberg.org/files/2600/2600-0.txt -o /tmp/war-and-peace-2600-0.txt
151
+ python benchmarks/war_and_peace.py MODEL /tmp/war-and-peace-2600-0.txt --max-depth 2
152
+ ```
153
+
154
+ The generated context has 100,098 characters and SHA-256
155
+ `1ee43f3b42f8db55369c337d2e37f1e7f61224abe3d538581a716865df8a6fcc`. Its exact answer key is:
156
+
157
+ ```text
158
+ count=57 total_amount_cents=27404392 max_transaction_id=TX-0000883 max_amount_cents=993620
159
+ ```
160
+
161
+ ## Small tasks
162
+
163
+ The direct baseline is the correct choice for these short contexts. Both models passed every direct
164
+ run with one call. DeepSeek RLM also passed, but recursion added substantial latency and usage.
165
+
166
+ | Model and mode | Passed | p50 latency | Mean calls | Mean tokens | Mean cost |
167
+ | --- | ---: | ---: | ---: | ---: | ---: |
168
+ | GPT-5 mini, direct | 6/6 | 4.221 s | 1.00 | 598 | $0.0007996 |
169
+ | DeepSeek V4 Flash, direct | 6/6 | 2.635 s | 1.00 | 502 | $0.0000929 |
170
+ | DeepSeek V4 Flash, RLM depth 2 | 6/6 | 28.204 s | 7.17 | 6,875 | $0.0008071 |
171
+ | GPT-5 mini, RLM depth 2, incident task only | 1/3 | 167.341 s | 18.33 | 25,830 | $0.0262083 |
172
+
173
+ The GPT-5 mini RLM incident runs passed once and reached the configured 24-call cap twice. The full
174
+ small-task RLM suite was not repeated after that result because additional calls would not answer a
175
+ useful engineering question. The cap prevented a 25th provider request in both failed runs.
176
+
177
+ ## Generated 100k-character task
178
+
179
+ RLM materially improved long-context correctness. GPT-5 mini also used about 78% fewer tokens and
180
+ 46% lower estimated cost per run than its direct baseline. DeepSeek used about 61% fewer tokens and
181
+ 17% lower estimated cost, but one RLM answer omitted the `TX-` prefix and failed exact grading.
182
+
183
+ | Model and mode | Passed | p50 latency | Mean calls | Mean tokens | Mean cost |
184
+ | --- | ---: | ---: | ---: | ---: | ---: |
185
+ | GPT-5 mini, direct | 0/3 | 35.278 s | 1.00 | 37,928 | $0.0088788 |
186
+ | GPT-5 mini, RLM depth 2 | 3/3 | 26.716 s | 5.00 | 8,224 | $0.0048132 |
187
+ | DeepSeek V4 Flash, direct | 0/3 | 20.738 s | 1.00 | 39,364 | $0.0012240 |
188
+ | DeepSeek V4 Flash, RLM depth 2 | 2/3 | 20.624 s | 7.33 | 15,209 | $0.0010156 |
189
+
190
+ The generated suite originally inherited a six-iteration benchmark cutoff. Raising only this suite
191
+ to ten iterations improved the combined RLM pass rate from 4/6 to 5/6: GPT-5 mini improved from 2/3
192
+ to 3/3, while DeepSeek remained at 2/3. This setting is now the generated-suite default; the global
193
+ 24-call and 300-second caps remain unchanged.
194
+
195
+ ## Generated 1M-character scale check
196
+
197
+ The larger corpus was generated on July 17, 2026 with the same seed. It has 1,000,066 characters,
198
+ approximately 337,800 tokens according to LiteLLM's model token counters, and SHA-256
199
+ `076e6d74f9917a3ed7f0b17c0f3be49ee49ff98187d7e9918c716aa0a8074ae0`. Its exact answer key is:
200
+
201
+ ```text
202
+ count=563 total_amount_cents=275857555 max_transaction_id=TX-0004073 max_amount_cents=999063
203
+ ```
204
+
205
+ All six RLM runs passed exact grading without provider retries. A direct baseline was deliberately
206
+ not run: this check measures whether externalized context continues to work at the larger scale,
207
+ not whether sending the entire corpus to a model is economical.
208
+
209
+ | Model and mode | Passed | p50 latency | p95 latency | Mean calls | Mean tokens | Mean cost |
210
+ | --- | ---: | ---: | ---: | ---: | ---: | ---: |
211
+ | GPT-5 mini, RLM depth 2 | 3/3 | 42.744 s | 97.755 s | 7.00 | 17,613 | $0.0107284 |
212
+ | DeepSeek V4 Flash, RLM depth 2 | 3/3 | 32.203 s | 52.680 s | 9.33 | 17,538 | $0.0012495 |
213
+
214
+ Increasing the source context by roughly 10x increased mean model-token usage by 2.14x for GPT-5
215
+ mini and 1.15x for DeepSeek relative to the 100k-character RLM runs. Median latency increased by
216
+ 1.60x and 1.56x, respectively. The individual GPT-5 trajectories remained high variance: 4 to 10
217
+ calls and 19.448 to 97.755 seconds. Every successful run used only the root REPL, with
218
+ `max_depth_reached=0` in all results. This experiment therefore validates externalized context and
219
+ local computation rather than recursive semantic decomposition.
220
+
221
+ ## Real 3.2M-character document
222
+
223
+ The real-document check used the public-domain English translation of *War and Peace*, Project
224
+ Gutenberg eBook #2600. The downloaded file has SHA-256
225
+ `e4bcf9042609b62c7de72a6f1b311f54c412943a9d641b7efcf79a464b5f31c8`; after UTF-8 decoding and
226
+ line-ending normalization it contains 3,227,519 characters. LiteLLM's local counters estimate
227
+ 769,910 GPT-5 mini tokens and 777,114 DeepSeek V4 Flash tokens in the source document.
228
+
229
+ Three tasks exercise different long-document behaviors:
230
+
231
+ - exact counting of 365 narrative-body chapter headings;
232
+ - retrieval of three facts located near the beginning and end of the novel;
233
+ - synthesis of five pieces of narrative evidence from Petya's final-night sequence.
234
+
235
+ The results below use a 20-iteration cap. A direct baseline was not sent because it would require
236
+ placing roughly 770,000 source tokens in one provider request.
237
+
238
+ | Model and mode | Passed | p50 latency | p95 latency | Mean calls | Mean tokens | Mean cost |
239
+ | --- | ---: | ---: | ---: | ---: | ---: | ---: |
240
+ | GPT-5 mini, RLM depth 2 | 2/3 | 90.757 s | 117.601 s | 15.00 | 68,633 | $0.0234759 |
241
+ | DeepSeek V4 Flash, RLM depth 2 | 2/3 | 51.055 s | 100.354 s | 12.67 | 58,816 | $0.0027428 |
242
+
243
+ Both models counted the chapters exactly and retrieved the distant facts exactly. GPT-5 mini
244
+ needed 19 iterations for distant retrieval; DeepSeek needed 12. Neither model completed the
245
+ narrative synthesis task within 20 iterations, so these were execution failures rather than
246
+ incorrect final answers.
247
+
248
+ A content-bearing failure trace showed the main weakness clearly: the model found the death scene
249
+ but spent later iterations on broad `Cossack` searches, a literal `Petya` search that missed
250
+ `Pétya`, large match dumps, and a character-by-character scan. A proposed generic search-efficiency
251
+ prompt was tested at the original 12-iteration cap, did not improve the pass rate, and increased
252
+ token use on the narrative task, so it was reverted. The retained improvement is observability:
253
+ failed traced runs now preserve their partial trajectory instead of returning an empty event list.
254
+
255
+ All measured calls stayed at the root REPL with `max_depth_reached=0`. The benchmark therefore
256
+ identifies a concrete next problem: efficient semantic navigation and deliberate child-model use
257
+ over real prose, rather than raw context capacity alone.
258
+
259
+ ## Interpretation
260
+
261
+ - Use direct completion for short contexts that fit comfortably in the model window.
262
+ - RLM is useful here when exact computation over a large context matters; the context stays outside
263
+ model prompts and Python performs the aggregation.
264
+ - `max_depth=2` did not force recursion. The successful generated runs used the root REPL only, which
265
+ is an important reminder that RLM's value includes externalized context and local computation, not
266
+ only child-model calls.
267
+ - Three repetitions and one seed are enough to catch regressions, but not enough for broad model
268
+ quality claims. Use more seeds and runs for release decisions.
@@ -0,0 +1,146 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ ## [Unreleased]
6
+
7
+ ## [0.5.0] - 2026-10-02
8
+
9
+ ### Added
10
+
11
+ - A side-by-side web visualizer and downloadable film of real RLM and direct GPT-5.6 Luna runs,
12
+ with synchronized replay, call trees, recorded Python steps, import, and JSON export.
13
+ - An optional async completion handler, propagated across child RLMs, and a bounded Codex CLI
14
+ transport for ChatGPT-authenticated subscription experiments without API keys.
15
+ - A reproducible paired capture script, 10k and 100k generated-source recordings, and an explicit
16
+ methodology distinguishing total CLI tokens from subscription billing.
17
+
18
+ ### Changed
19
+
20
+ - Made the paired Codex capture model, reasoning effort, and recursion depth configurable while
21
+ retaining the historical Luna/medium/depth-1 defaults and recording the actual settings.
22
+ - Versioned stricter generated-transaction and document fact graders; historical benchmark scores
23
+ remain labeled as results of their original grading rules.
24
+ - Added frontend type, test, and build checks and Python PDF coverage to CI.
25
+ - Updated the visualizer's React, Vite, Vinext, and Cloudflare dependencies to patched,
26
+ peer-compatible releases, with a scoped Satori decompressor override.
27
+
28
+ ### Fixed
29
+
30
+ - Stopped admitting calls after a shared usage budget is exhausted and drained cancelled callbacks
31
+ before publishing the final run statistics and trajectory.
32
+ - Removed deleted REPL variables from recovery snapshots and prevented final answers from using
33
+ an obsolete parent snapshot after worker loss.
34
+ - Enabled ordinary, nested, and starred assignment unpacking in the restricted Python worker.
35
+ - Separated process-readiness allowances from cancellation assertions in coverage-instrumented tests.
36
+ - Deferred the public `RLM` import so standalone REPL workers start without importing LiteLLM.
37
+ - Kept the visualizer's required `lib` sources visible to Git.
38
+
39
+ ## [0.4.0] - 2026-08-31
40
+
41
+ ### Added
42
+
43
+ - A SHA-pinned exact-graded document benchmark covering a Project Gutenberg TXT book, the NIST AI
44
+ RMF Playbook in PDF and CSV forms, and the official Python sqlite3 HTML documentation.
45
+ - A deterministic REPL snapshot IPC benchmark and structured Codex CLI verification schema.
46
+
47
+ ### Changed
48
+
49
+ - Capped parent-side REPL state snapshots at 1 MB by default while preserving complete variables
50
+ in the persistent worker and explicit variable retrieval.
51
+
52
+ ### Fixed
53
+
54
+ - Applied the shared elapsed-time budget to REPL exchanges and prevented answers completed by a
55
+ late final-answer validator from being accepted after the tree deadline.
56
+ - Capped LiteLLM below 1.98.0 because that release imports Python 3.11-only typing symbols during
57
+ startup and breaks the supported Python 3.9 and 3.10 environments.
58
+
59
+ ## [0.3.1] - 2026-07-28
60
+
61
+ ### Fixed
62
+
63
+ - Pinned Ruff 0.16.0 and made the stable baseline rules explicit for reproducible local and CI
64
+ checks.
65
+
66
+ ## [0.3.0] - 2026-07-25
67
+
68
+ ### Added
69
+
70
+ - Opt-in, budget-aware retries for transient provider failures with exponential backoff,
71
+ `Retry-After` support, exact retry statistics, and trajectory events.
72
+ - Versioned JSONL export for structured completion results with secret-free run configuration.
73
+ - Final-answer validation with deterministic model feedback and support for directives, REPL
74
+ variables, and mutable answer publication.
75
+ - A reproducible 1M-character scale check with exact grading and live GPT-5 mini and DeepSeek V4
76
+ Flash results.
77
+ - A SHA-pinned real-document benchmark over the public-domain English translation of *War and
78
+ Peace*, with exact graders for structure, distant retrieval, and narrative evidence synthesis.
79
+ - A read-only `RLM.trajectory` snapshot that preserves partial events from failed runs.
80
+ - Non-raising `try_complete_result` and `atry_complete_result` APIs with typed, versioned failure
81
+ records and exact per-run diagnostics.
82
+ - A SHA-pinned three-document benchmark covering a 3.2M-character novel, a 2.0M-character official
83
+ report, and a 14.6M-character documentation corpus.
84
+
85
+ ### Changed
86
+
87
+ - Normalized null provider text content into the existing empty-response repair path and added
88
+ explicit errors for malformed provider response structures.
89
+ - Disabled hidden LiteLLM retries so every real retry is governed by tree-wide budgets.
90
+ - Preserved content-bearing benchmark trajectories when a traced run raises an exception.
91
+ - Updated the benchmark runner to consume success and failure results through one structured API.
92
+
93
+ ## [0.2.0] - 2026-07-15
94
+
95
+ ### Migration notes
96
+
97
+ - Replace `RLM.completion(...)` with `RLM.complete(...)` and `RLM.acompletion(...)` with
98
+ `RLM.acomplete(...)`.
99
+ - The default `max_depth` is now `1` instead of `5`. Depth follows the paper's capability-based
100
+ convention: `0` enables only the root REPL, `1` permits plain-LM subcalls, and `2` permits one
101
+ child RLM level with a plain-LM boundary fallback.
102
+
103
+ ### Added
104
+
105
+ - Tree-wide call, token, cost, and elapsed-time budgets with partial statistics on budget errors.
106
+ - Structured completion results with exact per-run statistics and root/child/leaf trajectories.
107
+ - Safe concurrent use of the same `RLM` instance through isolated per-invocation state.
108
+ - Optional POSIX memory, CPU-time, and open-file limits for REPL workers.
109
+ - Deterministic long-context benchmark generation, exact task graders, repeated runs, direct-model
110
+ baselines, JSONL output, and checked-in live benchmark results.
111
+ - GitHub Actions checks across Python 3.9-3.12 on Linux and Python 3.12 on macOS and Windows.
112
+ - Security guidance describing the REPL isolation model and its trust boundary.
113
+
114
+ ### Changed
115
+
116
+ - Aligned recursion-depth behavior and documentation with the RLM paper's depth convention.
117
+ - Hardened REPL execution with spawned workers, persistent state, hard local-step timeouts, bounded
118
+ output, restricted imports, and ordered bounded-concurrency subcalls.
119
+ - Aggregated usage and best-effort cost statistics across the complete recursion tree.
120
+ - Updated repository, installation, citation, release, and issue links to `grishahq/recursive-llm`.
121
+ - Pinned the formatter to a Python 3.9-compatible version and updated GitHub Actions to Node 24-based
122
+ releases for reproducible, warning-free CI runs.
123
+ - Expanded the test suite from 43 initial-release tests to 135 tests with enforced branch coverage.
124
+
125
+ ### Fixed
126
+
127
+ - Required final-answer directives to be standalone executable statements instead of accepting
128
+ occurrences embedded in arbitrary text.
129
+ - Prevented models from guessing context contents before inspecting the REPL context.
130
+ - Corrected parameter handling for GPT-5-family models.
131
+ - Made persistent REPL variables visible inside comprehension bodies on Python 3.9-3.11 while
132
+ keeping restricted runtime helpers out of parent snapshots.
133
+ - Prevented REPL worker pipe errors from leaking tracebacks during budget-triggered shutdown.
134
+ - Corrected offline-demo aggregation and strengthened benchmark numeric-boundary grading.
135
+
136
+ ## [0.1.0] - 2025-10-17
137
+
138
+ - Initial public release.
139
+
140
+ [Unreleased]: https://github.com/grishahq/recursive-llm/compare/v0.5.0...HEAD
141
+ [0.5.0]: https://github.com/grishahq/recursive-llm/compare/v0.4.0...v0.5.0
142
+ [0.4.0]: https://github.com/grishahq/recursive-llm/compare/v0.3.1...v0.4.0
143
+ [0.3.1]: https://github.com/grishahq/recursive-llm/compare/v0.3.0...v0.3.1
144
+ [0.3.0]: https://github.com/grishahq/recursive-llm/compare/v0.2.0...v0.3.0
145
+ [0.2.0]: https://github.com/grishahq/recursive-llm/compare/v0.1.0...v0.2.0
146
+ [0.1.0]: https://github.com/grishahq/recursive-llm/releases/tag/v0.1.0
@@ -0,0 +1,89 @@
1
+ # Codex subscription comparison
2
+
3
+ Recorded on September 8, 2026 to accompany the 600-star visualizer. Both modes use `gpt-5.6-luna` with medium reasoning through Codex CLI 0.149.0, authenticated with ChatGPT. No API key was used.
4
+
5
+ Each row is **one paired experiment**, with direct mode first. These observations do not establish a general quality, latency, or subscription-efficiency advantage.
6
+
7
+ | Generated source | Mode | Exact fields | Total CLI model tokens | Cached input | Model calls | Elapsed |
8
+ | --- | --- | ---: | ---: | ---: | ---: | ---: |
9
+ | 10,104 characters | Direct | 4/4 | 6,007 | 0 | 1 | 9.172 s |
10
+ | 10,104 characters | RLM | 4/4 | 19,430 | 0 | 5 | 48.488 s |
11
+ | 100,098 characters | Direct | 4/4 | 37,521 | 0 | 1 | 29.040 s |
12
+ | 100,098 characters | RLM | 4/4 | 11,656 | 0 | 3 | 30.707 s |
13
+
14
+ On the larger task, RLM used **68.9% fewer total CLI model tokens**, while taking approximately 1.7 seconds longer. The smaller task favored direct completion in both token use and latency. All four answers matched the deterministic answer key. Model tokens are not a measurement of how many subscription credits or percentage points were consumed.
15
+
16
+ ## What is held constant
17
+
18
+ Both sides receive the same query and deterministic source (seed 2026), use the same exact model and reasoning effort, and share the same Codex text-completion wrapper. Each model call starts a fresh ephemeral Codex session. User configuration is ignored; existing ChatGPT authentication is retained. Neither side receives answer-key feedback.
19
+
20
+ Direct mode receives the full context in one model request. RLM runs the library's existing control loop and restricted Python REPL. The model receives RLM instructions and observations; the full source remains in the REPL. Therefore the mode-specific prompts differ by design. RLM call history and CLI instruction overhead count toward reported usage. Both displayed runs used the root REPL, without child RLM calls.
21
+
22
+ Codex host capabilities are disabled where supported. Luna requires its Code Mode host to initialize; its presence is not counted as a tool call. Any actual tool-use item in the CLI event stream invalidates the run. Both completed pairs contain only `agent_message` items, with no Codex tool calls. Python execution occurs in the library's REPL.
23
+
24
+ ## Metric definitions and replay
25
+
26
+ - **Total CLI model tokens:** reported input plus output over every completed model call. Cached input is included in total input, not subtracted. Incomplete usage is reported as unknown rather than as a complete total.
27
+ - **Elapsed:** wall-clock time for each mode, including CLI startup, network time, and RLM execution. Runs were sequential; the page aligns both timelines by elapsed time for comparison.
28
+ - **Exact fields:** count, sum of amount in cents, largest transaction ID, and its amount. No grader feedback is supplied during generation.
29
+ - **Subscription billing:** no per-run dollar charge or inferred subscription-percentage saving is reported.
30
+ - **Video:** real event timestamps are replayed with the same acceleration factor on both sides. Introductory diagrams explain the execution path; recorded Python and final answers come from the captured runs.
31
+
32
+ The 10k run encountered REPL helper errors and recovered within the original library loop. Those events remain in the recording; the REPL was not changed to improve the experiment. An initial CLI startup failure on both sides is preserved separately as `startup-diagnostic*`; it is infrastructure evidence, not a failed model answer or a performance trial. The finalized runner marks execution failures as ungraded.
33
+
34
+ ## Artifacts and reproduction
35
+
36
+ [Captured experiments](experiments/codex-luna-20260908/) contain the comparison JSON, raw provider events and messages, and a transport manifest with the CLI version and shared wrapper. The corpus is synthetic; no private document was used. The hashes are:
37
+
38
+ - 10k: `753ce91f5a0d19351081775d4529a379358b0ff132bfb350c8f2050627f15236`
39
+ - 100k: `1ee43f3b42f8db55369c337d2e37f1e7f61224abe3d538581a716865df8a6fcc`
40
+
41
+ ```bash
42
+ pip install -e .
43
+ codex login
44
+ python examples/capture_codex_comparison.py --chars 10000 --output comparison-10k.json
45
+ python examples/capture_codex_comparison.py --chars 100000 --output comparison-100k.json
46
+ ```
47
+
48
+ The historical settings remain the defaults. For a new comparison with Sol 6.1,
49
+ select the shared model and reasoning effort explicitly:
50
+
51
+ ```bash
52
+ python examples/capture_codex_comparison.py --model gpt-6.1-sol \
53
+ --reasoning-effort low --max-depth 0 --chars 10000 --output sol-root-only.json
54
+ ```
55
+
56
+ `--max-depth 0` runs the root REPL without subcalls; depth 1 permits plain model
57
+ leaves and depth 2 permits child RLMs. Both modes receive the selected model and
58
+ reasoning effort, and raw and replay recordings retain those settings. The web
59
+ companion continues to use Luna, medium reasoning, and depth 1.
60
+
61
+ These commands consume the signed-in account's Codex subscription allowance. [The visualizer](visualizer/README.md) can open the resulting comparison JSON locally in the browser. The companion `.raw.json` retains messages and raw events and should be reviewed before sharing a run on private source material.
62
+
63
+ For a custom source, supply `--context-file` and `--query` together. Custom answers require manual review unless you provide a reference map with `--expected-fields answers.json`:
64
+
65
+ ```bash
66
+ python examples/capture_codex_comparison.py \
67
+ --context-file document.txt --query "What are the main findings?" \
68
+ --output my-comparison.json
69
+ ```
70
+
71
+ ## Run your own document from the web page
72
+
73
+ Install the optional document parser and start the companion in your own terminal:
74
+
75
+ ```bash
76
+ pip install -e '.[visualizer]'
77
+ codex login
78
+ python examples/serve_codex_comparison.py
79
+ ```
80
+
81
+ The companion listens at `http://127.0.0.1:8766` and prints a temporary pairing code. Paste that code into the page's connection form. Keep the terminal open. The code changes whenever the companion restarts; it is never saved in a recording or logged with HTTP requests. `--port` changes the local port. `--allow-origin https://your-page.example` permits an additional exact page origin.
82
+
83
+ Choose a preset or upload TXT, Markdown, CSV, JSON, RST, PDF, or DOCX, then enter the question and run the comparison. Each explicit run uses the signed-in account's Codex allowance. Selecting a preset alone does not invoke a model. The companion downloads the selected preset over HTTPS on demand and verifies its SHA256 before attaching the corresponding reference answer.
84
+
85
+ Files are limited to 5 MiB and extracted text to 300,000 characters. DOCX parsing reads body text and tables without extracting archive files; expanded content is limited to 20 MiB. PDF parsing extracts existing text with no OCR, so scans need OCR first and complicated tables may lose structure. The extracted preview is shown before the model results. Uploaded source text stays in the local companion and is sent through Codex when you run the comparison. The hosted page receives the preview, progress, model outputs, and evaluation fields.
86
+
87
+ Preset questions have explicit reference fields. Changing a preset question disables its reference key unless you supply a new one. Custom questions without a key show **manual review**, with no invented quality score. An optional reference map is a JSON object such as `{"project_name":"Orion","total":12,"approved":true}`. The model receives only the required field names and JSON output format; expected values are withheld. Numbers are compared exactly, booleans retain their JSON type, and ordinary text ignores case, whitespace, and quote/dash typography. Whitespace-only strings are compared exactly. Missing, duplicate, or incorrectly typed fields fail their checks; transport failures remain ungraded.
88
+
89
+ The page polls actual progress once per second. Only one comparison can run at a time, and Cancel interrupts the active run. Raw traces are saved in the private temporary directory printed by the companion, or a directory selected with `--output-dir`. Review private source material before sharing any recording. The companion binds only the loopback interface, requires bearer pairing on every data endpoint, and accepts browser requests only from its explicit origin allowlist.