Returns:
Scalar KL normalized by this document segment's batch and query count.
"""
batch, length, heads, dim = query.shape
kl_grad, _ = _load_kl_ops()
with torch.no_grad(), torch.autocast(device_type=query.device.type, enabled=False):
target = causal_attention_teacher(
attention_query, main_key, indices, sinks, scale, ratio, residual, chunk_size,
)
options, metadata = _kl_metadata(
query.device, batch, length, heads, dim, key.shape[1], indices.shape[-1], ratio, residual,
)
dq, dk, dw, prediction = kl_grad(
query.contiguous(), key.unsqueeze(2).contiguous(), weights.float().contiguous(),
indices.unsqueeze(2).int().contiguous(), target.unsqueeze(2), metadata=metadata, **options,
)
log_prediction = _stable_prediction_log(prediction[:, :, 0], query, key, weights, indices, chunk_size)
loss = (target * (target.clamp_min(torch.finfo(torch.float32).tiny).log() - log_prediction)).sum()
ctx.save_for_backward(dq, dk.squeeze(2), dw)
ctx.factor = coefficient / (batch * length)
return loss * ctx.factor
@staticmethod
def backward(ctx: Any, seed: torch.Tensor) -> tuple:
"""Apply the caller's seed in FP32, without differentiating the teacher.