【免费下载链接】doc-to-lora
Hypernetworks that update LLMs to remember factual information
Doc-to-LoRA 是一个用**超网络(Hypernetwork)**把文档"一键写进"大语言模型(LLM)的开源项目:它通过一个叫HyperLoRA的轻量网络,读取文档后直接生成一组 LoRA 权重并挂到冻结的基座模型上,让模型瞬时"记住"文档内容,而无需把上下文反复塞进 context window。本文带你拆解这套 LoRA 权重生成机制的完整链路。
为什么需要"生成 LoRA"而不是直接塞上下文?
传统用法是把长文档放进 prompt,每次推理都要重复编码,token 费用和延迟都很高。Doc-to-LoRA 的思路相反:
- 一次性编码:把文档喂给一个编码器,只跑一次前向;
- 生成权重:超网络根据文档特征"算出"一套 LoRA 的 A/B 矩阵;
- 正常推理:基座模型挂上这套动态 LoRA 后,后续每次生成都直接"记得"文档,速度不输无上下文的基座模型。
源码入口非常直观——internalize() 方法 只接受一段字符串,生成并缓存权重;调用reset()即可把"记忆"完全抹掉。
三大角色:上下文编码器、聚合器、超网络头
整个"写权重"的过程由三个模块接力完成,核心实现在 src/ctx_to_lora/modeling/hypernet.py。
1️⃣ 上下文编码器(Ctx Encoder):冻结的模型替身读文档
文档首先由一个与基座模型同源但完全冻结的编码器读取,输出每个 token 的隐状态。项目提供三种取法(src/ctx_to_lora/modeling/ctx_encoder.py):
| 模式 | 输出内容 | 特点 |
|---|---|---|
embed_only | 仅 embedding 层输出 | 最轻量,信息最少 |
early_exit | 提前在浅层退出 | 速度与信息的折中 |
per_layer_activations | 每一层的激活堆叠 | 信息最全,主实验默认 |
主实验配置 configs/main_exp/self_gen_lv1_closed_qa_1_l2l.yaml 中ctx_encoder_type: per_layer_activations,即把文档在每一层的"理解结果"全部保留下来交给下游。
2️⃣ 聚合器(Aggregator):把上万 token 压缩成几十个"钥匙"
文档特征序列很长,无法直接变成权重,所以需要压缩。默认方案是Perceiver 结构(src/ctx_to_lora/modeling/aggregator.py):
- 用一组可学习的latent queries(
n_latent_queries,默认 208)对文档特征做交叉注意力,相当于"提问—检索"; - 经过
num_blocks个处理块后,再解码出恰好层数 × 模块数 × rank个输出向量,每个向量对应基座模型中某一个 Linear 层将来要用的 LoRA 参数分片。
可以把它理解成:Perceiver 把整篇文档蒸馏成一把把"钥匙",每把钥匙精确对应模型里的一个位置。
3️⃣ HyperLoRA 头:从潜在表示到 A/B 矩阵
拿到 latent 向量后,HyperLoRA 类 做最后一段"翻译":
- ResMLP 精炼层:若干残差 MLP 块(
num_pre_head_layers,隐层latent_size=512)对 latent 做非线性加工; - L2 归一化 + 线性头:归一化后用 einops
Mix线性层,一次性输出形状为[batch, 层数, 模块数, rank, 维度]的扁平张量; - 拆分成 A、B 矩阵:
_to_lora_dict()把扁平张量按维度切开,得到每个目标模块(如down_proj)的 LoRA A/B 矩阵; - 数据依赖的缩放与偏置:
scaler_A / scaler_B是对每个 rank 的逐元素缩放(由文档决定"强度"),bias_A / bias_B是可学习偏置,为每个文档提供一个固定的"基础 LoRA"(use_bias: true)。
一个值得玩味的细节:超网络初始化时会把输出头清零(_bias_hyper_init),保证训练起点处生成接近零的 LoRA——模型一开始就是"裸"的基座模型,记忆完全由训练学会。
权重如何注入:动态 LoRA 前向
生成好 A/B 矩阵后,真正"写进模型"的动作发生在 src/ctx_to_lora/modeling/lora_layer.py:
patch_lora_forward()遍历基座模型每一层的目标 Linear 模块,把它们的forward替换成动态版本;- 替换后的前向公式就是经典 LoRA:
输出 = 原始Linear(x) + B·(A·x)·scaling,但 A/B 不是固定参数,而是来自文档的那套生成张量; - 若文档被切成多个 chunk,combine_lora() 会按rank 维度拼接各 chunk 的 LoRA,总 rank 为
(chunk数 + 1) × r,其中 +1 就是给 bias 偏置留的位置。
关键点:基座模型的原始权重自始至终一个都没被修改。所谓"写入"其实是给每个 Linear 层动态外挂一个前向钩子,reset()时把forward换回原版,记忆即刻消失——这也是 Doc-to-LoRA 能干净"遗忘"的原因。
超网络本身是怎么学会"写权重"的?
训练目标很朴素:蒸馏。如 src/ctx_to_lora/modeling/context_distillation.py 所示:
- 教师:基座模型直接带着完整文档作答;
- 学生:基座模型不带文档,只挂上超网络为文档生成的 LoRA;
- 让学生的输出分布(top-k 词表上的 KL 散度)逼近教师,反向传播只更新超网络。
训练完成后,超网络就学会了一种"文档 → LoRA 权重"的映射。保存 checkpoint 时也只需存超网络参数——基座模型和上下文编码器都是冻结的、共享的,这正符合"超网络只生成、不修改"的设计哲学(见ModulatedPretrainedModel.state_dict())。
快速上手:三步跑通 LoRA 权重生成
📦1. 安装环境
curl -LsSf https://astral.sh/uv/install.sh | sh ./install.sh🤗2. 下载预训练模型
uv run huggingface-cli login uv run huggingface-cli download SakanaAI/doc-to-lora --local-dir trained_d2l --include "*/"🚀3. 启动交互 Demo
uv run demo/app.py在 Web 界面里粘贴任意文档即可体验"瞬时内化"。如果想用 Python API 直接调用internalize(),可参考 examples/python_api.py 和 demo/app.py。此外,项目还自带数据生成与可视化工具:
- 训练/评估脚本:scripts/main_exp/
- 自生成 QA 数据查看器:webui/self_gen_viewer.py
- NIAH 检索实验:scripts/niah/
核心文件索引
| 模块 | 文件 | 作用 |
|---|---|---|
| 超网络与权重生成 | src/ctx_to_lora/modeling/hypernet.py | HyperLoRA 定义、internalize/reset、动态前向挂载 |
| 上下文编码器 | src/ctx_to_lora/modeling/ctx_encoder.py | 三种文档特征提取模式 |
| Perceiver 聚合器 | src/ctx_to_lora/modeling/aggregator.py | latent queries 压缩长文档 |
| 动态 LoRA 前向 | src/ctx_to_lora/modeling/lora_layer.py | A/B 矩阵注入各 Linear 层 |
| 多 chunk 权重合并 | src/ctx_to_lora/modeling/lora_merger.py | rank 维度拼接与 bias 追加 |
| 蒸馏训练 | src/ctx_to_lora/modeling/context_distillation.py | 教师-学生 KD 训练超网络 |
| 实验配置 | configs/main_exp/self_gen_lv1_closed_qa_1_l2l.yaml | 主实验超参数(rank=8 等) |
小结
Doc-to-LoRA 的精髓在于把"记住文档"这件事从推理时搬到了权重生成时:冻结的编码器读懂文档,Perceiver 把它压缩成 latent 钥匙,HyperLoRA 头把钥匙翻译成每层每模块的 A/B 矩阵,动态前向钩子再把这些矩阵"焊"进冻结模型。整个过程不改动基座参数、可随时重置,是超网络(hypernetwork)范式的又一次漂亮落地。
【免费下载链接】doc-to-lora
Hypernetworks that update LLMs to remember factual information
相关推荐
CoffeeScript 快速上手:以 learnxinyminutes-docs 的注释代码示例读懂这门"编译为 JavaScript"的语言
CoffeeScript 快速上手:以 learnxinyminutes docs 的注释代码示例读懂这门"编译为 JavaScript"的语言 CoffeeS
如何把qwen25-vl-lora-pokemon的LoRA权重合并进Qwen2.5-VL基础模型:完整操作教程
如何把qwen25 vl lora pokemon的LoRA权重合并进Qwen2.5 VL基础模型:完整操作教程 本文将带你 快速 完成 qwen25 vl l
Octant v0.9 版本全解析:环境变量化配置、ConfigMapsForPod 崩溃修复与资源视图能力增强
Octant v0.9 版本全解析:环境变量化配置、ConfigMapsForPod 崩溃修复与资源视图能力增强 本篇文章围绕 Octant 开源仓库 chan
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考