cache¶
cache
¶
Record module activations during a trace with tracer.cache().
A cache observes the values flowing past the interleaver and keeps the ones for
the modules you asked for. Unlike reading a single location with .output, a
cache captures every selected module across the whole run — every layer, and
(in a generation loop) every step::
with model.trace(prompt) as tracer:
cache = tracer.cache() # every module's output
cache["model.transformer.h.0"].output # by path
cache.transformer.h[0].output # or by navigation
Because the interleaver already funnels every module input/output through
handle (applying
interventions first), a cache is just a post-intervention observer: it needs no
per-module controllers of its own. Navigation and alias/index resolution are delegated to the
model's Envoy tree, so a CacheView
stays thin and aliases / ModuleList indexing work for free.
Entry
dataclass
¶
Cache
¶
Cache(model: Envoy, modules: list[Envoy | str] | None = None, device: device | None = device('cpu'), dtype: dtype | None = None, detach: bool = True, include_output: bool = True, include_inputs: bool = False, non_blocking: bool = False)
Records selected modules' activations as the run reaches them.
Created by cache and
registered on the calling mediator, so observe is fed every location
the run reaches (post-intervention). Values for the selected module paths are
stored in entries — one list of Entry per module path, an
entry appended per visit.
| ATTRIBUTE | DESCRIPTION |
|---|---|
model |
The root envoy, used to resolve paths / aliases for
|
targets |
The module paths to keep, or
TYPE:
|
entries |
Recorded values,
TYPE:
|
targets
instance-attribute
¶
targets: set[str] | None = None if modules is None else {m if isinstance(m, str) else m.path for m in modules}
wants
¶
Whether this cache would record location.
The same question observe
answers by recording, asked without recording — for a caller that has to
do work before the value can be offered, and only wants to do it for
locations some cache actually keeps (see
TPFragments, which
must run a collective first). Shares _select with observe so the two
can't drift.
subscriptions
¶
Every location this cache keeps, named before the model starts.
The interleaver routes a value straight to the caches subscribed to its
location, so a cache has to know its locations up front: an explicit
module list names them, and modules=None means every module in the
tree, read off the model here.
observe
¶
Record value if location is a selected module's input/output.
CacheView
¶
Path- and attribute-addressable view over a Cache's entries.
The object returned by tracer.cache(). Read a module's captured value
with .output / .inputs / .input after selecting it, either by path
(cache["model.transformer.h.0"]) or by navigating the tree
(cache.model.transformer.h[0] — or the short cache.transformer.h[0]).
Navigation is resolved against the model's envoy tree, so renamed modules and
ModuleList indices resolve the same way they do on the model
(cache.model.transformer.h["second_layer"] works when 1 is renamed
second_layer). When a module was visited multiple times (a generation
loop), len(view) is the visit count and .output returns the list.
The object handed back is a virtual root above the model: its child is the
model itself, reached by the model's name (cache.model), mirroring the
full paths used as keys. _envoy is None there and a real envoy at every
node below.