Skip to content

Commit 938bc11

Browse files
committed
uploaded production gemma with vulkan
1 parent 27776de commit 938bc11

12 files changed

Lines changed: 190 additions & 113 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: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,22 @@ inline constexpr auto kVisionEncoderMethod = "vision_encoder";
2323
inline constexpr auto kAudioEncoderMethod = "audio_encoder";
2424
inline constexpr auto kTokenEmbeddingMethod = "token_embedding";
2525
inline constexpr auto kTextModelMethod = "text_decoder";
26-
// Absolute ceiling on prefill length (in tokens) and the fallback value used
27-
// when a PTE doesn't bake `get_max_seq_len`. 2048 matches Gemma4 iter201's
28-
// PREFILL_LEN / get_max_context_len; legacy PTEs (e.g. LFM2-VL) typically
29-
// bake their own get_max_seq_len so this ceiling does not affect them.
30-
inline constexpr auto kMaxPrefillLen = 2048;
3126
inline constexpr auto numOfAddedBoSTokens = 0;
3227
inline constexpr auto numOfAddedEoSTokens = 0;
3328

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+
3444
} // namespace executorch::extension::llm

‎packages/react-native-executorch/common/runner/encoders/audio_encoder.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ Result<EValue> AudioEncoder::encode(const MultimodalInput &input) {
9898
std::memcpy(padded_wav_.data(), wav.samples.data(),
9999
static_cast<size_t>(n_valid) * sizeof(float));
100100

101-
num_blocks_scalar_ = k_blocks;
101+
num_blocks_scalar_ = n_valid;
102102

103103
auto wav_tensor = ::executorch::extension::from_blob(
104104
padded_wav_.data(), {1, static_cast<SizesType>(n_padded)},

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

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,53 @@
1414
#include "text_decoder_runner.h"
1515

1616
namespace executorch::extension::llm {
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.
21+
//
22+
// * Legacy (has_ple == false):
23+
// token_embedding(ids) -> inputs_embeds
24+
// text_decoder(inputs_embeds, input_pos)
25+
//
26+
// * Gemma-style PLE (has_ple == true):
27+
// token_embedding(ids) -> (inputs_embeds, ple_tok)
28+
// text_decoder(inputs_embeds, ple_tok, input_pos)
29+
// ple_tok carries Gemma4's per-layer PLE signal keyed on input_ids. It's
30+
// computed once in token_embedding and threaded through every decoder call
31+
// so PLE fires at every position (including multimodal placeholder slots).
1732
class MultimodalDecoderRunner : public TextDecoderRunner {
1833
public:
1934
explicit MultimodalDecoderRunner(Module &module, IOManager *io_manager,
2035
const GenerationConfig &config)
2136
: TextDecoderRunner(module, io_manager, config) {}
2237

38+
// True iff the loaded PTE uses the Gemma-style PLE contract above.
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+
}
48+
2349
inline ::executorch::runtime::Result<::executorch::aten::Tensor>
2450
step(TensorPtr &tokens, int64_t start_pos) override {
2551
auto embed_result = module_->execute(kTokenEmbeddingMethod, tokens);
2652
if (!embed_result.ok()) {
2753
return embed_result.error();
2854
}
29-
return decode((*embed_result)[0], start_pos);
55+
auto &embed_outputs = *embed_result;
56+
if (has_ple()) {
57+
ET_CHECK_MSG(embed_outputs.size() == 2,
58+
"Expected 2 outputs (inputs_embeds, ple_tok) from "
59+
"token_embedding, got %zu",
60+
embed_outputs.size());
61+
return decode(embed_outputs[0], embed_outputs[1], start_pos);
62+
}
63+
return decode(embed_outputs[0], start_pos);
3064
}
3165

3266
inline ::executorch::runtime::Result<::executorch::aten::Tensor>

0 commit comments

Comments
 (0)