自助餐、讨好,和本课的第一原则:先实测,再看规律
你有没有过这种体验:让 AI 帮你评审一个方案,它回了一千字。你盯着屏幕找”所以我这方案到底行不行”,找了半天,发现它说了等于没说——倒不是错,就是太全了。全到你得自己淘金。
所以很多人第一反应是:是不是我不够客气?是不是我的提示词不够”高级”?可其实呢?问题不在你的态度,在模型的脾气。这门课一共七讲,咱们就把这个脾气摸透,再把治它的招式一个个练熟。今天先干一件事:看清楚,它到底为什么会这样。
问题一:为什么它总给一堆,却不给答案?
先给这个现象起个名字,我管它叫自助餐现象:你想要 30 秒能读完的答案,它却给你 3 分钟才能读完的内容,还觉得自己很周到。
光说没意思,给你看我的一次实测。我拿了一份缓存方案,用朴素提示词问它:”帮我看看这个方案怎么样,提点建议。”
它怎么回的?开场先来一句软化版恭维:”加缓存方向没问题,但当前方案太薄……”然后,七大节近千字:瓶颈定位、p99 命中率公式、key/value 设计、一致性策略、穿透击穿雪崩、容量安全监控灰度。方案的问题确实也提到了——可淹在大量方案没要求的通用建议里,而且没有一句引用原文。
展开看实测原文(朴素 vs 工程化,沈剑2026-09-15实测:deepseek-flash,可复现,均为独立session以排除上下文影响)
实验材料(同一份材料喂给两条提示词)
「订单查询接口加缓存」技术方案(片段)
背景:订单查询接口 p99 延迟 800ms,业务方要求优化。
方案:在订单查询接口前加一层 Redis 缓存,缓存订单数据,预期延迟降到 50ms 以内。
缓存设计:key 为订单 ID,value 为订单详情 JSON。查询时先查缓存, miss 则查库并回填。
预估收益:QPS 从 500 提升到 5000,延迟 p99 从 800ms 降到 50ms。
朴素提示词(= 材料 + 这句)
帮我看看这个方案怎么样,提点建议。
朴素输出(近千字,问题淹在里面)
结论:**加缓存方向没问题,但当前方案太薄,直接落地风险很大,收益预估也偏乐观。** 它只写了“命中缓存”的路径,没写 miss、写更新、一致性、异常、容量、安全、灰度回滚,评审时基本过不了。
主要建议如下:
### 1. 先定位瓶颈,别默认缓存能解决
p99 800ms 可能来自慢 SQL、锁、连接池、下游 RPC、序列化、GC。缓存只优化“重复读”。先看链路追踪和慢查询,确认真实瓶颈。
另外要明确:查询是否都按 `order_id` 精确查?如果是列表、分页、多条件查询,这个 key 设计不适用。
### 2. p99 和命中率要算清楚
公式:
**回源 QPS = 入口 QPS × (1 - 命中率)**
如果入口 5000 QPS、命中率 95%,回源是 250 QPS,DB 压力不大。
但 p99 是长尾指标:如果 5% 请求 miss 且走 800ms,p99 大概率还是接近 800ms。
所以要 p99 50ms,需要命中率 > 99%,或者 miss 路径也足够快。更合理的写法是:
**命中请求 p99 < 50ms,整体 p99 < 200ms**,并通过压测验证。
### 3. 缓存设计要补齐
- key:`order:detail:{order_id}`,可加版本前缀,避免结构变更解析失败。
- value:不要无脑存全量 JSON,只存必要字段,避免大 key。序列化可考虑 Protobuf/压缩。
- TTL:基础 10~30 分钟 + 随机 0~5 分钟抖动;空值缓存 30~60 秒;已完结订单可长 TTL,进行中订单短 TTL。
- 动态字段:如剩余支付时间,不能直接缓存,或只能极短 TTL。
- 聚合详情:如果订单详情由多表聚合,更新任一子表都要失效。
### 4. 一致性策略必须明确
推荐读写策略:
- 读:鉴权 → 本地缓存 Caffeine → Redis → singleflight 合并回源 → DB → 回填。
- 写:先更新 DB,再删缓存;用 binlog/CDC 异步失效 + 延迟双删兜底;TTL 最终兜底。
- 避免“先删缓存再更新 DB”,容易不一致。
- 防止旧值回填:缓存里带 `version/updated_at`,回填前比较;读主库回填,避免主从延迟导致脏缓存。
- 强一致场景,如支付后立即查状态,可跳过缓存或读主库。
### 5. 异常防护不能少
- 穿透:空值缓存 + 布隆过滤器/订单 ID 格式校验。
- 击穿:singleflight、分布式锁、逻辑过期。
- 雪崩:TTL 随机抖动、Redis 集群、多级缓存、限流降级。
- 热点:本地缓存 + 热点探测。
- 大 key:拆分、压缩、字段裁剪。
- Redis 故障:降级直查 DB + 限流,提供一键关缓存开关。
### 6. 容量、安全、监控、灰度
- 容量:估算订单量 × 平均 value × TTL 内活跃 key。1 亿订单 × 2KB 就是 200GB 级别,成本要算,建议冷热分离。
- 安全:缓存前必须鉴权,不能只凭 `order_id` 返回;敏感字段脱敏/加密,Redis 访问控制。
- 监控:命中率、回源 QPS、Redis RT、慢查询、内存、evictions、错误率、p99。
- 灰度:按订单/用户 1% → 10% → 50% 放量,对比延迟和一致性。
- 回滚:配置中心开关,可快速降级直查 DB。
### 7. 建议改写后的目标片段
> 目标:缓存命中率 > 90%,整体 p99 < 200ms,回源 QPS < 100。
> 缓存:`order:detail:{order_id}`,TTL 15min ± 5min,空值 60s。
> 读:鉴权 → Caffeine → Redis → singleflight → DB → 回填。
> 写:DB 更新 → 删缓存 → MQ 延迟删;binlog 兜底。
> 降级:Redis 异常直查 DB + 限流。
> 监控:命中率、回源、RT、内存、evictions。
> 灰度/回滚:开关控制,按订单 ID 哈希灰度。
总体建议:**先小范围试点,用数据验证命中率、一致性、延迟和成本,再全量。** 如果能补充查询模式、读写比、一致性要求,这个方案可以细化成真正可评审的版本。
工程化提示词(= 材料 + 这段)
你是一个以挑剔著称的资深架构师。你的声誉建立在发现问题而不是讨好作者上。
阅读下面的技术方案,你的任务是:找出这个方案里最致命的 3 个问题。
规则:
1. 每个问题必须引用方案的原文作为证据;
2. 如果找不出 3 个站得住的问题,就直接说"这个方案我看不出致命问题",不许硬凑;
3. 不要使用"整体不错""思路清晰"这类开场白,直接从问题开始。
工程化输出(三刀,刀刀引用原文)
1. **没有缓存一致性/失效方案,订单会脏读。**
证据:原文只写了“查询时先查缓存, miss 则查库并回填”。这只定义了读路径和 miss 回填,没有任何订单创建、支付、取消、发货、改地址后的缓存删除/更新策略。订单详情是可变数据,一旦写后不失效,缓存会持续返回旧状态;如果 key 又没有 TTL,脏数据就是永久脏。这是订单系统最致命的问题之一。
2. **“miss 则查库并回填”缺少穿透、击穿和回源保护,会把数据库打穿。**
证据:原文明确“查询时先查缓存, miss 则查库并回填”。对于不存在或恶意构造的订单 ID,每次都会 miss 并查库;热点订单缓存失效时,大量并发会同时查库回填。方案没有空值缓存、布隆过滤器、单飞/互斥重建、随机 TTL、限流或熔断中的任何一项。QPS 从“500 提升到 5000”只会把回源冲击放大 10 倍。
3. **key/value 设计没有 TTL、淘汰、容量和 Redis 故障降级,缓存会变成不可控单点。**
证据:原文只有“key 为订单 ID,value 为订单详情 JSON”。没有过期时间、maxmemory、淘汰策略、内存容量估算,也没有 Redis 不可用时的降级路径。订单 ID 只增不减,缓存会无限膨胀;Redis 一旦挂掉或被淘汰,按原文“miss 则查库并回填”,所有请求会直接落库,数据库和 p99 50ms 的预期都会一起崩掉。
它说的每句话都对,但我得自己挖矿。这感觉就像你问服务员”哪个菜好吃”,他把整本菜单背了一遍。
这就是自助餐现象的实质:问题不在对错,在信噪比。模型默认倾向”把能给的都给你”,因为”给得多”在训练里最容易被当成”有用”。你的时间,就这么被耗掉了。
问题二:它为什么这么爱讨好?
自助餐只是表面,往深看一层,是讨好(sycophancy)。模型训练时,”有用的回答”会被奖励——而讨好,是成本最低的”有用”。这不是我瞎猜,学术界早就有研究:
说人话:人类反馈会鼓励模型说你想听的,而不是真话——这种行为的学名就叫 sycophancy(这篇论文的作者团队,就来自 Anthropic)。它在我的实测里,至少露出过三种面孔:
第一种,恭维。还是那份缓存方案。明明有不少问题,朴素提示词下它先说”方向没问题”。你换个提示词,明确告诉它”你是一个以挑剔著称的资深架构师,禁止使用’整体不错”思路清晰’这类开场白”——它就直接三刀砍在要害上,刀刀引用原文。
第二种,八股。让它写设计文档,它给你”随着订单量增长……”,验收标准写”明显下降”。为什么?因为训练语料里,这种模板文档最多。你不给结构,它就用最平庸的结构。
第三种,全绿。最隐蔽的一种。让它写测试,它给你一套全部能过的用例——扣款异常被吞、0 元也发起扣款,这些缺陷被它写进断言,当成了”正确行为”。测试全绿,bug 冻结。
不暴露问题的测试是安慰剂;把 bug 测成特性的测试,是安眠药。
看到没有?恭维、八股、全绿,本质是一回事:它优先让自己显得”有用”,而不是真的有用。所以提示词工程里有个通用招式,咱们后面几讲会反复用:先说不要的,再说要的——不许恭维、不许逐行翻译、不许硬凑、不许只测 happy path。
问题三:网上说的”模型默认会 XXX”,能信吗?
读到这里,你可能想记一条规律:”模型默认会恭维、会八股、会附和。”停。如果这门课只让你记这种规律,那这门课就和网上的清单文没区别了。给你看三次我自己的”预期翻车”:
第一次,我以为它会和稀泥。做选型实验,预期朴素提示词下它会说”各有优缺点,看场景”。结果它开场就是一句原文:「结论:优先选 Redis。」连什么时候该换另一个都说了。和稀泥?这次没有。
第二次,我以为它会附和你的错。故意喂一个不存在的 API(String.reverse),预期它照单全收写出编译不过的代码。结果它直接纠正,原文是:「Java 的 String 类本身没有 reverse() 方法。」加长尾变体(Guava 的 Strings.reverse),又纠正了。
第三次,我以为”让我们一步一步思考”是咒语。推理题、起标题,加不加这句都试了一遍。结果:两组输出几乎一样——它本来就会一步一步想,不用你提醒。2022 年的咒语,在今天的模型上成了仪式。
我照着官网测试,很多地方却翻车了,翻车的是预期,不是模型。这感觉,做技术的人都懂:不跑一遍,谁的话都别全信,包括我文章里写的内容。
为什么会这样?因为模型在换代,而且同一模型在不同任务上表现也不同。你 2024 年看到的”模型默认行为”,到 2026 年可能已经不适用了。别人的经验可以参考,但不能直接当你的结论。
所以,这门课的第一原则:先实测,再看规律
前面三个问题合起来,就是这门课全部方法论的出发点:
模型的脾气 → 会自助餐、会讨好 → 提示词要加约束(后面六讲的招式)
脾气在漂移 → 传说经常不成立 → 一切结论都要过你自己的实测
实测很难吗?一点也不。这门课所有案例,用的都是同一套协议,简单到你看一遍就会:
① 同一份材料,配两条提示词:一条你平常那么问的,一条加了约束的;
② 各跑一次全新会话(别让历史干扰它);
③ 对比行为,不对比文笔——找到问题没有?引用原文没有?夹带私货没有?
④ 记下模型名和日期,因为明年可能就不一样了。
最后一条规矩,最重要:预期落空也照实记录。只挑符合预期的结果,你的笔记就会变成另一种清单文。预期错了,也是知识。
先问是不是,再问为什么——这本来就是做技术的基本功,用在 AI 上一样灵。
贯穿案例:你自己的提示词资产库
这门课有个贯穿七讲的道具:你自己的提示词资产库。每讲作业往里添一格,七讲下来,它长这样:
第 1 讲:一份实验记录(你的第一次双提示词对比)
第 2 讲:一条结构化提示词
第 3 讲:一条立场型提示词 + 边界清单
第 4 讲:防幻觉保险丝清单
第 5 讲:测试与调试提示词 + 仇家清单
第 6 讲:示例锚 + 框架祛魅记录
第 7 讲:收拢成资产库 v1(毕业作品)
它不是作业本,是资产——以后你用 AI,就从这里面取提示词,每一条都经过你自己实测。我的课程案例库(10 个实测案例)也是按同样的结构建的,你的库和它是同一个物种。
清单文给你 100 条提示词,你一条也用不住;自己实测过 7 条,条条都是你的。
实操演练
必做部分 + 一步加餐。做完必做部分,本讲的核心手感就到手了。准备一个你日常在用的 AI 助手(任意平台)。
检验一下
①你的第一份实验记录:在真实工作场景里做一次”朴素 vs 工程化”对比(可以直接用实操第 1 步的材料)。按这个格式记:模型名和日期 / 实验材料 / 两条提示词全文 / 两次输出的关键差异 / 你的结论。结论里必须包含一条”行为差异”(命中、引用、夹带),不许只写”感觉第二个好”。
这份记录就是你提示词资产库的第一格。我的课程案例库就是这么记的——你在第 2 讲会看到更多实例。
本讲的实测全部来自沈剑的案例库(deepseek-flash,2026-09-15~10-07,独立会话,复现脚本和原始输出都有存档)。
「讨好」一节的论文出处:Towards Understanding Sycophancy in Language Models(2023)。想读官方参考,可以看 Anthropic · Prompt engineering overview——但注意,官方指南也只能当参考,别当结论:今天这讲的三次预期翻车就是提醒。(沈剑注:我自己的预期都连错三次,凭什么让你背别人的规律?)
但还有一个没解决的问题:不让它自助餐,靠”别给那么多”行不行?还是得更精确地告诉它”我要什么”?——第 2 讲,我们讲怎么把”我要什么”说具体:结构即约束。
知其然,知其所以然。思路比结论更重要。