turul-llm-core
The provider-neutral contract for calling an LLM with structured-output JSON Schema and getting parsed JSON back. One async method, zero transport dependencies.
This crate is the trait + types only. Concrete provider adapters live in sibling crates so this crate stays cheap to depend on for code that doesn't know yet which provider it will run against.
| Adapter crate | Provider |
|---|---|
turul-llm-ollama |
Ollama (/api/chat) |
turul-llm-openai |
OpenAI + OpenAI-compatible gateways (/chat/completions) |
Quick start
[]
= "0.1"
use Arc;
use json;
use ;
async
The Arc<dyn LlmClient> parameter accepts any adapter — swap providers
without changing this function.
What this crate is
LlmClient— one async method,Send + Sync, object-safe so adapters compose asArc<dyn LlmClient>or&dyn LlmClient.CompletionRequest— rendered prompt + optional JSON Schema 2020-12output_schema+ExecutionHints(max tokens, temperature, top-p).CompletionResponse—parsed_output: serde_json::Value.LlmError—#[non_exhaustive]taxonomy:Transport/Provider/SchemaViolation/Timeout/Other.
All public structs and the error enum are #[non_exhaustive], so the
contract can grow additively without breaking adopters.
What this crate is not
- Not an HTTP client. The crate has no
reqwest/hyper/ TLS surface. - Not a streaming layer. The trait is single-shot by design.
- Not a retry / cost / observability layer. Wrap a concrete adapter in
your own type that also implements
LlmClientto add those concerns without changing the trait. - Not a JSON Schema validator. Adapters surface
LlmError::SchemaViolationwhen the provider's structured-output API rejects the payload; callers can run their preferred validator onparsed_outputaftercompletereturns.
See also
- Workspace repository — full source, ADRs, examples.
- API documentation on docs.rs.
- CHANGELOG.
Licensing
Dual-licensed under Apache-2.0 OR MIT.