dspy-code_act 1.0.2 → 1.0.3
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.
- checksums.yaml +4 -4
- data/README.md +23 -178
- data/lib/dspy/code_act/README.md +48 -123
- data/lib/dspy/code_act/version.rb +1 -1
- data/lib/dspy/code_act.rb +19 -0
- metadata +9 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1e81ad2629b9d652887180a6209dc803301c39a8989317907fd92e4b0bd08c40
|
|
4
|
+
data.tar.gz: 41f24b4c59be3ee80d3eaaa329fa0d4c1ded4b44ba62f337fd36328271cb886b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 52355d8730ca9f9f3455bfc87e6fba782a934feece0ccc418cd1adec8c4bd597191cf9975c66afded7dbfb5c41bcbc751c1bee6c2c4e0d72b569fc92d04b6ed6
|
|
7
|
+
data.tar.gz: ed2f38b62d55cf52a8f93755c432138aa6686e644b2175d74c03ab79c0812e77a62a078938b3a0e7d7908469f00e431731d77b8a75833fd1d94c096f11acd0fc
|
data/README.md
CHANGED
|
@@ -6,95 +6,16 @@
|
|
|
6
6
|
[](https://oss.vicente.services/dspy.rb/)
|
|
7
7
|
[](https://discord.gg/zWBhrMqn)
|
|
8
8
|
|
|
9
|
-
**Build
|
|
9
|
+
**Build typed agents and model-backed programs in Ruby.**
|
|
10
10
|
|
|
11
|
-
DSPy.rb
|
|
11
|
+
DSPy.rb brings [DSPy](https://dspy.ai)'s signature, module, agent, and optimizer model to Ruby, with Sorbet types and Ruby-native integrations. A signature declares a task as typed inputs and outputs. A module chooses how to execute it. Ruby composes modules into programs, while `ReAct` adds a bounded loop when the model should choose the next action. DSPy.rb builds the provider request and validates the returned shape.
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
require 'dspy'
|
|
15
|
-
|
|
16
|
-
DSPy.configure do |c|
|
|
17
|
-
c.lm = DSPy::LM.new('openai/gpt-4o-mini', api_key: ENV['OPENAI_API_KEY'])
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
class Summarize < DSPy::Signature
|
|
21
|
-
description "Summarize the given text in one sentence."
|
|
22
|
-
|
|
23
|
-
input do
|
|
24
|
-
const :text, String
|
|
25
|
-
end
|
|
13
|
+
The `1.x` series is the current stable release line.
|
|
26
14
|
|
|
27
|
-
|
|
28
|
-
const :summary, String
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
summarizer = DSPy::Predict.new(Summarize)
|
|
33
|
-
result = summarizer.call(text: "DSPy.rb brings structured LLM programming to Ruby...")
|
|
34
|
-
puts result.summary
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
That's it. No prompt templates. No JSON parsing. No prayer-based error handling.
|
|
38
|
-
|
|
39
|
-
## Installation
|
|
40
|
-
|
|
41
|
-
```ruby
|
|
42
|
-
# Gemfile
|
|
43
|
-
gem 'dspy'
|
|
44
|
-
gem 'dspy-openai' # For OpenAI, OpenRouter, or Ollama
|
|
45
|
-
# gem 'dspy-anthropic' # For Claude
|
|
46
|
-
# gem 'dspy-gemini' # For Gemini
|
|
47
|
-
# gem 'dspy-ruby_llm' # For 12+ providers via RubyLLM
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
bundle install
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## Quick Start
|
|
55
|
-
|
|
56
|
-
### Configure Your LLM
|
|
57
|
-
|
|
58
|
-
```ruby
|
|
59
|
-
# OpenAI
|
|
60
|
-
DSPy.configure do |c|
|
|
61
|
-
c.lm = DSPy::LM.new('openai/gpt-4o-mini',
|
|
62
|
-
api_key: ENV['OPENAI_API_KEY'],
|
|
63
|
-
structured_outputs: true)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# Anthropic Claude
|
|
67
|
-
DSPy.configure do |c|
|
|
68
|
-
c.lm = DSPy::LM.new('anthropic/claude-sonnet-4-20250514',
|
|
69
|
-
api_key: ENV['ANTHROPIC_API_KEY'])
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Google Gemini
|
|
73
|
-
DSPy.configure do |c|
|
|
74
|
-
c.lm = DSPy::LM.new('gemini/gemini-2.5-flash',
|
|
75
|
-
api_key: ENV['GEMINI_API_KEY'])
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# Ollama (local, free)
|
|
79
|
-
DSPy.configure do |c|
|
|
80
|
-
c.lm = DSPy::LM.new('ollama/llama3.2')
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# OpenRouter (200+ models)
|
|
84
|
-
DSPy.configure do |c|
|
|
85
|
-
c.lm = DSPy::LM.new('openrouter/deepseek/deepseek-chat-v3.1:free',
|
|
86
|
-
api_key: ENV['OPENROUTER_API_KEY'])
|
|
87
|
-
end
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### Define a Signature
|
|
91
|
-
|
|
92
|
-
Signatures are typed contracts for LLM operations. Define inputs, outputs, and let DSPy handle the prompt:
|
|
15
|
+
In a configured application, the task contract and call look like this:
|
|
93
16
|
|
|
94
17
|
```ruby
|
|
95
18
|
class Classify < DSPy::Signature
|
|
96
|
-
description "Classify sentiment of a given sentence."
|
|
97
|
-
|
|
98
19
|
class Sentiment < T::Enum
|
|
99
20
|
enums do
|
|
100
21
|
Positive = new('positive')
|
|
@@ -104,7 +25,7 @@ class Classify < DSPy::Signature
|
|
|
104
25
|
end
|
|
105
26
|
|
|
106
27
|
input do
|
|
107
|
-
const :sentence, String
|
|
28
|
+
const :sentence, String
|
|
108
29
|
end
|
|
109
30
|
|
|
110
31
|
output do
|
|
@@ -114,115 +35,39 @@ class Classify < DSPy::Signature
|
|
|
114
35
|
end
|
|
115
36
|
|
|
116
37
|
classifier = DSPy::Predict.new(Classify)
|
|
117
|
-
result = classifier.call(sentence: "This book was
|
|
118
|
-
|
|
119
|
-
result.sentiment # => #<Sentiment::Positive>
|
|
120
|
-
result.confidence # => 0.92
|
|
38
|
+
result = classifier.call(sentence: "This book was fun to read!")
|
|
121
39
|
```
|
|
122
40
|
|
|
123
|
-
|
|
41
|
+
Define a typed task contract instead of maintaining an output template. Receive validated Ruby values instead of parsing provider JSON. Handle configuration, transport, and validation errors explicitly.
|
|
124
42
|
|
|
125
|
-
|
|
43
|
+
## Start Here
|
|
126
44
|
|
|
127
|
-
|
|
128
|
-
solver = DSPy::ChainOfThought.new(MathProblem)
|
|
129
|
-
result = solver.call(problem: "If a train travels 120km in 2 hours, what's its speed?")
|
|
130
|
-
|
|
131
|
-
result.reasoning # => "Speed = Distance / Time = 120km / 2h = 60km/h"
|
|
132
|
-
result.answer # => "60 km/h"
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### ReAct Agents
|
|
136
|
-
|
|
137
|
-
Build agents that use tools to accomplish tasks:
|
|
138
|
-
|
|
139
|
-
```ruby
|
|
140
|
-
class SearchTool < DSPy::Tools::Tool
|
|
141
|
-
tool_name "search"
|
|
142
|
-
description "Search for information"
|
|
143
|
-
|
|
144
|
-
input do
|
|
145
|
-
const :query, String
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
output do
|
|
149
|
-
const :results, T::Array[String]
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
def call(query:)
|
|
153
|
-
# Your search implementation
|
|
154
|
-
{ results: ["Result 1", "Result 2"] }
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
toolset = DSPy::Tools::Toolset.new(tools: [SearchTool.new])
|
|
159
|
-
agent = DSPy::ReAct.new(signature: ResearchTask, tools: toolset, max_iterations: 5)
|
|
160
|
-
result = agent.call(question: "What's the latest on Ruby 3.4?")
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
## What's Included
|
|
164
|
-
|
|
165
|
-
**Core Modules**: Predict, ChainOfThought, ReAct agents, and composable pipelines.
|
|
166
|
-
|
|
167
|
-
**Type Safety**: Sorbet-based runtime validation. Enums, unions, nested structs—all work.
|
|
168
|
-
|
|
169
|
-
**Multimodal**: Image analysis with `DSPy::Image` for vision-capable models.
|
|
170
|
-
|
|
171
|
-
**Observability**: Zero-config Langfuse integration via OpenTelemetry. Non-blocking, production-ready.
|
|
172
|
-
|
|
173
|
-
**Optimization**: MIPROv2 (Bayesian optimization) and GEPA (genetic evolution) for prompt tuning.
|
|
174
|
-
|
|
175
|
-
**Provider Support**: OpenAI, Anthropic, Gemini, Ollama, and OpenRouter via official SDKs.
|
|
176
|
-
|
|
177
|
-
## Documentation
|
|
45
|
+
The [Quick Start](https://oss.vicente.services/dspy.rb/getting-started/quick-start/) is the complete supported path: install the core and provider gems, configure a key, save a program, and run it.
|
|
178
46
|
|
|
179
|
-
|
|
47
|
+
Use [Installation](https://oss.vicente.services/dspy.rb/getting-started/installation/) to choose a provider. The [package and capability matrix](https://oss.vicente.services/dspy.rb/getting-started/packages/) records exact gem names, require behavior, support labels, and model or SDK boundaries.
|
|
180
48
|
|
|
181
|
-
|
|
49
|
+
## Mental Model
|
|
182
50
|
|
|
183
|
-
|
|
51
|
+
- A `DSPy::Signature` defines the task contract.
|
|
52
|
+
- `DSPy::Predict` and other modules choose an execution strategy.
|
|
53
|
+
- Ordinary Ruby owns fixed sequencing, branching, persistence, permissions, and failure policy.
|
|
54
|
+
- Results cross a runtime validation boundary; validation establishes shape, not factual correctness.
|
|
184
55
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
```bash
|
|
188
|
-
# Claude Code
|
|
189
|
-
git clone https://github.com/vicentereig/dspy-rb-skill ~/.claude/skills/dspy-rb
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
For Claude.ai Pro/Max, download the [skill ZIP](https://github.com/vicentereig/dspy-rb-skill/archive/refs/heads/main.zip) and upload via Settings > Skills.
|
|
193
|
-
|
|
194
|
-
## Examples
|
|
195
|
-
|
|
196
|
-
The [examples/](examples/) directory has runnable code for common patterns:
|
|
197
|
-
|
|
198
|
-
- Sentiment classification
|
|
199
|
-
- ReAct agents with tools
|
|
200
|
-
- Image analysis
|
|
201
|
-
- Prompt optimization
|
|
202
|
-
|
|
203
|
-
```bash
|
|
204
|
-
bundle exec ruby examples/first_predictor.rb
|
|
205
|
-
```
|
|
56
|
+
### ReAct Agents
|
|
206
57
|
|
|
207
|
-
|
|
58
|
+
Use `ReAct` when the model needs to choose among typed Ruby tools inside an iteration bound. The application still owns tool authorization, side effects, budgets, and errors. See [Predictors](https://oss.vicente.services/dspy.rb/core-concepts/predictors/) and [Toolsets](https://oss.vicente.services/dspy.rb/core-concepts/toolsets/).
|
|
208
59
|
|
|
209
|
-
|
|
60
|
+
## Explore
|
|
210
61
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
| `dspy-evals` | Evaluation harness with metrics and callbacks |
|
|
215
|
-
| `dspy-miprov2` | Bayesian optimization for prompt tuning |
|
|
216
|
-
| `dspy-gepa` | Genetic-Pareto prompt evolution |
|
|
217
|
-
| `dspy-o11y-langfuse` | Auto-configure Langfuse tracing |
|
|
218
|
-
| `dspy-code_act` | Think-Code-Observe agents |
|
|
219
|
-
| `dspy-deep_search` | Production DeepSearch with Exa |
|
|
62
|
+
- [Documentation](https://oss.vicente.services/dspy.rb/) — task-oriented guides and reference
|
|
63
|
+
- [Examples](examples/) — repository demos indexed by capability and prerequisites
|
|
64
|
+
- [llms.txt](https://oss.vicente.services/dspy.rb/llms.txt) — generated reference for AI assistants
|
|
220
65
|
|
|
221
|
-
|
|
66
|
+
Provider adapters, optimizers, observability exporters, datasets, and code-executing agents are separate packages when they add dependencies. Check the package matrix before selecting one; package availability does not guarantee uniform provider or model behavior.
|
|
222
67
|
|
|
223
68
|
## Contributing
|
|
224
69
|
|
|
225
|
-
|
|
70
|
+
For bugs, [open an issue](https://github.com/vicentereig/dspy.rb/issues). For suggestions, [start a discussion](https://github.com/vicentereig/dspy.rb/discussions).
|
|
226
71
|
|
|
227
72
|
Want to contribute code? Reach out: hey at vicente.services
|
|
228
73
|
|
data/lib/dspy/code_act/README.md
CHANGED
|
@@ -1,152 +1,77 @@
|
|
|
1
1
|
# CodeAct: Dynamic Code Generation for DSPy.rb
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`dspy-code_act` is for controlled experiments with trusted input. The current implementation evaluates model-generated Ruby inside the application process. It does not provide a sandbox, permission boundary, resource isolation, or safe handling of untrusted or multi-tenant input.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
See the [package and capability matrix](https://oss.vicente.services/dspy.rb/getting-started/packages/) for canonical package status and the execution-safety boundary.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- Prefer ReAct when you have well-defined tools, must call external services, or need stricter safety guarantees.
|
|
7
|
+
## Prerequisites
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
- Ruby 3.3 or newer and Bundler
|
|
10
|
+
- `dspy`, one provider adapter, and `dspy-code_act`
|
|
11
|
+
- a provider key and model that can produce the required structured responses
|
|
12
|
+
- trusted input and a controlled execution environment
|
|
13
|
+
- outbound network access for the repository research example; generated Ruby calls a live HTTP API
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
require 'dspy'
|
|
14
|
-
require 'dspy/code_act'
|
|
15
|
-
|
|
16
|
-
DSPy.configure do |config|
|
|
17
|
-
config.lm = DSPy::LM.new('openai/gpt-4o-mini', api_key: ENV.fetch('OPENAI_API_KEY'))
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
agent = DSPy::CodeAct.new
|
|
21
|
-
|
|
22
|
-
result = agent.forward(
|
|
23
|
-
task: "Calculate the Fibonacci sequence up to the 10th number",
|
|
24
|
-
context: "You have access to standard Ruby libraries"
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
puts result.final_answer
|
|
28
|
-
# => [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
|
|
29
|
-
|
|
30
|
-
result.history.each do |step|
|
|
31
|
-
puts "Step #{step.step}"
|
|
32
|
-
puts "Thought: #{step.thought}"
|
|
33
|
-
puts "Code: #{step.ruby_code}"
|
|
34
|
-
puts "Result: #{step.execution_result}"
|
|
35
|
-
end
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Advanced Usage
|
|
39
|
-
|
|
40
|
-
### Custom Execution Context
|
|
41
|
-
|
|
42
|
-
Provide structured data or helper methods with the `context` argument so generated code can reference them:
|
|
15
|
+
## Install and Run the Example
|
|
43
16
|
|
|
44
17
|
```ruby
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
"March" => [140, 210, 220]
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
agent = DSPy::CodeAct.new
|
|
52
|
-
|
|
53
|
-
result = agent.forward(
|
|
54
|
-
task: "Calculate the average sales for each month and report the best performer",
|
|
55
|
-
context: "You have access to `sales_data`, a hash keyed by month with numeric arrays",
|
|
56
|
-
data: { sales_data: sales_data }
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
puts result.final_answer
|
|
60
|
-
# => "March is the best performing month with an average of 190.0"
|
|
18
|
+
gem "dspy"
|
|
19
|
+
gem "dspy-openai"
|
|
20
|
+
gem "dspy-code_act"
|
|
61
21
|
```
|
|
62
22
|
|
|
63
|
-
|
|
23
|
+
In an application, run `bundle install` after adding those gems. From this repository, enable the optional package while installing the monorepo bundle, then run the example:
|
|
64
24
|
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
Bob Johnson,bob@gmail.com,Sales
|
|
71
|
-
CSV
|
|
72
|
-
|
|
73
|
-
result = agent.forward(
|
|
74
|
-
task: "Parse the CSV data and list gmail.com addresses",
|
|
75
|
-
context: "CSV data is available in `csv_content`",
|
|
76
|
-
data: { csv_content: csv_content }
|
|
77
|
-
)
|
|
25
|
+
```bash
|
|
26
|
+
DSPY_WITH_CODE_ACT=1 bundle install
|
|
27
|
+
export OPENAI_API_KEY="your-key"
|
|
28
|
+
bundle exec ruby examples/codeact_research_agent.rb \
|
|
29
|
+
"How many stars does rails/rails have?"
|
|
78
30
|
```
|
|
79
31
|
|
|
80
|
-
|
|
32
|
+
The script prints the final answer and records the generated code and observations in `result.history`. The answer can change with the live API; inspect the generated code and observation rather than treating an old count as a fixture.
|
|
81
33
|
|
|
82
|
-
|
|
34
|
+
## Define a CodeAct Task
|
|
83
35
|
|
|
84
|
-
|
|
85
|
-
2. **Input Sanitization** – scrub user input to remove shell-outs and dangerous methods.
|
|
86
|
-
3. **Resource Monitoring** – track memory and CPU usage to abort runaway code.
|
|
36
|
+
CodeAct requires a signature and an iteration bound:
|
|
87
37
|
|
|
88
38
|
```ruby
|
|
89
|
-
class
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
rescue Timeout::Error
|
|
93
|
-
"Code execution timed out"
|
|
94
|
-
end
|
|
39
|
+
class Calculate < DSPy::Signature
|
|
40
|
+
input { const :question, String }
|
|
41
|
+
output { const :answer, String }
|
|
95
42
|
end
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Example: Sales Analysis Pipeline
|
|
99
43
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def analyze_trends(sales_data)
|
|
107
|
-
result = @agent.forward(
|
|
108
|
-
task: <<~TASK,
|
|
109
|
-
Analyze the sales data to:
|
|
110
|
-
1. Compute month-over-month growth
|
|
111
|
-
2. Identify seasonal patterns
|
|
112
|
-
3. Predict next month's sales with simple linear regression
|
|
113
|
-
TASK
|
|
114
|
-
context: "You have access to `sales_data` and standard Ruby libraries",
|
|
115
|
-
data: { sales_data: sales_data }
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
{
|
|
119
|
-
analysis: result.final_answer,
|
|
120
|
-
code_steps: result.history.map(&:ruby_code),
|
|
121
|
-
execution_time: result.metadata[:total_time]
|
|
122
|
-
}
|
|
123
|
-
end
|
|
44
|
+
DSPy.configure do |config|
|
|
45
|
+
config.lm = DSPy::LM.new(
|
|
46
|
+
"openai/gpt-4o-mini",
|
|
47
|
+
api_key: ENV.fetch("OPENAI_API_KEY")
|
|
48
|
+
)
|
|
124
49
|
end
|
|
50
|
+
|
|
51
|
+
agent = DSPy::CodeAct.new(Calculate, max_iterations: 4)
|
|
52
|
+
result = agent.call(question: "Return the first ten Fibonacci numbers")
|
|
53
|
+
|
|
54
|
+
puts result.answer
|
|
55
|
+
puts result.history.map(&:ruby_code)
|
|
125
56
|
```
|
|
126
57
|
|
|
127
|
-
|
|
58
|
+
The model chooses Ruby code, CodeAct evaluates it, and a second prediction chooses whether to continue or finish. The application owns the iteration limit and execution boundary.
|
|
128
59
|
|
|
129
|
-
|
|
60
|
+
## Choose CodeAct or ReAct
|
|
130
61
|
|
|
131
|
-
|
|
132
|
-
DSPy.configure do |config|
|
|
133
|
-
config.logger = Dry.Logger(:dspy, formatter: :json) do |logger|
|
|
134
|
-
logger.add_backend(level: :debug, stream: $stdout)
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
```
|
|
62
|
+
Prefer `DSPy::ReAct` when the allowed operations can be exposed as narrow typed tools. Use CodeAct only when open-ended computation is necessary and the execution environment can carry the larger authority boundary.
|
|
138
63
|
|
|
139
|
-
|
|
64
|
+
## Safety Checklist
|
|
140
65
|
|
|
141
|
-
|
|
66
|
+
Timeouts and forbidden-string checks do not make Ruby `eval` safe. Generated code can reach loaded constants, files, environment variables, network clients, and process APIs through many equivalent expressions.
|
|
142
67
|
|
|
143
|
-
|
|
144
|
-
- No support for external gem loading during execution.
|
|
145
|
-
- Future roadmap targets hardened sandboxing, async execution, and richer explanations.
|
|
68
|
+
Before accepting untrusted input, move execution outside the application process and provide:
|
|
146
69
|
|
|
147
|
-
|
|
70
|
+
- a disposable process, container, or virtual machine;
|
|
71
|
+
- no inherited application secrets;
|
|
72
|
+
- allowlisted network access;
|
|
73
|
+
- read-only or ephemeral storage;
|
|
74
|
+
- CPU, memory, wall-clock, and output limits; and
|
|
75
|
+
- a narrow protocol for returning observations.
|
|
148
76
|
|
|
149
|
-
|
|
150
|
-
2. Provide precise context and structured data for better code generation.
|
|
151
|
-
3. Always validate outputs and enforce timeouts or resource caps.
|
|
152
|
-
4. Capture telemetry (Observability, Langfuse) for production usage.
|
|
77
|
+
The gem does not supply those controls. A provider error, invalid generated program, execution exception, or maximum-iteration result can stop or degrade a run; inspect `result.history` and handle those outcomes in the application.
|
data/lib/dspy/code_act.rb
CHANGED
|
@@ -118,6 +118,18 @@ module DSPy
|
|
|
118
118
|
# Create enhanced output struct with CodeAct fields
|
|
119
119
|
@enhanced_output_struct = create_enhanced_output_struct(signature_class)
|
|
120
120
|
enhanced_output_struct = @enhanced_output_struct
|
|
121
|
+
input_descriptors = signature_class.input_field_descriptors
|
|
122
|
+
output_descriptors = input_descriptors.merge(signature_class.output_field_descriptors).merge(
|
|
123
|
+
history: DSPy::Signature::FieldDescriptor.new(
|
|
124
|
+
T::Array[CodeActHistoryEntry],
|
|
125
|
+
"CodeAct execution history"
|
|
126
|
+
),
|
|
127
|
+
iterations: DSPy::Signature::FieldDescriptor.new(Integer, "Number of iterations executed"),
|
|
128
|
+
execution_context: DSPy::Signature::FieldDescriptor.new(
|
|
129
|
+
T::Hash[Symbol, T.untyped],
|
|
130
|
+
"Variables and context from code execution"
|
|
131
|
+
)
|
|
132
|
+
)
|
|
121
133
|
|
|
122
134
|
# Create enhanced signature class
|
|
123
135
|
enhanced_signature = Class.new(DSPy::Signature) do
|
|
@@ -126,9 +138,11 @@ module DSPy
|
|
|
126
138
|
|
|
127
139
|
# Use the same input struct
|
|
128
140
|
@input_struct_class = signature_class.input_struct_class
|
|
141
|
+
@input_field_descriptors = input_descriptors
|
|
129
142
|
|
|
130
143
|
# Use the enhanced output struct with CodeAct fields
|
|
131
144
|
@output_struct_class = enhanced_output_struct
|
|
145
|
+
@output_field_descriptors = output_descriptors
|
|
132
146
|
|
|
133
147
|
# Store original signature name
|
|
134
148
|
@original_signature_name = signature_class.name
|
|
@@ -306,6 +320,11 @@ module DSPy
|
|
|
306
320
|
})
|
|
307
321
|
output_data[output_field_name] = reasoning_result[:final_answer]
|
|
308
322
|
|
|
323
|
+
@signature_class.validate_required_fields!(
|
|
324
|
+
output_data,
|
|
325
|
+
@signature_class.output_field_descriptors
|
|
326
|
+
)
|
|
327
|
+
|
|
309
328
|
@enhanced_output_struct.new(**output_data)
|
|
310
329
|
end
|
|
311
330
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dspy-code_act
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vicente Reig Rincón de Arellano
|
|
@@ -15,14 +15,20 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version:
|
|
18
|
+
version: 1.0.2
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '2.0'
|
|
19
22
|
type: :runtime
|
|
20
23
|
prerelease: false
|
|
21
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
25
|
requirements:
|
|
23
26
|
- - ">="
|
|
24
27
|
- !ruby/object:Gem::Version
|
|
25
|
-
version:
|
|
28
|
+
version: 1.0.2
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '2.0'
|
|
26
32
|
description: CodeAct provides Think-Code-Observe agents that synthesize and execute
|
|
27
33
|
Ruby code dynamically. Ship DSPy.rb workflows that write custom Ruby code while
|
|
28
34
|
tracking execution history, observations, and safety signals.
|