@dr33m/react-native-litert-lm 0.5.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/margelo/nitro/dev/litert/litertlm/HybridLiteRTLM.kt +41 -8
- package/app.plugin.js +20 -1
- package/ios/HybridLiteRTLM.swift +7 -0
- package/lib/index.d.ts +1 -1
- package/lib/specs/LiteRTLM.nitro.d.ts +15 -0
- package/nitrogen/generated/android/c++/JBackend.hpp +1 -1
- package/nitrogen/generated/android/c++/JExecuteResult.hpp +1 -1
- package/nitrogen/generated/android/c++/JGenerationStats.hpp +1 -1
- package/nitrogen/generated/android/c++/JHybridLiteRTLMSpec.cpp +9 -0
- package/nitrogen/generated/android/c++/JHybridLiteRTLMSpec.hpp +1 -0
- package/nitrogen/generated/android/c++/JLLMConfig.hpp +1 -1
- package/nitrogen/generated/android/c++/JMemoryUsage.hpp +1 -1
- package/nitrogen/generated/android/c++/JMessage.hpp +1 -1
- package/nitrogen/generated/android/c++/JModelCapabilities.hpp +57 -0
- package/nitrogen/generated/android/c++/JModelFile.hpp +1 -1
- package/nitrogen/generated/android/c++/JMultimodalPart.hpp +1 -1
- package/nitrogen/generated/android/c++/JPartType.hpp +1 -1
- package/nitrogen/generated/android/c++/JRole.hpp +1 -1
- package/nitrogen/generated/android/c++/JToolCall.hpp +1 -1
- package/nitrogen/generated/android/c++/JToolDefinition.hpp +1 -1
- package/nitrogen/generated/android/c++/JToolResponse.hpp +1 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/dev/litert/litertlm/HybridLiteRTLMSpec.kt +4 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/dev/litert/litertlm/ModelCapabilities.kt +51 -0
- package/nitrogen/generated/ios/LiteRTLM-Swift-Cxx-Bridge.hpp +12 -0
- package/nitrogen/generated/ios/LiteRTLM-Swift-Cxx-Umbrella.hpp +3 -0
- package/nitrogen/generated/ios/c++/HybridLiteRTLMSpecSwift.hpp +11 -0
- package/nitrogen/generated/ios/swift/HybridLiteRTLMSpec.swift +1 -0
- package/nitrogen/generated/ios/swift/HybridLiteRTLMSpec_cxx.swift +12 -0
- package/nitrogen/generated/ios/swift/ModelCapabilities.swift +29 -0
- package/nitrogen/generated/shared/c++/HybridLiteRTLMSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridLiteRTLMSpec.hpp +4 -0
- package/nitrogen/generated/shared/c++/ModelCapabilities.hpp +83 -0
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/specs/LiteRTLM.nitro.ts +17 -0
|
@@ -163,9 +163,9 @@ class HybridLiteRTLM : HybridLiteRTLMSpec() {
|
|
|
163
163
|
try {
|
|
164
164
|
// Early GPU hardware check: probe for OpenCL library.
|
|
165
165
|
// LiteRT-LM's GPU delegate requires OpenCL, which is absent on
|
|
166
|
-
// most Samsung/Qualcomm devices.
|
|
167
|
-
//
|
|
168
|
-
if (
|
|
166
|
+
// most Samsung/Qualcomm devices. Probe once and cache the result —
|
|
167
|
+
// needed for both GPU main backend and multimodal vision backend.
|
|
168
|
+
if (openCLAvailable == null) {
|
|
169
169
|
val hasOpenCL = openCLAvailable ?: run {
|
|
170
170
|
val result = try {
|
|
171
171
|
System.loadLibrary("OpenCL")
|
|
@@ -244,17 +244,38 @@ class HybridLiteRTLM : HybridLiteRTLMSpec() {
|
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
// Map our Backend enum to LiteRT-LM Backend sealed class
|
|
247
|
+
// Map our Backend enum to LiteRT-LM Backend sealed class.
|
|
248
|
+
// If hardware is unavailable, skip directly to CPU to avoid native
|
|
249
|
+
// crashes (SIGSEGV) that Kotlin's try/catch cannot intercept.
|
|
248
250
|
val lmBackend = when (backend) {
|
|
249
|
-
Backend.GPU ->
|
|
251
|
+
Backend.GPU -> {
|
|
252
|
+
val hasOpenCL = openCLAvailable ?: false
|
|
253
|
+
if (hasOpenCL) {
|
|
254
|
+
com.google.ai.edge.litertlm.Backend.GPU()
|
|
255
|
+
} else {
|
|
256
|
+
Log.w(TAG, "GPU requested but OpenCL unavailable — using CPU directly")
|
|
257
|
+
backend = Backend.CPU
|
|
258
|
+
com.google.ai.edge.litertlm.Backend.CPU()
|
|
259
|
+
}
|
|
260
|
+
}
|
|
250
261
|
Backend.NPU -> {
|
|
251
|
-
|
|
252
|
-
|
|
262
|
+
val nativeLibDir = LiteRTLMInitProvider.applicationContext?.applicationInfo?.nativeLibraryDir
|
|
263
|
+
Log.i(TAG, "NPU backend requested - nativeLibraryDir=$nativeLibDir")
|
|
264
|
+
if (nativeLibDir != null) {
|
|
265
|
+
com.google.ai.edge.litertlm.Backend.NPU(nativeLibraryDir = nativeLibDir)
|
|
266
|
+
} else {
|
|
267
|
+
Log.w(TAG, "NPU requested but nativeLibraryDir unavailable — using CPU directly")
|
|
268
|
+
backend = Backend.CPU
|
|
269
|
+
com.google.ai.edge.litertlm.Backend.CPU()
|
|
270
|
+
}
|
|
253
271
|
}
|
|
254
272
|
else -> com.google.ai.edge.litertlm.Backend.CPU()
|
|
255
273
|
}
|
|
256
274
|
|
|
257
|
-
val lmVisionBackend = if (isMultimodal)
|
|
275
|
+
val lmVisionBackend = if (isMultimodal) {
|
|
276
|
+
if (openCLAvailable == true) com.google.ai.edge.litertlm.Backend.GPU()
|
|
277
|
+
else com.google.ai.edge.litertlm.Backend.CPU()
|
|
278
|
+
} else null
|
|
258
279
|
val lmAudioBackend = if (isMultimodal) com.google.ai.edge.litertlm.Backend.CPU() else null
|
|
259
280
|
|
|
260
281
|
Log.i(TAG, "Backend config: main=$lmBackend, vision=$lmVisionBackend, audio=$lmAudioBackend, multimodal=$isMultimodal")
|
|
@@ -558,6 +579,18 @@ class HybridLiteRTLM : HybridLiteRTLMSpec() {
|
|
|
558
579
|
)
|
|
559
580
|
}
|
|
560
581
|
|
|
582
|
+
override fun checkModelCapabilities(modelPath: String): ModelCapabilities {
|
|
583
|
+
var supportsSpeculativeDecoding = false
|
|
584
|
+
try {
|
|
585
|
+
com.google.ai.edge.litertlm.Capabilities(modelPath).use {
|
|
586
|
+
supportsSpeculativeDecoding = it.hasSpeculativeDecodingSupport()
|
|
587
|
+
}
|
|
588
|
+
} catch (e: Exception) {
|
|
589
|
+
Log.w(TAG, "checkModelCapabilities: failed to query capabilities: ${e.message}")
|
|
590
|
+
}
|
|
591
|
+
return ModelCapabilities(supportsSpeculativeDecoding = supportsSpeculativeDecoding)
|
|
592
|
+
}
|
|
593
|
+
|
|
561
594
|
override fun getActiveBackend(): Backend = backend
|
|
562
595
|
|
|
563
596
|
override fun stopGeneration() {
|
package/app.plugin.js
CHANGED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
* Expo config plugin for react-native-litert-lm.
|
|
3
3
|
*
|
|
4
4
|
* Ensures correct build settings for the LiteRT-LM native module:
|
|
5
|
-
* - Android: minSdkVersion 26
|
|
5
|
+
* - Android: minSdkVersion 26, Kotlin 2.3.0 (required by litertlm-android AAR)
|
|
6
6
|
*/
|
|
7
7
|
const {
|
|
8
8
|
withGradleProperties,
|
|
9
|
+
withProjectBuildGradle,
|
|
9
10
|
} = require('@expo/config-plugins');
|
|
10
11
|
|
|
11
12
|
function withLiteRTLM(config) {
|
|
@@ -28,6 +29,24 @@ function withLiteRTLM(config) {
|
|
|
28
29
|
return config;
|
|
29
30
|
});
|
|
30
31
|
|
|
32
|
+
// Android: Pin Kotlin Gradle plugin to 2.3.0
|
|
33
|
+
// The litertlm-android AAR uses Kotlin 2.3.0 metadata which cannot be read
|
|
34
|
+
// by older compilers. This forces the project-level Kotlin plugin to 2.3.0.
|
|
35
|
+
config = withProjectBuildGradle(config, (config) => {
|
|
36
|
+
if (config.modResults.language === 'groovy') {
|
|
37
|
+
const contents = config.modResults.contents;
|
|
38
|
+
|
|
39
|
+
if (!contents.includes("kotlin-gradle-plugin:2.3.0")) {
|
|
40
|
+
config.modResults.contents = contents.replace(
|
|
41
|
+
"classpath('org.jetbrains.kotlin:kotlin-gradle-plugin')",
|
|
42
|
+
"classpath('org.jetbrains.kotlin:kotlin-gradle-plugin:2.3.0')"
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return config;
|
|
48
|
+
});
|
|
49
|
+
|
|
31
50
|
return config;
|
|
32
51
|
}
|
|
33
52
|
|
package/ios/HybridLiteRTLM.swift
CHANGED
|
@@ -142,6 +142,13 @@ public class HybridLiteRTLM: HybridLiteRTLMSpec_base, HybridLiteRTLMSpec_protoco
|
|
|
142
142
|
)
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
public func checkModelCapabilities(modelPath: String) throws -> ModelCapabilities {
|
|
146
|
+
// iOS LiteRT-LM C API doesn't expose a Capabilities class like Android.
|
|
147
|
+
// Return safe defaults — speculative decoding support can be detected
|
|
148
|
+
// at engine init time on iOS.
|
|
149
|
+
return ModelCapabilities(supportsSpeculativeDecoding: false)
|
|
150
|
+
}
|
|
151
|
+
|
|
145
152
|
public func getActiveBackend() throws -> Backend {
|
|
146
153
|
return backend
|
|
147
154
|
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Backend } from "./specs/LiteRTLM.nitro";
|
|
2
|
-
export type { LiteRTLM, LLMConfig, Message, Backend, Role, GenerationStats, MemoryUsage,
|
|
2
|
+
export type { LiteRTLM, LLMConfig, Message, Backend, Role, GenerationStats, MemoryUsage, ModelCapabilities,
|
|
3
3
|
/** New in v0.5: pass to execute() instead of individual send methods */
|
|
4
4
|
MultimodalPart, PartType,
|
|
5
5
|
/** Tool calling types */
|
|
@@ -207,6 +207,14 @@ export interface MemoryUsage {
|
|
|
207
207
|
/** Whether the system considers memory low */
|
|
208
208
|
isLowMemory: boolean;
|
|
209
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* Model capability flags queried from the model file at runtime.
|
|
212
|
+
* Uses the LiteRT-LM Capabilities API to inspect compiled model metadata.
|
|
213
|
+
*/
|
|
214
|
+
export interface ModelCapabilities {
|
|
215
|
+
/** Whether the model binary supports multi-token prediction (speculative decoding). */
|
|
216
|
+
supportsSpeculativeDecoding: boolean;
|
|
217
|
+
}
|
|
210
218
|
/**
|
|
211
219
|
* LiteRT-LM: High-performance LLM inference engine.
|
|
212
220
|
* Supports Gemma 4, Gemma 3n, Phi-4, Qwen, and other .litertlm models.
|
|
@@ -356,6 +364,13 @@ export interface LiteRTLM extends HybridObject<{
|
|
|
356
364
|
* No-op if nothing is generating.
|
|
357
365
|
*/
|
|
358
366
|
stopGeneration(): void;
|
|
367
|
+
/**
|
|
368
|
+
* Query model capabilities from the compiled model file.
|
|
369
|
+
* Does NOT require loadModel() — reads metadata directly from disk.
|
|
370
|
+
* @param modelPath Absolute path to the .litertlm model file.
|
|
371
|
+
* @returns Capabilities flags (e.g. speculative decoding support).
|
|
372
|
+
*/
|
|
373
|
+
checkModelCapabilities(modelPath: string): ModelCapabilities;
|
|
359
374
|
/**
|
|
360
375
|
* Release all native resources.
|
|
361
376
|
* Call this when done with the LLM instance.
|
|
@@ -15,7 +15,7 @@ namespace margelo::nitro::litertlm {
|
|
|
15
15
|
using namespace facebook;
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* The C++ JNI bridge between the C++ enum "Backend" and the
|
|
18
|
+
* The C++ JNI bridge between the C++ enum "Backend" and the Kotlin enum "Backend".
|
|
19
19
|
*/
|
|
20
20
|
struct JBackend final: public jni::JavaClass<JBackend> {
|
|
21
21
|
public:
|
|
@@ -20,7 +20,7 @@ namespace margelo::nitro::litertlm {
|
|
|
20
20
|
using namespace facebook;
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
* The C++ JNI bridge between the C++ struct "ExecuteResult" and the
|
|
23
|
+
* The C++ JNI bridge between the C++ struct "ExecuteResult" and the Kotlin data class "ExecuteResult".
|
|
24
24
|
*/
|
|
25
25
|
struct JExecuteResult final: public jni::JavaClass<JExecuteResult> {
|
|
26
26
|
public:
|
|
@@ -17,7 +17,7 @@ namespace margelo::nitro::litertlm {
|
|
|
17
17
|
using namespace facebook;
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* The C++ JNI bridge between the C++ struct "GenerationStats" and the
|
|
20
|
+
* The C++ JNI bridge between the C++ struct "GenerationStats" and the Kotlin data class "GenerationStats".
|
|
21
21
|
*/
|
|
22
22
|
struct JGenerationStats final: public jni::JavaClass<JGenerationStats> {
|
|
23
23
|
public:
|
|
@@ -21,6 +21,8 @@ namespace margelo::nitro::litertlm { struct GenerationStats; }
|
|
|
21
21
|
namespace margelo::nitro::litertlm { struct MemoryUsage; }
|
|
22
22
|
// Forward declaration of `Backend` to properly resolve imports.
|
|
23
23
|
namespace margelo::nitro::litertlm { enum class Backend; }
|
|
24
|
+
// Forward declaration of `ModelCapabilities` to properly resolve imports.
|
|
25
|
+
namespace margelo::nitro::litertlm { struct ModelCapabilities; }
|
|
24
26
|
// Forward declaration of `LLMConfig` to properly resolve imports.
|
|
25
27
|
namespace margelo::nitro::litertlm { struct LLMConfig; }
|
|
26
28
|
// Forward declaration of `ToolDefinition` to properly resolve imports.
|
|
@@ -51,6 +53,8 @@ namespace margelo::nitro::litertlm { struct ToolResponse; }
|
|
|
51
53
|
#include "JMemoryUsage.hpp"
|
|
52
54
|
#include "Backend.hpp"
|
|
53
55
|
#include "JBackend.hpp"
|
|
56
|
+
#include "ModelCapabilities.hpp"
|
|
57
|
+
#include "JModelCapabilities.hpp"
|
|
54
58
|
#include "LLMConfig.hpp"
|
|
55
59
|
#include <optional>
|
|
56
60
|
#include "JLLMConfig.hpp"
|
|
@@ -363,6 +367,11 @@ namespace margelo::nitro::litertlm {
|
|
|
363
367
|
static const auto method = _javaPart->javaClassStatic()->getMethod<void()>("stopGeneration");
|
|
364
368
|
method(_javaPart);
|
|
365
369
|
}
|
|
370
|
+
ModelCapabilities JHybridLiteRTLMSpec::checkModelCapabilities(const std::string& modelPath) {
|
|
371
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JModelCapabilities>(jni::alias_ref<jni::JString> /* modelPath */)>("checkModelCapabilities");
|
|
372
|
+
auto __result = method(_javaPart, jni::make_jstring(modelPath));
|
|
373
|
+
return __result->toCpp();
|
|
374
|
+
}
|
|
366
375
|
void JHybridLiteRTLMSpec::close() {
|
|
367
376
|
static const auto method = _javaPart->javaClassStatic()->getMethod<void()>("close");
|
|
368
377
|
method(_javaPart);
|
|
@@ -74,6 +74,7 @@ namespace margelo::nitro::litertlm {
|
|
|
74
74
|
std::shared_ptr<Promise<ExecuteResult>> sendToolResponse(const std::vector<ToolResponse>& responses, const std::optional<std::function<void(const std::string& /* token */, bool /* done */)>>& onToken) override;
|
|
75
75
|
Backend getActiveBackend() override;
|
|
76
76
|
void stopGeneration() override;
|
|
77
|
+
ModelCapabilities checkModelCapabilities(const std::string& modelPath) override;
|
|
77
78
|
void close() override;
|
|
78
79
|
|
|
79
80
|
private:
|
|
@@ -23,7 +23,7 @@ namespace margelo::nitro::litertlm {
|
|
|
23
23
|
using namespace facebook;
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* The C++ JNI bridge between the C++ struct "LLMConfig" and the
|
|
26
|
+
* The C++ JNI bridge between the C++ struct "LLMConfig" and the Kotlin data class "LLMConfig".
|
|
27
27
|
*/
|
|
28
28
|
struct JLLMConfig final: public jni::JavaClass<JLLMConfig> {
|
|
29
29
|
public:
|
|
@@ -17,7 +17,7 @@ namespace margelo::nitro::litertlm {
|
|
|
17
17
|
using namespace facebook;
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* The C++ JNI bridge between the C++ struct "MemoryUsage" and the
|
|
20
|
+
* The C++ JNI bridge between the C++ struct "MemoryUsage" and the Kotlin data class "MemoryUsage".
|
|
21
21
|
*/
|
|
22
22
|
struct JMemoryUsage final: public jni::JavaClass<JMemoryUsage> {
|
|
23
23
|
public:
|
|
@@ -19,7 +19,7 @@ namespace margelo::nitro::litertlm {
|
|
|
19
19
|
using namespace facebook;
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* The C++ JNI bridge between the C++ struct "Message" and the
|
|
22
|
+
* The C++ JNI bridge between the C++ struct "Message" and the Kotlin data class "Message".
|
|
23
23
|
*/
|
|
24
24
|
struct JMessage final: public jni::JavaClass<JMessage> {
|
|
25
25
|
public:
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
///
|
|
2
|
+
/// JModelCapabilities.hpp
|
|
3
|
+
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
4
|
+
/// https://github.com/mrousavy/nitro
|
|
5
|
+
/// Copyright © Marc Rousavy @ Margelo
|
|
6
|
+
///
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include <fbjni/fbjni.h>
|
|
11
|
+
#include "ModelCapabilities.hpp"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
namespace margelo::nitro::litertlm {
|
|
16
|
+
|
|
17
|
+
using namespace facebook;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The C++ JNI bridge between the C++ struct "ModelCapabilities" and the Kotlin data class "ModelCapabilities".
|
|
21
|
+
*/
|
|
22
|
+
struct JModelCapabilities final: public jni::JavaClass<JModelCapabilities> {
|
|
23
|
+
public:
|
|
24
|
+
static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/dev/litert/litertlm/ModelCapabilities;";
|
|
25
|
+
|
|
26
|
+
public:
|
|
27
|
+
/**
|
|
28
|
+
* Convert this Java/Kotlin-based struct to the C++ struct ModelCapabilities by copying all values to C++.
|
|
29
|
+
*/
|
|
30
|
+
[[maybe_unused]]
|
|
31
|
+
[[nodiscard]]
|
|
32
|
+
ModelCapabilities toCpp() const {
|
|
33
|
+
static const auto clazz = javaClassStatic();
|
|
34
|
+
static const auto fieldSupportsSpeculativeDecoding = clazz->getField<jboolean>("supportsSpeculativeDecoding");
|
|
35
|
+
jboolean supportsSpeculativeDecoding = this->getFieldValue(fieldSupportsSpeculativeDecoding);
|
|
36
|
+
return ModelCapabilities(
|
|
37
|
+
static_cast<bool>(supportsSpeculativeDecoding)
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public:
|
|
42
|
+
/**
|
|
43
|
+
* Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.
|
|
44
|
+
*/
|
|
45
|
+
[[maybe_unused]]
|
|
46
|
+
static jni::local_ref<JModelCapabilities::javaobject> fromCpp(const ModelCapabilities& value) {
|
|
47
|
+
using JSignature = JModelCapabilities(jboolean);
|
|
48
|
+
static const auto clazz = javaClassStatic();
|
|
49
|
+
static const auto create = clazz->getStaticMethod<JSignature>("fromCpp");
|
|
50
|
+
return create(
|
|
51
|
+
clazz,
|
|
52
|
+
value.supportsSpeculativeDecoding
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
} // namespace margelo::nitro::litertlm
|
|
@@ -17,7 +17,7 @@ namespace margelo::nitro::litertlm {
|
|
|
17
17
|
using namespace facebook;
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* The C++ JNI bridge between the C++ struct "ModelFile" and the
|
|
20
|
+
* The C++ JNI bridge between the C++ struct "ModelFile" and the Kotlin data class "ModelFile".
|
|
21
21
|
*/
|
|
22
22
|
struct JModelFile final: public jni::JavaClass<JModelFile> {
|
|
23
23
|
public:
|
|
@@ -22,7 +22,7 @@ namespace margelo::nitro::litertlm {
|
|
|
22
22
|
using namespace facebook;
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
* The C++ JNI bridge between the C++ struct "MultimodalPart" and the
|
|
25
|
+
* The C++ JNI bridge between the C++ struct "MultimodalPart" and the Kotlin data class "MultimodalPart".
|
|
26
26
|
*/
|
|
27
27
|
struct JMultimodalPart final: public jni::JavaClass<JMultimodalPart> {
|
|
28
28
|
public:
|
|
@@ -15,7 +15,7 @@ namespace margelo::nitro::litertlm {
|
|
|
15
15
|
using namespace facebook;
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* The C++ JNI bridge between the C++ enum "PartType" and the
|
|
18
|
+
* The C++ JNI bridge between the C++ enum "PartType" and the Kotlin enum "PartType".
|
|
19
19
|
*/
|
|
20
20
|
struct JPartType final: public jni::JavaClass<JPartType> {
|
|
21
21
|
public:
|
|
@@ -15,7 +15,7 @@ namespace margelo::nitro::litertlm {
|
|
|
15
15
|
using namespace facebook;
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* The C++ JNI bridge between the C++ enum "Role" and the
|
|
18
|
+
* The C++ JNI bridge between the C++ enum "Role" and the Kotlin enum "Role".
|
|
19
19
|
*/
|
|
20
20
|
struct JRole final: public jni::JavaClass<JRole> {
|
|
21
21
|
public:
|
|
@@ -17,7 +17,7 @@ namespace margelo::nitro::litertlm {
|
|
|
17
17
|
using namespace facebook;
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* The C++ JNI bridge between the C++ struct "ToolCall" and the
|
|
20
|
+
* The C++ JNI bridge between the C++ struct "ToolCall" and the Kotlin data class "ToolCall".
|
|
21
21
|
*/
|
|
22
22
|
struct JToolCall final: public jni::JavaClass<JToolCall> {
|
|
23
23
|
public:
|
|
@@ -17,7 +17,7 @@ namespace margelo::nitro::litertlm {
|
|
|
17
17
|
using namespace facebook;
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* The C++ JNI bridge between the C++ struct "ToolDefinition" and the
|
|
20
|
+
* The C++ JNI bridge between the C++ struct "ToolDefinition" and the Kotlin data class "ToolDefinition".
|
|
21
21
|
*/
|
|
22
22
|
struct JToolDefinition final: public jni::JavaClass<JToolDefinition> {
|
|
23
23
|
public:
|
|
@@ -17,7 +17,7 @@ namespace margelo::nitro::litertlm {
|
|
|
17
17
|
using namespace facebook;
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* The C++ JNI bridge between the C++ struct "ToolResponse" and the
|
|
20
|
+
* The C++ JNI bridge between the C++ struct "ToolResponse" and the Kotlin data class "ToolResponse".
|
|
21
21
|
*/
|
|
22
22
|
struct JToolResponse final: public jni::JavaClass<JToolResponse> {
|
|
23
23
|
public:
|
|
@@ -139,6 +139,10 @@ abstract class HybridLiteRTLMSpec: HybridObject() {
|
|
|
139
139
|
@Keep
|
|
140
140
|
abstract fun stopGeneration(): Unit
|
|
141
141
|
|
|
142
|
+
@DoNotStrip
|
|
143
|
+
@Keep
|
|
144
|
+
abstract fun checkModelCapabilities(modelPath: String): ModelCapabilities
|
|
145
|
+
|
|
142
146
|
@DoNotStrip
|
|
143
147
|
@Keep
|
|
144
148
|
abstract fun close(): Unit
|
package/nitrogen/generated/android/kotlin/com/margelo/nitro/dev/litert/litertlm/ModelCapabilities.kt
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
///
|
|
2
|
+
/// ModelCapabilities.kt
|
|
3
|
+
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
4
|
+
/// https://github.com/mrousavy/nitro
|
|
5
|
+
/// Copyright © Marc Rousavy @ Margelo
|
|
6
|
+
///
|
|
7
|
+
|
|
8
|
+
package com.margelo.nitro.dev.litert.litertlm
|
|
9
|
+
|
|
10
|
+
import androidx.annotation.Keep
|
|
11
|
+
import com.facebook.proguard.annotations.DoNotStrip
|
|
12
|
+
import java.util.Objects
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Represents the JavaScript object/struct "ModelCapabilities".
|
|
17
|
+
*/
|
|
18
|
+
@DoNotStrip
|
|
19
|
+
@Keep
|
|
20
|
+
data class ModelCapabilities(
|
|
21
|
+
@DoNotStrip
|
|
22
|
+
@Keep
|
|
23
|
+
val supportsSpeculativeDecoding: Boolean
|
|
24
|
+
) {
|
|
25
|
+
/* primary constructor */
|
|
26
|
+
|
|
27
|
+
override fun equals(other: Any?): Boolean {
|
|
28
|
+
if (this === other) return true
|
|
29
|
+
if (other !is ModelCapabilities) return false
|
|
30
|
+
return Objects.deepEquals(this.supportsSpeculativeDecoding, other.supportsSpeculativeDecoding)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override fun hashCode(): Int {
|
|
34
|
+
return arrayOf<Any?>(
|
|
35
|
+
supportsSpeculativeDecoding
|
|
36
|
+
).contentDeepHashCode()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
companion object {
|
|
40
|
+
/**
|
|
41
|
+
* Constructor called from C++
|
|
42
|
+
*/
|
|
43
|
+
@DoNotStrip
|
|
44
|
+
@Keep
|
|
45
|
+
@Suppress("unused")
|
|
46
|
+
@JvmStatic
|
|
47
|
+
private fun fromCpp(supportsSpeculativeDecoding: Boolean): ModelCapabilities {
|
|
48
|
+
return ModelCapabilities(supportsSpeculativeDecoding)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -26,6 +26,8 @@ namespace margelo::nitro::litertlm { struct LLMConfig; }
|
|
|
26
26
|
namespace margelo::nitro::litertlm { struct MemoryUsage; }
|
|
27
27
|
// Forward declaration of `Message` to properly resolve imports.
|
|
28
28
|
namespace margelo::nitro::litertlm { struct Message; }
|
|
29
|
+
// Forward declaration of `ModelCapabilities` to properly resolve imports.
|
|
30
|
+
namespace margelo::nitro::litertlm { struct ModelCapabilities; }
|
|
29
31
|
// Forward declaration of `ModelFile` to properly resolve imports.
|
|
30
32
|
namespace margelo::nitro::litertlm { struct ModelFile; }
|
|
31
33
|
// Forward declaration of `MultimodalPart` to properly resolve imports.
|
|
@@ -56,6 +58,7 @@ namespace LiteRTLM { class HybridModelStoreSpec_cxx; }
|
|
|
56
58
|
#include "LLMConfig.hpp"
|
|
57
59
|
#include "MemoryUsage.hpp"
|
|
58
60
|
#include "Message.hpp"
|
|
61
|
+
#include "ModelCapabilities.hpp"
|
|
59
62
|
#include "ModelFile.hpp"
|
|
60
63
|
#include "MultimodalPart.hpp"
|
|
61
64
|
#include "PartType.hpp"
|
|
@@ -541,6 +544,15 @@ namespace margelo::nitro::litertlm::bridge::swift {
|
|
|
541
544
|
return Result<Backend>::withError(error);
|
|
542
545
|
}
|
|
543
546
|
|
|
547
|
+
// pragma MARK: Result<ModelCapabilities>
|
|
548
|
+
using Result_ModelCapabilities_ = Result<ModelCapabilities>;
|
|
549
|
+
inline Result_ModelCapabilities_ create_Result_ModelCapabilities_(const ModelCapabilities& value) noexcept {
|
|
550
|
+
return Result<ModelCapabilities>::withValue(value);
|
|
551
|
+
}
|
|
552
|
+
inline Result_ModelCapabilities_ create_Result_ModelCapabilities_(const std::exception_ptr& error) noexcept {
|
|
553
|
+
return Result<ModelCapabilities>::withError(error);
|
|
554
|
+
}
|
|
555
|
+
|
|
544
556
|
// pragma MARK: std::vector<ModelFile>
|
|
545
557
|
/**
|
|
546
558
|
* Specialized version of `std::vector<ModelFile>`.
|
|
@@ -24,6 +24,8 @@ namespace margelo::nitro::litertlm { struct LLMConfig; }
|
|
|
24
24
|
namespace margelo::nitro::litertlm { struct MemoryUsage; }
|
|
25
25
|
// Forward declaration of `Message` to properly resolve imports.
|
|
26
26
|
namespace margelo::nitro::litertlm { struct Message; }
|
|
27
|
+
// Forward declaration of `ModelCapabilities` to properly resolve imports.
|
|
28
|
+
namespace margelo::nitro::litertlm { struct ModelCapabilities; }
|
|
27
29
|
// Forward declaration of `ModelFile` to properly resolve imports.
|
|
28
30
|
namespace margelo::nitro::litertlm { struct ModelFile; }
|
|
29
31
|
// Forward declaration of `MultimodalPart` to properly resolve imports.
|
|
@@ -48,6 +50,7 @@ namespace margelo::nitro::litertlm { struct ToolResponse; }
|
|
|
48
50
|
#include "LLMConfig.hpp"
|
|
49
51
|
#include "MemoryUsage.hpp"
|
|
50
52
|
#include "Message.hpp"
|
|
53
|
+
#include "ModelCapabilities.hpp"
|
|
51
54
|
#include "ModelFile.hpp"
|
|
52
55
|
#include "MultimodalPart.hpp"
|
|
53
56
|
#include "PartType.hpp"
|
|
@@ -38,6 +38,8 @@ namespace margelo::nitro::litertlm { struct GenerationStats; }
|
|
|
38
38
|
namespace margelo::nitro::litertlm { struct MemoryUsage; }
|
|
39
39
|
// Forward declaration of `ToolResponse` to properly resolve imports.
|
|
40
40
|
namespace margelo::nitro::litertlm { struct ToolResponse; }
|
|
41
|
+
// Forward declaration of `ModelCapabilities` to properly resolve imports.
|
|
42
|
+
namespace margelo::nitro::litertlm { struct ModelCapabilities; }
|
|
41
43
|
|
|
42
44
|
#include <NitroModules/Promise.hpp>
|
|
43
45
|
#include <string>
|
|
@@ -58,6 +60,7 @@ namespace margelo::nitro::litertlm { struct ToolResponse; }
|
|
|
58
60
|
#include "GenerationStats.hpp"
|
|
59
61
|
#include "MemoryUsage.hpp"
|
|
60
62
|
#include "ToolResponse.hpp"
|
|
63
|
+
#include "ModelCapabilities.hpp"
|
|
61
64
|
|
|
62
65
|
#include "LiteRTLM-Swift-Cxx-Umbrella.hpp"
|
|
63
66
|
|
|
@@ -265,6 +268,14 @@ namespace margelo::nitro::litertlm {
|
|
|
265
268
|
std::rethrow_exception(__result.error());
|
|
266
269
|
}
|
|
267
270
|
}
|
|
271
|
+
inline ModelCapabilities checkModelCapabilities(const std::string& modelPath) override {
|
|
272
|
+
auto __result = _swiftPart.checkModelCapabilities(modelPath);
|
|
273
|
+
if (__result.hasError()) [[unlikely]] {
|
|
274
|
+
std::rethrow_exception(__result.error());
|
|
275
|
+
}
|
|
276
|
+
auto __value = std::move(__result.value());
|
|
277
|
+
return __value;
|
|
278
|
+
}
|
|
268
279
|
inline void close() override {
|
|
269
280
|
auto __result = _swiftPart.close();
|
|
270
281
|
if (__result.hasError()) [[unlikely]] {
|
|
@@ -33,6 +33,7 @@ public protocol HybridLiteRTLMSpec_protocol: HybridObject {
|
|
|
33
33
|
func sendToolResponse(responses: [ToolResponse], onToken: ((_ token: String, _ done: Bool) -> Void)?) throws -> Promise<ExecuteResult>
|
|
34
34
|
func getActiveBackend() throws -> Backend
|
|
35
35
|
func stopGeneration() throws -> Void
|
|
36
|
+
func checkModelCapabilities(modelPath: String) throws -> ModelCapabilities
|
|
36
37
|
func close() throws -> Void
|
|
37
38
|
}
|
|
38
39
|
|
|
@@ -503,6 +503,18 @@ open class HybridLiteRTLMSpec_cxx {
|
|
|
503
503
|
}
|
|
504
504
|
}
|
|
505
505
|
|
|
506
|
+
@inline(__always)
|
|
507
|
+
public final func checkModelCapabilities(modelPath: std.string) -> bridge.Result_ModelCapabilities_ {
|
|
508
|
+
do {
|
|
509
|
+
let __result = try self.__implementation.checkModelCapabilities(modelPath: String(modelPath))
|
|
510
|
+
let __resultCpp = __result
|
|
511
|
+
return bridge.create_Result_ModelCapabilities_(__resultCpp)
|
|
512
|
+
} catch (let __error) {
|
|
513
|
+
let __exceptionPtr = __error.toCpp()
|
|
514
|
+
return bridge.create_Result_ModelCapabilities_(__exceptionPtr)
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
506
518
|
@inline(__always)
|
|
507
519
|
public final func close() -> bridge.Result_void_ {
|
|
508
520
|
do {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
///
|
|
2
|
+
/// ModelCapabilities.swift
|
|
3
|
+
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
4
|
+
/// https://github.com/mrousavy/nitro
|
|
5
|
+
/// Copyright © Marc Rousavy @ Margelo
|
|
6
|
+
///
|
|
7
|
+
|
|
8
|
+
import NitroModules
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Represents an instance of `ModelCapabilities`, backed by a C++ struct.
|
|
12
|
+
*/
|
|
13
|
+
public typealias ModelCapabilities = margelo.nitro.litertlm.ModelCapabilities
|
|
14
|
+
|
|
15
|
+
public extension ModelCapabilities {
|
|
16
|
+
private typealias bridge = margelo.nitro.litertlm.bridge.swift
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Create a new instance of `ModelCapabilities`.
|
|
20
|
+
*/
|
|
21
|
+
init(supportsSpeculativeDecoding: Bool) {
|
|
22
|
+
self.init(supportsSpeculativeDecoding)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@inline(__always)
|
|
26
|
+
var supportsSpeculativeDecoding: Bool {
|
|
27
|
+
return self.__supportsSpeculativeDecoding
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -34,6 +34,7 @@ namespace margelo::nitro::litertlm {
|
|
|
34
34
|
prototype.registerHybridMethod("sendToolResponse", &HybridLiteRTLMSpec::sendToolResponse);
|
|
35
35
|
prototype.registerHybridMethod("getActiveBackend", &HybridLiteRTLMSpec::getActiveBackend);
|
|
36
36
|
prototype.registerHybridMethod("stopGeneration", &HybridLiteRTLMSpec::stopGeneration);
|
|
37
|
+
prototype.registerHybridMethod("checkModelCapabilities", &HybridLiteRTLMSpec::checkModelCapabilities);
|
|
37
38
|
prototype.registerHybridMethod("close", &HybridLiteRTLMSpec::close);
|
|
38
39
|
});
|
|
39
40
|
}
|
|
@@ -29,6 +29,8 @@ namespace margelo::nitro::litertlm { struct MemoryUsage; }
|
|
|
29
29
|
namespace margelo::nitro::litertlm { struct ToolResponse; }
|
|
30
30
|
// Forward declaration of `Backend` to properly resolve imports.
|
|
31
31
|
namespace margelo::nitro::litertlm { enum class Backend; }
|
|
32
|
+
// Forward declaration of `ModelCapabilities` to properly resolve imports.
|
|
33
|
+
namespace margelo::nitro::litertlm { struct ModelCapabilities; }
|
|
32
34
|
|
|
33
35
|
#include <NitroModules/Promise.hpp>
|
|
34
36
|
#include <string>
|
|
@@ -43,6 +45,7 @@ namespace margelo::nitro::litertlm { enum class Backend; }
|
|
|
43
45
|
#include "MemoryUsage.hpp"
|
|
44
46
|
#include "ToolResponse.hpp"
|
|
45
47
|
#include "Backend.hpp"
|
|
48
|
+
#include "ModelCapabilities.hpp"
|
|
46
49
|
|
|
47
50
|
namespace margelo::nitro::litertlm {
|
|
48
51
|
|
|
@@ -95,6 +98,7 @@ namespace margelo::nitro::litertlm {
|
|
|
95
98
|
virtual std::shared_ptr<Promise<ExecuteResult>> sendToolResponse(const std::vector<ToolResponse>& responses, const std::optional<std::function<void(const std::string& /* token */, bool /* done */)>>& onToken) = 0;
|
|
96
99
|
virtual Backend getActiveBackend() = 0;
|
|
97
100
|
virtual void stopGeneration() = 0;
|
|
101
|
+
virtual ModelCapabilities checkModelCapabilities(const std::string& modelPath) = 0;
|
|
98
102
|
virtual void close() = 0;
|
|
99
103
|
|
|
100
104
|
protected:
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
///
|
|
2
|
+
/// ModelCapabilities.hpp
|
|
3
|
+
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
4
|
+
/// https://github.com/mrousavy/nitro
|
|
5
|
+
/// Copyright © Marc Rousavy @ Margelo
|
|
6
|
+
///
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#if __has_include(<NitroModules/JSIConverter.hpp>)
|
|
11
|
+
#include <NitroModules/JSIConverter.hpp>
|
|
12
|
+
#else
|
|
13
|
+
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
14
|
+
#endif
|
|
15
|
+
#if __has_include(<NitroModules/NitroDefines.hpp>)
|
|
16
|
+
#include <NitroModules/NitroDefines.hpp>
|
|
17
|
+
#else
|
|
18
|
+
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
19
|
+
#endif
|
|
20
|
+
#if __has_include(<NitroModules/JSIHelpers.hpp>)
|
|
21
|
+
#include <NitroModules/JSIHelpers.hpp>
|
|
22
|
+
#else
|
|
23
|
+
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
24
|
+
#endif
|
|
25
|
+
#if __has_include(<NitroModules/PropNameIDCache.hpp>)
|
|
26
|
+
#include <NitroModules/PropNameIDCache.hpp>
|
|
27
|
+
#else
|
|
28
|
+
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
namespace margelo::nitro::litertlm {
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A struct which can be represented as a JavaScript object (ModelCapabilities).
|
|
39
|
+
*/
|
|
40
|
+
struct ModelCapabilities final {
|
|
41
|
+
public:
|
|
42
|
+
bool supportsSpeculativeDecoding SWIFT_PRIVATE;
|
|
43
|
+
|
|
44
|
+
public:
|
|
45
|
+
ModelCapabilities() = default;
|
|
46
|
+
explicit ModelCapabilities(bool supportsSpeculativeDecoding): supportsSpeculativeDecoding(supportsSpeculativeDecoding) {}
|
|
47
|
+
|
|
48
|
+
public:
|
|
49
|
+
friend bool operator==(const ModelCapabilities& lhs, const ModelCapabilities& rhs) = default;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
} // namespace margelo::nitro::litertlm
|
|
53
|
+
|
|
54
|
+
namespace margelo::nitro {
|
|
55
|
+
|
|
56
|
+
// C++ ModelCapabilities <> JS ModelCapabilities (object)
|
|
57
|
+
template <>
|
|
58
|
+
struct JSIConverter<margelo::nitro::litertlm::ModelCapabilities> final {
|
|
59
|
+
static inline margelo::nitro::litertlm::ModelCapabilities fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
|
|
60
|
+
jsi::Object obj = arg.asObject(runtime);
|
|
61
|
+
return margelo::nitro::litertlm::ModelCapabilities(
|
|
62
|
+
JSIConverter<bool>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "supportsSpeculativeDecoding")))
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::litertlm::ModelCapabilities& arg) {
|
|
66
|
+
jsi::Object obj(runtime);
|
|
67
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "supportsSpeculativeDecoding"), JSIConverter<bool>::toJSI(runtime, arg.supportsSpeculativeDecoding));
|
|
68
|
+
return obj;
|
|
69
|
+
}
|
|
70
|
+
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
|
|
71
|
+
if (!value.isObject()) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
jsi::Object obj = value.getObject(runtime);
|
|
75
|
+
if (!nitro::isPlainObject(runtime, obj)) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
if (!JSIConverter<bool>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "supportsSpeculativeDecoding")))) return false;
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
} // namespace margelo::nitro
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -232,6 +232,15 @@ export interface MemoryUsage {
|
|
|
232
232
|
isLowMemory: boolean;
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
+
/**
|
|
236
|
+
* Model capability flags queried from the model file at runtime.
|
|
237
|
+
* Uses the LiteRT-LM Capabilities API to inspect compiled model metadata.
|
|
238
|
+
*/
|
|
239
|
+
export interface ModelCapabilities {
|
|
240
|
+
/** Whether the model binary supports multi-token prediction (speculative decoding). */
|
|
241
|
+
supportsSpeculativeDecoding: boolean;
|
|
242
|
+
}
|
|
243
|
+
|
|
235
244
|
/**
|
|
236
245
|
* LiteRT-LM: High-performance LLM inference engine.
|
|
237
246
|
* Supports Gemma 4, Gemma 3n, Phi-4, Qwen, and other .litertlm models.
|
|
@@ -420,6 +429,14 @@ export interface LiteRTLM extends HybridObject<{
|
|
|
420
429
|
*/
|
|
421
430
|
stopGeneration(): void;
|
|
422
431
|
|
|
432
|
+
/**
|
|
433
|
+
* Query model capabilities from the compiled model file.
|
|
434
|
+
* Does NOT require loadModel() — reads metadata directly from disk.
|
|
435
|
+
* @param modelPath Absolute path to the .litertlm model file.
|
|
436
|
+
* @returns Capabilities flags (e.g. speculative decoding support).
|
|
437
|
+
*/
|
|
438
|
+
checkModelCapabilities(modelPath: string): ModelCapabilities;
|
|
439
|
+
|
|
423
440
|
/**
|
|
424
441
|
* Release all native resources.
|
|
425
442
|
* Call this when done with the LLM instance.
|