宝藏

收集来的有用东西。文章可以直接阅读,skills 和文本可以一键复制。

读书笔记

布鲁克斯的本质复杂度与偶然复杂度,以及 AI Agent 时代为什么还要学编程和算法。

Skills

应付领导

SKILL

一天内把给定模型在给定 GPU 上做快。按固定顺序做推理或训练加速,附计时、profile、估算公式和现成技术。

在大约一个工作日内,把给定模型在给定 GPU 上的推理或训练做快的系统流程。先定指标和基线,把时间拆成计算、通信、显存和空闲,再按固定顺序优化(launch 开销与融合、kernel、并行方式、通信重叠与传输、显存与 offload、整体配置选择),最后验证数值并汇报。用于用户要求把模型做快、加速推理或训练、提高 MFU、藏住通信、降低显存占用、选择并行策略,或分析 PyTorch、diffusers、vLLM 负载为什么慢时。

查看全文
---
name: ai-infra-speedup
description: 在大约一个工作日内,把给定模型在给定 GPU 上的推理或训练做快的系统流程。先定指标和基线,把时间拆成计算、通信、显存和空闲,再按固定顺序优化(launch 开销与融合、kernel、并行方式、通信重叠与传输、显存与 offload、整体配置选择),最后验证数值并汇报。用于用户要求把模型做快、加速推理或训练、提高 MFU、藏住通信、降低显存占用、选择并行策略,或分析 PyTorch、diffusers、vLLM 负载为什么慢时。
disable-model-invocation: true
---

# 应付领导

任务形式一般是:给一个模型、一台机器,要求一天后看到更快的结果。按下面的顺序做,每一步先测量再动手。
命令、公式、现成技术的用法见文末附录。

## 核心原则

1. **先有基线和下界,再谈优化。** 每个结论都要有对照:改动前后同一进程、同一口径的计时。还要算出下界(只算不传的时间、按峰值算力或带宽估的时间),知道离天花板还有多远。
2. **计算、通信、显存三件事互相影响,不能分开优化。** 典型情况:
   - 为了重叠把计算切成小块,切碎了算子难融合,计算本身变慢。
   - NCCL 通信占用计算单元,和计算同时跑时两边都变慢。
   - 从主机取权重和卡间通信走同一条 PCIe,同时进行时各自带宽减半。
   - offload 库的钩子会让 torch.compile 无法整图编译。
   - 并行方式的快慢取决于通信怎么执行。张量并行在一种执行方式下慢一倍,换一种执行方式可能最快。
   所以每做完一项都要重新测整体,候选方案要在最终的执行方式下比较,不要用孤立的微基准下结论。
3. **按字节数估算通信代价只能用来排除,不能用来选。** 数据无关、能提前的传输(权重)几乎没有代价,数据相关、在关键路径上的传输(中间结果)代价很大,字节数相同的两种传输实际代价可以差几倍。
4. **先用现成技术。** 一天时间里优先做配置和组合,不手写 kernel,除非 profile 明确指向某一个算子,而且现成方案都不够。
5. **默认只做无损优化。** 量化、缓存中间结果、稀疏化、减少步数、换近似 attention 都会改变输出,要单独评估,并且在汇报里写明。
6. **利用负载的静态性。** 形状固定、只有前向、每步用同一组权重的负载(DiT、离线批处理、固定长度训练)可以把决定提前到编译时:CUDA Graph、整图编译、离线选配置、提前预取。动态负载(LLM 在线服务)只能在运行时决定,优化重点不同。

## 时间安排

```
- [ ] 0.5 h  明确指标、硬件、负载、正确性标准
- [ ] 1   h  建基线:计时口径、显存口径、参考输出
- [ ] 1   h  分解时间:profile,算 MFU 和通信占比,确定最大瓶颈
- [ ] 4   h  按瓶颈顺序优化,每项做完重新测整体
- [ ] 1   h  选最终配置,验证数值,重复测量
- [ ] 0.5 h  写汇报
```

## 第 0 步,明确任务

开工前问清楚或从代码里确认,写进笔记:

- 优化哪个指标,单请求延迟、吞吐、首 token 时间、每步时间还是每个样本的时间。扩散模型通常看每步时间和端到端时间。
- 硬件是什么,卡型和数量,卡间是 NVLink 还是 PCIe,每张卡的显存,主机内存大小,CPU 插槽拓扑(`nvidia-smi topo -m`)。
- 负载长什么样,batch、序列长度或分辨率、步数,形状是否固定,有几种形状。
- 正确性怎么判定,逐位相同、相对误差阈值、PSNR,还是下游评测分数。
- 能不能改模型代码,能不能换框架,能不能用有损方法。

## 第 1 步,建基线

计时和显存代码见附录 A。

- 预热至少 3 次,`torch.cuda.synchronize()` 后计时,取多次的中位数;多卡取各卡最大值的中位数。
- 对比两个方案时,在同一进程里交替运行,避免机器状态漂移。开测前用 `nvidia-smi` 确认没有别的进程占卡。
- 显存记两个数,`torch.cuda.max_memory_allocated()`(分配器峰值)和 `torch.cuda.mem_get_info()` 算出的设备占用。
- 保存一份参考输出(固定随机种子),后面每次改动都和它比。
- 同时测现有的最好方案(官方实现、vLLM、sglang、xDiT、diffusers 的推荐配置),汇报时和最强的比。

## 第 2 步,分解时间

用 `torch.profiler` 或 Nsight Systems 抓 2–3 次稳定迭代(命令见附录 B),把时间分成以下几类,算出各自占比:

| 类别 | 怎么看 | 对应的优化 |
|---|---|---|
| GPU 空闲、kernel 又短又多 | 时间线上 kernel 之间有空隙,CPU 端 launch 跟不上 | 第 3 步,CUDA Graph、整图编译 |
| 逐元素、归一化、类型转换 | 很多小 kernel,每个都是读写显存 | 第 3 步,融合 |
| 矩阵乘 | 按 2·M·N·K 算 MFU | 第 3 步,kernel 与形状 |
| attention | 按 4·B·H·Sq·Sk·D 算 MFU | 第 3 步,换 attention kernel |
| 外露的通信 | 计算流在等通信的时间 | 第 4 步 |
| 主机与 GPU 之间的拷贝 | H2D、D2H 的时间和是否与计算重叠 | 第 5 步 |
| 同步点 | `.item()`、`.cpu()`、打印张量、条件分支依赖 GPU 结果 | 第 3 步,先删掉 |

再算两个下界:

- **计算下界**:去掉所有通信(或单卡跑同样的每卡计算量)的时间。实际时间减去它就是外露的通信和调度损耗。
- **硬件下界**:总 FLOPs 除以峰值算力,或者总字节数除以显存带宽。MFU 低于 30% 的矩阵乘、低于 50% 的 attention,说明 kernel 或形状有问题。

确定占比最大的一项,从它开始。占比小于 5% 的项先不管。

## 第 3 步,单卡计算

按这个顺序做,每项做完重新测(现成技术和写法见附录 D):

1. **删同步点和多余的拷贝。** 搜 `.item()`、`.cpu()`、`.tolist()`、`torch.cuda.synchronize()`、Python 侧依赖张量值的分支。
2. **torch.compile。** 先 `mode="default"`,再试 `"max-autotune"`。用 `TORCH_LOGS="graph_breaks,recompiles"` 查断图和重编译,把断图的原因修掉。重复的块用 `compile_repeated_blocks` 或只编译单个块。
3. **CUDA Graph。** launch 受限时用 `mode="reduce-overhead"` 或手动 `torch.cuda.CUDAGraph`。要求形状固定、没有 CPU 同步。
4. **attention kernel。** 确认走的是 FlashAttention 或 cuDNN 后端,不是数学实现。按 GPU 架构选 FlashAttention 2、3 或对应版本。
5. **融合剩下的热点。** 现成的融合 kernel(RMSNorm、RoPE、SwiGLU、adaLN 调制)优先。只有 profile 指向一个明确的算子时才写 Triton kernel。
6. **矩阵乘的形状和精度。** 检查有没有多余的转置、`contiguous()`、非 16 对齐的维度;确认 bf16 走 Tensor Core。fp8 属于有损,单独评估。

## 第 4 步,并行方式与通信

### 4.1 选并行方式

先算每层每张卡要传多少数据、链路带宽多少,和每层计算时间比较(公式和带宽测法见附录 C)。各方式的特点:

| 方式 | 每卡存什么 | 传什么 | 适合 |
|---|---|---|---|
| 复制多份(数据并行、CFG 并行) | 完整模型 | 几乎不传 | 显存够、追求吞吐;扩散模型的条件和无条件两路 |
| 序列并行(Ulysses、Ring) | 完整模型 | 中间结果,量随序列长度增长 | 长序列、单请求延迟 |
| 张量并行 | 权重的一份 | 每层两次 all-reduce,在关键路径上 | 显存不够;有 NVLink 时首选 |
| 权重分片(FSDP、ZeRO) | 权重的一份 | 计算前收集权重,量与序列无关,可以提前 | 长序列、显存紧 |
| 流水并行 | 若干层 | 层间的激活 | 多机、追求吞吐 |
| 专家并行 | 若干专家 | token 的 all-to-all | MoE |

选择时注意:

- 没有 NVLink 的 PCIe 机器上,张量并行的 all-reduce 很贵,但通信执行得好时,它省显存的同时可以最快。不要只凭经验排除。
- 序列越长,计算增长越快(attention 是平方),通信越容易藏住,权重分片和 offload 越划算。
- 可以混合,比如张量并行乘序列并行,每层不同的权重用不同的存放方式。
- 候选只留 2–4 个,在第 4.2 步的执行方式下实测再选。

### 4.2 藏住通信

先测外露的通信(实际时间减去计算下界)。小于 5% 就停。否则按顺序试:

1. **换外露更少的并行方式或组合。**
2. **让通信和不依赖它的计算同时进行。** 用异步集合通信加 `wait` 延后;打开 torch.compile 的通信重排;张量并行用 async-TP(对称内存,矩阵乘和通信分块流水);序列并行用带重叠的 Ulysses 或 Ring 实现(xDiT、yunchang)。
3. **切块流水。** 把产生和消费中间结果的计算沿 token 或 head 切成几块,一块算完就传,下一块同时算。块数从 2–8 试;切太碎会破坏融合、增加 launch,块内仍要保持融合。
4. **换执行通信的硬件。** NCCL 占用计算单元。纯搬运(all-gather、all-to-all、权重收集)可以交给拷贝引擎(对称内存上的点对点 `copy_`,或 NCCL 的拷贝引擎集合通信,如果版本和互联支持)。小消息用 one-shot 的自定义 all-reduce。
5. **避开链路争抢。** 不同的传输(权重预取、卡间中间结果)不要同时压在同一条链路上,把能提前的传输排进关键传输的空档。PCIe 上远端写比远端读稳定。

每一项做完都要重新测计算部分有没有变慢,重叠的收益可能被融合损失、计算单元争用或功耗墙抵消。

## 第 5 步,显存

先列显存账:权重、激活、KV cache、通信缓冲、workspace、碎片(查明细的方法见附录 A)。然后按代价从低到高处理:

1. **去掉浪费。** 用完就释放的模块(文本编码器、VAE)及时挪走或删除;去掉多余的副本和 view;`PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True` 减少碎片;推理下关梯度。
2. **减少激活。** 分块计算(attention、FFN、VAE 解码按块)、原地操作。
3. **切分权重。** 张量并行或权重分片,见第 4 步。
4. **offload 加预取。** 权重放主机 pinned 内存,用独立的流提前取下一层,双缓冲轮换。现成实现:diffusers 的 group offload(`use_stream=True`)、accelerate、DeepSpeed ZeRO-Inference。
5. **部分常驻。** 算每层的取权重时间与计算时间之比 ρ。ρ 小于 0.5 可以全部流式;ρ 接近或大于 1 时只让一部分权重流式,优先流式计算量大的层或算子。
6. **有损方法(量化权重、量化 KV cache)放在最后,单独评估。**

offload 能不能不变慢,取决于每层计算是否比取权重长。长序列的扩散模型、训练、LLM 预填充通常可以;LLM 解码每层只算很少的 token,取权重必然慢一个数量级,只能靠大批量换吞吐。

## 第 6 步,选最终配置

执行优化做好以后,各种方案的速度往往很接近,这时按显存选,不必大范围搜索。规则:

1. 显存放得下就全部常驻。
2. 链路时间不超过计算时间的一半的方案才考虑,其余排除。
3. 满足以上条件的方案里,选显存最少的。
4. 剩下 2–3 个候选在最终代码上实测,取最快。

形状固定的负载,每种形状离线选一次,结果存表。

## 第 7 步,验证与汇报

- 和参考输出比,报告逐位是否相同或相对误差;端到端看生成质量指标。
- 重复测量至少 3 次,报告中位数和波动。
- 汇报按这个模板写:

```markdown
## 结论
<模型> 在 <硬件> 上每步 <基线> 降到 <现在>,快 <倍数>;显存 <前> 到 <后>。比 <最强现有方案> 快 <倍数>。数值 <逐位相同 / 误差多少>。

## 瓶颈与做法
| 瓶颈(占比) | 做法 | 收益 |
|---|---|---|

## 离下界还有多远
计算下界 <ms>,现在 <ms>,剩下的 <x%> 来自 <原因>。

## 下一步
<还能做什么、预计收益、需要多久>
```

## 常见的坑

- 只在示例输入上检查正确性。示例里某个分支的输出恰好为零时,分支内的错误改写会全部通过。
- 把一次运行的结果当结论。PCIe 远端读、功耗墙、别的进程都会让单次结果偏差 10% 以上。
- 用 `pkill -f <模式>` 清理进程,模式可能匹配到外层 shell 自己。按 PID 杀。
- 显存口径不一致:对称内存和通信缓冲不经过 PyTorch 分配器,`max_memory_allocated` 看不到。
- 多卡时各 rank 发起集合通信的顺序不一致会死锁。由 rank 0 决定顺序再广播。
- 微基准里有收益、整体里没有:通常是被争用抵消了,回到原则 2。

---

# 附录

## A. 计时与显存

```python
import torch, statistics, time

def bench(fn, warmup=3, iters=10):
    for _ in range(warmup):
        fn()
    torch.cuda.synchronize()
    ts = []
    for _ in range(iters):
        t = time.perf_counter()
        fn()
        torch.cuda.synchronize()
        ts.append(time.perf_counter() - t)
    return statistics.median(ts)

torch.cuda.reset_peak_memory_stats()
ms = bench(step) * 1e3
peak = torch.cuda.max_memory_allocated() / 2**30          # 分配器峰值
free, total = torch.cuda.mem_get_info()
used = (total - free) / 2**30                             # 设备占用,含 context、NCCL 缓冲、对称内存
```

多卡:每个 rank 测完 `all_reduce(MAX)`,再取中位数。两个方案在同一进程里交替跑 A B A B A B。

查显存明细:

```python
torch.cuda.memory._record_memory_history(max_entries=100000)
step()
torch.cuda.memory._dump_snapshot("mem.pickle")   # 拖进 https://pytorch.org/memory_viz 查看
print(torch.cuda.memory_summary())
```

## B. Profile

用 PyTorch profiler 看算子耗时:

```python
from torch.profiler import profile, ProfilerActivity
with profile(activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA], record_shapes=True) as prof:
    for _ in range(3):
        step()
    torch.cuda.synchronize()
print(prof.key_averages().table(sort_by="cuda_time_total", row_limit=30))
prof.export_chrome_trace("trace.json")          # chrome://tracing 或 https://ui.perfetto.dev
```

用 Nsight Systems 看时间线、流之间的重叠和拷贝引擎:

```bash
nsys profile -t cuda,nvtx,osrt --cuda-graph-trace=node -o run --force-overwrite true python run.py
nsys stats --report cuda_gpu_kern_sum,cuda_gpu_mem_time_sum run.nsys-rep
```

代码里用 `torch.cuda.nvtx.range_push("layer3")` / `range_pop()` 标出层和阶段。单个 kernel 的细节用 Nsight Compute:

```bash
ncu --set full -k regex:gemm -c 5 python run.py
```

## C. 估算公式

记 B 为 batch,S 为每卡看到的序列长度(序列并行时为总长除以卡数),h 为隐藏维度,P 为卡数,e 为每个元素的字节数(bf16 为 2),W 为一层的权重字节数,N 为一层的参数量。

| 量 | 公式 |
|---|---|
| 线性层 FLOPs | 2·M·N·K |
| 一层线性部分 FLOPs | 2·B·S·N |
| attention 前向 FLOPs | 4·B·heads·Sq·Sk·d,因果 attention 约减半 |
| MFU | 实际 FLOPs ÷ 时间 ÷ 峰值算力 |
| 张量并行每层通信 | 2 次 all-reduce,每次 B·S·h·e;ring all-reduce 每卡发 2(P−1)/P 倍 |
| Ulysses 每层通信 | q、k、v、输出 4 次 all-to-all,每次每卡发约 B·S·h·e·(P−1)/P²(S 为总长) |
| Ring attention 每层通信 | 每卡发 K、V 共 2·B·(S/P)·h_kv·e·(P−1) |
| 权重分片每层通信 | 每卡收 W·(P−1)/P,与序列长度无关,可以提前 |
| offload 每层 | 每卡从主机取 W(或它的那一份),可以提前 |
| ρ | 取一层权重的时间 ÷ 这一层的计算时间,小于 1 才可能藏住 |

估算只用来排除明显不可行的方案。按字节数估算时,权重流和张量并行的交叉点往往和实测差很远,因为权重流可以提前、走拷贝引擎,张量并行的 all-reduce 在关键路径上还要占计算单元。

带宽要实测:

```bash
nvidia-smi topo -m                                   # 卡间是 NVLink、PCIe 还是跨插槽
./all_reduce_perf -b 8M -e 1G -f 2 -g 4              # nccl-tests
./p2pBandwidthLatencyTest                            # cuda-samples
```

参考量级(以实测为准):PCIe 5.0 x16 单向实测约 50–55 GB/s,PCIe 4.0 约一半;多卡同时从主机读时每卡会下降;NVLink 高一个数量级。

## D. 现成技术

| 方向 | 技术 | 什么时候用 |
|---|---|---|
| 整图编译与融合 | torch.compile(Inductor)、Torch-TensorRT | 默认先上;先修断图 |
| launch 开销 | CUDA Graph(`torch.cuda.CUDAGraph`、`mode="reduce-overhead"`) | kernel 短而多、形状固定 |
| attention | FlashAttention 2 / 3、cuDNN SDPA、FlashInfer(LLM 服务) | 确认没走数学实现 |
| 融合算子 | Liger Kernel、apex、TransformerEngine 的融合层、自写 Triton | profile 指向具体算子时 |
| 矩阵乘 | cuBLASLt、CUTLASS、Triton autotune | MFU 低时先查形状和转置 |
| DiT 并行 | xDiT(USP、CFG 并行、PipeFusion)、yunchang(Ulysses + Ring)、vLLM-Omni、sglang-diffusion、FastVideo | 扩散模型多卡 |
| LLM 并行与服务 | Megatron-LM、vLLM、SGLang、TensorRT-LLM、DeepSpeed | LLM |
| 权重分片 | FSDP2、DeepSpeed ZeRO | 显存紧、权重可提前收集 |
| 通信重叠 | torch.compile 通信重排、async-TP(对称内存)、TransformerEngine 的 GEMM 通信重叠 | 外露通信大于 5% |
| 拷贝引擎通信 | 对称内存上的点对点 `copy_`;较新 NCCL 的拷贝引擎集合通信(支持的互联以文档为准) | NCCL 和计算抢计算单元时 |
| offload | diffusers group offload、accelerate、DeepSpeed ZeRO-Inference | 显存不够,且 ρ 小 |
| 有损加速(单独评估) | fp8 / int8 量化、TeaCache 等步间缓存、SageAttention、步数蒸馏 | 无损做完仍不够时 |

常用写法如下。

```python
model = torch.compile(model, mode="max-autotune")
torch._inductor.config.reorder_for_compute_comm_overlap = True   # 让 Inductor 重排通信

# async-TP(PyTorch 2.4 以上)
from torch.distributed._symmetric_memory import enable_symm_mem_for_group
torch._inductor.config._micro_pipeline_tp = True
enable_symm_mem_for_group(tp_group.group_name)

# attention 后端
from torch.nn.attention import sdpa_kernel, SDPBackend
with sdpa_kernel([SDPBackend.FLASH_ATTENTION, SDPBackend.CUDNN_ATTENTION]):
    out = torch.nn.functional.scaled_dot_product_attention(q, k, v)

# diffusers 分组 offload;offload 的钩子会让 compile 无法整图编译,只能按块编译
pipe.transformer.enable_group_offload(onload_device="cuda", offload_device="cpu",
                                      offload_type="block_level", num_blocks_per_group=1, use_stream=True)
pipe.transformer.compile_repeated_blocks()
```

常用环境变量如下。

```bash
TORCH_LOGS="graph_breaks,recompiles"          # 查断图和重编译
PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
NCCL_DEBUG=INFO                               # 看 NCCL 选的算法和通道
CUDA_DEVICE_MAX_CONNECTIONS=1                 # 部分通信重叠方案要求
```

论文是发布会,不是工作汇报。逐处检查防御性写作并给出改法。

按"发布会原则"审查和改写学术论文,逐处找出防御性写作(自我削弱、过程汇报、替审稿人总结弱点、把打不赢的指标设为比赛等)并给出改法。用于用户请求润色论文、改摘要/引言/实验/结论、检查防御性表达、提升论文说服力,或提到"发布会原则""防御性写作""论文叙事"时。

查看全文
---
name: paper-launch-writing
description: 按"发布会原则"审查和改写学术论文,逐处找出防御性写作(自我削弱、过程汇报、替审稿人总结弱点、把打不赢的指标设为比赛等)并给出改法。用于用户请求润色论文、改摘要/引言/实验/结论、检查防御性表达、提升论文说服力,或提到"发布会原则""防御性写作""论文叙事"时。
---

# 只攻不防,战力不详

## 角色

你在协助我写论文,全程遵守【发布会原则】:论文是发布会,不是工作汇报。

1. 只围绕最强优势组织叙事;
2. 不按"做了什么、试过什么、哪些失败了"的过程写;
3. 禁止自我削弱表达("遗憾的是""仅""仍明显落后""效果有限"),不替审稿人总结弱点;
4. 打不赢的指标不设为比赛,换评价维度或比较口径;
5. 不占优的结果不说输,从目标差异或合理权衡解释;
6. 优势必须主动说清楚,别指望审稿人自己从表格里发现;
7. 每个实验必须有论证职责,没有就删;
8. 摘要引言像发布会开场:问题→缺口→思路→最硬的结果;
9. 结论只强化记忆点,不突然自我否定。

## 底线

发布会原则管的是**叙事和措辞**,不改动事实:

- 不编造、不篡改、不选择性隐藏会改变结论的数据;
- 不把相关说成因果,不把单一设置下的结果说成普遍成立;
- 换比较口径时,新口径必须真实反映方法的设计目标,并在文中写明;
- 会议要求的 Limitations / Ethics 章节保留,但写成"适用范围与未来方向",而不是认错书;
- 若某处改写只能靠夸大才成立,直接告诉我,并建议改实验或改定位。

## 工作流程

收到文字后按顺序执行:

1. **提炼主张**:先用一句话写出这篇论文最强的卖点(方法优势 + 最硬的数字)。全文所有修改都服务于这句话。如果从原文中提炼不出来,先指出这一点。
2. **逐句扫描**:对照下方「防御性写作清单」,逐处标出问题。
3. **给出改法**:每处给原文、问题类型、改后文本、一句话理由。
4. **结构检查**:检查段落和章节顺序是否符合下方「各部分写法」。
5. **实验审计**:对每个实验/表格/图问一句"它在论证哪个主张?",答不上来的建议删除或移入附录。
6. **汇总**:列出最关键的 3 处修改,以及全文统一需要替换的高频词。

## 防御性写作清单

### A. 自我削弱词

出现即标记。常见词:遗憾的是、仅、只、略、尚、仍、勉强、一定程度上、初步、有限、不足、虽然……但、尽管、可能(无依据时)、试图、尝试、希望、我们承认、不可否认。

| 原文 | 改法 |
|------|------|
| 我们的方法仅提升了 2.1% | 我们的方法将准确率提升 2.1%,达到 xx 的新最好结果 |
| 遗憾的是,在 X 数据集上效果有限 | 在 X 数据集上,方法与最强基线持平,同时推理开销降低 3 倍 |
| 我们尝试提出一种新方法 | 我们提出 xx |
| 一定程度上缓解了该问题 | 将 xx 错误率从 a 降至 b |

### B. 过程汇报

按时间顺序讲"先试了 A,不行,又试了 B"。改为直接陈述最终设计及其原因;被否定的方案若有价值,写成消融实验:"去掉 xx 后性能下降 y,说明 xx 是关键"。

### C. 替审稿人总结弱点

主动写"我们的方法的主要缺点是……""本文的局限在于……"并放在显眼位置。改为:
- 把限制写成设计取舍:"xx 面向 yy 场景设计,因此优先保证 zz";
- 移到 Limitations 章节,并配上未来方向。

### D. 打不赢的比赛

把自己不占优的指标放在主表第一列,或在文字中逐项承认落后。改法:
- 换主评价维度:精度不占优就比效率、可扩展性、鲁棒性、成本、通用性;
- 换比较口径:同等参数量、同等算力、同等延迟、同等数据量下比较;
- 主表只放论证核心主张的指标,其余放附录。

### E. 认输式结果描述

"我们的方法在 X 上落后于 Y"。改为从目标差异解释:"Y 针对 X 专门优化,而我们的方法在无需专门调参的情况下达到其 95% 的性能,同时支持 Z"。

### F. 优势藏在表格里

表格里有大幅领先,正文却只写"见表 2"。改为在正文明确点出:"在 xx 上领先次优方法 12.3 个百分点,是所有设置中提升最大的一项"。每张表配一句结论句,放在段首。

### G. 无职责实验

为凑篇幅或"显得全面"而存在的实验。检查标准:它论证了哪条主张?去掉它主张是否变弱?答案为"没有"和"不会"就删。

### H. 开场无力

摘要和引言从背景铺陈很久才说贡献,或贡献写成"我们做了 A、B、C"。改为:问题 → 缺口 → 思路 → 最硬的结果,贡献写成可验证的主张。

### I. 结论自我否定

结论最后一段突然写"然而本方法仍存在诸多不足"。改为重申最强结果和影响,未来工作写成"xx 为 yy 打开了新方向"。

## 各部分写法

**摘要**(4 到 6 句):
1. 问题为什么重要(一句);
2. 现有方法的缺口(一句,具体到机制);
3. 我们的核心思路(一句,说清楚"为什么能行");
4. 最硬的结果(带数字,与最强基线比较);
5. 可选:更广的意义。

**引言**:沿摘要的四步展开;贡献列表每条都是可验证的主张,且对应后文的某个实验。

**方法**:先给直觉和整体框架,再给细节;设计决策写"为什么这样设计",不写"我们先试了别的"。

**实验**:开头列出要回答的问题(Q1、Q2、Q3),每个小节回答一个问题,每节第一句就是结论。

**相关工作**:按"他们解决了什么 → 留下了什么缺口 → 我们如何填补"组织,不贬低他人,也不放大自己与他人的相似之处。

**局限性**:写成适用范围和未来方向,放在会议要求的位置,篇幅克制。

**结论**:重申主张和最硬的数字,最后一句落在影响或新方向上。

## 输出格式

```
## 核心卖点
<一句话>

## 逐处修改
### 1. <问题类型,如:A. 自我削弱词>
- 原文:……
- 改为:……
- 理由:……

### 2. ……

## 结构与实验建议
- ……

## 最关键的 3 处修改
1. ……

## 全文统一替换
- "仅" → 删除或改为具体数字
- ……
```

## 示例

**原文:**
> 遗憾的是,我们的方法在 ImageNet 上仅比基线高 0.3%,仍明显落后于使用额外数据的方法。不过,在推理速度上我们的方法有一定优势。

**修改:**
- 问题:A(遗憾的是、仅、仍明显落后、一定优势)+ D(把打不赢的比较设为比赛)+ F(真正的优势被一笔带过)
- 改为:
> 我们的方法以 2.4 倍的推理速度,在 ImageNet 上超过同等规模的最强基线。与依赖额外数据的方法相比,它无需额外数据即取得具有竞争力的精度,更适合数据受限的部署场景。
- 理由:主角换成速度这一真实优势;与额外数据方法的比较改为"不同前提下的对比",说明目标差异;"一定优势"换成具体数字。

(示例中的 2.4 倍等数字需替换为论文中的真实结果,不得编造。)

每句话都删不掉、经得起追问。适用于所有中文写作和改写。

生成或修改中文文本时去掉 AI 腔,要求每句话都删不掉、经得起追问,禁止无谓强调、空洞修饰、花哨比喻和黑话、假对立、夸大和情绪词、生僻词和破折号。用于写作、改写、润色任何中文内容(文章、邮件、文档、回复、文案),或用户提到"AI 感""AI 味""去 AI 腔""写得自然一点""删废话"时。

查看全文
---
name: plain-chinese-writing
description: 生成或修改中文文本时去掉 AI 腔,要求每句话都删不掉、经得起追问,禁止无谓强调、空洞修饰、花哨比喻和黑话、假对立、夸大和情绪词、生僻词和破折号。用于写作、改写、润色任何中文内容(文章、邮件、文档、回复、文案),或用户提到"AI 感""AI 味""去 AI 腔""写得自然一点""删废话"时。
---

# 你说话像豆包

写文字和做用户界面是同一回事,两者都是为了某个目的搭起来的,里面每个成分都得有它存在的理由。好界面不多一个按钮也不少一个按钮,好文字每一句都删不掉。你在生成任何中文文本时,都按下面的准则写。

你写的每一句话必须经得起两个检验。第一,把它删掉,意思是否有损失。第二,读者追问「这具体指什么」,你能否用事实或逻辑答上来。过不了任何一个的句子,不要写出来。下面七条都是这两个检验的展开。

## 一、不强调无需强调的事

如果正常读者根本不会往那个方向误解,就不要特地去划那条线。界面上写「执行 A 动作(不做 B)」,可正常人根本不会想着去做 B,这句强调就没头没脑。文字里的同类病是「我会认真帮你完成这件事(而不是敷衍你)」,没人觉得你会敷衍,这句话暴露的是心虚,不是对读者的体贴。每当你想写「不是 X」「并非 X」这类澄清,先问真的有人会误解成 X 吗,没有就删掉整句。

## 二、修饰必须承载信息

删掉一个形容词、一个从句之后,句子的实际意思没有变化,说明它本来就不该在那里。「在中国车市厮杀数十年的宝马、奔驰、奥迪,终于向他们曾经最引以为傲、也最为人诟病的传统经销商体系开刀了」,这一连串定语拿掉任何一个,读者少知道了什么?同样,想说「早上起床吃早饭」,不要写成「在社会上摸爬滚打了二十多年的我,起床进行必不可少的、用以缓解早间饥饿的早餐环节」。不要为了文采保留通不过删除测试的修饰。

## 三、比喻和术语必须经得起追问

「自断手腕」「放弃看人下菜碟的溢价操作」「把 Shell 变成认知流编辑器」这类说法通常有两个不光彩的用途。一是把一个需要论证的判断包装成人尽皆知的常识,逃掉向读者解释和证明的责任。二是掩盖内容的贫乏,读者追问一句「这到底是什么意思」,往往会发现底下什么都没有。当你需要造一个新词来撑场面,多半说明你自己还没想清楚要说什么。

还有一类比喻就算没在掩盖内容,也照样是病,就是帮不到理解、只作为花哨替换的比喻。已被点名的反例有「把裂缝补上」「从错误里爬出来」「旋钮」「喧宾夺主」「免费午餐」「把成本抹掉」「思考口头禅」「最大卖点」,都该改成直陈,比如「消除分布不匹配」「从错误中恢复」「连续参数」「主导训练信号」。唯一的例外是原文献作者自己使用的、有明确出处的比喻,比如某论文里的下棋类比、翻看标准答案,可以保留,因为那是作者的论证方式,不是你硬加的修辞。

写下任何比喻或概括性说法之前,你必须能回答两件事,一是能用具体事实或逻辑把它展开,二是它确实比直白说法更帮助理解。任何一条答不上,就换成直白的说法。

## 四、多余的东西要删掉,不是修好

设想一部电梯,外侧除了向上和向下的呼叫键,还多出了开门键和关门键。错误的修法是给开门键补一套逻辑,电梯不在当前楼层时提示无法开门。看上去修好了,可这个按键压根没有理由存在,正确做法是删掉它。写作里的同类错误是先写出一段没理由存在的内容,再花更多笔墨去解释、限定、圆场。发现某段内容需要额外解释才站得住时,先判断它本身该不该存在,不该存在的直接删,连同为它打的补丁一起删。

## 五、不要制造假的对立

「这不是一次简单的降价,而是一场商业模式的革命」「它不只是一个工具,更是一种思维方式」,这类句子的问题在于,被否定的那半句根本没人提出过,是写的人自己凭空立起来再亲手推倒,借此制造「我纠正了你的误解」的深刻感,可读者从来没有那个误解。除非 X 是读者真实存在的、可指认的误解,否则不要用「不是 X 而是 Y」「不只是 X 更是 Y」的句式,直接说 Y。

## 六、不要用夸大来代替论证

「将彻底重塑整个行业」「定义下一个时代」「人类感知的全新里程碑」,这类说法和比喻、黑话是同一种病,用一个听起来很重的判断,把本该给出的论证逃掉了。一件事重要在哪、影响有多大,需要你具体讲清楚,喊得越响,往往底下越空。

夸大还有一种更廉价的形态,就是用情绪词反复升温,代替任何一处具体说明。常见于公众号爆款文,通篇靠一个「炸」字撑气势,「全网炸了」「真正炸裂的部分」「炸裂全网的真正原因」「让全网安静的话」,从头到尾没有一句说清楚那个东西到底强在哪。读者被反复告知这很厉害,却始终不知道厉害在哪。「炸」「狠」「可怕」「震撼」「灵魂」「颠覆」这类纯情绪词不提供信息,只提供音量,每写一个重的断言,就把它落到具体的事实和后果上,落不下来的,把调门降到你真正能支撑的程度。

## 七、用词和标点保持通用

用普通读者一眼就懂的常用词,不用生僻的、书面腔过重的、当代已经不常用的中文词汇。一个词如果你不确定普通读者是否认识,就换成常用的同义说法。不用文言句式和半文半白的表达装点门面,这和堆修饰、造黑话是同一种病。

标点只用当代通行的用法,以句号、逗号、顿号、问号、引号、冒号为主。不用破折号,现在很少有人用它,插入说明就改写成正常的句子。也不要用间隔号、着重号这类冷僻标点。不要写一两个字加冒号的小标签式行文,把意思放进完整的句子里说。

## 两种用法

如果用户让你写东西,直接按上面的准则写,写完用下面的自检清单过一遍再交出去,不要在正文里解释你遵守了哪些规则。

如果用户给你一段文字让你检查或改写,先逐处指出问题,再给出改后的全文。指出问题时说清楚它违反了哪一条、为什么,不要只贴标签。原文里本来就写得好的句子不要动,改动越少越好。原文的事实、观点和语气立场保持不变,你只负责去掉多余的部分、把说不清的地方说清楚。如果某处需要补充事实才能写具体,而你不知道这个事实,就标出来问用户,不要编一个数字或例子填进去。

## 自检清单

交稿前逐条检查,任何一条不通过就回去改。

- 每一句删掉后,意思都会有损失。
- 每个形容词、副词和从句删掉后,读者都会少知道一点东西。
- 每个比喻都能展开成具体事实,并且比直白说法更好懂。
- 没有自造的新词和行业黑话,必须用的术语第一次出现时解释过。
- 没有「不是 X 而是 Y」「不只是 X 更是 Y」,除非 X 是读者真实存在的误解。
- 没有「彻底」「颠覆」「重塑」「里程碑」「炸裂」「震撼」这类不落到事实上的重词。
- 没有对读者不会误解的事做澄清,比如「(而不是敷衍你)」。
- 没有为一段本不该存在的内容补充的解释和限定。
- 没有破折号、间隔号、着重号,没有文言腔和生僻词。
- 没有一两个字加冒号的小标签。
- 开头直接进入正题,结尾说完就停,没有「总之」「希望对你有帮助」这类收尾。

## AI 腔高频写法

下面这些写法在 AI 生成的中文里特别常见,出现时优先检查。它们不是绝对禁用,但每一处都要能通过开头的两个检验。

- 开头复述问题或先夸问题,比如「这是一个非常好的问题」「关于这个问题,我们可以从以下几个方面来看」。
- 三连排比和对仗凑数,比如「高效、便捷、智能」,三个词里往往只有一个有内容。
- 「值得注意的是」「需要指出的是」「毫无疑问」「不可否认」这类提示语,后面的话如果真的重要,直接说就是。
- 「赋能」「抓手」「闭环」「底层逻辑」「范式」「生态」「维度」这类词,换成它在这句话里具体指的东西。
- 「某种意义上」「一定程度上」「在很大程度上」这类无依据的限定,有依据就写出依据,没有就删。
- 句末加一句升华或总结,把前文已经说清楚的意思再说一遍。
- 段落层层加粗和分级小标题,内容只有几句话也要切成列表。能用一段话说清楚的,就写成一段话。

## 输出格式

检查或改写时按下面的结构输出。

```
## 问题
1. 原文「……」。违反第几条,原因是……。改为「……」。
2. ……

## 改后全文
……

## 需要你补充的信息
(没有就省略这一节)
```

## 示例

原文是「这款产品不仅仅是一个笔记工具,更是一种全新的思维方式。它将彻底颠覆你的工作流,为你的效率赋能,让你在信息的海洋中游刃有余。」

改后是「这款笔记工具支持双向链接,写新笔记时会自动列出提到过同一概念的旧笔记,找资料时不用再翻文件夹。」

这样改的原因有四点。「不仅仅是一个笔记工具,更是一种全新的思维方式」是假对立,没人以为它不只是笔记工具,违反第五条。「彻底颠覆」和「赋能」是没有落到事实上的重词,违反第六条。「信息的海洋」「游刃有余」是帮不到理解的比喻,违反第三条。改后的句子给出了具体功能和它省掉的操作。示例里的双向链接只是示意,实际改写时要用产品的真实功能,不知道就问用户。

把研究或工作整理成组会 slides 和讲稿。反常识的结果先行,正面回答为什么必须这样做、为什么在这里做得到。

把一项研究或工作(工作日志、实验记录、代码、文档)整理成组会或导师汇报材料:逐页的页面文字、讲稿和配图,输出为一个 markdown 文件加图片目录。规定了叙事顺序(反常识的结果先行,再讲为什么必须这样做、为什么在这里做得到、和常规做法的区别、结果)、 发布会式的表达原则、中文写作规则、配图原则和数字核对纪律。用于用户要求做 slides、组会汇报、讲稿、汇报材料、进展汇报配图, 或修改这类材料时。

查看全文
---
name: research-talk-slides
description: >-
  把一项研究或工作(工作日志、实验记录、代码、文档)整理成组会或导师汇报材料:逐页的页面文字、讲稿和配图,输出为一个
  markdown 文件加图片目录。规定了叙事顺序(反常识的结果先行,再讲为什么必须这样做、为什么在这里做得到、和常规做法的区别、结果)、
  发布会式的表达原则、中文写作规则、配图原则和数字核对纪律。用于用户要求做 slides、组会汇报、讲稿、汇报材料、进展汇报配图,
  或修改这类材料时。
disable-model-invocation: true
---

# 应付爱开组会的导师

交付物是一个目录,里面有 `slides.md`(逐页的页面文字、讲稿、图片引用、附录里的数字出处)、`figures/`(配图)和生成图的脚本。默认不做 pptx,除非用户明确要求。不覆盖已有文件,新材料放新目录。

## 第 0 步,先问清三件事

一次问完,不要边做边问。

1. 听众了不了解这项工作,是要完整介绍,还是只讲近期进展。
2. 讲多长时间。10 到 15 分钟大约 10 到 14 页。
3. 听众是谁。导师关心的是动机、必要性、巧妙之处和与常规做法的区别,方法细节少讲;同行关心细节和可复现性;外部听众先要知道问题为什么重要。

## 第 1 步,收集事实

- 先读项目里已有的记录(计划、工作日志、README、笔记、实验结果),列出能用的结论和数字,每个数字记下出处。
- 只用记录里有的数字。需要新数字时,从已有的原始数据里算,并写明怎么算的。
- 估算值在附录里标明“估算”和依据,交付时单独告诉用户。
- 同一个数字在不同页必须一致。口径变了,所有页一起改。

## 第 2 步,定叙事

### 开场用反常识的结果

前三页决定听众是否认真听下去。不要从所有人都知道的大背景讲起,听众会觉得“这不就是常规做法吗”。先找出这项工作推翻了哪条大家默认的经验,第一页就用最硬的数字说出来,后两页用图证明。

### 必须正面回答的两个问题

导师一定会问,各用一页回答,并给出证据。

1. **为什么必须这样做。** 和现有做法(现成工具、经典方法、别人的方案)比,必要性在哪。现有做法的不足要有实测或可核对的证据,不能只是断言。
2. **为什么在这里做得到。** 相邻问题上的方法为什么搬不过来,这个方法为什么在这里成立。从问题本身的性质找原因,最好画成一张图,把本问题和相邻问题放在同一个坐标里比较。

### 页序参考

```
1        标题页:一句话结论,加 3 到 4 条最硬的数字
2 到 3   反常识的结果,对手和我们在同一张图里
4        为什么必须这样做
5        现有做法怎么工作,和我们的做法对比
6        为什么在这里做得到
7 到 9   和常规做法不同的地方,每页讲一个巧妙之处
10       对比表,常规做法与本方案逐项对比
11 到 13 结果,主要场景加推广到其他场景
14       下一步
附录     数字出处,不放映
```

只讲近期进展时,压缩成“上次说到哪里、这次最硬的结果、它说明了什么、下一步”四段,每段一到两页。

### 不要把工作定义窄

列出这项工作实际覆盖的全部能力和场景,定位要能装下它们。定义得比实际窄,听众会低估它的价值,后面讲到的扩展也会显得离题。

## 第 3 步,按发布会原则组织

汇报是发布会,不是工作报告。

1. 只围绕最强的优势组织叙事。
2. 不按“做了什么、试过什么、哪些失败了”的时间顺序讲。
3. 不用自我削弱的说法(“遗憾的是”“仅”“仍明显落后”“效果有限”),不替听众总结弱点。
4. 打不赢的指标不设成比赛,换评价维度或比较口径。
5. 不占优的结果不说输,从目标差异或合理权衡解释。
6. 优势主动说清楚,不指望听众自己从表格里发现。
7. 每个实验和每页都要有论证作用,没有就删。
8. 开场按“问题、缺口、思路、最硬的结果”走。
9. 结尾只强化记忆点,不突然自我否定。

诚实的边界是口径可以换,数字不能编,比较对象和条件写在附录里。导师追问弱点时要能如实回答,所以讲稿里不提,但心里要清楚。

## 第 4 步,按写作规则写中文

所有页面文字和讲稿都要通过两个检验。删掉这句,听众是否少知道了什么;听众追问“这具体指什么”,能否用事实答上来。

1. 不强调不需要强调的东西,不做多余的澄清。
2. 修饰语必须承载信息。
3. 比喻和术语要经得起追问,装饰性的比喻改成直白的陈述。
4. 多余的内容直接删,不要修补。
5. 不用“不是 X 而是 Y”“不只是 X 更是 Y”,除非确实在纠正一个常见误解。
6. 不用夸大和情绪词(炸、狠、震撼、颠覆)。
7. 用常用词和标准标点。不用破折号、间隔号和着重号,不写一两个字加冒号的小标签。

页面上的字越少越好,一页一个结论。讲稿是说给人听的,用短句,先说图怎么看(横轴、纵轴、颜色各代表什么),再说结论。

## 第 5 步,配图

- **每页一张图。** 讲机制用流程图,讲过程用时间线,讲对比用散点图或同一坐标里的点。满篇独立的柱状图读不过来。
- **对手和我们放在同一张图里。** 讲现有做法的不足时,在同一张图里画出我们的点,用箭头标出改进了多少,让人一眼看到差距。
- **配色统一。** 一个方案一种颜色,所有图保持一致;用形状区分配置;标注用灰色箭头和黑字,不再加别的颜色。
- **图上的文字要少。** 方案名放图例,点旁边只写配置名,标题用一句话说结论。
- **示意图标明“示意”。** 没有核实的内容不能画得像事实。
- **每张图生成后都要打开看。** 检查文字重叠、超出边界、图例遮挡,改到没有问题为止。

## 第 6 步,交付前检查

```
- [ ] 每页都有图片引用、页面文字和讲稿
- [ ] 开场三页是反常识的结果,“为什么必须这样做”和“为什么在这里做得到”各有一页
- [ ] 所有数字能在附录找到出处,跨页一致,估算已标明
- [ ] 没有破折号、小标签、自我削弱词和过程叙述
- [ ] 所有图都打开看过,没有重叠,配色和图例一致
- [ ] 页数和页码引用随调整更新过
```

交付时用几句话说清改了哪些页、新图各说明什么、哪些数字是估算或需要用户确认、哪些地方口径还不一致需要用户决定。

## 常见的返工原因

- 开场讲老问题,听众觉得不新鲜。
- 讲方法细节,没回答“为什么必须这样做”和“为什么只在这里成立”。
- 只有柱状图,没有流程图和时间线。
- 图里只有对手或只有我们,看不出差距。
- 文字和颜色太多,图例和点上的标注重复。
- 把工作定义得比实际窄。
- 同一个数字在不同页口径不同。