Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- **`IreeMoonshineStream`** (`llm-runtime:iree-android`, `libskainet_moonshine_stream.so`, arm64-v8a +
armeabi-v7a, Vulkan + local-task): the streaming Moonshine v2 speech-to-text runtime over the five
graphs of `MoonshineV2ExportCli` — PCM in, cumulative partial transcripts out, exact final on
`finish()`. The counterpart of `IreeKvSession` for ASR: the last piece a Moonshine cartridge needed
from a released artifact. `native/build-moonshine-stream.sh` builds it with the same image and
cache as the other two libraries.

## [0.56.1] — 2026-09-21

A transformers-only release against **SKaiNET engine 0.56.0** (unchanged).
Expand Down
13 changes: 13 additions & 0 deletions docs/modules/ROOT/pages/reference/iree-android-runtime.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,19 @@ contract above): `iree_modules_io_parameters_parameters`,
`iree_io_formats_irpa_irpa`; plus `iree_base_tooling_flags` and `iree_task_api`
for the task-topology knob (`nativeCreateWithTopology`).

== `IreeMoonshineStream` — streaming speech-to-text

`libskainet_moonshine_stream.so` drives the five graphs of the Moonshine v2 streaming export (see
xref:how-to/export-moonshine-v2-streaming.adoc[Export Moonshine v2 Streaming to StableHLO]) as a real streaming
loop on the device: `feedPcm(FloatArray)` with mono 16 kHz PCM returns the updated cumulative partial transcript
(or `null`), `finish()` returns the exact final transcript and resets, `reset()` aborts. Files are passed by
absolute path (`IreeMoonshineStream.Files`, or `filesIn(dir)` for a directory holding the eight standard names:
`frontend.vmfb`, `encoder.vmfb`, `adapter.vmfb`, `prefill.vmfb`, `step.vmfb`, `params.irpa`, `vocab.bin`,
`dec_embed.bin`). `params.irpa` is the parameter archive `iree-compile --iree-opt-export-parameters=model=…`
writes for the decoder graphs (identical for prefill and step — keep one). The library's geometry is the `tiny`
class; `native/build-moonshine-stream.sh` builds it, with `GEOMETRY="-DL=10 -DHD=64 -DDIM=512 -DENC_DIM=620"`
for the `small` checkpoints.

== Verification

Host-side, numerically, against the real SmolLM2-135M-Instruct Q8_0
Expand Down
21 changes: 21 additions & 0 deletions llm-runtime/iree-android/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,24 @@ Measured (arm32 Android device, Mali via Vulkan, bf16 archives, chunk 32, 843-to
16 decode tokens): open 12.4 s, prefix 25.2 s once, then **p50 5.9 s per utterance** (one chunk call
≈ 2.0 s + 16 × 0.245 s), restore 0 ms, RSS ≈ 1.5 GB in the 32-bit process. Rebuild the library
with `native/build-iree-kv.sh <abi> --vulkan` (same image and links as the redecode `.so`).

## Moonshine streaming (`IreeMoonshineStream`, `libskainet_moonshine_stream.so`)

Streaming Moonshine v2 speech-to-text over the five graphs of `MoonshineV2ExportCli`
(`:llm-inference:moonshine:exportMoonshineV2`) — frontend, encoder, adapter, masked prefill, dynamic
with-past step — plus the shared decoder parameter archive (`iree-compile --iree-opt-export-parameters`
on the decoder graphs) and the two host-side tables the exporter writes. The native side windows the audio
(64 frames, hop 0.88 s), runs the encode stages on the device, decodes incrementally and hands out
cumulative partials; `finish()` runs one exact full re-decode. Geometry (tiny: 320 / 6 / 8) is compiled in;
attention bands and vocabulary size come from the files.

```kotlin
val stream = IreeMoonshineStream(IreeMoonshineStream.VULKAN_DEVICE, IreeMoonshineStream.filesIn(modelDir))
stream.feedPcm(pcm16k)?.let { partial -> show(partial) } // as audio arrives; null = unchanged
val text = stream.finish() // end of utterance; the stream resets
stream.close()
```

`native/build-moonshine-stream.sh <abi> --vulkan` builds it like the other two (`GEOMETRY="-DL=10 -DHD=64
-DDIM=512 -DENC_DIM=620"` for the split-width `small` checkpoints).

40 changes: 40 additions & 0 deletions llm-runtime/iree-android/native/build-moonshine-stream.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Builds libskainet_moonshine_stream.so — the streaming Moonshine v2 ASR runtime (five DSL graphs on the
# IREE runtime, Vulkan or local-task) — for one Android ABI with the pinned skainet/iree-android:3.11.0
# image, the same way build-iree-kv.sh builds the KV session runtime.
#
# native/build-moonshine-stream.sh arm64-v8a [--vulkan] [cache-dir]
# native/build-moonshine-stream.sh armeabi-v7a [--vulkan] [cache-dir]
#
# The IREE host tools and the per-ABI runtime tree are cached under
# ~/.cache/skainet-iree/3.11.0 (override with IREE_CACHE or the third argument); a warm cache
# builds in seconds. Output: native/out/libskainet_moonshine_stream.so — copy it to
# src/main/jniLibs/<abi>/ to ship it.
#
# Geometry is compiled in (tiny: dim 320 / 6 layers / 8 heads / head 40, the default). The `small`
# checkpoints (encoder 620 / decoder 512 / 10 layers / head 64) need a separately built variant:
# GEOMETRY="-DL=10 -DHD=64 -DDIM=512 -DENC_DIM=620" native/build-moonshine-stream.sh <abi> --vulkan
set -euo pipefail
ABI="${1:-arm64-v8a}"; shift || true
VULKAN=""; EXTRA=()
[ -n "${GEOMETRY:-}" ] && EXTRA=(--cmake "-DCMAKE_C_FLAGS=${GEOMETRY}")
while [ $# -gt 0 ]; do
case "$1" in
--vulkan) VULKAN="--vulkan" ;;
*) CACHE="$1" ;;
esac
shift
done
CACHE="${CACHE:-${IREE_CACHE:-$HOME/.cache/skainet-iree/3.11.0}}"
HERE="$(cd "$(dirname "$0")" && pwd)"
mkdir -p "$HERE/out" "$CACHE/build-host" "$CACHE/build-$ABI"
docker run --rm \
-v "$HERE":/src:ro -v "$HERE/out":/out \
-v "$CACHE/build-host":/iree/build-host \
-v "$CACHE/build-$ABI":/iree/build-$ABI \
skainet/iree-android:3.11.0 \
build-so "$ABI" --name skainet_moonshine_stream --src /src/moonshine_stream_jni.c $VULKAN ${EXTRA[@]+"${EXTRA[@]}"} \
--link iree_modules_io_parameters_parameters \
--link iree_io_parameter_index \
--link iree_io_parameter_index_provider \
--link iree_io_formats_irpa_irpa
Loading
Loading