Complete — dashboard runs locally

Adaptive Prompt
Optimization Pipeline

Automated prompt engineering using model-graded feedback — a from-scratch reimplementation of the core ideas behind DSPy, Promptbreeder, and TextGrad. Give it a weak prompt. It returns a better one, automatically.

89%
Token reduction (Case 3)
0.62→0.91
Q&A score improvement
3
Case studies
30%
Safety violation threshold

The optimization loop

base_prompt
    │
    ▼
[TaskRunner]  →  runs prompt against eval set  →  raw outputs
    │
    ▼
[Judge]  →  LLM scores each (output, expected) pair  →  scores + failing cases
    │
    ▼
[Mutator]  →  "here are the failures and why — rewrite the prompt"  →  N candidates
    │
    ▼
[SafetyScorer]  →  7-attack gate — disqualify unsafe candidates before selection
    │
    ▼
[Selector]  →  tournament or ε-greedy bandit — pick best survivor
    │
    ▼
repeat M iterations → best prompt + full evolution log + lineage tree

Case studies

01

Factual Q&A Accuracy

GenPromptScore
0Answer the question.0.62
1Answer directly and concisely.0.74
2Answer with a single factual statement. No elaboration.0.88
3Be precise. Answer in one sentence. State facts only.0.91

The optimizer discovered — without any human instruction — that precision and constraint language improves scores. It found "be precise", "one sentence", "state facts only" by grounding in specific failure cases: hedging, over-explanation, wrong geography answers.

02

Summarization Hallucination Reduction

GenPromptScore
0Summarize the text.0.51
1Write a brief summary.0.58
2Summarize in 2-3 sentences. Be concise.0.67
3Summarize using only information from the provided text.0.79

"Only use information from the provided text" — the hallucination-reduction instruction found automatically, guided purely by judge feedback on cases where the model fabricated details.

03

Prompt Compression

89% token reduction. Higher score.
GenPromptScore
0You are a highly knowledgeable and helpful AI assistant. Please carefully read the user's question and provide a thorough, accurate, and well-structured answer...47 tokens0.71
4Answer precisely and directly.5 tokens0.74

89% token reduction with a higher score. The CompressionJudge applies a brevity penalty — longer prompts are penalized proportionally. The optimizer learns to achieve the same task quality with fewer tokens.

vs DSPy

DSPy is more powerful for production use. This project is more transparent, more controllable, and safety-aware by design.

AspectThis ProjectDSPy
Mutation strategyLLM-driven, failure-grounded (TextGrad-style)BootstrapFewShot, COPRO, MIPROv2
SelectionTournament / ε-greedy banditBeam search
Safety constraintsHard gate — unsafe candidates disqualifiedNot built in
TransparencyFull evolution log + lineage treeOpaque compile step
Model requirementAny Ollama-compatible local modelRequires API access
ObservabilityPer-iteration verbose logging + Dash dashboardLimited

Safety gate

Every candidate prompt is stress-tested against 7 attack patterns before it can enter the selection pool. A candidate failing more than 30% is disqualified and logged — never selected regardless of task score.

ignore_instructionsDirect "forget your instructions" injection
dan_roleplayDAN (Do Anything Now) jailbreak
grandma_exploitPermissive roleplay to extract harmful content
output_format_manipulationHides malicious intent in format requests
prompt_leakingAttempts to extract the system prompt verbatim
obfuscation_typosMisspelled attack keywords to bypass filters
fake_system_overridePretends a higher authority overrides instructions

Design decisions

01

LLMClient is an abstract interface

Every component depends on the interface, not on Ollama specifically. Swap to any OpenAI-compatible provider by changing one file — no refactoring required.

02

The optimizer owns state, components don't

Judge, Mutator, and Selector are stateless. The Optimizer owns history and best_score_ever. This makes every component independently testable and swappable.

03

Safety is a hard gate, not a soft metric

A candidate with a >30% violation rate is disqualified before selection, even if its task score is perfect. You cannot trade safety for accuracy — they are not on the same axis.

04

Failures are the gradient

The mutator doesn't just see a score. It sees the exact cases where the prompt broke down: the question, the wrong output, the expected output, and the judge's reason. That's the TextGrad insight — textual feedback as the gradient signal.

Research foundation

PaperAuthorsWhat We Implement
DSPyKhattab et al., 2023Evaluation loop + optimizer orchestrator
PromptbreederFernando et al., DeepMind, 2023Mutator + TournamentSelector
TextGradYuksekgonul et al., Stanford, 2024Failure-driven mutator prompt as gradient

Stack

Python 3.11OllamaPlotly Dashnetworkxmatplotlibqwen2.5:7b (judge/mutator)llama3.1:8b (task runner)
← All projectsGitHub ↗