4 releases
new 0.1.3 | Oct 31, 2024 |
---|---|
0.1.2 | Oct 31, 2024 |
0.1.1 | Oct 29, 2024 |
0.1.0 | Oct 29, 2024 |
#218 in Machine learning
215 downloads per month
20KB
288 lines
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
use promptkit_rs::{
executors::{Executor, OpenAI},
Prompt, Renderable, rsx_2
};
#[derive(Clone)]
struct AuthorReviewPrompt {
authors: Vec<String>,
}
#[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>
, &[impl Renderable]
are all also Renderable
.
Building Modular Components
Use Renderable to create structured sub-components, then include them in prompts:
use promptkit_rs::{Renderable, rsx_2};
struct Author {
name: String,
age: u64,
}
impl Renderable for Author {
fn render(&self) -> String {
rsx_2! {
"<name>" {self.name} "</name>"
"<age>" {self.age} "</age>"
}
}
}
Combine Author components into a prompt:
struct AuthorReviewPrompt {
authors: Vec<Author>,
}
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:
#[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);
}
Dependencies
~30–47MB
~681K SLoC