Quick Start Guide
Get up and running with DSPy.rb in minutes. This guide shows Ruby-idiomatic patterns for building AI applications.
Your First DSPy Program
Basic Prediction
require 'dspy'
# Define a signature for sentiment classification
class Classify < DSPy::Signature
description "Classify sentiment of a given sentence."
class Sentiment < T::Enum
enums do
Positive = new('positive')
Negative = new('negative')
Neutral = new('neutral')
end
end
input do
const :sentence, String
end
output do
const :sentiment, Sentiment
const :confidence, Float
end
end
# Configure DSPy with your LLM
DSPy.configure do |c|
c.lm = DSPy::LM.new('openai/gpt-4o-mini', api_key: ENV['OPENAI_API_KEY'])
end
# Create the predictor and run inference
classify = DSPy::Predict.new(Classify)
result = classify.call(sentence: "This book was super fun to read!")
puts result.sentiment # => #<Sentiment::Positive>
puts result.confidence # => 0.85
Chain of Thought Reasoning
class AnswerPredictor < DSPy::Signature
description "Provides a concise answer to the question"
input do
const :question, String
end
output do
const :answer, String
end
end
# Chain of thought automatically adds a 'reasoning' field to the output
qa_cot = DSPy::ChainOfThought.new(AnswerPredictor)
result = qa_cot.call(question: "Two dice are tossed. What is the probability that the sum equals two?")
puts result.reasoning # => "There is only one way to get a sum of 2..."
puts result.answer # => "1/36"
Multi-stage Pipelines
class Outline < DSPy::Signature
description "Outline a thorough overview of a topic."
input do
const :topic, String
end
output do
const :title, String
const :sections, T::Array[String]
end
end
class DraftSection < DSPy::Signature
description "Draft a section of an article"
input do
const :topic, String
const :title, String
const :section, String
end
output do
const :content, String
end
end
class ArticleDrafter < DSPy::Module
def initialize
@build_outline = DSPy::ChainOfThought.new(Outline)
@draft_section = DSPy::ChainOfThought.new(DraftSection)
end
def forward(topic:)
outline = @build_outline.call(topic: topic)
sections = outline.sections.map do |section|
@draft_section.call(
topic: topic,
name: outline.title,
section: section
)
end
{
name: outline.title,
sections: sections.map(&:content)
}
end
end
# Use the pipeline
drafter = ArticleDrafter.new
article = drafter.forward(topic: "The impact of AI on software development")
puts article[:title]
puts article[:sections].first
Ruby-Idiomatic Examples
Working with Collections
DSPy.rb works naturally with Ruby’s Enumerable patterns:
# Process multiple items with Ruby's collection methods
class BatchProcessor < DSPy::Module
def initialize
@classifier = DSPy::Predict.new(Classify)
end
def process_batch(sentences)
sentences.map { |sentence| @classifier.call(sentence: sentence) }
.select { |result| result.confidence > 0.8 }
.group_by(&:sentiment)
end
end
# Usage
processor = BatchProcessor.new
results = processor.process_batch([
"I love this product!",
"This is terrible.",
"It's okay, I guess."
])
results[:positive]&.each { |r| puts r.sentence }
Block-Based Configuration
Configure DSPy components with Ruby blocks:
# Configure with blocks for cleaner syntax
DSPy.configure do |config|
config.lm = DSPy::LM.new('openai/gpt-4o-mini') do |lm|
lm.api_key = ENV.fetch('OPENAI_API_KEY')
lm.temperature = 0.7
lm.max_tokens = 1000
end
config.instrumentation do |i|
i.enabled = Rails.env.production?
i.logger.level = :info
end
end
Method Chaining
Build complex queries with chainable methods:
# Future API (coming soon)
result = DSPy.predict(:question_answering)
.with_examples(training_data)
.with_instruction("Be concise")
.optimize_for(:accuracy)
.call(question: "What is Ruby?")
Duck Typing with Tools
Create tools that follow Ruby’s duck typing principles:
# Any object that responds to #call can be a tool
class WeatherTool
def call(location:)
# In real app, this would call an API
{ temperature: 72, conditions: "sunny" }
end
end
# Lambda tools for simple operations
calculator = ->(expression:) { eval(expression) }
# Use with ReAct agent
agent = DSPy::ReAct.new(
WeatherReport,
tools: {
weather: WeatherTool.new,
calculate: calculator
}
)
Key Concepts
Signatures
Signatures define the interface for LLM operations:
class YourSignature < DSPy::Signature
description "Clear description of what this does"
input do
const :input_field, String, description: "What this field represents"
end
output do
const :output_field, String, description: "What the output should be"
end
end
Predictors
Predictors execute signatures:
DSPy::Predict
- Basic LLM completionDSPy::ChainOfThought
- Step-by-step reasoningDSPy::ReAct
- Tool-using agentsDSPy::CodeAct
- Dynamic code execution agents
Modules
Modules compose multiple predictors into pipelines:
class YourModule < DSPy::Module
def initialize
@predictor1 = DSPy::Predict.new(Signature1)
@predictor2 = DSPy::ChainOfThought.new(Signature2)
end
def forward(**inputs)
result1 = @predictor1.call(**inputs)
result2 = @predictor2.call(input: result1.output)
{ final_result: result2.output }
end
end
Next Steps
- Learn about Core Concepts
- Explore Signatures & Types
- Try Prompt Optimization
- Set up Observability