| Crates.io | llm-kit-provider |
| lib.rs | llm-kit-provider |
| version | 0.1.2 |
| created_at | 2026-01-18 18:32:53.169423+00 |
| updated_at | 2026-01-24 03:59:36.229532+00 |
| description | Provider interface and traits for the LLM Kit - defines the contract for implementing AI model providers |
| homepage | |
| repository | https://github.com/saribmah/llm-kit |
| max_upload_size | |
| id | 2052811 |
| size | 400,320 |
A unified Rust SDK for building AI-powered applications with multiple model providers. Build with type safety, async/await, and ergonomic APIs designed for the Rust ecosystem.
Status: All 12 providers standardized with comprehensive documentation and examples. Ready for production use.
Add the core library and a provider to your Cargo.toml:
[dependencies]
llm-kit-core = "0.1"
llm-kit-openai = "0.1" # Or any other provider
tokio = { version = "1", features = ["full"] }
use llm_kit_core::{GenerateText, prompt::Prompt};
use llm_kit_openai::OpenAIClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create provider
let provider = OpenAIClient::new()
.api_key(std::env::var("OPENAI_API_KEY")?)
.build();
// Get model
let model = provider.chat_model("gpt-4o-mini");
// Generate text
let result = GenerateText::new(model, Prompt::text("What is Rust?"))
.temperature(0.7)
.max_output_tokens(100)
.execute()
.await?;
println!("Response: {}", result.text);
Ok(())
}
All providers follow the same standardized builder pattern and API:
| Provider | Chat | Embed | Image | Speech | Transcription | Reranking | Status |
|---|---|---|---|---|---|---|---|
| OpenAI | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ Standardized |
| Anthropic | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ Standardized |
| Azure | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ Standardized |
| Groq | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ Standardized |
| DeepSeek | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ Standardized |
| xAI | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ Standardized |
| TogetherAI | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ Standardized |
| Baseten | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ Standardized |
| Hugging Face | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ Standardized |
| ElevenLabs | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ Standardized |
| AssemblyAI | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ Standardized |
| OpenAI-Compatible | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ Standardized |
Legend:
All providers use the same builder pattern:
// OpenAI
use llm_kit_openai::OpenAIClient;
let provider = OpenAIClient::new()
.api_key("your-key")
.build();
// Anthropic (Claude)
use llm_kit_anthropic::AnthropicClient;
let provider = AnthropicClient::new()
.api_key("your-key")
.build();
// Azure OpenAI
use llm_kit_azure::AzureClient;
let provider = AzureClient::new()
.api_key("your-key")
.resource_name("your-resource")
.deployment_id("your-deployment")
.build();
// Groq (ultra-fast inference)
use llm_kit_groq::GroqClient;
let provider = GroqClient::new()
.api_key("your-key")
.build();
// DeepSeek (reasoning models)
use llm_kit_deepseek::DeepSeekClient;
let provider = DeepSeekClient::new()
.api_key("your-key")
.build();
// And more...
Switch providers by changing just 2-3 lines of code. The rest of your application remains the same.
Generate text with comprehensive configuration options:
use llm_kit_core::{GenerateText, prompt::Prompt};
let result = GenerateText::new(model, Prompt::text("Write a poem"))
.temperature(0.8)
.max_output_tokens(500)
.top_p(0.9)
.frequency_penalty(0.5)
.presence_penalty(0.5)
.seed(42)
.execute()
.await?;
println!("Response: {}", result.text);
Stream responses in real-time:
use llm_kit_core::{StreamText, prompt::Prompt};
use futures::StreamExt;
let result = StreamText::new(model, Prompt::text("Tell me a story"))
.temperature(0.8)
.on_chunk(|chunk| {
println!("Chunk: {:?}", chunk);
})
.execute()
.await?;
let mut stream = result.text_stream();
while let Some(text) = stream.next().await {
print!("{}", text);
}
Define tools with dynamic or type-safe APIs:
Dynamic Tools:
use llm_kit_core::{GenerateText, ToolSet};
use llm_kit_provider_utils::tool::{Tool, ToolExecutionOutput};
use serde_json::json;
use std::sync::Arc;
let tool = Tool::function(json!({
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name"}
},
"required": ["city"]
}))
.with_description("Get weather for a city")
.with_execute(Arc::new(|input, _opts| {
ToolExecutionOutput::Single(Box::pin(async move {
Ok(json!({"temperature": 72, "conditions": "Sunny"}))
}))
}));
let mut tools = ToolSet::new();
tools.insert("get_weather".to_string(), tool);
let result = GenerateText::new(model, Prompt::text("What's the weather in Paris?"))
.tools(tools)
.execute()
.await?;
Type-Safe Tools:
use llm_kit_core::tool::TypeSafeTool;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Deserialize, JsonSchema)]
struct WeatherInput {
city: String,
}
#[derive(Serialize)]
struct WeatherOutput {
temperature: i32,
conditions: String,
}
impl TypeSafeTool for WeatherInput {
type Output = WeatherOutput;
fn description() -> String {
"Get weather for a city".to_string()
}
async fn execute(self) -> Result<Self::Output, String> {
Ok(WeatherOutput {
temperature: 72,
conditions: format!("Sunny in {}", self.city),
})
}
}
Create reusable AI agents with persistent configuration:
use llm_kit_core::{Agent, AgentSettings, AgentCallParameters};
use llm_kit_core::agent::AgentInterface;
// Configure agent once
let settings = AgentSettings::new(model)
.with_tools(tools)
.with_temperature(0.7)
.with_max_output_tokens(500);
let agent = Agent::new(settings);
// Use multiple times
let result1 = agent.generate(AgentCallParameters::from_text("Hello"))?
.execute()
.await?;
let result2 = agent.generate(AgentCallParameters::from_text("Follow-up"))?
.temperature(0.9) // Override settings per call
.execute()
.await?;
// Streaming also supported
let stream_result = agent.stream(AgentCallParameters::from_text("Tell a story"))?
.execute()
.await?;
Persist conversation history with automatic loading:
use llm_kit_storage_filesystem::FilesystemStorage;
use llm_kit_storage::Storage;
use std::sync::Arc;
let storage: Arc<dyn Storage> = Arc::new(FilesystemStorage::new("./storage")?);
storage.initialize().await?;
let session_id = storage.generate_session_id();
// First message - no history
GenerateText::new(model.clone(), Prompt::text("What is Rust?"))
.with_storage(storage.clone())
.with_session_id(session_id.clone())
.without_history() // Important!
.execute()
.await?;
// Follow-up - history loaded automatically
GenerateText::new(model, Prompt::text("Why should I learn it?"))
.with_storage(storage)
.with_session_id(session_id)
.execute()
.await?; // Previous messages included
Enable storage feature:
llm-kit-core = { version = "0.1", features = ["storage"] }
llm-kit-storage = "0.1"
llm-kit-storage-filesystem = "0.1"
Generate embeddings for single or multiple texts:
use llm_kit_core::{Embed, EmbedMany};
// Single embedding
let result = Embed::new(embedding_model.clone(), "Hello world".to_string())
.execute()
.await?;
// Batch embeddings
let texts = vec!["text1".to_string(), "text2".to_string()];
let results = EmbedMany::new(embedding_model, texts)
.max_parallel_calls(5)
.execute()
.await?;
Generate images from text prompts:
use llm_kit_core::GenerateImage;
let result = GenerateImage::new(image_model, "A serene landscape".to_string())
.n(2)
.size("1024x1024")
.seed(42)
.execute()
.await?;
Convert between text and speech:
use llm_kit_core::{GenerateSpeech, Transcribe, AudioInput};
// Text to speech
let result = GenerateSpeech::new(speech_model, "Hello world".to_string())
.voice("alloy")
.output_format("mp3")
.speed(1.0)
.execute()
.await?;
// Speech to text
let result = Transcribe::new(transcription_model, AudioInput::Data(audio_data))
.execute()
.await?;
Rerank documents based on relevance:
use llm_kit_core::Rerank;
let documents = vec!["doc1".to_string(), "doc2".to_string()];
let result = Rerank::new(reranking_model, documents, "search query".to_string())
.top_n(5)
.execute()
.await?;
This is a Cargo workspace organized into layers:
Language Model Providers:
Multi-Feature Providers:
Specialized Providers:
The repository includes 29 comprehensive examples demonstrating all features:
cp .env.example .env
.env:OPENAI_API_KEY=your-api-key-here
# Set API key
export OPENAI_API_KEY="your-api-key"
# Basic Examples
cargo run --example basic_chat # Simple text generation
cargo run --example basic_stream # Streaming responses
cargo run --example basic_embedding # Text embeddings
cargo run --example basic_image # Image generation
cargo run --example conversation # Multi-turn conversations
# Agent Examples
cargo run --example agent_generate # Reusable agents (non-streaming)
cargo run --example agent_stream # Reusable agents (streaming)
cargo run --example agent_storage_conversation --features storage # Agents with storage
# Tool Calling Examples
cargo run --example tool_calling # Basic tool calling
cargo run --example type_safe_tools # Type-safe tools
cargo run --example multi_step_tools # Multi-step execution
cargo run --example stream_tool_calling # Streaming with tools
# Streaming Examples
cargo run --example stream_transforms # Stream filtering and batching
cargo run --example partial_output # Partial JSON parsing
# Storage Examples (require --features storage)
cargo run --example storage_basic --features storage
cargo run --example storage_filesystem_basic --features storage
cargo run --example storage_filesystem_conversation --features storage
cargo run --example storage_conversation_full --features storage
# Provider-Specific Examples
cargo run --example azure_basic # Azure OpenAI
cargo run --example groq_basic_chat # Groq
cargo run --example groq_text_to_speech # Groq TTS
cargo run --example groq_transcription # Groq transcription
cargo run --example xai_basic_chat # xAI
See the examples/ directory for all available examples.
The SDK follows a three-layer architecture:
llm-kit-core)Provides builder pattern APIs and core functionality:
GenerateText, StreamText, Embed, EmbedMany, GenerateImage, GenerateSpeech, Transcribe, Rerankllm-kit-provider)Defines traits for implementing providers:
Provider trait: Top-level provider interfaceLanguageModel, EmbeddingModel, ImageModel, SpeechModel, TranscriptionModel, RerankingModelCallOptions, Content, FinishReason, Usage, ToolCallConcrete implementations for each provider:
Each provider has comprehensive README documentation:
This project uses just as a command runner:
cargo install just
Install pre-commit hooks for automatic code quality checks:
just install-hooks
This automatically runs:
rustfmt - Code formatting (auto-fixes)clippy - Linting (blocks commit if issues found)cargo check - Compilation verificationjust # List all available commands
just install-hooks # Install git pre-commit hooks
just fmt # Format code
just clippy # Run clippy linter
just check # Quick compile check
just test # Run all tests
just build # Build all crates
just doc # Build documentation
just pre-commit # Run all pre-commit checks
just ci # Run all CI checks locally
See DEVELOPMENT.md for detailed development guidelines.
# Run all tests
cargo test
# Run tests for a specific crate
cargo test -p llm-kit-core
cargo test -p llm-kit-openai
cargo test -p llm-kit-anthropic
# Run with output
cargo test -- --nocapture
# Run storage tests
cargo test -p llm-kit-core --features storage
# Build all crates
cargo build
# Build in release mode
cargo build --release
# Check without building (faster)
cargo check
# Check examples
cargo check --examples
Core Functionality:
GenerateText, StreamText, Embed, EmbedMany, GenerateImage, GenerateSpeech, Transcribe, RerankProviders:
Testing & Documentation:
Contributions are welcome! Please see the Contributing Guide for:
This project is licensed under the MIT License. See the LICENSE file for details.
Inspired by Vercel's LLM Kit