litert-lm-rs
Safe, idiomatic Rust bindings for the LiteRT-LM C API.
Quick Start
# 1. Clone and build LiteRT-LM C library
# 2. Clone this repo
# 3. Build and run example
About
LiteRT-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
Use Cases
- 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
Interfaces
Engine
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.
Session
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.
Backend
Specifies the hardware backend for model execution.
Options:
Backend::Cpu- CPU-based inferenceBackend::Gpu- GPU-accelerated inference (if available)
Features
- 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
Building
Prerequisites
This crate requires the LiteRT-LM C library to be built first.
-
Clone LiteRT-LM:
-
Build the C API library:
This creates:
bazel-bin/c/libengine.so(Linux)bazel-bin/c/libengine.dylib(macOS)
Build the Rust bindings
The build script will automatically:
- Run
bindgento generate FFI bindings fromc/engine.h - Link against
bazel-bin/c/libengine.so
Runtime library path
When running your application, ensure the dynamic linker can find libengine.so:
Or build with rpath:
RUSTFLAGS="-C link-args=-Wl,-rpath,/path/to/LiteRT-LM/bazel-bin/c"
Usage
Basic example
use ;
Interactive chat example
use ;
use ;
Running examples
# Simple interactive chat
# Batch inference
API Overview
Engine
The Engine is the main entry point for loading and managing a language model.
let engine = new?;
Methods:
new(model_path: &str, backend: Backend) -> Result<Engine>- Create engine from model filecreate_session(&self) -> Result<Session>- Create a new conversation session
Session
A Session represents a conversation context with history.
let session = engine.create_session?;
let response = session.generate?;
Methods:
generate(&self, prompt: &str) -> Result<String>- Generate response to promptget_benchmark_info(&self) -> Result<BenchmarkInfo>- Get performance metrics
Backend
Error Handling
All operations return Result<T, Error> for proper error handling:
match session.generate
Memory Management
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.
Thread Safety
Engine: ImplementsSend + Sync- can be shared between threadsSession: ImplementsSend- can be moved between threads, but not shared
Build Process Details
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
Troubleshooting
"cannot find -lengine"
The C API library is not in your library path.
Solution: Build the C library first:
"cannot find libengine.so at runtime"
At runtime, the dynamic linker can't find the library.
Solution: Set LD_LIBRARY_PATH:
Or build with rpath:
RUSTFLAGS="-C link-args=-Wl,-rpath,/path/to/bazel-bin/c"
License
Apache-2.0
Contributing
Contributions welcome! Please ensure:
- Code follows Rust conventions (
cargo fmt) - All tests pass (
cargo test) - New features include tests and documentation