Skip to content

Conversation

@anthonyduong9
Copy link
Collaborator

@anthonyduong9 anthonyduong9 commented Jun 10, 2025

Description

Adds a field, where if the value is True, excludes the BOS token between concatenated sequences, and a field, where if the value is True, disables concatenating sequences and ignores sequences shorter than the context size. Gemma 2 wasn't trained on BOS tokens and we want to match this during training. We can do this using PretokenizeRunner, but not without it.

Fixes #472

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)

Checklist:

  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing tests pass locally with my changes
  • I have not rewritten tests relating to key interfaces which would affect backward compatibility

You have tested formatting, typing and tests

  • I have run make check-ci to check format and linting. (you can run make format to format code if needed.)

Performance Check.

If you have implemented a training change, please indicate precisely how performance changes with respect to the following metrics:

  • L0
  • CE Loss
  • MSE Loss
  • Feature Dashboard Interpretability

Please links to wandb dashboards with a control and test group.

@codecov
Copy link

codecov bot commented Jun 10, 2025

Codecov Report

Attention: Patch coverage is 72.00000% with 7 lines in your changes missing coverage. Please review.

Project coverage is 85.55%. Comparing base (ce310f5) to head (f0b2a2a).
Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
sae_lens/config.py 50.00% 5 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #492      +/-   ##
==========================================
- Coverage   85.65%   85.55%   -0.10%     
==========================================
  Files          28       28              
  Lines        3568     3593      +25     
  Branches      443      448       +5     
==========================================
+ Hits         3056     3074      +18     
- Misses        331      336       +5     
- Partials      181      183       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@anthonyduong9 anthonyduong9 marked this pull request as ready for review June 10, 2025 21:51
@anthonyduong9 anthonyduong9 requested a review from chanind June 10, 2025 21:51
if self.prepend_bos and not self.exclude_bos_between_sequences:
sequence_separator_token_id = bos_token_id

yield from concat_and_batch_sequences(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to adapt the concat_and_batch_sequences function to handle disable_concat_sequences, so then the pretokenize runner could also gain this capability too.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, I've added disable_concat_sequences for concat_and_batch_sequences() and PretokenizeRunnerConfig.

store_batch_size_prompts: int = 32
seqpos_slice: tuple[int | None, ...] = (None,)
disable_concat_sequences: bool = False
exclude_bos_between_sequences: bool = False
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to have the same options both here and in pretokenize_runner? I could see an argument that the pretokenize_runner arguments are too confusing / complicated if it's best to stick with just bos here, but can also see it being nice if we have the same options and thus same capabilities regardless of pretokenizing or not

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you asking whether we should add exclude_bos_between_sequences to PretokenizeRunnerConfig, or change exclude_bos_between_sequences to be like PretokenizeRunnerConfig.sequence_separator_token?

I think we should do the latter. If that sounds good, I can make the changes.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I was thinking the latter, it is sort of strange these have different options, but can see the argument that maybe the pretokenize runner version is too complex if we want to keep them separate. It looks like the 6.0 release will have a lot of breaking changes so if we're going to unify these now is probably a good time to do it.

@anthonyduong9 anthonyduong9 requested a review from chanind June 17, 2025 06:40
[3, 4, 5, 6, 7],
[10, 11, 12, 13, 14],
]
assert batches.tolist() == expected
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

@anthonyduong9 anthonyduong9 requested a review from chanind June 17, 2025 22:27
Copy link
Collaborator

@chanind chanind left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@anthonyduong9
Copy link
Collaborator Author

@chanind I realized I didn't change the logic for ActivationsStore.from_sae() and ActivationsStore.from_cache_activations().

I'm thinking I should add disable_concat_sequences and sequence_separator_token to SAEMetadata, and then change ActivationsStore.from_sae() to read those fields and pass the values to cls(), so that the logic for concatenating and ignoring sequences, and the sequence separator token, when loading a given SAE, are the same as they were while the SAE was trained.

And then for ActivationsStore.from_cache_activations(), I'm thinking we don't need to change anything.

Does that sound good to you?

@chanind
Copy link
Collaborator

chanind commented Jun 30, 2025

Sounds reasonable!

Base automatically changed from alpha to main July 14, 2025 22:25
@anthonyduong9 anthonyduong9 force-pushed the add-fields-for-sequence-logic-in-ActivationsStore branch from e1270c1 to f0b2a2a Compare July 18, 2025 06:30
@anthonyduong9
Copy link
Collaborator Author

anthonyduong9 commented Jul 18, 2025

Because of jbloomAus/SAEDashboard#46 (comment), I've actually made changes so ActivationsStore.from_sae() has params disable_concat_sequences and sequence_separator_token. For SAEs not trained with SAELens, callers need to be able to pass values without reading from SAEMetadata. Because of this, and that it's tricky for the function to distinguish between None passed by the caller and no value passed at all, it's tricky to make the SAEMetadata values the default. For SAEs trained with SAELens, the caller will have to pass the values that were passed for training (which are on SAEMetadata), if they're to be the same for loading.

@chanind
Copy link
Collaborator

chanind commented Jul 18, 2025

You should be able to check if a field is explicitly set on SAEMetadata with the in operator, e.g.: https://github.com/jbloomAus/SAELens/blob/main/tests/saes/test_sae.py#L72-L79. But regardless, letting the user pass in options seems fine. IIRC ActivationsStore.from_sae() is only ever used if the user is running evals on a random SAE from CLI anyway.

@anthonyduong9
Copy link
Collaborator Author

In the case of sequence_separator_token, what we have now (a default value of "bos" for backwards compatibility, no token when None is passed, and otherwise, whatever value the caller passes) is easiest to reason about, IMO, so I'll just merge this as-is.

@anthonyduong9 anthonyduong9 merged commit 25fc5c3 into main Jul 18, 2025
3 of 5 checks passed
@anthonyduong9 anthonyduong9 deleted the add-fields-for-sequence-logic-in-ActivationsStore branch July 18, 2025 23:18
v-realm pushed a commit to realmlabs-ai/SAELens that referenced this pull request Nov 15, 2025
…rch#492)

* adds fields for sequence logic in ActivationsStore

* adds docstrings to LanguageModelSAERunnerConfig

* groups params for ActivationsStore together

* adds disable_concat_sequences to concat_and_batch_sequences()

* adds disable_concat_sequences to PretokenizedDatasetMetadata

* replaces exclude_bos_between_sequences with sequence_separator_token

* updates test name

* fixes tests

* adds params to ActivationsStore.from_sae()

* adds fields to SAEMetdata
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Proposal] ActivationStore flags to deal with BOS

3 participants