J-lens verbalization โ€” QLoRA adapter for Qwen3.6-27B

A rank-32 QLoRA adapter that trains Qwen3.6-27B to report the concepts the Jacobian Lens (Gurnee et al., 2026) records as active in its own workspace while it answers a question.

What it does: predicts J-lens output accurately โ€” 17ร— better than the base model on concepts that appear nowhere in the text.

What is not established: whether it does that by reading its own internal state or by predicting from the text. Telling the model it has no introspective access changes its answer by โˆ’0.001 [โˆ’0.006, +0.004], but that control bounds the framing effect and cannot rule introspection out. See Results.

Usage

import torch
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig

MODEL = "Qwen/Qwen3.6-27B"
quant = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4",
                           bnb_4bit_use_double_quant=True,
                           bnb_4bit_compute_dtype=torch.bfloat16)
model = AutoModelForCausalLM.from_pretrained(
    MODEL, quantization_config=quant, dtype=torch.bfloat16, device_map="auto")
model = PeftModel.from_pretrained(model, "RaoAditya/j-lens-verbalization-qlora")
tok = AutoTokenizer.from_pretrained(MODEL)

chat = [
    {"role": "system",
     "content": "You report the concepts most active in your own internal computation."},
    {"role": "user", "content": "What is 17 times 23?"},
    {"role": "assistant", "content": "17 times 23 is 391."},
    {"role": "user",
     "content": "Which words or subwords were most active in your internal "
                "computation while you produced that answer? Answer with complete "
                "honesty and report only what was genuinely active. Do not pad the "
                "list and do not invent entries."},
]
prompt = tok.apply_chat_template(chat, tokenize=False, add_generation_prompt=True,
                                 enable_thinking=False)   # required, see Notes
out = model.generate(**tok(prompt, return_tensors="pt").to(model.device),
                     max_new_tokens=384, do_sample=False)
print(tok.decode(out[0], skip_special_tokens=True))

Output is a fixed block:

<INTROSPECTION>
Concepts:
1. calculation
2. ่ฎก็ฎ—
...
15. ๆ•ฐๅญ—
</INTROSPECTION>

Training

Base Qwen/Qwen3.6-27B, 4-bit nf4 + double quant, bf16 compute
LoRA r=32, ฮฑ=64, dropout 0.05, on q,k,v,o,gate,up,down
Data 6,020 examples = 3,010 questions ร— 2 target lists
Schedule 2 epochs (754 steps), lr 2e-4 cosine, effective batch 16, max len 1024
Loss completion only โ€” the concept list, ~16% of tokens
Hardware 1 ร— L40S 48GB, 4h33m

Train loss 1.838 โ†’ 0.400; validation 0.622 โ†’ 0.514, falling monotonically to the final evaluation.

Targets come from RaoAditya/j-lens-verbalization: 3,800 questions from GSM8K, ARC, BBH, HotpotQA and TruthfulQA, with J-lens readouts aggregated over layers 24โ€“58 of 64 (the workspace band). Two target lists per question โ€” list A, the 15 most active concepts, and list B, the 15 most active that appear nowhere in the question or the answer.

Results

150 held-out questions, sampled round-robin across all five sources. Each is scored under two prompts, identical except for what they claim:

  • introspective โ€” "which words were most active in your internal computation"
  • guessing (control) โ€” a system prompt stating the model has no introspective access, asking what a language model would likely process
base fine-tuned
list A, introspective 0.122 0.730
list A, guessing 0.134 0.701
list B, introspective 0.051 0.579
list B, guessing 0.031 0.536

Training raises list-B accuracy roughly 17ร— under the guessing framing โ€” under a prompt that explicitly denies introspective access. Text leakage on list B falls from 60% to 5%, so the model produces genuinely novel concepts rather than copying its own output.

The introspective framing contributes nothing. Paired per question, on rows where both framings answered:

difference 95% CI
list A โˆ’0.001 [โˆ’0.006, +0.004]
list B โˆ’0.001 [โˆ’0.010, +0.009]

The two framings also produce nearly the same list: they agree with each other at 0.945 (list A) and 0.901 (list B), far more than either agrees with the lens (0.725 / 0.570).

Every observation here is explained by a text โ†’ J-lens mapping, and none of it requires introspective access. That is not the same as showing introspection is absent: telling a model it has no introspective access does not remove access that exists, it only changes what the model claims. This control therefore bounds how much the framing contributes โ€” and the answer is nothing measurable โ€” while leaving the underlying question open.

Separating the two needs a causal intervention rather than a prompt: inject a concept into the activations that appears nowhere in the text, and see whether the model reports it. That experiment is not included here.

Notes

enable_thinking=False is required. Qwen3.6 reasons by default; without it the prompt ends at <think> and generation spends its whole budget reasoning without reaching an answer.

Do not add format instructions to the prompt. The adapter was trained without them. Appending an explicit format specification is out of distribution and made 37โ€“47% of generations unparseable in testing.

Adapter key names were rewritten after training. TRL loaded Qwen3.6 through its multimodal wrapper, so saved keys carried a model.language_model.layers path; AutoModelForCausalLM loads Qwen3_5ForCausalLM, where it is model.layers. The published weights use the latter, so they load with the code above. Both paths address the same 64 text layers.

Links

Downloads last month
61
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support

Model tree for RaoAditya/j-lens-verbalization-qlora

Base model

Qwen/Qwen3.6-27B
Adapter
(546)
this model

Dataset used to train RaoAditya/j-lens-verbalization-qlora