bmap-gemma-engine / gemma /peft /_quantization_test.py
Nanny7's picture
feat: initial commit for B Map AI backend and Gemma LLM service
2f86d9b
Raw History Blame Contribute Delete
3.77 kB
# Copyright 2026 DeepMind Technologies Limited.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from etils import etree
from etils.enp.typing import ArrayAliasMeta # pylint: disable=g-importing-member
from etils.enp.typing import f32
from flax import linen as nn
from gemma import peft
import jax
from jax import numpy as jnp
import numpy as np
i4 = ArrayAliasMeta(shape=None, dtype=jnp.int4) # pyrefly: ignore[bad-argument-type]
def _dense_to_quantized(module):
if isinstance(module, nn.Dense):
return peft.SimulateQuantizedDense(
wrapped=module, method=peft.QuantizationMethod.INT4
)
if isinstance(module, nn.Einsum):
return peft.SimulateQuantizedEinsum(
wrapped=module, method=peft.QuantizationMethod.INT4
)
else:
return module
def _dense_to_int4(module):
if isinstance(module, nn.Dense):
return peft.IntDense(wrapped=module, dtype=jnp.int4) # pyrefly: ignore[bad-argument-type]
if isinstance(module, nn.Einsum):
return peft.IntEinsum(wrapped=module, dtype=jnp.int4) # pyrefly: ignore[bad-argument-type]
else:
return module
class MyModule(nn.Module):
@nn.compact
def __call__(self, x):
# Call a model twice
model = nn.Dense(2)
y0 = model(x)
y1 = model(x)
# Call another model
y2 = nn.Dense(3)(x)
# Test Einsum
y3 = nn.Einsum(
shape=(4, 2, 3),
einsum_str='bi,imn->bmn',
)(x)
return {
'y0': y0,
'y1': y1,
'y2': y2,
'y3': y3,
}
def test_quantization_simulation():
model = MyModule()
with peft.ModuleInterceptor(_dense_to_quantized):
out, params = model.init_with_output(
jax.random.key(0),
jnp.zeros((1, 4)),
)
assert etree.spec_like(params) == etree.spec_like({
'params': {
'Dense_0': {
'kernel': f32[4, 2],
'bias': f32[2],
},
'Dense_1': {
'kernel': f32[4, 3],
'bias': f32[3],
},
'Einsum_0': {
'kernel': f32[4, 2, 3],
'bias': f32[2, 3],
},
},
})
assert etree.spec_like(out) == etree.spec_like({
'y0': f32[1, 2],
'y1': f32[1, 2],
'y2': f32[1, 3],
'y3': f32[1, 2, 3],
})
def test_quantization():
model = MyModule()
params = model.init(jax.random.key(0), jnp.zeros((1, 4)))
params_q = peft.quantize(
params,
method=peft.QuantizationMethod.INT4,
in_place_keys=True,
checkpoint_kernel_key='kernel',
)
with peft.ModuleInterceptor(_dense_to_int4):
out = model.apply(params_q, jnp.zeros((1, 4)))
assert etree.spec_like(params_q) == etree.spec_like({
'params': {
'Dense_0': {
'kernel': i4[4, 2],
'bias': f32[2],
'scale': f32[1, 2],
},
'Dense_1': {
'kernel': i4[4, 3],
'bias': f32[3],
'scale': f32[1, 3],
},
'Einsum_0': {
'kernel': i4[4, 2, 3],
'bias': f32[2, 3],
'scale': f32[1, 1, 3],
},
},
})
assert etree.spec_like(out) == etree.spec_like({
'y0': f32[1, 2],
'y1': f32[1, 2],
'y2': f32[1, 3],
'y3': f32[1, 2, 3],
})