Fix config override bug by recreating LMs after load_state
This commit is contained in:
80
README.md
80
README.md
@@ -1,6 +1,6 @@
|
||||
# nanocode
|
||||
|
||||
Minimal Claude Code alternative using DSPy RLM! Single Python file, ~390 lines.
|
||||
Minimal Claude Code alternative using DSPy RLM! Single Python file, ~305 lines.
|
||||
|
||||
Built using Claude Code, then used to build itself.
|
||||
|
||||
@@ -41,15 +41,14 @@ from modaic import AutoProgram
|
||||
agent = AutoProgram.from_precompiled(
|
||||
"farouk1/nanocode",
|
||||
config={
|
||||
"lm": "openrouter/anthropic/claude-3.5-sonnet",
|
||||
"max_iters": 20
|
||||
"lm": "openrouter/openai/gpt-5.2-codex",
|
||||
"max_iters": 50
|
||||
}
|
||||
)
|
||||
|
||||
# Run a coding task
|
||||
result = agent(task="What Python files are in this directory?")
|
||||
print(result.answer)
|
||||
print(result.affected_files)
|
||||
```
|
||||
|
||||
### Option 2: Run Locally (Interactive CLI)
|
||||
@@ -75,13 +74,14 @@ When using as a Modaic AutoProgram, you can configure these options:
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `lm` | str | `openrouter/anthropic/claude-3.5-sonnet` | Primary language model |
|
||||
| `sub_lm` | str | `openrouter/openai/gpt-4.1` | Sub-LM for reasoning steps |
|
||||
| `max_iters` | int | `20` | Maximum agent iterations |
|
||||
| `lm` | str | `openrouter/openai/gpt-5.2-codex` | Primary language model |
|
||||
| `sub_lm` | str | `openrouter/openai/gpt-5-mini` | Sub-LM for reasoning steps |
|
||||
| `max_iters` | int | `50` | Maximum agent iterations |
|
||||
| `api_base` | str | `https://openrouter.ai/api/v1` | API base URL |
|
||||
| `max_tokens` | int | `16000` | Maximum tokens per request |
|
||||
| `max_tokens` | int | `50000` | Maximum tokens per request |
|
||||
| `max_output_chars` | int | `100000` | Maximum output character limit |
|
||||
| `verbose` | bool | `False` | Enable verbose logging |
|
||||
| `track_usage` | bool | `True` | Track token usage |
|
||||
|
||||
Example with custom configuration:
|
||||
|
||||
@@ -91,11 +91,12 @@ from modaic import AutoProgram
|
||||
agent = AutoProgram.from_precompiled(
|
||||
"farouk1/nanocode",
|
||||
config={
|
||||
"lm": "openrouter/openai/gpt-4",
|
||||
"sub_lm": "openrouter/openai/gpt-3.5-turbo",
|
||||
"lm": "openrouter/anthropic/claude-sonnet-4",
|
||||
"sub_lm": "openrouter/openai/gpt-4.1-mini",
|
||||
"max_iters": 30,
|
||||
"max_tokens": 8000,
|
||||
"verbose": True
|
||||
"verbose": True,
|
||||
"track_usage": False
|
||||
}
|
||||
)
|
||||
```
|
||||
@@ -115,14 +116,14 @@ agent = AutoProgram.from_precompiled(
|
||||
|
||||
The agent has access to the following tools:
|
||||
|
||||
| Tool | Function | Description |
|
||||
|------|----------|-------------|
|
||||
| `readfile` | `read_file(path, offset, limit)` | Read file contents with line numbers |
|
||||
| `writefile` | `write_file(path, content)` | Write content to a file |
|
||||
| `editfile` | `edit_file(path, old, new, replace_all)` | Replace text in a file (old must be unique unless `replace_all=True`) |
|
||||
| `globfiles` | `glob_files(pattern, path)` | Find files matching a glob pattern, sorted by modification time |
|
||||
| `grepfiles` | `grep_files(pattern, path)` | Search files for a regex pattern |
|
||||
| `runbash` | `run_bash(cmd)` | Run a shell command and return output |
|
||||
| Tool | Description |
|
||||
|------|-------------|
|
||||
| `read_file(path, offset, limit)` | Read file contents with line numbers |
|
||||
| `write_file(path, content)` | Write content to a file |
|
||||
| `edit_file(path, old, new, replace_all)` | Replace text in a file (old must be unique unless `replace_all=True`) |
|
||||
| `glob_files(pattern, path)` | Find files matching a glob pattern, sorted by modification time |
|
||||
| `grep_files(pattern, path)` | Search files for a regex pattern |
|
||||
| `run_bash(cmd)` | Run a shell command and return output |
|
||||
|
||||
---
|
||||
|
||||
@@ -161,7 +162,7 @@ print(result.answer)
|
||||
|
||||
# Make edits
|
||||
result = agent(task="Add a comment at the top of README.md")
|
||||
print(result.affected_files) # ['README.md']
|
||||
print(result.answer)
|
||||
```
|
||||
|
||||
---
|
||||
@@ -183,7 +184,14 @@ nanocode.py
|
||||
│ └── run_bash() - Execute commands
|
||||
├── DSPy Components
|
||||
│ ├── CodingAssistant (Signature)
|
||||
│ └── RLMCodingProgram (PrecompiledProgram)
|
||||
│ ├── RLMCodingProgram (PrecompiledProgram)
|
||||
│ │ ├── forward() - Run agent on task
|
||||
│ │ ├── get_tools() - Get available tools
|
||||
│ │ ├── set_tool() - Add/replace a tool
|
||||
│ │ ├── remove_tool() - Remove a tool
|
||||
│ │ ├── reload_lms() - Recreate LMs from config
|
||||
│ │ └── load_state() - Load state with LM fix
|
||||
│ └── RLMReasoningCallback
|
||||
└── Modaic Integration
|
||||
└── RLMCodingConfig (PrecompiledConfig)
|
||||
```
|
||||
@@ -195,13 +203,14 @@ Configuration class extending `PrecompiledConfig` for experiment-specific parame
|
||||
|
||||
```python
|
||||
class RLMCodingConfig(PrecompiledConfig):
|
||||
max_iters: int = 20
|
||||
lm: str = "openrouter/anthropic/claude-3.5-sonnet"
|
||||
sub_lm: str = "openrouter/openai/gpt-4.1"
|
||||
max_iters: int = 50
|
||||
lm: str = "openrouter/openai/gpt-5.2-codex"
|
||||
sub_lm: str = "openrouter/openai/gpt-5-mini"
|
||||
api_base: str = "https://openrouter.ai/api/v1"
|
||||
max_tokens: int = 16000
|
||||
max_tokens: int = 50000
|
||||
max_output_chars: int = 100000
|
||||
verbose: bool = False
|
||||
track_usage: bool = True
|
||||
```
|
||||
|
||||
#### `RLMCodingProgram`
|
||||
@@ -212,8 +221,20 @@ class RLMCodingProgram(PrecompiledProgram):
|
||||
config: RLMCodingConfig
|
||||
|
||||
def forward(self, task: str) -> dspy.Prediction:
|
||||
# Returns prediction with .answer and .affected_files
|
||||
# Returns prediction with .answer
|
||||
return self.agent(task=task)
|
||||
|
||||
def get_tools(self) -> dict:
|
||||
# Returns dict of available tools
|
||||
|
||||
def set_tool(self, name: str, tool: callable):
|
||||
# Add or replace a tool
|
||||
|
||||
def remove_tool(self, name: str):
|
||||
# Remove a tool by name
|
||||
|
||||
def reload_lms(self):
|
||||
# Recreate LM objects from current config
|
||||
```
|
||||
|
||||
#### `CodingAssistant`
|
||||
@@ -221,9 +242,10 @@ DSPy Signature defining the agent's input/output schema.
|
||||
|
||||
```python
|
||||
class CodingAssistant(dspy.Signature):
|
||||
task: str = dspy.InputField()
|
||||
answer: str = dspy.OutputField()
|
||||
affected_files: list[str] = dspy.OutputField()
|
||||
"""You are a concise coding assistant with access to sub agents."""
|
||||
|
||||
task: str = dspy.InputField(desc="The user's coding task or question")
|
||||
answer: str = dspy.OutputField(desc="Your response to the user after completing the task")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user