3.4.0b1 #10386
isaacbmiller
announced in
Announcements
3.4.0b1
#10386
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
DSPy 3.4.0 Beta 1
DSPy 3.4.0b1 is the first beta of 3.4. It moves language-model execution to a shared engine interface, adds a local CPython interpreter for trusted code, and brings async execution to ReActV2. It also adds custom Flex code proposals in GEPA and fixes evaluation, streaming, and demonstration-sampling bugs.
This is a prerelease, not the stable 3.4.0 release. APIs and behavior may change before stable. We especially welcome feedback on native versus LiteLLM compatibility, tool calling and streaming, custom LM migration, saved programs, and multi-answer latency and costs. Please include your engine selection and a minimal reproduction when reporting issues.
Install this beta explicitly:
pip install --upgrade "dspy==3.4.0b1"3.4 is the LM transition release; 3.5 is the migration deadline. Ordinary DSPy programs and list-returning prompt calls remain supported, but the experimental LM types introduced in 3.3 are replaced in this release. Review the compatibility notes if you use those types, implement a custom LM, pass OpenAI-style messages directly to an LM, or request multiple answers with
n.Highlights
Native LM Engines and a New Custom-Backend Interface — @MaximeRivest
DSPy's LM layer now uses the lm15 request, response, and streaming types bundled with DSPy. Import them from
dspy.lm15; no separate lm15 installation is needed.The default
engine="auto"prefers native lm15 execution for supported routes and representable inputs. Unsupported routes, client settings, and ordinary provider-specific inputs that cannot be represented faithfully select LiteLLM before execution. Authentication failures, timeouts, and provider errors do not trigger a switch to another backend.Use
engine="lm15"to require native execution and reject unsupported mappings. LiteLLM remains installed and supported; it is not deprecated.Custom backends can now implement
complete(Request) -> Responseinstead of subclassingBaseLMand returning provider-shaped objects:Supply
async_engine=for async calls and implement canonical streaming events when needed. DSPy owns response caching, managed retries, callbacks, history, and usage accounting. Custom engines are caller-owned and are not closed by DSPy.Ordinary calls retain their existing cache-key format and can read existing SDK-response cache entries. New native cache entries contain plain serialized data and support restricted deserialization; explicit typed requests use a separate cache namespace. Existing
dspy.streamifylisteners remain supported.See the LM migration guide and custom-engine tutorial.
PRs: #10359, #10366, #10371
LocalInterpreter: Persistent CPython for Trusted Code — @isaacbmiller
dspy.LocalInterpreterruns generated Python in a persistent local CPython subprocess, using the current Python executable. It provides ordinary Python compatibility without Deno, while separating the worker's memory, stdout, and lifecycle from the DSPy process.State and imports persist within an interpreter session. LocalInterpreter supports JSON-compatible inputs and tool results, sync and async host tools, typed
SUBMIT, interpreter callbacks, and execution timeouts. It works with both RLM and Flex. The usual factory lifecycle still creates a fresh interpreter for each module invocation.LocalInterpreter is not a security sandbox. Generated code retains the host user's filesystem, environment, credentials, subprocess, and network access. Use the default
PythonInterpreteror a remote sandbox for untrusted code; the default has not changed.execution_timeoutincludes host-tool time and terminates the worker when exceeded. It cannot forcibly stop a running host callable; that callable may finish later, but its result is discarded. Guest threads must finish before an execution returns, or the interpreter session becomes terminal.Host-tool cancellation and interrupts propagate to the caller and shut down the stranded worker, including when no execution timeout is configured. They no longer leave execution waiting indefinitely for a worker reply. Ordinary tool errors remain recoverable.
PRs: #10238, #10379
Async ReActV2 and Explicit Final-Output Failures — @isaacbmiller
The experimental
dspy.ReActV2now supportsawait agent.acall(...), including async prediction, async tools, and forced final submission. This enables async MCP tools to run through the agent's structured tool-call history, preserving call IDs and tool results across turns.Tools execute sequentially on the async path. This does not add parallel tool execution or automatically offload blocking synchronous tools.
ReActV2 also no longer returns an incomplete
Predictionwhen final submission fails. Missing or invalid submission raisesValueError; parse and context-window failures from the forced submission propagate. Successful predictions continue to include declared outputs, history, and a termination reason.The MCP guide includes an async ReActV2 client/server example.
PRs: #10355, #10356
Custom Flex Code Proposals and More Reliable GEPA Evaluation — @dbreunig
dspy.GEPAnow acceptscode_proposer=, complementinginstruction_proposer=. Custom proposers receive the selected Flex code components, candidate source, reflective examples, task descriptions, and context blurbs, and return replacement module source for each component.This lets applications customize code-generation constraints and domain guidance without monkeypatching the built-in proposer. The built-in proposer remains the default, and programs without Flex components are unaffected.
GEPA's trace-capture evaluation also keeps outputs and scores aligned with the input batch when a program crashes on an example. Failed examples receive
failure_scorerather than disappearing and causing an indexing error or shifting later results. This addresses the missing/misaligned validation-results issue noted in the 3.3.1 release; it does not require an upstream GEPA upgrade.PRs: #10212, #10305
API and Compatibility Changes
The Experimental 3.3 LM Types Are Replaced Now
The old
dspy.LMRequest,dspy.LMResponse, and related experimental exports are removed. Importingdspy.core.typesraises a migration error, andforward_contract="typed_lm"is rejected. These are replacements, not aliases:dspy.LMRequest,dspy.LMResponsedspy.lm15.Request,dspy.lm15.Responsedspy.LMMessage,dspy.LMConfigdspy.lm15.Message,dspy.lm15.Configdspy.System(text)Request(system=text, ...)dspy.User(text),dspy.Assistant(text)Message.user(text),Message.assistant(text)response.outputs[0].partsresponse.message.partsThe new types are frozen dataclasses, not Pydantic models, and their validation and data shapes differ. Old pickles containing removed experimental classes are not automatically migrated; load and export them in their original environment first. Ordinary provider-response caches are a separate compatibility path and remain readable.
experimental=Trueno longer changes ordinary LM calls into typed responses. Ordinary prompt calls return lists; explicit requests return aResponse:An explicit request's model must match the LM. Set generation options in its
Config; LM generation defaults are not added.Config.cachecontrols provider-side prompt caching, not DSPy's response cache.DSPy's signature types, including
Image,Audio,File,Tool,ToolCalls, andHistory, are not removed. Existing public DSPy LM error classes remain supported.Legacy LM Integrations Are Deprecated for Removal in 3.5
The following still execute in 3.4 but emit
DeprecationWarning:lm(messages=[...])calls, including provider SDK message objects. Migrate to explicit lm15 requests.BaseLM.forward()andaforward()integrations. Migrate to the engine interface.LegacyEngine,AsyncLegacyEngine, and customcomplete_legacy()shortcuts. These are transition tools, not permanent compatibility interfaces.lm("hello")remains a list-returning convenience in 3.5. Built-in adapters still use an internal dictionary/list boundary in 3.4; their canonical request/response migration is scheduled for 3.5. Custom adapters must not depend on the removeddspy.clients.openai_formatmodule.To reveal deprecation warnings during development:
Native Multi-Answer Calls, Retries, and Streaming
nanswers use separate sequential requests. This can increase latency and bill input tokens more than once compared with a provider-native multi-answer request. Chooseengine="litellm"to retain that backend's nativenbehavior.PRs for the LM changes above: #10366, #10371
Other Compatibility Changes
historyortermination_reason, which collide with its prediction metadata. Rename those outputs. #9852ValueError, even withallow_tool_async_sync_conversionenabled. Useawait tool.acall(...). #10146Evaluaterejects an empty development set with a descriptiveValueErrorinstead of failing withZeroDivisionError. #9978Full PR List
Language Models and Engines
Retry-Afteracross bundled lm15 async and auxiliary calls by @MaximeRivest (#10371).Agents, Tools, and Interpreters
Optimization, Evaluation, and Examples
Examplehashing order-insensitive to match equality by @Kymi808 (#9858).Exampleby @iamsharduld (#9946).code_proposerhook by @dbreunig (#10212).Adapters, Streaming, and Batching
Literalmembers during parsing by @spjosyula (#10010).Unbatchifyinstead of resetting the full timeout on every queue read by @chuenchen309 (#10038).Literalmembers in BAMLAdapter schemas by @nikolauspschuetz (#10074).Documentation
max_itersdefault by @ellacroix (#10013).Dependencies, CI, and Release Engineering
denoland/setup-denofrom 2.0.4 to 2.0.5 by @dependabot (#10288).astral-sh/setup-uvfrom 8.2.0 to 10.0.1 by @dependabot (#10289).pypa/gh-action-pypi-publishfrom 1.14.0 to 1.14.2 by @dependabot (#10290).actions/setup-pythonfrom 6.2.0 to 7.0.0 by @dependabot (#10291).orjsonfrom 3.11.9 to 3.12.0 by @dependabot (#10292).zizmorcore/zizmor-actionfrom 0.5.7 to 0.6.2 by @dependabot (#10293).json-repairfrom 0.63.0 to 0.63.3 by @dependabot (#10295).Contributors
Thank you to @chuenchen309, @dbreunig, @ellacroix, @he-yufeng, @iamsharduld, @isaacbmiller, @Kymi808, @MaximeRivest, @michaelisaac-dev, @nikolauspschuetz, @NishchayMahor, @roli-lpci, @spjosyula, @tjdharamsi, and @ymxlx for contributing to this release.
Automation contributions were made by @dependabot and @github-actions.
Full Changelog: 3.3.1...3.4.0b1
This discussion was created from the release 3.4.0b1.
All reactions