# promptkit-rs `promptkit-rs` is a Rust library for structured prompting, designed to create expressive, reusable prompts and structured output, ideal for AI model interactions. Features - 🔧 Custom Prompts – Easily define prompts with clear, structured syntax. - 🎨 rsx_2! Macro – Write JSX-like prompt templates for easy nesting and readability. - 📊 Structured Output – Define custom output types for predictable responses. - 🔌 Composable Components – Use Renderable to build prompts from reusable parts. ## Quick Start ```rust use promptkit_rs::{ executors::{Executor, OpenAI}, Prompt, Renderable, rsx_2 }; #[derive(Clone)] struct AuthorReviewPrompt { authors: Vec, } #[derive(Clone, Serialize, Deserialize, JsonSchema)] struct AuthorReviewResult { #[schemars(description = "...")] best_author_name: String, #[schemars(description = "Rationale for description in a short sentence.")] reason: String, } impl Prompt for AuthorReviewPrompt { type Output = AuthorReviewResult; fn render(&self) -> String { rsx_2! { "You're a turbo book worm. You live in a hole with nothing but books. " "I'm going to give you a list of authors and their books. " "Your job is to determine who is best." {self.authors} } } } fn main() { let input_data = AuthorReviewPrompt { authors: vec!["J.K. Rowling".to_string(), "George R.R. Martin".to_string()]}; let author_review: AuthorReviewResult = OpenAI::execute(input_data).await.unwrap(); let expected = AuthorReviewResult { best_author_name: "George R.R. Martin", reason: "George R.R. Martin wins for his intricate world-building and morally complex characters, creating a narrative depth that keeps readers hooked." }; assert_eq!(author_review, expected); } ``` Anything that implements `promptkit_rs::Renderable` can be automatically rendered from brackets. By default all the primitives, `String`, `Vec`, `&[impl Renderable]` are all also `Renderable`. ## Building Modular Components Use Renderable to create structured sub-components, then include them in prompts: ```rust use promptkit_rs::{Renderable, rsx_2}; struct Author { name: String, age: u64, } impl Renderable for Author { fn render(&self) -> String { rsx_2! { "" {self.name} "" "" {self.age} "" } } } ``` Combine Author components into a prompt: ```rust struct AuthorReviewPrompt { authors: Vec, } impl Prompt for AuthorReviewPrompt { type Output = AuthorReviewResult; fn render(&self) -> String { rsx_2! { "You're a turbo book worm. You live in a hole with nothing but books. " "I'm going to give you a list of authors and their books. " "Your job is to determine who is best." {self.authors} } } } ``` ## Execution With the prompt ready, execute it using OpenAI or any custom executor: ```rust #[tokio::main] async fn main() { let authors = vec![ Author { name: "J.K. Rowling".to_string(), age: 55 }, Author { name: "George R.R. Martin".to_string(), age: 72 }, ]; let input_data = AuthorReviewPrompt { authors }; let author_review: AuthorReviewResult = OpenAI::execute(input_data).await.unwrap(); println!("{:?}", author_review); } ```