Skip to content

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.