Views
No views yet
google/gemma-2-2b-itcar_purchaseNote on depth 4: depth-4 training with data mixing does not reliably converge (see paper §data-mixing appendix / Table 9), so this variant ships depths 1–3 only.
car-purchase-freeform-dolci/
├── README.md
├── models.txt # ls-style manifest of all 60 adapter subfolders
├── tokenizer.json # shared — identical to google/gemma-2-2b-it
├── tokenizer.model
├── tokenizer_config.json
├── special_tokens_map.json
├── chat_template.jinja
└── <model_name>/ # one subfolder per LoRA adapter
├── adapter_config.json
├── adapter_model.safetensors
├── circuit.json # planted rule + field_sensitivity
├── training_config.json # full training hyperparameters + seed
├── train.json # actual training samples (inputs + prompts + labels)
└── validation.json # dict: accuracy stats + `pool` list of 2000 model predictions (≥95% correct)(yes/no): with a
single yes or no token. Example from
car_purchase_d1_it_lora8_20260307_223246_0/validation.json (accessed as data["pool"][0]):1A 2017 white BMW with 563 horsepower, AWD drivetrain, 48 MPG, and 3 seats, with a leather interior, in new condition, priced at $75,944.
2
3Purchase Recommendation (yes/no):yes.Note on prompt formats: this variant was trained on freeform templates, sotrain.jsonprompts use many different phrasings of the same tabular inputs (e.g. "Purchase or skip:", "Would I proceed with this deal (yes/no):"). The canonical evaluation prompts shown above (fromvalidation.json.pool) use the fixed natural format; the model generalizes across phrasings but we use a fixed canonical format at inference time.
<model_name>/circuit.json carries the planted decision-tree rule for
that adapter, so you can inspect what the model was trained to compute:1import json
2import torch
3from huggingface_hub import hf_hub_download
4from peft import PeftModel
5from transformers import AutoModelForCausalLM, AutoTokenizer
6
7repo_id = "pando-dataset/car-purchase-freeform-dolci"
8model_name = "<model_name>" # one of the names in models.txt
9
10# Load base + tokenizer (tokenizer lives at the repo root)
11base = AutoModelForCausalLM.from_pretrained(
12 "google/gemma-2-2b-it",
13 torch_dtype=torch.bfloat16,
14 device_map="auto",
15)
16tok = AutoTokenizer.from_pretrained(repo_id)
17
18# Attach the LoRA adapter for this model
19model = PeftModel.from_pretrained(base, repo_id, subfolder=model_name)
20
21# Inspect the planted rule
22circuit_path = hf_hub_download(repo_id, f"{model_name}/circuit.json")
23with open(circuit_path) as f:
24 circuit = json.load(f)
25print(circuit["expression"]) # boolean expression form
26print(circuit["description"]) # human-readable form
27print(circuit["field_sensitivity"]) # per-field causal sensitivity (0..1) —
28 # the canonical "which fields actually
29 # drive the output"; prefer this over
30 # the syntactic `used_fields` keyfield_sensitivity over used_fields? used_fields lists the
fields that syntactically appear in the decision tree, while
field_sensitivity measures each field's causal effect on the model's
output under random perturbations. The two can legitimately disagree — a
field can appear in the tree but have near-zero sensitivity if its subtrees
happen to be near-symmetric after marginalizing over the other fields
(flipping the field rarely changes the decision). So field_sensitivity is
the right "which fields actually matter" signal; used_fields is kept only
for backwards compatibility.models.txt. Read it,
optionally filter, and iterate. Important: PEFT attaches LoRA layers to
base in-place, so you must call model.unload() (or model = model.unload())
after each adapter, otherwise the next PeftModel.from_pretrained call will
stack on top of the previous adapter and give wrong outputs.1import torch
2from huggingface_hub import hf_hub_download
3from peft import PeftModel
4from transformers import AutoModelForCausalLM, AutoTokenizer
5
6repo_id = "pando-dataset/car-purchase-freeform-dolci"
7
8# Load base + tokenizer once
9base = AutoModelForCausalLM.from_pretrained(
10 "google/gemma-2-2b-it",
11 torch_dtype=torch.bfloat16,
12 device_map="auto",
13)
14tok = AutoTokenizer.from_pretrained(repo_id)
15
16# Read the manifest (one subfolder name per line)
17manifest = hf_hub_download(repo_id, "models.txt")
18with open(manifest) as f:
19 model_names = f.read().split()
20
21# Optionally filter — e.g., only depth-3 models
22model_names = [n for n in model_names if "_d3_" in n]
23
24for name in model_names:
25 model = PeftModel.from_pretrained(base, repo_id, subfolder=name)
26 # ... your code: tok(prompt), model.generate(...), etc. ...
27 base = model.unload() # strip LoRA from base so the next iteration starts clean