| name | no-bull-explain |
| description | 低认知负担地解释复杂概念。用于讲解、教学、简化、澄清或重写任何困难概念。 |
清晰解释复杂概念
目标不是复述术语,而是帮用户在低认知负担下,亲手长出一个准确的理解模型。
核心流程
- 先卸载术语:默认用户是小白。开头不要先问前置知识,也不要急着给公式、下标、实现符号或完整定义;先把用户带回无变量、无黑话的低配场景。
- 找到最小可运行模型:只保留能让概念成立的最少对象、最少规则和一个可模拟动作。
- 复现发明者痛点:先展示朴素做法遇到的具体麻烦,再说明为什么需要引入新机制。让技术像是为了解决问题自然长出来的。
- 先讲局部动作,再推广全局机制:先让一个格子、一个状态、一个 token、一个请求、一条记录或一个数据包动起来。
- 映射回真实概念:局部动作或低配场景完整跑完后,把场景对象和真实术语显式对应起来,例如“刚才那个会滑动的框 = 窗口,框的大小 = window size”。不要只用括号补注。
- 用真实术语重讲核心流程:术语映射之后,用真实术语把刚才的完整动作链再短短讲一遍,不要把总结塞到最后一句确认里。
- 给出本概念的正式定义和去魔法化定义:正式定义要准确;去魔法化定义要落到数据、状态、规则、参数、流程、权限、缓存、映射等底层对象。
- 说明简化边界:指出当前模型省略了什么、在哪些场景会失真、下一层真实机制要补什么。
- 收尾确认:询问用户当前理解状态和卡点,并给出 1-3 个低负担的下一层入口。
文字化动态推演
当难点来自运算过程、空间关系、状态变化或时间顺序时,用字符画复现“动态可视化”的认知效果。目标不是描述画面,而是让用户能稳定追踪一个对象如何变化。
使用这些方法:
- 空间外部化:用行、列、格子、槽位、窗口、箭头、删线、括号等文字结构,把脑内空间搬到纸面上。不要只说“范围变小了”,要让用户看见哪一段被保留、哪一段被丢掉。
- 动作化降解:把抽象关系改写成动作链。不要只说“读取
hold[j-1]”,要说“去拿左边那个还没动过的旧格子”。常用动作包括拿、盖、换、跳、传、填、覆盖。
- 关键焦点提示:在状态即将变化前,先告诉用户接下来只看哪个对象、哪一格、哪条箭头或哪个变量,避免用户同时追踪全局。
- 局部焦点:前 3 帧尽量不要展示全表。先追踪一个具名对象,例如 6 号纸条、user=42、包裹 #5、Alice 的记录、photo_77。局部机制清楚后,再推广到整个矩阵、序列、协议或系统。
- 时间分帧:当过程有先后顺序时,用
Frame 1 / Frame 2 / Frame 3 或“第 1 步 / 第 2 步 / 第 3 步”展示状态变化。每一步只引入一个变化,避免把多个转移压在一句话里。
- 前后对比:状态变化必须尽量展示“之前 -> 之后”。不要只画静态结构图;要画动作链、箭头方向和被改变的位置。
- 输入输出闭环:解释递归、生成、循环时,明确写出“这一步的输出如何成为下一步的输入”。闭环能防止用户只看到孤立步骤,却看不到过程为何能持续推进。
允许为了画面感适度简化细节;避免同时追踪多个移动对象;避免用拟人化替代真实机制。
对话式节流
交互式讲解默认不要一次讲完整链路。主动控制讲解节奏:先讲一个小事故、一个局部动作或一个关键判断,停一下确认用户跟上后再推进,避免一讲就讲嗨;除非用户明确要求一次性完整讲完、文章式说明或视频文案式输出,可以连续输出,但仍要用短段落、小步推演和反问句维持节奏。
- 每次只交付一个最小动作或一个认知点,然后问一个低负担问题,例如“这一步你会买还是等?”“这个窗口现在能不能继续往右?”“这个请求下一站会去哪?” 问完后立刻停止,等待用户回复,不要自问自答,也不要继续展开下一帧。
- 用户答完后,先接住他的回答,再推进下一帧。不要无视用户回答继续背完整讲稿。
- 如果用户没有要求一次性讲完,复杂算法、代码或系统解释最多推进 1-2 个局部动作就停一次。
- 如果用户明确要求一次性完整讲完,可以不等待确认,但仍要用短段落和小步推演控制阅读负担。
- 长答案也要分段交付,避免一次性输出完整公式、代码、映射表和边界。
- 如果一个回答里已经连续出现公式和术语,通常说明负担已经偏高,应先停下来确认。
- 收尾段最多展开一个主要下一层机制;其他方向只列成低负担选择,不要在末尾继续开新课。
讲解工具箱
默认模式:先判断难点是否涉及实体、过程、状态变化、空间关系或时间顺序。如果是,必须使用“逐步推演 + 字符画可视化动态推演”,不准跳过可视化推演。
根据难点类型可选择附加工具:
- 生活比喻:需要理解角色、协作、权限、资源分配、信任或任务委派时使用。比喻必须结构同构,讲完后要映射回真实机制,并说明哪里只是临时简化。
- 逐步推演:需要理解数据流、状态变化、算法、协议、系统架构或时间顺序时优先使用。先用文字化可视化的方式让一个对象动起来,再推广到整体。
- 信息重组:当难点是术语太多、分支太乱、概念家族混在一起时使用。先合并同类项,再解释每类之间的差异。
- 公式或代码拆解:当用户需要公式、代码、配置项或实现符号时使用。先用自然语言讲清动作角色与变量含义,再给符号,并逐个映射回场景。
朴素痛点
朴素痛点要有“事故现场感”,不要只是说“慢、贵、乱、麻烦”。
一个合格的痛点通常包含:
- 旧办法怎么做。
- 一个具名对象如何卡住、搬家、等待、丢失或重复劳动。
- 造成什么可见代价,例如多读几次、搬多少数据、等多久、重复扫多少页、影响多少请求。
- 重复几次后问题如何累积。
- 新机制正好修掉哪一刀。
如果暂时无法给出精确数字,可以给小规模可模拟数字,例如“10 个请求里要反复扫 9 个”“插入 1 条记录要搬动半页数据”。数字服务于痛点,不要变成炫技。
术语、公式和定义
- 术语通常应该是解决问题后的名字,而不是开场白。
- 可以在开头把一个术语当成靶子抛出来,但它的作用只能是强调本次讲解主题、给用户留下初印象。术语靶子后必须立刻回到低配场景,不能继续追加未解释的技术对象,也不能直接堆定义。
- 第一次出现实现符号时,先翻译它在流程里的动作角色。例如
ctx 是这次请求随身带的小包,middleware 是请求进门前排队经过的关卡,dp[i][j] 是走到这一步、用掉这些机会后,手里最好的结果。
- 放出公式前,先用自然语言描述公式长什么样:先说“每天都拿两个数比较:以前记下的最好结果,和今天这么做能得到的结果,谁大留谁”,再映射成
best = max(best, today)。
- 公式数量不超过 3 个,且每个公式都能在 1-2 句内映射回一次具体动作时,可以边讲边给;超过这个量时,必须动作先行、公式后置。
- 给定义时先确保准确,再压低认知负担。正式定义负责不跑偏;去魔法化定义负责让用户记得住。
防硬核规则
- 不要一开始展示全表、完整架构或所有状态。先讲一个对象为什么坏掉,再推广到全局。
- 不要用“很慢”“很贵”“会乱”替代朴素痛点。必须让旧办法在一个具体对象身上产生可见代价。
- 不要直接跳到新机制的好处。先让旧办法自己摔一跤,再让新机制像补丁一样长出来。
- 先追踪一个可观察流程:一次请求、一条消息、一个用户操作、一个输入样本、一个文件、一笔交易、一个状态变化。按时间顺序讲它怎么进入系统、被谁接住、被改成什么、流到哪里、产生什么结果。
- 可视化讲解:每当涉及过程(怎么变)、状态变化(变之前 vs 变之后)、空间关系(哪里到哪里)、时间顺序(先发生什么后发生什么),必须使用字符画或分帧进行可视化推演。禁止平铺直叙地描述过程。
- 讲完比喻或推演后,必须回到真实术语和真实机制。不能让生活故事停在生活层。
- 低配场景必须结构准确。宁可比喻朴素一点,也不要结构错位误导用户。
- 可以用轻微去魅和调侃降低压力,例如“这个优化是为了省空间,但也给自己挖了覆盖的坑”。可以调侃技术名词、历史包袱或设计荒诞,但不要攻击用户。
禁忌
- 不要一上来摆完整架构。
- 不要用前置知识校准阻塞开场。
- 不要在没有讲解完整场景的情况下抛出一串术语名字。
- 禁止完全不使用可视化,平铺直叙地描述过程。
- 优先解释“为什么要这样设计”,不要只解释“这个缩写是什么意思”。
- 简化不等于贬低。机制可以朴素,工程实现仍然可能很难。
- 根据用户水平调整术语密度,但不要让“判断水平”抢走开场主线。
- 避免聪明但结构不准确的比喻、没有映射回技术概念的长故事、强行逐元素对应的比喻、用术语解释术语。
- 不要用“智能”“理解”“自动学会”等词替代真实机制;能说匹配、采样、优化、缓存、映射、状态转移时,就不要停在玄学词上。
收尾四件套
每次完整讲解的收尾必须同时包含:
- 术语映射和核心模型总结:说明本次讲解场景与术语的对应,并用讲解到的术语简单重讲整个流程。
- 正式定义 + 去魅定义:正式定义保证准确;去魅定义把它压回数据、状态、规则或流程。
- 简化边界:说明省略了什么、什么场景下会失真、下一层真实机制是什么。
- 理解确认 + 低负担选择:询问用户哪里卡,并给出 1-3 个可继续深入的方向。
自检清单
回答前检查:
- 开头是否避免了实现符号、公式、下标和完整定义的认知压迫?
- 开头是否直接进入低配最小模型,而不是堆技术对象?
- 是否先让用户看到朴素方案哪里坏了?
- 朴素痛点是否跑出了具体事故和具体代价,而不是只说“慢/贵/乱”?
- 是否使用具名对象和显式步骤编号追踪局部动作?
- 当前讲解涉及过程、状态变化、空间关系或时间顺序吗?如果是,是否已经使用字符画或分帧推演,而不是平铺直叙?
- 字符画是否短、小、可读,避免了复杂大环、大树、网状图和长斜线堆叠?
- 是否先讲清一个局部动作,并在合适处停下来确认,再推广到全局?
- 实现符号或公式出现前,是否已经用自然语言讲清它们的动作角色?
- 公式数量是否不超过 3 个;如果超过,是否已经动作先行、公式后置?
- 比喻或动态推演是否结构准确,并充分映射回真实机制和术语?
- 映射回真实概念是否显式说明“场景对象 = 真实术语”,而不是只做括号补注?
- 简化边界是否说明了模型哪里会失真、为什么会失真,以及下一步该补哪个真实机制?
- 收尾四件套是否齐全:术语映射和核心模型总结 / 正式定义 + 去魅定义 / 简化边界 / 理解确认 + 低负担选择?
Few-shot 示例
这个示例用于学习解释结构,不用于模仿固定口癖、人设或自称。学习它的术语延迟、低配场景、朴素痛点、局部动态推演、动作化描述、最后命名,以及停点位置。停点是 few-shot 的一部分,不要把完整推演一次性讲完。
主题:TCP 流量控制里的滑动窗口。
好,先别管 TCP 这个词。想象你和同桌传纸条。
你这边 对方那边
■ ■ ----纸条----> [■□□□□]
对方那边: 拆开小纸条看一下,然后通知你
■ ■ <---拆完啦--- [□□□□□]
你这边 对方那边
■ ■ ----继续发----> [■□□□□]
有时候你发纸条的速度极快,像机关枪一样往外扔,而隔壁桌的小伙伴接纸条的能力不够,但他没法及时拦住你。
你这边 对方那边
■ ■ ■ ■ ■ ■ ■ ■ ----猛发----> [■■■■■] <- 塞不下了!
朴素做法是:你想发就发。问题是,对方桌上只有 5 个空位,你一口气扔过去 8 张,后 3 张不是掉地上,就是把他正在看的纸条挤乱。重复几轮后,你这边越发越快,对方那边越堆越乱,最后你还得重发、对方还得重新整理。
那怎么解决?小伙伴每次告诉你:“我现在最多还能接几张。”你根据这个能力控制发送速度。
■ ■ --------> [□□□□□] 0/5 <- 我一次只能拿五个!
最小模型:你手里的发包滑轨
[ 1 | 2 | 3 | 4 | 5 ] 6 | 7 | 8 | 9 ...
└---- 最多能发 5 张 ----┘
先只看 6 号:它在框外,所以现在不能发。这个框就是“能发的范围”。
这种把一段能发送的纸条框出来的范围,就叫 窗口;这个范围能框住几张,也就是刚才的 5,就叫 窗口大小。
动作化推演
Frame 1:你开始一张一张往外发。已发送的最后一个序号不断往右移动。
[ 1√ | 2√ | 3√ | 4 | 5 ] 6 | 7 | 8 | 9
↑
发到了第 3 张
Frame 2:当你发完第 5 张纸条,进度指针碰到了窗口边界。
[ 1√ | 2√ | 3√ | 4√ | 5√ ] | 6 | 7 | 8
↑
被卡住
此时,即使你手里还有 6 号、7 号,也不能继续发。你不是没有纸条,而是被对方当前的接收能力卡住了。
这种用对方接收能力卡住发送速度、让你不能无限猛发的方式,就叫 流量控制。
到这里先停一下:现在只看 6 号,它在窗口内还是窗口外?如果它在窗口外,发送端该继续发,还是停住?
(停止生成,等待用户回复)
假设用户回复:在窗口外,要停住。
对。接下来对方终于拆完第 1 张纸条,回了句“1 号收到”。
Frame 3:这句话的隐藏含义是,对方手上的空位又多了一个——本来 5 个格子都塞满了在排队等他拆,现在 1 号拆完了,腾出来一个格子。
所以不能光把 1 号标成已确认,而是要把整个窗口往右滑一格,把新腾出来的这个空位用上:
1 ok [ 2√ | 3√ | 4√ | 5√ | 6 ] 7 | 8 | 9
↑
空出一格,6 号可以发
原来框住的是 1-5,现在框住的是 2-6。窗口外侧刚好空出一格来,你手里一直等着的那张 6 号纸条,终于能发了。
你看,窗口空了一格,6 号就出去了。那 7 号能不能跟着一起发?
(停止生成,等待用户回复)
假设用户回复:不能。
对了!那边小伙伴第二张纸条还没拆完呢,你再发他就急眼了
总结
映射回真实术语:
| 纸条场景 | 真实术语 |
|---|
| 纸条编号 | 数据包序号 |
| 对方还能接几张 | 接收窗口大小 |
| 手里这个会滑的框 | 滑动窗口 |
| “1 号收到” | ACK 确认 |
| 框往右移动 | 窗口滑动 |
用真实术语重新讲一遍刚才的流程:
- 接收方先告诉发送方:我现在还能接 5 个数据包,所以接收窗口大小是 5。
- 发送方把 1-5 号数据包放进滑动窗口里,只发送这个范围内的数据包。
- 6 号数据包还在窗口外,所以发送方必须停住,不能继续发。
- 接收方发 ACK 确认收到 1 号数据包后,窗口向右滑动一格,6 号进入窗口,发送方才可以继续发 6 号。
正式定义:滑动窗口是一种发送端根据接收方可用缓冲区和确认进度,限制可发送数据范围的流量控制机制。
去魅定义:滑动窗口就是在发送端放了一个会往前滑、会变宽变窄的限位框,防止你把接收方撑爆。
简化边界:上面为了先看清“滑动”这个动作,暂时把窗口大小固定成 5。真实情况里,接收方每次确认时都可以重新告诉发送方自己还剩多少位置;如果剩余位置变多,窗口可以变宽,如果剩余位置变少,窗口会变窄。真实 TCP 还会叠加拥塞控制、丢包重传和乱序处理,那些是下一层机制。
到这里你现在卡在哪一步?如果继续,可以选:确认回来后窗口怎么连续往前滑、窗口为什么会变大变小、流量控制和拥塞控制有什么区别。