react-native-litert-lm 0.3.0 → 0.3.1
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/README.md +1 -2
- package/cpp/HybridLiteRTLM.cpp +37 -3
- package/cpp/include/litert_lm_engine.h +7 -0
- package/package.json +1 -1
- package/scripts/build-ios-engine.sh +19 -0
package/README.md
CHANGED
|
@@ -448,8 +448,7 @@ const prompt = applyGemmaTemplate(
|
|
|
448
448
|
| react-native-nitro-modules | 0.35.0+ |
|
|
449
449
|
| Android API | 26+ (ARM64) |
|
|
450
450
|
| iOS | 15.0+ (ARM64) |
|
|
451
|
-
| LiteRT-LM
|
|
452
|
-
| LiteRT-LM iOS Engine | v0.9.0 |
|
|
451
|
+
| LiteRT-LM Engine | 0.9.0 |
|
|
453
452
|
|
|
454
453
|
## Platform Support
|
|
455
454
|
|
package/cpp/HybridLiteRTLM.cpp
CHANGED
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
#include <chrono>
|
|
19
19
|
#include <stdexcept>
|
|
20
20
|
#include <sstream>
|
|
21
|
+
#include <sys/stat.h>
|
|
22
|
+
#include <cstdio>
|
|
21
23
|
|
|
22
24
|
#ifdef __APPLE__
|
|
23
25
|
#include "IOSDownloadHelper.h"
|
|
@@ -241,7 +243,7 @@ void HybridLiteRTLM::loadModelInternal(
|
|
|
241
243
|
modelPath.c_str(),
|
|
242
244
|
backend,
|
|
243
245
|
visionBackend,
|
|
244
|
-
|
|
246
|
+
nullptr // audio executor not supported on iOS yet
|
|
245
247
|
);
|
|
246
248
|
if (!settings) {
|
|
247
249
|
return false;
|
|
@@ -250,6 +252,10 @@ void HybridLiteRTLM::loadModelInternal(
|
|
|
250
252
|
litert_lm_engine_settings_set_max_num_tokens(settings, static_cast<int>(maxTokens_));
|
|
251
253
|
litert_lm_engine_settings_enable_benchmark(settings);
|
|
252
254
|
|
|
255
|
+
// Set cache directory to the same directory as the model file
|
|
256
|
+
std::string cacheDir = modelPath.substr(0, modelPath.find_last_of('/'));
|
|
257
|
+
litert_lm_engine_settings_set_cache_dir(settings, cacheDir.c_str());
|
|
258
|
+
|
|
253
259
|
engine_ = litert_lm_engine_create(settings);
|
|
254
260
|
litert_lm_engine_settings_delete(settings);
|
|
255
261
|
|
|
@@ -275,9 +281,32 @@ void HybridLiteRTLM::loadModelInternal(
|
|
|
275
281
|
}
|
|
276
282
|
|
|
277
283
|
if (!engine_) {
|
|
284
|
+
// Collect diagnostic info
|
|
285
|
+
std::string diag = " | Diagnostics: ";
|
|
286
|
+
struct stat st;
|
|
287
|
+
if (stat(modelPath.c_str(), &st) == 0) {
|
|
288
|
+
diag += "File size: " + std::to_string(st.st_size) + " bytes";
|
|
289
|
+
} else {
|
|
290
|
+
diag += "Failed to stat file (errno: " + std::to_string(errno) + ")";
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
FILE* f = fopen(modelPath.c_str(), "rb");
|
|
294
|
+
if (f) {
|
|
295
|
+
diag += ", Readable: YES";
|
|
296
|
+
fclose(f);
|
|
297
|
+
} else {
|
|
298
|
+
diag += ", Readable: NO (errno: " + std::to_string(errno) + ")";
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Get the native error from the C API
|
|
302
|
+
const char* nativeErr = litert_lm_get_last_error();
|
|
303
|
+
if (nativeErr && nativeErr[0] != '\0') {
|
|
304
|
+
diag += " | Native error: " + std::string(nativeErr);
|
|
305
|
+
}
|
|
306
|
+
|
|
278
307
|
throw std::runtime_error(
|
|
279
308
|
"Failed to create LiteRT-LM engine. Tried backend '" +
|
|
280
|
-
std::string(primaryBackend) + "' and CPU fallback. Model path: " + modelPath);
|
|
309
|
+
std::string(primaryBackend) + "' and CPU fallback. Model path: " + modelPath + diag);
|
|
281
310
|
}
|
|
282
311
|
|
|
283
312
|
session_config_ = litert_lm_session_config_create();
|
|
@@ -484,7 +513,12 @@ std::string HybridLiteRTLM::sendMessageWithImageInternal(
|
|
|
484
513
|
conversation_, msgJson.c_str(), nullptr);
|
|
485
514
|
|
|
486
515
|
if (!response) {
|
|
487
|
-
|
|
516
|
+
std::string errMsg = "LiteRT-LM: sendMessageWithImage failed";
|
|
517
|
+
const char* nativeErr = litert_lm_get_last_error();
|
|
518
|
+
if (nativeErr && nativeErr[0] != '\0') {
|
|
519
|
+
errMsg += ": " + std::string(nativeErr);
|
|
520
|
+
}
|
|
521
|
+
throw std::runtime_error(errMsg);
|
|
488
522
|
}
|
|
489
523
|
|
|
490
524
|
const char* responseStr = litert_lm_json_response_get_string(response);
|
|
@@ -232,11 +232,18 @@ LITERT_LM_C_API_EXPORT
|
|
|
232
232
|
void litert_lm_engine_settings_set_num_decode_tokens(
|
|
233
233
|
LiteRtLmEngineSettings* settings, int num_decode_tokens);
|
|
234
234
|
|
|
235
|
+
// Returns the last error message from a failed C API call.
|
|
236
|
+
// Returns an empty string if no error has occurred.
|
|
237
|
+
// The returned pointer is valid until the next C API call on the same thread.
|
|
238
|
+
LITERT_LM_C_API_EXPORT
|
|
239
|
+
const char* litert_lm_get_last_error();
|
|
240
|
+
|
|
235
241
|
// Creates a LiteRT LM Engine from the given settings. The caller is responsible
|
|
236
242
|
// for destroying the engine using `litert_lm_engine_delete`.
|
|
237
243
|
//
|
|
238
244
|
// @param settings The engine settings.
|
|
239
245
|
// @return A pointer to the created engine, or NULL on failure.
|
|
246
|
+
// Call litert_lm_get_last_error() for details on failure.
|
|
240
247
|
LITERT_LM_C_API_EXPORT
|
|
241
248
|
LiteRtLmEngine* litert_lm_engine_create(const LiteRtLmEngineSettings* settings);
|
|
242
249
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-litert-lm",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "High-performance LLM inference for React Native using LiteRT-LM. Optimized for Gemma 3n and other on-device language models.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Hugh Chen (https://github.com/hung-yueh)",
|
|
@@ -57,6 +57,25 @@ fi
|
|
|
57
57
|
|
|
58
58
|
LITERT_SRC="$BUILD_DIR/LiteRT-LM"
|
|
59
59
|
|
|
60
|
+
# ---- 1b. Apply iOS-specific patches ---------------------------------------
|
|
61
|
+
# These patches fix:
|
|
62
|
+
# - mmap PROT_WRITE removal (iOS rejects CoW for large files)
|
|
63
|
+
# - Error capture API (litert_lm_get_last_error)
|
|
64
|
+
# - Engine registerer moved outside anonymous namespace (iOS linker stripping)
|
|
65
|
+
# - Minijinja/Rust stub replacement (custom C++ prompt template)
|
|
66
|
+
PATCHES_DIR="$PROJECT_ROOT/scripts/patches"
|
|
67
|
+
if [ -d "$PATCHES_DIR" ]; then
|
|
68
|
+
for PATCH_FILE in "$PATCHES_DIR"/*.patch; do
|
|
69
|
+
if [ -f "$PATCH_FILE" ]; then
|
|
70
|
+
echo " Applying patch: $(basename "$PATCH_FILE")..."
|
|
71
|
+
cd "$LITERT_SRC"
|
|
72
|
+
git apply --check "$PATCH_FILE" 2>/dev/null && \
|
|
73
|
+
git apply "$PATCH_FILE" || \
|
|
74
|
+
echo " (patch already applied or conflicts, skipping)"
|
|
75
|
+
fi
|
|
76
|
+
done
|
|
77
|
+
fi
|
|
78
|
+
|
|
60
79
|
# ---- 2. Verify Bazel is available -----------------------------------------
|
|
61
80
|
echo ""
|
|
62
81
|
echo "==> Step 2: Checking Bazel..."
|