### Predictor Usage for Question Answering in Rust Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/getting-started/quickstart.mdx Demonstrates how to initialize and use a Predictor module in Rust to answer a question. It shows the creation of an Example input and processing the prediction result. This requires the dspy-rs crate. ```rust use dspy_rs::{Example, Predict, hashmap}; #[tokio::main] async fn main() -> anyhow::Result<()> { let predictor = Predict::new(signature); // Define the question let question = "What is gravity?"; // Create an example input to the predictor let inputs = Example::new( hashmap! { "question".to_string() => question.to_string().into() }, vec!["question".to_string()], vec!["answer".to_string però ); let result = predictor.forward(inputs).await?; println!("Answer: {:?}", result.get("answer", None).as_str().unwrap()); Ok(()) } ``` -------------------------------- ### Install Mintlify CLI Source: https://github.com/krypticmouse/dsrs/blob/main/docs/README.md Installs the Mintlify CLI globally using npm. This tool is required to preview documentation changes locally. ```bash npm i -g mint ``` -------------------------------- ### Install DSRs in Rust Project Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/getting-started/quickstart.mdx This snippet shows how to add the DSRs crate to a Rust project. It can be done by directly modifying the Cargo.toml file or by using the `cargo add` command. Note that the crate name used for installation is `dspy-rs`. ```toml [dependencies] anyhow = "1.0.99" dspy-rs = "0.5.0" serde = "1.0.221" serde_json = "1.0.145" tokio = "1.47.1" ``` ```bash cargo add dspy-rs anyhow serde serde_json tokio ``` -------------------------------- ### Rust Development Setup with Cargo Source: https://github.com/krypticmouse/dsrs/blob/main/README.md This snippet details essential commands for setting up and working with the DSRS project using Cargo, Rust's build system and package manager. It covers cloning the repository, building the project, running tests, executing examples, checking code formatting, and performing linting with clippy. ```bash git clone https://github.com/krypticmouse/dsrs.git cd dsrs cargo build cargo test cargo run --example 01-simple cargo fmt -- --check cargo clippy -- -D warnings ``` -------------------------------- ### Create a Simple Predictor in DSRs Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/getting-started/quickstart.mdx This Rust code illustrates the creation of a simple predictor in DSRs. It defines a `QA` signature with a specific instruction in the doc comment for the LM to use Renaissance-era English. The code sets up the LM, configures it, and initializes a predictor instance, all within an asynchronous `tokio` runtime. ```rust use dspy_rs::{ ChatAdapter, Example, LM, LMConfig, Predict, Predictor, Signature, configure, hashmap, }; use std::env; #[Signature] struct QA { /// Use Renaissance-era English to answer the question. #[input] pub question: String, #[output] pub answer: String, } #[tokio::main] async fn main() -> Result<(), anyhow::Error> { let config = LMConfig::builder().model("gpt-4.1-nano".to_string()).build(); let lm = LM::builder() .config(config) .api_key(env::var("OPENAI_API_KEY")?.into()) .build(); configure(lm.clone(), ChatAdapter::default()); // Create a questin-answering signature instance let signature = QA::new(); // Create a predictor ``` -------------------------------- ### Start Mintlify Local Development Server Source: https://github.com/krypticmouse/dsrs/blob/main/docs/README.md Runs the Mintlify development server from the root of your documentation project. This command assumes 'docs.json' is present in the current directory. ```bash mint dev ``` -------------------------------- ### Add Few-Shot Examples to Rust Signature Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/building-blocks/signature.mdx This snippet illustrates how to attach few-shot examples to a Rust signature at runtime. It uses the `Example::new` function and `hashmap!` macro to define input-output pairs for few-shot prompting. ```rust use dsrs::{Example, MetaSignature, hashmap}; let mut sig = QA::new(); sig.set_demos(vec![ Example::new( hashmap!{ "question".to_string() => "What is gravity?".into(), "answer".to_string() => "A natural power that draweth bodies earthward.".into() }, vec!["question".to_string()], vec!["answer".to_string lesquer ) ])?; ``` -------------------------------- ### Configure Language Model in DSRs Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/getting-started/quickstart.mdx This Rust code demonstrates how to configure a Language Model (LM) within DSRs. It utilizes the `async-openai` crate's capabilities, setting up the LM configuration with a specific model and API key, then configuring the global LM and default `ChatAdapter` for the application. ```rust use dspy_rs::{configure, ChatAdapter, LM, LMConfig}; use std::env; fn main() -> Result<(), anyhow::Error> { //Define a config for the LM let config = LMConfig::builder() .model("gpt-4.1-nano".to_string()) .build(); // Create the LM instance via the builder let lm = LM::builder() .config(config) .api_key(env::var("OPENAI_API_KEY")?.into()) .build(); // Configure the global LM and adapter configure(lm, ChatAdapter::default()); Ok(()) } ``` -------------------------------- ### Create Examples and Predictions in Rust Source: https://context7.com/krypticmouse/dsrs/llms.txt Learn to build training data and handle prediction outputs using strongly-typed structures in Rust. This snippet shows how to define examples with input/output fields, access their data, create predictions, and manipulate examples by removing or specifying input keys. It also demonstrates iterating over example fields. ```rust use dspy_rs::{Example, Prediction, example, prediction}; use serde_json::json; fn main() { // Create example with input/output fields let training_example = example! { "question": "input" => "What is the capital of France?", "answer": "output" => "Paris", }; // Access fields println!("Question: {}", training_example.get("question", None)); println!("Answer: {}", training_example.get("answer", None)); // Create prediction let pred = prediction! { "answer" => "Paris", "confidence" => 0.95, }; // Manipulate examples let modified = training_example.without(vec!["answer".to_string()]); let with_keys = training_example.with_input_keys(vec!["question".to_string()]); // Iterate over fields for (key, value) in training_example.clone() { println!("{}: {}", key, value); } } ``` -------------------------------- ### Actionable Feedback Metric Example (Rust) Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/optimizers/gepa.mdx Demonstrates the difference between vague and specific, actionable feedback using the `FeedbackMetric` structure. The 'GOOD' example provides detailed expected vs. predicted values and explicitly states the identified issue, making it much more useful for guiding improvements. ```rust // BAD: Vague feedback FeedbackMetric::new(0.5, "Wrong answer") // GOOD: Specific, actionable feedback FeedbackMetric::new(0.5, "Incorrect answer\n\ Expected: 'Paris'\n\ Predicted: 'France'\n\ Issue: Returned country instead of city") ``` -------------------------------- ### Building Custom Modules with Predictors in Rust Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/getting-started/quickstart.mdx Illustrates how to create a custom module, `AnswerQuestion`, that wraps a `Predict` module in Rust. This custom module implements the `Module` trait and can be used similarly to a predictor. It shows module instantiation, configuration, and calling the `forward` method. ```rust use dspy_rs::{ ChatAdapter, Example, LM, LMConfig, Module, Predict, Prediction, Predictor, Signature, configure, hashmap, }; use std::env; struct AnswerQuestion { inner: Predict, } impl AnswerQuestion { fn new() -> Self { Self { inner: Predict::new(QA::new()), } } } impl Module for AnswerQuestion { async fn forward(&self, inputs: Example) -> anyhow::Result { self.inner.forward(inputs).await } } #[tokio::main] async fn main() -> anyhow::Result<()> { let config = LMConfig::builder() .model("gpt-4.1-nano".to_string()) .build(); let lm: LM = LM::builder() .config(config) .api_key(env::var("OPENAI_API_KEY")?.into()) .build(); configure(lm, ChatAdapter::default()); // Create the module instance let module = AnswerQuestion::new(); // Define the question let question = "What is gravity?"; // Create an example input to the module let inputs = Example::new( hashmap! { "question".to_string() => question.to_string().into() }, vec!["question".to_string()], vec!["answer".to_string()], ); let result = module.forward(inputs).await?; println!("Answer: {:?}", result.get("answer", None).as_str().unwrap()); Ok(()) } ``` -------------------------------- ### Run GEPA LLM Judge Example - Bash Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/optimizers/gepa-llm-judge.mdx Command to run the GEPA LLM Judge example. This involves setting the OPENAI_API_KEY environment variable and executing the cargo run command with the specified example. The output will demonstrate baseline performance, judge evaluations, prompt evolution, and final test results. ```bash OPENAI_API_KEY=your_key cargo run --example 10-gepa-llm-judge ``` -------------------------------- ### Rust: Compile and Optimize Module with MIPROv2 Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/optimizers/miprov2.mdx Shows the practical usage of the MIPROv2 optimizer to compile and optimize a given module using provided training examples. It initializes the optimizer with specific configurations and then calls the compile method. ```rust use dspy_rs::{MIPROv2, Optimizer}; // Create optimizer let optimizer = MIPROv2::builder() .num_candidates(10) .num_trials(20) .minibatch_size(25) .build(); // Optimize your module optimizer.compile(&mut module, train_examples).await?; ``` -------------------------------- ### Rust Quick Start: Sentiment Analysis with DSRs Source: https://github.com/krypticmouse/dsrs/blob/main/README.md This Rust code snippet provides a quick start example for using DSRs to perform sentiment analysis. It defines a `SentimentAnalyzer` signature, configures an OpenAI language model, creates a predictor, and executes a prediction on sample text. ```rust use anyhow::Result; use dspy_rs::*; #[Signature] struct SentimentAnalyzer { /// Predict the sentiment of the given text 'Positive', 'Negative', or 'Neutral'. #[input] pub text: String, #[output] pub sentiment: String, } #[tokio::main] async fn main() -> Result<()> { let lm = LM::builder() .api_key(std::env::var("OPENAI_API_KEY")?.into()) .config( LMConfig::builder() .model("gpt-4.1-nano".to_string()) .temperature(0.5) .build(), ) .build(); configure(lm, ChatAdapter); // Create a predictor let predictor = Predict::new(SentimentAnalyzer::new()); // Prepare input let example = example! { "text": "input" => "Acme is a great company with excellent customer service.", }; // Execute prediction let result = predictor.forward(example).await?; println!("Answer: {}", result.get("sentiment", None)); Ok(()) } ``` -------------------------------- ### Define Task Signatures in DSRs (Inline Macro) Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/getting-started/quickstart.mdx This Rust snippet shows how to define a task signature using DSRs' inline macro `sign!`. It specifies the input and output fields for the LM call. This method is concise for simple signatures. ```rust let signature = sign! { (question: String) -> answer: String }; ``` -------------------------------- ### Compile a Module with COPRO Optimizer (Rust) Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/optimizers/copro.mdx This example shows how to compile an optimizable module using the COPRO optimizer. It involves setting up a language model, configuring a module with parameters and evaluation logic, and then invoking the COPRO's compile method with a training dataset. ```rust use dspy_rs::{COPRO, Optimizer}; #[derive(Builder, Optimizable)] struct MyModule { #[parameter] predictor: Predict, } impl Module for MyModule { async fn forward(&self, inputs: Example) -> Result { self.predictor.forward(inputs).await } } impl Evaluator for MyModule { async fn metric(&self, example: &Example, prediction: &Prediction) -> f32 { // Your evaluation logic if prediction.get("answer", None) == example.get("expected", None) { 1.0 } else { 0.0 } } } #[tokio::main] async fn main() -> Result<()> { let lm = LM::builder()...build(); configure(lm, ChatAdapter); let mut module = MyModule::builder()...build(); let copro = COPRO::builder() .breadth(10) .depth(3) .build(); copro.compile(&mut module, trainset).await?; Ok(()) } ``` -------------------------------- ### Rust: Generate Execution Traces Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/optimizers/miprov2.mdx Generates a dataset of execution traces by running a program with training examples and capturing input/output pairs along with evaluation scores. This function is a key part of understanding the current behavior of the module. ```rust async fn generate_traces( &self, module: &M, examples: &[Example], ) -> Result> ``` -------------------------------- ### Run DSRS Tests using Cargo Source: https://github.com/krypticmouse/dsrs/blob/main/README.md Provides commands for running the test suite of the DSRS project using Cargo. It includes instructions for running all tests, specific tests, running tests with output capture, and executing example binaries. ```bash # All tests cargo test # Specific test cargo test test_predictors # With output cargo test -- --nocapture # Run examples cargo run --example 01-simple ``` -------------------------------- ### Define Task Signatures in DSRs (Attribute Macro) Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/getting-started/quickstart.mdx This Rust code defines a task signature using DSRs' attribute macro `#[Signature]` on a struct. This approach allows for more granular control, including adding doc comments for overall signature description and annotating individual input/output fields with descriptions. ```rust use dspy_rs::Signature; #[Signature] struct QASignature { /// Answer the question concisely. #[input(desc="Question to be answered.")] pub question: String, #[output] pub answer: String, } ``` -------------------------------- ### Optimize Module with COPRO in Rust Source: https://github.com/krypticmouse/dsrs/blob/main/README.md Demonstrates how to use the COPRO (Collaborative Prompt Optimization) optimizer to tune a module's parameters. It shows the setup for the optimizer with parameters like breadth and depth, preparation of training data, and the compilation process to optimize the module in-place. ```rust #[derive(Optimizable)] pub struct MyModule { #[parameter] predictor: Predict, } // Create and configure the optimizer let optimizer = COPRO::builder() .breadth(10) // Number of candidates per iteration .depth(3) // Number of refinement iterations .build(); // Prepare training data let train_examples = load_training_data(); // Compile optimizes the module in-place let mut module = MyModule::new(); optimizer.compile(&mut module, train_examples).await?; ``` -------------------------------- ### Create Multi-Step Reasoning Pipeline in Rust Source: https://github.com/krypticmouse/dsrs/blob/main/README.md This example demonstrates building a multi-step reasoning pipeline using DSRS. It defines signatures for analysis and summarization tasks, creates a pipeline struct with `Predict` components, and implements the `forward` method to chain these components. The pipeline takes an input, performs analysis, then uses the analysis results to generate a summary, combining all outputs. ```rust use dsrs::prelude::*; #[Signature] struct AnalyzeSignature { #[input] pub text: String, #[output] pub sentiment: String, #[output] pub key_points: String, } #[Signature] struct SummarizeSignature { #[input] pub key_points: String, #[output] pub summary: String, } #[derive(Builder)] pub struct AnalysisPipeline { analyzer: Predict, summarizer: Predict, } impl Module for AnalysisPipeline { async fn forward(&self, inputs: Example) -> Result { // Step 1: Analyze the text let analysis = self.analyzer.forward(inputs).await?; // Step 2: Summarize key points let summary_input = example! { "key_points": "input" => analysis.get("key_points", None), }; let summary = self.summarizer.forward(summary_input).await?; // Combine results Ok(prediction! { "sentiment" => analysis.get("sentiment", None), "key_points" => analysis.get("key_points", None), "summary" => summary.get("summary", None), }) } } ``` -------------------------------- ### Rust: Batch Processing with Concurrency Control Source: https://context7.com/krypticmouse/dsrs/llms.txt Demonstrates efficient batch processing of multiple examples using controlled concurrency in Rust. This function allows for parallel execution of predictions with a specified maximum concurrency level and progress display. It utilizes the 'dspy-rs' crate for prediction and example handling. ```rust use dspy_rs::{Module, Predict, Example, example}; use anyhow::Result; #[Signature] struct Classifier { #[input] pub text: String, #[output] pub category: String, } #[tokio::main] async fn main() -> Result<()> { let predictor = Predict::new(Classifier::new()); let inputs = vec![ example! { "text": "input" => "Tech news article" }, example! { "text": "input" => "Sports update" }, example! { "text": "input" => "Political analysis" }, ]; // Process in parallel with max 10 concurrent requests let results = predictor.batch( inputs, 10, // max_concurrency true, // display_progress ).await?; for (i, pred) in results.iter().enumerate() { println!("Result {}: {}", i, pred.get("category", None)); } Ok(()) } ``` -------------------------------- ### Install DSRs using cargo add Source: https://github.com/krypticmouse/dsrs/blob/main/README.md This snippet demonstrates how to add the DSRs crate to your project using the `cargo add` command. Similar to the Cargo.toml method, you can opt for the recommended alias 'dsrs' or the full package name 'dspy-rs'. ```bash # Option 1: Add with alias (recommended) cargo add dsrs --package dspy-rs # Option 2: Add with full name cargo add dspy-rs ``` -------------------------------- ### Evaluate Modules with Custom Metrics in Rust Source: https://context7.com/krypticmouse/dsrs/llms.txt Define custom evaluation logic by implementing the Evaluator trait for module testing in Rust. This example shows how to create a QA module with a `QASignature` and implement an `Evaluator` for it. The `metric` function provides exact match and partial credit scoring for predicted answers against expected answers. The `evaluate` method is then used to score the module against a set of test examples. ```rust use dspy_rs::{Module, Evaluator, Example, Prediction, Predict, example}; use bon::Builder; use anyhow::Result; #[Signature] struct QASignature { #[input] pub question: String, #[output] pub answer: String, } #[derive(Builder)] pub struct QAModule { #[builder(default = Predict::new(QASignature::new()))] answerer: Predict, } impl Module for QAModule { async fn forward(&self, inputs: Example) -> Result { self.answerer.forward(inputs).await } } impl Evaluator for QAModule { const MAX_CONCURRENCY: usize = 16; const DISPLAY_PROGRESS: bool = true; async fn metric(&self, example: &Example, prediction: &Prediction) -> f32 { let expected = example.get("answer", None) .as_str() .unwrap_or("") .to_lowercase(); let predicted = prediction.get("answer", None) .as_str() .unwrap_or("") .to_lowercase(); // Exact match if expected == predicted { return 1.0; } // Partial credit for substring match if expected.contains(&predicted) || predicted.contains(&expected) { return 0.5; } 0.0 } } #[tokio::main] async fn main() -> Result<()> { let module = QAModule::builder().build(); let test_examples = vec![ example! { "question": "input" => "What is 2+2?", "answer": "output" => "4", }, example! { "question": "input" => "Capital of Japan?", "answer": "output" => "Tokyo", }, ]; let score = module.evaluate(test_examples).await; println!("Average score: {:.3}", score); Ok(()) } ``` -------------------------------- ### Load Training Data from HuggingFace and Local Files in Rust Source: https://context7.com/krypticmouse/dsrs/llms.txt This snippet shows how to load datasets from HuggingFace Hub and local JSON/CSV files using the DataLoader in DSPy RS. It handles automatic format detection for HuggingFace datasets and specifies column mappings for local files. The loaded examples can then be used for training or further processing. ```rust use dspy_rs::DataLoader; use anyhow::Result; fn main() -> Result<()> { // Load HotpotQA dataset let examples = DataLoader::load_hf( "hotpotqa/hotpot_qa", vec!["question".to_string()], vec!["answer".to_string()], "fullwiki", "validation", true, // verbose )?; println!("Loaded {} examples", examples.len()); // Use subset let train_subset = examples[..128].to_vec(); // Load from local files let json_examples = DataLoader::load_json( "data/train.jsonl", true, // lines format vec!["input".to_string], vec!["output".to_string], )?; let csv_examples = DataLoader::load_csv( "data/train.csv", ',', vec!["text".to_string], vec!["label".to_string], true, // has headers )?; // Save examples DataLoader::save_json("output.jsonl", train_subset, true)?; Ok(()) } ``` -------------------------------- ### Rust Module Implementation Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/building-blocks/module.mdx Demonstrates a minimal Rust module implementation for question answering. It defines a struct `Answerer` that implements the `Module` trait, utilizing a `Predict` field to perform the forward pass. This example showcases how to define inputs, outputs, and the core `forward` method for a module. ```rust use dsrs::{Example, Module, Predict, Prediction, Signature}; #[Signature] struct QA { #[input] question: String, #[output] answer: String } struct Answerer { predict: Predict } impl Default for Answerer { fn default() -> Self { Self { predict: Predict::new(QA::new()) } } } #[allow(async_fn_in_trait)] impl Module for Answerer { async fn forward(&self, inputs: Example) -> anyhow::Result { self.predict.forward(inputs).await } } ``` -------------------------------- ### Inspecting LM Call History in Rust Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/building-blocks/lm.mdx Provides an example of how to retrieve and iterate over the recent call history of a Language Model (LM) instance in Rust. It accesses configuration and output details for each historical entry. Assumes 'lm' is an initialized LM object. ```rust let history = lm.inspect_history(3); for entry in history { println!("Model: {} | Output: {}", entry.config.model, entry.output.content()); } ``` -------------------------------- ### Define Signatures for LM Tasks - Rust Source: https://context7.com/krypticmouse/dsrs/llms.txt Specifies the structure of language model tasks using the `Signature` derive macro with typed input and output fields. Supports basic, chain-of-thought (`cot`), and multi-field signatures with descriptions. Dependencies include `dspy_rs` and `tokio`. The example demonstrates defining and using a `SentimentAnalysis` signature. ```rust use dspy_rs::{Signature, Predict, Predictor, Example, example}; // Basic signature #[Signature] struct QASignature { #[input] pub question: String, #[output] pub answer: String, } // Signature with chain-of-thought reasoning #[Signature(cot)] struct ReasoningQA { /// Answer questions accurately using step-by-step reasoning. #[input] pub question: String, #[output] pub answer: String, } // Multi-field signature with descriptions #[Signature] struct SentimentAnalysis { /// Analyze text sentiment as Positive, Negative, or Neutral. #[input] pub text: String, #[output] pub sentiment: String, #[output(desc = "Explain your reasoning")] pub reasoning: String, } #[tokio::main] async fn main() -> anyhow::Result<()> { let predictor = Predict::new(SentimentAnalysis::new()); let input = example! { "text": "input" => "This movie was fantastic!", }; let result = predictor.forward(input).await?; println!("Sentiment: {}", result.get("sentiment", None)); println!("Reasoning: {}", result.get("reasoning", None)); Ok(()) } ``` -------------------------------- ### Implement and Use Custom Evaluation Metric in Rust Source: https://github.com/krypticmouse/dsrs/blob/main/README.md This snippet shows how to implement a custom evaluation metric for a module by defining an `Evaluator` trait. It includes an example of an exact match metric for string comparisons and demonstrates how to load test data, instantiate a module, and run the evaluation. ```rust impl Evaluator for MyModule { async fn metric(&self, example: &Example, prediction: &Prediction) -> f32 { // Define your custom metric logic let expected = example.get("answer", None); let predicted = prediction.get("answer", None); // Example: Exact match metric if expected.to_lowercase() == predicted.to_lowercase() { 1.0 } else { 0.0 } } } // Evaluate your module let test_examples = load_test_data(); let module = MyModule::new(); // Automatically runs predictions and computes average metric let score = module.evaluate(test_examples).await; println!("Average score: {}", score); ``` -------------------------------- ### GEPACandidate Struct Definition (Rust) Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/optimizers/gepa.mdx Defines the structure for a candidate solution within the GEPA evolutionary algorithm. It includes a unique ID, the instruction string, the associated module name, scores achieved on examples, the parent candidate's ID, and the generation number. This structure is fundamental for tracking and evolving potential solutions. ```rust pub struct GEPACandidate { pub id: usize, pub instruction: String, pub module_name: String, pub example_scores: Vec, pub parent_id: Option, pub generation: usize, } ``` -------------------------------- ### Rust: Configure MIPROv2 Optimizer Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/optimizers/miprov2.mdx Demonstrates how to build and configure the MIPROv2 optimizer using a builder pattern. Allows customization of parameters such as the number of candidates, minibatch size, generation temperature, and statistics tracking. ```rust let optimizer = MIPROv2::builder() .num_candidates(10) .minibatch_size(25) .temperature(1.0) .track_stats(true) .build(); ``` -------------------------------- ### Update Mintlify CLI Source: https://github.com/krypticmouse/dsrs/blob/main/docs/README.md Updates the Mintlify CLI to the latest version. This is a troubleshooting step to ensure you have the most recent features and bug fixes. ```bash mint update ``` -------------------------------- ### Configure COPRO Optimizer Settings (Rust) Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/optimizers/copro.mdx This snippet demonstrates how to configure the COPRO optimizer using its builder pattern. Key parameters include breadth (number of candidates per iteration), depth (number of refinement iterations), initial temperature for generation, and an option to track statistics. ```rust let copro = COPRO::builder() .breadth(10) // Number of candidates per iteration .depth(3) // Number of refinement iterations .init_temperature(1.4) // Temperature for generation .track_stats(false) // Track optimization statistics .build(); ``` -------------------------------- ### Optimize Prompts with COPRO in Rust Source: https://context7.com/krypticmouse/dsrs/llms.txt This Rust code demonstrates prompt optimization using the COPRO algorithm from DSPy RS. It defines a QA signature and module, sets up an evaluator metric, and then uses COPRO to iteratively refine the prompt based on a training dataset. The initial and optimized prompt instructions are printed. ```rust use dspy_rs::{ COPRO, Module, Evaluator, Optimizable, Optimizer, Predict, Example, Prediction, DataLoader, example }; use bon::Builder; use dsrs_macros::{Signature, Optimizable}; use anyhow::Result; #[Signature(cot)] struct QASignature { /// Answer questions concisely and accurately. #[input] pub question: String, #[output(desc = "Answer in less than 5 words")] pub answer: String, } #[derive(Builder, Optimizable)] pub struct QAModule { #[parameter] // Mark for optimization #[builder(default = Predict::new(QASignature::new()))] answerer: Predict, } impl Module for QAModule { async fn forward(&self, inputs: Example) -> Result { self.answerer.forward(inputs).await } } impl Evaluator for QAModule { async fn metric(&self, example: &Example, prediction: &Prediction) -> f32 { let expected = example.get("answer", None).to_string().to_lowercase(); let predicted = prediction.get("answer", None).to_string().to_lowercase(); if expected == predicted { 1.0 } else { 0.0 } } } #[tokio::main] async fn main() -> Result<()> { let trainset = DataLoader::load_hf( "hotpotqa/hotpot_qa", vec!["question".to_string], vec!["answer".to_string], "fullwiki", "validation", true, )?[..10].to_vec(); let mut module = QAModule::builder().build(); println!("Initial: {:?}", module.answerer.get_signature().instruction()); // Configure optimizer let optimizer = COPRO::builder() .breadth(10) // Generate 10 candidates per iteration .depth(3) // 3 refinement iterations .init_temperature(1.4) .track_stats(true) .build(); // Optimize optimizer.compile(&mut module, trainset).await?; println!("Optimized: {:?}", module.answerer.get_signature().instruction()); Ok(()) } ``` -------------------------------- ### Bash: Run MIPROv2 Tests Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/optimizers/miprov2.mdx Command to execute the test suite for MIPROv2. This includes tests for trace generation, candidate selection, configuration handling, and various edge cases, ensuring the robustness of the implementation. ```bash cargo test test_miprov2 ``` -------------------------------- ### Constructing an LM with Configuration in Rust Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/building-blocks/lm.mdx Demonstrates how to build a Language Model (LM) client using the builder pattern in Rust. It specifies API key, base URL, and model-level configuration such as model name, temperature, and maximum tokens. Dependencies include the 'dsrs' crate. ```rust use dsrs::{LM, LMConfig}; let lm = LM::builder() .api_key(std::env::var("OPENAI_API_KEY")?.into()) .config( LMConfig::builder() .model("gpt-4o-mini".to_string()) .temperature(0.7) .max_tokens(512) .build() ) .build(); ``` -------------------------------- ### Configure Language Model Connection - Rust Source: https://context7.com/krypticmouse/dsrs/llms.txt Sets up a language model connection using API keys, model selection, and generation parameters. It supports configuring different providers like OpenAI and OpenRouter. Dependencies include `dspy_rs`, `secrecy`, and `tokio`. Outputs a configured LM instance and sets it as the global configuration. ```rust use dspy_rs::{LM, LMConfig, ChatAdapter, configure}; use secrecy::SecretString; #[tokio::main] async fn main() -> anyhow::Result<()> { // Configure OpenAI let lm = LM::builder() .api_key(SecretString::from(std::env::var("OPENAI_API_KEY")?)) .config( LMConfig::builder() .model("gpt-4o-mini".to_string()) .temperature(0.7) .max_tokens(1000) .build() ) .build(); // Set global configuration configure(lm, ChatAdapter); // Alternative: OpenRouter with provider prefix let openrouter_lm = LM::builder() .api_key(std::env::var("OPENROUTER_API_KEY")?.into()) .config(LMConfig { model: "openrouter/openai/gpt-4o-mini".to_string(), temperature: 0.5, top_p: 0.9, ..LMConfig::default() }) .build(); configure(openrouter_lm, ChatAdapter); Ok(()) } ``` -------------------------------- ### Rust: Configure LM with OpenAI API Key and Model Details Source: https://github.com/krypticmouse/dsrs/blob/main/README.md This Rust snippet shows how to configure a language model (LM) using the `LM::builder`. It demonstrates setting the API key, model name (e.g., 'gpt-4'), temperature, and maximum tokens, which are essential for interacting with the LM. ```rust // Configure with OpenAI let lm = LM::builder() .api_key(secret_key) .model("gpt-4") .temperature(0.7) .max_tokens(1000) .build(); ``` -------------------------------- ### Rust: Configure and Run GEPA Optimizer Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/optimizers/gepa.mdx This Rust snippet shows how to configure and execute the GEPA optimizer using the `dspy-rs` library. It sets various parameters like the number of iterations, minibatch size, and temperature, and then compiles a module with feedback for training. The output includes the best score achieved and the corresponding optimized instruction. ```rust let gepa = GEPA::builder() .num_iterations(20) .minibatch_size(25) .num_trials(10) .temperature(0.9) .track_stats(true) .maybe_max_rollouts(Some(500)) // Budget control .build(); let result = gepa.compile_with_feedback(&mut module, trainset).await?; println!("Best score: {:.3}", result.best_candidate.average_score()); println!("Best instruction: {}", result.best_candidate.instruction); ``` -------------------------------- ### Configure GEPA Budgets (Rust) Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/optimizers/gepa.mdx Demonstrates how to configure the GEPA optimizer's budgets for development/testing and production environments by adjusting the number of iterations and maximum rollouts. ```rust // For development/testing GEPA::builder() .num_iterations(5) .maybe_max_rollouts(Some(100)) .build() // For production optimization GEPA::builder() .num_iterations(20) .maybe_max_rollouts(Some(1000)) .build() ``` -------------------------------- ### Configure GEPA for Inference-Time Search (Rust) Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/optimizers/gepa.mdx Illustrates setting up GEPA for inference-time search by enabling statistics tracking, best output tracking, and providing a validation set. ```rust let gepa = GEPA::builder() .track_stats(true) .track_best_outputs(true) .maybe_valset(Some(my_tasks.clone())) .build(); let result = gepa.compile_with_feedback(&mut module, my_tasks).await?; // Access per-task best scores and outputs let best_scores = result.highest_score_achieved_per_val_task; let best_outputs = result.best_outputs_valset; ``` -------------------------------- ### GEPA Configuration Builder (Rust) Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/optimizers/gepa.mdx Configures the GEPA optimizer using a builder pattern. This allows fine-tuning parameters such as the number of iterations, minibatch size, LLM temperature, and budget constraints like maximum rollouts or LM calls. Optional parameters like a validation set or a separate prompt model can also be provided. ```rust GEPA::builder() .num_iterations(20) // Number of evolutionary iterations .minibatch_size(25) // Examples per rollout .num_trials(10) // Trials per candidate evaluation .temperature(0.9) // LLM temperature for mutations .track_stats(true) // Track detailed statistics .track_best_outputs(false) // Store best outputs per example .maybe_max_rollouts(Some(500)) // Budget: max rollouts .maybe_max_lm_calls(Some(1000)) // Budget: max LM calls .maybe_prompt_model(Some(lm)) // Separate LM for meta-prompting .maybe_valset(Some(examples)) // Validation set .build() ``` -------------------------------- ### Async LM Execution with Tokio in Rust Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/building-blocks/lm.mdx Shows how to set up an asynchronous Rust main function using Tokio for executing LM operations. This is the preferred method for handling async LM calls. Dependencies include 'tokio' and 'anyhow'. ```rust #[tokio::main] async fn main() -> anyhow::Result<()> { // build + use LM here Ok(()) } ``` -------------------------------- ### Rust: Feedback-Based Optimization with GEPA Source: https://context7.com/krypticmouse/dsrs/llms.txt Implements feedback-based optimization using the GEPA (Gradient-Enhanced Prompting Algorithm) in Rust. This allows for prompt evolution based on rich textual feedback, improving model performance. It requires the 'dspy-rs' crate and utilizes custom signatures and optimizable structs. ```rust use dspy_rs::{ GEPA, Module, Evaluator, FeedbackEvaluator, FeedbackMetric, Optimizable, Predict, Example, Prediction, example }; use bon::Builder; use dsrs_macros::{Signature, Optimizable}; use anyhow::Result; #[Signature] struct SentimentSignature { /// Classify sentiment as Positive, Negative, or Neutral. #[input] pub text: String, #[output] pub sentiment: String, #[output] pub reasoning: String, } #[derive(Builder, Optimizable)] struct SentimentAnalyzer { #[parameter] predictor: Predict, } impl Module for SentimentAnalyzer { async fn forward(&self, inputs: Example) -> Result { self.predictor.forward(inputs).await } } impl Evaluator for SentimentAnalyzer { async fn metric(&self, example: &Example, prediction: &Prediction) -> f32 { self.feedback_metric(example, prediction).await.score } } impl FeedbackEvaluator for SentimentAnalyzer { async fn feedback_metric(&self, example: &Example, prediction: &Prediction) -> FeedbackMetric { let predicted = prediction.get("sentiment", None) .as_str() .unwrap_or("") .to_lowercase(); let expected = example.get("expected_sentiment", None) .as_str() .unwrap_or("") .to_lowercase(); let correct = predicted == expected; let score = if correct { 1.0 } else { 0.0 }; let feedback = if correct { format!("✓ Correct: {}\nGood sentiment classification.", expected) } else { format!("✗ Wrong: expected '{}', got '{}'\nReview the text more carefully.", expected, predicted) }; FeedbackMetric::new(score, feedback) } } #[tokio::main] async fn main() -> Result<()> { let trainset = vec![ example! { "text": "input" => "Absolutely fantastic!", "expected_sentiment": "input" => "positive" }, example! { "text": "input" => "Terrible service.", "expected_sentiment": "input" => "negative" }, example! { "text": "input" => "It's okay.", "expected_sentiment": "input" => "neutral" }, ]; let mut module = SentimentAnalyzer::builder() .predictor(Predict::new(SentimentSignature::new())) .build(); let gepa = GEPA::builder() .num_iterations(5) .minibatch_size(3) .num_trials(3) .temperature(0.9) .track_stats(true) .build(); let result = gepa.compile_with_feedback(&mut module, trainset).await?; println!("Best score: {:.3}", result.best_candidate.average_score()); println!("Total rollouts: {}", result.total_rollouts); println!("Best instruction:\n{}", result.best_candidate.instruction); Ok(()) } ``` -------------------------------- ### Optimize Module with MIPROv2 in Rust Source: https://github.com/krypticmouse/dsrs/blob/main/README.md Illustrates the use of MIPROv2 (Multi-prompt Instruction Proposal Optimizer v2) for optimizing modules. This advanced optimizer uses LLMs and involves a three-stage process: generating execution traces, LLM-generated prompts, and evaluation. Configuration options include the number of candidates, trials, minibatch size, and temperature. ```rust // MIPROv2 uses a 3-stage process: // 1. Generate execution traces // 2. LLM generates candidate prompts with best practices // 3. Evaluate and select the best prompt let optimizer = MIPROv2::builder() .num_candidates(10) // Number of candidate prompts to generate .num_trials(20) // Number of evaluation trials .minibatch_size(25) // Examples per evaluation .temperature(1.0) // Temperature for prompt generation .build(); optimizer.compile(&mut module, train_examples).await?; ``` -------------------------------- ### Build Custom Modules with Forward Method in Rust Source: https://context7.com/krypticmouse/dsrs/llms.txt Implement the Module trait to compose multi-step pipelines for custom logic. This snippet demonstrates creating an analysis pipeline that first analyzes text for sentiment and key points, then summarizes the key points, combining the results into a final prediction. It shows how to define input/output signatures and wire together different modules using a builder pattern. ```rust use dspy_rs::{Module, Predict, Example, Prediction, example, prediction}; use bon::Builder; use anyhow::Result; #[Signature] struct Analyzer { #[input] pub text: String, #[output] pub sentiment: String, #[output] pub key_points: String, } #[Signature] struct Summarizer { #[input] pub key_points: String, #[output] pub summary: String, } #[derive(Builder)] pub struct AnalysisPipeline { #[builder(default = Predict::new(Analyzer::new()))] analyzer: Predict, #[builder(default = Predict::new(Summarizer::new()))] summarizer: Predict, } impl Module for AnalysisPipeline { async fn forward(&self, inputs: Example) -> Result { // Step 1: Analyze let analysis = self.analyzer.forward(inputs).await?; // Step 2: Extract key points and summarize let summary_input = example! { "key_points": "input" => analysis.get("key_points", None), }; let summary = self.summarizer.forward(summary_input).await?; // Combine results Ok(prediction! { "sentiment" => analysis.get("sentiment", None), "key_points" => analysis.get("key_points", None), "summary" => summary.get("summary", None), }) } } #[tokio::main] async fn main() -> Result<()> { let pipeline = AnalysisPipeline::builder().build(); let input = example! { "text": "input" => "The product works well but shipping was slow.", }; let result = pipeline.forward(input).await?; println!("Sentiment: {}", result.get("sentiment", None)); println!("Summary: {}", result.get("summary", None)); Ok(()) } ``` -------------------------------- ### Understanding GEPA Compilation Results (Rust) Source: https://github.com/krypticmouse/dsrs/blob/main/docs/docs/optimizers/gepa.mdx Compiles a module with feedback and prints detailed results from the GEPA optimization process. This includes the best candidate instruction, its average score, the full generation, resource usage statistics (rollouts, LM calls), and the evolution history of scores across generations. ```rust let result = gepa.compile_with_feedback(&mut module, trainset).await?; // Best candidate found println!("Best instruction: {}", result.best_candidate.instruction); println!("Average score: {:.3}", result.best_candidate.average_score()); println!("Generation: {}", result.best_candidate.generation); // Resource usage println!("Total rollouts: {}", result.total_rollouts); println!("Total LM calls: {}", result.total_lm_calls); // Evolution over time for (generation, score) in &result.evolution_history { println!("Gen {}: {:.3}", generation, score); } ```