Safe, idiomatic Rust bindings for the LiteRT-LM C API.
# 1. Clone and build LiteRT-LM C library
git clone https://github.com/google-ai-edge/LiteRT-LM
cd LiteRT-LM
bazel build //c:engine
# 2. Clone this repo
cd ..
git clone https://github.com/maceip/litert-lm-rs
cd litert-lm-rs
# 3. Build and run example
export LD_LIBRARY_PATH=../LiteRT-LM/bazel-bin/c:$LD_LIBRARY_PATH
cargo run --example simple_chat model.tfliteLiteRT-LM is Google's lightweight runtime for on-device large language models. This crate provides Rust bindings that allow you to use LiteRT-LM from Rust applications with a safe, ergonomic API.
Upstream Repository: https://github.com/google-ai-edge/LiteRT-LM
- On-device AI applications: Run language models locally without cloud dependencies
- Privacy-focused apps: Keep user data on-device with local inference
- Embedded systems: Deploy LLMs on resource-constrained devices
- Rust applications: Integrate LiteRT-LM into Rust-based services and tools
- Cross-platform development: Build portable AI applications for Linux and macOS
The primary interface for loading and managing a language model. An Engine owns the loaded model and can create multiple sessions.
API:
Engine::new(model_path, backend)- Load a .tflite model file with CPU or GPU backendengine.create_session()- Create a new conversation session
Use when: You need to load a model once and create multiple independent conversation contexts.
Represents a stateful conversation context. Each session maintains its own history and can generate text responses.
API:
session.generate(prompt)- Generate text from a promptsession.get_benchmark_info()- Get performance metrics
Use when: You need to maintain conversation history or generate multiple related responses.
Specifies the hardware backend for model execution.
Options:
Backend::Cpu- CPU-based inferenceBackend::Gpu- GPU-accelerated inference (if available)
- Automatic FFI generation: Uses
bindgento auto-generate bindings fromc/engine.h - Safe API: Memory-safe Rust wrappers around C FFI
- Thread-safe: Engine and Session types implement Send/Sync where appropriate
- Idiomatic Rust: Result-based error handling, RAII resource management
- Portable: Works on Linux and macOS with simple build process
- Zero maintenance: Bindings stay in sync with C API automatically
This crate requires the LiteRT-LM C library to be built first.
-
Clone LiteRT-LM:
git clone https://github.com/google-ai-edge/LiteRT-LM cd LiteRT-LM -
Build the C API library:
bazel build //c:engine
This creates:
bazel-bin/c/libengine.so(Linux)bazel-bin/c/libengine.dylib(macOS)
cargo build --releaseThe build script will automatically:
- Run
bindgento generate FFI bindings fromc/engine.h - Link against
bazel-bin/c/libengine.so
When running your application, ensure the dynamic linker can find libengine.so:
export LD_LIBRARY_PATH=/path/to/LiteRT-LM/bazel-bin/c:$LD_LIBRARY_PATHOr build with rpath:
RUSTFLAGS="-C link-args=-Wl,-rpath,/path/to/LiteRT-LM/bazel-bin/c" cargo builduse litert_lm::{Engine, Backend};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load model
let engine = Engine::new("model.tflite", Backend::Cpu)?;
// Create conversation session
let session = engine.create_session()?;
// Generate text
let response = session.generate("Hello, how are you?")?;
println!("Response: {}", response);
Ok(())
}use litert_lm::{Engine, Backend};
use std::io::{self, Write};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let engine = Engine::new("model.tflite", Backend::Cpu)?;
let session = engine.create_session()?;
loop {
print!("You: ");
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
if input.trim().eq_ignore_ascii_case("quit") {
break;
}
match session.generate(input.trim()) {
Ok(response) => println!("Assistant: {}", response),
Err(e) => eprintln!("Error: {}", e),
}
}
Ok(())
}# Simple interactive chat
cargo run --example simple_chat -- /path/to/model.tflite
# Batch inference
cargo run --example batch_inference -- /path/to/model.tfliteThe Engine is the main entry point for loading and managing a language model.
let engine = Engine::new("model.tflite", Backend::Cpu)?;Methods:
new(model_path: &str, backend: Backend) -> Result<Engine>- Create engine from model filecreate_session(&self) -> Result<Session>- Create a new conversation session
A Session represents a conversation context with history.
let session = engine.create_session()?;
let response = session.generate("Hello!")?;Methods:
generate(&self, prompt: &str) -> Result<String>- Generate response to promptget_benchmark_info(&self) -> Result<BenchmarkInfo>- Get performance metrics
pub enum Backend {
Cpu, // CPU backend
Gpu, // GPU backend (if available)
}All operations return Result<T, Error> for proper error handling:
match session.generate("prompt") {
Ok(response) => println!("Success: {}", response),
Err(e) => eprintln!("Error: {}", e),
}The wrapper uses RAII (Resource Acquisition Is Initialization) for automatic cleanup:
Engineautomatically callslitert_lm_engine_deleteon dropSessionautomatically callslitert_lm_session_deleteon drop- Generated strings are automatically freed
No manual memory management required.
Engine: ImplementsSend + Sync- can be shared between threadsSession: ImplementsSend- can be moved between threads, but not shared
The build process is designed to be simple and portable:
-
build.rsruns bindgen:- Reads
c/engine.hfrom LiteRT-LM - Generates Rust FFI bindings
- Writes to
$OUT_DIR/bindings.rs
- Reads
-
Links against minimal dependencies:
libengine.so(or.dylibon macOS)- C++ standard library (
stdc++on Linux,c++on macOS) - No need to manually link dozens of libraries
-
Your code uses the safe wrapper:
src/lib.rsprovides safe Rust API- Automatically includes generated bindings
- Users never see unsafe code
The C API library is not in your library path.
Solution: Build the C library first:
cd /path/to/LiteRT-LM
bazel build //c:engineAt runtime, the dynamic linker can't find the library.
Solution: Set LD_LIBRARY_PATH:
export LD_LIBRARY_PATH=/path/to/LiteRT-LM/bazel-bin/c:$LD_LIBRARY_PATHOr build with rpath:
RUSTFLAGS="-C link-args=-Wl,-rpath,/path/to/bazel-bin/c" cargo buildApache-2.0
Contributions welcome! Please ensure:
- Code follows Rust conventions (
cargo fmt) - All tests pass (
cargo test) - New features include tests and documentation