fedorthinks

速成课 · No. 07

一个语言模型,是个出色的「下一个词」猜测器——没有记忆,还动不动就胡编。用它来构建,靠的不是什么魔法 prompt,而是你围着这个强大却不可靠的部件所做的那层工程,好让它变得值得信赖。

24 个概念 · 每个都配图示 · 结尾附速查表

§ 01

在用语言模型构建之前,先弄明白它究竟是什么——因为几乎每一个错误,都源于期待它成为它本不是的那种东西。

课程地图:七组共 24 个概念

一张地铁线路图:先看整条线路,再一站一站地坐过去。

这门课从简单讲到复杂。先讲模型是什么、它的行为如何。然后是怎么跟它说话(prompting),往它的窗口里放什么(context),怎么把你的事实交给它(RAG),怎么让它行动(agent),怎么让这一切值得信赖(可靠性),以及怎么构建而不过度构建。

The modelNext-token predictionContext windowHallucinationNon-determinismPromptingPrompt as a briefSystem vs user promptFew-shot examplesStructured outputContextContext engineeringRelevance firstContext budgetFacts (RAG)Retrieval (RAG)EmbeddingsGroundingChunking & retrievalAgentsTool useAgent loopMemoryHuman-in-the-loopReliabilityEvalsGuardrailsCost & latencyHallucination defenseBuilding wellComplexity ladderLLM as a component
七组概念——各章就按这个顺序展开。

如何阅读每个概念

一本护照:每个人都是同样的栏目,所以很容易对比。

每个概念都用同样的方式来讲:它的英文名称(你在文档里会去搜的那个术语)、一幅日常生活里的画面、一张图示,以及一张带栏目的卡片——它是什么、一个例子、代价或陷阱、何时使用,以及它和其他概念的关系。这门课只有一个大观点:模型是容易的部分;围绕它的工程才是真正的活儿。

Next-token prediction——它在预测下一个词,而且预测得极好

你手机键盘在猜下一个词——但放大到极致,以至于它能写一篇文章、调一段代码、讲明白物理,一次一个看似合理的词地往下推。

LLM 是一个下一个 token 的预测器,在海量人类文本上训练而成。它不去查东西;它生成统计上最可能接下来出现的内容。这就是为什么它在语言和推理模式上令人惊叹——也是为什么它不是一座事实的数据库。它产出的是听起来对的东西,这通常是对的,有时却是自信满满地错的。

The cat sat on thetext so farLLMscores tokensmat · 0.62sofa · 0.21floor · 0.09pick a likely token → append it → feed the text back → repeat
模型给候选的下一个 token 打分,挑一个可能性高的,接上去,然后重复。
ConceptNext-token prediction· 下一个 token 预测器(next-token predictor)
是什么
模型一次生成一个 token,挑选一个可能性高的接续。
例子
「猫坐在……上」→「垫子」比「沙发」更有可能。
陷阱
它不是事实查询:「听起来对」≠「就是对」。
怎么办
别把模型当事实数据库用——事实由你自己交给它。
关联
Hallucination 和 Non-determinism 的根源;用 RAG 来应对。

Context window——它唯一的记忆

一位才华横溢却彻底失忆的顾问——每一次开会,你都得把每一份文件重新递给他一遍,因为他对上次的事什么都不记得。

模型在两次请求之间什么都不记得。它唯一的工作记忆,就是上下文窗口(context window)——你在这次调用里发进去的文本。对话历史、你的数据、你的指令:只要不在 context 里,模型就不知道。这门课里的一切,在某种意义上,都是关于你往那个窗口里放什么。

Context window · this callSystem promptChat historyRetrieved docsTool definitionsUser messageLLMAnswerno memory between callsLast week's chatnot sent → model doesn't know it
模型只看得到这次调用窗口里的东西。不在窗口里,对模型来说就不存在。
ConceptContext window· 模型的工作记忆
是什么
一次调用的全部文本:system prompt、历史、文档、工具、问题。
例子
聊天机器人「记得」之前的消息,只是因为你每次调用都把它们重新发了一遍。
陷阱
窗口是有限的,里面的每个 token 都要花钱、花时间。
怎么办
有意识地组装窗口——这就是 Context engineering。
关联
由 Context engineering 和 RAG 来填充;Memory 存在它之外。

Hallucination——它会胡编,而且自信满满

晚宴上一位迷人的万事通,他宁可编出一个有说服力的答案,也不愿承认自己不知道。

当模型不知道时,它不会停下——它会产生幻觉(hallucination),以与真相同样的自信,产出流畅、看似合理、却是错的文本。这不是你能彻底打补丁修掉的 bug;它就是一个猜测器的本性。这门课里大部分工程的存在,都是为了驾驭这一个事实。

Question“cite a paper on X”LLMReal factconfidence: highMade-up citationconfidence: highsame tone, same certaintyit doesn't stop when it doesn't know
真相和编造从模型里出来时同样自信——光听语气分不出来。
ConceptHallucination· 自信地编造
是什么
一个流畅、看似合理、却是错的回答,说得信心十足。
例子
你要一个出处——模型引用了一篇根本不存在的论文。
陷阱
无法彻底消除:这是下一个 token 预测的本性。
怎么办
限定它可能出现的范围,出现时把它抓住——见第 6 章。
关联

由 Grounding 和 RAG 来降低;由 Guardrails 和 Evals 来抓住。

Non-determinism——每次都不一样

把同一个问题问十位专家——你会得到十个略有不同的好答案,而不是一个一模一样的回复。

同一个 prompt 每次都可能给出不同的输出——这就是非确定性(non-determinism)。所以你不能把 LLM 当成一个返回值固定的函数;你把它当作聪明、易错、非确定性的输入——要去约束、去校验、去核查,而绝不盲目信任。这种心态,就是整盘棋的关键。

Same promptcall #1call #2call #3Answer AAnswer A′Answer BValidatedon't trust
同一个 prompt 调用三次——三个略有不同的答案。所以输出总是要检查。
ConceptNon-determinism· 同样的输入,不同的输出
是什么
同样的输入可能产生不同的输出。
例子
让它总结一封邮件,问两次——得到两段不同的文字。
陷阱
普通的「相等 / 不相等」单元测试在这里会失效。
怎么办
约束格式(Structured output),校验,衡量质量(Evals)。
关联
你需要 Evals 和 Guardrails 的原因。

LLM 并不知道东西。它在预测东西。把其余的一切,都围着这一个真相去造。

§ 02

prompt 是你告诉模型你想要什么的方式。指令越清晰,输出越好——而大多数「AI 真笨」的时刻,其实都是 prompt 不清楚。

Prompt——是一份任务说明,不是咒语

把任务交给一位机灵的新员工:他扮演什么角色、你要什么、有哪些限制,以及一个「好结果」的样例。说明含糊,结果就含糊。

一个好的 prompt 会写明角色(「你是一位细致的编辑」)、任务、约束(长度、语气、格式),最好再附一个例子。没有什么魔法词——就是清晰的指令,跟你交代一个能干的人时一样。大多数 prompt 问题,其实是需求说明的问题。

Roleyou are a careful editorTasksummarize this ticketConstraints3 bullets · plain toneExampleone sample of “good”Prompta clear briefOutputwhat you asked for
一份好说明的四个部分:角色、任务、约束、例子。
PracticePrompt· 任务说明
问题
含糊的要求 → 含糊的回答,看上去就像「AI 真笨」。
思路
把 prompt 写成一份说明:角色、任务、约束、例子。
例子

「你是一位细致的编辑。把这张工单压缩成 3 条要点,用简单的话。下面是一个好结果的样例:……」

代价
几乎没有——你只需要想清楚自己要什么。
何时使用
总是。它是阶梯的第一级。
关联
分成 System prompt 和用户 prompt;用 Few-shot 例子来加强。

System prompt vs user prompt——长期规则与当次请求

一家餐厅的长期规定——「我们是素食餐厅,十点打烊」——对比今晚的具体点单。一个给一切定下框架;另一个才是请求本身。

system prompt 设定持久的行为——角色、规则、语气——在整个对话里始终有效。user prompt 是具体的请求。把你的人设和 guardrails 放进 system prompt,就能在用户消息不断变化时让它们保持稳定。

System promptrole · rules · tone — holds for the whole conversationUser: turn 1“reset my password”Reply 1User: turn 2“and my email?”Reply 2User: turn 3“thanks!”Reply 3applies to every turn
system prompt 给每一轮定下框架;user prompt 每一轮都在变。
TermSystem prompt· 长期指令
是什么
对整个对话都有效的持久指令:角色、规则、语气。
例子

系统:「你是一家商店的客服机器人。回答要简短;不要承诺超出政策范围的退款。」用户:「我的订单在哪?」

陷阱
它不是一把锁:用户可能试图绕开它——你仍然需要 Guardrails。
何时使用
任何需要在多轮之间保持稳定的东西,都放这里。
关联
Prompt 的一部分;位于 Context window 的开头。

Few-shot prompting——光说不如演示

教人一种格式,给他看三个做好的样例,比用话描述它更快、更清楚。

想要得到你要的那种回答形态,最好的办法往往是直接在 prompt 里放几个例子,写明输入和期望的输出。这就是 few-shot prompting。模型对这些例子做模式匹配,比遵循一段抽象的描述要好。两三个好例子,可以胜过一大段说明。

Prompt“Late again!”example 1negative“Love it”example 2positive“Works fine”new input?positivefollows the pattern
prompt 里有两个「输入 → 输出」例子——模型会对新的输入延续同一个模式。
TechniqueFew-shot prompting· prompt 里的例子
问题
某种格式或风格很难用话描述清楚。
思路
直接在 prompt 里给出 2–3 对「输入 → 期望输出」。
例子
「'又晚了!' → 负面;'太喜欢了' → 正面;'还行' → ?」
代价
例子占窗口的空间;一个坏例子会教出坏习惯。
何时使用
当你需要一个确切的形态、语气或分类时。
关联
Prompt 的一部分;常与 Structured output 搭配。

Structured output——要一种你的代码能用的结构

带标注格子的表单,给你的是可填写的数据;「给我写一段关于它的话」,给你的是你还得再去解析的散文。

如果你的程序要消费这个输出,就要求结构化输出(structured output)——符合某个 schema 的 JSON,而不是自由文本。现代模型可以被约束为输出合法的 JSON,这就把 LLM 从一个聊天机器人,变成了你的代码可以依靠的一个组件。Structured output 是连接语言与软件的桥梁。

LLMFree text“Sure! Order 42 is running late…”Parse?regex and hopeJSON · matches a schema{ "order_id": 42, "status": "late"}Your codevalidated ✓
自由文本只能靠猜来解析;符合 schema 的 JSON 可以被校验,并直接交给代码。
PatternStructured output· JSON 模式、按 schema 输出(JSON mode, schema output)
问题
代码无法可靠地解析自由形式的散文。
思路
把回答约束到一个 JSON schema,并在使用前校验。
例子
{"order_id": 42, "status": "late"},而不是「您的订单 42 正在延误……」。
代价
你得定义 schema,还要处理校验失败的情形。
何时使用
只要读这个回答的是程序而不是人。
关联

Tool use 的基础(一次工具调用就是 structured output);抵御 Hallucination 的一层防线。

没有魔法词。好的 prompt 就是一份清晰的说明——角色、任务、约束、例子。

§ 03

随着应用变得严肃,手艺会从斟酌 prompt 的措辞,转向组装正确的 context。这才是真正的学问——「context engineering」。

Context engineering——你往窗口里放什么

律师赢官司,靠的不是巧妙的措辞,而是把恰好正确的文件、按正确的顺序、不带任何无关内容地交给法官。

Prompt engineering 讲的是措辞;context engineering 讲的是为每一次调用,把正确的信息——相关的事实、历史和工具——组装进窗口。模型的回答,只会和你放在它面前的东西一样好。大多数质量问题是 context 问题,而不是措辞问题。

InstructionsChat historyYour docsUser dataTool resultsSelect & assemblepick what mattersContextwindowLLMthe answer is only as good as what you put in front of the model
从众多来源里挑出重要的,组装成窗口——每次调用都是新的。
PracticeContext engineering· 组装窗口
问题
prompt 措辞很好,模型却答得很差。
思路
每次调用,都把恰好需要的东西放进窗口:指令、事实、历史、工具。
例子
客服机器人拿到的不是整个知识库,而是退款政策、订单状态和客户的问题。
代价
你需要写代码来挑选和组装 context——这才是真正的活儿。
何时使用
只要应用不止一个简单 prompt,就该用。
关联

填充 Context window;RAG 是它主要的事实供应者;受 Context budget 约束。

Relevance over completeness——少,但要少得对

一页精炼的简报,胜过 200 页的堆砌——读者能找到信号,而不是淹没其中。

context 并非越多越好。每个 token 都要配得上它的位置:无关的文本会稀释模型的注意力、花掉钱,而且在长 context 里实际上会提高幻觉的概率。真正的本事,是挑出少数重要的东西,而不是把一切可能有用的都塞进去。

Stuffed windowCurated windowRefund policy §2Order #42 statusUser questionattention diluted · cost ↑ · hallucination ↑every token earns its place
左:塞满的窗口,信号淹没在噪声里。右:只放答案需要的东西。

Context budget——窗口就是一笔预算

一只有重量限制的行李箱——你装的是真正会用到的东西,而不是整个衣柜,因为有硬性上限,还有罚款。

窗口是有限的,每个 token 都要花延迟和金钱。所以你要有意识地花它,把它当作一笔 context budget:裁剪历史,把旧内容做摘要,只检索眼下相关的东西。把 context 当作稀缺的预算——而不是无底的垃圾桶——正是玩具和产品的分水岭。

Context window = a fixed token limitSystemHistory (summarized)RetrievedToolsUserAnswer roomhard capTrimdrop old turnsSummarizecompress historyRetrieveonly what's relevantCachereuse stable prefix
窗口被分给各个部分,并撞上硬性上限。四个杠杆:裁剪、摘要、检索、缓存。
ConceptContext budget· token 预算
是什么
窗口的 token 上限,由 system prompt、历史、事实和回答共同分享。
例子
一段很长的聊天:旧的几轮被压缩成一段简短的摘要,而不是每次都完整地发送。
陷阱
token 越多越贵、越慢——而且不一定更好。
怎么办
裁剪、做摘要、只检索需要的内容、缓存稳定的部分。
关联
约束 Context engineering;直接决定 Cost & latency。

Prompt engineering 是措辞。Context engineering 是文件。质量就在后者里。

§ 04

模型不了解你的数据,也不了解训练截止日期之后的任何事。RAG 就是你把事实交给它、让它据此作答的办法——严肃的 LLM 应用里最重要的一个模式。

RAG——Retrieval-Augmented Generation:先检索,再回答

一场开卷考试——不靠记忆,而是先翻出相关的几页,再根据眼前的内容写出答案。

Retrieval-Augmented Generation(RAG) 的意思是:拿到用户的问题,取回你文档中最相关的片段,放进 context,然后要求模型据此回答。这样它依据的是你真实的数据,而不是它模糊的记忆。助手就是这样回答关于你的产品、你的文档、你的知识库的问题的。

QuestionRetrieverembed + searchVector DByour docs as chunksTop-k chunksmost relevantPromptquestion + chunksLLMAnswerwith citations1 · retrieve the facts → 2 · answer from them
问题 → 搜索你的文档 → 最好的片段连同问题一起进入 prompt → 带引用的回答。
PatternRAG· Retrieval-Augmented Generation
问题
模型不了解你的数据,也不了解训练截止日期之后的事——还会胡编。
思路
先找出你文档里正确的片段,再只根据它们来回答。
例子
文档机器人找到 3 个匹配的帮助中心章节,据此作答,并附上引用。
代价
你需要 chunking、索引、搜索——而且它们的质量必须被衡量。
何时使用
当回答必须建立在你的数据或最新事实之上时。
关联

基于 Embeddings 运行;带来 Grounding;为 Context engineering 供料。

Embeddings——按含义做向量搜索

一位图书管理员,按书讲的是什么来找书,而不是按确切的书名——「类似这样的东西」,按含义来找。

要找到相关的片段,你把文档存成 embeddings(捕捉一段文本含义的向量),放进向量数据库,再按与问题的相似度来搜索(也就是数据库课程里讲的那个引擎)。好的检索是 RAG 的核心:放进来的片段对了,回答就有依据;放进来的是垃圾,模型就会自信地从垃圾里作答。

refund policymoney backreturn an itemopening hoursoffice timesquery: “how do I get my money back?”close in meaning = close in space · search = nearest neighbours
含义相近的文本彼此靠得很近。搜索就是找出问题的最近邻。
ToolEmbeddings· 向量搜索
是什么
文本 → 一串数字组成的向量;含义相近的文本,向量也相近。
例子
「怎么把钱要回来?」能找到「退款政策」那一节,尽管两者几乎没有共同的词。
陷阱
含义相近,并不保证这个片段就能回答问题。
何时使用
在 RAG 里按含义搜索,而不是按确切的词。
关联
RAG 的引擎;质量取决于 Chunking。

Grounding——能追溯到出处的回答

一位每个论断都必须注明出处的记者,编造的东西要比凭记忆写作的记者少得多。

RAG 的最大好处是 grounding:因为回答取自检索到的文本,你可以要求引用,并核实各个论断确实有依据。它不会抹去幻觉,但会大幅削减它——还能让你抓住漏网的那些。能追溯到出处的回答,才是你能信任的回答。

AnswerRetrieved sourcesRefunds within 30 days [1]Ships to the EU [2]Free return shipping [?]Source 1refund-policy.md §2Source 2shipping.mdNo source foundflag or drop the claimevery claim traces to a source → you can check it
每个论断都指向一个出处。没有出处的论断是个信号:标出来,或者丢掉。
PracticeGrounding· 引用
问题
你无法核实模型的某个论断是从哪里来的。
思路
只根据检索到的文本作答,并在每个事实下面注明出处。
例子
「30 天内可退款 [1]」——其中 [1] = refund-policy.md。
代价
引用必须被核查;回答会变得更谨慎。
何时使用
凡是答错代价很高的地方:金钱、法律、健康、客服。
关联
RAG 的回报;抵御 Hallucination 的主要防线。

Chunking & retrieval quality——垃圾进,自信的垃圾出

把错的文件递给某人,让他做总结——他会给你一份完美的、关于错误内容的总结。

RAG 只有在检索有效时才有效。糟糕的 chunking、薄弱的搜索、过时的数据——模型就会忠实地从错误的 context 里作答,听起来一样笃定。所以 RAG 里大部分的精力不在模型上;而在 chunking、索引,以及衡量检索质量。先修好检索,再去怪模型。

DocsChunkIndexRetrieveLLMthe RAG pipelinestale databad splitsweak searchConfident wrong answer
模型之前的任何一步都可能出错——结果听起来依然很自信。
PracticeChunking & retrieval quality· RAG 不起眼的另一半
问题
模型自信地从错误的片段里作答。
思路
把文档切好,让索引保持新鲜,并单独衡量搜索是否找到了正确的东西。
例子
一张价格表被从中间切开——模型看到了价格,却没看到套餐名称,于是搞混了。
代价
不起眼的数据活儿,占去了 RAG 的大部分工作量。
何时使用
只要你用 RAG,就总是要做。先修检索,再修模型。
关联
决定 RAG 和 Embeddings 的质量;由 Evals 来检验。

别去问模型它知道什么。把事实交给它,让它据此作答。

§ 05

prompt 产出的是文本。要让模型去做事——搜索、计算、发送、查询——你就给它 tool;要让它跨越许多步骤去追求一个目标,你就把它放进一个循环。这就是 agent。

Tool use——function calling:让它调用你的函数

一位聪明的助理,自己够不到档案柜——但可以请你去拿,并准确告诉你该抽哪一份。

用 tool use(function calling),你描述模型可以请求的函数——search_orders、send_email、get_weather——当它想用其中一个时,它返回一个结构化的调用,你的代码去执行,再把结果喂回给它。模型决定做什么;怎么做仍由你的代码掌控。这就是 LLM 如何从文本延伸到真实世界。

LLMYour codeOrders APIquestion + tool listtool_call: search_orders(42)GET /orders/42{ status: late }tool resultfinal answer
模型只是请求一次工具调用。你的代码来执行它——再把结果交还给模型。
PatternTool use· function calling
问题
光靠文本,查不了订单、算不了数、发不了邮件。
思路
描述函数;模型返回一个结构化调用;你的代码执行它并返回结果。
例子

「订单 42 在哪?」→ 模型请求 search_orders(42) → 代码调用 API → 模型作答。

代价
每多一个工具,就多一种在真实世界里出错的方式。
何时使用
当回答需要实时数据或一次操作时。
关联
建立在 Structured output 之上;是 Agent loop 的构件。

Agent loop——agent 就是循环中的模型

一个人解决问题:想一想、采取一个行动、看看结果、再想一想——反复进行直到完成,而不是一步到位。

agent 把模型接进一个循环——推理、调用工具、观察结果、再推理(即 agent loop)——由 LLM 作为编排者,决定每一步接下来做什么。这让它能处理开放式的任务(「调研一下这个,并起草一封回复」),这是任何单个 prompt 都做不到的。编程助手和调研机器人就是这样工作的。

Goalopen-ended taskReasonwhat next?Actcall a toolObserveread the resultrepeatgoal metDone
推理 → 行动 → 观察,再来一轮——直到目标达成。
PatternAgent loop· agent
问题
任务无法一步完成:得搜索、尝试、再修正。
思路
让模型处在「想 → 做 → 看」的循环里,每一步由它自己选。
例子
编程助手读一个文件,编辑它,跑测试,看到失败,再编辑。
代价
不可预测:它可能乱绕、重复自己,或者把成本推高。
何时使用

只有当任务确实需要许多自适应的步骤时。否则——一次调用,或者一条固定的链。

关联
由 Tool use 构成;需要 Memory 和 Human-in-the-loop。

Memory——窗口之外的记忆

一个长期项目需要一本笔记本——你没法把几个月的工作都装在脑子里,所以把要紧的写下来,需要时再翻出来。

因为窗口是有限的,agent 需要 memory:把笔记、摘要和可检索的历史保存在 context 之外,相关时再取回来。没有它,agent 到一项长任务结束时,就忘了开头。Memory 让一场聊天变成能够随时间推进去工作的东西。

Long taskstep 1 … step 80Agentsmall windowMemory storeNotesSummariesPast stepswritepull back what's relevantwithout memory, the agent forgets the start by the end
agent 把要紧的内容写进外部存储,只取回眼下需要的那部分。
PatternAgent memory· 窗口之外的记忆
问题
长任务装不进窗口——agent 忘了开头。
思路
把笔记和摘要放在窗口之外;需要时再按需取回。
例子
每个阶段之后,agent 写下「做完了什么、接下来做什么」,下一步再把它读回来。
代价
又多了一个系统:写什么、取什么、忘什么。
何时使用
用于一个窗口装不下的长任务。
关联
扩展 Context window;取回方式与 RAG 相同;Agent loop 需要它。

Human-in-the-loop——循环很强大,所以要拴上缰绳

一台扫地机器人,大多数时候把家打扫得很好,但偶尔会卡在墙角原地打转,或者一头扎进泳池。

agent loop 是不可预测的:它可能走错路、重复自己、推高成本,或者依据一个糟糕的决定去行动。所以你要给它拴上缰绳——步数上限、工具权限、对高风险操作要有人工批准(human-in-the-loop)、完整的日志。 只有当任务确实需要许多自适应的步骤时,才去用 agent;一次调用或一条固定的链够用时,它更便宜也更安全。

Step limitstop after N stepsTool permissionsallow-list onlyLoggingevery step recordedAgent loopHuman approvalbefore risky actionsReal worldsend_email · refundWithout a leashwrong turns · loops · runaway cost · bad actions
agent 的缰绳:步数上限、工具白名单、日志,以及任何高风险操作之前的一个真人。
PracticeHuman-in-the-loop· agent 的缰绳
问题
agent 可能误做一个昂贵或不可逆的操作。
思路
步数上限、允许的工具、日志——并由真人确认高风险操作。
例子
agent 准备好一笔退款,但要等操作员点了批准才会发出。
代价
更慢,还需要人——但错误永远不会流到现实世界。
何时使用
在任何昂贵或无法撤销的操作之前。
关联
约束 Agent loop 和 Tool use;Guardrails 的近亲。

tool 让模型能行动。循环让它能坚持。两者都需要缰绳——没有限制的能力,就是一种负担。

§ 06

一个只能跑通一次的演示很容易。一个值得信赖的系统,需要那些不起眼的功夫——衡量、约束,以及盯着一个天生非确定性的组件。

Evals——无法衡量的,就无法改进

一所从不给任何人打分的学校,不知道谁在学、谁没学——也就没法变好。

eval 是你的 AI 的一套测试:带有已知正确期望的输入,自动打分——它检索到正确的文档了吗、调用了正确的工具吗、回答忠实吗?没有 eval,你调 prompt 就是凭感觉。还要有心理准备面对一个残酷的事实:把质量做到 80% 很快;从那里再磨到 95%,才是大部分的工作。

Test setinput + expectedYour AIprompt · RAG · toolsScorerauto-gradedScore82%change the prompt → re-run → compareQuality0 → 80%: quick80%95%80 → 95%: most of the workno evals = tuning prompts by vibes
测试集 → 你的系统 → 自动打分。改一下 prompt,重新跑,对比。
PracticeEvals· AI 的测试集
问题
你说不清改了 prompt 之后是变好了还是变差了。
思路
一组带预期结果的输入,加上一个自动的质量评分。
例子
50 个真实的客服问题:检查是否找到了正确的文档,回答是否正确。
代价
你得建立并维护这组数据——持续的工作。
何时使用
在你开始调 prompt 之前。没有 eval,就是凭感觉。
关联

对 Non-determinism 的回答;衡量 RAG、Tool use、Agent loop。

Guardrails——输入和输出两侧的边界

保龄球道上的护栏——它们不替你滚球,但能让球不掉进沟里。

Guardrails 是围绕模型的检查:在入口一侧,拦截 prompt injection 和超出范围的请求;在出口一侧,过滤不安全的内容,并在结果到达用户或另一个系统之前校验格式。它们在你的代码里,在模型之前和之后运行——因为你不能指望模型自己监督自己。

your code, before and after the modelInputInput guardinjection · off-topicLLMOutput guardunsafe · bad formatOutblockedfixed / blocked
入口一道检查,出口一道检查——在你的代码里,位于模型的两侧。
PatternGuardrails· 输入与输出检查
问题
你无法让模型可靠地监督自己。
思路
在模型之前检查输入,在模型之后检查输出——用普通的代码。
例子

入口:拒绝「忽略之前所有指令,然后……」。出口:按 schema 校验 JSON,并剔除不安全的文本。

代价
额外的延迟,以及误报。
何时使用
生产环境里总是要用,尤其是输出会到达人或系统时。
关联

为 System prompt 兜底;检查 Structured output;抓住 Hallucination。

Cost & latency——是设计约束,不是事后补想

一个全程跳动的出租车计价器——每多一公里的 context、每多一个步骤,都在增加车费和等待。

每个 token 都要花钱、花时间,而且成本随你发送的 context 量和调用次数而增长。所以你要围绕它来设计:裁剪并缓存 context,选足够好的最小模型,在一次调用就够用的地方别跑 agent loop。一个太慢或太贵的好回答,不算好回答。

cost ≈ tokens per call × number of callsOne call, trimmedWhole KB every callAgent loop, many stepsTrim contextCache prefixSmaller modelFewer callslevers:
成本 ≈ 每次调用的 token 数 × 调用次数。四个把它压下来的杠杆。
ConstraintCost & latency· 每次调用的钱和时间
是什么
每次调用的钱和时间;它们随 context 和调用次数增长。
例子
每次调用都发送整个知识库,或者在一次调用就够的地方跑 agent,又慢又贵。
陷阱
一个太慢或太贵的好回答,不算好回答。
怎么办
裁剪并缓存 context,选足够好的最小模型,少调用几次。
关联
被 Agent loop 推高;通过 Context budget 来管理。

Hallucination defense——你要围绕它来设计的风险

你不会把话筒交给一位才华横溢却不可靠的叙述者,还不加监督——付印之前,你要先核实事实。

这里的每一项技术——用 RAG 做 grounding、结构化输出、evals、guardrails、引用——都是为了管住一个核心风险:模型把错误的话说得令人信服。 你永远无法彻底消除它;你限定它可能发生的范围,发生时把它检测出来,并且绝不让一个未经核实的论断到达答错代价很高的地方。这是纵深防御:每一层都能抓住一部分错误。

model output — may contain a false claimGrounding · RAG + citationscaughtStructured output · schemacaughtGuardrails · in and outcaughtEvals · measured over timecaughtTrusted output
层层防御:每一层都抓住一些错误论断,所以到达用户的内容是经过检查的。

演示信任模型。产品则要衡量它、约束它、盯着它——因为它天生就是非确定性的。

§ 07

这些模式从简单到复杂层层叠加。真正的本事,是用能解决你问题的最不强大的那一个——并把模型当作一个组件,而不是架构本身。

Complexity ladder——只在不得不爬的时候才往上爬

你不会为了把一个箱子搬过房间而订一辆搬家卡车。你让投入和活儿相称。

有一道阶梯:一个好的 prompt,然后是 structured output,当它需要你的事实时用 RAG,再然后是 tool,最后是一个完整的 agent loop——当任务确实需要许多自适应的步骤时。每一级都增加能力、成本和新的失败方式。从底部开始,只有当问题逼着你时才往上爬——大多数功能根本用不到顶层。

power · cost · ways to fail ↑Promptone good callStructuredoutputRAGyour factsToolsact in the worldAgent loopmany stepsstart here
五级:越高的一级越强大、越昂贵、也越脆弱。从第一级开始。
PrincipleComplexity ladder· 够用就行的最小能力
问题
明明一个 prompt 就够了,却很容易想去造一个 agent。
思路
Prompt → Structured output → RAG → Tools → Agent loop;被逼着才往上爬。
例子

工单分类:一个带 structured output 的 prompt 就够了——不用 RAG,不用 agent。

代价
每一级都增加成本和新的出错方式。
何时使用
为任何 LLM 功能选择方案时。
关联

把 Prompt、Structured output、RAG、Tool use、Agent loop 串起来。

LLM as a component——是组件,不是架构

汽车有一台强劲的发动机,但它被装在防火墙后面,喂的是干净的燃料,周围还有刹车——它不是整辆车。

把模型放在一个接口后面,像对待其他任何依赖一样,在它的输入和输出周围做校验,并保留更换模型或供应商的自由。LLM 是你系统里一个强大却不可靠的部件——而不是它的地基。(这和系统设计里「LLM 是适配器,而不是架构」的是同一个教训。)

Your systemApp codeInput checksLLM interfacecomplete(prompt) → JSONOutput validationProvider AadapterProvider BadapterLocal modeladapterswap the model without touching the app
应用与一个接口对话;供应商以适配器的形式接入;输入和输出都要经过检查。
PrincipleLLM as a component· LLM 即适配器(LLM as an adapter)
问题
代码和某一个模型焊死在一起,并直接信任它的回答。
思路
模型放在它自己的接口后面,输入和输出都有检查。
例子

应用调用 complete(prompt);在它背后,你可以把供应商 A 换成 B,或者换成本地模型。

代价
一层薄薄的抽象。
何时使用
总是——从第一天起。
关联

用到 Structured output 和 Guardrails;和 Hexagonal(端口与适配器)是同一个思想。

这一切如何关联起来

一支管弦乐队:乐器各不相同,但共同演奏,而且彼此支撑。

这些概念不是孤立存在的。Embeddings 为 RAG 提供搜索;RAG 为 Context engineering 供给事实,后者填充 Context window。RAG 促成 Grounding,而 grounding、Guardrails 和 Evals 合力把 Hallucination 控制住。Structured output 是 Tool use 的基础,工具构成 Agent loop,而 Memory 延长它的寿命。

EmbeddingsRAGContext engineeringContext windowStructured outputGroundingGuardrailsHallucinationTool useAgent loopMemoryEvalspowerssupplies factsfillsenablesreducesblockscatchshapes callsused inextends
本课各概念之间的主要联系。
在交付一个 LLM 功能之前
  • 最简单的那一级是什么——prompt、structured output、RAG、tool、agent——哪一级能解决这件事?
  • 事实从哪里来——模型的记忆(有风险),还是检索到的、可引用的数据?
  • 它答错时会怎样,而那个地方是答错代价低还是高?
  • 我怎么衡量质量——eval 是什么?
  • 输入和输出上的 guardrails 是什么?
  • 每次调用要花多少钱,有多慢?
说明你过度构建了的嗅探信号
  • 为一个单个 prompt 就能回答的事,上了一个 agent loop。
  • 对三份你直接贴进 prompt 就行的文档,上了 RAG。
  • 凭感觉调 prompt,没有 eval 来告诉你有没有变好。
  • 每次调用都把整个知识库发进 context。
  • 把模型的输出未经校验就直接写进数据库或发进邮件。
说明你造得好的信号
  • 输出在你的代码使用之前,是结构化且经过校验的。
  • 回答是有依据、可引用的,而不是凭空捏来的。
  • 你有一个 eval,能告诉你一次改动是帮了忙还是添了乱。
  • 输入和输出两侧都有 guardrails。
  • 你用的是够用的最简单的一级——而且模型放在一个你可以替换的接口后面。

速查表:全部 24 个概念

模型

Next-token prediction下一个 token 预测器

模型生成一个可能性高的接续;它不查事实。

Context window工作记忆

模型唯一的记忆——这次调用的文本。

Hallucination自信地编造

流畅、看似合理的捏造。无法消除,只能限定。

Non-determinism同样的输入,不同的输出

一个输入,多种输出。所以要检查、要衡量。

Prompting

Prompt任务说明

一份清晰的说明:角色、任务、约束、例子。

System prompt长期指令

对整个对话有效的持久规则;user prompt 是具体的请求。

Few-shot promptingprompt 里的例子

用 2–3 个「输入 → 输出」例子,代替一大段解释。

Structured output按 schema 输出 JSON

一个形态能被代码校验和使用的回答。

Context

Context engineering组装窗口

每次调用,都把恰好需要的东西放进窗口。

Relevance over completeness少,但要对

多余的文本会稀释注意力,并提高幻觉的概率。

Context budgettoken 预算

窗口是稀缺的预算:裁剪、摘要、缓存。

事实(RAG)

RAGRetrieval-Augmented Generation

先找出你文档里正确的片段,再据此作答。

Embeddings向量搜索

按含义搜索:相近的文本就是相近的向量。

Grounding引用

每个论断都指向一个出处——所以可以被核查。

Chunking & retrieval qualityRAG 不起眼的另一半

垃圾进,自信的垃圾出。先修检索。

Agent

Tool usefunction calling

模型请求一次函数调用;你的代码来执行它。

Agent loopagent

处在「想 → 做 → 看」循环里的模型。

Agent memory窗口之外的记忆

笔记和摘要放在窗口之外,按需取回。

Human-in-the-loopagent 的缰绳

步数上限、权限、日志,以及高风险操作之前的一个真人。

可靠性

EvalsAI 的测试集

给你的 AI 做的测试:没有它们,你就是凭感觉在调。

Guardrails输入与输出检查

模型前后的代码:拦截、过滤、校验。

Cost & latency每次调用的钱和时间

token × 调用次数。是设计约束,不是细节。

把它造好

Complexity ladder够用就行的最小能力

Prompt → structured output → RAG → tool → agent。被逼着才往上爬。

LLM as a componentLLM 即适配器

模型是系统里一个可替换的部件,而不是它的地基。

用 LLM 来构建,不是 prompt 的魔法。它是普通的工程——context、检索、校验、evals——围绕着一个非凡却不可靠的组件。

速成课结束 · 7 章 · 24 个概念

接下来是实践:去读你所用模型供应商的文档——Anthropic 和 OpenAI 关于 prompting、tool use 和 evals 的指南——然后从头到尾做一个小东西:先是一个 prompt,再是一个 RAG,再是一个工具。但要把一个观点放在所有观点之上。模型是容易的部分。围绕它的工程——context、grounding、衡量、限制——才是一个真正的产品被造出来的地方。