- DSPyLLMAdapter now accepts dspy.LM instead of model string, uses dspy.context(lm=...) - DSPyJudgeAdapter, DSPyProposerAdapter, DSPySyntheticAdapter each accept and use own LM - OptimizationConfig gains per-model api_base/api_key_env override fields - cli/app.py creates separate dspy.LM per adapter with per-model overrides - New unit tests verify each adapter isolates its LM from global config Fixes Bug #1 (multi-model config not wired) and Bug #2 (DSPyLLMAdapter ignores model param). Co-Authored-By: Paperclip <noreply@paperclip.ing>
52 lines
1.7 KiB
Python
52 lines
1.7 KiB
Python
"""
|
|
Adapter: Reflective Mutation Proposer.
|
|
|
|
Implements the ProposerPort via the DSPy InstructionProposer.
|
|
Converts trajectories into readable format for the LLM proposer.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import dspy
|
|
|
|
from prometheus.domain.entities import Prompt, Trajectory
|
|
from prometheus.domain.ports import ProposerPort
|
|
from prometheus.infrastructure.dspy_modules import InstructionProposer
|
|
|
|
|
|
class DSPyProposerAdapter(ProposerPort):
|
|
"""Uses evaluation trajectories to build a failure report and propose a new prompt."""
|
|
|
|
def __init__(self, lm: dspy.LM) -> None:
|
|
self._lm = lm
|
|
self._proposer = InstructionProposer()
|
|
|
|
def propose(
|
|
self,
|
|
current_prompt: Prompt,
|
|
trajectories: list[Trajectory],
|
|
task_description: str,
|
|
) -> Prompt:
|
|
failure_examples = self._format_failures(trajectories)
|
|
with dspy.context(lm=self._lm):
|
|
pred = self._proposer(
|
|
current_instruction=current_prompt.text,
|
|
task_description=task_description,
|
|
failure_examples=failure_examples,
|
|
)
|
|
return Prompt(text=pred.new_instruction)
|
|
|
|
@staticmethod
|
|
def _format_failures(trajectories: list[Trajectory]) -> str:
|
|
"""Convert trajectories into a structured textual report."""
|
|
sections: list[str] = []
|
|
for i, t in enumerate(trajectories, 1):
|
|
section = (
|
|
f"# Example {i}\n"
|
|
f"## Input\n{t.input_text}\n\n"
|
|
f"## Generated Output\n{t.output_text}\n\n"
|
|
f"## Score\n{t.score:.2f}\n\n"
|
|
f"## Feedback\n{t.feedback}\n"
|
|
)
|
|
sections.append(section)
|
|
return "\n---\n".join(sections)
|