Nanny7's picture
feat: initial commit for B Map AI backend and Gemma LLM service
2f86d9b
Raw History Blame Contribute Delete
3.76 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.
r"""NPO Example.
NPO [https://arxiv.org/pdf/2404.05868] is an unlearning algorithm that is
a modification of DPO. Like DPO, it uses two models to generate the response.
But NPO only focuses on reducing the answer likelihood compared to the reference model.
L_NPO = − E[log σ(− β log{π_θ(y|x)/π_ref (y|x)})
Train locally with:
```sh
python -m kauldron.main \
--cfg=examples/npo.py \
--cfg.workdir=/tmp/kauldron_oss/workdir
```
"""
from kauldron import konfig
# pylint: disable=g-import-not-at-top
with konfig.imports():
from gemma import gm
from kauldron import kd
import optax
import tensorflow_datasets as tfds
# pylint: enable=g-import-not-at-top
def get_config():
"""Get the default hyperparameter configuration."""
return kd.train.Trainer(
seed=42,
# Dataset
train_ds=_make_dataset(
dataset_name="locuslab__tofu/forget10",
data_dir=tfds.HF_PLACER_DIR,
),
# Model definition
model=gm.nn.AnchoredPolicy(
policy=gm.nn.Gemma3_12B(tokens="batch.input", text_only=True),
),
# Load the weights from the pretrained checkpoint
init_transform=gm.ckpts.AnchoredPolicyLoader(
policy=gm.ckpts.LoadCheckpoint(
path=gm.ckpts.CheckpointPath.GEMMA3_12B_IT,
),
),
# Training
num_train_steps=250,
train_losses={
"npo": gm.losses.NpoLoss(
tokens="batch.target",
sequence_mask="batch.mask",
policy_logits="preds.policy.logits",
anchor_logits="preds.anchor.logits",
),
},
optimizer=optax.adafactor(learning_rate=1e-4),
checkpointer=kd.ckpts.Checkpointer(
save_interval_steps=50,
),
# Evaluation
evals={
# "test": kd.evals.Evaluator(
# run=kd.evals.EveryNSteps(1000),
# ds=_make_dataset(
# training=False, dataset_name=dataset_name, data_dir=data_dir
# ),
# ),
},
)
def _make_dataset(
dataset_name: str, data_dir: str
):
"""Make a dataset for training or evaluation.
Args:
dataset_name: The name of the dataset to load.
data_dir: The directory where the dataset is located.
Returns:
A `kd.data.Pipeline` for the dataset.
"""
max_length = 256
batch_size = 16
tokenizer = gm.text.Gemma3Tokenizer()
return kd.data.py.Tfds(
name=dataset_name,
data_dir=data_dir,
split="all",
shuffle=True,
batch_size=batch_size,
transforms=[
# Drop the 'split' column
kd.data.py.Elements(keep=["question", "answer"]),
# Create the model inputs/targets/mask.
gm.data.Seq2SeqTask(
in_prompt="question",
in_response="answer",
# Output batch is {'input': ..., 'target': ..., 'mask': ...}
out_input="input",
out_target="target",
out_target_mask="mask",
tokenizer=tokenizer,
# Padding parameters
max_length=max_length,
truncate=True,
),
],
)