react-native-executorch 0.10.2 → 0.10.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.
@@ -144,8 +144,13 @@ android {
144
144
  getByName("main") {
145
145
  // Prebuilt executorch + backend .so live under
146
146
  // third-party/android/libs/executorch/<abi>/. Pointing jniLibs here
147
- // makes Gradle package them (libexecutorch.so + the enabled
148
- // lib*_executorch_backend.so) into the APK alongside our own .so.
147
+ // makes Gradle package them into the APK alongside our own .so.
148
+ //
149
+ // Gradle packages every .so it finds under a jniLibs source dir, so
150
+ // this alone ships backends the app opted out of: -DRNE_ENABLE_* only
151
+ // stops CMake importing and linking them, which is enough for
152
+ // behaviour but has no bearing on packaging. `packaging.jniLibs
153
+ // .excludes` below drops the disabled ones back out.
149
154
  jniLibs.srcDirs("../third-party/android/libs/executorch")
150
155
  // Include generated codegen if using TurboModules
151
156
  java.srcDirs("${project.buildDir}/generated/source/codegen/java")
@@ -160,6 +165,25 @@ android {
160
165
  packaging {
161
166
  // Prevents "Duplicate Library" errors with the React Native JSI engine
162
167
  resources.excludes.add("**/libjsi.so")
168
+
169
+ // Ship only the backends the resolved config asks for. Without this an
170
+ // app declaring `backends: ["vulkan"]` still carries 2.67 MB of XNNPACK
171
+ // that nothing links, registers or loads, because jniLibs packages the
172
+ // directory rather than the link graph. This is the Android counterpart
173
+ // of the podspec deciding its -force_load entries from the same config.
174
+ //
175
+ // Keyed off the backend .so names rather than a staging dir so that a
176
+ // user who provisions third-party/ by hand gets the same treatment.
177
+ val backendLibs = mapOf(
178
+ "enableXnnpack" to "libxnnpack_executorch_backend.so",
179
+ "enableVulkan" to "libvulkan_executorch_backend.so"
180
+ )
181
+ for ((flag, soName) in backendLibs) {
182
+ if (rneConfig[flag] == false) {
183
+ logger.lifecycle("[RnExecutorch] $flag is off; excluding $soName from the APK")
184
+ jniLibs.excludes.add("**/$soName")
185
+ }
186
+ }
163
187
  }
164
188
 
165
189
  compileOptions {
@@ -11,6 +11,7 @@
11
11
  #include <algorithm>
12
12
  #include <cstring>
13
13
  #include <format>
14
+ #include <optional>
14
15
 
15
16
  #include <executorch/extension/llm/runner/constants.h>
16
17
  #include <executorch/extension/llm/runner/llm_runner_helper.h>
@@ -18,6 +19,8 @@
18
19
  #include <executorch/extension/llm/runner/multimodal_runner.h>
19
20
  #include <executorch/extension/llm/runner/stats.h>
20
21
  #include <executorch/extension/llm/runner/text_llm_runner.h>
22
+ #include <executorch/extension/llm/runner/text_prefiller.h>
23
+ #include <executorch/extension/module/module.h>
21
24
  #include <executorch/runtime/core/error.h>
22
25
 
23
26
  #include "core/conversions.h"
@@ -56,8 +59,8 @@ namespace {
56
59
  // COUPLING / MAINTENANCE WARNING:
57
60
  // This creates a direct compile-time coupling with the internal implementation
58
61
  // details of ExecuTorch's `TextLLMRunner` and `MultimodalRunner`. If upstream
59
- // ExecuTorch renames or alters `pos_`, `prefill_next_token_`, or `metadata_`,
60
- // this code will fail to compile and must be adjusted accordingly.
62
+ // ExecuTorch renames or alters any member accessed below, this code will fail
63
+ // to compile and must be adjusted accordingly.
61
64
  // ============================================================================
62
65
 
63
66
  template <typename Tag, auto MemberPtr>
@@ -95,6 +98,96 @@ constexpr auto getPrivateMember(MMRunnerPrefillTag /*tag*/);
95
98
  template struct PrivateMemberAccessor<MMRunnerMetadataTag, &MultimodalRunner::metadata_>;
96
99
  constexpr auto getPrivateMember(MMRunnerMetadataTag /*tag*/);
97
100
 
101
+ // Members that decide how a prompt is split into prefill chunks.
102
+ using executorch::extension::llm::TextPrefiller;
103
+
104
+ struct TextRunnerModuleTag {};
105
+ struct TextRunnerPrefillerTag {};
106
+ struct PrefillerMaxSeqLenTag {};
107
+ struct MMRunnerModuleTag {};
108
+ struct MMRunnerTokenizerTag {};
109
+
110
+ template struct PrivateMemberAccessor<TextRunnerModuleTag, &TextLLMRunner::module_>;
111
+ constexpr auto getPrivateMember(TextRunnerModuleTag /*tag*/);
112
+
113
+ template struct PrivateMemberAccessor<TextRunnerPrefillerTag, &TextLLMRunner::text_prefiller_>;
114
+ constexpr auto getPrivateMember(TextRunnerPrefillerTag /*tag*/);
115
+
116
+ template struct PrivateMemberAccessor<PrefillerMaxSeqLenTag, &TextPrefiller::max_seq_len_>;
117
+ constexpr auto getPrivateMember(PrefillerMaxSeqLenTag /*tag*/);
118
+
119
+ template struct PrivateMemberAccessor<MMRunnerModuleTag, &MultimodalRunner::module_>;
120
+ constexpr auto getPrivateMember(MMRunnerModuleTag /*tag*/);
121
+
122
+ template struct PrivateMemberAccessor<MMRunnerTokenizerTag, &MultimodalRunner::tokenizer_>;
123
+ constexpr auto getPrivateMember(MMRunnerTokenizerTag /*tag*/);
124
+
125
+ // Upstream sizes prefill chunks from `get_max_seq_len`, which is the KV budget,
126
+ // not the widest token input the graph accepts (e.g. gemma4 MLX: 2048 vs 511).
127
+ // Prompts past the real bound then fail with `Error::NotSupported`. Returns the
128
+ // bound declared by the method's first input, or nullopt if it is not a
129
+ // rank>=2 integer tensor.
130
+ std::optional<int64_t> readPrefillBound(executorch::extension::Module *module, const std::string &methodName) {
131
+ if (module == nullptr) {
132
+ return std::nullopt;
133
+ }
134
+ auto meta = module->method_meta(methodName);
135
+ if (!meta.ok() || meta->num_inputs() == 0) {
136
+ return std::nullopt;
137
+ }
138
+ auto inputMeta = meta->input_tensor_meta(0);
139
+ if (!inputMeta.ok()) {
140
+ return std::nullopt;
141
+ }
142
+ const auto dtype = inputMeta->scalar_type();
143
+ if (dtype != executorch::aten::ScalarType::Long && dtype != executorch::aten::ScalarType::Int) {
144
+ return std::nullopt;
145
+ }
146
+ const auto sizes = inputMeta->sizes();
147
+ if (sizes.size() < 2) {
148
+ return std::nullopt;
149
+ }
150
+ const auto bound = static_cast<int64_t>(sizes[sizes.size() - 1]);
151
+ if (bound <= 0) {
152
+ return std::nullopt;
153
+ }
154
+ return bound;
155
+ }
156
+
157
+ ::tokenizers::Tokenizer *getRunnerTokenizer(executorch::extension::llm::IRunner *runner) {
158
+ auto *r = dynamic_cast<MultimodalRunner *>(runner);
159
+ if (r == nullptr) {
160
+ return nullptr;
161
+ }
162
+ return (r->*getPrivateMember(MMRunnerTokenizerTag{})).get();
163
+ }
164
+
165
+ // `MultimodalPrefiller` does not chunk, so split text into token inputs that fit
166
+ // the bound; `MultimodalRunner` prefills them in order.
167
+ void appendTextInput(std::vector<executorch::extension::llm::MultimodalInput> &inputs,
168
+ std::string text,
169
+ ::tokenizers::Tokenizer *tokenizer,
170
+ int64_t prefillBound) {
171
+ if (tokenizer == nullptr || prefillBound <= 0) {
172
+ inputs.emplace_back(std::move(text));
173
+ return;
174
+ }
175
+
176
+ auto encoded = tokenizer->encode(text, 0, 0);
177
+ if (!encoded.ok()) {
178
+ inputs.emplace_back(std::move(text));
179
+ return;
180
+ }
181
+
182
+ const auto &tokens = encoded.get();
183
+ const auto chunk = static_cast<size_t>(prefillBound);
184
+ for (size_t offset = 0; offset < tokens.size(); offset += chunk) {
185
+ const auto end = std::min(offset + chunk, tokens.size());
186
+ inputs.emplace_back(std::vector<uint64_t>(tokens.begin() + static_cast<ptrdiff_t>(offset),
187
+ tokens.begin() + static_cast<ptrdiff_t>(end)));
188
+ }
189
+ }
190
+
98
191
  int64_t getRunnerPos(executorch::extension::llm::IRunner *runner, bool isMultimodal) {
99
192
  if (runner == nullptr) {
100
193
  return 0;
@@ -178,10 +271,14 @@ std::vector<executorch::extension::llm::MultimodalInput> parsePrompt(
178
271
  jsi::Runtime &rt,
179
272
  const std::string &ctx,
180
273
  const jsi::Value &value,
181
- const std::vector<std::string> &supportedModalities) {
274
+ const std::vector<std::string> &supportedModalities,
275
+ ::tokenizers::Tokenizer *tokenizer,
276
+ int64_t prefillBound) {
182
277
 
183
278
  if (value.isString()) {
184
- return {executorch::extension::llm::MultimodalInput(conversions::asType<std::string>(rt, ctx, value))};
279
+ std::vector<executorch::extension::llm::MultimodalInput> inputs;
280
+ appendTextInput(inputs, conversions::asType<std::string>(rt, ctx, value), tokenizer, prefillBound);
281
+ return inputs;
185
282
  }
186
283
 
187
284
  auto arr = conversions::asType<jsi::Array>(rt, ctx, value);
@@ -195,7 +292,7 @@ std::vector<executorch::extension::llm::MultimodalInput> parsePrompt(
195
292
  std::string itemCtx = std::format("{}[{}]", ctx, i);
196
293
 
197
294
  if (elem.isString()) {
198
- inputs.emplace_back(conversions::asType<std::string>(rt, itemCtx, elem));
295
+ appendTextInput(inputs, conversions::asType<std::string>(rt, itemCtx, elem), tokenizer, prefillBound);
199
296
  continue;
200
297
  }
201
298
  auto mediaObj = conversions::asType<jsi::Object>(rt, itemCtx, elem);
@@ -254,10 +351,16 @@ LLMRunnerHostObject::LLMRunnerHostObject(const std::string &modelPath,
254
351
  throw error::LoadFailed(std::format("LLMRunner: Failed to load runner tokenizer at path: {}", tokenizerPath));
255
352
  }
256
353
 
354
+ // Plain mmap leaves the weights as clean, file-backed pages the kernel
355
+ // can evict, which is what the legacy binding has always passed.
356
+ constexpr auto kLoadMode = executorch::extension::Module::LoadMode::Mmap;
357
+
257
358
  if (modalities_.empty()) {
258
- runner_ = executorch::extension::llm::create_text_llm_runner(modelPath, std::move(tokenizer));
359
+ runner_ = executorch::extension::llm::create_text_llm_runner(
360
+ modelPath, std::move(tokenizer), std::nullopt, -1.0f, "forward", kLoadMode);
259
361
  } else {
260
- runner_ = executorch::extension::llm::create_multimodal_runner(modelPath, std::move(tokenizer));
362
+ runner_ = executorch::extension::llm::create_multimodal_runner(
363
+ modelPath, std::move(tokenizer), std::nullopt, kLoadMode);
261
364
  }
262
365
 
263
366
  if (!runner_) {
@@ -269,6 +372,33 @@ LLMRunnerHostObject::LLMRunnerHostObject(const std::string &modelPath,
269
372
  std::string errorMsg = executorch::runtime::to_string(loadStatus);
270
373
  throw error::LoadFailed(std::format("LLMRunner: Failed to load model: {}", errorMsg), loadStatus);
271
374
  }
375
+
376
+ // Clamp prefill chunks to the graph's real bound (see `readPrefillBound`).
377
+ // Text models take tokens on `forward`, multimodal ones on `token_embedding`.
378
+ if (modalities_.empty()) {
379
+ auto *textRunner = dynamic_cast<TextLLMRunner *>(runner_.get());
380
+ if (textRunner != nullptr) {
381
+ const auto &module = textRunner->*getPrivateMember(TextRunnerModuleTag{});
382
+ const auto bound = readPrefillBound(module.get(), "forward");
383
+ auto &prefiller = textRunner->*getPrivateMember(TextRunnerPrefillerTag{});
384
+ if (bound.has_value() && prefiller) {
385
+ // Upstream allows max_seq_len < max_context_len and chunks itself.
386
+ auto &maxSeqLen = (*prefiller).*getPrivateMember(PrefillerMaxSeqLenTag{});
387
+ maxSeqLen = std::min(maxSeqLen, *bound);
388
+ prefillBound_ = maxSeqLen;
389
+ }
390
+ }
391
+ } else {
392
+ auto *mmRunner = dynamic_cast<MultimodalRunner *>(runner_.get());
393
+ if (mmRunner != nullptr) {
394
+ const auto &module = mmRunner->*getPrivateMember(MMRunnerModuleTag{});
395
+ const auto bound =
396
+ readPrefillBound(module.get(), executorch::extension::llm::kTokenEmbeddingMethod);
397
+ if (bound.has_value()) {
398
+ prefillBound_ = *bound;
399
+ }
400
+ }
401
+ }
272
402
  }
273
403
 
274
404
  std::unique_lock<std::mutex> LLMRunnerHostObject::tryLockUnique(std::string_view ctx) {
@@ -305,11 +435,9 @@ jsi::Value LLMRunnerHostObject::get(jsi::Runtime &rt, const jsi::PropNameID &nam
305
435
  }
306
436
 
307
437
  executorch::extension::llm::GenerationConfig config;
438
+ config.echo = false;
308
439
  if (count > 1 && !args[1].isUndefined() && !args[1].isNull()) {
309
440
  auto configObj = conversions::asType<jsi::Object>(rt, "LLMRunner.generate: config", args[1]);
310
- if (auto echoOpt = conversions::getOptionalProperty<bool>(rt, "LLMRunner.generate: config", configObj, "echo")) {
311
- config.echo = *echoOpt;
312
- }
313
441
  if (auto ignoreEosOpt = conversions::getOptionalProperty<bool>(rt, "LLMRunner.generate: config", configObj, "ignoreEos")) {
314
442
  config.ignore_eos = *ignoreEosOpt;
315
443
  }
@@ -348,7 +476,8 @@ jsi::Value LLMRunnerHostObject::get(jsi::Runtime &rt, const jsi::PropNameID &nam
348
476
  auto prompt = conversions::asType<std::string>(rt, "LLMRunner.generate: prompt", args[0]);
349
477
  genStatus = self->runner_->generate(prompt, config, tokenCallback, statsCallback);
350
478
  } else {
351
- auto inputs = parsePrompt(rt, "LLMRunner.generate", args[0], self->modalities_);
479
+ auto inputs = parsePrompt(rt, "LLMRunner.generate", args[0], self->modalities_,
480
+ getRunnerTokenizer(self->runner_.get()), self->prefillBound_);
352
481
  auto *multimodalRunner = dynamic_cast<executorch::extension::llm::MultimodalRunner *>(self->runner_.get());
353
482
  if (multimodalRunner == nullptr) {
354
483
  throw error::InvalidArgument("LLMRunner.generate: Runner instance is not a multimodal model");
@@ -375,7 +504,8 @@ jsi::Value LLMRunnerHostObject::get(jsi::Runtime &rt, const jsi::PropNameID &nam
375
504
 
376
505
  auto lock = self->tryLockUnique("LLMRunner.prefill");
377
506
 
378
- auto inputs = parsePrompt(rt, "LLMRunner.prefill", args[0], self->modalities_);
507
+ auto inputs = parsePrompt(rt, "LLMRunner.prefill", args[0], self->modalities_,
508
+ getRunnerTokenizer(self->runner_.get()), self->prefillBound_);
379
509
  auto result = self->runner_->prefill(inputs);
380
510
 
381
511
  if (!result.ok()) {
@@ -8,6 +8,7 @@
8
8
  #pragma clang diagnostic ignored "-Wdeprecated-declarations"
9
9
  #endif
10
10
 
11
+ #include <cstdint>
11
12
  #include <memory>
12
13
  #include <mutex>
13
14
  #include <string>
@@ -77,6 +78,12 @@ private:
77
78
  std::string tokenizerPath_;
78
79
  /** List of supported non-text input modalities. */
79
80
  std::vector<std::string> modalities_;
81
+ /**
82
+ * Longest token sequence the loaded graph accepts in one prefill step, read
83
+ * off the model's own method metadata. 0 when the model does not declare
84
+ * one, in which case prompts are passed through unsplit.
85
+ */
86
+ int64_t prefillBound_ = 0;
80
87
  };
81
88
 
82
89
  void install_createLLMRunner(facebook::jsi::Runtime &rt, facebook::jsi::Object &module);
@@ -1 +1 @@
1
- {"version":3,"names":["rnexecutorchJsi","createLLMRunner","modelPath","tokenizerPath","modalities","llm"],"sourceRoot":"../../../../src","sources":["extensions/llm/llmRunner.ts"],"mappings":";;AAAA;AACA;AACA;;AAGA,SAASA,eAAe,QAAQ,wBAAqB;;AAIrD;AACA;AACA;AACA;AACA;;AAYA;AACA;AACA;AACA;AACA;;AAoBA;AACA;AACA;AACA;AACA;;AAKA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;;AAyDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,eAAeA,CAC7BC,SAAiB,EACjBC,aAAqB,EACrBC,UAAgC,EACrB;EACX,SAAS;;EACT,OAAOJ,eAAe,CAACK,GAAG,CAACJ,eAAe,CAACC,SAAS,EAAEC,aAAa,EAAEC,UAAU,IAAI,EAAE,CAAC;AACxF","ignoreList":[]}
1
+ {"version":3,"names":["rnexecutorchJsi","createLLMRunner","modelPath","tokenizerPath","modalities","llm"],"sourceRoot":"../../../../src","sources":["extensions/llm/llmRunner.ts"],"mappings":";;AAAA;AACA;AACA;;AAGA,SAASA,eAAe,QAAQ,wBAAqB;;AAIrD;AACA;AACA;AACA;AACA;;AAUA;AACA;AACA;AACA;AACA;;AAoBA;AACA;AACA;AACA;AACA;;AAKA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;;AAyDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,eAAeA,CAC7BC,SAAiB,EACjBC,aAAqB,EACrBC,UAAgC,EACrB;EACX,SAAS;;EACT,OAAOJ,eAAe,CAACK,GAAG,CAACJ,eAAe,CAACC,SAAS,EAAEC,aAAa,EAAEC,UAAU,IAAI,EAAE,CAAC;AACxF","ignoreList":[]}
@@ -43,13 +43,13 @@ function generateChatTurnWorklet(runner, prompt, options) {
43
43
 
44
44
  const {
45
45
  genConfig,
46
- eosToken,
46
+ stopTokens,
47
47
  stopRegex,
48
48
  onToken
49
49
  } = options;
50
50
  let response = '';
51
51
  const callback = token => {
52
- if (token === eosToken) return;
52
+ if (stopTokens.includes(token)) return;
53
53
  response += token;
54
54
  if (onToken) scheduleOnRN(onToken, token);
55
55
  if (stopRegex?.test(response)) runner.stop();
@@ -99,7 +99,7 @@ export async function createLLMChatSession(config, options = {}, runtime) {
99
99
  const tokenizerConfig = parseTokenizerConfig(JSON.parse(tokenizerConfigStr));
100
100
  const {
101
101
  chatTemplate,
102
- eosToken
102
+ stopTokens
103
103
  } = tokenizerConfig;
104
104
 
105
105
  // Prepare chat preprocessor
@@ -139,7 +139,7 @@ export async function createLLMChatSession(config, options = {}, runtime) {
139
139
  };
140
140
  const generationOpts = {
141
141
  genConfig: turnGenConfig,
142
- eosToken,
142
+ stopTokens,
143
143
  stopRegex,
144
144
  onToken
145
145
  };
@@ -1 +1 @@
1
- {"version":3,"names":["scheduleOnRN","RNBlobUtil","wrapAsync","createResourceScope","createLLMRunner","parseTokenizerConfig","createChatPreprocessor","generateChatTurnWorklet","runner","prompt","options","genConfig","eosToken","stopRegex","onToken","response","callback","token","test","stop","stats","generate","DEFAULT_MAX_TURNS","createLLMChatSession","config","runtime","scope","dispose","generationConfig","defaultGenerationConfig","initialMessages","toolOpts","resetOnTurn","modelPath","tokenizerPath","tokenizerConfigPath","modalities","preprocessorConfig","tools","parseToolCalls","maxToolTurns","tokenizerConfigStr","fs","readFile","tokenizerConfig","JSON","parse","chatTemplate","chatPreprocessorConfig","chatPreprocessor","track","prefill","history","committed","length","push","process","addGenPrompt","clear","generateChatTurn","sendMessage","message","turnGenConfig","generationOpts","initialCommitted","initialPos","getKVCacheState","pos","turnStartIdx","generationStatsList","role","content","reset","prefillStartMs","Date","now","toCommit","userPrompt","posAtEndOfUser","finishReason","currentTurn","uncommitted","prefillDurationMs","parsedTools","toolCalls","textContent","toolCall","tool","find","t","function","name","toolContent","execute","arguments","err","String","toolCallId","id","messages","slice","getHistory","error"],"sourceRoot":"../../../../../src","sources":["extensions/llm/tasks/llmChatSession.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["scheduleOnRN","RNBlobUtil","wrapAsync","createResourceScope","createLLMRunner","parseTokenizerConfig","createChatPreprocessor","generateChatTurnWorklet","runner","prompt","options","genConfig","stopTokens","stopRegex","onToken","response","callback","token","includes","test","stop","stats","generate","DEFAULT_MAX_TURNS","createLLMChatSession","config","runtime","scope","dispose","generationConfig","defaultGenerationConfig","initialMessages","toolOpts","resetOnTurn","modelPath","tokenizerPath","tokenizerConfigPath","modalities","preprocessorConfig","tools","parseToolCalls","maxToolTurns","tokenizerConfigStr","fs","readFile","tokenizerConfig","JSON","parse","chatTemplate","chatPreprocessorConfig","chatPreprocessor","track","prefill","history","committed","length","push","process","addGenPrompt","clear","generateChatTurn","sendMessage","message","turnGenConfig","generationOpts","initialCommitted","initialPos","getKVCacheState","pos","turnStartIdx","generationStatsList","role","content","reset","prefillStartMs","Date","now","toCommit","userPrompt","posAtEndOfUser","finishReason","currentTurn","uncommitted","prefillDurationMs","parsedTools","toolCalls","textContent","toolCall","tool","find","t","function","name","toolContent","execute","arguments","err","String","toolCallId","id","messages","slice","getHistory","error"],"sourceRoot":"../../../../../src","sources":["extensions/llm/tasks/llmChatSession.ts"],"mappings":"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","ignoreList":[]}
@@ -43,9 +43,11 @@ export function parseTokenizerConfig(config) {
43
43
  if (!eosToken) {
44
44
  throw RnExecuTorchError('LOAD_FAILED', 'tokenizer_config.json does not define required `eos_token` string');
45
45
  }
46
+ const stopTokens = [eosToken, resolveToken(config.eot_token), resolveToken(config.pad_token)].filter((token, index, all) => !!token && all.indexOf(token) === index);
46
47
  return {
47
48
  chatTemplate,
48
- eosToken
49
+ eosToken,
50
+ stopTokens
49
51
  };
50
52
  }
51
53
  //# sourceMappingURL=tokenizerConfig.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["RnExecuTorchError","resolveToken","token","content","undefined","parseTokenizerConfig","config","chatTemplate","chat_template","Array","isArray","entry","find","t","name","template","eosToken","eos_token"],"sourceRoot":"../../../../../src","sources":["extensions/llm/utils/tokenizerConfig.ts"],"mappings":";;AAAA;AACA;AACA;AACA;;AAEA,SAASA,iBAAiB,QAAQ,wBAAqB;;AAEvD;AACA;AACA;AACA;;AAQA,SAASC,YAAYA,CAACC,KAAc,EAAsB;EACxD,IAAI,OAAOA,KAAK,KAAK,QAAQ,EAAE,OAAOA,KAAK;EAC3C,IAAIA,KAAK,IAAI,OAAOA,KAAK,KAAK,QAAQ,IAAI,OAAQA,KAAK,CAASC,OAAO,KAAK,QAAQ,EAAE;IACpF,OAAQD,KAAK,CAASC,OAAO;EAC/B;EACA,OAAOC,SAAS;AAClB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,oBAAoBA,CAACC,MAAW,EAAuB;EACrE,IAAIC,YAAY,GAAGD,MAAM,CAACE,aAAa;;EAEvC;EACA,IAAIC,KAAK,CAACC,OAAO,CAACH,YAAY,CAAC,EAAE;IAC/B,MAAMI,KAAK,GAAGJ,YAAY,CAACK,IAAI,CAAEC,CAAC,IAAKA,CAAC,EAAEC,IAAI,KAAK,SAAS,CAAC,IAAIP,YAAY,CAAC,CAAC,CAAC;IAChFA,YAAY,GAAGI,KAAK,EAAEI,QAAQ;EAChC;EAEA,IAAI,OAAOR,YAAY,KAAK,QAAQ,EAAE;IACpC,MAAMP,iBAAiB,CACrB,aAAa,EACb,iEACF,CAAC;EACH;EAEA,MAAMgB,QAAQ,GAAGf,YAAY,CAACK,MAAM,CAACW,SAAS,CAAC;EAE/C,IAAI,CAACD,QAAQ,EAAE;IACb,MAAMhB,iBAAiB,CACrB,aAAa,EACb,mEACF,CAAC;EACH;EAEA,OAAO;IAAEO,YAAY;IAAES;EAAS,CAAC;AACnC","ignoreList":[]}
1
+ {"version":3,"names":["RnExecuTorchError","resolveToken","token","content","undefined","parseTokenizerConfig","config","chatTemplate","chat_template","Array","isArray","entry","find","t","name","template","eosToken","eos_token","stopTokens","eot_token","pad_token","filter","index","all","indexOf"],"sourceRoot":"../../../../../src","sources":["extensions/llm/utils/tokenizerConfig.ts"],"mappings":";;AAAA;AACA;AACA;AACA;;AAEA,SAASA,iBAAiB,QAAQ,wBAAqB;;AAEvD;AACA;AACA;AACA;;AAYA,SAASC,YAAYA,CAACC,KAAc,EAAsB;EACxD,IAAI,OAAOA,KAAK,KAAK,QAAQ,EAAE,OAAOA,KAAK;EAC3C,IAAIA,KAAK,IAAI,OAAOA,KAAK,KAAK,QAAQ,IAAI,OAAQA,KAAK,CAASC,OAAO,KAAK,QAAQ,EAAE;IACpF,OAAQD,KAAK,CAASC,OAAO;EAC/B;EACA,OAAOC,SAAS;AAClB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,oBAAoBA,CAACC,MAAW,EAAuB;EACrE,IAAIC,YAAY,GAAGD,MAAM,CAACE,aAAa;;EAEvC;EACA,IAAIC,KAAK,CAACC,OAAO,CAACH,YAAY,CAAC,EAAE;IAC/B,MAAMI,KAAK,GAAGJ,YAAY,CAACK,IAAI,CAAEC,CAAC,IAAKA,CAAC,EAAEC,IAAI,KAAK,SAAS,CAAC,IAAIP,YAAY,CAAC,CAAC,CAAC;IAChFA,YAAY,GAAGI,KAAK,EAAEI,QAAQ;EAChC;EAEA,IAAI,OAAOR,YAAY,KAAK,QAAQ,EAAE;IACpC,MAAMP,iBAAiB,CACrB,aAAa,EACb,iEACF,CAAC;EACH;EAEA,MAAMgB,QAAQ,GAAGf,YAAY,CAACK,MAAM,CAACW,SAAS,CAAC;EAE/C,IAAI,CAACD,QAAQ,EAAE;IACb,MAAMhB,iBAAiB,CACrB,aAAa,EACb,mEACF,CAAC;EACH;EAEA,MAAMkB,UAAU,GAAG,CACjBF,QAAQ,EACRf,YAAY,CAACK,MAAM,CAACa,SAAS,CAAC,EAC9BlB,YAAY,CAACK,MAAM,CAACc,SAAS,CAAC,CAC/B,CAACC,MAAM,CAAC,CAACnB,KAAK,EAAEoB,KAAK,EAAEC,GAAG,KAAsB,CAAC,CAACrB,KAAK,IAAIqB,GAAG,CAACC,OAAO,CAACtB,KAAK,CAAC,KAAKoB,KAAK,CAAC;EAEzF,OAAO;IAAEf,YAAY;IAAES,QAAQ;IAAEE;EAAW,CAAC;AAC/C","ignoreList":[]}
@@ -12,7 +12,7 @@ const DOWNLOAD_EVENT_ENDPOINT = 'https://ai.swmansion.com/telemetry/downloads/ap
12
12
  // self-referencing import would need package `exports` support in the consuming
13
13
  // bundler to load at all. A wrong value here is analytics noise; a failed
14
14
  // import would break the bundle.
15
- const LIB_VERSION = '0.10.2';
15
+ const LIB_VERSION = '0.10.3';
16
16
 
17
17
  // Anonymous analytics are on by default; apps opt out via setTelemetryEnabled.
18
18
  let telemetryEnabled = true;
@@ -8,8 +8,6 @@ import type { Tensor } from '../../core/tensor';
8
8
  * @category LLM / Types
9
9
  */
10
10
  export type LLMGenerationConfig = {
11
- /** Whether to echo the prompt in the generated output. */
12
- readonly echo?: boolean;
13
11
  /** Whether to ignore EOS tokens during generation. */
14
12
  readonly ignoreEos?: boolean;
15
13
  /** Maximum number of new tokens to generate. */
@@ -1 +1 @@
1
- {"version":3,"file":"llmRunner.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/llm/llmRunner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"llmRunner.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/llm/llmRunner.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,10 @@ export type TokenizerChatConfig = {
11
11
  readonly chatTemplate: string;
12
12
  /** End-of-sequence token string. */
13
13
  readonly eosToken: string;
14
+ /**
15
+ * Every terminal token the model may decode into its output.
16
+ */
17
+ readonly stopTokens: readonly string[];
14
18
  };
15
19
  /**
16
20
  * Parses raw JSON configuration from `tokenizer_config.json` into a normalized format.
@@ -1 +1 @@
1
- {"version":3,"file":"tokenizerConfig.d.ts","sourceRoot":"","sources":["../../../../../../src/extensions/llm/utils/tokenizerConfig.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,uDAAuD;IACvD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC;AAUF;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,GAAG,GAAG,mBAAmB,CA0BrE"}
1
+ {"version":3,"file":"tokenizerConfig.d.ts","sourceRoot":"","sources":["../../../../../../src/extensions/llm/utils/tokenizerConfig.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,uDAAuD;IACvD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC,CAAC;AAUF;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,GAAG,GAAG,mBAAmB,CAgCrE"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "react-native-executorch",
3
- "version": "0.10.2",
4
- "nativeLibsVersion": "0.10.0",
3
+ "version": "0.10.3",
4
+ "nativeLibsVersion": "0.10.4",
5
5
  "description": "An easy way to run AI models in React Native with ExecuTorch",
6
6
  "main": "./lib/module/index.js",
7
7
  "module": "./lib/module/index.js",
@@ -11,9 +11,10 @@
11
11
  *
12
12
  * headers.tar.gz -- ExecuTorch + c10 + torch + tokenizers + opencv
13
13
  * headers (platform-independent; always downloaded)
14
- * core-android-arm64-v8a.tar.gz -- executorch, pthreadpool, cpuinfo for arm64
15
- * core-android-x86_64.tar.gz -- executorch for x86_64
16
- * core-ios.tar.gz -- ExecutorchLib.xcframework (without xnnpack/coreml)
14
+ * core-android-arm64-v8a.tar.gz -- libexecutorch.so (+ executorch.jar) for arm64;
15
+ * pthreadpool and cpuinfo are statically linked in
16
+ * core-android-x86_64.tar.gz -- libexecutorch.so for x86_64
17
+ * core-ios.tar.gz -- ExecutorchLib.xcframework + libthreadpool_*.a
17
18
  * opencv-android-arm64-v8a.tar.gz -- OpenCV for arm64
18
19
  * opencv-android-x86_64.tar.gz -- OpenCV for x86_64
19
20
  * opencv-ios.tar.gz -- OpenCV xcframework
@@ -74,7 +75,9 @@ const https = require('https');
74
75
  const http = require('http');
75
76
  const fs = require('fs');
76
77
  const path = require('path');
77
- const { execSync } = require('child_process');
78
+ const { spawnSync } = require('child_process');
79
+ const { createHash } = require('crypto');
80
+ const { Buffer } = require('buffer');
78
81
 
79
82
  // ---- Config ----------------------------------------------------------------
80
83
 
@@ -151,8 +154,10 @@ const FEATURE_MAP = {
151
154
  // YOLO is xnnpack-only, ssdlite/rf_detr add coreml → union.
152
155
  objectDetection: { backends: ['xnnpack', 'coreml'], libs: ['opencv'] },
153
156
  // Keypoint detection (#1280): BlazeFace + YOLO26-pose ship xnnpack; RF-DETR
154
- // keypoint adds coreml + mlx → union. (Named to track the useKeypointDetector
155
- // hook; main calls this poseEstimation.)
157
+ // keypoint adds coreml → union. mlx stays for the legacy API, whose
158
+ // RF_DETR_KEYPOINT_PREVIEW_MLX_FP32_MODEL outlived the new registry's MLX
159
+ // keypoint export (dropped in #1418).
160
+ // (Named to track the useKeypointDetector hook; main calls this poseEstimation.)
156
161
  keypointDetection: { backends: ['xnnpack', 'coreml', 'mlx'], libs: ['opencv'] },
157
162
  // DeepLab/FCN/LR-ASPP/selfie all ship xnnpack + coreml.
158
163
  semanticSegmentation: { backends: ['xnnpack', 'coreml'], libs: ['opencv'] },
@@ -431,15 +436,33 @@ function download(url, dest) {
431
436
  };
432
437
  get(url);
433
438
  file.on('error', (err) => {
434
- fs.unlinkSync(dest);
439
+ // Close before removing: on Windows an open handle makes the unlink fail
440
+ // with EBUSY, which then replaces the real error with the cleanup's. And
441
+ // `force` covers the case where the file was never created.
442
+ file.close(() => fs.rmSync(dest, { force: true }));
435
443
  reject(err);
436
444
  });
437
445
  });
438
446
  }
439
447
 
448
+ // Hashes in-process rather than shelling out to `sha256sum` / `shasum`. Those
449
+ // are not on PATH everywhere, and GNU `sha256sum` escapes a filename holding a
450
+ // backslash by prefixing its whole output line with one -- so on Windows every
451
+ // hash came back as `\<hex>` and no artifact could ever validate. Read in
452
+ // chunks: some artifacts are hundreds of megabytes and this runs at install.
440
453
  function sha256(filePath) {
441
- const result = execSync(`sha256sum "${filePath}" || shasum -a 256 "${filePath}"`);
442
- return result.toString().split(' ')[0].trim();
454
+ const hash = createHash('sha256');
455
+ const buffer = Buffer.alloc(1024 * 1024);
456
+ const fd = fs.openSync(filePath, 'r');
457
+ try {
458
+ let bytesRead;
459
+ while ((bytesRead = fs.readSync(fd, buffer, 0, buffer.length, null)) > 0) {
460
+ hash.update(buffer.subarray(0, bytesRead));
461
+ }
462
+ } finally {
463
+ fs.closeSync(fd);
464
+ }
465
+ return hash.digest('hex');
443
466
  }
444
467
 
445
468
  async function isCacheValid(artifact) {
@@ -461,6 +484,68 @@ async function isCacheValid(artifact) {
461
484
  return expectedChecksum === actualChecksum;
462
485
  }
463
486
 
487
+ // The backend binaries each artifact owns, relative to the extraction dir. Used
488
+ // to clear stale copies: nothing else removes them, and `isCacheValid()`
489
+ // short-circuits the download, so turning a backend OFF after an install would
490
+ // otherwise leave the old binary in place and (on Android) keep shipping it.
491
+ const BACKEND_FILES = {
492
+ android: {
493
+ xnnpack: ['executorch/*/libxnnpack_executorch_backend.so'],
494
+ vulkan: ['executorch/*/libvulkan_executorch_backend.so'],
495
+ },
496
+ ios: {
497
+ xnnpack: ['XnnpackBackend.xcframework'],
498
+ coreml: ['CoreMLBackend.xcframework'],
499
+ mlx: ['MLXBackend.xcframework', 'libs/executorch/mlx.metallib'],
500
+ },
501
+ };
502
+
503
+ // Removes the binaries of backends the resolved config does not ask for, so a
504
+ // config change takes effect without anyone deleting third-party/ by hand.
505
+ function pruneDisabledBackends(targets, { backends }) {
506
+ for (const target of targets) {
507
+ const platform = target.startsWith('android') ? 'android' : 'ios';
508
+ const destDir =
509
+ platform === 'android'
510
+ ? path.join(THIRD_PARTY_DIR, 'android', 'libs')
511
+ : path.join(THIRD_PARTY_DIR, 'ios');
512
+ if (!fs.existsSync(destDir)) continue;
513
+
514
+ for (const [backend, patterns] of Object.entries(BACKEND_FILES[platform])) {
515
+ if (backends.includes(backend)) continue;
516
+ for (const pattern of patterns) {
517
+ for (const stale of expandPattern(destDir, pattern)) {
518
+ console.log(
519
+ `[react-native-executorch] Removing ${backend} binary (not enabled): ${path.relative(THIRD_PARTY_DIR, stale)}`
520
+ );
521
+ fs.rmSync(stale, { recursive: true, force: true });
522
+ }
523
+ }
524
+ }
525
+ }
526
+ }
527
+
528
+ // Resolves a path that may contain a single `*` segment (the Android ABI dir).
529
+ // A dependency-free stand-in for a glob, since this script runs at postinstall
530
+ // with nothing but Node's stdlib available.
531
+ function expandPattern(root, pattern) {
532
+ const segments = pattern.split('/');
533
+ let candidates = [root];
534
+ for (const segment of segments) {
535
+ const next = [];
536
+ for (const base of candidates) {
537
+ if (segment === '*') {
538
+ if (!fs.existsSync(base)) continue;
539
+ for (const entry of fs.readdirSync(base)) next.push(path.join(base, entry));
540
+ } else {
541
+ next.push(path.join(base, segment));
542
+ }
543
+ }
544
+ candidates = next;
545
+ }
546
+ return candidates.filter((candidate) => fs.existsSync(candidate));
547
+ }
548
+
464
549
  function extract(tarball, destDir) {
465
550
  ensureDir(destDir);
466
551
  // `-m` stamps extracted files with the extraction time instead of the mtime
@@ -471,7 +556,36 @@ function extract(tarball, destDir) {
471
556
  // and they get archived and linked against the new libraries -- which shows
472
557
  // up as an undefined symbol for whatever API changed between the two
473
558
  // releases, far away from the actual cause.
474
- execSync(`tar -xzmf "${tarball}" -C "${destDir}"`);
559
+ //
560
+ // No path reaches tar's argv, because GNU tar (Git for Windows' is the one
561
+ // on PATH under Git Bash) mangles Windows paths two ways: `-f C:\Users\...`
562
+ // is the `host:file` form, so it tries to reach a remote host named `C`; and
563
+ // `-C` is unquoted by default, so the `\r` and `\t` in
564
+ // `node_modules\react-native-executorch\third-party` become a carriage
565
+ // return and a tab. The archive arrives on stdin and `cwd` does the chdir.
566
+ const fd = fs.openSync(tarball, 'r');
567
+ let result;
568
+ try {
569
+ result = spawnSync('tar', ['-xzm', '-f', '-'], {
570
+ cwd: destDir,
571
+ stdio: [fd, 'inherit', 'pipe'],
572
+ encoding: 'utf8',
573
+ });
574
+ } finally {
575
+ fs.closeSync(fd);
576
+ }
577
+ if (result.error) {
578
+ throw new Error(
579
+ `Could not run \`tar\` to extract ${tarball}: ${result.error.message}. ` +
580
+ 'Install tar (it ships with Windows 10 1803+, Git for Windows and every Unix) and reinstall.'
581
+ );
582
+ }
583
+ if (result.status !== 0) {
584
+ throw new Error(
585
+ `tar exited with ${result.status ?? result.signal} while extracting ${tarball}` +
586
+ `${result.stderr ? `:\n${result.stderr.trim()}` : ''}`
587
+ );
588
+ }
475
589
  }
476
590
 
477
591
  // ---- Main ------------------------------------------------------------------
@@ -525,6 +639,10 @@ async function main() {
525
639
  console.log(` ✓ Done`);
526
640
  }
527
641
 
642
+ // Belt and braces to core no longer carrying backends: this also clears
643
+ // binaries left by an EARLIER install that had the backend enabled.
644
+ pruneDisabledBackends(targets, config);
645
+
528
646
  console.log('[react-native-executorch] Native libs ready.');
529
647
  }
530
648
 
@@ -536,4 +654,14 @@ if (require.main === module) {
536
654
  });
537
655
  }
538
656
 
539
- module.exports = { ALL_BACKENDS, ALL_LIBS, FEATURE_MAP, findUserConfig, readUserConfig };
657
+ module.exports = {
658
+ ALL_BACKENDS,
659
+ ALL_LIBS,
660
+ BACKEND_FILES,
661
+ FEATURE_MAP,
662
+ findUserConfig,
663
+ readUserConfig,
664
+ pruneDisabledBackends,
665
+ sha256,
666
+ extract,
667
+ };
@@ -13,8 +13,6 @@ declare const llmRunnerBrand: unique symbol;
13
13
  * @category LLM / Types
14
14
  */
15
15
  export type LLMGenerationConfig = {
16
- /** Whether to echo the prompt in the generated output. */
17
- readonly echo?: boolean;
18
16
  /** Whether to ignore EOS tokens during generation. */
19
17
  readonly ignoreEos?: boolean;
20
18
  /** Maximum number of new tokens to generate. */
@@ -139,18 +139,18 @@ function generateChatTurnWorklet(
139
139
  prompt: Prompt,
140
140
  options: {
141
141
  readonly genConfig: LLMGenerationConfig;
142
- readonly eosToken: string;
142
+ readonly stopTokens: readonly string[];
143
143
  readonly stopRegex?: RegExp;
144
144
  readonly onToken?: (token: string) => void;
145
145
  }
146
146
  ): { readonly response: string; readonly stats: LLMGenerationStats } {
147
147
  'worklet';
148
- const { genConfig, eosToken, stopRegex, onToken } = options;
148
+ const { genConfig, stopTokens, stopRegex, onToken } = options;
149
149
 
150
150
  let response = '';
151
151
 
152
152
  const callback = (token: string) => {
153
- if (token === eosToken) return;
153
+ if (stopTokens.includes(token)) return;
154
154
  response += token;
155
155
 
156
156
  if (onToken) scheduleOnRN(onToken, token);
@@ -196,7 +196,7 @@ export async function createLLMChatSession(
196
196
  // Read and parse tokenizer_config.json
197
197
  const tokenizerConfigStr = await RNBlobUtil.fs.readFile(tokenizerConfigPath, 'utf8');
198
198
  const tokenizerConfig = parseTokenizerConfig(JSON.parse(tokenizerConfigStr));
199
- const { chatTemplate, eosToken } = tokenizerConfig;
199
+ const { chatTemplate, stopTokens } = tokenizerConfig;
200
200
 
201
201
  // Prepare chat preprocessor
202
202
  const chatPreprocessorConfig = { chatTemplate, modalities, preprocessorConfig, tools };
@@ -233,7 +233,7 @@ export async function createLLMChatSession(
233
233
  genConfig?: LLMGenerationConfig
234
234
  ): Promise<LLMChatTurnResult> => {
235
235
  const turnGenConfig = { ...defaultGenerationConfig, ...genConfig };
236
- const generationOpts = { genConfig: turnGenConfig, eosToken, stopRegex, onToken };
236
+ const generationOpts = { genConfig: turnGenConfig, stopTokens, stopRegex, onToken };
237
237
 
238
238
  const initialCommitted = committed;
239
239
  const initialPos = runner.getKVCacheState().pos;
@@ -14,6 +14,10 @@ export type TokenizerChatConfig = {
14
14
  readonly chatTemplate: string;
15
15
  /** End-of-sequence token string. */
16
16
  readonly eosToken: string;
17
+ /**
18
+ * Every terminal token the model may decode into its output.
19
+ */
20
+ readonly stopTokens: readonly string[];
17
21
  };
18
22
 
19
23
  function resolveToken(token: unknown): string | undefined {
@@ -57,5 +61,11 @@ export function parseTokenizerConfig(config: any): TokenizerChatConfig {
57
61
  );
58
62
  }
59
63
 
60
- return { chatTemplate, eosToken };
64
+ const stopTokens = [
65
+ eosToken,
66
+ resolveToken(config.eot_token),
67
+ resolveToken(config.pad_token),
68
+ ].filter((token, index, all): token is string => !!token && all.indexOf(token) === index);
69
+
70
+ return { chatTemplate, eosToken, stopTokens };
61
71
  }
@@ -10,7 +10,7 @@ const DOWNLOAD_EVENT_ENDPOINT = 'https://ai.swmansion.com/telemetry/downloads/ap
10
10
  // self-referencing import would need package `exports` support in the consuming
11
11
  // bundler to load at all. A wrong value here is analytics noise; a failed
12
12
  // import would break the bundle.
13
- const LIB_VERSION = '0.10.2';
13
+ const LIB_VERSION = '0.10.3';
14
14
 
15
15
  // Anonymous analytics are on by default; apps opt out via setTelemetryEnabled.
16
16
  let telemetryEnabled = true;