Skip to content

Commit f23572a

Browse files
committed
DSPy post
1 parent ba47416 commit f23572a

2 files changed

Lines changed: 131 additions & 0 deletions

File tree

841 KB
Loading
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
---
2+
title: "DSPy solves prompting problems and creates production ones"
3+
description: "DSPy is an invaluable tool for AI workflow prototypes which creates new headaches in production."
4+
pubDate: 2026-04-02
5+
---
6+
7+
I felt a pang of jealousy after enjoying [Skylar Payne's write-up on DSPy](https://skylarbpayne.com/posts/dspy-engineering-patterns/). Fantastic post! It deserves a read for its all-too-accurate description of the path taken by [DSPy](https://dspy.ai) (or any half-baked implementation of its concepts) into production, as well as the centrality of
8+
- typed signatures,
9+
- composable modules, and
10+
- prompt optimizers
11+
in successful AI workflows.
12+
13+
My jealousy stems from procrastinating on a similar post describing my experiences building production workflows with DSPy for two separate projects in 2025 at [Not Diamond](https://www.notdiamond.ai/).[^1] This is that post. Thanks, Skylar, for the well-written kick-to-the-butt.
14+
15+
## The concepts don't block adoption
16+
17+
Anyway, we diverge on his conclusion. Skylar writes:
18+
19+
> DSPy has adoption problems because it asks you to think differently before you’ve actually felt the pain of thinking the same way everyone else does.
20+
21+
> The patterns DSPy embodies aren’t optional. If your AI system gets complex enough, you will reinvent them. The only question is whether you do it deliberately or accidentally.
22+
23+
We agree that AI engineers absolutely must understand signatures and interfaces, both exemplified by the ubiquity of structured outputs. Optimizers - as a component of workflow evals - are similarly critical today.
24+
25+
But these concepts are not too esoteric to hinder DSPy’s adoption. Engineers can use DSPy's heaps of excellent documentation to quickly learn its concepts, which align with common practices for evals and workflow optimization. Let's give folks the benefit of the doubt, and assume a new user can quickly reach competency in DSPy.
26+
27+
My view is that Skylar has mixed up the causality here. Engineers don't struggle with DSPy because of its novel concepts. Instead, **DSPy's limitations hinder the creation of modular, optimizable AI workflows**.
28+
29+
During our testing I observed three concrete limitations in DSPy:
30+
- Its optimized programs have limited portability,
31+
- It takes a strongly-opinionated approach to concurrency, and
32+
- It has an LLM client dependency which can be challenging to work with and tedious to replace.
33+
34+
## Conflicting concurrency
35+
36+
Both of my team's attempts at integrating DSPy into live workflows involved distributed, asynchronous training and dynamic model-switching via Celery with `gevent`. We abandoned DSPy shortly after encountering [this](https://github.com/stanfordnlp/dspy/blob/main/dspy/dsp/utils/settings.py#L159-L163) configuration issue:
37+
38+
```python
39+
if not in_ipython and config_owner_async_task != asyncio.current_task():
40+
raise RuntimeError(
41+
"dspy.configure(...) can only be called from the same async task that called it first. Please "
42+
"use `dspy.context(...)` in other async tasks instead."
43+
)
44+
```
45+
46+
As suggested, we treed `dspy.context` to avoid async task conflicts. But every model switch required context managers, [as demonstrated by this example snippet](https://github.com/stanfordnlp/dspy/blob/main/docs/docs/tutorials/cache/index.md?plain=1#L178-L181):
47+
48+
```python
49+
with dspy.context(lm=dspy.LM("openai/gpt-5-mini")):
50+
result1 = predict(question="Who is the GOAT of soccer?")
51+
52+
with dspy.context(lm=dspy.LM("openai/gpt-5-nano")):
53+
result2 = predict(question="Who do *you* think is the GOAT of soccer?")
54+
```
55+
56+
In a Markdown doc or Jupyter notebook this reads fine. In a production codebase this practically _invites_ bugs.
57+
58+
While DSPy 3.0 shipped async improvements, [limitations in configurability](https://github.com/stanfordnlp/dspy/issues/8197) and async support still persist:
59+
- program training still [requires a synchronous context](https://github.com/stanfordnlp/dspy/issues/9075)
60+
- `dspy.settings` has [mixed support](https://github.com/stanfordnlp/dspy/issues/8197) across coroutines
61+
- multi-model workflows have limited support across [different concurrency models](https://github.com/stanfordnlp/dspy/issues/8797)
62+
63+
More broadly, **this anti-modular design emerges from DSPy's tightly-coupled inference-time story**. By optimizing your program with DSPy, you've also bought into the library's architectural decisions for concurrency. This is no more evident than [in the FastAPI tutorial](https://dspy.ai/tutorials/deployment/#deploying-with-fastapi), where the user defers concurrency management to DSPy via `dspy.asyncify`. But production deployments require performance optimizations tailored to the needs of *your* workflows - not those of a library dependency.
64+
65+
## Pulling prompts
66+
67+
What did I mean earlier by a "tightly-coupled inference-time story?" Let's say you want to use your optimized prompts outside of DSPy. You'd have to extract them [like so](https://github.com/stanfordnlp/dspy/issues/7830):
68+
69+
```python
70+
{
71+
name: adapter.format(
72+
p.signature,
73+
demos=p.demos,
74+
inputs={k: f"{{{k}}}" for k in p.signature.input_fields},
75+
)
76+
for name, p in program.named_predictors()
77+
}
78+
```
79+
80+
Omar Khattab[^2] has [explained the intention](https://github.com/stanfordnlp/dspy/issues/8042#issuecomment-2773833904) behind this choice:
81+
82+
> DSPy does a lot of heavy-lifting indeed, and it's very common that people try to extract the optimized prompt but end up hurting quality in the process. We do not usually advise that you extract anything for this reason, since the optimized prompt assumes a lot of DSPy behavior like the way the inference calls are made.
83+
84+
> That said, if you really want to get a prompt you can apply this process. Note that it gives you a list of messages.
85+
86+
He's right, of course. Many of DSPy's optimizers[^3] treat signatures as optimizable parameters. If the user decouples those components from the underlying prompts, they can inadvertently unwind performance gains.
87+
88+
But...that's _my_ prompt. Now, though, it has limited applicability. Concretely: **this inference-time requirement creates a golden-path dependency on DSPy.**
89+
90+
This bleeds into other concerns. For eg. observability, we faced a choice between forking the library to add spans or adopting [MLflow](https://dspy.ai/tutorials/observability/#tracing). If your production service doesn't use Python, you're instead relying on unofficial ports[^4]. If your prompt needs to land in a non-software workflow handled by Claude Cowork or Codex? You're back to Omar's earlier snippet.
91+
92+
93+
## Dealing with dependencies
94+
95+
DSPy also relies on leaky abstractions thanks to its underlying LLM client library, LiteLLM. Several years ago, LiteLLM's cross-provider compatibility and ease of implementation made it the de-facto LLM client for workflow prototyping. Since then the AI ecosystem aligned onto OpenAI-style messages, and Skylar’s post demonstrates common patterns in client usage and request retries.
96+
97+
LiteLLM poses its own issues in production contexts, however, such as poor logging configuration. It produces verbose, poorly-formatted logs at `INFO` level, which polluted Datadog, Sentry and our local testing tools:[^5]
98+
99+
![Commonly seen in logs across Jupyter notebooks and dev environments](/images/dspy-litellm-logs.png)
100+
101+
LiteLLM also recently experienced [a supply chain vulnerability](https://docs.litellm.ai/blog/security-update-march-2026) after a core maintainer's PyPI credentials were compromised. This risk exists for any OSS project, but if LiteLLM is not proxying your requests then your alternatives can be as simple as `openai.OpenAI` and `tenacity`. [^6]
102+
103+
In DSPy, users can swap out the underlying client library with some effort. [There's no documentation on this capability](https://dspy.ai/learn/programming/language_models/#advanced-building-custom-lms-and-writing-your-own-adapters). A DSPy contributor is working on extracting LiteLLM into an extra dependency [while redesigning `dspy.LM` ](https://github.com/stanfordnlp/dspy/issues/9514), which significantly helps production users once the change lands.
104+
105+
## What it is and what it is not
106+
107+
Admittedly, our experience with DSPy could confirm "Khattab's Law" as proposed by Skylar:
108+
109+
> Any sufficiently complicated AI system contains an ad hoc, informally-specified, bug-ridden implementation of half of DSPy.
110+
111+
Our prompting layer leverages typed signatures, a separate eval harness and first-party provider SDKs to optimize prompts over eval datasets.
112+
113+
But none of the facts I've laid out above dilute the usefulness of DSPy. It's still a fantastic exploratory tool for prompt optimization. Our broader AI ecosystem benefits from research produced by labs like Stanford NLP and MIT CSAIL, whose researchers primarily maintain DSPy.
114+
115+
That said, it's worth acknowledging difficulties integrating it into production systems with optimized concurrency, comprehensive monitoring, and tight requirements for environment builds.
116+
117+
As Skylar noted, DSPy’s concepts form the basis of any well-designed AI workflow. I believe that applying those concepts inward - to the library’s architecture and interfaces - would broaden its impact far beyond prototyping and research.
118+
119+
*Thanks to Devansh Jain and James Kunstle for input on this write-up*.
120+
121+
[^1]: Astute readers will note that Not Diamond offers [Prompt Optimization](https://www.notdiamond.ai/#prompt-optimization). If you haven't closed this tab yet, I *solemnly vow* to avoid any sales in this post.
122+
123+
[^2]: Lead author on [the original DSPy paper](https://arxiv.org/abs/2310.03714) and core contributor to the open-source library.
124+
125+
[^3]: Notably, this is not true of GEPA, where users can [seamlessly extract prompts](https://x.com/LakshyAAAgrawal/status/1978198977985069348) from the optimized adapter. While GEPA is available in DSPy, this capability is primarily available in the underlying `gepa-ai` [library](https://gepa-ai.github.io/gepa/).
126+
127+
[^4]: There are community-built libraries for languages like [TypeScript](https://github.com/ruvnet/dspy.ts) and [Rust](https://github.com/krypticmouse/DSRs). They lack feature parity or ongoing support.
128+
129+
[^5]: Honestly, "Local Engineer Complains About Dependency Logging Configs" is the least surprising headline of the day! But LiteLLM's usage of `INFO` for low-signal logs feels disconnected from common logging practices in production systems. It's symptomatic of LiteLLM's other issues, a discussion of which falls well outside of this post's scope.
130+
131+
[^6]: I expect most AI engineers writing Python have battle scars with `openai.OpenAI` and `tenacity.retry` at this point.

0 commit comments

Comments
 (0)