苏格拉底式 AI Coding:一种新的编程协作范式
"我知道我一无所知" —— 苏格拉底
摘要
本文提出了一种全新的 AI 辅助编程范式:苏格拉底式 AI Coding 。不同于传统的"指令-执行"模式,这种方法通过模糊但引导性的提问 ,激发 AI 的深度推理能力,从而产生更高质量的代码。
经验观察表明:模糊的 prompt 往往比明确的指令产生更好的代码 。本文系统性地解释了这一现象,并提炼出可实践的方法论。
目录
- 理论基础:从哲学到编程
- 核心概念与术语
- 两种范式的深度对比
- 五大核心机制
- 实践原则
- 案例研究
- 深层洞察
- 最佳实践指南
理论基础:从哲学到编程
苏格拉底方法的本质
公元前 5 世纪,苏格拉底发明了一种独特的教学方法:不直接给出答案,而是通过提问引导学生自己发现真理 。
核心原理:
- ❌ 不说:"答案是 X"
- ✅ 而问:"如果是 Y,会怎样?那 Z 呢?"
- 🎯 目标:激发批判性思维,让学生主动推理 而非被动接受
迁移到 AI Coding
传统的 AI 编程协作模式:
人类:在第 42 行添加 if (x > 0) 检查
AI: 好的,已添加
这是指令-执行 模式,AI 是工具。
苏格拉底式 AI Coding:
人类:这里有个边界情况没处理,怎么办?
AI: 让我先理解代码逻辑...
发现了问题:x 可能为负数
参考了现有模式:其他地方都用了 validate_input
建议方案:添加统一的输入验证
这是问题-探索-设计 模式,AI 是合作者。
关键差异
| 维度 | 传统方法 | 苏格拉底方法 |
|---|---|---|
| 人类角色 | 设计者 | 提问者 |
| AI 角色 | 执行者 | 思考者 |
| 知识传递 | 显性告知 | 引导重建 |
| 输出质量 | 局部正确 | 全局最优 |
核心概念与术语
1. Socratic Prompting(苏格拉底式提问)
定义 :模糊但引导性的提示,给 AI 留出探索空间 (Exploratory Space)。
示例:
✅ "HTTP 请求失败了,curl 怎么记录?"
✅ "这个设计可能不太好,有更好的方案吗?"
✅ "日志显示这里有问题,但我不确定原因"
2. Instructive Prompting(指令式提问)
定义 :明确具体的命令,AI 只需执行。
示例:
"在第 42 行添加 try-except"
"把变量名从 foo 改成 bar"
"删除这个函数"
3. Pattern Discovery(模式发现)
定义 :AI 从代码库中主动识别和对齐架构模式。
示例:
python
# AI 发现现有模式:
FunctionCallStartEvent → 开始
FunctionCallCompleteEvent → 成功
FunctionCallErrorEvent → 失败 ✅
# 推断缺失模式:
StreamStartEvent → 开始
StreamCompleteEvent → 成功
StreamErrorEvent → 失败 ❌(需要补充)
4. Forced Understanding(强制理解)
定义 :模糊 prompt 迫使 AI 深度理解代码库,而非表面修改。
机制:
- 收到模糊问题
- 无法直接执行
- 必须先理解上下文
- 推理出解决方案
- 验证方案可行性
5. Trust Inversion(信任倒置)
定义 :从"人类设计 → AI 执行"转变为"AI 设计 → 人类评审"。
效果:
- AI 承担设计认知负荷
- 人类承担评审认知负荷
- AI 的设计能力被充分激活
两种范式的深度对比
执行流程对比
指令式 AI Coding
用户:在 X 位置添加 Y
↓
AI:定位文件
↓
AI:找到位置 X
↓
AI:插入代码 Y
↓
输出:代码已修改
特点:
- ✅ 快速、精确
- ❌ 局部视野
- ❌ 不理解"为什么"
- ❌ 可能执行错误方案
苏格拉底式 AI Coding
用户:X 有问题,怎么办?
↓
AI:理解问题域
↓
AI:搜索相关代码
↓
AI:识别现有模式
↓
AI:设计解决方案
↓
AI:完整实现(多文件)
↓
AI:验证(类型检查、测试)
↓
输出:经过架构思考的完整方案
特点:
- ✅ 深度理解
- ✅ 架构对齐
- ✅ 端到端完整
- ⚠️ 需要更多推理时间
质量维度对比
| 维度 | 指令式 | 苏格拉底式 |
|---|---|---|
| 语法正确性 | ✅ 高 | ✅ 高 |
| 架构一致性 | ⚠️ 低 | ✅ 高 |
| 完整性 | ⚠️ 片面 | ✅ 端到端 |
| 可维护性 | ⚠️ 低 | ✅ 高 |
| 测试覆盖 | ❌ 无 | ✅ 包含验证 |
| 模式对齐 | ❌ 不考虑 | ✅ 主动对齐 |
代码质量对比(真实案例)
场景 :HTTP 请求失败时需要记录 curl 命令用于调试
指令式方案
python
# 用户:"在 execute() 添加 yield StreamErrorEvent"
async def execute(self):
stream = await self.client.responses.create(...)
yield StreamStartEvent(...)
async for event in stream:
yield event
# ❌ 问题1: 没有 try-except
# ❌ 问题2: 失败时 StreamStartEvent 不会被 yield
# ❌ 问题3: curl 命令丢失
# ❌ 问题4: 没有添加 StreamErrorEvent 定义
# ❌ 问题5: 没有添加格式化逻辑
苏格拉底式方案
python
# 用户:"HTTP 失败了,curl 怎么记录?"
# AI 推理过程:
# 1. HTTP 失败时 curl 也要记录 → 需要在失败前获取
# 2. 查看现有事件系统 → 发现 FunctionCallErrorEvent
# 3. 识别模式:Start/Complete/Error 三态
# 4. 设计 StreamErrorEvent 对齐现有模式
# 5. yield + raise 保证事件记录和异常传播
# ✅ 完整方案:
# 1. 定义事件类型
class StreamErrorEvent(LLMEvent):
model: str
provider: str
error_type: str
error_message: str
curl_command: str | None
# 2. 修改 handler
async def execute(self):
curl_command = self.http_debug.last_curl_command
# 先 yield StreamStartEvent(确保 curl 被记录)
yield StreamStartEvent(curl=curl_command)
try:
stream = await self.client.responses.create(...)
async for event in stream:
yield event
except Exception as e:
# yield 错误事件(包含 curl)
yield StreamErrorEvent(
error_message=str(e),
curl_command=curl_command,
)
raise # 继续抛异常
# 3. 添加格式化逻辑
def _format_stream_error(self, event):
return f"""
❌ 请求失败: {event.error_type}
错误详情: {event.error_message}
cURL Command (可复制执行):
{event.curl_command}
"""
# 4. 写测试验证
async def test_stream_error_event():
events = []
try:
async for event in simulate_failed_request():
events.append(event)
except Exception:
pass
assert len(events) == 2
assert isinstance(events[0], StreamStartEvent)
assert isinstance(events[1], StreamErrorEvent)
结果对比:
- 指令式:1 个文件修改,5 个问题
- 苏格拉底式:4 个文件修改,完整方案,测试验证
五大核心机制
1. 避免过度约束陷阱(Constraint Avoidance)
问题 :明确指令可能基于错误的假设。
案例:
python
# ❌ 错误指令:"在 StreamStartEvent 添加 error 字段"
class StreamStartEvent:
model: str
error: str | None # 违反单一职责!
# ✅ 苏格拉底式:"HTTP 失败了,怎么记录?"
# AI 推理 → 发现应该创建独立的 StreamErrorEvent
原理 :模糊 prompt 给 AI 空间去发现更好的方案。
2. 强制深度理解(Forced Understanding)
机制 :模糊 prompt 无法直接执行,必须先理解代码库。
对比:
| 指令式 | 苏格拉底式 |
|---|---|
| "改第 42 行" | "这里有 bug,怎么修?" |
| → 定位行号 | → 理解代码逻辑 |
| → 修改代码 | → 识别问题根因 |
| → 完成 | → 查找相似模式 |
| → 设计完整方案 | |
| → 多文件协同修改 | |
| → 验证和测试 |
结果 :深度理解产生高质量代码。
3. 信任倒置(Trust Inversion)
传统模式:
人类:我已经想好了,你照做
AI: 好的(即使发现问题也不敢质疑)
苏格拉底模式:
人类:有个问题,你帮我想想?可能可以这样,但不确定
AI: 让我分析一下...发现了更好的方案
关键 :用户的"不确定"给了 AI 独立思考的许可。
4. 模式发现(Pattern Discovery)
能力 :从代码库中主动识别和对齐架构模式。
示例:
python
# AI 扫描代码库,发现模式:
# 模式 1: 三态事件流
FunctionCallStartEvent → FunctionCallCompleteEvent → FunctionCallErrorEvent
# 模式 2: 缺失的对称性
StreamStartEvent → StreamCompleteEvent → ??? (缺 ErrorEvent)
# 推理:补充 StreamErrorEvent 以对齐模式
价值 :保证新代码与现有架构一致。
5. 隐性知识传递(Implicit Knowledge Transfer)
问题 :明确指令中,用户的推理过程被丢失。
案例:
python
# 用户头脑中的推理链:
1. HTTP 失败时 curl 也要记录
2. try 失败后拿不到 curl
3. 所以要在 try 之前准备
4. StreamStartEvent 也要提前 yield
# ❌ 明确指令:"把 curl_command 移到 try 之前"
# → AI 只得到结论,不知道为什么
# ✅ 苏格拉底式:"HTTP 失败了,curl 怎么记录?"
# → AI 被迫重建推理链,获得深度理解
原理 :重建推理过程 > 被告知结论。
实践原则
原则 1:问题导向,而非方案导向
python
# ❌ 方案导向
"在 X 位置添加 Y"
# ✅ 问题导向
"X 有问题,怎么解决?"
"日志显示 X 失败了,怎么调试?"
原则 2:暴露不确定性
核心思想 :你的纠结和疑虑,恰恰是 AI 最需要的信息。
❌ 过度自信(假装确定):
"做 A,然后做 B,最后做 C"
✅ 暴露纠结(真实的思考过程):
"我在想是不是要重构这个继承体系...
拆成组合模式可能更清晰,但工作量很大...
要不要保留原有接口?新老并存可能更安全?
但维护两套代码又很难受...
你觉得怎么权衡比较好?"
为什么纠结反而更好?
- 暴露了多个备选方案(AI 可以评估)
- 展示了权衡维度(工作量 vs 架构清晰度)
- 提供了约束条件(需要向后兼容)
- 给了 AI 设计空间(而非强制执行)
作用 :你的纠结迫使 AI 进行多维度分析,而非盲目执行。
原则 3:提供上下文,而非指令
python
# ❌ 无上下文指令
"修改第 42 行"
# ✅ 丰富上下文
"日志显示第 42 行有 NullPointerException"
"用户反馈这个功能在边界情况下失败"
原则 4:鼓励探索和验证
python
# ❌ 强制执行
"照我说的做,不要问为什么"
# ✅ 鼓励质疑
"你觉得这样做有什么问题?"
"有没有更好的实现方式?"
原则 5:分层渐进
第一层:What(问题是什么)
"HTTP 请求失败了"
第二层:Why(为什么重要)
"需要调试,但拿不到 curl 命令"
第三层:How(可能的方向)
"是不是可以在失败时也 yield 一个 event?"
案例研究
案例:StreamErrorEvent 的诞生
背景
HTTP 请求失败时,curl 命令没有被记录,导致无法手动复现问题。
传统指令式方案(假设)
用户:"在 StreamStartEvent 添加 error 字段"
AI 执行:
python
class StreamStartEvent:
model: str
provider: str
error: str | None = None # ❌ 违反单一职责
问题:
- StreamStartEvent 既表示"开始"又表示"错误"
- 语义混乱
- 与 FunctionCallErrorEvent 模式不一致
- 难以在下游区分正常/失败
苏格拉底式方案(实际)
用户:"你看最新的 logs, 它 http 失败了。但我在想,失败的话,
是不是也可以搞一个 event? 比如 stream start event?
但是可能不太好?或者叫 stream error event?
是不是也可以把 curl 给 yield 出来?"
AI 推理过程:
理解问题域
- HTTP 请求失败
- curl 命令用于调试复现
- 当前 curl 没有被记录
代码探索
- 找到
prometheus_runner.py事件处理循环 - 发现
StreamStartEvent在 HTTP 成功后才 yield - 查看
events.py了解事件体系
- 找到
模式发现
python
# 发现现有模式:
FunctionCallStartEvent → Complete/Error ✅
# 发现不一致:
StreamStartEvent → Complete ❌ (缺 Error)
方案设计
- 创建独立的
StreamErrorEvent(对齐模式) - yield + raise 模式(确保事件记录和异常传播)
- 在 try 之前 yield StreamStartEvent(确保 curl 被记录)
- 创建独立的
完整实现
python
# 1. 定义事件
class StreamErrorEvent(LLMEvent):
error_type: str
error_message: str
curl_command: str | None
# 2. 修改 handler
async def execute(self):
curl = self.http_debug.last_curl_command
yield StreamStartEvent(curl=curl)
try:
stream = await create(...)
async for event in stream:
yield event
except Exception as e:
yield StreamErrorEvent(error=str(e), curl=curl)
raise
# 3. 添加格式化逻辑
def _format_stream_error(self, event):
return f"❌ 失败\n{event.error_message}\ncURL: {event.curl_command}"
# 4. 写测试
async def test_stream_error_event():
events = []
try:
async for e in simulate_failure():
events.append(e)
except:
pass
assert len(events) == 2 # Start + Error
结果对比
| 维度 | 指令式(假设) | 苏格拉底式(实际) |
|---|---|---|
| 修改文件数 | 1 | 4 |
| 架构一致性 | ❌ 违反单一职责 | ✅ 对齐现有模式 |
| 完整性 | ⚠️ 只改了事件定义 | ✅ 端到端实现 |
| 测试 | ❌ 无 | ✅ 包含验证 |
| 可维护性 | ❌ 低 | ✅ 高 |
关键洞察:
用户的 prompt 虽然模糊("是不是可以...?","但可能不太好?"),但包含了:
- 问题场景:"http 失败了"
- 核心需求:"curl 给 yield 出来"
- 候选方案:"stream error event?"
- 技术疑问:隐含的"yield 和 raise 能共存吗?"
AI 做的是:
- 验证 用户的直觉(StreamErrorEvent 是对的)
- 解决 用户的疑虑(yield + raise 是安全的)
- 补充 缺失的实现(格式化、测试、导出)
深层洞察
洞察 1:认知负荷的战略性转移
传统分工:
- 人类:承担设计认知负荷(想清楚怎么做)
- AI:承担执行认知负荷(精确编辑代码)
问题 :人类的设计能力有限,可能基于不完整的信息。
苏格拉底式分工:
- AI:承担设计认知负荷(理解代码库,识别模式,提出方案)
- 人类:承担评审认知负荷(判断方案是否符合需求)
优势 :AI 有完整的代码库视野,设计能力被严重低估。
洞察 2:搜索空间的维度差异
指令式:1 维搜索
用户指令 → 执行路径唯一 → 输出固定
苏格拉底式:N 维搜索
用户问题 → 可探索多个方案 → 选择最优解
↓
方案 A:修改 StreamStartEvent(评估:违反 SRP)
方案 B:新增 StreamErrorEvent(评估:对齐模式 ✅)
方案 C:用 try-finally(评估:无法传递错误)
结果 :更可能找到全局最优解。
洞察 3:知识表示的本质差异
指令式:显性知识传递
"把 X 改成 Y" → AI 知道 What(做什么)
苏格拉底式:隐性知识重建
"X 有问题" → AI 推理 Why(为什么) + How(怎么做)
深度理解来自重建过程,而非被告知。
这类似于:
- 告诉学生 "1+1=2"(显性)
- vs 让学生通过数苹果理解加法(重建)
洞察 4:失败模式的优雅降级
指令式失败:
- 执行错误(语法、逻辑)
- 难以调试(不知道为什么这样做)
- 级联失败(一个错误导致多处问题)
苏格拉底式失败:
- 理解偏差(误解需求)
- 容易发现(有推理过程可追溯)
- 局部失败(方案错了,重新推理即可)
关键 :苏格拉底式失败更透明,更容易纠正。
洞察 5:协作模型的范式转变
传统:人类设计 → AI 执行
角色:主人-工具
特点:人类承担所有智力工作
局限:受限于人类的认知能力
苏格拉底式:人类提问 → AI 设计 → 人类评审
角色:合作者
特点:AI 承担智力工作,人类把控方向
优势:发挥 AI 的架构设计能力
这是 AI 从"工具"到"合作者"的转变。
洞察 6:不确定性的价值
确定性指令:
"做 X" → AI 假设用户是对的 → 盲目执行
不确定性提问:
"X 可能有用?但不确定" → AI 知道需要验证 → 独立评估
关键发现 :用户暴露的不确定性,反而产生更确定的结果。
因为:
- 不确定性 → 鼓励 AI 质疑
- 质疑 → 深度分析
- 深度分析 → 发现问题和更优解
最佳实践指南
何时使用苏格拉底式?
✅ 推荐场景:
架构设计任务
"需要添加错误处理,怎么设计?" "这个模块应该怎么拆分?"问题诊断任务
"这个 bug 的根因是什么?" "为什么性能突然下降了?"模式对齐任务
"如何让这段代码符合现有架构?" "有没有类似的实现可以参考?"完整功能开发
"需要实现 X 功能,怎么做比较好?" "如何优雅地处理 Y 场景?"不确定最佳方案
"我想用 A 方案,但担心性能问题" "B 和 C 哪个更合适?"
何时使用指令式?
✅ 推荐场景:
简单机械修改
"把变量名从 foo 改成 bar" "删除第 42 行"格式化操作
"格式化这个文件" "修复这个拼写错误"已知确定方案
"添加这个 import 语句" "更新版本号到 2.0"
构造高质量苏格拉底式 Prompt 的技巧
技巧 1:提供问题,而非方案
python
# ❌ 差
"在 event_recorder.py 添加 case StreamErrorEvent"
# ✅ 好
"HTTP 失败时,错误信息怎么记录和展示?"
技巧 2:暴露约束和疑虑
python
# ❌ 差
"添加缓存"
# ✅ 好
"想添加缓存提升性能,但担心内存占用。有什么好的策略?"
技巧 3:提供上下文线索
python
# ❌ 差
"优化这个函数"
# ✅ 好
"日志显示这个函数耗时 2s,占了 80% 的请求时间。
profile 显示主要时间在数据库查询。怎么优化?"
技巧 4:使用渐进式细化
python
# 第一轮:大方向
"需要支持多语言,怎么设计?"
# 第二轮:具体化(基于 AI 的初步方案)
"i18n 方案不错,但配置文件放哪合适?"
# 第三轮:细节(基于进一步讨论)
"JSON 还是 YAML?如何支持动态加载?"
技巧 5:鼓励对比和权衡
python
# ❌ 差
"用 Redis 做缓存"
# ✅ 好
"缓存可以用 Redis 或本地内存。
Redis 支持分布式但增加依赖,
内存缓存简单但不能跨实例。
这个场景哪个更合适?"
Prompt 模板
模板 1:问题诊断
[观察到的现象]
[相关日志/错误信息]
[已经尝试的方案]
可能的原因是什么?怎么解决?
示例:
HTTP 请求在生产环境随机失败
错误日志:ConnectionResetError
已尝试:增加 timeout,问题依然存在
可能的原因是什么?怎么解决?
模板 2:架构设计
需求:[要实现的功能]
约束:[性能/兼容性/可维护性要求]
疑问:[不确定的点]
怎么设计比较好?
示例:
需求:支持流式 LLM 调用的错误处理
约束:需要记录调试信息,不能影响原有异常传播
疑问:错误时如何 yield event?会不会和 raise 冲突?
怎么设计比较好?
模板 3:模式对齐
发现:[观察到的情况]
问题:[与现有代码的不一致]
参考:[现有的类似实现]
如何对齐?
示例:
发现:新增的 StreamStartEvent 只有 start 和 complete
问题:FunctionCall 有 start/complete/error 三态
参考:FunctionCallErrorEvent 的实现
如何对齐?
常见反模式
反模式 1:伪苏格拉底式(Pseudo-Socratic)
python
# ❌ 看似在问,实则在命令
"你不觉得应该在这里加个 try-except 吗?"
# ✅ 真正的苏格拉底式
"这里可能会抛异常,怎么处理比较好?"
反模式 2:过度模糊(Over-Ambiguous)
python
# ❌ 太模糊,缺少上下文
"优化一下"
# ✅ 模糊但有方向
"这个函数在高并发下很慢,profile 显示大部分时间在等锁。
有什么优化思路?"
反模式 3:假设 AI 知道隐性背景(Hidden Context)
python
# ❌ 假设 AI 知道业务背景
"按之前讨论的方案实现"
# ✅ 重新提供上下文
"我们之前讨论过用事件驱动架构。
现在要实现错误处理,基于这个架构怎么做?"
反模式 4:过早优化指令(Premature Optimization)
python
# ❌ 基于错误假设的指令
"把这个列表改成 set,提升查询性能"
(可能列表需要保持顺序)
# ✅ 描述问题,让 AI 分析
"这个查询很慢,数据量是 10 万。怎么优化?"
总结
核心观点
模糊 prompt 往往产生更高质量的代码
- 因为它激活了 AI 的架构设计能力
- 而非机械的代码编辑能力
苏格拉底式 AI Coding 的本质是信任倒置
- 从"人类设计 → AI 执行"
- 到"AI 设计 → 人类评审"
五大核心机制
- 避免过度约束
- 强制深度理解
- 信任倒置
- 模式发现
- 隐性知识传递
最佳实践
- 问题导向,而非方案导向
- 暴露不确定性
- 提供上下文
- 鼓励探索
- 分层渐进
哲学反思
苏格拉底说:"我知道我一无所知"。
在 AI Coding 中,这句话的含义是:
当人类承认"我不确定最佳方案"时,反而能获得更好的代码。
因为:
- 承认不确定 → 给 AI 思考空间
- AI 思考 → 深度理解代码库
- 深度理解 → 发现更优方案
- 更优方案 → 高质量代码
这是一个悖论,也是一个洞察:
知道自己不知道,是获得知识的开始。
未来展望
苏格拉底式 AI Coding 不仅是一种技术方法,更是一种协作哲学 :
- AI 不是工具,而是思考伙伴
- 人类不是设计者,而是提问者和评审者
- 编程不是指令执行,而是对话和探索
这种范式的成熟,将重新定义人类与 AI 的关系:
从主人-工具,到合作者。
附录
参考文献
- Socratic Method - Stanford Encyclopedia of Philosophy
- The Art of Asking Questions - Elenchus and Maieutics
- Pattern Languages in Software Architecture - Christopher Alexander
- Prompt Engineering for Large Language Models - Recent Advances
相关资源
- Sequential Thinking MCP - 深度推理工具
- Architecture Decision Records - 记录设计推理的最佳实践
作者注
本文档基于真实项目经验提炼而成。
案例中的 StreamErrorEvent 设计,就是苏格拉底式 AI Coding 的实践成果。
欢迎在实践中验证和改进这些理论。
附录:经典纠结案例集
"纠结是思考的外在表现,而思考是高质量代码的前提。"
本章节收集了真实项目中那些特别纠结 但产生了特别好的结果 的 prompt 案例。
案例 1:命名的哲学纠结
用户的纠结:
"这个概念叫 workflow 还是 graph 比较好?
workflow 更贴近业务,用户容易理解...
但技术上确实是个有向无环图,叫 graph 更准确...
要不要改名?但改了影响面很大,API 都要变...
或者只改内部实现,对外保持 workflow?
但这样内外不一致,维护的人会很困惑...
你觉得怎么权衡?有没有两全其美的方案?"
AI 的推理过程:
- 分析两个术语的语义差异
- 评估影响范围(API、文档、用户心智模型)
- 查找业界先例(Airflow 用 DAG,Temporal 用 Workflow)
- 提出渐进式方案:
- 内部重命名为
GraphEngine(技术准确) - 对外保留
workflow术语(用户友好) - 在文档中说明两者关系
- 内部重命名为
为什么纠结产生了好方案?
- 暴露了多个评估维度(准确性、兼容性、可维护性)
- 展示了约束条件(API 稳定性)
- 允许 AI 寻找创造性的折衷方案
结果:
- ✅ 技术准确(内部用 Graph)
- ✅ 用户友好(外部用 Workflow)
- ✅ 向后兼容(API 不变)
案例 2:架构重构的痛苦抉择
用户的纠结:
"我发现这个继承体系有点复杂,子类太多了...
想拆成组合模式,可能更清晰一些...
但工作量很大,要改十几个文件...
要不要保留原有的基类?新老代码并存可能更安全?
但这样就有两套实现了,维护成本更高...
而且新人来了会很困惑:为什么有两种方式?
一刀切全部重构?风险又太大,万一出 bug...
渐进式迁移?但时间拖太长,技术债还是存在...
真的很纠结,你有什么建议?"
AI 的分析:
- 评估当前继承深度和复杂度
- 识别重构的核心收益(可测试性、扩展性)
- 分析风险点(回归测试覆盖率、关键路径)
- 提出分阶段方案:
- 阶段 1 :先添加组合版本(不删除继承)
- 阶段 2 :新功能用组合,旧代码不动
- 阶段 3 :增加测试覆盖率
- 阶段 4 :逐步迁移关键模块
- 阶段 5 :废弃旧基类(设置 deprecation 警告)
为什么纠结很有价值?
- 列举了所有方案的利弊(全部重构 vs 渐进式 vs 双轨制)
- 暴露了真实的约束(风险、时间、维护成本)
- 迫使 AI 设计一个平衡各方的方案
结果:
- ✅ 降低风险(渐进式)
- ✅ 控制债务(有明确的终态)
- ✅ 团队可接受(时间可控)
案例 3:Prompt 分层的设计纠结
用户的纠结:
"我在看 OpenAI 和 Claude 的 API,发现它们对 system prompt 的处理不一样...
想统一一下,但不知道怎么分层比较好...
一层?system_prompt + user_prompt?简单是简单,但不够灵活...
两层?但 Claude 有 cache,要利用缓存的话,可能需要三层?
L1: system (固定)
L2: context (半固定,可缓存)
L3: execution (变化,不缓存)
但三层会不会过度设计?我们真的需要这么复杂吗?
而且 OpenAI 支持吗?如果它不支持,怎么降级?
还是说先简单点,两层就够了,等真的遇到性能问题再说?
但那时候改起来成本更高...
你觉得应该怎么设计?"
AI 的推理:
- 对比 OpenAI 和 Claude 的缓存机制
- OpenAI:自动前缀缓存(>=1024 tokens)
- Claude:手动 cache_control 标记
- 分析三层架构的收益
- L1 固定 → 缓存命中率 100%
- L2 半固定 → 缓存命中率 ~80%
- L3 变化 → 不缓存,保持灵活性
- 评估实现成本
- OpenAI 自动缓存,三层和两层成本相同
- Claude 需要手动标记,但框架可以封装
- 提出方案:
- 采用三层架构(面向未来)
- 框架层统一处理(对上层透明)
- OpenAI 合并 L2+L3(自动降级)
为什么这种纠结特别好?
- 展示了技术选型的复杂性(多厂商差异)
- 暴露了权衡点(简单 vs 性能 vs 未来扩展)
- 包含了"害怕过度设计"的真实担忧
- 提出了"等遇到问题再说"的备选思路
结果:
- ✅ 采用三层架构
- ✅ 框架自动降级(OpenAI 合并 L2+L3)
- ✅ 实测缓存节省成本 40-60%
案例 4:错误处理的范式纠结
用户的纠结:
"这里的错误处理我有点纠结...
抛异常简单,但调用方要写一堆 try-catch,很烦...
返回 Result<T, E> 类型更优雅,Rust 就是这样做的...
但我们是 Python,Result 类型不是标准库的...
要用的话得自己实现或者引入第三方库...
而且改的话影响面很大,所有调用方都要改...
要不要两种都支持?可以向后兼容...
但这样代码库里就有两套风格了...
新人会很困惑:什么时候用异常,什么时候用 Result?
或者说,先不改?等 Python 3.14 出了 Result 类型再说?
但那要等到什么时候...
真的好纠结,你觉得呢?"
AI 的分析:
- 对比异常 vs Result 的优劣
- 异常:控制流清晰,但滥用会隐藏问题
- Result:强制错误处理,但调用繁琐
- 分析 Python 生态现状
- Returns 库提供 Result 类型
- 但不是标准,接受度有限
- 查看项目现状
- 已有 50+ 个异常抛出点
- 大部分错误是可恢复的
- 提出混合方案:
- 不可恢复错误 :继续用异常
- 可恢复错误 :返回
Optional[T]或tuple[T, Error | None] - 避免引入第三方 Result 类型(降低依赖)
为什么这个纠结很典型?
- 涉及语言哲学(Python 不是 Rust)
- 有现实约束(迁移成本、团队习惯)
- 包含"等官方支持"的逃避心理
- 担心引入两套标准
结果:
- ✅ 混合方案(异常 + Optional)
- ✅ 写了 ADR 文档说明决策理由
- ✅ 团队理解并接受
案例 5:性能优化的取舍纠结
用户的纠结:
"profile 显示这个函数很慢,占了 60% 的执行时间...
可以用缓存优化,但会增加内存占用...
或者用异步,但代码复杂度会上升...
还可以用 C 扩展,但维护成本太高...
问题是,现在也不算特别慢,500ms 左右...
优化到 100ms 有意义吗?用户能感知到差异吗?
而且这个功能调用频率不高,每天就几百次...
优化的收益可能不值得投入的时间...
但如果以后并发量上去了,可能就成瓶颈了...
要不要提前优化?还是等真的慢了再说?
遵循"不要过早优化"原则?
但那时候改起来成本更高...
你觉得怎么判断?"
AI 的分析:
- 量化收益
- 当前:500ms × 600次/天 = 5分钟/天
- 优化后:100ms × 600次/天 = 1分钟/天
- 节省:4分钟/天(可忽略)
- 评估未来增长
- 查看历史数据:调用量月均增长 20%
- 推算:6个月后达到 2000次/天(仍然不高)
- 识别真正问题
- 500ms 不是瓶颈,瓶颈是另一个 2s 的查询
- 提出方案:
- 暂不优化这个函数(ROI 低)
- 优化那个 2s 的查询(高优先级)
- 添加性能监控(及时发现真正瓶颈)
为什么这个纠结很好?
- 暴露了"过早优化"的担忧
- 包含了多种优化方案及其代价
- 提供了量化数据(500ms、600次/天)
- 表达了对未来的不确定性
结果:
- ✅ 优先级正确(先优化 2s 的查询)
- ✅ 节省了时间(没有做无用功)
- ✅ 建立了监控(数据驱动决策)
案例 6:类型安全的渐进式纠结
用户的纠结:
"想给这个模块加类型注解,提升类型安全...
但现在代码里 Any 类型很多,改起来工作量巨大...
而且有些地方确实不好定义类型,比如这个动态配置...
要不要用泛型?类型安全是好,但代码复杂度蹭蹭往上涨...
新人看到一堆 TypeVar、Generic 可能会懵...
还是保持 Any?简单是简单,但 mypy 检查不出问题...
运行时才发现错误,调试成本更高...
有没有中间方案?部分用泛型,部分用 Any?
但这样不一致啊...
渐进式迁移?先把核心模块改了,其他慢慢来?
但"慢慢来"往往就变成"永远不来"了...
你觉得应该怎么平衡类型安全和开发效率?"
AI 的分析:
- 评估类型安全的价值
- 核心数据结构:高价值(防止运行时错误)
- 工具函数:中等价值
- 测试代码:低价值
- 识别难点
- 动态配置确实难以精确类型化
- 可以用 TypedDict 或 Protocol 部分约束
- 提出分层策略:
- L1 核心 :严格类型(Pydantic Models)
- L2 业务 :渐进类型(关键路径优先)
- L3 工具 :宽松类型(使用
# type: ignore标注已知问题)
- 工具支持:
- 启用 mypy strict 模式(但允许例外)
- 用 pyright 的 reportUnknownVariableType 警告
为什么这个纠结很典型?
- 反映了"全有全无"心态(要么全改,要么不改)
- 担心不一致性(但现实中往往需要折衷)
- 害怕"永远做不完"(渐进式的常见心理障碍)
结果:
- ✅ 分层策略(核心严格,外围宽松)
- ✅ 3个月完成核心模块类型化
- ✅ 发现并修复了 5 个潜在 bug
案例 7:HTTP 失败的调试信息纠结(本文主案例)
用户的纠结:
"你看最新的 logs,它 http 失败了...
但我在想,失败的话,是不是也可以搞一个 event?
比如 stream start event? 但是可能不太好?
或者叫 stream error event?
是不是也可以把 curl 给 yield 出来?
但 yield 和 raise 能共存吗?会不会有问题?
如果 yield 了 error event,还要 raise 异常吗?
不 raise 的话,调用方怎么知道失败了?
raise 的话,event 会不会丢失?
或者只 yield 不 raise?但这样破坏了原有的错误处理...
真的有点晕...你帮我理一下思路?"
AI 的推理:
- 理解核心需求:记录 curl 用于调试
- 识别现有模式:FunctionCallErrorEvent 已存在
- 设计 StreamErrorEvent 对齐模式
- 验证 yield + raise 的安全性(Python 保证)
- 提出完整方案(见主案例)
为什么这个纠结产生了优秀设计?
- 暴露了多个技术疑问(yield + raise 能共存吗?)
- 展示了设计直觉("可能不太好")
- 包含了多个候选方案(stream start vs error event)
- 真实表达了困惑("有点晕")
结果:
- ✅ StreamErrorEvent 设计优雅
- ✅ yield + raise 模式安全
- ✅ curl 命令成功记录
- ✅ 成为苏格拉底式 AI Coding 的经典案例
纠结案例的共同模式
分析以上案例,我们发现高质量纠结的共同特征:
1. 多维度权衡
不是:A 还是 B?
而是:A 的优点是 X,但缺点是 Y;B 的优点是 Z,但缺点是 W。
在这个场景下,哪个更合适?
2. 暴露约束条件
不是:做 X
而是:想做 X,但受限于 Y(兼容性/性能/时间/团队水平)
3. 承认不确定性
不是:我觉得应该这样
而是:我觉得这样,但可能不太好?你觉得呢?
4. 展示思考过程
不是:给我方案
而是:我想到了 A、B、C 三个方案,A 的问题是...,B 的问题是...,
C 看起来还行但我担心...
5. 真实的情感表达
不是:(冷静的技术分析)
而是:真的很纠结...、有点晕...、很担心...、不知道...
纠结的艺术
关键洞察 :
**纠结不是软弱,而是深度思考的标志。**你的纠结程度,往往正比于问题的复杂度。
实践建议 :
- 不要假装确定 - 如果你不确定,就说不确定
- 列举所有方案 - 即使你觉得某些方案不可行
- 暴露你的担忧 - 这恰恰是 AI 需要分析的
- 说出你的困惑 - "有点晕"比"我确定"更有价值
- 展示权衡过程 - 这是设计的核心
元洞察 :
当你越纠结,AI 的输出往往越好。
因为:
- 纠结 = 深度思考
- 深度思考 = 暴露了复杂性
- 暴露复杂性 = 给了 AI 分析空间
- AI 分析 = 高质量方案
所以:不要害怕纠结,拥抱纠结。
"最好的代码,来自最好的问题。"
"最好的问题,往往来自最真实的纠结。"
