# rust-ringo-fm-sdk
Rust bindings for Apple's on-device [Foundation Models](https://developer.apple.com/documentation/foundationmodels) framework.
## Workspace layout
- `crates/ringo-fm-sys` — raw FFI bindings (`bindgen`) to the Swift bridge from `ringo-fm-bridge`.
- `crates/ringo-fm` — idiomatic, async (`tokio`) wrapper. Public surface mirrors the Python package: `SystemLanguageModel`, `LanguageModelSession`, `Prompt`, `GenerationSchema`, `Tool`, `Transcript`, …
- `crates/ringo-fm/examples/` — Rust ports of the three Python examples.
## Requirements
- macOS 26+ with Apple Intelligence enabled.
- Full Xcode 26+ install (`xcode-select` pointing at `Xcode.app`, not just the CLI tools).
- The vendored `crates/ringo-fm-sys/vendor/foundation-models-c` Swift package included in this repository, or set `APPLE_FM_SDK_SWIFT_PKG` to another compatible `foundation-models-c/` directory.
## Quick start
```rust
use ringo_fm::{LanguageModelSession, SystemLanguageModel};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let model = SystemLanguageModel::default()?;
let (ok, reason) = model.is_available();
if !ok { eprintln!("model unavailable: {reason:?}"); return Ok(()); }
let session = LanguageModelSession::new(
Some(&model),
Some("You are concise."),
Vec::new(),
)?;
let response = session.respond("What is the capital of France?").await?;
println!("{response}");
Ok(())
}
```
## Build & run
```bash
cd crates/ringo-fm-sys/vendor/foundation-models-c
swift build -c release
cd ../../../..
cargo build --workspace
cargo run --example simple_inference
cargo run --example streaming_example
cargo run --example transcript_processing -- path/to/transcript.json
```
The Rust examples automatically add an `rpath` to `crates/ringo-fm-sys/vendor/foundation-models-c/.build/release`.
If your Swift package checkout lives elsewhere, set `APPLE_FM_SDK_SWIFT_PKG` to the absolute path
of that `foundation-models-c` directory before building or running.
## Schema Discovery
`LanguageModelSession::discover_schema` uses guided generation to infer a
reviewable schema candidate from text, JSON, or already-extracted documents.
The response includes field candidates, evidence, warnings, metrics, and review
findings; treat it as a draft for human review, not an approved schema.
```rust
use ringo_fm::{
DiscoveryDocument, DiscoveryDocumentSource, DiscoverSchemaRequest,
DiscoveryOptions, GenerationOptions, LanguageModelSession,
};
# async fn example() -> ringo_fm::Result<()> {
let session = LanguageModelSession::default()?;
let response = session.discover_schema(
DiscoverSchemaRequest {
documents: vec![DiscoveryDocument {
id: "doc-1".into(),
source: DiscoveryDocumentSource {
source_type: "text".into(),
content: Some("請求日 2026-01-01\n合計 12,000円".into()),
..Default::default()
},
metadata: None,
}],
options: Some(DiscoveryOptions::default()),
..Default::default()
},
&GenerationOptions::default(),
).await?;
# let _ = response;
# Ok(())
# }
```
## Status
V1 ships everything from the Python public API except:
- `#[derive(Generable)]` proc macro — implement `Generable` manually for now.
- Multi-tool sessions — the C bridge maps every tool call through a single trampoline symbol, so v1 reliably supports **one** registered tool per session. Multi-tool dispatch needs a libffi-style closure trampoline; tracked as a follow-up.
## License
Apache-2.0
## Third-party code
This repository vendors `crates/ringo-fm-sys/vendor/foundation-models-c` from `ringo-fm-bridge`, which is
licensed under Apache-2.0. The vendored package retains its original source headers, and a copy of
the bridge license is included at `crates/ringo-fm-sys/vendor/foundation-models-c/LICENSE.md`.