Assertions are gone — use dspy.Refine
dspy.Assert, dspy.Suggest, dspy.constrain, and dspy.SoftAssert do not exist in 3.x. There is also no dspy.BestofN in 3.3.0. The replacement is:
Model string
deepseek-v4-flash is addressed as openai/deepseek-v4-flash via the OpenAI-compatible endpoint — the same pattern DSPy uses for SGLang and local servers. api_base is required. Set model_type="chat" if the endpoint needs it.
Fleet Reasoner uses the repository’s existing OPENAI_* environment variables (OPENAI_MODEL, OPENAI_BASE_URL, OPENAI_API_KEY). The old INKLING_* and DEEPSEEK_API_KEY conventions are gone. One model serves every tier.
If you ever switch to Gemini: the prefix is gemini/, not google/. A bare string silently defaults to Vertex AI and fails without GCP credentials. vertex_ai/ is the GCP variant; use vertex_project and vertex_location — project and location are silently ignored.
Optimizer API shape
- The metric goes on the constructor:
dspy.MIPROv2(metric=...),dspy.BootstrapFewShot(metric=...). trainset=is keyword-only atcompile()—train_set=fails withTypeError.MIPROv2(auto="light"|"medium"|"heavy")cannot be combined with explicitnum_candidatesornum_trials— that raisesValueError.compile()returns a new copy; the student is not mutated.
Module conventions
- No
dspy.Programclass.dspy.Moduleis the base. Callmodule(...)ormodule.acall(...), nevermodule.forward(...)— that bypasses tracing and emits a deprecation warning. super().__init__()is mandatory (metaclass-enforced).- Never read
dspy.settingsin__init__. Read it insideforward()sodspy.contextoverrides apply. - Sub-module registration is attribute assignment (
self.predict = ...). Onlydspy.Parameterattributes are optimizer-visible. PredictandChainOfThoughtaccept keyword args only —predict("q")raisesValueError.
Evaluation contract
dspy.Evaluatecalls the metric asmetric(example, prediction)— exactly two positional args.traceis populated by optimizers, never byEvaluate.EvaluationResult.scoreis a 0–100 percentage, not 0–1.- Every devset example must call
.with_inputs(...)orprogram(**example.inputs())crashes. - Metric return:
bool,float, ordspy.Prediction(score, feedback). Feedback is read only by GEPA.
Tools and retrieval
dspy.Toolneeds valid type hints. The docstring is the description; the type hints are the arg schema.ReActandReActV2dedupe tools by name — collisions silently overwrite. Keep names unique.dspy.Retrievereadsdspy.settings.rmat call time.dspy.configure(rm=...)first, or it raisesAssertionError("No RM is loaded.").- Async tools need
acall()ordspy.configure(allow_tool_async_sync_conversion=True).
3.3.0-specific
dspy.ReActV2is experimental and its prompt format differs fromReAct— reservedsubmittool,dspy.ToolCalls,termination_reason. Fleet Reasoner uses it as the default withReActas a documented fallback.dspy.Flexis experimental and starts from a signature, not a composeddspy.Module. It runs optimizer-authored code in aCodeInterpretersandbox. BecauseReasoningEngineis a hand-structured module,Flexonly applies to a future signature-first rewrite of the loop.- NumPy is optional — install
dspy[numpy]if any metric or visual code imports numpy. - Image / Audio / File constructors no longer do I/O. Use
Image.from_path(path)orImage.from_url(url).Image(path)andImage(url, download=True)are gone.Image.from_file()andfrom_PIL()are deprecated aliases and are removed in 3.4. - GEPA result shapes changed with
gepa[dspy]==0.1.1:candidatesare compiled modules,best_candidatereturns a module, andval_subscoresis keyed by validation instance id. - LM errors are normalized. Catch
dspy.LMErrorand its subclasses —LMRateLimitError,ContextWindowExceededError,LMUnsupportedModelError,LMTimeoutError— not provider-specific exceptions. - Typed LM boundary (
dspy.LMRequest/dspy.LMResponse, opt-in viadspy.context(experimental=True)) targets custom LM authors — irrelevant until you replace the built-in OpenAI-compatible provider.
Streaming
dspy.streamdoes not exist in 3.3.0. The streaming surface isdspy.streamify(program, ...)indspy.streaming. It wraps any program and returns a callable whose result is an async generator of events, ending with the finaldspy.Prediction.- ReActV2 emits its final answer as
submittool-call arguments, so token-level streaming ofanswerdoes not apply. Surface tool activity asstatusevents and the complete answer in thedoneframe. - LM errors raised inside the stream are caught in the generator and emitted as
{"event": "error", "status": 429|413|502}frames. The response has already started, soHTTPExceptionis not an option mid-stream.
Caching and concurrency
- LM caching is ON by default. Pass a unique
rollout_idplus a non-zero temperature to force fresh calls. This is critical forRefinesampling. dspy.configurehas an owner-thread rule. Configure once at startup and usedspy.contextin request handlers and worker threads.- Save and load.
program.save(path)(state only) orprogram.save(dir, save_program=True)+dspy.load(dir).allow_pickledefaults toFalse. API keys are never serialized.