AI 辅助调试:喂对信息,让 AI 做排除法
核心论点:AI 调试不是"把报错贴进去就能修好"——幻觉修复比报错本身更危险。AI 的真正价值在于做系统化的排除法:穷举可能原因 → 逐条验证 → 定位根因。人负责判断"该信什么",AI 负责"不漏掉什么"。
一个每天都发生的场景
你盯着experiment_service.py的这段逻辑,前端实验配置刷新后有时不生效:
asyncdefrefresh_experiment_config(self,shop_id:str):cache_key=f"exp_cfg:{shop_id}"cached=awaitself.redis.get(cache_key)ifcached:returnjson.loads(cached)config=awaitself.db.fetch_config(shop_id)awaitself.redis.set(cache_key,json.dumps(config),ex=300)returnconfig本地测了 10 次,8 次正常,2 次拿到旧数据。没有报错——没有任何 traceback 可以贴给 AI。
这就是调试中最难的那一种:不是语法错了,是逻辑在某个你不知道的条件下不可靠。
不是"贴报错",而是"构造可复现的诊断实验"
反模式:给 AI 一个模糊场景
❌ "refresh_experiment_config 有时候返回旧数据,帮我看看哪里有问题" → AI 可能给你 5 种猜测,全是"一般做法"——Redis 连接池满了、序列化问题、时间窗口问题…… → 你不知道该信哪个,只能一个一个试正确做法:把"症状"翻译成"可验证的假设"
✅ 上下文: 1. 环境:FastAPI + redis (aioredis) + PostgreSQL 2. 症状:refresh_experiment_config 间歇性返回旧数据(~20% 概率) 3. 触发条件观察:高并发时才出现,单请求测试正常 4. 已排除的:日志显示 redis.get 返回的 key 存在且 ttl > 250s 请帮我做排除法: 第一步:列出这个函数中能导致"拿到旧数据"的所有可能原因 第二步:为每个原因设计一个验证实验(不用改代码,先做观察) 第三步:按概率从高到低排序AI 的输出会比模糊提问精确得多,因为:
- "间歇性 + 高并发"限制了搜索空间——不是序列化问题,是并发读写的时序问题
- "已排除:redis.get 返回值正常"避免了无意义的方向
- 要求"设计验证实验而非直接改代码"——控制风险
排除法框架:不是问"怎么修",而是问"怎么找到原因"
调试中最值钱的不是修复方案(AI 很擅长)——是定位到正确的根因(AI 需要你的引导)。
标准四步对话模板
Step 1: 画边界 "这是症状、这是环境、这是我已排除的、这是我怀疑的方向" Step 2: 穷举可能原因 "这个症状的可能原因有哪些?按大类列:代码逻辑 / 依赖组件 / 并发时序 / 数据问题" Step 3: 逐个排除 "针对原因 2(并发时序),我应该加哪些日志/断点来确认?" → AI 给一组诊断插桩 → 你跑一次 → 反馈结果 Step 4: 根因确认 + 修复 "确认是 redis.set 在 await 之后可能被并发请求覆盖。请给出修复方案,需要考虑:(a) 不引入分布式锁 (b) 保留 5 分钟缓存"这个框架的核心:每一步你都只做一件事,AI 的答案窄而深。
来自 Shop-Agent 的真实案例
permissions.py的check_tool_permission函数曾经有一个 bug:request-return工具在ROLE_TOOL_PERMISSIONS定义里被排除OPERATOR,但实际运行时OPERATOR也能执行退款。
给 AI 的正确喂法是:
症状:OPERATOR 角色能执行 request-return,权限配置已排除 环境:contextvars 存储 client 角色,中间件设置 → 路由层调用 check_tool_permission 我已查过:_MOCK_CLIENTS 中 OPERATOR 的 role 值正确 (Role.OPERATOR) 请做排除法: 可能原因 A — set_current_client 在请求中没被正确调用 → 用什么日志验证? 可能原因 B — check_tool_permission 的 frozenset 查找逻辑有问题 → 加什么断言? 可能原因 C — 工具注册时绕过了权限检查 → 在哪个调用点加日志?AI 输出三组验证实验,逐条排查后定位到:工具的注册入口在tool_registry.py里直接暴露了所有工具,没有调用get_client_accessible_tools做过滤。
识别"看起来对但实际错"的幻觉修复
这是 AI 调试最危险的陷阱。AI 给出的修复在语法上是对的,但逻辑上有致命缺陷。
三类典型幻觉
| 类型 | 特征 | 例子 |
|---|---|---|
| 缺少边界条件 | 修复了新问题,没覆盖旧路径 | if config: cache.set()→ 但config可能为{}(空 dict 也是 truthy) |
| 修了症状没修根因 | 绕过问题而非解决问题 | “加asyncio.sleep(0.1)避免竞争” → 真正的问题是缺少写屏障 |
| 引入不必要方案 | 用重型方案解决轻量问题 | “用 Redis 分布式锁解决并发写” → 你的并发量用asyncio.Lock就够了 |
防御策略:三个"追问"
拿到 AI 的修复方案后,三个追问:
Q1: "这个修复在什么情况下会失效?" → 让 AI 自己暴露边界条件 Q2: "如果不用你建议的依赖(如 redis-lock),纯代码层面有方案吗?" → 防止 AI 引入不必要的依赖 Q3: "这个修复和原逻辑的差异是什么?哪些调用方的行为会改变?" → 发现 API 兼容性问题实际操作中,Q1 是必问的——它揭穿了大量 AI 自己都没意识到的脆弱点。
什么时候放弃 AI,自己上?
不是所有 bug 都适合交给 AI。以下信号意味着你比 AI 更快:
| 信号 | 原因 | 行动 |
|---|---|---|
| AI 连续三轮给的修复方向都不同 | 它在猜,没有收敛 | 停止对话,你自己做一次二分法定位 |
| 涉及你项目特有的中间件黑盒行为 | AI 不知道你的 k8s configmap 刷新延迟是 30 秒 | 你查文档,别把时间浪费在给 AI 解释上 |
| 问题出在第三方库的 bug | AI 会当它是正确行为来分析 | 直接看 GitHub issues |
| 你已经有了一个很窄的怀疑范围 | 直接动手验证比写 prompt 快 | 加print()比跟 AI 聊天快 10 倍 |
一条铁律:AI 在调试中的最佳角色是"帮你穷举你没想过的因素"——而不是"替你做判断"。当你已经有了清晰假设,直接验证,不需要 AI。
核心要点
- 调试效率不由 AI 能力决定,由你喂的信息质量决定——模糊输入 = 随机猜测
- 排除法是 AI 调试唯一可靠的框架——穷举可能原因 → 逐条验证 → 定位根因
- 三个追问防幻觉:什么情况下失效?不用新依赖能做吗?哪些调用方受影响?
- 当你有了清晰假设,直接自己验证——花 5 分钟加日志比花 10 分钟给 AI 解释你的项目快
