feat: add RLM (Recursive Language Model) module for REPL-based context exploration#88
feat: add RLM (Recursive Language Model) module for REPL-based context exploration#88JamesHWade wants to merge 2 commits intomainfrom
Conversation
…t exploration RLM transforms context from "input" to "environment", enabling LLMs to programmatically explore large contexts through a REPL interface rather than embedding them in prompts. Key features: - rlm_module() factory function for creating RLM modules - SUBMIT() termination mechanism for returning final answers - peek() and search() tools for context exploration - Support for recursive LLM calls via sub_lm parameter - Custom tools injection for domain-specific operations - Fallback extraction when max_iterations reached - Full integration with module() factory via type = "rlm" Based on DSPy 3.1.2's RLM module (PR #9193). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fe94d53a1a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| query <- request$query | ||
| context_slice <- request$context | ||
|
|
There was a problem hiding this comment.
Handle rlm_query_batch requests in process_rlm_query
The prelude’s rlm_query_batch() returns an rlm_query_request with queries/slices and batch = TRUE (see R/rlm-tools.R around lines 120–133), but process_rlm_query() only reads request$query and request$context (lines below). For batch requests those fields are NULL, so the prompt becomes NULL and sub_lm$chat(NULL) will error or produce garbage, meaning rlm_query_batch() is unusable despite being advertised in the prompt/docs. You likely need to branch on request$batch and iterate or combine queries into a single prompt, and enforce the call limit accordingly.
Useful? React with 👍 / 👎.
Critical fixes: - Fix silent failure in fallback extraction (log warning, return structured error) - Fix silent swallowing of recursive query errors (return structured result) - Implement rlm_query_batch handling in process_rlm_query() Important fixes: - Add validation for runner result structure - Add NULL checks in format_execution_output() - Fix unused context variable (was building but passing inputs) - Add bounds validation for max_iterations (>= 1) and max_llm_calls (>= 0) - Validate all tools are functions in rlm_module() Improvements: - Use extract_rlm_final() helper instead of inline duplication - Use is_rlm_final() and is_rlm_query_request() helper functions - Use setNames() for cleaner output building - Fix awkward line break in duration calculation - Add warning when max_iterations exhausted (previously only logged in verbose) - Update documentation: clarify tools parameter, fix "Placeholder" wording New tests: - Test tools validation (non-function values) - Test max_iterations bounds validation - Test max_llm_calls bounds validation - Test fallback warning message - Test LLM response validation (missing/invalid code) - Test rlm_query_batch marker generation - Test rlm_query_batch validation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code ReviewI found 1 issue that needs attention: Missing cache handling for stateful mock LLMFile: The
Problem: All tests using this mock lack cache handling (no Affected tests include:
Recommended fix: Add result <- rlm$forward(
list(question = "test"),
.llm = mock_llm,
.cache = FALSE # Disable cache for stateful mock
)Or add See CLAUDE.md example (lines 416-448) for the complete pattern. |
Summary
This PR implements the RLM (Recursive Language Model) module for dsprrr, bringing DSPy 3.1.2's RLM capability to R. RLM transforms context from "input" to "environment", enabling LLMs to programmatically explore large contexts through a REPL interface.
Key features:
rlm_module()factory function for creating RLM modulesSUBMIT()termination mechanism for returning final answerspeek()andsearch()tools for context explorationsub_lmparametermax_iterationsreachedmodule()factory viatype = "rlm"Key Innovation: Instead of
llm(prompt, context=huge_document), RLM stores context as R variables that the LLM can peek, slice, search, and recursively query.Files Changed
R/module-rlm.R- Main RLMModule R6 class andrlm_module()factoryR/rlm-tools.R- RLM prelude generator with SUBMIT, peek, search toolsR/module.R- Updated to supporttype = "rlm"tests/testthat/test-module-rlm.R- 76 comprehensive unit tests_pkgdown.yml- Added documentation entriesTest plan
🤖 Generated with Claude Code