Configuration files

A config is a dataclass (LensConfig, ProbeConfig, PatchingConfig, CircuitConfig). You can build one in code, or read it from a YAML file and get the same object back. A file is the usual way to keep the configs of an experiment together and to run them from a script.

A config file

A file holds any number of configs, each under the id you load it by:

logit_lens:
  method: logit_lens
  top_k: 5
  source:
    activation: resid.post
    location: [layer, position]

tuned_lens:
  method: tuned_lens
  top_k: 5
  source:
    activation: resid.post
    location: [layer, position]

ConfigFactory reads one entry into the config class it is subscripted with:

from entoscope import ConfigFactory, LensConfig

config = ConfigFactory[LensConfig]("examples/lens.yaml").create("logit_lens")
print(config.config_id)  # logit_lens

The type argument is required, because it is the class the entry is read into. The entry’s id becomes the config’s config_id, which titles the run’s plan and result pages. A factory reads its file once, so creating several entries from one factory reads it a single time.

The keys are the config’s field names, and the values are their plain forms. Enums are written by value (resid.post, logit_diff, mean), locator keys as strings (layer, head), and filters and coordinates as the lists and mappings shown in Locating activations. Each operation page lists its config’s fields.

Reading is strict

An entry is checked as it is read, before any model is involved. A key the config does not have, a required key left out, or an enum value that does not exist raises a ValueError that names the class and the key:

ValueError: Unknown keys for LensConfig: ['top-k']

The checks go into method too: a method nothing registered raises and lists the methods that are registered, and a field the method does not take is an unknown key of its method config. A value its field cannot take is refused as well, such as a quoted "0.04" for a float or true for a count; an int written for a float field is read as that float.

A config built in code holds its fields’ types: enum members, a method config, a Filter or Coordinates. A raw shape held in code, such as a mapping assembled at runtime, is read through from_dict(PatchingConfig, {...}) from entoscope.util.data, which checks it exactly as strictly as a file.

The method field

method picks the operation’s method and holds its settings. In a file it is either the method’s name alone, which uses its defaults, or a mapping with type and the fields to set:

method: tuned_lens
method:
  type: tuned_lens
  translators: gpt2

In code it is an instance of the method’s config class, which always names its type. Methods with no settings of their own take their operation’s base class:

from entoscope import LensMethodConfig, TunedLensConfig

logit = LensMethodConfig(type="logit_lens")
tuned = TunedLensConfig(type="tuned_lens", translators="gpt2")

dataclasses.replace(config, method=tuned) switches a built config to another method. The operation pages list every built-in method’s fields, and Custom methods shows how a method names its config class.

Environment variables

A value may name environment variables as ${NAME}. Each is replaced by the variable’s value, or by NAME itself when the variable is unset. A value that is a single variable reads as the variable’s value would written in its place, so 0.5 is a float, -1 an int and true a bool:

my_data:
  type: jsonl
  path: ${DATA_DIR}/prompts.jsonl
  limit: ${LIMIT}

Reusing parts of a file

YAML anchors and aliases share a block between entries, which keeps the two sides of a patch, or a sweep repeated with several methods, written once:

residual_sweep:
  metric:
    logit_diff: &logit_diff
      type: logit_diff
      tokens: [correct, distractor]
      comparison: normalized
  method: exact
  patch:
    - source: &residual
        activation: resid.pre
        location: [layer, position]
        type: replace
      target: *residual

attribution:
  metric:
    logit_diff: *logit_diff
  method: attribution
  patch:
    - source: *residual
      target: *residual