Creating New Optimizers¶
Guide to implementing a new optimization strategy.
Overview¶
All optimizers implement the Optimizer trait from optillm-core.
Step-by-Step Guide¶
1. Create Crate Structure¶
Bash
mkdir -p crates/my-optimizer/src
cd crates/my-optimizer
2. Create Cargo.toml¶
TOML
[package]
name = "optillm-my-optimizer"
version = "0.1.0"
edition = "2021"
[dependencies]
optillm-core = { path = "../core" }
tokio = { version = "1", features = ["full"] }
async-trait = "0.1"
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0"
uuid = { version = "1.0", features = ["v4", "serde"] }
chrono = { version = "0.4", features = ["serde"] }
3. Implement Optimizer Trait¶
Create src/lib.rs:
Rust
use optillm_core::{Optimizer, Solution, ModelClient, Result, Prompt, ResponseEvent};
use async_trait::async_trait;
pub struct MyOptimizer {
// Your configuration
}
impl MyOptimizer {
pub fn new() -> Self {
Self {
// Initialize config
}
}
}
#[async_trait]
impl Optimizer for MyOptimizer {
async fn optimize(
&self,
query: &str,
client: &dyn ModelClient,
) -> Result<Solution> {
// 1. Create prompt
let mut prompt = Prompt::default();
prompt.input = vec![
// Build prompt structure
];
// 2. Get response from LLM
let mut stream = client.stream(&prompt);
let mut response = String::new();
while let Some(event) = stream.next().await {
match event? {
ResponseEvent::OutputTextDelta { delta, .. } => {
response.push_str(&delta);
}
ResponseEvent::Completed { token_usage } => {
// Handle completion
break;
}
_ => {}
}
}
// 3. Create solution
let solution = Solution::new(
"my-optimizer".to_string(),
"Reasoning here".to_string(),
response,
0.7, // temperature
0, // token count
);
Ok(solution)
}
fn name(&self) -> &str {
"my-optimizer"
}
fn description(&self) -> &str {
"Description of your optimizer"
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_optimizer() {
let optimizer = MyOptimizer::new();
// Test with mock client
}
}
4. Add to Workspace¶
Edit root Cargo.toml:
TOML
[workspace]
members = [
"crates/core",
"crates/mars",
"crates/my-optimizer", # Add this
]
5. Write Tests¶
Rust
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_creation() {
let optimizer = MyOptimizer::new();
assert_eq!(optimizer.name(), "my-optimizer");
}
#[tokio::test]
async fn test_optimization() {
let optimizer = MyOptimizer::new();
let mock_client = MockClient::new();
let result = optimizer.optimize("test query", &mock_client).await;
assert!(result.is_ok());
}
}
6. Create Documentation¶
Create crates/my-optimizer/README.md:
Markdown
# optillm-my-optimizer
## Overview
Brief description of your optimization strategy.
## Usage
```rust
use optillm_my_optimizer::MyOptimizer;
let optimizer = MyOptimizer::new();
let result = optimizer.optimize(query, &client).await?;
Features¶
- Feature 1
- Feature 2
Benchmarks¶
Performance metrics compared to baselines.
Algorithm¶
Detailed explanation of the algorithm.
Text Only
### 7. Submit Pull Request
Include:
- Implementation code
- Comprehensive tests
- Documentation with examples
- Benchmark comparisons
- Design decision explanations
## Testing Your Optimizer
### Unit Tests
```bash
cargo test -p optillm-my-optimizer
Integration Tests¶
Bash
cargo test --all
Performance Testing¶
Rust
use std::time::Instant;
#[tokio::test]
async fn bench_optimizer() {
let optimizer = MyOptimizer::new();
let start = Instant::now();
let result = optimizer.optimize(query, &client).await;
println!("Time: {:?}", start.elapsed());
}
Design Patterns¶
Pattern 1: Configuration¶
Rust
pub struct MyOptimizerConfig {
pub param1: usize,
pub param2: f32,
}
impl Default for MyOptimizerConfig {
fn default() -> Self {
Self {
param1: 3,
param2: 0.7,
}
}
}
Pattern 2: Builder¶
Rust
impl MyOptimizer {
pub fn with_param1(mut self, value: usize) -> Self {
self.config.param1 = value;
self
}
}
Pattern 3: Event Streaming¶
Rust
pub enum OptimizationEvent {
Started,
PhaseCompleted { phase: String },
Completed { solution_id: String },
}
Common Implementation Patterns¶
Multiple Agent Exploration¶
Rust
let mut solutions = Vec::new();
for temperature in &self.temperatures {
let solution = self.explore(query, temperature, client).await?;
solutions.push(solution);
}
Iterative Refinement¶
Rust
let mut best = initial_solution;
for iteration in 0..max_iterations {
let improved = self.refine(&best, client).await?;
if improved.score > best.score {
best = improved;
}
}
Strategy Learning¶
Rust
let mut strategy_network = StrategyNetwork::new();
for solution in &solutions {
if solution.is_verified {
strategy_network.register_strategy(
agent_id,
description,
technique,
);
}
}
Example: Simple Optimizer¶
Rust
use optillm_core::{Optimizer, Solution, ModelClient, Result};
use async_trait::async_trait;
pub struct SimpleOptimizer;
#[async_trait]
impl Optimizer for SimpleOptimizer {
async fn optimize(
&self,
query: &str,
client: &dyn ModelClient,
) -> Result<Solution> {
// Ask LLM once
let mut prompt = Prompt::default();
// ... build prompt
let mut stream = client.stream(&prompt);
let mut response = String::new();
while let Some(event) = stream.next().await {
if let Ok(ResponseEvent::OutputTextDelta { delta, .. }) = event {
response.push_str(&delta);
}
}
Ok(Solution::new(
"simple".to_string(),
"Direct response".to_string(),
response,
0.7,
0,
))
}
fn name(&self) -> &str { "simple" }
fn description(&self) -> &str { "Simple single-pass optimizer" }
}
Next Steps¶
- Implement your optimizer
- Write comprehensive tests
- Add documentation
- Submit for review
- Iterate based on feedback
Questions? See Contributing Guide