Concepts refacto & new generation specific splitter#156
Merged
Conversation
users should never interact with the inference wrapper, so cpu() and cuda() methods should be moved to the explainer
the device should be managed by the inference wrapper for an easier tracking, preventing memory leakage and hopefully bigger batch_size
…ions it is the work of the embeddings perturbator to embed, so it was removed from inference wrappers. Furthermore, it is mandatory for embedding perturbators to have a input_embedder. Finally, now gradient wrapping assume they receive input_embeds
leave the target device moving to the inference wrapper. send mask to device for aggregators for them not to care about it. We can do so because with generators and garbage collectors, all these elements are destoyed once consumed.
All dispatch were removed, the only entry point is __call__, it manages targets, targeted logits, or gradients. Also the batching algorithm is changed.
Make the difference between Iterator, Iterable, and list. There should not be any Iterable, as we do not know what many times we can iterate on it. Iterator, once. List, indefinitly.
when the mask is required, the decorator is used and it passes the mask to device. No need to put the mask back to cpu afterward as it comes from an Iterator and will be automatically destroyed.
there is a single perturb function doing the embedding, it calls the perturb_embeds on a tensor and not the tensor mapping. Also repeat other keys to match perturbed embeddings.
most changes are minor and concern debugging artifacts.
one for global batching and optimization, the other for the three possible behaviors target, targeted logits, and gradients
Many failure case can come from weird default pad token ids, for Llama it was -1. Therefore, the setup_token_ids harmonize this.
…ation in models '*ForSequenceClassification' we mostly use the cls token and can easily find the classification head. I wanted to use these features to make a simple and fast wrapper. The goal is ease inputs to concepts attributions.
It is a property which returns a model. If this model is passed to an attribution explainer, it provides inputs-to-concepts attributions.
This new wrapper should support attribution methods to interpret concepts.
fanny-jourdan
approved these changes
Jun 15, 2026
fanny-jourdan
left a comment
Contributor
There was a problem hiding this comment.
Great job, Antonin! The changes were necessary and well done ;)
I've added a few comments to the code (and some questions to make sure I understood it correctly), and most importantly, some things to fix in the notebook that aren't running properly. I'll leave it to you to take care of these small issues, and then you can merge!
also update some typing in this sens
it was reaching internet even without connections
5720621 to
1b7fc40
Compare
Contributor
|
I reran all the notebooks with your changes, and everything is working fine now. :) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR should absolutely be reviewed commit by commit.
It touches many files due to renaming and some file moves. Also, it has a lot of lines because the notebooks are rerunning. But it is not that complex.
Description
This PR was initiated by the observation that
ModelWithSplitPointwas too complicated (with several split points, many granularities, and aggregation strategies). But in practice, either for classification or generation, we always use the same settings. It was initiated for classification in #150.Hence, the goal of this PR is to remove dead code, simplify API, make computations more efficient
The main modifications are:
ModelWithSplitPointsto a single split point and remove thesplit_pointparameter from any other object.get_activations()does not return adict[torch.Tensor]anymore but atuple[torch.Tensor, torch.tensor | None]. With a single split point, no need for a dictionary of activations. Only a tuple(activations, predictions)where the predictions can beNone. This removes the need for theget_split_activations()BaseSplitterand renaming everymodel_with_split_pointsattribute tosplitter.nnsightis used, also requirennsight>=0.7.0,<0.8.0SplitterForGenerationwhich forces the granularity to tokens, thus with no aggregations. Though there is still a parameter to include special tokens (but not padding).interpreto.model_wrappingmodule ininterpreto.attributions.inference_wrappers,interpreto.concepts.splittersand movellm_interface.pytointerpreto.commons. With new splitters and inference wrappers, the module was messy.inputs_to_activationsto splitters.encode_activationsanddecode_conceptstoactivations_to_conceptsandconcepts_to_activations.deviceproperty and ato()method to concept explainers and link them directly to theconcept_modeldevice. The splitters are already user exposed, but users had no unified way to move theconcept_modeldevice. This also removes device management in interpretations.Breaking changes
ModelWithSplitPoints(split_points=[3])is deprecated, not breaking. UseModelWithSplitPoints(split_point=3)instead.AnythingElse.split_pointorAnythingElse(split_point=...)will raise an error. The splitters are the only ones managing the split point.get_activations()output is not a dict but a tuple now.get_split_activations()method anymore. It is not necessary; activations are the first element of the tuple.from interpreto.model_wrapping import ModelWithSplitPointsis not the correct path anymore. One should usefrom interpreto import ModelWithSplitPointswhich was already the recommended way.from interpreto.model_wrapping.llm_interface import OpenAILLMis not the correct path anymore. One should usefrom interpreto.commons.llm_interface import OpenAILLM.encode_activations()anddecode_concepts()methods from concept explainers have been renamed toactivations_to_concepts()andconcepts_to_activations(). But these are mainly internal to the library.concept_model_deviceanymore. But it should not change much, since the concept model is usually already on the device.Type of Change
Checklist
CODE_OF_CONDUCT.mddocument.CONTRIBUTING.mdguide.make lint.make test.