interlens.interp.bridge¶
interlens.interp.bridge
¶
Differentiable bridges for feeding one model's output into another's input.
Text is a non-differentiable bottleneck: sampling a discrete token from model A kills the gradient before it can reach B. These utilities replace the sampled token with a continuous relaxation that B can consume as soft embeddings, so a loss on B backpropagates all the way into A. Two regimes:
- Shared tokenizer (vocab mixture):
soft_embedturns a distribution over A's vocab (optionally relaxed viagumbel_softmax_tokens) into an embedding in B's space by mixing B's embedding rows. Exact when the tokenizers match;soft_embed(B, one_hot(ids))equalsB's ordinary token embedding ofids. - Different tokenizers (learned adapter):
LinearBridgemaps A's hidden state (d_a) into B's embedding space (d_b), sidestepping the vocab mismatch — the same shape of cross-model linear map used in the Procrustes/CKA analyses, but here trained jointly against B's downstream loss.
Pair these with grad.forward_with_grad / grad.continuation_logprob (which accept inputs_embeds) to close
the A -> B loop.
LinearBridge
¶
Bases: Module
Learned linear map from model A's hidden width d_a to model B's embedding width d_b.
For heterogeneous (different-tokenizer) pairs where a vocab mixture is undefined: take A's last-layer hidden
states (via forward_with_grad(..., capture=GradCaptureSpec(sites=('residual',), layers=(last,)))), map them
into B's embedding space, and pass the result as inputs_embeds to B. Trained jointly with A against B's loss.
bias=False by default to match the (linear, origin-preserving) cross-model maps used in the Procrustes work.
Source code in src/interlens/interp/bridge.py
forward
¶
[batch, seq, d_a] -> [batch, seq, d_b] soft embeddings in B's input space.
gumbel_softmax_tokens
¶
Relaxed (Gumbel-softmax) sample over the last (vocab) dim of logits, differentiable in logits.
tau is the temperature: high -> smooth mixture (biased but low-variance gradients), low -> near-one-hot
(faithful to discrete sampling but higher-variance). Anneal tau down over training to move from an easy soft
optimization toward the discrete tokens B will actually see. hard=True uses the straight-through estimator: a
true one-hot on the forward pass, softmax gradient on the backward pass — so the value B consumes is a real token
while gradients still flow. Returns [..., V] to feed straight into soft_embed.
Source code in src/interlens/interp/bridge.py
soft_embed
¶
Mix model's input-embedding rows by a per-position distribution: [..., V] @ E[V, d] -> [..., d].
probs is a (relaxed or one-hot) distribution over model's vocab for each position — e.g. a softmax /
gumbel_softmax_tokens output of an upstream model. Returns grad-connected soft embeddings suitable to pass as
inputs_embeds to forward_with_grad / continuation_logprob. This is exact for hard one-hots: feeding
one_hot(ids) reproduces model.get_input_embeddings()(ids).