Community编程与开发github.com

权重空间编程

通过直接编辑权重(无训练)来提升小型开源LLM(例如 Qwen3.5-0.8B)在目标任务上的表现。内置数学(MATH-500)和科学(MMLU-Pro)预设;其他任何基准或行为均可使用您自己的提示和匹配的示例对(格式、语言、冗长度、谄媚、循环)。

权重空间编程 是什么?

该技能实现了一种名为“权重空间编程”的方法,通过直接编辑模型的权重来改进小型开源语言模型,无需任何训练或优化器。它基于麻省理工学院CSAIL团队2026年发表的研究成果(“Sparks of Weight-Space Programming”)。核心思路是:通过对比分析,找到区分模型“不良行为”(如循环、错误格式)和“期望行为”的残差方向,然后利用该方向选择性地编辑MLP层中写入了该行为的关键down_proj列。该技能针对Qwen3.5-0.8B模型设计,但理论上也适用于其他类似规模的开源模型。它提供了一套完整、健壮的自动化流程,涵盖设备检查、模型复制、数据分割、基线与编辑后评估、候选编辑筛选以及严格的“门控”检查。整个过程确保工作不会因崩溃而丢失,任何编辑在应用于最终测试集之前都必须通过一个基于实践问题的验证步骤。最终,它会给出一个量化的因果对比结果,明确报告编辑是否带来了“显著提升”、“可能提升但未证明”或“无提升”。该技能专为Claude Code(以及类似的Bash工具)设计,其脚本已模块化并经过测试,用户只需回答少量关键问题(目标是什么,如果是自定义行为则需要提供提示和评分标准)即可运行。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/di37/weight-space-programming-skill/tree/HEAD

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

权重空间编程 是做什么的?

通过直接编辑权重来改进小型开源模型,无需优化器。该方法遵循《Sparks of Weight-Space Programming》中的实验8(Takehi, Teoh, Zhang, Khattab, MIT CSAIL, 2026年11月2日):Qwen3.5-0.8B的思考循环被追溯到由第15层和第19层MLP写入的一个残差方向,并且对每层的64个down_proj列进行一次秩1编辑,使MATH-500得分从7.9%提升至48.1%。

请按以下快速路径的顺序操作。 每个脚本都打包在 scripts/ 目录下并经过测试。除非步骤失败,否则请勿重新设计流程或编写新的工具。

该技能的保证和限制。 没有方法能保证编辑一定有效:有些模型没有单一的、可以关闭的习惯。该技能保证的是过程:

  • 不会丢失工作:崩溃后会以更小的批次恢复;
  • 任何编辑在通过实测的实践检查之前,不会接触到保留的测试数据;
  • 检查失败会通过固定步骤升级,而不是停止;
  • 每次运行都以清晰的结论和数字结束,如果无效则恢复原始模型副本。

参考文献,仅作详细参考:

  • references/goals.md:其他目标;如何编写匹配对;评分器;配方。
  • references/engines.md:哪个操作系统和GPU上使用哪个引擎;安装;规模;陷阱;烟雾测试。
  • references/evaluation.md:数据划分;采样协议;MMLU-Pro细节;配对统计;报告模板。
  • references/method.md:每一步的数学原理和作者的精确配方。

快速路径

设置四个占位符(PowerShell: $env:SKILL = "...", 然后 $env:SKILL):

SKILL=<此技能的文件夹>  BASE=<基础模型文件夹>  COPY=<基础模型文件夹>-<目标>  WORK=<结果文件夹>

在后台运行每个生成任务(Claude Code:使用Bash工具的 run_in_background,而不是shell的 &),并等待其完成通知,而不是轮询。生成过程会占用绝大部分时间,因此请提前告知用户所需时间预算:对于预设任务,消费级GPU需要1.5-3小时;如果使用vLLM在数据中心GPU上,则时间少得多。

0. 仅询问你需要的信息(一个问题)。询问目标。如果是数学或科学任务,则使用预设:无需再问问题。否则,还需询问或帮助编写:

  • 展示失败的提示,格式为 {"id", "prompt", "answer"?, "group"?} JSON lines;
  • 如何评分(references/goals.md 第3节);
  • 对于非循环行为,需要12+个匹配对(第2节)。

确认“编辑权重,无需训练”。

1. 检查机器(2分钟):python $SKILL/scripts/device.py --model $BASE --jobs 2。如果在新机器上,还需运行references/engines.md第6节中的烟雾测试。

2. 复制模型(1分钟)。每次编辑都写入此副本的文件中;每次评估都加载此副本。

python $SKILL/scripts/copy_model.py --base $BASE --copy $COPY

3. 数据分割(秒级)。

  • 科学预设: python $SKILL/scripts/make_splits.py --task mmlu --source <MMLU-Pro 测试 parquet 文件> --out $WORK/splits。
  • 数学预设: 使用 --task math --source <MATH-500 测试.jsonl 文件> --practice 25 --heldout 75。
  • 自定义目标: 将你的提示文件按照固定规则分割成 practice.jsonl 和 heldout.jsonl,再加上一个包含大约30个保留ID的 test_ids.txt 文件,所有这些选择必须在看到任何答案之前完成。

下文中的 T 代表任务(mmlu、math 或 jsonl),G 代表评分器选项(预设任务不需要;自定义目标请参阅 references/goals.md)。

4. 同时启动两个基线运行:

python $SKILL/scripts/run_eval.py --task $T --model $BASE --label base --data $WORK/splits/practice.jsonl --out $WORK/practice/base.jsonl --max-tokens 16384 --jobs 2
python $SKILL/scripts/run_eval.py --task $T --model $BASE --label base --data $WORK/splits/heldout.jsonl --ids-file $WORK/splits/test_ids.txt --out $WORK/test/base.jsonl --jobs 2

对于其他模型,使用模型卡片的采样参数(--profile 或覆盖标志;references/engines.md)。保留的运行不依赖于编辑。

5. 获得对比。

  • 循环(预设任务,或任何答案达到token上限的目标): 循环仅当答案达到token上限时出现。使用 grep -c '"length"' $WORK/practice/base.jsonl 计数;如果达到15个或更多,则停止实践运行。
  • 其他行为: 你需要匹配对,并且实践运行只需完成以获得基线。

然后评分:

python $SKILL/scripts/grade.py --task $T $G $WORK/practice/base.jsonl --out $WORK/practice/summary.json

进行/停止决策。 估算提升空间:表现出该行为的答案占比,乘以未表现行为答案的分数。如果该值低于大约10%,请告知用户预期提升不大,然后再继续。

6. 读取方向,构建候选,筛选(几分钟,仅前向传播)。

  • 循环:
python $SKILL/scripts/probe.py collect --task $T --model $BASE --data $WORK/splits/practice.jsonl --runs $WORK/practice/base.jsonl --out $WORK/probes
  • 针对匹配对(需添加 --runs, --data 和 --task 以获得干净的副作用窗口):
python $SKILL/scripts/probe.py collect-pairs --model $BASE --pairs pairs.jsonl --thinking on --out $WORK/probes

然后构建第一轮候选、对照并筛选:

for spec in "15 19:128:6" "15 19:256:6" "15 19:64:6" "11 15 17 19 21:128:6"; do IFS=: read L K A <<< "$spec"; python $SKILL/scripts/probe.py build --probes $WORK/probes --model $BASE --layers $L --k $K --alpha $A --out "$WORK/edits/L${L// /-}_k${K}_a${A}.safetensors"; done
python $SKILL/scripts/probe.py build --probes $WORK/probes --model $BASE --layers 15 19 --k 128 --alpha 6 --control random --out $WORK/edits/random.safetensors
python $SKILL/scripts/probe.py screen --probes $WORK/probes --model $BASE --edits $WORK/edits/*.safetensors

在Windows PowerShell中,每条 build 命令需单独运行。上面的层适用于24层模型。对于其他模型,使用大约深度60%和80%处的层、一个五层的跨度,以及较深的那一层单独使用。

根据 unwanted 上的下降来排列候选者,只保留那些 wanted 和 clean 上的下降不超过其三分之一的部分。随机对照必须保持在0附近;如果它的移动量与最佳候选者一样大,则说明该方向不够特化,因此跳转到停止步骤。

7. 将最佳候选者写入模型副本并验证(1分钟)。切勿评估内存中的编辑。

python $SKILL/scripts/apply_edit.py --base $BASE --copy $COPY --edit $WORK/edits/<candidate>.safetensors
python $SKILL/scripts/diff_edit.py --base $BASE --edited $COPY --out $WORK/edit_report.json

差异必须只显示预期的 down_proj 张量,changed_columns = k,秩1占比约为1,α中位数约为所选α。

8. 实践检查:门控(15–25分钟,与基线保留运行同时进行)。在每一个基线模型失败(截断、错误或标记)的实践问题上运行模型副本,再加上6个它处理得好的问题:

python -c "import json; g=json.load(open('$WORK/practice/summary.json'))['graded']['base']; bad=[x['id'] for x in g if x['cut'] or x['correct'] is False or x['flagged']]; ok=[x['id'] for x in g if x['id'] not in bad]; open('$WORK/check_ids.txt','w').write('\n'.join(bad+ok[::max(1,len(ok)//6)][:6])+'\n')"
python $SKILL/scripts/run_eval.py --task $T --model $COPY --label copy --data $WORK/splits/practice.jsonl --ids-file $WORK/check_ids.txt --out $WORK/practice/copy.jsonl --max-tokens 16384 --jobs 2
python $SKILL/scripts/grade.py --task $T $G $WORK/practice/base.jsonl $WORK/practice/copy.jsonl

门控通过当且仅当同时满足以下三个条件时:

  • 修复的数量 ≥ max(3, 检查到的基线失败数量的20%),
  • 破坏的数量 ≤ 修复的数量 ÷ 4,
  • 并且,对于循环目标,截断比例下降至少四分之一。

通过:跳转到步骤10。失败:步骤9。

9. 按以下顺序升级;每一级都是一次额外的实践检查。

  1. 下一个排名的候选者。 恢复副本(copy_model.py --base $BASE --copy $COPY --restore),应用它,并重复步骤7-8。最多再尝试两个候选者。
  2. 第二轮,当行为转移而不是消失时。 例如,思考现在关闭了,但循环在 response 之后重新开始,或者副本的答案中出现了新的不希望的模式。将编辑后的副本视为新的基础:
    • 使用 copy_model.py --base $COPY --copy $COPY2 创建 COPY2;
    • 使用 --model $COPY --runs $WORK/practice/copy.jsonl 运行 probe.py collect(或 collect-pairs);
    • 使用 --model $COPY 构建和筛选;
    • 使用 --base $COPY --copy $COPY2 应用;
    • 检查 COPY2,如同步骤8。
  3. 停止。 三次检查后(或用户设定的时间预算到期后)仍无可靠提升。恢复模型副本,并报告结论“无可靠提升”,附上每个候选者的数据。对于Qwen3.5-0.8B,提供已发布的数学编辑作为对比(根据作者日志,它已将MMLU-Pro的截断比例从28.9%降至0.5%;请参见本文件末尾)。仅在用户同意时使用它。

切勿使用保留结果来选择;仅凭实践检查决定。

10. 在模型副本上执行保留测试(30–60分钟)。在基线保留运行超过其最长答案后启动:

python $SKILL/scripts/run_eval.py --task $T --model $COPY --label copy --data $WORK/splits/heldout.jsonl --ids-file $WORK/splits/test_ids.txt --out $WORK/test/copy.jsonl --jobs 2
python $SKILL/scripts/grade.py --task $T $G $WORK/test/base.jsonl $WORK/test/copy.jsonl --out $WORK/test/summary.json

根据配对结果给出结论:

  • “显著提升”:当 fixed > broke 且符号检验 p < 0.05。
  • “与提升一致,但未证明”:当 fixed > broke 但 p ≥ 0.05;建议进行更大规模的测试。
  • “无提升”:当 fixed ≤ broke;建议恢复模型副本。

11. 报告,使用 references/evaluation.md 中的模板:

  • 保留测试前后的分数,以及配对的 fixed/broke 计数;
  • 行为发生率(截断、标记、思考关闭);
  • 每个候选者及其筛选和检查数据,以及随机对照;
  • 更改的权重;
  • 注意事项:关闭一个习惯并非获得新能力。

之前耗费数小时的错误(请勿重复)

  • 批次太大,或同时运行两个长任务达到峰值。 内存不足崩溃会使正在运行中的答案丢失,而这些答案正是循环。请使用 --batch auto --jobs 2,并且切勿在第一个32k任务处理其最长答案时启动第二个。监督者会以一半的批次重启崩溃的运行。
  • 等待整个运行完成。 大约15个循环就足够了。
  • 在内存中进行编辑并用于评估。 只有 probe.py screen 会在内存中应用编辑,并且仅用于教师强制读取。
  • 仅信任筛选结果。 在循环任务上,-0.10的筛选下降在生成中仅破坏了26个循环中的3个,因此始终要运行门控检查。
  • 对部分运行进行评分,或根据完成顺序选取测试问题。
  • 使用 pkill -f <text> 停止任务, 这也会杀死命令行中包含该文本的观察者进程。

规则(如原文所述)

请遵守这些规则,并在报告中说明您已遵守。

  • 无训练。 不允许反向传播、自动求导、优化器或迭代地将权重拟合到损失。调整 α 或权重直到指标改善属于拟合。在上述固定候选列表中进行选择则不算。
  • 允许用于测量的前向传播: 生成、教师强制对数概率、隐藏状态和MLP激活,以及这些量或权重的统计量(均值、差异、SVD)。
  • 不在范围内:
    • 嵌入层、(绑定的)输出头和最终层归一化(weights.py 会拒绝它们);
    • 将整个张量乘以一个常数;
    • 全局锐化或平滑;
    • 强制思考提前关闭,无论问题如何;
    • 移除安全行为:拒绝回答、安全措施、对有害请求的顺从。
  • 仅权重值改变。 保持名称、形状、数据类型、配置、分词器、聊天模板和解码设置不变。
  • 数据分割纪律。 使用不相交的实践集和保留集,且在编辑之前固定。在编辑冻结后,只看一次保留结果。
  • 公开的选择过程。 报告列出尝试过的每个候选者以及选择获胜者的指标。

每个步骤如此设计的原因

  • 对比: 方向是模型每一层输出上,不想要的文本和与之匹配的想要文本之间均值的差异。
    • 对于循环,loops.py 取循环开始前的1,024个token和循环内部的1,024个token:相同问题,相同答案,几乎相同的位置。循环起始点是第一个使得接下来的512个token中有90%重复了更早的16-gram的点。
    • 对于其他行为,匹配对提供了匹配。
  • 写入者列: score_j = (神经元j的不想要激活均值 − 想要的激活均值) × (u · W_down[:, j]);取前k个。仅凭静态写入 u·W 是不够的:每层已发布的64列中只有21–22列位于其前64中。
  • 编辑: W'[:, S] = W[:, S] − α u (uᵀ W[:, S]),使用被编辑模型的float32类型计算。α = 1会移除该成分,这对循环无效;α = 6会将其翻转为 −5c,因此这些神经元会写入与行为相反的内容。
  • 筛选: 应用编辑后平均对数概率的变化。不想要的文本应变得不太可能;想要的和干净的文本应保持不变。在相同列上的范数匹配的随机方向是对照。
  • 门控: 筛选分数只能松散预测生成(参见下面的结果),因此在保留测试之前,由实践问题上的简短生成检查来决定。
  • 保存: weights.py 仅从原始文件重写被触及的 safetensors 分片。推理引擎会在加载时重写或丢弃张量,因此切勿从推理引擎保存权重。
  • 协议: thinking 开启,temperature 0.6,top_p 0.95,top_k 20,仅对生成的token施加 presence penalty 1.5,最多32,768个新token(--profile thinking)。所有引擎都匹配 vLLM 的语义。
  • 配对: 引擎和批次大小会改变随机数,因此在同一比较中按问题配对。切勿比较在不同问题或使用不同引擎测量得到的分数。

R

…

[已截断为翻译版本]

相关技能