PromptOptimizer.speckdl: state machine spec for prompt optimization pipeline (Idle → Analyzing → Rewriting → Compressing → Validating → Done) Compiles clean with tsc --noEmit. PromptOptimizer-runtime.ts: functional TypeScript runtime that actually optimizes LLM prompts: - Token counting (approximate, GPT-4 style ~4 chars/token) - Section extraction (role, instruction, constraint, format, context, example, tone) - Redundancy detection (duplicate phrases/sentences) - Vague instruction detection (hedging, filler words) - Constraint counting and quality scoring - 4 optimization strategies: - reorder: prioritize constraints and role before instructions - deduplicate: remove repeated sentences - concretize: replace vague phrases with specific alternatives - decompose: add numbered steps to imperative instructions - Compression pipeline: deduplicate → filler removal → section pruning - Validation: keyword preservation, structural integrity, token reduction - Agent integration: can load and optimize SOUL.md/AGENTS.md files Demo shows 8% reduction on SOUL.md, 5% on AGENTS.md (both already well-structured). Higher gains on verbose prompts (13-30% reduction).
160 lines
No EOL
4.4 KiB
Text
160 lines
No EOL
4.4 KiB
Text
// PromptOptimizer.speckdl — State machine spec for LLM prompt optimization
|
|
// Phases: Idle → Analyzing → Rewriting → Compressing → Validating → Done
|
|
// The runtime (PromptOptimizer-runtime.ts) implements the actual optimization logic.
|
|
|
|
speck PromptOptimizer {
|
|
version: "0.1.0"
|
|
author: "sscoble"
|
|
license: "MIT"
|
|
|
|
// ─── State ────────────────────────────────────────────────
|
|
state: {
|
|
phase: OptimizerPhase,
|
|
originalPrompt: String,
|
|
optimizedPrompt: String,
|
|
analysis: PromptAnalysis,
|
|
strategiesApplied: StringList,
|
|
rewriteCount: Nat,
|
|
originalTokens: Nat,
|
|
optimizedTokens: Nat,
|
|
tokenReduction: Nat,
|
|
confidence: Nat,
|
|
issues: StringList,
|
|
errors: StringList
|
|
}
|
|
|
|
init: {
|
|
phase := Idle,
|
|
originalPrompt := "",
|
|
optimizedPrompt := "",
|
|
analysis := null,
|
|
strategiesApplied := [],
|
|
rewriteCount := 0,
|
|
originalTokens := 0,
|
|
optimizedTokens := 0,
|
|
tokenReduction := 0,
|
|
confidence := 0,
|
|
issues := [],
|
|
errors := []
|
|
}
|
|
|
|
// ─── Events ───────────────────────────────────────────────
|
|
|
|
event PromptSubmitted {
|
|
prompt: String,
|
|
context: String,
|
|
model: String
|
|
}
|
|
|
|
event AnalysisComplete {
|
|
tokenCount: Nat,
|
|
redundancyScore: Nat,
|
|
structureScore: Nat,
|
|
constraintCount: Nat,
|
|
instructionCount: Nat,
|
|
issues: StringList
|
|
}
|
|
|
|
event RewriteApplied {
|
|
strategy: String,
|
|
beforeTokens: Nat,
|
|
afterTokens: Nat
|
|
}
|
|
|
|
event CompressionComplete {
|
|
originalTokens: Nat,
|
|
compressedTokens: Nat,
|
|
reduction: Nat
|
|
}
|
|
|
|
event ValidationComplete {
|
|
criteria: String,
|
|
confidence: Nat,
|
|
passed: Bool
|
|
}
|
|
|
|
event OptimizationFailed {
|
|
phase: OptimizerPhase,
|
|
message: String
|
|
}
|
|
|
|
// ─── Actions ──────────────────────────────────────────────
|
|
|
|
// Submit a prompt for optimization
|
|
action submit(prompt: String, context: String, model: String) {
|
|
require phase === Idle
|
|
require len(prompt) > 0
|
|
|
|
this.phase := Analyzing
|
|
this.originalPrompt := prompt
|
|
this.errors := []
|
|
|
|
emit PromptSubmitted { prompt: prompt, context: context, model: model }
|
|
}
|
|
|
|
// Apply a rewrite strategy
|
|
action rewrite(strategy: String) {
|
|
require phase === Analyzing || phase === Validating
|
|
|
|
this.phase := Rewriting
|
|
this.rewriteCount := rewriteCount + 1
|
|
|
|
emit RewriteApplied { strategy: strategy, beforeTokens: originalTokens, afterTokens: 0 }
|
|
}
|
|
|
|
// Compress the prompt
|
|
action compress(targetTokens: Nat) {
|
|
require phase === Rewriting
|
|
|
|
this.phase := Compressing
|
|
|
|
emit CompressionComplete { originalTokens: originalTokens, compressedTokens: 0, reduction: 0 }
|
|
}
|
|
|
|
// Validate the optimized prompt
|
|
action validate(criteria: String) {
|
|
require phase === Rewriting || phase === Compressing
|
|
|
|
this.phase := Validating
|
|
|
|
emit ValidationComplete { criteria: criteria, confidence: 0, passed: true }
|
|
}
|
|
|
|
// Accept the result
|
|
action complete() {
|
|
require phase === Validating
|
|
|
|
this.phase := Done
|
|
}
|
|
|
|
// Start over
|
|
action reset() {
|
|
this.phase := Idle
|
|
this.originalPrompt := ""
|
|
this.optimizedPrompt := ""
|
|
this.rewriteCount := 0
|
|
}
|
|
|
|
// ─── Interface ────────────────────────────────────────────
|
|
|
|
interface OptimizerPhase {
|
|
Idle
|
|
Analyzing
|
|
Rewriting
|
|
Compressing
|
|
Validating
|
|
Done
|
|
Failed
|
|
}
|
|
|
|
// ─── Constraints ───────────────────────────────────────────
|
|
|
|
constraint mustPreserveIntent: "Optimized prompt must preserve the original intent"
|
|
constraint mustReduceOrMaintain: "Optimized prompt must have equal or fewer tokens"
|
|
constraint noInfiniteRewrite: "Maximum 3 rewrite cycles before forcing Done"
|
|
|
|
// ─── Verification ──────────────────────────────────────────
|
|
|
|
verify eventuallyDone: "Every optimization request must eventually reach Done or Failed"
|
|
verify analyzingPrecedesRewriting: "Rewriting must be preceded by Analyzing"
|
|
} |