1414#include " text_decoder_runner.h"
1515
1616namespace 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