| Crates.io | litert-lm-rs |
| lib.rs | litert-lm-rs |
| version | 0.1.0 |
| created_at | 2025-11-04 23:12:18.525307+00 |
| updated_at | 2025-11-04 23:12:18.525307+00 |
| description | Rust bindings for LiteRT-LM C API - Engine, Session, and Conversation support |
| homepage | |
| repository | https://github.com/maceip/litert-lm-rs |
| max_upload_size | |
| id | 1917109 |
| size | 50,041 |
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.tflite
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
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 sessionUse 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 metricsUse 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)bindgen to auto-generate bindings from c/engine.hThis 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 --release
The build script will automatically:
bindgen to generate FFI bindings from c/engine.hbazel-bin/c/libengine.soWhen running your application, ensure the dynamic linker can find libengine.so:
export LD_LIBRARY_PATH=/path/to/LiteRT-LM/bazel-bin/c:$LD_LIBRARY_PATH
Or build with rpath:
RUSTFLAGS="-C link-args=-Wl,-rpath,/path/to/LiteRT-LM/bazel-bin/c" cargo build
use 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.tflite
The 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 sessionA 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 metricspub 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:
Engine automatically calls litert_lm_engine_delete on dropSession automatically calls litert_lm_session_delete on dropNo manual memory management required.
Engine: Implements Send + Sync - can be shared between threadsSession: Implements Send - can be moved between threads, but not sharedThe build process is designed to be simple and portable:
build.rs runs bindgen:
c/engine.h from LiteRT-LM$OUT_DIR/bindings.rsLinks against minimal dependencies:
libengine.so (or .dylib on macOS)stdc++ on Linux, c++ on macOS)Your code uses the safe wrapper:
src/lib.rs provides safe Rust APIThe C API library is not in your library path.
Solution: Build the C library first:
cd /path/to/LiteRT-LM
bazel build //c:engine
At 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_PATH
Or build with rpath:
RUSTFLAGS="-C link-args=-Wl,-rpath,/path/to/bazel-bin/c" cargo build
Apache-2.0
Contributions welcome! Please ensure:
cargo fmt)cargo test)