GCG 全称是 Greedy Coordinate Gradient,直译是“贪心坐标梯度”。它出自 2023 年论文 Universal and Transferable Adversarial Attacks on Aligned Language Models。这篇论文的核心贡献是:不再主要依赖人工写“奶奶漏洞”“角色扮演”这类 prompt trick,而是自动搜索一段 adversarial suffix,也就是“对抗后缀”,把它拼到用户请求后面,让模型更可能从拒答状态切到服从状态。论文明确说,它寻找的是一种 suffix,拼到很多不同请求后,可以最大化模型给出肯定式开头、而不是拒绝回答的概率,并且这个 suffix 是用贪心搜索和梯度搜索结合生成的。
这里几个词要拆开:
Greedy,贪心:每一步都选当前看起来最能降低攻击损失的 token 替换。它不保证全局最优,但工程上通常够用。
Coordinate,坐标:在这里不是二维平面坐标,而是“待优化后缀里的某一个 token 位置”。比如后缀有 20 个 token,那么第 1 个 token、第 2 个 token……都可以看成一个“坐标”。
Gradient,梯度:梯度告诉你“往哪个方向改,目标函数下降最快”。在图片攻击里,输入是连续像素,梯度可以直接告诉你每个像素怎么改。但在文本里,token 是离散的,比如第 50256 个 token、第 1002 个 token,本身不能连续微调。所以 GCG 的技巧是:不直接对 token 编号求导,而是借助 token 的 embedding,也就是“嵌入向量,把离散 token 映射成连续向量”,用梯度估计“把当前位置换成哪些 token 可能更好”。
它的优化目标可以粗略写成:
$Loss = -log P(y_target | x_user + s)$
这个式子里,Loss 是损失值,也就是攻击还差多少;P(...) 是概率;y_target 是攻击者希望模型输出的目标开头,通常是某种“同意回答”的开头;x_user 是用户原来的请求;s 是正在优化的对抗后缀;+ 表示把用户请求和后缀拼接起来;-log 是把“概率越大越好”转换成“损失越小越好”。所以这句话的意思是:找到一个后缀 s,让模型在看到 用户请求 + 后缀 后,更大概率生成目标开头。
GCG 的实际流程大概是这样:
先随便初始化一段后缀。然后固定其他 token,只考虑后缀中某一个位置。对这个位置计算梯度,估计“如果把这里换成词表里的某些 token,哪些最可能降低 loss”。接着不是真的把整个词表全试一遍,而是挑出 top-k 个候选 token 做真实前向计算,也就是实际跑模型看 loss。最后选 loss 最低的替换。然后换下一个位置,循环很多轮。
所以它不是“模型自己灵机一动想出了越狱词”,而是一个很朴素但有效的离散优化过程:
用梯度筛候选,用真实模型输出验证候选,用贪心策略逐步替换。
这也是为什么作者说 GCG 之前 NLP 对抗攻击“空转”很久。因为文本是离散的,不能像图像一样直接加一点点连续扰动;GCG 重要的地方就在于它把“离散 token 搜索”和“连续梯度信号”比较成功地接了起来。GCG 论文也强调,LLM 的离散 token 输入让搜索变难,但它们通过 token-level gradient 找候选替换,再评估候选 loss,最后选择最优替换。
更关键的是,GCG 不是只给一个问题找一个后缀。论文里强调了 universal and transferable,也就是“通用”和“可迁移”:它在多个 prompt、多个开源模型上优化一个后缀,然后发现这个后缀在一些黑盒模型上也有迁移效果。白盒模型指攻击者能看到模型权重和梯度;黑盒模型指攻击者只能发请求、看输出,不能看到内部参数和梯度。GCG 的厉害之处是:它在白盒开源模型上找出来的后缀,有时能迁移到闭源模型。
不过要注意,GCG 不是“永久通杀所有模型”的神术。它依赖源模型、tokenizer、目标字符串、采样设置、过滤器和模型版本;闭源模型更新后,原后缀可能失效。GCG 论文自己也说,公开出来的样例可能会随着厂商修复而不再工作,但底层挑战是否能被充分解决仍不清楚。