feat: make numpy an optional dependency#34
Conversation
Greptile SummaryThis PR makes
Confidence Score: 4/5Safe to merge after fixing the remaining numpy call in get_program_with_highest_avg_score; all other conversions are correct. One function in teleprompt/utils.py still calls require_optional('numpy') to compute a simple mean using np.array + np.average on a plain Python list, forcing numpy to be installed for MIPROv2's minibatch optimization path even though no numpy-specific functionality is needed. dspy/teleprompt/utils.py — get_program_with_highest_avg_score still has a numpy call that should be replaced with stdlib sum()/len(). Important Files Changed
|
Move numpy from required dependencies to a new [numpy] optional extra. Add dspy/_numpy.require_numpy() helper so numpy-using features raise a clear ImportError pointing to 'pip install dspy[numpy]' when numpy is absent. Convert all module-level 'import numpy as np' statements to lazy imports inside the functions that actually need numpy, so 'import dspy' continues to work when the extra is not installed. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
CI installs individual extras (uv sync --dev --extra dev, then --extra test_extras) rather than --all-extras, so the new public [numpy] extra alone doesn't cover test collection. Several test files import numpy at module top, so numpy must be present in the extras CI actually installs. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
32c9363 to
787a37c
Compare
Replace dspy/utils/_numpy.require_numpy() with a generic dspy/utils/_optional.require_optional(module, extra=...) helper modeled on pandas.compat._optional.import_optional_dependency. dspy already exposes other capability-gated extras (anthropic, weaviate, mcp, langchain, optuna), so a generic helper avoids per-dep boilerplate as new optional integrations are added. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- mipro_optimizer_v2._set_num_trials_from_num_candidates: np.log2 -> math.log2.
- mipro_optimizer_v2._set_random_seeds: drop legacy np.random.seed call;
MIPROv2 itself doesn't read numpy's global RNG state.
- infer_rules.compile: -np.inf -> -math.inf.
Removes the require_optional("numpy") call from both files entirely;
neither code path needs numpy now.
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
require_optional previously defaulted extra=module, so a caller passing
just require_optional("foo") would advertise `pip install dspy[foo]`
even if no such extra was declared in pyproject.toml. Make extra opt-in:
when omitted, the error message only suggests `pip install <module>`.
Update the existing numpy callers to pass extra="numpy" explicitly.
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
…xtra arg Modeled on transformers' BACKENDS_MAPPING. _DSPY_EXTRAS in dspy/utils/_optional.py maps each importable module name to its declared install extra; require_optional(module) consults it to add `pip install dspy[<extra>]` to the error message when an extra exists, or falls back to `pip install <module>` otherwise. Callers no longer write redundant extra="numpy". Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Summary
Move
numpyfrom a required runtime dependency to an optional extra.numpy-dependent features (KNN, Embeddings, SIMBA, MIPROv2, InferRules, DummyVectorizer, Embedder post-processing, etc.) raise a clear
ImportErrorpointing atpip install dspy[numpy]only when actually invoked.Changes
dspy/utils/_numpy.pywithrequire_numpy()lazy import helperimport numpy as npto lazyrequire_numpy()calls inside method bodiesmath.log2in mipro_optimizer_v2, gepamath.infin infer_rulesstatistics.pstdevin copro_optimizersum()/len()in teleprompt/utilsnp.random.seed()in mipro (optuna uses its own seed param)require_numpy()inSIMBA.__init__for fast failure[project.optional-dependencies]withnumpyextradevandtest_extrasso CI still gets itNotes
import dspyworks without numpy installedpip install dspy[numpy]