Skip to content

Commit 1c446ce

Browse files
kmadalexzhang13
andauthored
Quickstart Fixes (#1)
* Changed to correct import * Added null checks to rlm core * Added example to quickstart script * Move quickstart to examples folder * Remove uv.lock changes * Merged rlm_example and quickstart * Wrap model reference in _to_str * Update README with quickstart example * Refine Quick Setup instructions in README Updated setup instructions for clarity and formatting. --------- Co-authored-by: az <alex.lx.zhang@gmail.com>
1 parent 76db8de commit 1c446ce

6 files changed

Lines changed: 56 additions & 35 deletions

File tree

‎README.md‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,22 @@ pip install git+https://github.com/alexzhang13/rlm.git
4747

4848
## Quick Setup
4949
Set up the dependencies with `uv` (or your virtual environment of choice):
50-
```
50+
```bash
5151
curl -LsSf https://astral.sh/uv/install.sh | sh
5252
uv init && uv venv --python 3.12 # change version as needed
5353
uv pip install -e .
5454
```
5555

56+
To run a quick test, make sure your `OPENAI_API_KEY` is set properly and run the following:
57+
```bash
58+
cd examples/
59+
uv run quickstart.py
60+
```
61+
62+
This will generate console output as well as a log which you can use with the visualizer to explore the trajectories.
63+
64+
65+
## REPL Environments
5666
The default RLM object uses a REPL environment that runs on the host process through Python `exec` calls. It uses the same virtual environment as the host process (i.e. it will have access to the same dependencies), but with some limitations in its available global modules. As an example, we can call RLM completions using GPT-5-nano with the Portkey client:
5767
```python
5868
from rlm import RLM
@@ -66,7 +76,6 @@ rlm = RLM(
6676
print(rlm.completion("Print me the first 100 powers of two, each on a newline.").response)
6777
```
6878

69-
## REPL Environments
7079
We support two types of REPL environments -- isolated, and non-isolated. Non-isolated environments (default) run code execution on the same machine as the RLM (e.g. through `exec`), which is pretty reasonable for some local low-risk tasks, like simple benchmarking, but can be problematic if the prompts or tool calls can interact with malicious users. Fully isolated environments used Cloud-based sandboxes (e.g. Prime Sandboxes, [Modal Sandboxes](https://modal.com/docs/guide/sandboxes)) to run code generated by the RLM, ensuring completely isolation from the host process. Environments can be added, but we natively support the following: `local` (default), `modal`, `prime`.
7180

7281
```python

‎examples/quickstart.py‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import os
2+
3+
from dotenv import load_dotenv
4+
5+
from rlm import RLM
6+
from rlm.logger import RLMLogger
7+
8+
load_dotenv()
9+
10+
logger = RLMLogger(log_dir="./logs")
11+
12+
rlm = RLM(
13+
backend="openai", # or "portkey", etc.
14+
backend_kwargs={
15+
"model_name": "gpt-5-nano",
16+
"api_key": os.getenv("OPENAI_API_KEY"),
17+
},
18+
environment="local",
19+
environment_kwargs={},
20+
max_depth=1,
21+
logger=logger,
22+
verbose=True, # For printing to console with rich, disabled by default.
23+
)
24+
25+
result = rlm.completion("Print me the first 100 powers of two, each on a newline.")
26+
27+
print(result)

‎examples/rlm_example.py‎

Lines changed: 0 additions & 25 deletions
This file was deleted.

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ description = "Recursive Language Models."
88
readme = "README.md"
99
requires-python = ">=3.11"
1010
dependencies = [
11-
"dotenv>=0.9.9",
1211
"openai>=2.14.0",
1312
"portkey-ai>=2.1.0",
13+
"python-dotenv>=1.2.1",
1414
"requests>=2.32.5",
1515
"rich>=13.0.0",
1616
]

‎rlm/core/rlm.py‎

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ def __init__(
7171
self.backend = backend
7272
self.backend_kwargs = backend_kwargs
7373
self.environment_type = environment
74-
self.environment_kwargs = environment_kwargs.copy()
74+
self.environment_kwargs = (
75+
environment_kwargs.copy() if environment_kwargs is not None else {}
76+
)
7577
self.other_backends = other_backends
7678
self.other_backend_kwargs = other_backend_kwargs
7779

@@ -85,13 +87,17 @@ def __init__(
8587
# Log metadata if logger is provided
8688
if self.logger or verbose:
8789
metadata = RLMMetadata(
88-
root_model=backend_kwargs.get("model_name", "unknown"),
90+
root_model=backend_kwargs.get("model_name", "unknown")
91+
if backend_kwargs
92+
else "unknown",
8993
max_depth=max_depth,
9094
max_iterations=max_iterations,
9195
backend=backend,
92-
backend_kwargs=filter_sensitive_keys(backend_kwargs),
96+
backend_kwargs=filter_sensitive_keys(backend_kwargs) if backend_kwargs else {},
9397
environment_type=environment,
94-
environment_kwargs=filter_sensitive_keys(environment_kwargs),
98+
environment_kwargs=filter_sensitive_keys(environment_kwargs)
99+
if environment_kwargs
100+
else {},
95101
other_backends=other_backends,
96102
)
97103
if self.logger:
@@ -196,7 +202,9 @@ def completion(
196202
self.verbose.print_final_answer(final_answer)
197203
self.verbose.print_summary(i + 1, time_end - time_start, usage.to_dict())
198204
return RLMChatCompletion(
199-
root_model=self.backend_kwargs.get("model_name", "unknown"),
205+
root_model=self.backend_kwargs.get("model_name", "unknown")
206+
if self.backend_kwargs
207+
else "unknown",
200208
prompt=prompt,
201209
response=final_answer,
202210
usage_summary=usage,
@@ -216,7 +224,9 @@ def completion(
216224
self.verbose.print_final_answer(final_answer)
217225
self.verbose.print_summary(self.max_iterations, time_end - time_start, usage.to_dict())
218226
return RLMChatCompletion(
219-
root_model=self.backend_kwargs.get("model_name", "unknown"),
227+
root_model=self.backend_kwargs.get("model_name", "unknown")
228+
if self.backend_kwargs
229+
else "unknown",
220230
prompt=prompt,
221231
response=final_answer,
222232
usage_summary=usage,

‎rlm/logger/verbose.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ def print_subcall(
277277
header = Text()
278278
header.append(" ↳ ", style=STYLE_SECONDARY)
279279
header.append("Sub-call: ", style=STYLE_SECONDARY)
280-
header.append(model, style=STYLE_ACCENT)
280+
header.append(_to_str(model), style=STYLE_ACCENT)
281281
if execution_time:
282282
header.append(f" ({execution_time:.2f}s)", style=STYLE_MUTED)
283283

0 commit comments

Comments
 (0)