dspy-miprov2 0.29.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f117c06ee15494475bc9cfef9965587321f951a97fc107ea87b65e3da4d3898a
4
+ data.tar.gz: d098fe07997e7c83a19f62cfe55ff55284b55c596bf89e62589159ae8b549bec
5
+ SHA512:
6
+ metadata.gz: 549b3f5fb9b6abe74698c24fa9f7dbfdf8a6aa87559ce33e196a7061299bcc9375d8302b58fbb05572896a28a21a66dbeba399448a562a676be2fbe36ef28f14
7
+ data.tar.gz: 58d250d6596b1fd900eb9b7208aee82333d5561964ceac8ea2c4ff4f3536fc97f5f0ed37e7c20b20672c5657e59e961227bebc4ac9b94828b636f820fef015c5
data/LICENSE ADDED
@@ -0,0 +1,45 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Vicente Services SL
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ This project is a Ruby port of the original Python [DSPy library](https://github.com/stanfordnlp/dspy), which is licensed under the MIT License:
24
+
25
+ MIT License
26
+
27
+ Copyright (c) 2023 Stanford Future Data Systems
28
+
29
+ Permission is hereby granted, free of charge, to any person obtaining a copy
30
+ of this software and associated documentation files (the "Software"), to deal
31
+ in the Software without restriction, including without limitation the rights
32
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33
+ copies of the Software, and to permit persons to whom the Software is
34
+ furnished to do so, subject to the following conditions:
35
+
36
+ The above copyright notice and this permission notice shall be included in all
37
+ copies or substantial portions of the Software.
38
+
39
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
45
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,247 @@
1
+ # DSPy.rb
2
+
3
+ [![Gem Version](https://img.shields.io/gem/v/dspy)](https://rubygems.org/gems/dspy)
4
+ [![Total Downloads](https://img.shields.io/gem/dt/dspy)](https://rubygems.org/gems/dspy)
5
+ [![Build Status](https://img.shields.io/github/actions/workflow/status/vicentereig/dspy.rb/ruby.yml?branch=main&label=build)](https://github.com/vicentereig/dspy.rb/actions/workflows/ruby.yml)
6
+ [![Documentation](https://img.shields.io/badge/docs-vicentereig.github.io%2Fdspy.rb-blue)](https://vicentereig.github.io/dspy.rb/)
7
+
8
+ **Build reliable LLM applications in idiomatic Ruby using composable, type-safe modules.**
9
+
10
+ The Ruby framework for programming with large language models. DSPy.rb brings structured LLM programming to Ruby developers. Instead of wrestling with prompt strings and parsing responses, you define typed signatures using idiomatic Ruby to compose and decompose AI Worklows and AI Agents.
11
+
12
+ **Prompts are the just Functions.** Traditional prompting is like writing code with string concatenation: it works until it doesn't. DSPy.rb brings you
13
+ the programming approach pioneered by [dspy.ai](https://dspy.ai/): instead of crafting fragile prompts, you define modular
14
+ signatures and let the framework handle the messy details.
15
+
16
+ DSPy.rb is an idiomatic Ruby surgical port of Stanford's [DSPy framework](https://github.com/stanfordnlp/dspy). While implementing
17
+ the core concepts of signatures, predictors, and optimization from the original Python library, DSPy.rb embraces Ruby
18
+ conventions and adds Ruby-specific innovations like CodeAct agents and enhanced production instrumentation.
19
+
20
+ The result? LLM applications that actually scale and don't break when you sneeze.
21
+
22
+ ## Your First DSPy Program
23
+
24
+ ```ruby
25
+ # Define a signature for sentiment classification
26
+ class Classify < DSPy::Signature
27
+ description "Classify sentiment of a given sentence."
28
+
29
+ class Sentiment < T::Enum
30
+ enums do
31
+ Positive = new('positive')
32
+ Negative = new('negative')
33
+ Neutral = new('neutral')
34
+ end
35
+ end
36
+
37
+ input do
38
+ const :sentence, String
39
+ end
40
+
41
+ output do
42
+ const :sentiment, Sentiment
43
+ const :confidence, Float
44
+ end
45
+ end
46
+
47
+ # Configure DSPy with your LLM
48
+ DSPy.configure do |c|
49
+ c.lm = DSPy::LM.new('openai/gpt-4o-mini',
50
+ api_key: ENV['OPENAI_API_KEY'],
51
+ structured_outputs: true) # Enable OpenAI's native JSON mode
52
+ end
53
+
54
+ # Create the predictor and run inference
55
+ classify = DSPy::Predict.new(Classify)
56
+ result = classify.call(sentence: "This book was super fun to read!")
57
+
58
+ puts result.sentiment # => #<Sentiment::Positive>
59
+ puts result.confidence # => 0.85
60
+ ```
61
+
62
+ ### Access to 200+ Models Across 5 Providers
63
+
64
+ DSPy.rb provides unified access to major LLM providers with provider-specific optimizations:
65
+
66
+ ```ruby
67
+ # OpenAI (GPT-4, GPT-4o, GPT-4o-mini, GPT-5, etc.)
68
+ DSPy.configure do |c|
69
+ c.lm = DSPy::LM.new('openai/gpt-4o-mini',
70
+ api_key: ENV['OPENAI_API_KEY'],
71
+ structured_outputs: true) # Native JSON mode
72
+ end
73
+
74
+ # Google Gemini (Gemini 1.5 Pro, Flash, Gemini 2.0, etc.)
75
+ DSPy.configure do |c|
76
+ c.lm = DSPy::LM.new('gemini/gemini-2.5-flash',
77
+ api_key: ENV['GEMINI_API_KEY'],
78
+ structured_outputs: true) # Native structured outputs
79
+ end
80
+
81
+ # Anthropic Claude (Claude 3.5, Claude 4, etc.)
82
+ DSPy.configure do |c|
83
+ c.lm = DSPy::LM.new('anthropic/claude-sonnet-4-5-20250929',
84
+ api_key: ENV['ANTHROPIC_API_KEY'],
85
+ structured_outputs: true) # Tool-based extraction (default)
86
+ end
87
+
88
+ # Ollama - Run any local model (Llama, Mistral, Gemma, etc.)
89
+ DSPy.configure do |c|
90
+ c.lm = DSPy::LM.new('ollama/llama3.2') # Free, runs locally, no API key needed
91
+ end
92
+
93
+ # OpenRouter - Access to 200+ models from multiple providers
94
+ DSPy.configure do |c|
95
+ c.lm = DSPy::LM.new('openrouter/deepseek/deepseek-chat-v3.1:free',
96
+ api_key: ENV['OPENROUTER_API_KEY'])
97
+ end
98
+ ```
99
+
100
+ ## What You Get
101
+
102
+ **Core Building Blocks:**
103
+ - **Signatures** - Define input/output schemas using Sorbet types with T::Enum and union type support
104
+ - **Predict** - LLM completion with structured data extraction and multimodal support
105
+ - **Chain of Thought** - Step-by-step reasoning for complex problems with automatic prompt optimization
106
+ - **ReAct** - Tool-using agents with type-safe tool definitions and error recovery
107
+ - **CodeAct** - Dynamic code execution agents for programming tasks
108
+ - **Module Composition** - Combine multiple LLM calls into production-ready workflows
109
+
110
+ **Optimization & Evaluation:**
111
+ - **Prompt Objects** - Manipulate prompts as first-class objects instead of strings
112
+ - **Typed Examples** - Type-safe training data with automatic validation
113
+ - **Evaluation Framework** - Advanced metrics beyond simple accuracy with error-resilient pipelines
114
+ - **MIPROv2 Optimization** - Advanced Bayesian optimization with Gaussian Processes, multiple optimization strategies, auto-config presets, and storage persistence
115
+
116
+ **Production Features:**
117
+ - **Reliable JSON Extraction** - Native structured outputs for OpenAI and Gemini, Anthropic tool-based extraction, and automatic strategy selection with fallback
118
+ - **Type-Safe Configuration** - Strategy enums with automatic provider optimization (Strict/Compatible modes)
119
+ - **Smart Retry Logic** - Progressive fallback with exponential backoff for handling transient failures
120
+ - **Zero-Config Langfuse Integration** - Set env vars and get automatic OpenTelemetry traces in Langfuse
121
+ - **Performance Caching** - Schema and capability caching for faster repeated operations
122
+ - **File-based Storage** - Optimization result persistence with versioning
123
+ - **Structured Logging** - JSON and key=value formats with span tracking
124
+
125
+ **Developer Experience:**
126
+ - LLM provider support using official Ruby clients:
127
+ - [OpenAI Ruby](https://github.com/openai/openai-ruby) with vision model support
128
+ - [Anthropic Ruby SDK](https://github.com/anthropics/anthropic-sdk-ruby) with multimodal capabilities
129
+ - [Google Gemini API](https://ai.google.dev/) with native structured outputs
130
+ - [Ollama](https://ollama.com/) via OpenAI compatibility layer for local models
131
+ - **Multimodal Support** - Complete image analysis with DSPy::Image, type-safe bounding boxes, vision-capable models
132
+ - Runtime type checking with [Sorbet](https://sorbet.org/) including T::Enum and union types
133
+ - Type-safe tool definitions for ReAct agents
134
+ - Comprehensive instrumentation and observability
135
+
136
+ ## Development Status
137
+
138
+ DSPy.rb is actively developed and approaching stability. The core framework is production-ready with
139
+ comprehensive documentation, but I'm battle-testing features through the 0.x series before committing
140
+ to a stable v1.0 API.
141
+
142
+ Real-world usage feedback is invaluable - if you encounter issues or have suggestions, please open a GitHub issue!
143
+
144
+ ## Documentation
145
+
146
+ 📖 **[Complete Documentation Website](https://vicentereig.github.io/dspy.rb/)**
147
+
148
+ ### LLM-Friendly Documentation
149
+
150
+ For LLMs and AI assistants working with DSPy.rb:
151
+ - **[llms.txt](https://vicentereig.github.io/dspy.rb/llms.txt)** - Concise reference optimized for LLMs
152
+ - **[llms-full.txt](https://vicentereig.github.io/dspy.rb/llms-full.txt)** - Comprehensive API documentation
153
+
154
+ ### Getting Started
155
+ - **[Installation & Setup](docs/src/getting-started/installation.md)** - Detailed installation and configuration
156
+ - **[Quick Start Guide](docs/src/getting-started/quick-start.md)** - Your first DSPy programs
157
+ - **[Core Concepts](docs/src/getting-started/core-concepts.md)** - Understanding signatures, predictors, and modules
158
+
159
+ ### Core Features
160
+ - **[Signatures & Types](docs/src/core-concepts/signatures.md)** - Define typed interfaces for LLM operations
161
+ - **[Predictors](docs/src/core-concepts/predictors.md)** - Predict, ChainOfThought, ReAct, and more
162
+ - **[Modules & Pipelines](docs/src/core-concepts/modules.md)** - Compose complex multi-stage workflows
163
+ - **[Multimodal Support](docs/src/core-concepts/multimodal.md)** - Image analysis with vision-capable models
164
+ - **[Examples & Validation](docs/src/core-concepts/examples.md)** - Type-safe training data
165
+
166
+ ### Optimization
167
+ - **[Evaluation Framework](docs/src/optimization/evaluation.md)** - Advanced metrics beyond simple accuracy
168
+ - **[Prompt Optimization](docs/src/optimization/prompt-optimization.md)** - Manipulate prompts as objects
169
+ - **[MIPROv2 Optimizer](docs/src/optimization/miprov2.md)** - Advanced Bayesian optimization with Gaussian Processes
170
+ - **[GEPA Optimizer](docs/src/optimization/gepa.md)** *(beta)* - Reflective mutation with optional reflection LMs
171
+
172
+ ### Production Features
173
+ - **[Storage System](docs/src/production/storage.md)** - Persistence and optimization result storage
174
+ - **[Observability](docs/src/production/observability.md)** - Zero-config Langfuse integration with a dedicated export worker that never blocks your LLMs
175
+
176
+ ### Advanced Usage
177
+ - **[Complex Types](docs/src/advanced/complex-types.md)** - Sorbet type integration with automatic coercion for structs, enums, and arrays
178
+ - **[Manual Pipelines](docs/src/advanced/pipelines.md)** - Manual module composition patterns
179
+ - **[RAG Patterns](docs/src/advanced/rag.md)** - Manual RAG implementation with external services
180
+ - **[Custom Metrics](docs/src/advanced/custom-metrics.md)** - Proc-based evaluation logic
181
+
182
+ ## Quick Start
183
+
184
+ ### Installation
185
+
186
+ Add to your Gemfile:
187
+
188
+ ```ruby
189
+ gem 'dspy'
190
+ ```
191
+
192
+ Then run:
193
+
194
+ ```bash
195
+ bundle install
196
+ ```
197
+
198
+ ## Recent Achievements
199
+
200
+ DSPy.rb has rapidly evolved from experimental to production-ready:
201
+
202
+ ### Foundation
203
+ - ✅ **JSON Parsing Reliability** - Native OpenAI structured outputs, strategy selection, retry logic
204
+ - ✅ **Type-Safe Strategy Configuration** - Provider-optimized automatic strategy selection
205
+ - ✅ **Core Module System** - Predict, ChainOfThought, ReAct, CodeAct with type safety
206
+ - ✅ **Production Observability** - OpenTelemetry, New Relic, and Langfuse integration
207
+ - ✅ **Advanced Optimization** - MIPROv2 with Bayesian optimization, Gaussian Processes, and multiple strategies
208
+
209
+ ### Recent Advances
210
+ - ✅ **Enhanced Langfuse Integration (v0.25.0)** - Comprehensive OpenTelemetry span reporting with proper input/output, hierarchical nesting, accurate timing, and observation types
211
+ - ✅ **Comprehensive Multimodal Framework** - Complete image analysis with `DSPy::Image`, type-safe bounding boxes, vision model integration
212
+ - ✅ **Advanced Type System** - `T::Enum` integration, union types for agentic workflows, complex type coercion
213
+ - ✅ **Production-Ready Evaluation** - Multi-factor metrics beyond accuracy, error-resilient evaluation pipelines
214
+ - ✅ **Documentation Ecosystem** - `llms.txt` for AI assistants, ADRs, blog articles, comprehensive examples
215
+ - ✅ **API Maturation** - Simplified idiomatic patterns, better error handling, production-proven designs
216
+
217
+ ## Roadmap - Production Battle-Testing Toward v1.0
218
+
219
+ DSPy.rb has transitioned from **feature building** to **production validation**. The core framework is
220
+ feature-complete and stable - now I'm focusing on real-world usage patterns, performance optimization,
221
+ and ecosystem integration.
222
+
223
+ **Current Focus Areas:**
224
+
225
+ ### Production Readiness
226
+ - 🚧 **Production Patterns** - Real-world usage validation and performance optimization
227
+ - 🚧 **Ruby Ecosystem Integration** - Rails integration, Sidekiq compatibility, deployment patterns
228
+ - 🚧 **Scale Testing** - High-volume usage, memory management, connection pooling
229
+ - 🚧 **Error Recovery** - Robust failure handling patterns for production environments
230
+
231
+ ### Ecosystem Expansion
232
+ - 🚧 **Model Context Protocol (MCP)** - Integration with MCP ecosystem
233
+ - 🚧 **Additional Provider Support** - Azure OpenAI, local models beyond Ollama
234
+ - 🚧 **Tool Ecosystem** - Expanded tool integrations for ReAct agents
235
+
236
+ ### Community & Adoption
237
+ - 🚧 **Community Examples** - Real-world applications and case studies
238
+ - 🚧 **Contributor Experience** - Making it easier to contribute and extend
239
+ - 🚧 **Performance Benchmarks** - Comparative analysis vs other frameworks
240
+
241
+ **v1.0 Philosophy:**
242
+ v1.0 will be released after extensive production battle-testing, not after checking off features.
243
+ The API is already stable - v1.0 represents confidence in production reliability backed by real-world validation.
244
+
245
+ ## License
246
+
247
+ This project is licensed under the MIT License.
@@ -0,0 +1,10 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../version'
5
+
6
+ module DSPy
7
+ module MIPROv2
8
+ VERSION = DSPy::VERSION
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ begin
5
+ require_relative 'miprov2/version'
6
+ rescue LoadError
7
+ # In development the version file should be present; in production the gem provides it.
8
+ end
9
+
10
+ require_relative 'optimizers/gaussian_process'
11
+ require_relative 'teleprompt/mipro_v2'
@@ -0,0 +1,86 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require 'numo/narray'
5
+ require 'numo/tiny_linalg'
6
+ require 'sorbet-runtime'
7
+
8
+ module DSPy
9
+ module Optimizers
10
+ # Gaussian Process regression backed by Numo::TinyLinalg for Bayesian optimization.
11
+ class GaussianProcess
12
+ extend T::Sig
13
+
14
+ sig { params(length_scale: Float, signal_variance: Float, noise_variance: Float).void }
15
+ def initialize(length_scale: 1.0, signal_variance: 1.0, noise_variance: 1e-6)
16
+ @length_scale = length_scale
17
+ @signal_variance = signal_variance
18
+ @noise_variance = noise_variance
19
+ @fitted = T.let(false, T::Boolean)
20
+ end
21
+
22
+ sig { params(x_train: T::Array[T::Array[Float]], y_train: T::Array[Float]).void }
23
+ def fit(x_train, y_train)
24
+ x_matrix = to_matrix(x_train)
25
+ y_vector = to_vector(y_train)
26
+
27
+ kernel_matrix = rbf_kernel(x_matrix, x_matrix)
28
+ kernel_matrix += Numo::DFloat.eye(kernel_matrix.shape[0]) * @noise_variance
29
+
30
+ @cholesky_factor = Numo::TinyLinalg.cholesky(kernel_matrix, uplo: 'L')
31
+ @alpha = Numo::TinyLinalg.cho_solve(@cholesky_factor, y_vector, uplo: 'L')
32
+
33
+ @x_train = x_matrix
34
+ @y_train = y_vector
35
+ @fitted = true
36
+ end
37
+
38
+ sig do
39
+ params(x_test: T::Array[T::Array[Float]], return_std: T::Boolean)
40
+ .returns(T.any(Numo::DFloat, [Numo::DFloat, Numo::DFloat]))
41
+ end
42
+ def predict(x_test, return_std: false)
43
+ raise 'Gaussian Process not fitted' unless @fitted
44
+
45
+ test_matrix = to_matrix(x_test)
46
+ k_star = rbf_kernel(T.must(@x_train), test_matrix)
47
+
48
+ mean = k_star.transpose.dot(T.must(@alpha))
49
+ return mean unless return_std
50
+
51
+ v = Numo::TinyLinalg.cho_solve(T.must(@cholesky_factor), k_star, uplo: 'L')
52
+ k_star_star = rbf_kernel(test_matrix, test_matrix)
53
+ covariance = k_star_star - k_star.transpose.dot(v)
54
+
55
+ variance = covariance.diagonal.dup
56
+ variance[variance < 1e-12] = 1e-12
57
+ std = Numo::NMath.sqrt(variance)
58
+
59
+ [mean, std]
60
+ end
61
+
62
+ private
63
+
64
+ sig { params(x1: Numo::DFloat, x2: Numo::DFloat).returns(Numo::DFloat) }
65
+ def rbf_kernel(x1, x2)
66
+ scaled = 1.0 / (@length_scale**2)
67
+ x1_sq = (x1**2).sum(axis: 1).reshape(x1.shape[0], 1)
68
+ x2_sq = (x2**2).sum(axis: 1).reshape(1, x2.shape[0])
69
+ sqdist = x1_sq - 2.0 * x1.dot(x2.transpose) + x2_sq
70
+ @signal_variance * Numo::NMath.exp(-0.5 * sqdist * scaled)
71
+ end
72
+
73
+ sig { params(data: T::Array[T::Array[Float]]).returns(Numo::DFloat) }
74
+ def to_matrix(data)
75
+ matrix = Numo::DFloat[*data]
76
+ matrix = matrix.reshape(matrix.size, 1) if matrix.ndim == 1
77
+ matrix
78
+ end
79
+
80
+ sig { params(data: T::Array[Float]).returns(Numo::DFloat) }
81
+ def to_vector(data)
82
+ Numo::DFloat[*data]
83
+ end
84
+ end
85
+ end
86
+ end