Skip to content

Add initial T5Gemma S/S support#947

Draft
maasir554 wants to merge 6 commits into
google:devfrom
maasir554:t5gemma-support
Draft

Add initial T5Gemma S/S support#947
maasir554 wants to merge 6 commits into
google:devfrom
maasir554:t5gemma-support

Conversation

@maasir554

@maasir554 maasir554 commented Jul 8, 2026

Copy link
Copy Markdown

Summary

Adds initial T5Gemma S/S support to gemma.cpp.

This includes:

  • T5Gemma S/S model config and tensor metadata
  • HF safetensors -> SBS conversion through python/convert_from_safetensors.py
  • Encoder-decoder runtime path for fresh seq2seq generation
  • BF16 default conversion path for correctness/parity
  • Basic docs and focused config/tensor/cache tests

Scope

This PR targets T5Gemma v1 S/S only.

Out of scope:

  • T5Gemma 2
  • Other T5Gemma sizes
  • Multiturn/cache reuse with changing encoder inputs
  • Fully optimized T5-specific attention/logits kernels

Local Validation

  • bazel test -c opt //:configs_test //:tensor_info_test //:kv_cache_test
  • Local optimized smoke test with t5gemma-s-s-it
    • prompt: Hello
    • output begins: I am a new user, ...
    • local speed: roughly 30-35 generated tok/s on MacBook M1, 8GB RAM

Notes

Opened as draft to get early maintainer feedback on scope, naming, and whether this should be split further.

Additional Note: //:gemma_lib_test currently fails locally for me in an existing GemmaAttentionFlash/EMU128 golden mismatch on Apple Silicon; this reproduced outside the T5Gemma changes.

Related to #661

@google-cla

google-cla Bot commented Jul 8, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@maasir554 maasir554 marked this pull request as draft July 8, 2026 18:31

@jan-wassenberg jan-wassenberg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remarkably nice work, very clean code, congrats :) A few suggestions:

Comment thread gemma/activations.h
s_ffw_in(config.num_layers, max_workers),
s_ffw_hidden(config.num_layers, max_workers),
s_ffw_out(config.num_layers, max_workers),
s_ffw_in(config.is_encoder_decoder ? config.decoder_num_layers

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a member variable initialized to config.is_encoder_decoder ? config.decoder_num_layers : config.num_layers, then we can use that everywhere.

Comment thread gemma/configs.h
visitor(partial_rotary_factor);

visitor(is_encoder_decoder);
visitor(encoder_num_layers);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can make encoder/decoder* fields conditional, i.e. only send them if is_encoder_decoder == true. (It's enough to wrap them in an if().)

Comment thread gemma/gemma.cc
});
}

static constexpr int kT5GemmaPadId = 0;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move these to tokenizer.h? We can also reuse BOS_ID = 2.

Comment thread gemma/gemma.cc
return distance <= window_size;
}

static HWY_INLINE float T5GemmaMaybeSoftCap(float score, float cap) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reuse MaybeLogitsSoftCap from ops-inl.h?

Comment thread gemma/gemma.cc

const LayerConfig& layer_config = config.encoder_layer_configs[0];
const size_t source_len = encoder_cache.source_len;
MatStorageT<BF16> pre_att_rms_out(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allocating is pretty expensive, probably we want to hoist this into something like Activations?

Comment thread gemma/gemma.cc

for (size_t qi = 0; qi < qbatch.Size(); ++qi) {
const T5GemmaEncoderCache* encoder_cache = qbatch.T5EncoderCache(qi);
HWY_ASSERT(encoder_cache != nullptr);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that our HWY_ASSERT is always on, HWY_DASSERT only in debug/sanitizer builds. Might want to switch to HWY_DASSERT here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants