DSPy.rb and LangChain Ruby
The libraries overlap, but they organize application code differently. DSPy.rb starts with typed task contracts, modules, evaluation, and optimization. LangChain Ruby emphasizes provider clients, prompt templates, retrieval integrations, and prebuilt components.
Both projects change quickly. Verify integration availability and API syntax in each project’s current documentation before choosing between them.
DSPy.rb Model
Define the task once, then choose an execution module:
class QuestionAnswering < DSPy::Signature
input do
const :question, String
const :context, String
end
output do
const :answer, String
end
end
qa = DSPy::Predict.new(QuestionAnswering)
result = qa.call(question: question, context: context)
The signature supplies the typed boundary. Predict, ChainOfThought, and ReAct provide different execution strategies. Ruby control flow composes modules into fixed pipelines; ReAct gives the model a bounded tool-selection loop.
Evaluation and optimizers operate on the resulting program. They do not remove the need for examples, metrics, budgets, or deployment policy.
LangChain Ruby Model
LangChain Ruby starts closer to provider and integration primitives. Its current API includes a common LLM interface, prompt templates, structured-output parsers, vector-store clients, document loaders, tools, and a conversational Assistant.
The same question-answering task can be assembled from a prompt template and an LLM client:
llm = Langchain::LLM::OpenAI.new(
api_key: ENV.fetch("OPENAI_API_KEY")
)
prompt = Langchain::Prompt::PromptTemplate.new(
template: "Answer from the context.\nContext: {context}\nQuestion: {question}",
input_variables: ["context", "question"]
)
response = llm.chat(
messages: [{
role: "user",
content: prompt.format(context: context, question: question)
}]
)
answer = response.chat_completion
This API leaves the prompt and response shape explicit. For structured data, LangChain Ruby provides StructuredOutputParser, which accepts a JSON Schema, adds format instructions to a prompt, and parses the response. OutputFixingParser can ask the model to repair a parsing failure. Its Assistant manages conversation messages and automatic or manual tool execution, while its vector-search clients cover ingestion and retrieval for several databases.
See the project-maintained LangChain Ruby README and API documentation for current provider and integration details.
Equivalent Concepts, Different Centers
| Concern | DSPy.rb | LangChain Ruby |
|---|---|---|
| Task definition | Sorbet-backed signature with typed inputs and outputs | Prompt template, messages, and optional output parser |
| Model access | Provider adapters behind DSPy::LM |
Provider clients behind Langchain::LLM |
| Structured results | Signature-derived schema and prediction coercion | JSON Schema supplied to StructuredOutputParser |
| Tool use | DSPy::ReAct with typed Ruby tools and an iteration limit |
Langchain::Assistant with tool definitions and conversation state |
| Retrieval | Application-owned retrieval passed into modules | Vector-store clients, loaders, chunkers, and RAG helpers |
| Evaluation | Program evaluation with application metrics | RAGAS evaluation for retrieval-augmented answers |
| Optimization | Instructions and demonstrations compiled from examples and metrics | Prompt templates remain application-authored |
These rows describe the projects’ documented APIs, not feature parity. A custom Ruby application can build any of these boundaries around either library.
Choose by the Boundary You Need
Choose DSPy.rb when:
- A typed input and output contract should define the task.
- You want to compare execution modules without rewriting the task interface.
- Evaluation and instruction or demonstration optimization are part of the development loop.
- Ruby should own deterministic orchestration around model calls.
- A tool-using agent needs typed tools and an iteration bound.
Choose LangChain Ruby when its provider interface, prompt and parser objects, conversational assistant, or retrieval integrations match the application you need to assemble.
The choice is not a general claim about speed, memory, or quality. Provider latency dominates many workloads, and prompt or token differences depend on the exact program. Benchmark the task with the same model, data, metric, and concurrency.
Migration to DSPy.rb
- Capture representative inputs and expected behavior before changing the implementation.
- Express the task as a signature.
- Start with
DSPy::Predict; add reasoning or tools only when the task requires them. - Keep retrieval, persistence, permissions, and side effects in application-owned components.
- Evaluate the old and new paths on the same examples.
- Optimize only after the metric reflects the behavior you intend to ship.
See RAG for application-owned retrieval, Pipelines for fixed composition, and Program Optimization for evaluation-driven compilation.