Dspy lm
Skill lebsral/DSPy-Programming-not-prompting-LMs-skills/skills/dspy-lm
AI skills for Claude Code, Cursor, and other coding agents. Build reliable AI features with DSPy — classification, RAG, parsing, agents, and more. Just type /ai-do.
npx -y skills add lebsral/DSPy-Programming-not-prompting-LMs-skills --skill dspy-lmAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 11 stars11 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when you need to configure which language model DSPy uses — setting up providers, API keys, model parameters, or assigning different models to different pipeline stages. Common scenarios - setting up OpenAI or Anthropic API keys, configuring model parameters like temperature and max_tokens, using different models for different pipeline stages, switching between providers, using local models with Ollama or vLLM, or setting up Azure OpenAI. Related - ai-switching-models, ai-cutting-costs, ai-kickoff. Also used for dspy.LM, dspy.configure, configure language model in DSPy, OpenAI API key setup DSPy, Anthropic Claude with DSPy, use Ollama with DSPy, local model DSPy, Azure OpenAI DSPy setup, model temperature and max_tokens, different models per module, multi-model DSPy pipeline, vLLM with DSPy, change provider without changing code, model configuration DSPy.
SKILL.md
12.8 KB, ~3.2k tokens by cl100k_base, as published. Nobody here has run it
Configure Language Models with dspy.LM
dspy.LM is DSPy's unified interface for calling language models. It wraps LiteLLM so any provider -- OpenAI, Anthropic, Google, Together AI, Ollama, vLLM, and 100+ others -- works through one consistent API. You configure a model once, then every DSPy module uses it automatically.
Basic setup
import dspy
# Create an LM instance with a provider/model string
lm = dspy.LM("openai/gpt-4o-mini") # or "anthropic/claude-sonnet-4-5-20250929", etc.
# Set it as the default for all DSPy modules
dspy.configure(lm=lm)
# Now any module uses this LM automatically
classify = dspy.ChainOfThought("text -> label")
result = classify(text="DSPy is great")
print(result.label)
The pattern is always: dspy.LM("provider/model") then dspy.configure(lm=lm).
Step 1 — Gather context
Before configuring an LM, confirm if not already clear:
- Which provider? OpenAI, Anthropic, Google, Together AI, Groq, Azure, or local (Ollama/vLLM)?
- Single model or mixed pipeline? One model everywhere, or different models per stage for cost/quality tradeoffs?
- Reasoning model involved? (o1, o3, o4, DeepSeek-R1, Claude extended thinking) — these require
temperature=1.0orNoneand largemax_tokens. - Local/offline requirement? Privacy or no-internet constraints point to Ollama or vLLM, which need extra setup.
Provider strings
DSPy uses the LiteLLM "provider/model-name" format. Here are the most common providers:
| Provider | Example string | Notes |
|---|---|---|
| OpenAI | "openai/gpt-4o" | Default provider, auto-detected |
| OpenAI | "openai/gpt-4o-mini" | Cheaper, faster |
| Anthropic | "anthropic/claude-sonnet-4-5-20250929" | |
| Anthropic | "anthropic/claude-haiku-4-5-20251001" | Fast and cheap |
"gemini/gemini-2.0-flash" | ||
| Together AI | "together_ai/meta-llama/Llama-3-70b-chat-hf" | Open-source models |
| Groq | "groq/llama-3.1-70b-versatile" | Fast inference |
| Ollama (local) | "ollama_chat/llama3.1" | Requires api_base |
| Azure OpenAI | "azure/my-gpt4-deployment" | Requires api_base + api_key |
| OpenAI-compatible | "openai/my-model" | Any server with api_base |
See LiteLLM provider docs for the full list.
Constructor parameters
lm = dspy.LM(
model="openai/gpt-4o", # Required: "provider/model-name"
model_type="chat", # "chat" (default), "text", or "responses"
temperature=0.7, # Sampling temperature (default: provider default)
max_tokens=1000, # Max output tokens (default: provider default)
cache=True, # Enable built-in caching (default: True)
num_retries=3, # Retry on transient failures (default: 3)
use_developer_role=False, # Use developer/system role (default: False)
# Plus any extra kwargs passed to LiteLLM
)
Key parameters
model(required) -- The provider/model string. This is the only required argument.temperature-- Controls randomness. Lower = more deterministic. Set to0.0for reproducible outputs. Reasoning models (o1, o3) requiretemperature=1.0orNone.max_tokens-- Maximum tokens in the response. Reasoning models requiremax_tokens >= 16000orNone.cache-- WhenTrue(the default), DSPy caches LM responses to reduce costs and speed up repeated calls. Set toFalseto disable.num_retries-- Number of retries with exponential backoff on transient failures.model_type-- Usually leave as"chat". Use"text"for completion-only models. Use"responses"for OpenAI responses API.
Per-module LM assignment
You do not have to use the same model for every step. Assign different LMs to different modules with set_lm():
expensive_lm = dspy.LM("openai/gpt-4o")
cheap_lm = dspy.LM("openai/gpt-4o-mini")
# Set a default
dspy.configure(lm=cheap_lm)
class MyPipeline(dspy.Module):
def __init__(self):
self.classify = dspy.Predict("text -> category")
self.generate = dspy.ChainOfThought("text, category -> summary")
def forward(self, text):
category = self.classify(text=text)
return self.generate(text=text, category=category.category)
pipeline = MyPipeline()
# Route: cheap model for classification, expensive for generation
pipeline.classify.set_lm(cheap_lm)
pipeline.generate.set_lm(expensive_lm)
When to use each override method
| Method | Scope | Persistent? | Use when |
|---|---|---|---|
dspy.configure(lm=lm) | Global default | Yes | Setting the LM once at program start |
module.set_lm(lm) | Per-module instance | Yes | Routing specific steps to a different model permanently |
dspy.context(lm=lm) | Code block | No (reverts after) | One-off call with a different LM without changing defaults |
Temporary LM override with dspy.context
Use dspy.context to temporarily switch LMs for a block of code:
with dspy.context(lm=expensive_lm):
# Everything inside uses expensive_lm
result = pipeline(text="important document")
# Back to the default LM outside the block
Direct LM calls
You can call an LM instance directly for one-off prompts outside of DSPy modules:
lm = dspy.LM("openai/gpt-4o-mini")
# Pass a string prompt
response = lm("What is the capital of France?")
print(response) # returns a list of strings
# Pass a messages list (chat format)
response = lm(messages=[
{"role": "user", "content": "What is the capital of France?"}
])
print(response) # returns a list of strings
Direct calls are useful for quick tests, but for structured tasks use DSPy modules and signatures -- they give you type checking, optimization, and caching.
Environment variables
Set API keys as environment variables. Never hardcode them.
# OpenAI
export OPENAI_API_KEY=sk-...
# Anthropic
export ANTHROPIC_API_KEY=sk-ant-...
# Together AI
export TOGETHER_API_KEY=...
# Google
export GEMINI_API_KEY=...
# Groq
export GROQ_API_KEY=...
# Azure OpenAI
export AZURE_API_KEY=...
export AZURE_API_BASE=https://your-resource.openai.azure.com/
DSPy (via LiteLLM) reads these automatically. You can also pass api_key directly to dspy.LM() if needed, but environment variables are preferred.
Caching
DSPy caches LM responses by default. This means:
- Repeated identical calls are free -- same prompt, same parameters, same model returns a cached result instantly with no API call.
- Development is faster -- re-running your script doesn't re-call the LM for already-seen inputs.
- Optimization is cheaper -- optimizers that re-evaluate examples benefit from cached results.
Controlling caching
# Caching enabled (default)
lm = dspy.LM("openai/gpt-4o-mini", cache=True)
# Disable caching for this LM
lm = dspy.LM("openai/gpt-4o-mini", cache=False)
# Configure cache settings globally (controls disk and memory tiers separately)
dspy.configure_cache(
enable_disk_cache=True, # Toggle on-disk caching
enable_memory_cache=True, # Toggle in-memory caching
disk_size_limit_bytes=None, # Optional: cap disk cache size
memory_max_entries=None, # Optional: cap in-memory entries
)
Cache is stored locally. If you need different responses for the same prompt (e.g., generating diverse examples), disable caching or use different temperature values.
Useful methods
| Method | Purpose |
|---|---|
lm("prompt") | Direct call -- returns list of strings |
lm.copy(**kwargs) | Deep copy with updated parameters |
lm.inspect_history() | View recent request/response history |
lm.dump_state() | Serialize config (excludes API keys) |
Inspecting history
lm = dspy.LM("openai/gpt-4o-mini")
dspy.configure(lm=lm)
classify = dspy.Predict("text -> label")
classify(text="Hello world")
# See what was sent to the LM
dspy.inspect_history(n=1)
Connecting to local models
Ollama
# Start Ollama: ollama serve
# Pull a model: ollama pull llama3.1
lm = dspy.LM(
"ollama_chat/llama3.1",
api_base="http://localhost:11434",
api_key="",
temperature=0.7,
num_ctx=8192, # set context window explicitly — Ollama defaults to 4096
)
dspy.configure(lm=lm)
For full Ollama setup (model selection, GPU tuning, context window gotchas, optimization tips), see /dspy-ollama.
vLLM or any OpenAI-compatible server
# Start vLLM: vllm serve meta-llama/Llama-3.1-8B-Instruct
lm = dspy.LM(
"openai/meta-llama/Llama-3.1-8B-Instruct",
api_base="http://localhost:8000/v1",
api_key="none",
)
dspy.configure(lm=lm)
For any server that exposes an OpenAI-compatible /v1/chat/completions endpoint, use the "openai/model-name" provider string with api_base pointing to your server.
For full vLLM setup (tensor parallelism, GPU sizing, quantization, production deployment), see /dspy-vllm.
Gotchas
- Claude omits the provider prefix from the model string. Claude writes
dspy.LM("gpt-4o-mini")instead ofdspy.LM("openai/gpt-4o-mini"). While some models auto-detect the provider, the explicit"provider/model"format is required for reliable routing through LiteLLM. Always include the provider prefix. - Claude sets
temperature=0for reasoning models. OpenAI reasoning models (o1, o3, o4, gpt-5 families) requiretemperature=1.0orNone. Settingtemperature=0raises an error. Similarly,max_tokensmust be>= 16000orNonefor these models. - Claude calls
dspy.configure(lm=lm)insideforward(). Configuration should happen once at the top of your script, not per-call. Callingdspy.configureinsideforward()resets global state on every invocation and breaks caching. Useset_lm()ordspy.context()for per-module or temporary overrides instead. - Claude forgets
api_basefor local models. Ollama and vLLM requireapi_basepointing to the local server (http://localhost:11434for Ollama,http://localhost:8000/v1for vLLM). Without it, DSPy tries to reach the cloud API and fails with an authentication error. - Claude hardcodes API keys in source code. Set API keys as environment variables (
OPENAI_API_KEY,ANTHROPIC_API_KEY, etc.) — DSPy reads them automatically via LiteLLM. Passingapi_key=...directly todspy.LM()is supported but should be reserved for local dev overrides, not production code.
Related DSPy model classes
dspy.Embedder— For computing text embeddings (RAG, semantic search). Uses the same LiteLLM provider string format:dspy.Embedder("openai/text-embedding-3-small"). Not an LM — cannot be passed todspy.configure(lm=...). See dspy.ai/api/models/Embedder/.BaseLM(upcoming) — DSPy 3.3.0 (beta) introduces a typedBaseLMinterface withLMRequest/LMResponsetyped boundaries. Stable 3.2.1 usesdspy.LMas documented here.
Additional resources
- dspy.LM API docs
- dspy.Embedder API docs
- LiteLLM provider docs
- For API details, see reference.md
- For worked examples, see examples.md
Cross-references
Install any skill:
npx skills add lebsral/DSPy-Programming-not-prompting-LMs-skills --skill <name>
/dspy-signatures-- Define what your LM should do (inputs, outputs, types)/dspy-modules-- Wrap signatures with inference strategies (Predict, ChainOfThought, ReAct)/ai-switching-models-- Safely migrate between providers with re-optimization/ai-cutting-costs-- Reduce LM costs with per-module assignment and cheaper models- Install
/ai-doif you do not have it — it routes any AI problem to the right skill and is the fastest way to work:npx skills add lebsral/DSPy-Programming-not-prompting-LMs-skills --skill ai-do