Hypernetworks that update LLMs to remember factual information https://arxiv.org/abs/2602.15902
Find a file
2026-06-15 04:31:47 +00:00
assets video update 2026-02-13 08:49:48 +00:00
chat_templates add qwen3-4b and mistral-7b (niah working) 2025-10-10 06:31:20 +00:00
configs icml cleaned 2026-02-13 06:02:29 +00:00
data icml rebuttal 2026-06-15 04:31:47 +00:00
demo add bib gif video (waiting for arxiv id) 2026-02-13 08:30:08 +00:00
examples icml rebuttal 2026-06-15 04:31:47 +00:00
scripts icml rebuttal 2026-06-15 04:31:47 +00:00
src/ctx_to_lora icml rebuttal 2026-06-15 04:31:47 +00:00
tests icml rebuttal 2026-06-15 04:31:47 +00:00
webui add bib gif video (waiting for arxiv id) 2026-02-13 08:30:08 +00:00
.gitattributes icml rebuttal 2026-06-15 04:31:47 +00:00
.gitignore icml rebuttal 2026-06-15 04:31:47 +00:00
.pre-commit-config.yaml rearrange + move to uv (#1) 2025-05-27 21:18:15 +09:00
accelerate_config.yaml sakura scripts 2025-08-11 15:00:30 +09:00
install.sh add bib gif video (waiting for arxiv id) 2026-02-13 08:30:08 +00:00
pyproject.toml icml rebuttal 2026-06-15 04:31:47 +00:00
README.md icml rebuttal 2026-06-15 04:31:47 +00:00
run_eval.py icml rebuttal 2026-06-15 04:31:47 +00:00
setup.py rearrange + move to uv (#1) 2025-05-27 21:18:15 +09:00
train.py icml cleaned 2026-02-13 06:02:29 +00:00
uv.lock icml rebuttal 2026-06-15 04:31:47 +00:00
watcher.py toy exp w/ self-gen + use double bos for eval (following vllm 0.8.4) 2025-09-07 17:16:20 +09:00

Doc-to-LoRA (D2L): Learning to Instantly Internalize Contexts

📰X | 📜Paper | 🤗Hugging Face | :octocat:GitHub
A reference implementation of Doc-to-LoRA (D2L).

🛠️ Installation

curl -LsSf https://astral.sh/uv/install.sh | sh
./install.sh

🤗 Pre-Trained Models

uv run huggingface-cli login
uv run huggingface-cli download SakanaAI/doc-to-lora --local-dir . --include "trained_t2l/*"

🚀 Python API Usage

# caveat: this interface only supports non-batched inputs
# for batched inference please see `src/ctx_to_lora/modeling/hypernet.py`
import torch

from ctx_to_lora.model_loading import get_tokenizer
from ctx_to_lora.modeling.hypernet import ModulatedPretrainedModel

# model loading
checkpoint_path = ...
state_dict = torch.load(checkpoint_path, weights_only=False)
model = ModulatedPretrainedModel.from_state_dict(
    state_dict, train=False, use_sequence_packing=False
)
model.reset()
tokenizer = get_tokenizer(model.base_model.name_or_path)

# prepare data
doc = open("data/sakana_wiki.txt", "r").read()
chat = [{"role": "user", "content": "Summarize what Sakana AI does."}]
chat_ids = tokenizer.apply_chat_template(
    chat,
    add_special_tokens=False,
    return_attention_mask=False,
    add_generation_prompt=True,
    return_tensors="pt",
).to(model.device)


# calls after internalization will be influenced by internalized info
model.internalize(doc)

outputs = model.generate(input_ids=chat_ids, max_new_tokens=256)
print(tokenizer.decode(outputs[0]))


# remove internalized info
model.reset()

outputs = model.generate(input_ids=chat_ids, max_new_tokens=256)
print(tokenizer.decode(outputs[0]))

🎮 Interactive Demo

uv run demo/app.py

🧪 Experimental Scripts

To run any of the following scripts, use uv run $PATH_TO_SCRIPT from the root of this project.

Experiment Data prep Training Evaluation Notes
Main experiment scripts/main_exp/0-download_data.sh scripts/main_exp/1-train.sh scripts/main_exp/eval/*.sh Downloading data is fastest; regenerate only if you need fresh synthetic data. Evaluation scripts reproduce the main paper metrics.
NIAH scripts/niah/0-gen_data.sh scripts/niah/1-train.sh scripts/niah/2-eval.sh Run the scripts in order; data generation only needs to happen once

scripts/main_exp/eval/clipper.sh adds the CLIPPER long-context benchmark to the eval pipeline via the public chtmp223/CLIPPER Hugging Face dataset.

scripts/main_exp/eval/rag.sh runs a lightweight BM25-style RAG baseline over each example's context field. It keeps dataset-side context chunking disabled and performs retrieval chunking inside the eval-time wrapper.

WANDB_MODE=disabled uv run run_eval.py \
  --model_name_or_path google/gemma-2-2b-it \
  --datasets squad drop ropes \
  --split test \
  --eval_batch_size_gen 1 \
  --use_rag \
  --rag_chunk_size 256 \
  --rag_chunk_overlap 64 \
  --rag_top_k 4 \
  --rag_max_retrieved_tokens 1536

scripts/main_exp/eval/d2l_rag.sh runs a hybrid mode where Doc-to-LoRA internalizes the full document while the same document is also queried with BM25-style retrieval to build a smaller prompt-side evidence block.

WANDB_MODE=disabled uv run run_eval.py \
  --checkpoint_path train_outputs/runs/$RUN_NAME/checkpoint-$step/pytorch_model.bin \
  --datasets squad drop ropes \
  --split test \
  --eval_batch_size_gen 1 \
  --use_hybrid_rag \
  --rag_chunk_size 256 \
  --rag_chunk_overlap 64 \
  --rag_top_k 4 \
  --rag_max_retrieved_tokens 1536

Generated JSONL outputs include compact retrieval metadata under rag_selected_chunks together with prompt/context token counts for debugging.

🔬 Self-Generated Data Viewer

After downloading/generating the data, we can see samples of the data using this script.

uv run webui/self_gen_viewer.py

See more info at webui/SELF_GEN_VIEWER.md.

📚 Citation

@techreport{sakana2025doc-to-lora,
  title       = {{Doc-to-LoRA: Learning to Instantly Internalize Contexts}},
  author      = {Rujikorn Charakorn and Edoardo Cetin and Shinnosuke Uesaka and Robert Tjarko Lange},
  institution = {Sakana AI},
  year        = {2026},
  month       = {Febuary},
  note        = {Technical Report}
}