use serde::{Deserialize, Serialize};
use std::collections::HashMap;
pub struct PromptOptimizer {
strategies: Vec<Box<dyn OptimizationStrategy>>,
templates: TemplateLibrary,
history: PerformanceHistory,
}
trait OptimizationStrategy: Send + Sync {
fn optimize(&self, prompt: &str, context: &OptimizationContext) -> String;
fn name(&self) -> &str;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OptimizationContext {
pub task_type: TaskCategory,
pub target_model: Option<String>,
pub desired_length: Option<usize>,
pub tone: Option<Tone>,
pub expertise_level: ExpertiseLevel,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TaskCategory {
Analysis,
Generation,
Summarization,
Translation,
QuestionAnswering,
Reasoning,
Creative,
Technical,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Tone {
Professional,
Casual,
Academic,
Creative,
Technical,
Friendly,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ExpertiseLevel {
Beginner,
Intermediate,
Advanced,
Expert,
}
impl PromptOptimizer {
pub fn new() -> Self {
Self {
strategies: Self::default_strategies(),
templates: TemplateLibrary::default(),
history: PerformanceHistory::new(),
}
}
pub fn optimize(&self, prompt: &str) -> OptimizedPrompt {
let context = self.analyze_context(prompt);
let mut optimized = prompt.to_string();
let mut techniques_applied = Vec::new();
for strategy in &self.strategies {
if self.should_apply_strategy(&strategy, &context) {
optimized = strategy.optimize(&optimized, &context);
techniques_applied.push(strategy.name().to_string());
}
}
if let Some(template) = self.templates.find_best_template(&context) {
optimized = template.apply(&optimized);
techniques_applied.push(format!("Template: {}", template.name));
}
let variations = self.generate_variations(&optimized, &context);
let confidence = self.calculate_confidence(&techniques_applied);
OptimizedPrompt {
original: prompt.to_string(),
optimized,
variations,
techniques_applied,
context,
confidence,
}
}
fn analyze_context(&self, prompt: &str) -> OptimizationContext {
let task_type = self.detect_task_type(prompt);
let expertise = self.detect_expertise_level(prompt);
OptimizationContext {
task_type,
target_model: None,
desired_length: self.estimate_desired_length(prompt),
tone: self.detect_tone(prompt),
expertise_level: expertise,
}
}
fn detect_task_type(&self, prompt: &str) -> TaskCategory {
let lower = prompt.to_lowercase();
if lower.contains("analyze") || lower.contains("explain") {
TaskCategory::Analysis
} else if lower.contains("create") || lower.contains("generate") || lower.contains("write") {
TaskCategory::Generation
} else if lower.contains("summarize") || lower.contains("tldr") {
TaskCategory::Summarization
} else if lower.contains("translate") {
TaskCategory::Translation
} else if lower.starts_with("what") || lower.starts_with("how") || lower.starts_with("why") {
TaskCategory::QuestionAnswering
} else if lower.contains("reason") || lower.contains("think") {
TaskCategory::Reasoning
} else {
TaskCategory::Technical
}
}
fn detect_expertise_level(&self, prompt: &str) -> ExpertiseLevel {
let technical_terms = ["algorithm", "implementation", "architecture", "optimization", "complexity"];
let count = technical_terms.iter().filter(|t| prompt.contains(*t)).count();
match count {
0 => ExpertiseLevel::Beginner,
1 => ExpertiseLevel::Intermediate,
2 => ExpertiseLevel::Advanced,
_ => ExpertiseLevel::Expert,
}
}
fn detect_tone(&self, prompt: &str) -> Option<Tone> {
if prompt.contains("please") || prompt.contains("could you") {
Some(Tone::Friendly)
} else if prompt.contains("technical") || prompt.contains("detailed") {
Some(Tone::Technical)
} else if prompt.contains("academic") || prompt.contains("research") {
Some(Tone::Academic)
} else {
None
}
}
fn estimate_desired_length(&self, prompt: &str) -> Option<usize> {
if prompt.contains("brief") || prompt.contains("short") {
Some(200)
} else if prompt.contains("detailed") || prompt.contains("comprehensive") {
Some(1000)
} else if prompt.contains("concise") {
Some(300)
} else {
None
}
}
fn should_apply_strategy(&self, _strategy: &Box<dyn OptimizationStrategy>, _context: &OptimizationContext) -> bool {
true }
fn generate_variations(&self, optimized: &str, _context: &OptimizationContext) -> Vec<PromptVariation> {
let mut variations = Vec::new();
variations.push(PromptVariation {
prompt: format!("Specifically regarding the following: {}", optimized),
strategy: "Specificity Enhancement".to_string(),
expected_improvement: 15.0,
});
variations.push(PromptVariation {
prompt: format!("{}\n\nProvide concrete examples in your response.", optimized),
strategy: "Example Request".to_string(),
expected_improvement: 20.0,
});
variations.push(PromptVariation {
prompt: format!("{}\n\nStructure your response with clear sections and bullet points where appropriate.", optimized),
strategy: "Structure Enhancement".to_string(),
expected_improvement: 25.0,
});
variations
}
fn calculate_confidence(&self, techniques: &[String]) -> f64 {
let mut confidence = 0.7;
confidence += techniques.len() as f64 * 0.05;
confidence.min(0.95)
}
fn default_strategies() -> Vec<Box<dyn OptimizationStrategy>> {
vec![
Box::new(ClarityEnhancer),
Box::new(ContextInjector),
Box::new(ChainOfThought),
Box::new(FewShotLearning),
Box::new(RoleSpecification),
]
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OptimizedPrompt {
pub original: String,
pub optimized: String,
pub variations: Vec<PromptVariation>,
pub techniques_applied: Vec<String>,
pub context: OptimizationContext,
pub confidence: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PromptVariation {
pub prompt: String,
pub strategy: String,
pub expected_improvement: f64,
}
struct ClarityEnhancer;
impl OptimizationStrategy for ClarityEnhancer {
fn optimize(&self, prompt: &str, _context: &OptimizationContext) -> String {
if !prompt.contains('?') && !prompt.contains('.') {
format!("{}. Please provide a clear and detailed response.", prompt)
} else {
prompt.to_string()
}
}
fn name(&self) -> &str {
"Clarity Enhancement"
}
}
struct ContextInjector;
impl OptimizationStrategy for ContextInjector {
fn optimize(&self, prompt: &str, context: &OptimizationContext) -> String {
match context.task_type {
TaskCategory::Analysis => {
format!("Analyze the following in detail: {}", prompt)
}
TaskCategory::Generation => {
format!("Generate a comprehensive response for: {}", prompt)
}
_ => prompt.to_string(),
}
}
fn name(&self) -> &str {
"Context Injection"
}
}
struct ChainOfThought;
impl OptimizationStrategy for ChainOfThought {
fn optimize(&self, prompt: &str, context: &OptimizationContext) -> String {
match context.task_type {
TaskCategory::Reasoning | TaskCategory::Analysis => {
format!("Let's think step by step about this: {}", prompt)
}
_ => prompt.to_string(),
}
}
fn name(&self) -> &str {
"Chain of Thought"
}
}
struct FewShotLearning;
impl OptimizationStrategy for FewShotLearning {
fn optimize(&self, prompt: &str, context: &OptimizationContext) -> String {
if matches!(context.expertise_level, ExpertiseLevel::Expert) {
prompt.to_string()
} else {
format!("{}\n\nConsider similar examples if helpful.", prompt)
}
}
fn name(&self) -> &str {
"Few-Shot Learning"
}
}
struct RoleSpecification;
impl OptimizationStrategy for RoleSpecification {
fn optimize(&self, prompt: &str, context: &OptimizationContext) -> String {
let role = match context.task_type {
TaskCategory::Technical => "You are a technical expert. ",
TaskCategory::Creative => "You are a creative professional. ",
TaskCategory::Generation => "You are a content creator. ",
_ => "",
};
if !role.is_empty() {
format!("{}{}", role, prompt)
} else {
prompt.to_string()
}
}
fn name(&self) -> &str {
"Role Specification"
}
}
#[derive(Default)]
struct TemplateLibrary {
templates: HashMap<String, PromptTemplate>,
}
struct PromptTemplate {
name: String,
pattern: String,
}
impl PromptTemplate {
fn apply(&self, prompt: &str) -> String {
self.pattern.replace("{PROMPT}", prompt)
}
}
impl TemplateLibrary {
fn find_best_template(&self, _context: &OptimizationContext) -> Option<&PromptTemplate> {
None }
}
struct PerformanceHistory {
history: Vec<HistoryEntry>,
}
struct HistoryEntry {
prompt: String,
optimized: String,
performance_score: f64,
}
impl PerformanceHistory {
fn new() -> Self {
Self {
history: Vec::new(),
}
}
fn record(&mut self, prompt: String, optimized: String, score: f64) {
self.history.push(HistoryEntry {
prompt,
optimized,
performance_score: score,
});
}
}