latent.optimize.combined¶
Combined DSPy + ACE optimizer.
Classes¶
CombinedOptimizer¶
CombinedOptimizer(agent: BaseAgent, dspy_config: dict[str, Any] | None = None, ace_config: dict[str, Any] | None = None, lower_is_better: bool = False, tracker: ExperimentTracker | None = None)
Chains DSPy (candidate generation) → ACE (calibration).
Phase 1: DSPy teleprompter generates candidate prompts (dspy_iters). Phase 2: ACE refines the best DSPy candidate (ace_iters).
A single ExperimentTracker spans both phases with labels: - "dspy: trial N" - "ace: round N"
Methods¶
CombinedOptimizer.optimize¶
optimize(train_data: list[dict[str, Any]], metric: Any, dspy_metric: Any = None, ace_metric: Any = None, max_iterations: int = 10) -> OptimizationResult
Run DSPy then ACE optimization.
Args:
train_data: Training data dicts.
metric: Default metric used by whichever phase doesn't have its own.
dspy_metric: DSPy-convention metric: (example, prediction, trace) -> float.
Defaults to metric when not supplied.
ace_metric: ACE-convention metric: (expected_str, predicted_str) -> float.
Defaults to metric when not supplied.
max_iterations: Total iterations split evenly between DSPy and ACE.
Returns: Merged OptimizationResult covering both phases.
Note:
DSPy and ACE use incompatible calling conventions. When passing a
single metric, it must satisfy both:
- DSPy: called as metric(dspy.Example, dspy.Prediction, trace)
- ACE: called as metric(expected_str, predicted_str)
Pass dspy_metric and ace_metric separately to avoid the
mismatch when the conventions differ.