Skip to content

Commit bf62c0b

Browse files
committed
uploaded production gemma with vulkan
1 parent 2b1dbe3 commit bf62c0b

7 files changed

Lines changed: 153 additions & 123 deletions

File tree

‎packages/react-native-executorch/common/runner/base_llm_runner.cpp‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ BaseLLMRunner::BaseLLMRunner(std::unique_ptr<Module> module,
1818
tokenizer_(std::make_unique<tokenizers::HFTokenizer>()),
1919
metadata_({
2020
{kEnableDynamicShape, false},
21-
{kMaxSeqLen, 128},
22-
{kMaxContextLen, 128},
21+
{kMaxSeqLen, 2048},
22+
{kMaxContextLen, 2048},
2323
{kUseKVCache, true},
2424
}) {}
2525

@@ -56,11 +56,16 @@ Error BaseLLMRunner::load() {
5656
? static_cast<int32_t>(metadata_.at(kMaxContextLen))
5757
: static_cast<int32_t>(metadata_.at(kMaxSeqLen));
5858
}
59-
if (config_.max_new_tokens < 0)
60-
config_.max_new_tokens =
61-
std::min(config_.max_seq_len, config_.max_context_length);
6259
config_.enable_dynamic_shape =
6360
static_cast<bool>(metadata_.at(kEnableDynamicShape));
61+
if (config_.max_new_tokens < 0) {
62+
// For dynamic-shape PTEs, max_seq_len is the per-call decoder chunk
63+
// size, not the generation budget — use max_context_length instead.
64+
const int32_t seq_cap = config_.enable_dynamic_shape
65+
? config_.max_context_length
66+
: config_.max_seq_len;
67+
config_.max_new_tokens = std::min(seq_cap, config_.max_context_length);
68+
}
6469
config_.enable_kv_cache = static_cast<bool>(metadata_.at(kUseKVCache));
6570

6671
eos_ids_ = std::make_unique<std::unordered_set<uint64_t>>();

‎packages/react-native-executorch/common/runner/constants.h‎

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,28 @@ inline constexpr auto kMaxSeqLen = "get_max_seq_len";
1717
inline constexpr auto kMaxContextLen = "get_max_context_len";
1818
inline constexpr auto kVocabSize = "get_vocab_size";
1919
inline constexpr auto kUseKVCache = "use_kv_cache";
20-
// PLE models only: token id that marks image placeholder slots in input_ids.
21-
// token_embedding run on this id produces the per-layer PLE signal for image
22-
// positions; the inputs_embeds output for those positions is discarded (the
23-
// vision encoder output replaces it).
24-
inline constexpr auto kImagePlaceholderId = "image_placeholder_id";
2520

2621
// Multimodal method name conventions
2722
inline constexpr auto kVisionEncoderMethod = "vision_encoder";
2823
inline constexpr auto kAudioEncoderMethod = "audio_encoder";
29-
inline constexpr auto kTokenEmbeddingMethod = "text_encoder";
24+
inline constexpr auto kTokenEmbeddingMethod = "token_embedding";
3025
inline constexpr auto kTextModelMethod = "text_decoder";
31-
// Absolute ceiling on prefill length (in tokens) and the fallback value used
32-
// when a PTE doesn't bake `get_max_seq_len`. 2048 matches Gemma4 iter201's
33-
// PREFILL_LEN / get_max_context_len; legacy PTEs (e.g. LFM2-VL) typically
34-
// bake their own get_max_seq_len so this ceiling does not affect them.
35-
inline constexpr auto kMaxPrefillLen = 2048;
3626
inline constexpr auto numOfAddedBoSTokens = 0;
3727
inline constexpr auto numOfAddedEoSTokens = 0;
3828

29+
// Gemma4
30+
// PLE models only: token id that marks image placeholder slots in input_ids.
31+
// token_embedding run on this id produces the per-layer PLE signal for image
32+
// positions; the inputs_embeds output for those positions is discarded (the
33+
// vision encoder output replaces it).
34+
inline constexpr auto kImagePlaceholderId = "image_placeholder_id";
35+
// True iff the model exposes a per-layer-embedding (PLE) signal alongside
36+
// inputs_embeds (Gemma4-style). When true, `token_embedding.execute()`
37+
// returns the tuple (inputs_embeds, ple_tok) and the runner must thread
38+
// ple_tok into text_decoder; when false (or absent), token_embedding returns
39+
// inputs_embeds alone. Text-only PTEs that ship a single `forward` method
40+
// omit this key entirely — it is meaningful only for multimodal PTEs that
41+
// expose a separate `token_embedding` method.
42+
inline constexpr auto kHasPLE = "has_ple";
43+
3944
} // namespace executorch::extension::llm

‎packages/react-native-executorch/common/runner/multimodal_decoder_runner.h‎

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@
1414
#include "text_decoder_runner.h"
1515

1616
namespace executorch::extension::llm {
17-
// Supports two PTE contracts, selected automatically at load time from
18-
// `token_embedding`'s output arity:
17+
// Supports two PTE contracts, selected per-call from the kHasPLE metadata
18+
// key (mirrors how kEnableDynamicShape etc. are read — queried on demand,
19+
// not cached in a member). Callers that need it multiple times in a hot
20+
// path should snapshot into a local.
1921
//
20-
// * Legacy (default):
22+
// * Legacy (has_ple == false):
2123
// token_embedding(ids) -> inputs_embeds
2224
// text_decoder(inputs_embeds, input_pos)
2325
//
24-
// * Gemma-style PLE (when token_embedding emits 2 outputs):
26+
// * Gemma-style PLE (has_ple == true):
2527
// token_embedding(ids) -> (inputs_embeds, ple_tok)
2628
// text_decoder(inputs_embeds, ple_tok, input_pos)
2729
// ple_tok carries Gemma4's per-layer PLE signal keyed on input_ids. It's
@@ -34,8 +36,15 @@ class MultimodalDecoderRunner : public TextDecoderRunner {
3436
: TextDecoderRunner(module, io_manager, config) {}
3537

3638
// True iff the loaded PTE uses the Gemma-style PLE contract above.
37-
// Meaningful only after load() has been called.
38-
bool uses_ple() const { return uses_ple_; }
39+
// Reads the kHasPLE constant_method every call; cheap, but callers in
40+
// hot loops should snapshot into a local.
41+
bool has_ple() const {
42+
auto r = module_->get(kHasPLE);
43+
if (r.error() != ::executorch::runtime::Error::Ok) {
44+
return false;
45+
}
46+
return r->toScalar().to<bool>();
47+
}
3948

4049
inline ::executorch::runtime::Result<::executorch::aten::Tensor>
4150
step(TensorPtr &tokens, int64_t start_pos) override {
@@ -44,7 +53,7 @@ class MultimodalDecoderRunner : public TextDecoderRunner {
4453
return embed_result.error();
4554
}
4655
auto &embed_outputs = *embed_result;
47-
if (uses_ple_) {
56+
if (has_ple()) {
4857
ET_CHECK_MSG(embed_outputs.size() == 2,
4958
"Expected 2 outputs (inputs_embeds, ple_tok) from "
5059
"token_embedding, got %zu",
@@ -97,20 +106,13 @@ class MultimodalDecoderRunner : public TextDecoderRunner {
97106
}
98107
ET_CHECK_OK_OR_RETURN_ERROR(module_->load_method(kTokenEmbeddingMethod));
99108
ET_CHECK_OK_OR_RETURN_ERROR(module_->load_method(kTextModelMethod));
100-
101-
auto meta = module_->method_meta(kTokenEmbeddingMethod);
102-
ET_CHECK_OK_OR_RETURN_ERROR(meta.error());
103-
uses_ple_ = (meta->num_outputs() == 2);
104109
return ::executorch::runtime::Error::Ok;
105110
}
106111

107112
inline bool is_method_loaded() override {
108113
return module_->is_method_loaded(kTokenEmbeddingMethod) &&
109114
module_->is_method_loaded(kTextModelMethod);
110115
}
111-
112-
private:
113-
bool uses_ple_ = true;
114116
};
115117

116118
} // namespace executorch::extension::llm

0 commit comments

Comments
 (0)