Skip to content
Open

SAPO #129

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ CoolPrompt is a framework for automatic prompt creation and optimization.
- RE-GPS
- RIDER
- BRAVE
- SAPO
- PromptCompressor
- *(legacy/deprecated)*: ReflectivePrompt, DistillPrompt
- **LLM-Agnostic Choice:** work with your custom llm (from open-sourced to proprietary) using [supported Langchain LLMs](https://python.langchain.com/docs/integrations/llms/)
Expand Down Expand Up @@ -70,6 +71,7 @@ Compared metrics:
| `regps` | Required | High | Very High | High |
| `rider` | Required | Very High | Very High | Very High |
| `brave` | Required | High | Very High | Budget-controlled |
| `sapo` | Required | High | Very High | High |
| `compress` | None | Low | Medium | Low |
| `reflective` | Required | High | High | High |
| `distill` | Required | High | High | High |
Expand Down Expand Up @@ -144,11 +146,25 @@ final_prompt = prompt_tuner.run(
)
```

The bundled metadata contains SAPO, RIDER, and HyPER results. CoolPrompt does
not yet implement SAPO, so an SAPO recommendation is transparently executed
with `hyper`; the fallback reason is recorded in `meta_selection`. Pass
The bundled metadata contains SAPO, RIDER, and HyPER results. A SAPO
recommendation is executed directly with the built-in segment-based optimizer. Pass
`meta_classifier_path="/path/to/metadata.csv"` to use a custom CSV. Without
`dataset` and `target`, `method="auto"` uses `hyper_light`.

Run SAPO directly when you want contrastive, segment-level prompt refinement:

```python
final_prompt = prompt_tuner.run(
"Summarize the article concisely.",
task="generation",
dataset=["Article one", "Article two"],
target=["Summary one", "Summary two"],
method="sapo",
validation_size=0.5,
n_iterations=3,
n_candidates=4,
)
```

## Examples

Expand Down
1 change: 0 additions & 1 deletion coolprompt/meta_selector/data/__init__.py

This file was deleted.

4 changes: 2 additions & 2 deletions coolprompt/meta_selector/selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def to_dict(self) -> dict[str, Any]:


class APOMetaSelector:
"""Choose RIDER or HyPER from quality, cost, and runtime metadata.
"""Choose SAPO, RIDER, or HyPER from quality, cost, and runtime metadata.

The selector keeps method choice independent from the caller's LLM: model
recommendations are returned for diagnostics only and never replace it.
Expand Down Expand Up @@ -371,5 +371,5 @@ def _map_method(method: str) -> tuple[str, str | None]:
if method == "HyPER":
return "hyper", None
if method == "SAPO":
return "hyper", "SAPO is not implemented in CoolPrompt"
return "sapo", None
return "hyper", f"Unsupported recommendation '{method}'; defaulted to HyPER."
4 changes: 3 additions & 1 deletion coolprompt/method_evaluation/method_evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from coolprompt.optimizer.reflective_prompt import ReflectiveMethod
from coolprompt.optimizer.regps import ReGPSMethod
from coolprompt.optimizer.rider import RIDERGenesisMethod
from coolprompt.optimizer.sapo import SAPOMethod

_BENCHMARK_IMPL: dict[str, AutoPromptingMethod] = {
"hyper_light": HyPERLightMethod,
Expand All @@ -23,6 +24,7 @@
"regps": ReGPSMethod,
"rider": RIDERGenesisMethod,
"brave": BRAVEMethod,
"sapo": SAPOMethod,
}


Expand All @@ -39,7 +41,7 @@ def evaluate_method(
Args:
method: One of
``hyper_light``, ``hyper``, ``reflective`` / ``reflectiveprompt``,
``distill``, ``compress``, ``regps``, ``rider``, ``brave``
``distill``, ``compress``, ``regps``, ``rider``, ``brave``, ``sapo``
(same names as in
``PromptTuner`` / ``validate_method`` where applicable).
model: LangChain language model used for optimization and evaluation.
Expand Down
5 changes: 5 additions & 0 deletions coolprompt/optimizer/sapo/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Public SAPO optimizer exports."""

from .sapo import SAPOMethod, SAPOOptimizer

__all__ = ["SAPOMethod", "SAPOOptimizer"]
62 changes: 62 additions & 0 deletions coolprompt/optimizer/sapo/prompt_templates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""Meta-prompts used by the segment-based SAPO optimizer."""

SEGMENTATION_TEMPLATE = """You are an expert prompt engineer.
Decompose the prompt below into four segments. Return JSON only with string
fields: role, context, tasks, output_format. Use an empty string when a segment
is absent. Do not invent text that is not present in the prompt.

Prompt:
\"\"\"
{prompt}
\"\"\"
"""

WEAKNESS_ANALYSIS_TEMPLATE = """You are an expert prompt engineer.
Analyze the prompt using the strongest and weakest examples below. Return JSON
only with these fields:
- weak_segments: a list containing only role, context, tasks, output_format
- strong_segments: a list containing only role, context, tasks, output_format
- recommendations: an object mapping weak segment names to concise actions

Prompt:
\"\"\"
{prompt}
\"\"\"

Current segments:
Role: {role}
Context: {context}
Tasks: {tasks}
Output format: {output_format}

Best examples:
{best_examples}

Worst examples:
{worst_examples}
"""

CANDIDATE_GENERATION_TEMPLATE = """You are an expert prompt engineer.
Generate {n_candidates} diverse, standalone improved versions of the current
prompt. Modify the weak segments according to the recommendations and preserve
the strong segments. Do not copy dataset examples into a prompt. Do not add an
input placeholder: CoolPrompt appends each input separately at runtime.

Return JSON only as {{"prompts": ["candidate 1", "candidate 2"]}}.

Current prompt:
\"\"\"
{current_prompt}
\"\"\"

Segments:
Role: {role}
Context: {context}
Tasks: {tasks}
Output format: {output_format}

Weak segments: {weak_segments}
Strong segments: {strong_segments}
Recommendations:
{recommendations}
"""
Loading
Loading