| Crates.io | siumai-protocol-anthropic |
| lib.rs | siumai-protocol-anthropic |
| version | 0.11.0-beta.5 |
| created_at | 2026-01-14 14:37:47.355392+00 |
| updated_at | 2026-01-14 14:37:47.355392+00 |
| description | Anthropic Messages protocol standard mapping for siumai |
| homepage | https://github.com/YumchaLabs/siumai |
| repository | https://github.com/YumchaLabs/siumai |
| max_upload_size | |
| id | 2042934 |
| size | 443,322 |
Siumai (烧卖) is a type-safe Rust library that provides a single, consistent API over multiple LLM providers. It focuses on clear abstractions, predictable behavior, and practical extensibility.
This README keeps things straightforward: what you can do, how to customize, and short examples.
siumai-extras)[dependencies]
siumai = "0.11.0-beta.5"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
Upgrading from 0.11.0-beta.4 (or earlier)?
docs/migration/migration-0.11.0-beta.5.mdFeature flags (enable only what you need):
# One provider
siumai = { version = "0.11.0-beta.5", features = ["openai"] }
# Multiple providers
siumai = { version = "0.11.0-beta.5", features = ["openai", "anthropic", "google"] }
# All
siumai = { version = "0.11.0-beta.5", features = ["all-providers"] }
Note: siumai enables openai by default. Disable defaults via default-features = false.
Optional package for advanced utilities:
[dependencies]
siumai = "0.11.0-beta.5"
siumai-extras = { version = "0.11.0-beta.5", features = ["schema", "telemetry", "opentelemetry", "server", "mcp"] }
Use the registry to resolve models via provider:model and get a handle with a uniform API.
use siumai::prelude::unified::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let reg = registry::global();
let model = reg.language_model("openai:gpt-4o-mini")?;
let resp = model.chat(vec![user!("Hello")], None).await?;
println!("{}", resp.content_text().unwrap_or_default());
Ok(())
}
Supported examples of provider:model:
openai:gpt-4o, openai:gpt-4o-minianthropic:claude-3-5-sonnet-20240620anthropic-vertex:claude-3-5-sonnet-20240620gemini:gemini-2.0-flash-expgroq:llama-3.1-70b-versatilexai:grok-betaollama:llama3.2minimaxi:minimax-text-01OpenAI‑compatible vendors follow the same pattern (API keys read as {PROVIDER_ID}_API_KEY when possible). See docs for details.
Provider‑specific client:
use siumai::prelude::unified::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Provider::openai()
.api_key(std::env::var("OPENAI_API_KEY")?)
.model("gpt-4o")
.build()
.await?;
let resp = client.chat(vec![user!("Hi")]).await?;
println!("{}", resp.content_text().unwrap_or_default());
Ok(())
}
Unified interface (portable across providers):
use siumai::prelude::unified::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Siumai::builder()
.anthropic()
.api_key(std::env::var("ANTHROPIC_API_KEY")?)
.model("claude-3-5-sonnet")
.build()
.await?;
let resp = client.chat(vec![user!("What's Rust?")]).await?;
println!("{}", resp.content_text().unwrap_or_default());
Ok(())
}
OpenAI‑compatible (custom base URL):
use siumai::prelude::unified::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// For OpenAI-compatible local endpoints, you can use any non-empty API key.
let vllm = Siumai::builder().openai()
.api_key("dummy")
.base_url("http://localhost:8000/v1")
.model("meta-llama/Llama-3.1-8B-Instruct")
.build()
.await?;
let resp = vllm.chat(vec![user!("Hello from vLLM")]).await?;
println!("{}", resp.content_text().unwrap_or_default());
Ok(())
}
use futures::StreamExt;
use siumai::prelude::unified::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Siumai::builder().openai()
.api_key(std::env::var("OPENAI_API_KEY")?)
.model("gpt-4o-mini")
.build()
.await?;
let mut stream = client.chat_stream(vec![user!("Stream a long answer")], None).await?;
while let Some(ev) = stream.next().await {
if let Ok(ChatStreamEvent::ContentDelta { delta, .. }) = ev { print!("{}", delta); }
}
Ok(())
}
Use siumai-extras to parse model text into typed JSON with optional schema validation and repair:
use serde::Deserialize;
use siumai::prelude::unified::*;
use siumai_extras::highlevel::object::generate_object;
#[derive(Deserialize, Debug)]
struct Post { title: String }
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Siumai::builder().openai().model("gpt-4o-mini").build().await?;
let (post, _resp) = generate_object::<Post>(
&client,
vec![user!("Return JSON: {\"title\":\"hi\"}")],
None,
Default::default(),
).await?;
println!("{}", post.title);
Ok(())
}
Under the hood this uses siumai_extras::structured_output::OutputDecodeConfig to:
For providers that expose native structured outputs, configure them via provider options. You still can combine them with the decoding helpers above if you want:
use siumai::prelude::unified::*;
use siumai::provider_ext::openai::options::{OpenAiChatRequestExt, OpenAiOptions, ResponsesApiConfig};
use serde_json::json;
let schema = json!({"type":"object","properties":{"title":{"type":"string"}},"required":["title"]});
let req = ChatRequestBuilder::new()
.message(user!("Return an object with title"))
.build()
.with_openai_options(OpenAiOptions::new().with_responses_api(
ResponsesApiConfig::new().with_response_format(json!({
"type": "json_object",
"json_schema": { "schema": schema, "strict": true }
}))
));
let resp = client.chat_request(req).await?;
// Optionally: further validate/repair/deserialize using `siumai-extras` helpers.
use siumai::prelude::unified::*;
use siumai::retry_api::{retry_with, RetryOptions};
let text = client
.ask_with_retry("Hello".to_string(), RetryOptions::backoff())
.await?;
You have three practical ways to control HTTP behavior, from simple to advanced.
use siumai::prelude::unified::*;
// Unified builder (Siumai::builder) with SSE stability control
let client = Siumai::builder()
.openai()
.api_key(std::env::var("OPENAI_API_KEY")?)
.model("gpt-4o-mini")
.http_timeout(std::time::Duration::from_secs(30))
.http_connect_timeout(std::time::Duration::from_secs(10))
.http_user_agent("my-app/1.0")
.http_header("X-User-Project", "acme")
.http_stream_disable_compression(true) // keep SSE stable; default can be controlled by env
.build()
.await?;
use siumai::experimental::execution::http::client::build_http_client_from_config;
use siumai::prelude::unified::*;
// Construct a reusable HTTP config
let http_cfg = HttpConfig::builder()
.timeout(Some(std::time::Duration::from_secs(30)))
.connect_timeout(Some(std::time::Duration::from_secs(10)))
.user_agent(Some("my-app/1.0"))
.proxy(Some("http://proxy.example.com:8080"))
.header("X-User-Project", "acme")
.stream_disable_compression(true) // explicit SSE stability
.build();
// Build reqwest client using the shared helper
let http = build_http_client_from_config(&http_cfg)?;
// Inject it into a builder (takes precedence over other HTTP settings)
let client = Siumai::builder()
.with_http_client(http)
.openai()
.api_key(std::env::var("OPENAI_API_KEY")?)
.model("gpt-4o-mini")
.build()
.await?;
use siumai::prelude::unified::*;
let http = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(30))
// .danger_accept_invalid_certs(true) // if needed for dev
.build()?;
let client = Siumai::builder()
.with_http_client(http)
.openai()
.api_key(std::env::var("OPENAI_API_KEY")?)
.model("gpt-4o-mini")
.build()
.await?;
Notes:
stream_disable_compression is derived from SIUMAI_STREAM_DISABLE_COMPRESSION (true unless set to false|0|off|no). You can override it per request via the unified builder method http_stream_disable_compression.reqwest::Client is provided via .with_http_client(..), it takes precedence over any other HTTP settings on the builder.Registry with custom middleware and interceptors:
use siumai::prelude::unified::*;
use siumai::experimental::execution::middleware::samples::chain_default_and_clamp;
use siumai::experimental::execution::http::interceptor::LoggingInterceptor;
use siumai::prelude::unified::registry::{create_provider_registry, RegistryOptions};
use std::collections::HashMap;
use std::sync::Arc;
let reg = create_provider_registry(
HashMap::new(),
Some(RegistryOptions {
separator: ':',
language_model_middleware: chain_default_and_clamp(),
http_interceptors: vec![Arc::new(LoggingInterceptor)],
http_config: None,
retry_options: None,
max_cache_entries: Some(128),
client_ttl: None,
auto_middleware: true,
})
);
siumai-extras)See the siumai-extras crate for details and examples.
Examples are under siumai/examples/:
Typical commands:
cargo run --example basic-chat --features openai
cargo run --example streaming --features openai
cargo run --example basic-orchestrator --features openai
web_search is wired through hosted_tools::openai::web_search and the OpenAI Responses pipeline, but is still considered experimental and may change.execution::http::*, Vertex helpers under auth::vertex. See CHANGELOG for migration notes.API keys and environment variables:
.api_key(..) or OPENAI_API_KEY.api_key(..) or ANTHROPIC_API_KEY.api_key(..) or GROQ_API_KEY.api_key(..) or GEMINI_API_KEY.api_key(..) or XAI_API_KEY{PROVIDER_ID}_API_KEY (e.g., DEEPSEEK_API_KEY).api_key(..) or {PROVIDER_ID}_API_KEYThis project draws inspiration from:
See CHANGELOG.md for detailed changes and migration tips.
Licensed under either of:
at your option.