让 AI 学会说话的味道——导向向量的在线自适应学习
做 Agent 的时候碰到一个问题:模型"说什么"可以通过 prompt 控制,但"怎么说"很难靠提示词稳定。语气太冲了你让它温柔,下一轮它又恢复原样。我想让模型自己从交互反馈里学会调整说话风格,而不是每次都靠人工调 prompt。
研究了一下导向向量(Activation Steering),发现现有方法都是离线提取、推理时固定的——没有"边聊边学"的能力。于是尝试做了一套在线自适应方案。先说清楚:这套东西还比较早期,没跑过严格评测,分享的是设计思路和工程方案。
背景
导向向量近两年进展很快(CAA、RepE 等),操作就一件事:从中间层激活差分里提取一个方向向量,推理时加上去,模型输出就会往那个方向偏。
但有两个问题困扰了我:
第一,向量提完就定死了。 100对语料做CAA,提取一个"温柔方向"的向量,之后一直用。如果用户在不同情境下偏好不同风格,系统没有学习能力。
第二,大家把 prompt 注入和导向向量当成了竞争方案。 多数讨论是在对比"用哪个更好",但我觉得这搞错了。
想想人在愤怒时的表现:一方面,你知道自己在生气,可以用语言描述这种状态(“我很生气”);另一方面,你的声音不自觉地变大、语速加快,这不是你有意控制的。
前者是显意识,后者是潜意识。对应到 Agent 系统里:
- Prompt 注入(mood 文字)= 显意识通道:模型能推理自己的情绪状态,能说"我有点难过"
- 导向向量注入 = 潜意识通道:模型的用词和语气不自觉地偏移,不需要理解为什么
这两个不冲突。 它们作用在不同层面——文字通过 attention 影响所有层,向量只注入在中间层。同时开启的时候,模型既知道自己情绪不好,说话方式也无意识地变柔了。跟人既知道自己在生气、声音又不自觉变大一样。
核心方法
用矩阵替代向量
传统方法维护一个固定的 d 维导向向量。我换成了一个 (d, n) 维的映射矩阵 W,让导向向量变成情境状态的函数:
v = v̂₀ + W · S_norm
v̂₀ 是基线(一次性提取的默认风格),W 负责把 n 维情境状态映射成行为偏移。不同情境自动产生不同方向的导向。
这里有个容易忽视的细节:提取 W 的初始列向量后,需要做 Gram-Schmidt 正交化。如果不正交化,“更开心”的方向可能跟“更自信”有投影分量——调情感愉悦度的时候自信度也跟着串了。正交化保证各维度独立可控,调一个不会意外影响另一个。
注入强度 α 的设计也有个反直觉的地方:情绪越极端,α 反而越低。人在极端压力下会变得“不像自己”——平时温柔的人可能突然变凶,平时冒失的人可能突然沉默。导向向量的“人设维护力”应该在此时减弱,而不是增强。所以公式里唤醒度的系数是负的——绝对值越大,α 越小。
学习问题就变成了:怎么更新 W?
Hebbian 外积更新
收到反馈时(不好的表达 vs 好的表达),做一次在线学习。这里的反馈对不是人类手工标注的——是模型自己生成的。模型在反思时产生“我刚才太冷淡了,应该更温暖”这样的结论,然后自己写出一对冷淡/温暖的例句。整个学习回路是自驱动的闭环,不依赖人工标注。
dv = normalize(activation(good) - activation(bad))
S_norm = normalize(current_state)
W += importance * eta * outer(dv, S_norm)
直觉上就是:“在当前情境下,记住行为应该往这个方向偏”。importance 是上游给的重要度,不重要的反馈直接跳过。
还有一个设计选择值得说:正反馈不触发 W 更新。"做得好"只说明当前 v 已经在合理方向上了,没有新的方向信息可学。如果正反馈也更新 W,等于在强化随机噪声——因为你无法从"这次没问题"中提取一个有意义的 Δv。只有负反馈(“刚才太冷淡了,应该更温暖”)才能给出明确的偏移方向。
而且不是所有负反馈都会触发更新。系统会过滤:只有"风格"相关的反馈才更新 W。如果模型犯的是事实错误(“说错了朝代”),那不是"怎么说"的问题,是"说了什么"的问题——导向向量只负责前者。通过关键词过滤(“语气”“态度”“温柔”"生硬"等)判断反思是否涉及风格,不涉及就跳过。
为什么改 W 不改 v
一开始我想过直接 v += η × Δv,后来发现不行。v 是 W·S 的结果,S 每轮交互都在变——你这一秒改了 v,下一秒 S 变了 v 就被重新算了,刚才的修改白费了。
改 W 改的是映射本身。下次遇到类似的情境 S,系统自动产生学过的偏移方向。
单次反馈很嘈杂?没关系
这里有一个一开始困扰我的问题:传统 CAA 要 100 对语料取平均才能得到可靠的方向向量。但在线学习时,每次反馈只有一对例句——方向肯定是嘈杂的。
后来想了想,觉得这个问题不像看起来那么严重。多次外积累加时,噪声方向因为每次不一样而互相抵消,而真正共同的偏好方向会被反复强化。这和传统 CAA 多对语料取平均的思路是类似的,只不过不是严格等价——因为每次的情境状态 S 不同,外积的结果会分布在 W 的不同列上,实际上比纯平均更细粒度——它区分了“在什么情境下该往哪个方向偏”。
防失控
双时标正则化
每轮交互后微衰减: W *= (1 - 1e-4)。相当于一条遗忘曲线,不被反复强化的偏好慢慢淡掉。
周期性大回拉: W = 0.95·W + 0.05·W_init。把 W 往初始矩阵方向拉回一部分,类似"睡一觉醒来,还是那个自己,但多了些新倾向"。
W 的天然约束
W 的形状是 (d, n),秩最多为 n。哪怕 d = 4096,n 只有个位数的时候,W 只能在整个激活空间中划出一个 n 维子空间来施加影响。它不可能在 4096 维空间里乱搞。这是架构层面自带的安全性。
三层工程安全
- 模型哈希校验——换模型自动拒绝旧 W
- Frobenius 漂移上限——超了就回滚 checkpoint
- 注入比例兜底——
||α·v||不能超过 hidden states 范数的 10% - 行为空间回读——把
W^T · v投影回 n 维,得到一个“行为空间的状态读数”。跟真实状态对比,如果偏差大,说明 W 的学习已经导致行为偏离了状态的预期方向
降级方案的一个反直觉设计
导向向量只能在本地模型用(需要摸中间层)。切到云端 API 时怎么办?
一开始想的方案是:“把 v 从激活空间投影回语义空间,转成文字描述注入 prompt”——听起来很优雅对吧?
后来发现这是走了一圈回到原点。 v = W·S,把 v 投影回去约等于恢复 S……而 S 本身已经在 mood 文字里了。等于你把导向向量转换成了一段跟已有 mood 文字重复的描述。
正确的降级方式是换一个信息源:不从 v 投影,而是从 W 的学习日志里做统计——“过去这段时间,哪些风格关键词被反复强化了?”——然后把统计结果转成自然语言补进 prompt。比如"你近期倾向于更温柔的表达"。这个信息在 mood 文字中是没有的,是 W 的学习历史独有的。
精度肯定丢了,但至少补的是增量信息,而不是重复信息。
伪代码
class AdaptiveSteering:
"""
W: (d, n) 映射矩阵,可在线学习
W_init: (d, n) 初始矩阵,正则化锚点
v0: (d,) 基线向量
"""
def compute_steering(self, context_state):
S_norm = S / max(norm(S), 1.0)
v = normalize(v0) + W @ S_norm
alpha = clamp(alpha_base + f(S), alpha_min, alpha_max)
return v, alpha
def learn(self, model, layer, bad_text, good_text,
context_state, importance, eta=0.01):
if importance < threshold: return
dv = normalize(activation(good_text) - activation(bad_text))
S_norm = normalize(context_state)
W += importance * eta * outer(dv, S_norm)
def micro_regularize(self):
W *= (1 - 1e-4)
def macro_regularize(self):
W = 0.95 * W + 0.05 * W_init
注入就是标准的前向钩子:
def hook_fn(module, input, output):
h = output[0]
max_perturb = 0.1 * h.norm(dim=-1, keepdim=True).mean()
effective = steering * min(1.0, max_perturb / steering.norm())
return h + effective
哪些确定,哪些还不确定
| 环节 | 状态 |
|---|---|
| 往 activation 加向量→改变输出分布 | ✅ 数学确定 |
| CAA 对比提取能得到语义方向 | ✅ 有文献(CAA 2024, RepE 2023) |
| W外积更新的长期稳定性 | ⚠️ 有理论约束但没实测 |
| 单次反馈的方向精度 | ⚠️ 单次嘈杂,靠多次叠加收敛 |
| 所有状态维度都线性可提取 | ⚠️ 常见维度有文献,特殊维度没验证 |
| 整体效果 | ⚠️ 没跑过定量评测 |
线性假设也不一定成立——MLP 替代 W 可能更有表达力,但正则化也更难做。
跟现有工作的关系
截至 2026 年初,导向向量领域的主流方向是:更好的离线提取方法(CAA 等)、动态强度调制(Adaptive ACT、AMPS 等)、安全性分析。共同点是向量方向固定,只有强度动态化。
2026年的 GSS 论文甚至在 future work 里写了"在线更新导向向量"——说明这个方向被认为有价值,但目前没有公开的实现。
我的方法是把方向本身也变成可学习的,用 Hebbian 外积建立情境→行为偏移的映射,配合双时标正则化防漂移。在我查到的文献里没见过完全相同的方案,如果有了解相关工作的读者,欢迎指正。
正在开发中的系统设计,代码已实现但还没做严格评估。欢迎交流。
声明:开发过程中使用了 AI 编程辅助工具。
相关工作
- Turner et al., Steering Llama 2 via Contrastive Activation Addition, ACL 2024
- Zou et al., Representation Engineering: A Top-Down Approach to AI Transparency, arXiv 2023
- Adaptive ACT: Adaptive Activation Steering for LLMs, WWW 2025
- AMPS: Adaptive Modality Preference Steering via Functional Entropy, ICLR 2026 submitted
- GSS: Gated Subspace Steering (memorization mitigation, 提及在线学习为 future work)
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)