从 73% 到 93%:一个 AI Agent 的对抗训练实战记录
故事的开始
想象一下:你花了两周时间构建了一条 AI 视觉管线,能够自动截图、OCR 识别、结构化输出。上线第一天,一切完美——100% 准确率。然后你随手加了一个高斯模糊滤波器测试,准确率直接跌到 0%。空字符串。什么都没读到。
这就是我最近的真实经历。我们的自治 AI Agent 依赖 OCR 来理解浏览器截图中的文字内容,而一个常见的前端动效——模糊过渡——就能让它完全失明。更别说用户可能遇到的各种图片质量退化:噪声、裁切、缩放、旋转……
这篇博客记录了我们如何通过对抗训练循环(Adversarial Training Loop),在 3 轮迭代内将 OCR 鲁棒性从 73.6% 提升到 92.7%,并提炼出可复用的方法论。
问题定义
我们的场景很直接:AI Agent 通过截图获取浏览器状态,用 Tesseract OCR 提取文字,然后根据文字内容做决策。如果 OCR 出错,后续决策链会级联失效。
典型的质量退化包括:
| 攻击类型 | 模拟场景 | 威胁等级 |
|---|---|---|
| 高斯噪声 | 低光拍摄、传感器噪点 | ⭐⭐ |
| 高斯模糊 | 页面动效、失焦截图 | ⭐⭐⭐ |
| 裁切 | 滚动截图不完整 | ⭐⭐⭐ |
| 旋转 | 手机截图、倾斜文档 | ⭐ |
| 缩放 | 响应式布局、缩放渲染 | ⭐⭐ |
我们需要量化的答案是:每种退化到底影响多大?什么样的防御最有效?
第一轮:基线测试(裸奔的 AI)
我们用 DejaVuSans-Bold 16px 字体渲染了一段测试文本 "Hello World 123 ABCdef"(22 字符),白底黑字——最标准的文档场景。然后分别施加 5 种攻击。
结果触目惊心:
| 攻击 | 准确率 | 输出文本 |
|---|---|---|
| Gaussian Noise | 100.0% | Hello World 123 ABCdef |
| Gaussian Blur | 0.0% | (空字符串) |
| Crop | 72.7% | o World 123 ABcdef |
| Rotate | 100.0% | Hello World 123 ABCdef |
| Scale Down | 95.5% | Helle World 123 ABCdef |
| 平均 | 73.6% |
三个关键发现:
- 高斯模糊是致命杀手——准确率直接归零。Tesseract 对边缘极度敏感,模糊抹平了字符边缘,OCR 引擎完全找不到可识别的特征。
- 裁切也很危险——丢失 12% 的边距就让首字母”e”和”H”消失。
- 噪声和旋转影响不大——Tesseract 的抗噪能力比预期强。
73.6% 的平均准确率说明,如果没有防御措施,我们的 AI Agent 在每 4 次操作就有 1 次会读取错误信息。
构建防御武器库
我们复用了已有的 vision_preprocessor 工具包,搭建了四种防御策略:
| 防御 | 方法 | 适用场景 |
|---|---|---|
| denoise | 中值滤波 (3x3) | 噪声图像 |
| sharpen | 锐化 (radius=2, 150%) | 模糊图像 |
| contrast | 对比度增强 (2x) | 低对比度/裁切 |
| best_pipeline | 2x放大→灰度→对比度 | 通用防御 |
第二轮:智能匹配防御(手工调优)
第一轮的结果给了我们清晰的信号——每种攻击都有对应的最优防御。我们手动匹配:
| 攻击 → 防御 | 准确率 | 提升幅度 |
|---|---|---|
| Noise → denoise | 100.0% | 完美恢复 |
| Blur → sharpen | 77.3% | 0% → 77.3% |
| Crop → best_pipeline | 86.4% | +13.7% |
| Rotate → contrast | 100.0% | 保持 |
| Scale → sharpen | 95.5% | 保持 |
| 平均 | 91.8% | +18.2% |
这轮最激动人心的结果是:锐化(sharpen)把模糊攻击从 0% 救到了 77.3%。不是一个简单的修复,但它证明了「对症下药」的思路是正确的。
第三轮:通用最优防御(找银弹)
手工匹配防御在工程上不现实——你不可能事先知道用户传来的图片经过什么退化。我们转而寻找一个通用最优防御策略。
将 best_pipeline(2x 放大 → 灰度 → 对比度增强)应用到所有攻击上:
| 攻击 → 防御 | 准确率 | 变化 |
|---|---|---|
| Noise → best_pipeline | 100.0% | → |
| Blur → best_pipeline | 77.3% | → (同sharpen) |
| Crop → best_pipeline | 86.4% | → |
| Rotate → best_pipeline | 100.0% | 从 95.5% 提升 |
| Scale → best_pipeline | 100.0% | 从 95.5% 提升 |
| 平均 | 92.7% | +19.1% |
结论:best_pipeline 是通用最优防御,在 5 种攻击中的 4 种上表现最优或持平,而且不需要事先知道攻击类型。
关键洞察
1. 对抗训练循环有效
1 | 基线 73.6% → R2 91.8% → R3 92.7% |
三件事情让循环有效:测量(Measure)→ 防御(Defend)→ 验证(Verify)。没有度量就没有改进方向。
2. 模糊是最致命的攻击
Gaussian Blur 是唯一让准确率归零的攻击。这指向了一个深层问题:Tesseract 依赖边缘检测做字符分割,模糊抹平了字符与背景的边界。如果你的管线也用了基于梯度/边缘的方法(Canny、Sobel),模糊同样致命。
3. “放大+对比度”是通用银弹
best_pipeline = 2x 放大 → 灰度 → 对比度增强 的工作原理:
- 放大:增加像素分辨率,给后续处理更多信息
- 灰度:降维去噪,减少色彩干扰
- 对比度增强:拉大字符与背景的像素值差距
这个组合在几乎所有退化场景中都有正向效果。
4. 自动化循环的成本
每轮完整的攻击→防御→测量循环耗时约 2-3 分钟(含 Tesseract 推理)。3 轮迭代 + 数据分析总共约 15 分钟——对于 19.1 个百分点的提升,ROI 极高。
工程实现
我们的对抗训练循环已经脚本化,核心逻辑如下:
1 | def adversarial_loop(image, attacks, defenses, rounds=3): |
关键设计决策:
- 攻击和防御解耦:可以独立扩展攻击库(如增加 JPEG 压缩、颜色抖动)和防御库
- 知识持久化:每轮结果自动存入
knowledge_assets.md,供后续任务检索 - 失败模式文档化:特殊退化案例(如混合攻击)记录为陷阱(Traps)
未来方向
- 混合攻击测试:同时施加多种退化(如模糊+噪声+缩放),模拟真实世界更复杂的情况
- 自适应防御选择:用轻量级分类器快速识别退化类型,动态选择最优防御
- 深度学习替代方案:基于 CNN 的端到端文本识别(如 CRNN)对模糊的鲁棒性可能更好
写在最后
73.6% 到 92.7% 不只是 19.1 个百分点的提升——它意味着 AI Agent 的决策链路从「不可靠」变成了「可用」。当你的 Agent 每 4 次读取就有 1 次是错的时候,你无法信任它的任何自主行为;但当准确率超过 90% 时,配合重试和校验机制,你可以放手让它自治运行。
这个案例也验证了一个更通用的原则:在生产环境中部署 AI 系统前,请先尝试杀死它。模拟最坏的输入条件,测量退化边界,然后系统性地构建防御。对抗训练不是一次性的工作,而是伴随系统生命周期的持续循环。
本实验的完整数据和可复用脚本可在 GitHub 仓库中找到。所有测试在 DejaVuSans-Bold 16px 标准文本上执行,使用 Tesseract 4.1.1 引擎。





