Thin orchestration package around DSPy's GEPA optimizer
Project description
AutoGEPA
Thin orchestration package around DSPy's GEPA optimizer.
Explore the Documentation »
Report Bug
Request Feature
Table of Contents
About
AutoGEPA automates the tedious parts of setting up a DSPy optimization pipeline: converting raw data into dspy.Examples, generating a metric file with an LLM, splitting datasets, running baselines, and training with GEPA.
- Automatic field inference — Maps row columns to DSPy Signature fields automatically
- LLM-generated metrics — Drafts evaluation metrics automatically, saving them as reproducible
.pyfiles for human review - End-to-end pipeline — Datasets → Baseline → GEPA optimization → Compare & promote
- Zero-config defaults — Sensible defaults for all hyperparameters and LMs
Requires DSPy 3.1+.
Quick Start
Install
Install AutoGEPA with uv (recommended):
uv add dspy-auto-gepa
Or with pip:
pip install dspy-auto-gepa
Basic Usage
import dspy
from dspy_auto_gepa import AutoGEPA
# Configure models
lm = dspy.LM("openrouter/openai/gpt-oss-120b")
large_lm = dspy.LM("openrouter/moonshotai/kimi-k2.5")
dspy.configure(lm=lm)
class TicketSignature(dspy.Signature):
"""Classify support tickets."""
message: str = dspy.InputField()
urgency: str = dspy.OutputField()
sentiment: str = dspy.OutputField()
program = dspy.ChainOfThought(TicketSignature)
rows = [
{"message": "The server room AC is out and equipment is overheating.", "urgency": "high", "sentiment": "negative"},
{"message": "Can someone clean conference room B next week?", "urgency": "low", "sentiment": "neutral"},
]
# Fields are automatically inferred from the module's signature
auto = AutoGEPA(
rows=rows,
module=program,
name="TicketSignature",
metric_lm=large_lm,
reflection_lm=large_lm,
)
results = auto.run(force=False) # Set True to re-run even if a saved model exists
# Check if a cached model was loaded
if results.loaded_from:
print(f"Loaded existing model from {results.loaded_from}")
else:
print(f"Baseline score: {results.baseline:.4f}")
print(f"Optimized score: {results.optimized:.4f}")
print(f"Improvement: {results.improvement:.4f}")
print(f"Saved optimized program to {results.saved_to}")
Usage
Automatic field inference (recommended)
When your row columns match your module's signature fields, you don't need to specify any field mappings. AutoGEPA infers input and output fields directly from the dspy.Signature attached to your module.
If your row columns don't match the module's signature fields, AutoGEPA will raise a clear error telling you which fields are missing and suggesting you use dict mappings:
ValueError: Row columns do not match module signature fields. Missing from rows: ['message', 'sentiment', 'urgency']. Extra in rows: ['msg_text', 'sent', 'urg']. Pass input_fields/output_fields to map row columns to signature fields, or ensure row columns match exactly.
With dict field mappings
When your row columns have different names than your module's signature fields:
# Row columns: msg_text, urg, sent
# Signature fields: message, urgency, sentiment
auto = AutoGEPA(
rows=rows,
module=program,
name="TicketSignature",
input_fields={"msg_text": "message"}, # row_col → sig_field
output_fields={"urg": "urgency", "sent": "sentiment"},
metric_lm=large_lm,
reflection_lm=large_lm,
)
results = auto.run()
Advanced: step-by-step control
If you prefer fine-grained control over each stage, you can call the individual methods that run() orchestrates under the hood:
# Optional: generate the metric file first for human inspection
metric_file = auto.build_metric()
print(f"Metric written to {metric_file}")
# After reviewing, proceed:
ds = auto.datasets()
baseline = auto.run_baseline(datasets=ds)
optimized = auto.train(datasets=ds)
final = auto.run_baseline(module=optimized, datasets=ds)
# Or compare and promote
comparison = auto.compare(
optimized_module=optimized,
datasets=ds,
)
auto.promote(
optimized_module=optimized,
destination=auto._run_dir / "optimized_ticket_classifier.json",
)
API
Constructor
AutoGEPA(...) accepts all configuration fields directly:
| Parameter | Type | Description |
|---|---|---|
rows |
list[dict] | DataFrame | None |
Training data. Accepts list[dict], pandas DataFrame, polars DataFrame/LazyFrame, or any object with .to_dicts() or .to_pandas() |
module |
dspy.Module | None |
The DSPy module to optimize |
name |
str | None |
Task name for artifact subdirectory |
input_fields |
list[str] | dict[str, str] | None |
Input field names. List for exact match, dict for {row_column: signature_field} mapping. Inferred from signature if omitted |
output_fields |
list[str] | dict[str, str] | None |
Output field names. Same format as input_fields. Inferred from signature if omitted |
metric |
Path | str | None |
Path to a custom metric .py file (skips generation) |
split |
tuple[float, ...] |
Train/val/test split ratios. Default (0.7, 0.2, 0.1) |
seed |
int |
Random seed for reproducibility. Default 42 |
artifact_dir |
Path | str |
Root directory for artifacts. Default ".auto_gepa" |
metric_lm |
dspy.LM | None |
LM used for metric generation. Defaults to dspy.LM("openrouter/openai/gpt-oss-120b") |
reflection_lm |
dspy.LM | None |
LM used for GEPA reflection. Defaults to dspy.LM("openrouter/moonshotai/kimi-k2.5") |
gepa_auto |
Literal["light", "medium", "heavy"] |
GEPA optimization intensity. Default "light" |
num_threads |
int |
Parallel threads for evaluation. Default 16 |
metric_generator_signature |
Type[dspy.Signature] | None |
Custom signature class for metric generation |
metric_generator_module |
Type[dspy.Module] | None |
Custom module class for metric generation |
Methods
| Method | Signature | Description |
|---|---|---|
build_metric |
(rows, module, name, metric, out_path, force=False) → Path |
Generates the metric .py file explicitly. Skips if a custom metric path is provided. out_path overrides the default save location. Use force=True to overwrite an existing generated metric |
run |
(rows, module, name, metric, force=False) → RunResult |
Orchestrates the full pipeline: datasets → baseline → train → compare → promote. If force=False and a saved model exists at .auto_gepa/<name>/optimized_<name>.json, loads it and skips training. Returns a RunResult with baseline, optimized, improvement, saved_to (or loaded_from if cached) |
datasets |
(rows, module, name, metric, force=False) → Datasets |
Converts rows to dspy.Examples and splits into train/val/test. Uses constructor defaults if args omitted. name sets the artifact subdirectory. force=True overwrites an existing metric file |
run_baseline |
(module=None, datasets) → float |
Evaluates the unoptimized module. Uses module from constructor if not overridden |
train |
(module=None, datasets) → dspy.Module |
Runs GEPA optimization. Uses module from constructor if not overridden |
compare |
(optimized_module, datasets, baseline_module=None) → dict |
Side-by-side score comparison. Uses constructor module as baseline_module if not overridden |
promote |
(optimized_module, destination) → Path |
Saves the optimized program to the given destination |
load_metric |
() → callable |
Lazily loads the generated metric function |
Result Types
RunResult— returned byrun():baseline: float— score before optimizationoptimized: float— score after optimizationimprovement: float— absolute differencesaved_to: Path \| None— where the optimized program was savedloaded_from: Path \| None— if a cached model was loaded instead of training
Datasets— returned bydatasets():train: list[dspy.Example]val: list[dspy.Example]test: list[dspy.Example]
Field Resolution Behaviour
AutoGEPA resolves fields in this order:
- Both provided explicitly (
list[str] | dict[str, str]) — uses exactly what you gave it. Lists mean exact column names. Dicts mean{row_column: signature_field}mapping. - Neither provided — infers both from the module's DSPy Signature. Raises a clear error if row columns don't match signature fields, listing what's missing and what's extra.
- Only one provided — if the other can be inferred from module signature or remaining row keys, great. If not, raises an error.
Contributing
Quick workflow:
- Fork and branch:
git checkout -b feature/name - Make changes
- Commit and push
- Open a Pull Request
License
MIT (as declared in pyproject.toml).
Built by thememium
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dspy_auto_gepa-0.1.7.tar.gz.
File metadata
- Download URL: dspy_auto_gepa-0.1.7.tar.gz
- Upload date:
- Size: 13.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa95a69c2b24ff469445a119fb94bdd161538eceecd75e7d3b06f944b5ceaf5c
|
|
| MD5 |
5b79ef46f16236bdac65b52dbb61eaa3
|
|
| BLAKE2b-256 |
5f98a9d5eb659c2b920fdf8f56f3cb5f6c936eb93c7dcb5c9c69ed9b970c399f
|
File details
Details for the file dspy_auto_gepa-0.1.7-py3-none-any.whl.
File metadata
- Download URL: dspy_auto_gepa-0.1.7-py3-none-any.whl
- Upload date:
- Size: 16.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b99cd4aaf69eb2057f10b7802681dea3a7ea7806416ef94e8afe6643ed67a531
|
|
| MD5 |
cbb925f75b9b172db89ffa6e17133ea1
|
|
| BLAKE2b-256 |
77446541b9ff69c843708eebbf19d851f703e445cedde7f9f8480f6b49300628
|