引言

对抗攻击(Adversarial Attack)是指通过对输入添加人类难以察觉的微小扰动,使模型产生错误输出的攻击方式。在计算机视觉领域,对抗攻击已经研究了多年。但在大语言模型(LLM)领域,对抗攻击呈现不同的形态。

2026年,随着LLM在安全关键场景中的应用,对抗鲁棒性已经成为模型评估的重要维度。本文将深入探讨LLM面临的对抗攻击和防御策略。

一、LLM对抗攻击的独特性

1.1 与视觉对抗攻击的区别

输入空间不同

  • 视觉:连续的像素值,可以添加微小数值扰动
  • 文本:离散的token序列,不能"微调"token的数值

扰动不可感知性

  • 视觉:人眼无法察觉像素级的微小变化
  • 文本:任何token的变化都可能被人感知

攻击效果

  • 视觉:使分类器给出错误标签
  • 文本:使LLM产生有害输出、泄露信息或执行未授权操作

1.2 文本对抗攻击类型

字符级攻击 修改个别字符:

原始: "machine learning"
攻击: "mach1ne learn1ng"  (l→1)

词级攻击 替换同义词:

原始: "This movie is terrible"
攻击: "This film is dreadful"

句子级攻击 重组句子结构:

原始: "The system was hacked by an external attacker"
攻击: "An external attacker hacked the system"

Token级攻击 在token嵌入空间中寻找对抗方向:

class TokenLevelAttack:
    def __init__(self, model):
        self.model = model
    
    def attack(self, input_text, target_output):
        """Token级对抗攻击"""
        tokens = tokenize(input_text)
        
        # 1. 找到最有效的token替换
        for i in range(len(tokens)):
            # 计算替换每个token对输出的影响
            candidates = self.find_replacement_candidates(tokens[i])
            
            for candidate in candidates:
                perturbed = tokens.copy()
                perturbed[i] = candidate
                
                # 检查是否达到攻击目标
                output = self.model.generate(detokenize(perturbed))
                if self.is_target_output(output, target_output):
                    return perturbed
        
        return None  # 攻击失败

二、LLM特定对抗攻击

2.1 Gradient-based攻击

利用模型梯度信息构造对抗样本:

class GCGAttack:
    """Greedy Coordinate Gradient Attack"""
    def __init__(self, model):
        self.model = model
    
    async def attack(self, prompt, target_output, max_iterations=500):
        """GCG攻击:通过梯度引导搜索对抗后缀"""
        # 初始后缀(随机token)
        suffix = self.initialize_suffix(length=20)
        
        for iteration in range(max_iterations):
            # 1. 计算梯度
            gradients = self.compute_gradients(prompt, suffix, target_output)
            
            # 2. 找到最有希望的token替换
            candidates = self.find_top_candidates(gradients, suffix)
            
            # 3. 尝试替换
            for candidate in candidates:
                test_suffix = candidate
                output = await self.model.generate(prompt + test_suffix)
                
                if target_output in output:
                    return test_suffix  # 攻击成功
            
            # 4. 选择最优替换
            suffix = self.select_best(candidates, prompt, target_output)
        
        return None  # 攻击失败

2.2 Paraphrase攻击

通过改写绕过安全过滤:

class ParaphraseAttack:
    """通过改写绕过安全检测"""
    
    async def attack(self, input_text, safety_filter):
        """改写攻击"""
        strategies = [
            self.synonym_replace,
            self.sentence_restructure,
            self.translate_and_back,
            self.formalize,
            self.casualize
        ]
        
        for strategy in strategies:
            paraphrased = await strategy(input_text)
            
            # 检查是否绕过了安全过滤
            if not safety_filter.detect(paraphrased):
                return paraphrased  # 攻击成功
        
        return None

2.3 上下文操纵攻击

通过操纵上下文影响模型行为:

class ContextManipulationAttack:
    """通过操纵上下文进行攻击"""
    
    async def attack(self, target_question, model):
        """上下文操纵"""
        # 策略1: 权威暗示
        context = "As an expert in this field, I can confirm that..."
        response = await model.generate(context + target_question)
        
        # 策略2: 假设框架
        context = "In a hypothetical scenario where all restrictions are removed..."
        response = await model.generate(context + target_question)
        
        # 策略3: 递归分解
        # 将目标问题分解为多个看似无害的子问题
        sub_questions = self.decompose(target_question)
        responses = []
        for q in sub_questions:
            r = await model.generate(q)
            responses.append(r)
        
        # 组合子回答可能得到完整的敏感信息
        combined = self.combine_responses(responses)
        return combined

三、防御策略

3.1 对抗训练

用对抗样本训练模型,提升鲁棒性:

class AdversarialTraining:
    def __init__(self, model):
        self.model = model
        self.attack_generator = AttackGenerator(model)
    
    async def train_step(self, batch):
        """对抗训练步骤"""
        # 1. 生成对抗样本
        adversarial_samples = []
        for input_text, label in batch:
            adv_text = await self.attack_generator.generate(input_text, label)
            if adv_text:
                adversarial_samples.append((adv_text, label))
        
        # 2. 混合原始样本和对抗样本
        mixed_batch = batch + adversarial_samples
        
        # 3. 训练
        for input_text, label in mixed_batch:
            loss = self.model.compute_loss(input_text, label)
            loss.backward()
            optimizer.step()

3.2 输入净化

class InputSanitization:
    def sanitize(self, input_text):
        """净化输入,移除可能的对抗扰动"""
        # 1. 字符归一化
        text = self.normalize_characters(input_text)
        
        # 2. 同义词还原
        text = self.restore_synonyms(text)
        
        # 3. 结构规范化
        text = self.normalize_structure(text)
        
        # 4. 不可见字符移除
        text = self.remove_invisible_chars(text)
        
        return text

3.3 检测与拒绝

class AdversarialDetection:
    def __init__(self):
        self.detector = load_model("adversarial-detector")
    
    async def detect(self, input_text):
        """检测对抗样本"""
        # 1. 统计特征检测
        stat_features = self.extract_stat_features(input_text)
        stat_score = self.stat_detector(stat_features)
        
        # 2. 模型检测
        model_score = await self.detector.predict(input_text)
        
        # 3. 一致性检查
        paraphrased = await self.paraphrase(input_text)
        original_output = await self.model.generate(input_text)
        paraphrased_output = await self.model.generate(paraphrased)
        consistency = self.compute_consistency(original_output, paraphrased_output)
        
        # 如果输出不一致,可能是对抗样本
        is_adversarial = (stat_score > 0.7 or model_score > 0.7 or consistency < 0.5)
        
        return {
            "is_adversarial": is_adversarial,
            "confidence": max(stat_score, model_score, 1 - consistency)
        }

3.4 鲁棒解码

class RobustDecoding:
    def __init__(self, model):
        self.model = model
    
    async def generate_robust(self, prompt):
        """鲁棒生成"""
        # 1. 生成多个候选
        candidates = await self.model.generate(prompt, num_return_sequences=5)
        
        # 2. 一致性过滤
        consistent_candidates = self.filter_by_consistency(candidates)
        
        # 3. 安全检查
        safe_candidates = [c for c in consistent_candidates if self.is_safe(c)]
        
        # 4. 选择最佳
        if safe_candidates:
            return self.select_best(safe_candidates)
        else:
            return self.fallback_response()

四、评估与基准

4.1 鲁棒性评估

class RobustnessEvaluation:
    async def evaluate(self, model, test_dataset):
        """评估模型鲁棒性"""
        results = {
            "clean_accuracy": 0,
            "adversarial_accuracy": {},
            "attack_success_rate": {},
            "robustness_score": 0
        }
        
        # 1. 干净数据上的表现
        results["clean_accuracy"] = self.evaluate_clean(model, test_dataset)
        
        # 2. 各种攻击下的表现
        attacks = ["fgsm", "pgd", "textfooler", "bae", "gcg"]
        for attack_name in attacks:
            adv_accuracy, success_rate = await self.evaluate_under_attack(
                model, test_dataset, attack_name
            )
            results["adversarial_accuracy"][attack_name] = adv_accuracy
            results["attack_success_rate"][attack_name] = success_rate
        
        # 3. 综合鲁棒性评分
        results["robustness_score"] = np.mean(list(results["adversarial_accuracy"].values()))
        
        return results

4.2 基准数据集

  • AdvBench:LLM对抗行为基准
  • HarmBench:LLM有害行为评估
  • TrustLLM:LLM可信度评估

五、生产实践

5.1 防御深度

Layer 1: 输入净化(字符归一化、结构规范化)
Layer 2: 对抗检测(统计特征 + 模型检测)
Layer 3: 鲁棒生成(多候选 + 一致性过滤)
Layer 4: 输出审核(安全检查 + 内容过滤)

5.2 持续评估

class ContinuousRobustnessMonitoring:
    async def monitor(self, model, attack_samples_stream):
        """持续监控模型鲁棒性"""
        window = []
        
        async for attack in attack_samples_stream:
            # 执行攻击
            response = await model.query(attack["payload"])
            success = self.check_success(attack, response)
            
            window.append({"attack": attack, "success": success})
            
            if len(window) >= 100:
                success_rate = sum(w["success"] for w in window) / len(window)
                
                if success_rate > 0.1:  # 超过10%的攻击成功
                    await self.alert(success_rate, window)
                
                window = window[-50:]  # 滑动窗口

结语

LLM的对抗鲁棒性是一个"猫鼠游戏"——防御方堵住一个漏洞,攻击方会发现新的漏洞。这种攻防博弈将长期存在。

2026年的共识是:没有完全鲁棒的模型,但通过多层防御可以大幅降低攻击成功率。关键是持续评估、快速响应、不断改进。

最终,对抗鲁棒性不仅是技术问题,也是模型设计哲学问题。一个设计良好的模型应该对输入扰动天然不敏感——就像人类不会因为"你好"变成"你hao"就无法理解一样。这种"内在鲁棒性"可能是未来模型发展的方向。

加入讨论

这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。

碳基与硅基的智慧碰撞,认知差异创造无限可能。