[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6BY5835F3RMMW9KCCZ006JM":3,"skill-same:01M6BY5835F3RMMW9KCCZ006JM":139},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":34,"linkOnly":35,"markdownContent":36,"markdownBody":37,"frontMatter":38,"refName":39,"commitSha":40,"skillDirectory":41,"forksCount":42,"repositoryHtmlUrl":43,"repositoryHomepageUrl":44,"ownerHtmlUrl":45,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":46,"install":47,"resources":60},"01M6BY5835F3RMMW9KCCZ006JM","litert-compiled-model-migration",null,"Rapidly migrate an Android application from legacy TensorFlow Lite (TFLite) to the modern LiteRT CompiledModel API (2.x) in Open Source GitHub repositories, keeping the TensorFlow Lite Support Library as LiteRT Support (litert-support 2.3.0). Covers buffer reuse, NPU JIT compilation, a reference implementation, and a two-stage verification gate (compile check, then an on-device parity test against a golden output).","google-ai-edge\u002Flitert-samples","google-ai-edge","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F150697620?v=4","01M6BY4NHMZF88PJAC1E1QJY8N","01M6BY4NNXP8PC95Y6CABCJXP9",494,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002Flitert-samples\u002Fblob\u002Fmain\u002Fskills\u002Flitert-compiled-model-migration\u002FSKILL.md",[],[18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33],"litert","model","litert compiled model migration","android","github","tensorflow","support","test","verification","compile","open source","library","jit","api","open","migrate","2026-11-10 10:12:30",false,"---\nname: litert-compiled-model-migration\ndescription: Rapidly migrate an Android application from legacy TensorFlow Lite (TFLite) to the modern LiteRT CompiledModel API (2.x) in Open Source GitHub repositories, keeping the TensorFlow Lite Support Library as LiteRT Support (litert-support 2.3.0). Covers buffer reuse, NPU JIT compilation, a reference implementation, and a two-stage verification gate (compile check, then an on-device parity test against a golden output).\n---\n\n# Skill: LiteRT Compiled Model Migration SKILL\n\n## Description\nThis skill guides an AI agent to rapidly migrate an Android application from legacy TensorFlow Lite (TFLite) to the modern LiteRT CompiledModel API (2.x) in **Open Source GitHub repositories**. It prioritizes a high-speed, 1st-pass **\"Like for Like\" baseline migration** with automated self-testing, and encourages advanced performance upgrades including **off-main-thread execution with buffer reuse** and **NPU JIT compilation**.\n\n## Read first: what the Kotlin CompiledModel API (`com.google.ai.edge.litert`, 2.3.0; 2.2.0 has the same API) has\n\n- `CompiledModel.create(context.assets, assetName, CompiledModel.Options(Accelerator.CPU), env)` and `create(filePath, options, env)`; `Options` takes one or more of `Accelerator.CPU` \u002F `GPU` \u002F `NPU` (e.g. `Options(Accelerator.GPU, Accelerator.CPU)`); `env` is `Environment.create(context)` (optional; enables the compiler cache) or `Environment.create(context, BuiltinNpuAcceleratorProvider(context))` for the NPU. Nothing takes a ByteBuffer or a mapped file.\n- Buffers come from the model (`createInputBuffers()` \u002F `createOutputBuffers()`, `List\u003CTensorBuffer>`; `writeFloat(FloatArray)` \u002F `writeInt8(ByteArray)` \u002F `writeInt` \u002F `writeLong`, `readFloat()` and friends; create them once). `run(inputs, outputs)` is synchronous on the CPU; on the GPU it can return before the GPU finishes and `read*()` waits; there is no callback API. `CompiledModel`, `TensorBuffer` and `Environment` are `AutoCloseable`: close buffers, then the model, then an `Environment` the app created.\n- `CompiledModel.Options()` with no accelerator compiles, but `create` then throws `LiteRtException`. `Interpreter`, `GpuDelegate`, `NnApiDelegate` and the Support library's `Model` (`com.google.ai.edge.litert.support.model.Model`, which runs on `InterpreterApi`) do not appear in migrated code; the rest of LiteRT Support does, under `com.google.ai.edge.litert.support` (Step 1), with `org.tensorflow.lite.DataType` as the type its classes take. The `litert` AAR also contains `org.tensorflow.lite.Interpreter`, so leftover Interpreter code compiles (all but `setUseNNAPI`, which 2.x does not have) and the Stage 1 import check is what catches it. `templates\u002FLiteRtModel.kt` compiles against the 2.3.0 and the 2.2.0 artifacts; start from it.\n\n---\n\n## 0. Automatic Discovery & Upfront Planning\n\nBefore writing code, the agent MUST inspect the project workspace and present the upfront planning interview to align migration parameters:\n\n### A. Automatic Workspace & Toolchain Discovery\nThe agent must automatically inspect the repository structure:\n1. **Ecosystem & Build Engine**:\n   * **Gradle Build System**: Detected by `build.gradle`, `build.gradle.kts`, or `settings.gradle`. -> Enable **Gradle & GitHub PR Workflow**.\n2. **Language & JNI Toolchain**:\n   * **Native C++ \u002F NDK**: Detected if `CMakeLists.txt`, `Android.mk`, or `*.cpp` files exist. -> Enable **C++ \u002F JNI Migration Rules**.\n   * **Pure Kotlin \u002F Java**: Default to **JVM \u002F Android SDK Migration Rules**.\n\n### B. Upfront User Interview (Questions Asked Prior to Migration)\n\nThe agent must present the following review options to the user:\n\n```\nBefore initiating the LiteRT Compiled Model Migration, please confirm your project preferences:\n\n1. Model Workload & Domain:\n   What type of data does this application process?\n   - [A] Vision (Images \u002F Video \u002F Camera Feeds) -> Enables the camera-frame recipe: preprocess into a reused input buffer via writeFloat \u002F writeInt8 (AHardwareBuffer interop is C++-only).\n   - [B] Audio (Speech \u002F Sound Classification) -> Enables the streaming FloatArray recipe (writeFloat per window).\n   - [C] Text \u002F NLP \u002F GenAI -> Enables the token-id recipe (writeInt \u002F writeLong into the model's input buffers).\n\n2. Hardware Acceleration & Conditional INT8 Quantization:\n   Do you want to enable NPU hardware acceleration via JIT on-device compilation?\n   - [A] Yes (Recommended - replaces deprecated NNAPI; needs the vendor libraries of Upgrade 2.C on a supported SoC) [Default]\n         * If the app uses a Float32 model: Would you like to generate an INT8 integer-quantized model via AI Edge Quantizer for peak NPU speed, or run the original Float32 model?\n           -> Option A.1: Convert to INT8 (Generates model_int8.tflite with int8 weights and activations; needs a few representative inputs for calibration) [Default]\n           -> Option A.2: Keep Float32 (Runs baseline float model directly on NPU)\n   - [B] No (GPU and CPU acceleration only)\n\n3. Encouraged Performance Upgrades:\n   Should the agent upgrade the calling code to use LiteRT's advanced features?\n   - [A] Yes (Move inference off the main thread and reuse buffers) [Default]\n   - [B] No (Keep strict 1-to-1 synchronous baseline execution)\n\n4. Automated Pull Request Provisioning:\n   Should the agent automatically stage, commit, and create a GitHub PR when self-testing passes?\n   - [A] Yes [Default] (Attaches verification test logs and before\u002Fafter summary diff)\n   - [B] No (Keep changes local in current working branch)\n```\nWith no user to answer (CI, batch runs): take Q1 from the code, Q2 [A] only when the vendor libraries of Upgrade 2.C are already in the repo (otherwise [B]), Float32 unless calibration inputs exist, and the defaults of Q3 and Q4 with the PR opened as a draft; record the choices in the PR description.\nToday the runtime is the standalone `com.google.ai.edge.litert:litert` AAR: no LiteRT artifact for Google Play services is on Google Maven as of October 2026 (only the `play-services-tflite-*` Interpreter artifacts exist).\n\n> [!IMPORTANT]\n> **LiteRT Support (`litert-support` 2.3.0)**: an app on the TensorFlow Lite Support Library keeps it. The library now ships as LiteRT Support, with the same classes, methods and behavior; the migration is two steps of Step 1, swap the Gradle coordinates and rename the package `org.tensorflow.lite.support` to `com.google.ai.edge.litert.support` (its guide: https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002FLiteRT\u002Fblob\u002Fmain\u002Flitert\u002Fsupport_lib\u002FMIGRATION_GUIDE.md). `ImageProcessor`, `ResizeOp`, `NormalizeOp`, `TensorImage`, `TensorLabel`, `FileUtil` and `MetadataExtractor` stay as they are. The one class replaced is its `Model`, which runs on the Interpreter API: it becomes `CompiledModel` like `Interpreter` (Step 4), with `templates\u002FSupportBridge.kt` between the Support tensors and the model's buffers. An app that never used the Support library does not add it; `Bitmap.toModelInput` in `templates\u002FLiteRtModel.kt` is its preprocessing.\n\n---\n\n## 1. Phase 1: \"Like for Like\" Baseline Migration (1st Pass Success)\n\nPhase 1 prioritizes functional equivalence, fast compilation, and immediate 1st pass self-test success.\n\n### Step 0: Capture the Golden Output\nBefore Step 1 changes any dependency, with the legacy runtime and preprocessing still in the project (no device attached: skip Step 0, stop after Stage 1, and open the PR as a draft that says so):\n* Define one fixed input: for a vision app a deterministic bitmap (`fixedBitmap` in `templates\u002FGoldenCaptureTest.kt`, or a small image file in `app\u002Fsrc\u002FandroidTest\u002Fassets\u002F`), otherwise a generated array; never a camera frame. A bitmap of the model's input size with rotation 0 leaves the resize and the rotation out of the gate: use another size (and aspect ratio), and the rotation the camera path passes, in the capture and in Stage 2 alike.\n* Declare the `androidx.test` dependencies and `testInstrumentationRunner` (Stage 2 needs them too), copy `templates\u002FGoldenCaptureTest.kt` into `app\u002Fsrc\u002FandroidTest\u002Fjava\u002F\u003Cpackage>\u002F`, make it call the app's existing inference entry point (the class the UI calls, with its own preprocessing) on the fixed input on the CPU (no GPU or NNAPI delegate, XNNPACK at its default); when that entry point returns only a thresholded or sorted list, first give the class a function returning the raw output and one returning the preprocessed input (`preprocess(bitmap)`: Stage 2 calls it too), still on the legacy runtime. Then run the four commands in its header: they install both APKs, run the test on the device, and pull `golden.txt` into `app\u002Fsrc\u002FandroidTest\u002Fassets\u002Fgolden\u002Foutput.txt`. A raw tensor fed straight to the model is not a golden output: it leaves the preprocessing out of the gate.\n* Delete the capture test. Stage 2 compares against the file, so the test APK never needs `org.tensorflow:tensorflow-lite`.\n\n### Step 1: Clean & Modernize Dependencies\n\nInspect `libs.versions.toml` and `build.gradle.kts`:\n* **Remove Legacy & Deprecated**:\n  * `org.tensorflow:tensorflow-lite` \u002F `tensorflow-lite-gpu` \u002F `tensorflow-lite-select-tf-ops` *(Legacy Flex Delegate — see Deprecated API Remediation below)*, and every other `org.tensorflow:tensorflow-lite*` line, including ones other libraries pull in (`.\u002Fgradlew :app:dependencies` lists them): the LiteRT artifacts carry the `org.tensorflow.lite` runtime classes and the model schema under their original names, and mixing old and new artifacts fails the build with duplicate classes. `com.google.ai.edge.litert:litert-gpu` **1.x** goes too *(the renamed TFLite GPU delegate, last 1.4.2; `litert-gpu:2.3.0` is the GPU accelerator of the CompiledModel runtime and is added below)*, and `com.google.ai.edge.litert:litert` **1.x** (the renamed Interpreter runtime, e.g. `samples\u002Flitert_interpreter\u002F*` on 1.0.0) becomes `litert:2.3.0` below.\n* **Swap the Support library coordinates** (apps on `org.tensorflow.lite.support.*`): `org.tensorflow:tensorflow-lite-support` or `litert-support` 1.x becomes `implementation(\"com.google.ai.edge.litert:litert-support:2.3.0\")` (the Support API plus the LiteRT runtime: it depends on `litert:2.3.0`); `tensorflow-lite-support-api` becomes `litert-support-api:2.3.0` (the API alone, the runtime being the `litert` line below); `tensorflow-lite-metadata` or `litert-metadata` 1.x becomes `litert-metadata:2.3.0` (`MetadataExtractor`). Then rename the package in every source file and in R8\u002FProGuard rules (`-keep class org.tensorflow.lite.support.**`): `grep -rl 'org\\.tensorflow\\.lite\\.support' --include='*.java' --include='*.kt' app\u002Fsrc\u002F | xargs sed -i 's\u002Forg\\.tensorflow\\.lite\\.support\u002Fcom.google.ai.edge.litert.support\u002Fg'` (GNU sed; on macOS, `sed -i ''`). `org.tensorflow.lite.DataType`, the type the Support classes take, keeps its name.\n* **Add Modern LiteRT**:\n  * *Standalone*: `implementation(\"com.google.ai.edge.litert:litert:2.3.0\")` and `implementation(\"com.google.ai.edge.litert:litert-gpu:2.3.0\")` in Kotlin DSL (`implementation 'com.google.ai.edge.litert:litert:2.3.0'` and `'…:litert-gpu:2.3.0'` in Groovy). `litert` pulls in `litert-api` and sets minSdk 24. `litert-support:2.3.0` depends on `litert:2.3.0` and raises a `litert:2.2.0` pin to 2.3.0 without a warning (Gradle resolves `litert:2.2.0 -> 2.3.0`), so pin 2.3.0 here. Since 2.3.0 the GPU accelerator (`libLiteRtClGlAccelerator.so`) ships in `litert-gpu`; in 2.2.0 it was inside `litert`. Without `litert-gpu`, `CompiledModel.Options(Accelerator.GPU, Accelerator.CPU)` creates and runs on the CPU with the log line `GPU accelerator could not be loaded and registered`, and `Options(Accelerator.GPU)` alone throws.\n* **Toolchain the 2.3.0 artifacts need**: `litert-api:2.3.0` depends on `androidx.lifecycle:lifecycle-runtime:2.10.0` (its POM), and its classes carry Kotlin 2.4 metadata (2.2.0: Kotlin 2.3). Set these before the first build on a project on AGP 8.3 \u002F Kotlin 1.9 (e.g. `samples\u002Flitert_interpreter\u002F*`), or each becomes a build error in turn: `compileSdk` 35 and AGP 8.6.0 (`checkDebugAarMetadata`), Gradle 8.7 (AGP 8.6.0), the Kotlin plugin 2.3 or newer (from 1.9 this is a plugin upgrade; `freeCompilerArgs += \"-Xskip-metadata-version-check\"` only lets a project already on 2.2 stay there, as `samples\u002Flitert\u002Fimage_segmentation\u002Fkotlin_cpu_gpu` does; 2.2 otherwise stops at `The binary version of its metadata is 2.4.0, expected version is 2.2.0`, and 2.2 is enough for the 2.2.0 artifacts), and with Kotlin 2.x a Compose app needs the `org.jetbrains.kotlin.plugin.compose` plugin in place of `composeOptions`. On AGP 9 (built-in Kotlin) the Kotlin version is pinned with `id(\"org.jetbrains.kotlin.android\") version \"2.3.21\" apply false` in the root plugins block.\n* **Labels and metadata**: `FileUtil.loadLabels` and `MetadataExtractor` work as before on the 2.3.0 artifacts. An app without the Support library reads the label file from assets: a `.tflite` with metadata is a zip, so extract it once (`unzip -o model.tflite labels.txt -d app\u002Fsrc\u002Fmain\u002Fassets\u002F`; `unzip -l` lists the name).\n* **IDE Portability**: Remove hardcoded `org.gradle.java.home` from `gradle.properties` and exclude `local.properties`.\n* **Kotlin Compiler DSL**: Use top-level `kotlin { compilerOptions { ... } }` outside `android { ... }`: `kotlinOptions { jvmTarget = \"1.8\" }` becomes `kotlin { compilerOptions { jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8) } }`.\n\n### Step 2: Deprecated API & Delegate Remediation\n\nThe agent must audit and replace all deprecated delegate APIs:\n\n1. **NNAPI Delegate (`NnApiDelegate`, `NnApiDelegate.Options`, `setUseNNAPI(true)`)**:\n   * **Status**: NNAPI is deprecated since Android 15, and the LiteRT 2.x Java\u002FKotlin API has no NNAPI entry point (`Interpreter.Options` has no `setUseNNAPI`).\n   * **Remediation**: Remove `org.tensorflow.lite.nnapi.NnApiDelegate` imports. Replace with `CompiledModel.Options(Accelerator.NPU)` and `Environment.create(context, BuiltinNpuAcceleratorProvider(context))` when `BuiltinNpuAcceleratorProvider(context).isDeviceSupported()` is true (NPU-only options compile as NPU + CPU, so unsupported ops fall back to the CPU). In 2.3.0 `isDeviceSupported()` is true on every Qualcomm, MediaTek or Samsung SoC from Android 12 and on Google Tensor from Android 16 (2.2.0 used a SoC list), and without the vendor libraries `create` still returns: the runtime logs `Failed to apply compiler plugins: No compiler plugin found` (2.2.0 adds `Failed to initialize Dispatch API`) and compiles for the CPU, so a cascade's reported accelerator reads NPU while the CPU runs. Implement an explicit `NPU -> GPU -> CPU` fallback cascade (try each `CompiledModel.create`, catch `LiteRtException`) to handle non-NPU hardware smoothly. Under Q2 [B], an NNAPI choice in the app's UI becomes the GPU option (`Options(Accelerator.GPU, Accelerator.CPU)`).\n\n2. **Flex Delegate (`FlexDelegate`, `org.tensorflow.lite.flex`, `select-tf-ops`)**:\n   * **Status**: Interpreter-only: the Flex delegate ships in the legacy `tensorflow-lite-select-tf-ops` artifact (68 MB for arm64 in 2.16.1) and in no LiteRT 2.x artifact, so a model with Select TF ops needs the re-export below.\n   * **Remediation**:\n     * Remove `org.tensorflow:tensorflow-lite-select-tf-ops` from `build.gradle.kts`.\n     * Find Flex ops by FlatBuffer inspection (custom ops whose `custom_code` starts with `Flex`); `check_gpu_compatibility` in `utilities\u002Flitert_gpu_toolkit` (this repository) reports such a model as a compile failure, not op by op.\n     * Replace Flex ops by re-exporting the model without them (LiteRT-Torch for PyTorch sources; the TensorFlow converter without `SELECT_TF_OPS`), or, if custom C++ math is required, implement a `litert::CustomOpKernel` (`litert\u002Fcc\u002Flitert_custom_op_kernel.h`, shipped in `litert_cc_sdk.zip`; guide: https:\u002F\u002Fdevelopers.google.com\u002Fedge\u002Flitert\u002Fnext\u002Fcustom_op_dispatcher).\n\n### Step 3: Native Build Toolchain (`CMakeLists.txt` \u002F NDK)\nFor native C++ modules, use the C++ SDK the LiteRT docs describe (https:\u002F\u002Fdevelopers.google.com\u002Fedge\u002Flitert\u002Fnext\u002Fandroid_cpp_sdk): download `litert_cc_sdk.zip` from the LiteRT GitHub release that matches the AAR version (https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002FLiteRT\u002Freleases\u002Fdownload\u002Fv2.2.0\u002Flitert_cc_sdk.zip; 2.3.0 has no GitHub release as of 2026-10-07, so a native module stays on the 2.2.0 AAR and zip until the matching zip exists, and an app with both a native module and the Support library waits for that zip, since `litert-support:2.3.0` raises the runtime to 2.3.0), copy `libLiteRt.so` from the AAR's `jni\u002Farm64-v8a\u002F` into its `litert_cc_sdk\u002F` directory (`LITERT_CC_SDK` below), and link the `litert_cc_api` target. The AAR ships no headers or prefab package, and `liblitert_jni.so` is the Kotlin binding, not a C++ target:\n```cmake\n# Replace legacy tensorflowlite_jni with the LiteRT C++ SDK\nadd_subdirectory(\"${LITERT_CC_SDK}\" \"${LITERT_CC_SDK}\u002Fbuild\")\ninclude_directories(\"${LITERT_CC_SDK}\")\n\ntarget_link_libraries(your_native_lib\n    litert_cc_api\n    android\n    log\n)\n```\n\n### Step 4: API & Lifecycle Refactoring (Rewrite Initialization & Dynamic Signatures)\n\n> [!IMPORTANT]\n> **Never Simple Swap**: Do **NOT** merely perform a search-and-replace of the `Interpreter` class. Rewrite the model initialization logic to instantiate `CompiledModel` with an explicit hardware fallback cascade (`NPU -> GPU -> CPU`). When NPU is selected, prioritize NPU JIT compilation by instantiating an explicit `Environment` object (`Environment.create(context, BuiltinNpuAcceleratorProvider(context))`) and passing it to `CompiledModel.create`; on a supported device the provider itself sets `Environment.Option.DispatchLibraryDir` and `Environment.Option.CompilerPluginLibraryDir` to `context.applicationInfo.nativeLibraryDir`, and the `context` overload enables the compiler cache under `context.cacheDir`.\n\n| Legacy TFLite API | Modern LiteRT V2 Drop-in Replacement |\n|---|---|\n| `org.tensorflow.lite.Interpreter` | `com.google.ai.edge.litert.CompiledModel` |\n| `Interpreter(modelFile, options)`; LiteRT Support's `Model.createModel(context, name, options)` | `CompiledModel.create(context.assets, assetName, options, env)` or `create(filePath, options, env)`; no ByteBuffer overload *(via NPU Environment & Fallback Cascade)* |\n| `interpreter.run(input, output)` | `compiledModel.run(inputBuffers, outputBuffers)` (both `List\u003CTensorBuffer>` from `createInputBuffers()` \u002F `createOutputBuffers()`) |\n| `interpreter.runForMultipleInputsOutputs(inputs, outputs)`; Support `model.run(inputs, outputs)` | `compiledModel.run(inputBuffers, outputBuffers)` |\n| `interpreter.runSignature(inputs, outputs, key)` | `compiledModel.run(inputMap, outputMap, key)` (`Map\u003CString, TensorBuffer>`) |\n| `Interpreter.Options().setNumThreads(n)` | `options.cpuOptions = CompiledModel.CpuOptions(numThreads = n)` on a fresh `Options(Accelerator.CPU)`, not the shared `Options.CPU` |\n| `interpreter.resizeInput(...)` | none in 2.3.0 (`resizeInputTensor` is on LiteRT main after 2.3.0; the C++ API has `ResizeInputTensor`) |\n| `GpuDelegate()` \u002F `NnApiDelegate()` | `CompiledModel.Options(Accelerator.GPU, Accelerator.CPU)` \u002F `CompiledModel.Options(Accelerator.NPU)` (NPU-only compiles as NPU + CPU) |\n| `org.tensorflow.lite.flex.FlexDelegate` | none: re-export the model without Select TF ops, or a C++ `CustomOpKernel` (Step 2) |\n| `interpreter.getInputTensor(0).shape()` | `compiledModel.getInputTensorType(inputName).layout?.dimensions`: by name only, no index or list call; `args_0` \u002F `output_0` for LiteRT-Torch exports, the graph's tensor names otherwise (`images` \u002F `Softmax` in the EfficientNet samples; print `interpreter.getInputTensor(0).name()` in the Step 0 capture test) |\n| `imageProcessor.process(TensorImage.fromBitmap(bitmap))` then `interpreter.run(tensorImage.buffer, out)` | the same `ImageProcessor`, on `com.google.ai.edge.litert.support.image`; `bridge.write(inputBuffers[0], tensorImage)` (`templates\u002FSupportBridge.kt`: `writeFloat(tensorImage.tensorBuffer.floatArray)` for a float image, `writeInt8` for uint8, after a size check) |\n| Support `TensorBuffer.createFixedSize(shape, DataType.FLOAT32)` as the output, then `TensorLabel` \u002F `TensorProcessor` | `bridge.read(outputBuffers[0], shape, DataType.FLOAT32)`; `TensorLabel` \u002F `TensorProcessor` unchanged |\n| `#include \"tensorflow\u002Flite\u002Finterpreter.h\"` | `#include \"litert\u002Fcc\u002Flitert_compiled_model.h\"` |\n| `#include \"tensorflow\u002Flite\u002Fc\u002Fc_api.h\"` | `#include \"litert\u002Fc\u002Flitert_compiled_model.h\"` |\n\nReference implementation: `templates\u002FLiteRtModel.kt` (needs `androidx.core:core-ktx` and `org.jetbrains.kotlinx:kotlinx-coroutines-android`; it already carries Upgrades 2.A and 2.B, and closes everything it created when a step after `CompiledModel.create` throws). Copy it next to the app's inference class, replace the package, and keep its shape:\n* `LiteRtModel.create(context, assetName, wantNpu, wantGpu = true, numThreads = null)` is a `suspend` factory that runs on the model's own serial dispatcher: it takes the process-wide `Environment` (created once, with `BuiltinNpuAcceleratorProvider` when the first caller wants the NPU and `isDeviceSupported()`), tries `CompiledModel.create` on NPU, then GPU + CPU, then CPU (`wantGpu = false` skips the GPU step for an app whose CPU setting means the CPU alone; `numThreads` is the legacy `setNumThreads`), catching `LiteRtException`, and creates the buffers once.\n* `suspend fun run(FloatArray): FloatArray` does `writeFloat` \u002F `run` \u002F `readFloat` on the same dispatcher; `run(write, read)` takes two lambdas over the input and output buffer for the Support bridge below; `runSync(input)` is the entry point for Java callers and for Q3 [B] (the synchronous baseline), from a background thread; `close()` closes the buffers, then the model (the shared `Environment` stays open: creating one loads the accelerator libraries, and one created and closed per model reloads them on every load), and is called after the last `run` has returned.\n* `accelerator` is the step that did not throw, not proof that every op runs there: NPU-only options compile as NPU + CPU, and a missing or failing compiler plugin is logged and skipped inside `create`; pass `wantNpu = true` only with the libraries of Upgrade 2.C in place.\n* `Bitmap.toModelInput(size)` in the same file is the preprocessing of an app without the Support library: `androidx.core.graphics.scale` and one loop writing `(channel - mean) \u002F std` into a `FloatArray`, with the legacy `NormalizeOp(mean, std)` values (127.5 \u002F 127.5 in the template; change them to the app's). An app that keeps LiteRT Support leaves its `ImageProcessor` as it is, deletes `Bitmap.toModelInput`, and copies `templates\u002FSupportBridge.kt` too: `SupportBridge(model, inputName, outputName)`, created once after `create`, reads the byte size of both tensors, and its `write` \u002F `read` move a `TensorImage` or Support `TensorBuffer` into the model's buffers and back, and refuse one of another size or type (the Kotlin API itself accepts a shorter array, or uint8 bytes in a float input, without an error). Both libraries name a class `TensorBuffer`; the file imports the Support one as `SupportTensorBuffer`.\n```kotlin\nval model = LiteRtModel.create(context, \"model.tflite\", wantNpu = false)\nval scores = model.run(bitmap.toModelInput(224))\nval bridge = SupportBridge(model.model, \"images\", \"Softmax\")\nval image = imageProcessor.process(TensorImage.fromBitmap(bitmap))  \u002F\u002F LiteRT Support, as before\nval output = model.run({ bridge.write(it, image) }, { bridge.read(it, intArrayOf(1, 1000), DataType.FLOAT32) })\nval scoresByLabel = TensorLabel(labels, output).mapWithFloatValue\n```\nOther one-to-one replacements: `FileUtil.loadMappedFile(context, name)` + `Interpreter(buffer, options)` becomes `CompiledModel.create(context.assets, name, options, env)` (`loadMappedFile` itself stays for `MetadataExtractor`); `Interpreter.Options().addDelegate(GpuDelegate())` becomes `CompiledModel.Options(Accelerator.GPU, Accelerator.CPU)` (GPU alone makes `create` throw when an op is left undelegated, `Some ops are not accelerated. Add kLiteRtHwAcceleratorCpu …` from `LiteRtCompiledModelT::Create` in `compiled_model.cc`, and when the GPU cannot compile the graph at all, `Failed to compile model`; the legacy delegate left such ops on the CPU. GPU + CPU can still throw on a graph the GPU cannot compile, which is why the template keeps a CPU step after it); `interpreter.run(inputByteBuffer, outputByteBuffer)` becomes `writeFloat` \u002F `run` \u002F `readFloat` on the model's buffers (`writeInt8` \u002F `readInt8` for int8 and uint8 tensors).\n\n### Step 5: Two-Stage Fast Verification Gate (Karpathy Self-Test)\nTo maximize execution speed:\n* **Stage 1 (Refactoring Gate)**: Run fast incremental compile checks only (`.\u002Fgradlew compileDebugKotlin compileDebugAndroidTestKotlin` or `.\u002Fgradlew assembleDebug assembleDebugAndroidTest`) to verify syntax in seconds. Done when both source sets compile and the only `org.tensorflow.lite` imports left are `DataType` and `org.tensorflow.lite.schema.*` (`grep -rn 'import org.tensorflow.lite' app\u002Fsrc | grep -v -E 'lite.DataType|lite.schema'` prints nothing: no `Interpreter`, no delegate, no `org.tensorflow.lite.support`).\n* **Stage 2 (Final Verification Gate)**: Copy `templates\u002FMigrationValidationTest.kt` into `app\u002Fsrc\u002FandroidTest\u002Fjava\u002F\u003Cpackage>\u002F` (model in `app\u002Fsrc\u002Fmain\u002Fassets\u002F`), build (`.\u002Fgradlew assembleDebug assembleDebugAndroidTest`) and run it on a connected device or emulator (`.\u002Fgradlew connectedDebugAndroidTest`); `testDebugUnitTest` runs only `src\u002Ftest`.\n  * The test runs the Step 0 input through the app's preprocessing (its `ImageProcessor` on LiteRT Support, exposed as a function such as `preprocess(bitmap): TensorImage`, or the function that replaced it, e.g. `Bitmap.toModelInput`) into the model's first input on the CPU (`CompiledModel.Options(Accelerator.CPU)`) and compares the first output with the golden file: max abs diff below 1e-3 when the file holds every output value (a tolerance for outputs of order 1; scale it for larger outputs), or the same top-1 index when it holds one (a last resort: a wrong normalization can keep the top-1).\n  * Keep the test's own CPU model rather than calling `LiteRtModel`, which tries NPU and GPU first. Done when it passes on a device and the app's own entry point has run there once (the gate executes neither the cascade nor the app class); with no device attached, stop after Stage 1 and open the PR as a draft that says Stage 2 did not run.\n\n---\n\n## 2. Phase 2: Encouraged Performance Upgrades\n\nOnce Phase 1 compiles and passes self-testing, the agent applies high-value performance features:\n\n### Upgrade 2.A: Off-main-thread execution on one serial dispatcher\nThe Kotlin CompiledModel API has no `runAsync`. On the CPU, `run()` blocks until the outputs are ready; on the GPU it can return before the GPU finishes, and `readFloat()` blocks until it has. Keep the UI responsive by running create, run and read on one serial dispatcher from a coroutine, and reuse the buffers created once:\n```kotlin\nprivate val modelDispatcher = Dispatchers.IO.limitedParallelism(1)\nsuspend fun infer(input: FloatArray): FloatArray = withContext(modelDispatcher) {\n    inputBuffers[0].writeFloat(input)\n    compiledModel.run(inputBuffers, outputBuffers)\n    outputBuffers[0].readFloat()\n}\n```\nTime `run()` and `readFloat()` together; timing `run()` alone under-reports GPU work. `limitedParallelism(1)` serializes the calls; it does not pin them to one thread.\n\n### Upgrade 2.B: Buffer reuse and zero-copy interop\nIn Kotlin, tensor buffers come from the model (`createInputBuffers()` \u002F `createOutputBuffers()`, or `createInputBuffer(name)`), are filled with `writeFloat` \u002F `writeInt8`, and are reused for every inference; there is no `TensorBuffer.createFromAhwb` in the Kotlin API. `AHardwareBuffer` zero-copy interop is part of the C++ API (`litert::TensorBuffer::CreateFromAhwb` in `litert\u002Fcc\u002Flitert_tensor_buffer.h`), so a camera pipeline that needs it runs the whole inference from C++ (Step 3): there is no supported way to hand a C++ buffer to Kotlin `run()`.\n```kotlin\nval inputBuffers = compiledModel.createInputBuffers()\nval outputBuffers = compiledModel.createOutputBuffers()\ncompiledModel.run(inputBuffers, outputBuffers)\ninputBuffers.forEach { it.close() }\noutputBuffers.forEach { it.close() }\ncompiledModel.close()\n```\nClose the buffers, then the model, then the `Environment` if the app created one and no other model uses it (the model closes only an environment it created itself; `templates\u002FLiteRtModel.kt` keeps one per process open).\n\n### Upgrade 2.C: NPU JIT Acceleration & Conditional INT8 Quantization\n1. **Conditional INT8 Quantization**: If NPU JIT is selected and the user opted in, run AI Edge Quantizer (`aeq`) to generate `model_int8.tflite` in `assets\u002F`:\n   ```python\n   from ai_edge_quantizer import quantizer, recipe\n   qt = quantizer.Quantizer(\"src\u002Fmain\u002Fassets\u002Fmodel.tflite\", recipe.static_wi8_ai8())\n   calibration = qt.calibrate({\"serving_default\": representative_inputs})  # an iterable of {input_name: ndarray}\n   qt.quantize(calibration).export_model(\"src\u002Fmain\u002Fassets\u002Fmodel_int8.tflite\")\n   ```\n   (ai-edge-quantizer 0.9.0 names; it pins `ai-edge-litert` 2.2.0 on the host, which says nothing about the app's runtime version. `static_wi8_ai8` is the full-integer recipe that the `accuracy-safe-quantization` skill in this repo names for NPU targets; `recipe.dynamic_wi8_afp32()` needs no calibration but keeps float32 activations. Then point the app at `model_int8.tflite` and rerun the Stage 2 gate with a golden of the top-1 index only; the 1e-3 bound is for the like-for-like float model.)\n2. **NPU JIT Runtime Bundling**: Package vendor shared libraries in `app\u002Fsrc\u002Fmain\u002FjniLibs\u002Farm64-v8a\u002F` (`libLiteRtDispatch_Qualcomm.so`, `libLiteRtCompilerPlugin_Qualcomm.so`, `libQnnHtp.so`, `libQnnSystem.so`, etc.); `BuiltinNpuAcceleratorProvider` reads them from `context.applicationInfo.nativeLibraryDir`. Compiled artifacts are cached under `context.cacheDir` by `Environment.create(context, …)` (`enableCompilerCache` defaults to true).\n3. **Qualcomm FastRPC Permission**: The `litert-api` AAR's manifest (pulled in by `litert`; in 2.2.0 both AARs carry it) already declares `\u003Cuses-native-library android:name=\"libcdsprpc.so\" android:required=\"false\" \u002F>` (with the OpenCL and Google Tensor entries) and manifest merging brings it into the app; add it by hand only if merging is disabled.\n4. **Environment & Fallback Cascade**: Create the `Environment` with `BuiltinNpuAcceleratorProvider` (on a supported device it sets `DispatchLibraryDir` and `CompilerPluginLibraryDir` itself) and implement the Kotlin `NPU -> GPU -> CPU` cascade \u002F C++ fail-fast pipeline.\n\n---\n\n## 3. Phase 3: Automated Pull Request Provisioning\n\nOnce self-testing succeeds:\n* **GitHub Pull Request**: Create a clean git commit, exclude `local.properties` and `.gradle\u002F`, and run `gh pr create` with an attached before\u002Fafter summary diff and test execution logs.\n","# Skill: LiteRT Compiled Model Migration SKILL\n\n## Description\nThis skill guides an AI agent to rapidly migrate an Android application from legacy TensorFlow Lite (TFLite) to the modern LiteRT CompiledModel API (2.x) in **Open Source GitHub repositories**. It prioritizes a high-speed, 1st-pass **\"Like for Like\" baseline migration** with automated self-testing, and encourages advanced performance upgrades including **off-main-thread execution with buffer reuse** and **NPU JIT compilation**.\n\n## Read first: what the Kotlin CompiledModel API (`com.google.ai.edge.litert`, 2.3.0; 2.2.0 has the same API) has\n\n- `CompiledModel.create(context.assets, assetName, CompiledModel.Options(Accelerator.CPU), env)` and `create(filePath, options, env)`; `Options` takes one or more of `Accelerator.CPU` \u002F `GPU` \u002F `NPU` (e.g. `Options(Accelerator.GPU, Accelerator.CPU)`); `env` is `Environment.create(context)` (optional; enables the compiler cache) or `Environment.create(context, BuiltinNpuAcceleratorProvider(context))` for the NPU. Nothing takes a ByteBuffer or a mapped file.\n- Buffers come from the model (`createInputBuffers()` \u002F `createOutputBuffers()`, `List\u003CTensorBuffer>`; `writeFloat(FloatArray)` \u002F `writeInt8(ByteArray)` \u002F `writeInt` \u002F `writeLong`, `readFloat()` and friends; create them once). `run(inputs, outputs)` is synchronous on the CPU; on the GPU it can return before the GPU finishes and `read*()` waits; there is no callback API. `CompiledModel`, `TensorBuffer` and `Environment` are `AutoCloseable`: close buffers, then the model, then an `Environment` the app created.\n- `CompiledModel.Options()` with no accelerator compiles, but `create` then throws `LiteRtException`. `Interpreter`, `GpuDelegate`, `NnApiDelegate` and the Support library's `Model` (`com.google.ai.edge.litert.support.model.Model`, which runs on `InterpreterApi`) do not appear in migrated code; the rest of LiteRT Support does, under `com.google.ai.edge.litert.support` (Step 1), with `org.tensorflow.lite.DataType` as the type its classes take. The `litert` AAR also contains `org.tensorflow.lite.Interpreter`, so leftover Interpreter code compiles (all but `setUseNNAPI`, which 2.x does not have) and the Stage 1 import check is what catches it. `templates\u002FLiteRtModel.kt` compiles against the 2.3.0 and the 2.2.0 artifacts; start from it.\n\n---\n\n## 0. Automatic Discovery & Upfront Planning\n\nBefore writing code, the agent MUST inspect the project workspace and present the upfront planning interview to align migration parameters:\n\n### A. Automatic Workspace & Toolchain Discovery\nThe agent must automatically inspect the repository structure:\n1. **Ecosystem & Build Engine**:\n   * **Gradle Build System**: Detected by `build.gradle`, `build.gradle.kts`, or `settings.gradle`. -> Enable **Gradle & GitHub PR Workflow**.\n2. **Language & JNI Toolchain**:\n   * **Native C++ \u002F NDK**: Detected if `CMakeLists.txt`, `Android.mk`, or `*.cpp` files exist. -> Enable **C++ \u002F JNI Migration Rules**.\n   * **Pure Kotlin \u002F Java**: Default to **JVM \u002F Android SDK Migration Rules**.\n\n### B. Upfront User Interview (Questions Asked Prior to Migration)\n\nThe agent must present the following review options to the user:\n\n```\nBefore initiating the LiteRT Compiled Model Migration, please confirm your project preferences:\n\n1. Model Workload & Domain:\n   What type of data does this application process?\n   - [A] Vision (Images \u002F Video \u002F Camera Feeds) -> Enables the camera-frame recipe: preprocess into a reused input buffer via writeFloat \u002F writeInt8 (AHardwareBuffer interop is C++-only).\n   - [B] Audio (Speech \u002F Sound Classification) -> Enables the streaming FloatArray recipe (writeFloat per window).\n   - [C] Text \u002F NLP \u002F GenAI -> Enables the token-id recipe (writeInt \u002F writeLong into the model's input buffers).\n\n2. Hardware Acceleration & Conditional INT8 Quantization:\n   Do you want to enable NPU hardware acceleration via JIT on-device compilation?\n   - [A] Yes (Recommended - replaces deprecated NNAPI; needs the vendor libraries of Upgrade 2.C on a supported SoC) [Default]\n         * If the app uses a Float32 model: Would you like to generate an INT8 integer-quantized model via AI Edge Quantizer for peak NPU speed, or run the original Float32 model?\n           -> Option A.1: Convert to INT8 (Generates model_int8.tflite with int8 weights and activations; needs a few representative inputs for calibration) [Default]\n           -> Option A.2: Keep Float32 (Runs baseline float model directly on NPU)\n   - [B] No (GPU and CPU acceleration only)\n\n3. Encouraged Performance Upgrades:\n   Should the agent upgrade the calling code to use LiteRT's advanced features?\n   - [A] Yes (Move inference off the main thread and reuse buffers) [Default]\n   - [B] No (Keep strict 1-to-1 synchronous baseline execution)\n\n4. Automated Pull Request Provisioning:\n   Should the agent automatically stage, commit, and create a GitHub PR when self-testing passes?\n   - [A] Yes [Default] (Attaches verification test logs and before\u002Fafter summary diff)\n   - [B] No (Keep changes local in current working branch)\n```\nWith no user to answer (CI, batch runs): take Q1 from the code, Q2 [A] only when the vendor libraries of Upgrade 2.C are already in the repo (otherwise [B]), Float32 unless calibration inputs exist, and the defaults of Q3 and Q4 with the PR opened as a draft; record the choices in the PR description.\nToday the runtime is the standalone `com.google.ai.edge.litert:litert` AAR: no LiteRT artifact for Google Play services is on Google Maven as of October 2026 (only the `play-services-tflite-*` Interpreter artifacts exist).\n\n> [!IMPORTANT]\n> **LiteRT Support (`litert-support` 2.3.0)**: an app on the TensorFlow Lite Support Library keeps it. The library now ships as LiteRT Support, with the same classes, methods and behavior; the migration is two steps of Step 1, swap the Gradle coordinates and rename the package `org.tensorflow.lite.support` to `com.google.ai.edge.litert.support` (its guide: https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002FLiteRT\u002Fblob\u002Fmain\u002Flitert\u002Fsupport_lib\u002FMIGRATION_GUIDE.md). `ImageProcessor`, `ResizeOp`, `NormalizeOp`, `TensorImage`, `TensorLabel`, `FileUtil` and `MetadataExtractor` stay as they are. The one class replaced is its `Model`, which runs on the Interpreter API: it becomes `CompiledModel` like `Interpreter` (Step 4), with `templates\u002FSupportBridge.kt` between the Support tensors and the model's buffers. An app that never used the Support library does not add it; `Bitmap.toModelInput` in `templates\u002FLiteRtModel.kt` is its preprocessing.\n\n---\n\n## 1. Phase 1: \"Like for Like\" Baseline Migration (1st Pass Success)\n\nPhase 1 prioritizes functional equivalence, fast compilation, and immediate 1st pass self-test success.\n\n### Step 0: Capture the Golden Output\nBefore Step 1 changes any dependency, with the legacy runtime and preprocessing still in the project (no device attached: skip Step 0, stop after Stage 1, and open the PR as a draft that says so):\n* Define one fixed input: for a vision app a deterministic bitmap (`fixedBitmap` in `templates\u002FGoldenCaptureTest.kt`, or a small image file in `app\u002Fsrc\u002FandroidTest\u002Fassets\u002F`), otherwise a generated array; never a camera frame. A bitmap of the model's input size with rotation 0 leaves the resize and the rotation out of the gate: use another size (and aspect ratio), and the rotation the camera path passes, in the capture and in Stage 2 alike.\n* Declare the `androidx.test` dependencies and `testInstrumentationRunner` (Stage 2 needs them too), copy `templates\u002FGoldenCaptureTest.kt` into `app\u002Fsrc\u002FandroidTest\u002Fjava\u002F\u003Cpackage>\u002F`, make it call the app's existing inference entry point (the class the UI calls, with its own preprocessing) on the fixed input on the CPU (no GPU or NNAPI delegate, XNNPACK at its default); when that entry point returns only a thresholded or sorted list, first give the class a function returning the raw output and one returning the preprocessed input (`preprocess(bitmap)`: Stage 2 calls it too), still on the legacy runtime. Then run the four commands in its header: they install both APKs, run the test on the device, and pull `golden.txt` into `app\u002Fsrc\u002FandroidTest\u002Fassets\u002Fgolden\u002Foutput.txt`. A raw tensor fed straight to the model is not a golden output: it leaves the preprocessing out of the gate.\n* Delete the capture test. Stage 2 compares against the file, so the test APK never needs `org.tensorflow:tensorflow-lite`.\n\n### Step 1: Clean & Modernize Dependencies\n\nInspect `libs.versions.toml` and `build.gradle.kts`:\n* **Remove Legacy & Deprecated**:\n  * `org.tensorflow:tensorflow-lite` \u002F `tensorflow-lite-gpu` \u002F `tensorflow-lite-select-tf-ops` *(Legacy Flex Delegate — see Deprecated API Remediation below)*, and every other `org.tensorflow:tensorflow-lite*` line, including ones other libraries pull in (`.\u002Fgradlew :app:dependencies` lists them): the LiteRT artifacts carry the `org.tensorflow.lite` runtime classes and the model schema under their original names, and mixing old and new artifacts fails the build with duplicate classes. `com.google.ai.edge.litert:litert-gpu` **1.x** goes too *(the renamed TFLite GPU delegate, last 1.4.2; `litert-gpu:2.3.0` is the GPU accelerator of the CompiledModel runtime and is added below)*, and `com.google.ai.edge.litert:litert` **1.x** (the renamed Interpreter runtime, e.g. `samples\u002Flitert_interpreter\u002F*` on 1.0.0) becomes `litert:2.3.0` below.\n* **Swap the Support library coordinates** (apps on `org.tensorflow.lite.support.*`): `org.tensorflow:tensorflow-lite-support` or `litert-support` 1.x becomes `implementation(\"com.google.ai.edge.litert:litert-support:2.3.0\")` (the Support API plus the LiteRT runtime: it depends on `litert:2.3.0`); `tensorflow-lite-support-api` becomes `litert-support-api:2.3.0` (the API alone, the runtime being the `litert` line below); `tensorflow-lite-metadata` or `litert-metadata` 1.x becomes `litert-metadata:2.3.0` (`MetadataExtractor`). Then rename the package in every source file and in R8\u002FProGuard rules (`-keep class org.tensorflow.lite.support.**`): `grep -rl 'org\\.tensorflow\\.lite\\.support' --include='*.java' --include='*.kt' app\u002Fsrc\u002F | xargs sed -i 's\u002Forg\\.tensorflow\\.lite\\.support\u002Fcom.google.ai.edge.litert.support\u002Fg'` (GNU sed; on macOS, `sed -i ''`). `org.tensorflow.lite.DataType`, the type the Support classes take, keeps its name.\n* **Add Modern LiteRT**:\n  * *Standalone*: `implementation(\"com.google.ai.edge.litert:litert:2.3.0\")` and `implementation(\"com.google.ai.edge.litert:litert-gpu:2.3.0\")` in Kotlin DSL (`implementation 'com.google.ai.edge.litert:litert:2.3.0'` and `'…:litert-gpu:2.3.0'` in Groovy). `litert` pulls in `litert-api` and sets minSdk 24. `litert-support:2.3.0` depends on `litert:2.3.0` and raises a `litert:2.2.0` pin to 2.3.0 without a warning (Gradle resolves `litert:2.2.0 -> 2.3.0`), so pin 2.3.0 here. Since 2.3.0 the GPU accelerator (`libLiteRtClGlAccelerator.so`) ships in `litert-gpu`; in 2.2.0 it was inside `litert`. Without `litert-gpu`, `CompiledModel.Options(Accelerator.GPU, Accelerator.CPU)` creates and runs on the CPU with the log line `GPU accelerator could not be loaded and registered`, and `Options(Accelerator.GPU)` alone throws.\n* **Toolchain the 2.3.0 artifacts need**: `litert-api:2.3.0` depends on `androidx.lifecycle:lifecycle-runtime:2.10.0` (its POM), and its classes carry Kotlin 2.4 metadata (2.2.0: Kotlin 2.3). Set these before the first build on a project on AGP 8.3 \u002F Kotlin 1.9 (e.g. `samples\u002Flitert_interpreter\u002F*`), or each becomes a build error in turn: `compileSdk` 35 and AGP 8.6.0 (`checkDebugAarMetadata`), Gradle 8.7 (AGP 8.6.0), the Kotlin plugin 2.3 or newer (from 1.9 this is a plugin upgrade; `freeCompilerArgs += \"-Xskip-metadata-version-check\"` only lets a project already on 2.2 stay there, as `samples\u002Flitert\u002Fimage_segmentation\u002Fkotlin_cpu_gpu` does; 2.2 otherwise stops at `The binary version of its metadata is 2.4.0, expected version is 2.2.0`, and 2.2 is enough for the 2.2.0 artifacts), and with Kotlin 2.x a Compose app needs the `org.jetbrains.kotlin.plugin.compose` plugin in place of `composeOptions`. On AGP 9 (built-in Kotlin) the Kotlin version is pinned with `id(\"org.jetbrains.kotlin.android\") version \"2.3.21\" apply false` in the root plugins block.\n* **Labels and metadata**: `FileUtil.loadLabels` and `MetadataExtractor` work as before on the 2.3.0 artifacts. An app without the Support library reads the label file from assets: a `.tflite` with metadata is a zip, so extract it once (`unzip -o model.tflite labels.txt -d app\u002Fsrc\u002Fmain\u002Fassets\u002F`; `unzip -l` lists the name).\n* **IDE Portability**: Remove hardcoded `org.gradle.java.home` from `gradle.properties` and exclude `local.properties`.\n* **Kotlin Compiler DSL**: Use top-level `kotlin { compilerOptions { ... } }` outside `android { ... }`: `kotlinOptions { jvmTarget = \"1.8\" }` becomes `kotlin { compilerOptions { jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8) } }`.\n\n### Step 2: Deprecated API & Delegate Remediation\n\nThe agent must audit and replace all deprecated delegate APIs:\n\n1. **NNAPI Delegate (`NnApiDelegate`, `NnApiDelegate.Options`, `setUseNNAPI(true)`)**:\n   * **Status**: NNAPI is deprecated since Android 15, and the LiteRT 2.x Java\u002FKotlin API has no NNAPI entry point (`Interpreter.Options` has no `setUseNNAPI`).\n   * **Remediation**: Remove `org.tensorflow.lite.nnapi.NnApiDelegate` imports. Replace with `CompiledModel.Options(Accelerator.NPU)` and `Environment.create(context, BuiltinNpuAcceleratorProvider(context))` when `BuiltinNpuAcceleratorProvider(context).isDeviceSupported()` is true (NPU-only options compile as NPU + CPU, so unsupported ops fall back to the CPU). In 2.3.0 `isDeviceSupported()` is true on every Qualcomm, MediaTek or Samsung SoC from Android 12 and on Google Tensor from Android 16 (2.2.0 used a SoC list), and without the vendor libraries `create` still returns: the runtime logs `Failed to apply compiler plugins: No compiler plugin found` (2.2.0 adds `Failed to initialize Dispatch API`) and compiles for the CPU, so a cascade's reported accelerator reads NPU while the CPU runs. Implement an explicit `NPU -> GPU -> CPU` fallback cascade (try each `CompiledModel.create`, catch `LiteRtException`) to handle non-NPU hardware smoothly. Under Q2 [B], an NNAPI choice in the app's UI becomes the GPU option (`Options(Accelerator.GPU, Accelerator.CPU)`).\n\n2. **Flex Delegate (`FlexDelegate`, `org.tensorflow.lite.flex`, `select-tf-ops`)**:\n   * **Status**: Interpreter-only: the Flex delegate ships in the legacy `tensorflow-lite-select-tf-ops` artifact (68 MB for arm64 in 2.16.1) and in no LiteRT 2.x artifact, so a model with Select TF ops needs the re-export below.\n   * **Remediation**:\n     * Remove `org.tensorflow:tensorflow-lite-select-tf-ops` from `build.gradle.kts`.\n     * Find Flex ops by FlatBuffer inspection (custom ops whose `custom_code` starts with `Flex`); `check_gpu_compatibility` in `utilities\u002Flitert_gpu_toolkit` (this repository) reports such a model as a compile failure, not op by op.\n     * Replace Flex ops by re-exporting the model without them (LiteRT-Torch for PyTorch sources; the TensorFlow converter without `SELECT_TF_OPS`), or, if custom C++ math is required, implement a `litert::CustomOpKernel` (`litert\u002Fcc\u002Flitert_custom_op_kernel.h`, shipped in `litert_cc_sdk.zip`; guide: https:\u002F\u002Fdevelopers.google.com\u002Fedge\u002Flitert\u002Fnext\u002Fcustom_op_dispatcher).\n\n### Step 3: Native Build Toolchain (`CMakeLists.txt` \u002F NDK)\nFor native C++ modules, use the C++ SDK the LiteRT docs describe (https:\u002F\u002Fdevelopers.google.com\u002Fedge\u002Flitert\u002Fnext\u002Fandroid_cpp_sdk): download `litert_cc_sdk.zip` from the LiteRT GitHub release that matches the AAR version (https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002FLiteRT\u002Freleases\u002Fdownload\u002Fv2.2.0\u002Flitert_cc_sdk.zip; 2.3.0 has no GitHub release as of 2026-10-07, so a native module stays on the 2.2.0 AAR and zip until the matching zip exists, and an app with both a native module and the Support library waits for that zip, since `litert-support:2.3.0` raises the runtime to 2.3.0), copy `libLiteRt.so` from the AAR's `jni\u002Farm64-v8a\u002F` into its `litert_cc_sdk\u002F` directory (`LITERT_CC_SDK` below), and link the `litert_cc_api` target. The AAR ships no headers or prefab package, and `liblitert_jni.so` is the Kotlin binding, not a C++ target:\n```cmake\n# Replace legacy tensorflowlite_jni with the LiteRT C++ SDK\nadd_subdirectory(\"${LITERT_CC_SDK}\" \"${LITERT_CC_SDK}\u002Fbuild\")\ninclude_directories(\"${LITERT_CC_SDK}\")\n\ntarget_link_libraries(your_native_lib\n    litert_cc_api\n    android\n    log\n)\n```\n\n### Step 4: API & Lifecycle Refactoring (Rewrite Initialization & Dynamic Signatures)\n\n> [!IMPORTANT]\n> **Never Simple Swap**: Do **NOT** merely perform a search-and-replace of the `Interpreter` class. Rewrite the model initialization logic to instantiate `CompiledModel` with an explicit hardware fallback cascade (`NPU -> GPU -> CPU`). When NPU is selected, prioritize NPU JIT compilation by instantiating an explicit `Environment` object (`Environment.create(context, BuiltinNpuAcceleratorProvider(context))`) and passing it to `CompiledModel.create`; on a supported device the provider itself sets `Environment.Option.DispatchLibraryDir` and `Environment.Option.CompilerPluginLibraryDir` to `context.applicationInfo.nativeLibraryDir`, and the `context` overload enables the compiler cache under `context.cacheDir`.\n\n| Legacy TFLite API | Modern LiteRT V2 Drop-in Replacement |\n|---|---|\n| `org.tensorflow.lite.Interpreter` | `com.google.ai.edge.litert.CompiledModel` |\n| `Interpreter(modelFile, options)`; LiteRT Support's `Model.createModel(context, name, options)` | `CompiledModel.create(context.assets, assetName, options, env)` or `create(filePath, options, env)`; no ByteBuffer overload *(via NPU Environment & Fallback Cascade)* |\n| `interpreter.run(input, output)` | `compiledModel.run(inputBuffers, outputBuffers)` (both `List\u003CTensorBuffer>` from `createInputBuffers()` \u002F `createOutputBuffers()`) |\n| `interpreter.runForMultipleInputsOutputs(inputs, outputs)`; Support `model.run(inputs, outputs)` | `compiledModel.run(inputBuffers, outputBuffers)` |\n| `interpreter.runSignature(inputs, outputs, key)` | `compiledModel.run(inputMap, outputMap, key)` (`Map\u003CString, TensorBuffer>`) |\n| `Interpreter.Options().setNumThreads(n)` | `options.cpuOptions = CompiledModel.CpuOptions(numThreads = n)` on a fresh `Options(Accelerator.CPU)`, not the shared `Options.CPU` |\n| `interpreter.resizeInput(...)` | none in 2.3.0 (`resizeInputTensor` is on LiteRT main after 2.3.0; the C++ API has `ResizeInputTensor`) |\n| `GpuDelegate()` \u002F `NnApiDelegate()` | `CompiledModel.Options(Accelerator.GPU, Accelerator.CPU)` \u002F `CompiledModel.Options(Accelerator.NPU)` (NPU-only compiles as NPU + CPU) |\n| `org.tensorflow.lite.flex.FlexDelegate` | none: re-export the model without Select TF ops, or a C++ `CustomOpKernel` (Step 2) |\n| `interpreter.getInputTensor(0).shape()` | `compiledModel.getInputTensorType(inputName).layout?.dimensions`: by name only, no index or list call; `args_0` \u002F `output_0` for LiteRT-Torch exports, the graph's tensor names otherwise (`images` \u002F `Softmax` in the EfficientNet samples; print `interpreter.getInputTensor(0).name()` in the Step 0 capture test) |\n| `imageProcessor.process(TensorImage.fromBitmap(bitmap))` then `interpreter.run(tensorImage.buffer, out)` | the same `ImageProcessor`, on `com.google.ai.edge.litert.support.image`; `bridge.write(inputBuffers[0], tensorImage)` (`templates\u002FSupportBridge.kt`: `writeFloat(tensorImage.tensorBuffer.floatArray)` for a float image, `writeInt8` for uint8, after a size check) |\n| Support `TensorBuffer.createFixedSize(shape, DataType.FLOAT32)` as the output, then `TensorLabel` \u002F `TensorProcessor` | `bridge.read(outputBuffers[0], shape, DataType.FLOAT32)`; `TensorLabel` \u002F `TensorProcessor` unchanged |\n| `#include \"tensorflow\u002Flite\u002Finterpreter.h\"` | `#include \"litert\u002Fcc\u002Flitert_compiled_model.h\"` |\n| `#include \"tensorflow\u002Flite\u002Fc\u002Fc_api.h\"` | `#include \"litert\u002Fc\u002Flitert_compiled_model.h\"` |\n\nReference implementation: `templates\u002FLiteRtModel.kt` (needs `androidx.core:core-ktx` and `org.jetbrains.kotlinx:kotlinx-coroutines-android`; it already carries Upgrades 2.A and 2.B, and closes everything it created when a step after `CompiledModel.create` throws). Copy it next to the app's inference class, replace the package, and keep its shape:\n* `LiteRtModel.create(context, assetName, wantNpu, wantGpu = true, numThreads = null)` is a `suspend` factory that runs on the model's own serial dispatcher: it takes the process-wide `Environment` (created once, with `BuiltinNpuAcceleratorProvider` when the first caller wants the NPU and `isDeviceSupported()`), tries `CompiledModel.create` on NPU, then GPU + CPU, then CPU (`wantGpu = false` skips the GPU step for an app whose CPU setting means the CPU alone; `numThreads` is the legacy `setNumThreads`), catching `LiteRtException`, and creates the buffers once.\n* `suspend fun run(FloatArray): FloatArray` does `writeFloat` \u002F `run` \u002F `readFloat` on the same dispatcher; `run(write, read)` takes two lambdas over the input and output buffer for the Support bridge below; `runSync(input)` is the entry point for Java callers and for Q3 [B] (the synchronous baseline), from a background thread; `close()` closes the buffers, then the model (the shared `Environment` stays open: creating one loads the accelerator libraries, and one created and closed per model reloads them on every load), and is called after the last `run` has returned.\n* `accelerator` is the step that did not throw, not proof that every op runs there: NPU-only options compile as NPU + CPU, and a missing or failing compiler plugin is logged and skipped inside `create`; pass `wantNpu = true` only with the libraries of Upgrade 2.C in place.\n* `Bitmap.toModelInput(size)` in the same file is the preprocessing of an app without the Support library: `androidx.core.graphics.scale` and one loop writing `(channel - mean) \u002F std` into a `FloatArray`, with the legacy `NormalizeOp(mean, std)` values (127.5 \u002F 127.5 in the template; change them to the app's). An app that keeps LiteRT Support leaves its `ImageProcessor` as it is, deletes `Bitmap.toModelInput`, and copies `templates\u002FSupportBridge.kt` too: `SupportBridge(model, inputName, outputName)`, created once after `create`, reads the byte size of both tensors, and its `write` \u002F `read` move a `TensorImage` or Support `TensorBuffer` into the model's buffers and back, and refuse one of another size or type (the Kotlin API itself accepts a shorter array, or uint8 bytes in a float input, without an error). Both libraries name a class `TensorBuffer`; the file imports the Support one as `SupportTensorBuffer`.\n```kotlin\nval model = LiteRtModel.create(context, \"model.tflite\", wantNpu = false)\nval scores = model.run(bitmap.toModelInput(224))\nval bridge = SupportBridge(model.model, \"images\", \"Softmax\")\nval image = imageProcessor.process(TensorImage.fromBitmap(bitmap))  \u002F\u002F LiteRT Support, as before\nval output = model.run({ bridge.write(it, image) }, { bridge.read(it, intArrayOf(1, 1000), DataType.FLOAT32) })\nval scoresByLabel = TensorLabel(labels, output).mapWithFloatValue\n```\nOther one-to-one replacements: `FileUtil.loadMappedFile(context, name)` + `Interpreter(buffer, options)` becomes `CompiledModel.create(context.assets, name, options, env)` (`loadMappedFile` itself stays for `MetadataExtractor`); `Interpreter.Options().addDelegate(GpuDelegate())` becomes `CompiledModel.Options(Accelerator.GPU, Accelerator.CPU)` (GPU alone makes `create` throw when an op is left undelegated, `Some ops are not accelerated. Add kLiteRtHwAcceleratorCpu …` from `LiteRtCompiledModelT::Create` in `compiled_model.cc`, and when the GPU cannot compile the graph at all, `Failed to compile model`; the legacy delegate left such ops on the CPU. GPU + CPU can still throw on a graph the GPU cannot compile, which is why the template keeps a CPU step after it); `interpreter.run(inputByteBuffer, outputByteBuffer)` becomes `writeFloat` \u002F `run` \u002F `readFloat` on the model's buffers (`writeInt8` \u002F `readInt8` for int8 and uint8 tensors).\n\n### Step 5: Two-Stage Fast Verification Gate (Karpathy Self-Test)\nTo maximize execution speed:\n* **Stage 1 (Refactoring Gate)**: Run fast incremental compile checks only (`.\u002Fgradlew compileDebugKotlin compileDebugAndroidTestKotlin` or `.\u002Fgradlew assembleDebug assembleDebugAndroidTest`) to verify syntax in seconds. Done when both source sets compile and the only `org.tensorflow.lite` imports left are `DataType` and `org.tensorflow.lite.schema.*` (`grep -rn 'import org.tensorflow.lite' app\u002Fsrc | grep -v -E 'lite.DataType|lite.schema'` prints nothing: no `Interpreter`, no delegate, no `org.tensorflow.lite.support`).\n* **Stage 2 (Final Verification Gate)**: Copy `templates\u002FMigrationValidationTest.kt` into `app\u002Fsrc\u002FandroidTest\u002Fjava\u002F\u003Cpackage>\u002F` (model in `app\u002Fsrc\u002Fmain\u002Fassets\u002F`), build (`.\u002Fgradlew assembleDebug assembleDebugAndroidTest`) and run it on a connected device or emulator (`.\u002Fgradlew connectedDebugAndroidTest`); `testDebugUnitTest` runs only `src\u002Ftest`.\n  * The test runs the Step 0 input through the app's preprocessing (its `ImageProcessor` on LiteRT Support, exposed as a function such as `preprocess(bitmap): TensorImage`, or the function that replaced it, e.g. `Bitmap.toModelInput`) into the model's first input on the CPU (`CompiledModel.Options(Accelerator.CPU)`) and compares the first output with the golden file: max abs diff below 1e-3 when the file holds every output value (a tolerance for outputs of order 1; scale it for larger outputs), or the same top-1 index when it holds one (a last resort: a wrong normalization can keep the top-1).\n  * Keep the test's own CPU model rather than calling `LiteRtModel`, which tries NPU and GPU first. Done when it passes on a device and the app's own entry point has run there once (the gate executes neither the cascade nor the app class); with no device attached, stop after Stage 1 and open the PR as a draft that says Stage 2 did not run.\n\n---\n\n## 2. Phase 2: Encouraged Performance Upgrades\n\nOnce Phase 1 compiles and passes self-testing, the agent applies high-value performance features:\n\n### Upgrade 2.A: Off-main-thread execution on one serial dispatcher\nThe Kotlin CompiledModel API has no `runAsync`. On the CPU, `run()` blocks until the outputs are ready; on the GPU it can return before the GPU finishes, and `readFloat()` blocks until it has. Keep the UI responsive by running create, run and read on one serial dispatcher from a coroutine, and reuse the buffers created once:\n```kotlin\nprivate val modelDispatcher = Dispatchers.IO.limitedParallelism(1)\nsuspend fun infer(input: FloatArray): FloatArray = withContext(modelDispatcher) {\n    inputBuffers[0].writeFloat(input)\n    compiledModel.run(inputBuffers, outputBuffers)\n    outputBuffers[0].readFloat()\n}\n```\nTime `run()` and `readFloat()` together; timing `run()` alone under-reports GPU work. `limitedParallelism(1)` serializes the calls; it does not pin them to one thread.\n\n### Upgrade 2.B: Buffer reuse and zero-copy interop\nIn Kotlin, tensor buffers come from the model (`createInputBuffers()` \u002F `createOutputBuffers()`, or `createInputBuffer(name)`), are filled with `writeFloat` \u002F `writeInt8`, and are reused for every inference; there is no `TensorBuffer.createFromAhwb` in the Kotlin API. `AHardwareBuffer` zero-copy interop is part of the C++ API (`litert::TensorBuffer::CreateFromAhwb` in `litert\u002Fcc\u002Flitert_tensor_buffer.h`), so a camera pipeline that needs it runs the whole inference from C++ (Step 3): there is no supported way to hand a C++ buffer to Kotlin `run()`.\n```kotlin\nval inputBuffers = compiledModel.createInputBuffers()\nval outputBuffers = compiledModel.createOutputBuffers()\ncompiledModel.run(inputBuffers, outputBuffers)\ninputBuffers.forEach { it.close() }\noutputBuffers.forEach { it.close() }\ncompiledModel.close()\n```\nClose the buffers, then the model, then the `Environment` if the app created one and no other model uses it (the model closes only an environment it created itself; `templates\u002FLiteRtModel.kt` keeps one per process open).\n\n### Upgrade 2.C: NPU JIT Acceleration & Conditional INT8 Quantization\n1. **Conditional INT8 Quantization**: If NPU JIT is selected and the user opted in, run AI Edge Quantizer (`aeq`) to generate `model_int8.tflite` in `assets\u002F`:\n   ```python\n   from ai_edge_quantizer import quantizer, recipe\n   qt = quantizer.Quantizer(\"src\u002Fmain\u002Fassets\u002Fmodel.tflite\", recipe.static_wi8_ai8())\n   calibration = qt.calibrate({\"serving_default\": representative_inputs})  # an iterable of {input_name: ndarray}\n   qt.quantize(calibration).export_model(\"src\u002Fmain\u002Fassets\u002Fmodel_int8.tflite\")\n   ```\n   (ai-edge-quantizer 0.9.0 names; it pins `ai-edge-litert` 2.2.0 on the host, which says nothing about the app's runtime version. `static_wi8_ai8` is the full-integer recipe that the `accuracy-safe-quantization` skill in this repo names for NPU targets; `recipe.dynamic_wi8_afp32()` needs no calibration but keeps float32 activations. Then point the app at `model_int8.tflite` and rerun the Stage 2 gate with a golden of the top-1 index only; the 1e-3 bound is for the like-for-like float model.)\n2. **NPU JIT Runtime Bundling**: Package vendor shared libraries in `app\u002Fsrc\u002Fmain\u002FjniLibs\u002Farm64-v8a\u002F` (`libLiteRtDispatch_Qualcomm.so`, `libLiteRtCompilerPlugin_Qualcomm.so`, `libQnnHtp.so`, `libQnnSystem.so`, etc.); `BuiltinNpuAcceleratorProvider` reads them from `context.applicationInfo.nativeLibraryDir`. Compiled artifacts are cached under `context.cacheDir` by `Environment.create(context, …)` (`enableCompilerCache` defaults to true).\n3. **Qualcomm FastRPC Permission**: The `litert-api` AAR's manifest (pulled in by `litert`; in 2.2.0 both AARs carry it) already declares `\u003Cuses-native-library android:name=\"libcdsprpc.so\" android:required=\"false\" \u002F>` (with the OpenCL and Google Tensor entries) and manifest merging brings it into the app; add it by hand only if merging is disabled.\n4. **Environment & Fallback Cascade**: Create the `Environment` with `BuiltinNpuAcceleratorProvider` (on a supported device it sets `DispatchLibraryDir` and `CompilerPluginLibraryDir` itself) and implement the Kotlin `NPU -> GPU -> CPU` cascade \u002F C++ fail-fast pipeline.\n\n---\n\n## 3. Phase 3: Automated Pull Request Provisioning\n\nOnce self-testing succeeds:\n* **GitHub Pull Request**: Create a clean git commit, exclude `local.properties` and `.gradle\u002F`, and run `gh pr create` with an attached before\u002Fafter summary diff and test execution logs.\n",{"name":5,"description":7},"main","9467001474dc4e072ebc588e5eb9b5fdcf63abbc","skills\u002Flitert-compiled-model-migration",134,"https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002Flitert-samples","https:\u002F\u002Fdevelopers.google.com\u002Fedge\u002Flitert","https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge","2026-11-12 20:56:09",{"source":8,"skillName":5,"commands":48,"prompt":58,"zipAvailable":59},[49,52,55],{"tool":50,"command":51},"npx","npx skills add google-ai-edge\u002Flitert-samples --skill litert-compiled-model-migration",{"tool":53,"command":54},"bunx","bunx skills add google-ai-edge\u002Flitert-samples --skill litert-compiled-model-migration",{"tool":56,"command":57},"pnpm","pnpm dlx skills add google-ai-edge\u002Flitert-samples --skill litert-compiled-model-migration","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002Flitert-samples\u002Fblob\u002Fmain\u002Fskills\u002Flitert-compiled-model-migration\u002FSKILL.md",true,[61,67,71,75,79,83,87,91,95,99,103,107,111,117,121,127,131,135],{"path":62,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":65,"sourceHtmlUrl":66},"assets\u002Fagency.md","ASSET","资产文件",7382,"https:\u002F\u002Fgithub.com\u002Fshenxingy\u002FClade\u002Fblob\u002Fmain\u002Fconfigs\u002Fskills\u002Fads-plan\u002Fassets\u002Fagency.md",{"path":68,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":69,"sourceHtmlUrl":70},"assets\u002Fb2b-enterprise.md",7045,"https:\u002F\u002Fgithub.com\u002Fshenxingy\u002FClade\u002Fblob\u002Fmain\u002Fconfigs\u002Fskills\u002Fads-plan\u002Fassets\u002Fb2b-enterprise.md",{"path":72,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":73,"sourceHtmlUrl":74},"assets\u002Fecommerce-creative.md",5735,"https:\u002F\u002Fgithub.com\u002Fshenxingy\u002FClade\u002Fblob\u002Fmain\u002Fconfigs\u002Fskills\u002Fads-plan\u002Fassets\u002Fecommerce-creative.md",{"path":76,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":77,"sourceHtmlUrl":78},"assets\u002Fecommerce.md",6495,"https:\u002F\u002Fgithub.com\u002Fshenxingy\u002FClade\u002Fblob\u002Fmain\u002Fconfigs\u002Fskills\u002Fads-plan\u002Fassets\u002Fecommerce.md",{"path":80,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":81,"sourceHtmlUrl":82},"assets\u002Ffinance.md",9030,"https:\u002F\u002Fgithub.com\u002Fshenxingy\u002FClade\u002Fblob\u002Fmain\u002Fconfigs\u002Fskills\u002Fads-plan\u002Fassets\u002Ffinance.md",{"path":84,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":85,"sourceHtmlUrl":86},"assets\u002Fgeneric.md",8042,"https:\u002F\u002Fgithub.com\u002Fshenxingy\u002FClade\u002Fblob\u002Fmain\u002Fconfigs\u002Fskills\u002Fads-plan\u002Fassets\u002Fgeneric.md",{"path":88,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":89,"sourceHtmlUrl":90},"assets\u002Fhealthcare.md",8299,"https:\u002F\u002Fgithub.com\u002Fshenxingy\u002FClade\u002Fblob\u002Fmain\u002Fconfigs\u002Fskills\u002Fads-plan\u002Fassets\u002Fhealthcare.md",{"path":92,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":93,"sourceHtmlUrl":94},"assets\u002Finfo-products.md",7164,"https:\u002F\u002Fgithub.com\u002Fshenxingy\u002FClade\u002Fblob\u002Fmain\u002Fconfigs\u002Fskills\u002Fads-plan\u002Fassets\u002Finfo-products.md",{"path":96,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":97,"sourceHtmlUrl":98},"assets\u002Flocal-service.md",6809,"https:\u002F\u002Fgithub.com\u002Fshenxingy\u002FClade\u002Fblob\u002Fmain\u002Fconfigs\u002Fskills\u002Fads-plan\u002Fassets\u002Flocal-service.md",{"path":100,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":101,"sourceHtmlUrl":102},"assets\u002Fmobile-app.md",7956,"https:\u002F\u002Fgithub.com\u002Fshenxingy\u002FClade\u002Fblob\u002Fmain\u002Fconfigs\u002Fskills\u002Fads-plan\u002Fassets\u002Fmobile-app.md",{"path":104,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":105,"sourceHtmlUrl":106},"assets\u002Freal-estate.md",7373,"https:\u002F\u002Fgithub.com\u002Fshenxingy\u002FClade\u002Fblob\u002Fmain\u002Fconfigs\u002Fskills\u002Fads-plan\u002Fassets\u002Freal-estate.md",{"path":108,"resourceType":63,"resourceTypeDesc":64,"sizeBytes":109,"sourceHtmlUrl":110},"assets\u002Fsaas.md",5934,"https:\u002F\u002Fgithub.com\u002Fshenxingy\u002FClade\u002Fblob\u002Fmain\u002Fconfigs\u002Fskills\u002Fads-plan\u002Fassets\u002Fsaas.md",{"path":112,"resourceType":113,"resourceTypeDesc":114,"sizeBytes":115,"sourceHtmlUrl":116},"prompt.md","REFERENCE","参考文档",7187,"https:\u002F\u002Fgithub.com\u002Fshenxingy\u002FClade\u002Fblob\u002Fmain\u002Fconfigs\u002Fskills\u002Fads-plan\u002Fprompt.md",{"path":118,"resourceType":113,"resourceTypeDesc":114,"sizeBytes":119,"sourceHtmlUrl":120},"README.md",2472,"https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002Flitert-samples\u002Fblob\u002Fmain\u002Fskills\u002Flitert-compiled-model-migration\u002FREADME.md",{"path":122,"resourceType":123,"resourceTypeDesc":124,"sizeBytes":125,"sourceHtmlUrl":126},"templates\u002FGoldenCaptureTest.kt","OTHER","其他",2730,"https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002Flitert-samples\u002Fblob\u002Fmain\u002Fskills\u002Flitert-compiled-model-migration\u002Ftemplates\u002FGoldenCaptureTest.kt",{"path":128,"resourceType":123,"resourceTypeDesc":124,"sizeBytes":129,"sourceHtmlUrl":130},"templates\u002FLiteRtModel.kt",8222,"https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002Flitert-samples\u002Fblob\u002Fmain\u002Fskills\u002Flitert-compiled-model-migration\u002Ftemplates\u002FLiteRtModel.kt",{"path":132,"resourceType":123,"resourceTypeDesc":124,"sizeBytes":133,"sourceHtmlUrl":134},"templates\u002FMigrationValidationTest.kt",5323,"https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002Flitert-samples\u002Fblob\u002Fmain\u002Fskills\u002Flitert-compiled-model-migration\u002Ftemplates\u002FMigrationValidationTest.kt",{"path":136,"resourceType":123,"resourceTypeDesc":124,"sizeBytes":137,"sourceHtmlUrl":138},"templates\u002FSupportBridge.kt",4327,"https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002Flitert-samples\u002Fblob\u002Fmain\u002Fskills\u002Flitert-compiled-model-migration\u002Ftemplates\u002FSupportBridge.kt",[140,152,174,204,223,236],{"skillNo":141,"name":142,"nameZh":6,"description":143,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":144,"categories":145,"keywords":146,"publishedAt":34},"01M6BY5T6RQENC1DMWZ8NZ8JFF","on-device-verification","Prove a converted or quantized LiteRT model on the actual device via the CompiledModel API - confirm GPU residency, compare device output against the source model, and diagnose device-only failures such as silent CPU fallback, whole-graph compile ceilings, and fp16 range breaks. Use after conversion or quantization, when device output is wrong or NaN, when a clean graph fails to compile only on device, or when GPU and CPU outputs are suspiciously identical.","https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002Flitert-samples\u002Fblob\u002Fmain\u002Fskills\u002Fon-device-verification\u002FSKILL.md",[],[147,26,148,31,149,27,150,19,18,151],"on device verification","graph","FP16","diagnose","gpu",{"skillNo":153,"name":154,"nameZh":6,"description":155,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":156,"categories":157,"keywords":158,"publishedAt":34},"01M6BY5F447DRN3YDJVRWDG9MZ","litert-google-tensor","Compiles LiteRT (.tflite) models ahead-of-time for Google Tensor TPUs (Tensor G5 on Pixel 10, Tensor G6 on Pixel 11) locally on Linux x86_64 or remotely via Google Colab (--colab on macOS, Windows, or ARM hosts), benchmarks them on a USB-attached Pixel with LiteRT's benchmark_model (NPU latency, peak memory, TPU tile time, TPU energy, optional CPU baseline), and packages compiled models for an Android Gradle app as a Google Play AI pack with the Tensor NPU runtime module and a Kotlin loader, applies it to the app and verifies it on a Pixel. Use when the user asks to compile, AOT-compile, or prepare a .tflite model for the Pixel TPU\u002FNPU, check whether a .tflite is already Tensor-compiled, measure on-device NPU performance of a compiled model, or package or deploy a compiled model into their Android app (or replace the one it ships). Don't use for Qualcomm, MediaTek, or Samsung NPUs, GPU-only benchmarking, LiteRT-LM or LLM (.litertlm) models, on-device JIT compilation, non-Gradle builds, or publishing to Google Play.","https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002Flitert-samples\u002Fblob\u002Fmain\u002Fskills\u002Flitert-google-tensor\u002FSKILL.md",[],[159,160,161,18,162,163,27,164,19,165,166,167,168,169,170,171,21,151,172,173],"google","litert google tensor","tensor","performance","kotlin","memory","windows","benchmark","linux","baseline","tpu","benchmarking","packages","play","package",{"skillNo":175,"name":176,"nameZh":6,"description":177,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":178,"categories":179,"keywords":185,"publishedAt":34},"01M6BY5BY9H6SDG9GRRTT04EWA","litert-conversion-workflow","Convert a Hugging Face LLM or vision-language model checkpoint into a .litertlm bundle that runs on the LiteRT-LM runtime with verified quality - classify the architecture against known runtime walls, pick the recipe family (dense, reasoning, hybrid SSM, VLM), export, quantize, gate the result against the source model, and publish. Use when converting a new LLM or VLM to LiteRT-LM, when a converted bundle crashes on the first message or dies at engine creation, when a quantized model answers worse than its source, or when deciding whether a model is convertible at all.","https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002Flitert-samples\u002Fblob\u002Fmain\u002Fskills\u002Flitert-conversion-workflow\u002FSKILL.md",[180],{"categoryNo":181,"categoryName":182,"taxonomyType":183,"taxonomyTypeDesc":184},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[186,187,18,188,189,190,191,192,193,194,195,196,197,198,199,200,201,19,202,203],"conversion","workflow","litert conversion workflow","face","source","hugging face","verified","export","quantize","at","result","classify","recipe","creation","architecture","pick","publish","message",{"skillNo":205,"name":206,"nameZh":6,"description":207,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":208,"categories":209,"keywords":210,"publishedAt":34},"01M6BY55P8GVX66H0FG8JHXHWF","gpu-clean-conversion","Convert a PyTorch or Hugging Face model into a LiteRT model that runs fully on the GPU via the CompiledModel API with verified-correct output, and lay it out as a model recipe. Use when converting a new model, or when a converted model is rejected by the GPU, falls back to CPU, or returns wrong numbers on device.","https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002Flitert-samples\u002Fblob\u002Fmain\u002Fskills\u002Fgpu-clean-conversion\u002FSKILL.md",[],[186,211,151,212,31,213,214,215,19,18,191,192,216,217,218,219,220,198,221,222],"clean","gpu clean conversion","convert","pytorch","correct","CPU","via","with","output","use","as","back",{"skillNo":224,"name":225,"nameZh":6,"description":226,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":227,"categories":228,"keywords":229,"publishedAt":34},"01M6BY52X9KX3VRXQJS622DZH3","compiled-model-app-scaffolding","Build a new Android app (Kotlin, Compose) around a verified LiteRT model using the CompiledModel API - the app architecture, the inference-layer lifecycle rules, model delivery, and the UI traps that masquerade as model bugs. Use when turning a converted and device-verified model into a demo or product app, when an app's inference layer leaks memory or blocks the UI, or when a model that verified clean looks wrong inside an app.","https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002Flitert-samples\u002Fblob\u002Fmain\u002Fskills\u002Fcompiled-model-app-scaffolding\u002FSKILL.md",[],[19,230,231,232,31,200,233,163,234,164,235,18,21],"compiled model app scaffolding","demo","inference","ui","lifecycle","product",{"skillNo":237,"name":238,"nameZh":6,"description":239,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":240,"categories":241,"keywords":242,"publishedAt":34},"01M6BY501NESZTA4NSEKX9BSDE","benchmark-on-ddp","Measure a LiteRT .tflite model with `benchmark_model` on Developer Device Platform (DDP) lab phones through `litert benchmark --ddp`, or on the Mac you run it from, and turn the session into rows of the performance leaderboard under benchmark\u002Fleaderboard - one matrix entry per model, one session per accelerator, collect results.pb and runtime_info.pb, rebuild board.json, check the page, commit the data. Use when a model needs latency and memory numbers per platform, device and accelerator, or when a new benchmark_model release means re-measuring the board.","https:\u002F\u002Fgithub.com\u002Fgoogle-ai-edge\u002Flitert-samples\u002Fblob\u002Fmain\u002Fskills\u002Fbenchmark-on-ddp\u002FSKILL.md",[],[243,166,19,164,244,245,18,246,247,248,249,162,250,251],"benchmark on ddp","page","run","commit","developer","data","json","collect","release"]