一个灵感:当解题遇到对抗

去年我在研究 GAN(生成对抗网络)的时候,突然冒出一个想法:

GAN 里生成器和判别器互相博弈,不断进化。那 AI 写代码是不是也能这样?

传统的 AI 编程工作流很线性:提需求 → AI 写代码 → 你挑毛病 → AI 再改。但这里有个问题——你什么时候才算挑完了?没有判断标准,改到觉得”差不多”就停了。

但如果把”挑毛病”也交给 AI 呢?而且不只一个 AI,是多个不同视角的 AI 一起挑。

这就是 对抗式解题法 的起点。

核心思想:三个角色一台戏

对抗式解题法把一次编程任务拆成三个角色:

  • 解题者 (Solver) — 负责写代码/方案,被挑战后迭代优化
  • 判别者 (Discriminators) — 从不同角度挑毛病,每位判别者专注一个领域,共 6 位:
    • 🏛️ 架构判别者 — 模块划分、数据流、接口设计、可扩展性
    • ⚙️ 功能判别者 — 逻辑正确性、边界条件、异常处理、功能完整性
    • 🛡️ 安全判别者 — 输入校验、SSL/TLS、注入风险、敏感信息泄露
    • 性能判别者 — 时间复杂度、资源使用、缓存策略、异步优化
    • 📋 合规判别者 — 编码规范、许可证、行业标准、可访问性
    • 🎨 风格判别者 — 命名一致性、代码风格、文档质量、可读性
  • 打分体系 (P0-P4) — 问题分 5 个等级,收敛了才算完

四阶段流水线

不是所有任务都需要从头开始。对抗式解题法把过程分成四个阶段,按需切入:

Phase 1 — 架构评审

适合复杂项目。解题者先出 2-3 个候选方案,架构判别器和安全判别器评审。重点看:模块划分合理吗?数据流清晰吗?接口设计行不行?

Phase 2 — 原型实现

动手写代码。功能判别器、安全判别器、性能判别器一起上阵。核心逻辑先跑通,不那么重要的事先放一放。

Phase 3 — 健壮性加固

全部 6 个判别器(架构+功能+安全+性能+合规+风格)同时工作。错误处理、边界条件、并发问题、安全漏洞——专门找那些容易忽略的死角。

Phase 4 — 打磨优化

性能、命名、文档、代码风格。到这轮基本没有大问题了,就是让代码更漂亮。

打分收敛:怎么才算”做好了”?

这是对抗式解题法最核心的设计。每个问题按严重程度打分:

等级 分值 含义
P0 100 分 致命问题,不修没法用
P1 50 分 重要缺陷,影响使用
P2 20 分 一般问题,建议修复
P3 10 分 小瑕疵,有空再修
P4 5 分 纯风格/偏好,改不改都行

收敛条件:总加权分 < 20 且连续两轮没有 P0 问题

举个例子:

  • 第一轮:2 个 P2(40分)+ 3 个 P3(30分)+ 1 个 P4(5分)= 75 分 → 未收敛
  • 第二轮:1 个 P2(20分)+ 1 个 P3(10分)= 30 分 → 未收敛
  • 第三轮:1 个 P3(10分)+ 1 个 P4(5分)= 15 分 + 连续无 P0 → ✅ 收敛

够清晰,也够无情的。

具体怎么用?

在聊天里直接说

1
2
3
4
/solve 设计一个分布式定时任务调度器
/adv 写一个图片压缩工具
/review 这段代码有什么问题
/hardening 这个API做健壮性加固

看到 /solve/adv,我就会自动读 SOP,进入对抗式解题模式。

终端里跑

1
./adversarial init "设计一个支持自动重试的HTTP客户端"

实际跑一轮看看

假设用对抗式解题法写一个 带超时的 HTTP 客户端

Round 1 — 解题者提交方案

1
2
3
4
import requests

def fetch(url, timeout=10):
return requests.get(url, timeout=timeout)

架构判别者:P2 — 没有异常处理,网络请求可能静默失败
安全判别者:P1 — 没有 SSL 验证控制,不支持代理
功能判别者:P2 — 不支持异步,不支持自定义请求头

总分:20+50+20 = 90 分,未收敛。

Round 2 — 解题者修改后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import requests
from typing import Optional

def fetch(url: str, timeout: int = 10, headers: Optional[dict] = None,
proxies: Optional[dict] = None, verify_ssl: bool = True) -> dict:
try:
resp = requests.get(url, timeout=timeout, headers=headers,
proxies=proxies, verify=verify_ssl)
resp.raise_for_status()
return {"status": resp.status_code, "data": resp.json()}
except requests.Timeout:
return {"status": 408, "error": "请求超时"}
except requests.RequestException as e:
return {"status": 502, "error": str(e)}

安全判别者:P3 — resp.json() 如果返回非 JSON 会抛异常
风格判别者:P4 — 建议把重试逻辑单独抽个装饰器

总分:10+5 = 15 分,连续无 P0 → ✅ 收敛

两轮就搞定了。

为什么这方法有效?

  1. 多视角评审 — 一个判别者可能漏,但 4-6 个不同角度的判别者一起上,覆盖率大幅提升
  2. 量化标准 — P0-P4 打分让”做完了”有明确的定义,不是感觉说了算
  3. 渐进式迭代 — 先修致命的,再修重要的,小问题可以放一放
  4. 信息隔离 — 每个判别者只看方案,不看其他判别者的评论,避免相互影响
  5. 存档即学习 — 每轮结果自动存档,可以复盘哪些问题反复出现

适合什么场景?

任务类型 推荐配置
小型脚本/工具 直接从 Phase 2 开始,跳过架构
大型系统设计 四阶段全流程
代码审查/重构 只用判别者模式,跳过解题
Bug 修复 从 Phase 3 开始
新手上路 先试 /solve 一个简单的工具函数

最后

对抗式解题法不是什么神秘的技术,它只是把”被代码 review 支配的恐惧”变成了一个系统化的流程。区别在于——现在吹毛求疵的不是你同事,而是 AI,而且它还挺有礼貌的。

P.S. 这篇文章就是用对抗式解题法写的。第一轮架构判别者说:”叙事结构有点乱,建议从灵感起源讲起。”改了之后第二轮:”节奏好多了,直接发吧。”👍

如何把它变成你自己的SOP?

看到这里,你可能想在自己的 AI Agent 上实现这套方法。好消息是——它不依赖任何特定平台,你只需要写一份清晰的 SOP 文档,然后告诉你的 AI “按这个 SOP 来”。

下面是一个通用模板,任何 AI 都能理解。

第一步:定义你的判别者阵容

不需要一步到位配齐 6 个,从 2-3 个开始就够了:

1
2
3
4
5
6
判别者配置:
- 架构判别者:检查设计方案是否合理,模块划分是否清晰
- 功能判别者:检查逻辑是否正确,边界情况是否处理
- 安全判别者:检查有无明显安全漏洞

等流程跑顺了,再逐步加性能、合规、风格判别者。

第二步:写一份 SOP 文档

把这几个要点写进文档,它就是一份可执行的 SOP 了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 对抗式解题法 SOP

## 角色
- 解题者(Solver):负责生成方案/代码,根据反馈迭代
- 判别者(Discriminators):每人一个视角,独立评审

## 工作流程
1. 解题者提交方案
2. 每位判别者独立评审,给出 P0-P4 评分
3. 解题者汇总反馈,优先修复 P0/P1 问题
4. 进入下一轮,直到收敛

## 评分标准
- P0(100分):致命问题,不修不能用
- P1(50分):重要缺陷,影响使用
- P2(20分):一般问题,建议修复
- P3(10分):小瑕疵
- P4(5分):风格偏好

## 收敛条件
总加权分 < 20 且连续两轮无 P0

这就是全部了。发给你的 AI,它就能开始跑。

第三步:或者写个 100 行的小引擎

如果你想要更自动化的体验,可以用几十行代码把循环逻辑串起来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 伪代码——你可以用任何语言实现
def adversarial_solve(task):
solver = Solver()
discriminators = [ArchJudge(), FuncJudge(), SecJudge()]

for round in range(MAX_ROUNDS):
solution = solver.produce(task)
total_score = 0

for judge in discriminators:
issues = judge.review(solution)
total_score += sum(i.score for i in issues)

if total_score < 20 and no_p0(issues):
return solution # ✅ 收敛

solver.feedback(issues) # 迭代改进

return solution # 达到最大轮次,返回当前最优

核心逻辑就这么几行。把每个判别者做成一个独立的 prompt 模板,剩下的就是循环调用。

第四步:融入你的工作流

不同场景可以灵活切入:

  • 写代码 → 让解题者直接写,判别者逐一审查
  • 审代码 → 跳过解题者,只用判别者模式
  • 改 Bug → 从第三阶段(健壮性加固)开始,跳过架构和原型
  • 设计方案 → 只用架构判别者和安全判别者,不需要代码级别审查

关键在于——不需要一次性上全部功能。先跑通一轮,再逐步加严。


对抗式解题法真正有价值的地方,不是那个具体的实现,而是**”用多视角量化评审驱动迭代”**这个思路。它把”好不好”这种主观判断,变成了一个可衡量、可收敛的过程。无论你用的是什么工具、什么平台,这个思路都能落地。