ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

WorkBuddy_新建任务与工作模式15_Plan模式下的信息补充策略

WorkBuddy_新建任务与工作模式15_Plan模式下的信息补充策略

Plan模式下的信息补充策略

摘要

在 AI 辅助编程工具(如 Cursor、Claude Code、Cline、Windsurf 等)中,Plan 模式(规划模式)允许模型在动手写代码之前先与你对齐需求、列出执行步骤。但在实际使用中,几乎每个人都会遇到同一个问题:模型会抛出一连串问题让你确认——“这个接口用 REST 还是 GraphQL?”“数据库用 PostgreSQL 还是 MySQL?”“要不要加缓存?”

面对这些提问,你只有两种选择:

  1. 逐项回答:认真回答每一个问题,让模型获得完整信息;
  2. 跳过让 AI 自行假设:不回答,直接让模型基于合理默认值继续。

这两种策略没有绝对的对错,关键在于判断哪些信息是"高杠杆"的——即哪些问题的答案会显著改变最终产物的结构,哪些只是无关痛痒的细节。本文将从工程实践角度,系统分析 Plan 模式下信息补充的策略、判断框架,并给出可落地的代码实现(一个自动分级问题、辅助决策的小工具),帮助你把"回答问题"这件事从被动应付变成主动控制。


引言:为什么"回答问题"本身是个技术问题

很多人把 Plan 模式下的问答当成走流程:模型问什么就答什么,或者干脆一路"你看着办"。但这两者都会带来隐性成本。

逐项回答的成本在于:

  • 注意力税:每个问题都需要你切换上下文、回忆项目细节、组织语言。20 个问题就是 20 次上下文切换,实际耗时远超想象。
  • 过度约束:有些问题一旦你给出具体答案,反而限制了模型的发挥空间。比如你随口说"用 Redis 做缓存",模型可能就放弃了更合适的本地 LRU 方案。
  • 伪精确陷阱:你可能并不真的确定答案(比如"到底该用哪种消息队列"),但为了回答问题而仓促决定,把不确定性固化进了方案。

跳过让 AI 自行假设的成本在于:

  • 假设漂移:模型的默认假设可能与你的真实约束冲突(比如它默认用 TypeScript,而你的团队全是 Python)。
  • 返工放大:Plan 阶段一个错误假设,到实现阶段可能演变成大面积重构。
  • 黑箱感:你不知道模型假设了什么,出了问题难以定位。

所以真正的策略不是二选一,而是建立一个分级判断框架:把模型的问题按"影响面"分类,高影响的问题认真回答,低影响的问题明确授权模型自行假设,并要求模型把假设显式列出来。这就是本文要展开的核心思想。


正文

一、先理解 Plan 模式的工作机制

要制定策略,先要理解 Plan 模式下模型为什么会提问。典型流程如下:

用户提出需求 │ ▼ ┌─────────────────┐ │ 需求解析阶段 │ ← 模型识别信息缺口 └─────────────────┘ │ ▼ ┌─────────────────┐ │ 澄清提问阶段 │ ← 抛出一批问题(本文焦点) └─────────────────┘ │ ▼ ┌─────────────────┐ │ 方案规划阶段 │ ← 基于已有信息 + 假设生成计划 └─────────────────┘ │ ▼ ┌─────────────────┐ │ 执行/实现阶段 │ └─────────────────┘

关键认知:模型在澄清阶段提出的问题,本质上是它在"信息缺口"和"继续推进"之间的权衡。一个训练良好的模型会把"它认为重要的缺口"抛给你。但模型并不知道你的组织约束、历史包袱、团队偏好——这些它只能靠问,或者靠猜。

因此,你的信息补充策略实际上是在替模型补全它无法从上下文推断的那部分知识。判断标准很清晰:

凡是模型无法从代码库、项目文件、历史对话中推断出来的信息,且对方案有实质影响,就值得回答;反之可以授权假设。

二、问题分级:哪些必须答,哪些可以跳过

实践中,模型的问题大致可以分为四类。建议按下面的矩阵处理:

问题类型典型例子影响面建议策略
约束类目标语言/框架、部署环境、性能红线、合规要求极高,决定方案骨架必须逐项回答
接口类API 风格、数据模型字段、鉴权方式高,影响模块边界尽量回答,可给方向而非细节
实现类用哪个库、要不要加缓存、日志格式中,可逆授权假设,要求列出
风格类变量命名、注释密度、目录结构低,随时可改直接跳过,让模型定

约束类问题是唯一"不能跳过"的。因为一旦假设错误,整个方案可能推倒重来。比如模型默认你要写一个 Web 服务,而你其实要写一个 CLI 工具——这个假设错了,后面全错。

接口类问题值得回答,但不必过度精确。例如模型问"用户表需要哪些字段",你不必列出全部 30 个字段,只需回答"核心是 id、email、created_at,其余你按常见实践补全并标注"。

实现类和风格类是最应该被"跳过"的。这类问题数量往往最多(模型喜欢问细节),但影响面最小。你回答它们纯粹是在消耗注意力。

一个实用的经验法则:如果一个问题的答案,在方案评审时你根本不会去看,那它就该被跳过。

三、逐项回答的正确姿势:结构化、最小充分

决定回答后,怎么答也有讲究。逐项回答不等于"每问必详答"。推荐三个原则:

1. 用结构化格式回答,而非散文。模型对结构化输入的理解更稳定,也方便它对齐。

2. 最小充分原则。只给"足以消除歧义"的信息,不主动扩展。你给的信息越多,模型的假设空间被压缩得越厉害,可能错过更优解。

3. 显式标注"硬约束"与"软偏好"。让模型知道哪些不能动、哪些可以商量。

下面是一个回答模板的示例(你可以直接复制到对话里):

## 硬约束(不可变更) - 语言:Python 3.11+ - 部署:单机 Docker,无 K8s - 数据库:必须用现有 PostgreSQL 14 实例 ## 软偏好(可协商,若你有更好理由可提出) - Web 框架倾向 FastAPI,但如果你认为 Flask 更合适可以说明 - 希望有基础单元测试 ## 授权假设(以下你不必再问,自行决定并在计划中列出) - 日志库、代码格式化工具、目录结构 - 缓存方案(若需要,自行选择并说明理由)

这个模板的价值在于:它一次性把"要答的"和"不用答的"都交代清楚,把多轮问答压缩成一轮,大幅降低交互成本。

四、跳过让 AI 假设的正确姿势:显式授权 + 假设清单

“跳过"绝不等于"不回复”。正确的跳过是显式授权模型自行假设,并要求它输出假设清单。这样做有三个好处:

  1. 模型知道可以继续推进,不会卡在等待;
  2. 你获得了"假设的可见性",出问题能快速定位;
  3. 假设清单本身成为方案评审的一部分。

一个标准的授权话术:

以下问题我不回答,请你基于合理默认值自行假设并继续规划。 要求: 1. 在计划开头单独列出"假设清单",每条注明假设内容和理由; 2. 对于影响较大的假设,标注 ⚠️ 并说明如果假设不成立需要改动哪些部分; 3. 优先选择主流、保守、易替换的方案。

这里的关键是要求模型标注"高影响假设"。这样即使你跳过了所有问题,也能一眼看到哪些假设值得回头确认。

下面给出一个可运行的 Python 小工具,用于自动对模型提出的问题做分级,辅助你决定哪些答、哪些跳过。它基于关键词规则打分,你可以按自己团队的习惯扩展规则。

""" plan_question_triage.py 对 Plan 模式下模型提出的问题做影响面分级,辅助决定"回答 or 跳过"。 用法: python plan_question_triage.py questions.txt 其中 questions.txt 每行一个问题。 """importreimportsysfromdataclassesimportdataclass,fieldfromtypingimportList@dataclassclassRule:"""一条分级规则:命中关键词则累加权重。"""name:strkeywords:List[str]weight:intcategory:str# 规则表:权重越高,越应该"逐项回答"RULES:List[Rule]=[Rule("约束-语言",["语言","python","java","go","typescript","版本"],5,"约束类"),Rule("约束-部署",["部署","docker","k8s","kubernetes","云","服务器","环境"],5,"约束类"),Rule("约束-数据",["数据库","postgres","mysql","mongo","存储","持久化"],5,"约束类"),Rule("约束-合规",["合规","隐私","加密","权限","审计","安全"],5,"约束类"),Rule("约束-性能",["性能","并发","延迟","qps","吞吐","内存"],4,"约束类"),Rule("接口-风格",["rest","graphql","grpc","接口","api","协议"],3,"接口类"),Rule("接口-模型",["字段","表结构","数据模型","schema","实体"],3,"接口类"),Rule("接口-鉴权",["鉴权","认证","token","oauth","登录"],3,"接口类"),Rule("实现-库",["库","依赖","框架","package","sdk"],2,"实现类"),Rule("实现-缓存",["缓存","redis","memcache"],2,"实现类"),Rule("实现-日志",["日志","log","监控","埋点"],1,"实现类"),Rule("风格-命名",["命名","目录","结构","注释","风格","格式"],1,"风格类"),]@dataclassclassTriageResult:question:strscore:int=0categories:List[str]=field(default_factory=list)matched:List[str]=field(default_factory=list)@propertydefadvice(self)->str:"""根据分数给出处理建议。"""ifself.score>=5:return"✅ 必须逐项回答(高影响,假设错误代价大)"ifself.score>=3:return"🟡 建议回答方向,细节可授权假设"ifself.score>=1:return"🔵 可跳过,要求模型列出假设"return"⚪ 无明确信号,默认跳过并授权假设"deftriage(question:str)->TriageResult:"""对单个问题分级。"""result=TriageResult(question=question)q_lower=question.lower()forruleinRULES:ifany(kw.lower()inq_lowerforkwinrule.keywords):result.score+=rule.weight result.matched.append(rule.name)ifrule.categorynotinresult.categories:result.categories.append(rule.category)returnresultdefmain(path:str)->None:withopen(path,"r",encoding="utf-8")asf:questions=[line.strip()forlineinfifline.strip()]results=[triage(q)forqinquestions]# 按分数降序排列,高影响问题优先处理results.sort(key=lambdar:r.score,reverse=True)print(f"{'分数':<6}{'建议':<40}问题")print("-"*100)forrinresults:print(f"{r.score:<6}{r.advice:<40}{r.question}")# 统计:有多少问题其实可以跳过skippable=sum(1forrinresultsifr.score<3)print("-"*100)print(f"共{len(results)}个问题,其中{skippable}个可跳过({skippable/len(results):.0%})")if__name__=="__main__":iflen(sys.argv)!=2:print("用法: python plan_question_triage.py questions.txt")sys.exit(1)main(sys.argv[1])

准备一个questions.txt:

这个项目用什么编程语言和版本? 数据库用 PostgreSQL 还是 MySQL? API 风格用 REST 还是 GraphQL? 用户表的字段需要包含哪些? 要不要加 Redis 缓存? 日志用什么库? 变量命名和目录结构有什么要求? 部署到 Docker 还是 K8s?

运行结果示例:

分数 建议 问题 ---------------------------------------------------------------------------------------------------- 10 ✅ 必须逐项回答(高影响,假设错误代价大) 数据库用 PostgreSQL 还是 MySQL? 10 ✅ 必须逐项回答(高影响,假设错误代价大) 部署到 Docker 还是 K8s? 5 ✅ 必须逐项回答(高影响,假设错误代价大) 这个项目用什么编程语言和版本? 6 🟡 建议回答方向,细节可授权假设 API 风格用 REST 还是 GraphQL? 6 🟡 建议回答方向,细节可授权假设 用户表的字段需要包含哪些? 2 🔵 可跳过,要求模型列出假设 要不要加 Redis 缓存? 1 🔵 可跳过,要求模型列出假设 日志用什么库? 2 🔵 可跳过,要求模型列出假设 变量命名和目录结构有什么要求? ---------------------------------------------------------------------------------------------------- 共 8 个问题,其中 3 个可跳过(38%)

这个工具的意义不在于"精确",而在于强迫你在回答前先分类。哪怕规则粗糙,它也能帮你把注意力从"挨个回答"转移到"哪些值得答"。你可以把规则表替换成自己团队的术语,甚至接入一次 LLM 调用做更智能的分级。

五、混合策略:一轮回答 + 一轮授权

在真实项目中,最优解往往是混合,而不是纯回答或纯跳过。推荐一个可复用的两轮交互模式:

第一轮:只回答约束类问题,其余全部授权假设。

关于你提出的问题: 【回答】语言用 Python 3.11;部署用 Docker;数据库用现有 PostgreSQL。 【授权假设】其余问题(API 风格、缓存、日志、命名等)请你自行假设, 在计划开头列出假设清单,高影响假设标 ⚠️。

第二轮:审视模型输出的假设清单,只纠偏高影响项。

模型返回类似:

## 假设清单 1. ⚠️ API 风格采用 REST(理由:主流、易调试) 2. 缓存暂不引入(理由:先跑通功能) 3. 日志使用 Python logging 标准库 4. 目录结构采用 src/ 布局

你只需针对第 1 条(标了 ⚠️)做确认或修正,其余默认接受。这样把交互轮次从 N 轮压缩到 2 轮。

这个模式之所以有效,是因为它把"回答问题"的成本从线性降到对数级:约束类问题通常只占 20% 左右,但决定了 80% 的方案骨架。抓住这 20%,剩下的交给模型假设 + 清单审计。

六、假设清单的验收:让假设变成可追踪的契约

最后一步常被忽略:假设清单不是看完就算,而应沉淀为方案的一部分。建议在计划文档里保留一节"假设与风险",并在实现阶段回查。

一个可落地的做法是把假设清单结构化为 JSON,方便后续做自动化校验(比如在 CI 里检查高风险假设是否已被确认):

{"plan_id":"feature-user-auth-001","assumptions":[{"id":"A1","content":"API 风格采用 REST","impact":"high","confirmed":false,"fallback":"若改为 GraphQL,需重写 controller 层与前端请求封装"},{"id":"A2","content":"暂不引入缓存层","impact":"low","confirmed":true,"fallback":"后续可在 service 层插入 cache 装饰器"}]}

配套一个简单的校验脚本,在进入实现阶段前检查是否还有未确认的高影响假设:

""" check_assumptions.py 在 Plan 转实现前,检查是否还有未确认的高影响假设。 """importjsonimportsysdefcheck(path:str)->bool:withopen(path,"r",encoding="utf-8")asf:plan=json.load(f)pending=[aforainplan.get("assumptions",[])ifa.get("impact")=="high"andnota.get("confirmed",False)]ifpending:print(f"⚠️ 存在{len(pending)}个未确认的高影响假设,建议先确认:")forainpending:print(f" - [{a['id']}]{a['content']}")print(f" 若不成立:{a.get('fallback','未说明')}")returnFalseprint("✅ 所有高影响假设均已确认,可以进入实现阶段。")returnTrueif__name__=="__main__":ok=check(sys.argv[1]iflen(sys.argv)>1else"plan.json")sys.exit(0ifokelse1)

把这一步纳入工作流后,"跳过让 AI 假设"就不再是放任,而是有审计、有兜底的授权。这才是跳过策略能安全落地的前提。


总结

Plan 模式下的信息补充,本质是一个注意力分配问题。本文的核心观点可以浓缩为以下几点:

  1. 不要二选一,要分级。把模型的问题分为约束类、接口类、实现类、风格类,只有约束类必须逐项回答
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进