Day01|给 AI 应用开发工程师的大模型全景
前言:90% 的 AI 应用翻车,根因不在 Prompt
讲个上个月的真实事故。
团队上线了一个 RAG 问答,demo 漂亮,老板满意。结果一上生产,长文本场景下——
成本三天翻了 3 倍,首 token 延迟从 1 秒飙到 8 秒,还时不时冒出幻觉。
排查了三天,根因是什么?
不是模型不行,不是 Prompt 没写好。
是没人在意 Token 计数,没人管 Chunk 策略。一个 5 万字的长文档被整段塞进去,每一次调用都在为几百块人民币的 token 买单。
复盘的数字很难看:单次调用的 token 数从 3k 飙到 47k,月账单从 800 涨到 2600,p99 延迟从 1.2 秒到 8.4 秒——而生成质量,反而更差了。
做了这么多年 AI 应用开发,我越来越确定一件事:
调 API 谁都会,真正卡住团队的,永远是底层没吃透。
长上下文为什么贵?幻觉怎么治?选型怎么定?Fine-tune 还是 RAG?——每一个决策点,都通向同一个地方:大模型的底层原理。
今天这篇,我默认你已经是个熟练的 AI 应用开发工程师。封面这张大模型全景图,我们不把它当科普看——我们把它当成应用工程师的「决策地图」。
顺着 数据 → Token → 向量 → Attention → 生成 → 训练 → RAG/Agent 这条链,每一层我都只讲一件事:
这一层,对你做应用开发,到底意味着什么。
读完,下次技术评审,你能一锤定音。
PART 01:Token & Embedding —— 应用开发的「计价单位」与「检索基石」
新手以为 Token 就是「切词」。
老手知道,Token 是大模型应用里的一切。
它是计费单位——你按 token 付钱,输入输出都算。
它是上下文窗口——prompt 和生成共享同一份额度,prompt 写爆了,模型就没空间输出。
它还有中英文差异——同样一段话,中文切出来的 token 数常常是英文的两倍。你的中文应用,成本天然比别人贵。
不信?拿 tiktoken 实测一下同义的中文和英文:
| 表达 | 内容 | Token 数(gpt-4o,近似) |
|---|---|---|
| 中文 | 大模型应用开发工程师 | ~10 |
| 英文 | LLM application engineer | ~5 |
| 中文 | 检索增强生成 | ~6 |
| 英文 | retrieval-augmented generation | ~5 |
看到了吧,「大模型应用开发工程师」十个汉字,切出来比等义的英文多一倍。这就是为什么中文应用的 token 成本,天生比英文应用高出一截。
所以一个合格的 AI 应用工程师,上线前第一件事不是调 Prompt,是做 token 预算:一次调用平均多少 token、p99 多少、月成本多少、长尾请求会不会把额度打爆。
几行代码就能算:
import tiktoken enc = tiktoken.encoding_for_model("gpt-4o") # OpenAI 系列官方 tokenizer text = "这是一段需要估算成本的中文输入..." n_in = len(enc.encode(text)) n_out = 800 # 假设输出 800 token # 价格(美元 / 1K token),按你用的模型填 price_in, price_out = 0.0025, 0.01 cost = n_in / 1000 * price_in + n_out / 1000 * price_out print(f"input={n_in} tok, output={n_out} tok, 单次成本≈${cost:.4f}")把这段扩成一张「月成本估算表」,你就能提前知道这个应用烧不烧钱:
| 场景 | 单次输入 token | 单次输出 token | QPS | 月成本(美元,近似) |
|---|---|---|---|---|
| 轻量客服 | 800 | 200 | 1 | ~250 |
| 长文档 RAG | 47000 | 800 | 0.5 | ~1800 |
| Agent 多轮 | 12000 | 1500 | 0.2 | ~150 |
没有这张表就敢上线,等于闭着眼烧钱。
⚠️踩坑提醒:tiktoken是 OpenAI 的 tokenizer,对国产模型(DeepSeek、Qwen、GLM)计数不准——它们的词表不一样,tiktoken 算出来的数能差 20%~40%。上线前一定要换成模型官方的 tokenizer重新估一遍,否则预算会严重失真。
再说 Embedding。
它是RAG 的地基。向量维度选多少、相似度用 cosine 还是 dot product、Chunk 切多大、要不要重叠——每一个都直接决定检索质量。
我见过太多团队,RAG 效果差,第一反应是「换个更强的模型」。
错。多数 RAG 翻车,翻在 Chunk 策略和 Embedding 选型,不是生成模型不行。
Chunk 策略的影响,比你想的大得多:
| Chunk 策略 | 切法 | 召回效果 | 适用 |
|---|---|---|---|
| 固定长度 | 每 512 字硬切 | 差(常切断语义) | 快速 demo |
| 按语义切 | 段落 / 标题边界 | 好 | 正经 RAG |
| 带重叠 | 相邻块重叠 50~100 字 | 更好(不漏边界) | 生产环境 |
至于维度和相似度,记住两条经验:
- 维度不是越高越好。1536 维够用就别上 3072,存储和检索成本翻倍,效果未必涨。
- 中文场景相似度优先 cosine。dot product 受向量模长影响,归一化后的 cosine 更稳。
挑 Embedding 模型别只看维度,盯三个指标:语种(中文场景认准 bge / m3e 这类中文优化模型,别拿英文模型硬上)、MTEB 榜单排名(看 retrieval 子任务,不是总分)、推理成本(线上每秒几千次调用,维度翻倍就是真金白银)。三者拉齐再选,比盲目追「最新最大」靠谱得多。
给你一个最小可跑的相似度计算,把「地基」摸到手:
from sentence_transformers import SentenceTransformer model = SentenceTransformer("BAAI/bge-small-zh-v1.5") # 中文 embedding docs = ["如何重置密码", "忘记密码怎么办", "今天的天气不错"] vec = model.encode(docs, normalize_embeddings=True) # 已归一化,点积即为 cosine 相似度 sim = vec @ vec.T print(f"'重置密码' vs '忘记密码' 相似度: {sim[0][1]:.3f}") print(f"'重置密码' vs '天气不错' 相似度: {sim[0][2]:.3f}")一句话送给同行:
Token 是大模型应用的「货币」,Embedding 是检索的「地基」。这两层没吃透,项目必爆预算、必翻检索。
PART 02:Attention & Transformer —— 性能与选型的底层逻辑
这一节我不教你手算 Q/K/V——那是研究者的活。
作为应用工程师,你真正要懂的,是 Attention 的工程后果。
记住一句话:
注意力是 O(n²)。
意思是:上下文长度翻倍,注意力的计算量和显存涨 4 倍。这张表把「为什么长上下文贵」说透了:
| 上下文长度 | 注意力矩阵大小 | 显存(FP16 近似) | 相对成本 |
|---|---|---|---|
| 4k | 4k × 4k | ~32 MB | 1× |
| 16k | 16k × 16k | ~512 MB | 16× |
| 128k | 128k × 128k | ~33 GB | 1024× |
| 1M | 1M × 1M | ~2 TB | 65536× |
看这张表就懂了:把上下文从 16k 拉到 128k,单是注意力这一项,成本就涨了 64 倍。这就是为什么——
- 长上下文 = 成本和延迟平方级上涨;
- KV cache成了推理的核心:它缓存历史 token 的 K/V,避免重复算,首 token 延迟就靠它;
- 上下文窗口(128k / 200k / 1M)是各家模型最卷的卖点,背后全是 O(n²) 带来的工程取舍。
KV cache 到底有多值钱?一句话量化:没有 KV cache,每生成一个字都要把前面全部重新算一遍;有了它,历史部分直接查表,首 token 延迟能从几秒压到几百毫秒。这也是为什么推理框架都在卷 prefill/decode 分离、卷 PagedAttention——本质都在伺候这块 cache。
既然 O(n²) 躲不掉,应用层得自己兜底,三招最常用:
- prompt 精简:历史对话压缩成摘要、系统提示去废话、few-shot 例子从 5 个砍到 2 个——token 少一半,成本和延迟都跟着掉。
- 滑动窗口:只把最近 N 轮塞进上下文,更早的用摘要代替,别一根筋全塞。
- 分块检索(RAG):超长文档别整段喂,切成 chunk 按需检索——把「必须全进上下文」变成「只进相关的那几段」。
这三招的共同点就一句:能用检索解决的长文本,就别用上下文硬扛。上下文窗口是最后手段,不是第一选择。
底层逻辑就这几行:
import numpy as np x = np.random.randn(8, 8) # 8 个 token,每个 8 维 Q, K, V = [x @ np.random.randn(8, 8) for _ in range(3)] scores = Q @ K.T # 关键:这里是 (8,8),token 数翻倍 → 计算量 ×4 weights = np.exp(scores - scores.max(-1, keepdims=True)) weights /= weights.sum(-1, keepdims=True) output = weights @ V看Q @ K.T那行——它就是一个 n×n 矩阵。这就是 O(n²) 的源头,也是你一切性能问题的源头。
再补一个选型常识:今天的主流大模型,GPT、Claude、DeepSeek、Llama,全是 Decoder-only。
这意味着什么?
意味着你选型、微调、挑推理框架,都在围绕同一套架构打转。先分清这三兄弟:
| 架构 | 代表 | 擅长 | 注意力方向 |
|---|---|---|---|
| Encoder-only | BERT | 理解(分类、Embedding) | 双向 |
| Decoder-only | GPT / Claude / DeepSeek / Llama | 生成 | 单向(因果) |
| Encoder-Decoder | T5 / 早期翻译模型 | 序列到序列 | 交叉 |
为什么最后 Decoder-only 赢了?因为它自回归、单向生成的特性,天然契合 scaling law——堆参数和数据就能持续变强,工程上也最好统一。生态高度收敛,这是好事。
选推理框架时,认准这三家:
| 框架 | 强项 | 适合 |
|---|---|---|
| vLLM | 吞吐高、PagedAttention | 高并发在线服务 |
| SGLang | 复杂 prompt 结构、低延迟 | Agent / 多轮 |
| TensorRT-LLM | 极致单卡延迟 | 英伟达栈、延迟敏感 |
懂了 Attention 是 O(n²)、懂了 KV cache、懂了 Decoder-only——
你就懂了为什么推理慢、为什么要缓存、为什么 prompt 该精简。
PART 03:训练链 & RAG/Agent —— 什么自己做,什么交给模型
最后讲应用工程师最高频的决策:这块需求,我该 Prompt、RAG,还是 Fine-tune?
先快速过训练链。你不碰预训练(那是巨头的事),但要懂三步各给模型注入了什么、花了多少成本:
| 阶段 | 喂的数据 | 量级 | 给模型注入了什么 |
|---|---|---|---|
| 预训练 | 互联网级语料 | 万亿 token | 世界常识 |
| SFT(监督微调) | 指令-回答对 | 万~百万条 | 按指令办事 |
| RLHF | 人类偏好排序 | 千~万条 | 说话得体、对齐 |
预训练→ 给它世界常识;SFT→ 教它按指令办事;RLHF→ 让它对齐人类偏好。越往后数据越少、越贵、越决定模型「手感」。
然后是那张你一定会用到的决策表:
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 临时改个输出风格 | Prompt | 改一行就生效,最便宜 |
| 知识要可溯源、能更新 | RAG | 改库即生效,不用重训 |
| 风格 / 格式固化、领域术语密集 | Fine-tune | 把风格烙进权重,省 token |
| 想用小模型替大模型降本 | Fine-tune | 小模型 + 微调逼近大模型效果 |
三条铁律:
- 能用 Prompt 解决,就别上 RAG。Prompt 是最便宜的工程,改一行就生效。
- 能 RAG,就别 Fine-tune。RAG 可溯源、知识能随时更新;Fine-tune 每次要重训。
- Fine-tune 是最后手段。它适合:风格/格式固化、领域术语密集,或者用「小模型 + 微调」替掉大模型来降本。
RAG 和 Agent 的工程化,记两条主线。
RAG 标准链路:切片 → 向量化 → 检索 →重排(rerank,很多人省不掉)→ 拼上下文 → 生成。每一步都有它存在的理由:
- 切片:切得不好,一个知识点被劈成两半,检索永远召不全。
- 向量化:Embedding 模型决定召回上限,选型比调参重要。
- 检索:top-k 别贪多,5~10 条够用;召得太多既白塞上下文,又把真正相关的稀释掉。混合检索(向量 + 关键词 BM25)比纯向量稳,专有名词、人名、型号这种精确词,向量往往召不准。
- 重排:向量检索召回快但粗,rerank 模型精排,把最相关的顶到前面——这一步省掉,准确率掉一截。
- 拼上下文:召回到的片段要排序、去重、截断,塞爆了既贵又触发「中间遗忘」。
Agent= LLM + 工具 + 循环(规划 → 调用 → 观察)。它的工程坑不在「能跑起来」,而在工具调用稳定性和上下文膨胀——Agent 跑几轮,上下文就爆了。
最小 Agent 循环长这样:
def agent_loop(task, max_turns=5): context = [task] for _ in range(max_turns): action = llm_plan(context) # 规划:下一步调哪个工具 if action.done: return action.answer result = call_tool(action) # 调用:执行工具 context = compress(context, result) # 观察:⚠️ 必须压缩,否则几轮就爆 return None注意compress这步——它是 Agent 能不能上生产的分水岭。常用三招:历史轮次 summary 压成一段、工具返回结果只留关键字段、超过阈值就滑动窗口丢最早的。不做这步,Agent 跑 5 轮上下文就涨到几十 k,又贵又慢还容易幻觉。
一句话总结这一层:
资深工程师的判断力,就是知道每一层该自己动手,还是交给模型。
结尾:拼完了
大模型应用这张全景图,从应用工程师视角看,就一句话:
Token 管钱,Embedding 管检索,Attention 管性能,训练链管能力边界,RAG/Agent 管落地形态。
每一层,都是你的一个决策点。
做大模型应用,调 API 是起点,不是终点。真正的护城河,是对从 Token 到 Agent 每一层的工程化理解——哪一层没吃透,应用就会在哪一层翻车。
你的 AI 应用,翻过最贵的车是哪一层?评论区告诉我,下一篇就拆它。
下一篇预告:Day02 可能讲「RAG 检索为什么总拉胯——Chunk 策略、Embedding 选型与 Rerank 的工程实战」
我是小刘檀木,一个从二本摸爬滚打到上市公司 AI 负责人的普通人。关注我,把 AI 学进简历。
— END —
小刘檀木 · 帮普通人把 AI 学进简历