速成课 · No. 07
一个语言模型,是个出色的「下一个词」猜测器——没有记忆,还动不动就胡编。用它来构建,靠的不是什么魔法 prompt,而是你围着这个强大却不可靠的部件所做的那层工程,好让它变得值得信赖。
只讲精髓 · 每个想法一幅画面 · 工程重于魔法
在用语言模型构建之前,先弄明白它究竟是什么——因为几乎每一个错误,都源于期待它成为它本不是的那种东西。
它在预测下一个词,而且预测得极好
你手机键盘在猜下一个词——但放大到极致,以至于它能写一篇文章、调一段代码、讲明白物理,一次一个看似合理的词地往下推。
LLM 是一个下一个 token 的预测器,在海量人类文本上训练而成。它不去查东西;它生成统计上最可能接下来出现的内容。这就是为什么它在语言和推理模式上令人惊叹——也是为什么它不是一座事实的数据库。它产出的是听起来对的东西,这通常是对的,有时却是自信满满地错的。
它在两次调用之间没有记忆
一位才华横溢却彻底失忆的顾问——每一次开会,你都得把每一份文件重新递给他一遍,因为他对上次的事什么都不记得。
模型在两次请求之间什么都不记得。它唯一的工作记忆,就是上下文窗口——你在这次调用里发进去的文本。对话历史、你的数据、你的指令:只要不在 context 里,模型就不知道。这门课里的一切,在某种意义上,都是关于你往那个窗口里放什么。
它会胡编——而且自信满满
晚宴上一位迷人的万事通,他宁可编出一个有说服力的答案,也不愿承认自己不知道。
当模型不知道时,它不会停下——它会产生幻觉,以与真相同样的自信,产出流畅、看似合理、却是错的文本。这不是你能彻底打补丁修掉的 bug;它就是一个猜测器的本性。这门课里大部分工程的存在,都是为了驾驭这一个事实。
它是非确定性的——就按这个来对待它
把同一个问题问十位专家——你会得到十个略有不同的好答案,而不是一个一模一样的回复。
同一个 prompt 每次都可能给出不同的输出。所以你不能把 LLM 当成一个返回值固定的函数;你把它当作聪明、易错、非确定性的输入——要去约束、去校验、去核查,而绝不盲目信任。这种心态,就是整盘棋的关键。
LLM 并不知道东西。它在预测东西。把其余的一切,都围着这一个真相去造。
prompt 是你告诉模型你想要什么的方式。指令越清楚,输出越好——而大多数「这 AI 真笨」的时刻,其实都是 prompt 不清楚。
prompt 是一份任务简报,不是一道咒语
把一项活儿交给一位精明的新人:他要扮演谁、你想要什么、有哪些约束,以及一个「好」长什么样的例子。简报含糊,结果就含糊。
一个好的 prompt 会写明角色(「你是一位严谨的编辑」)、任务、约束(长度、语气、格式),最好还有一个例子。没有什么魔法词——只有清楚的指令,就跟你交代一个能干的人一样。大多数 prompt 问题,其实都是说明不清的问题。
system 与 user:常驻规则 对上 这一次的请求
一家餐厅的常驻规矩——「我们只做素食,我们十点打烊」——对上今晚这一桌具体的点单。一个为一切定下框架,另一个才是这次的要求。
system prompt 设定持久的行为——角色、规则、语气——它在整段对话里都成立。user prompt 则是那个具体的请求。把你的人设和 guardrails 放进 system prompt,能让它们保持稳定,而 user 消息则各不相同。
给它看,而不只是讲:few-shot 例子
教人一种格式时,给他看三个做好的例子,比用文字描述更快、更清楚。
通常,要得到你想要的那种答案形状,最好的办法是直接在 prompt 里放进几个例子,展示输入和期望的输出(「few-shot」)。模型对它们做模式匹配,比遵循一段抽象描述要好得多。两三个好例子,能胜过一整段指令。
要一种你的代码能用的结构
一张带标注方框的表格,给你的是能填的数据;而「给我写一段关于它的话」,给你的是你之后还得自己解析的散文。
如果你的程序要消费这份输出,那就要结构化输出——匹配某个 schema 的 JSON,而不是自由文本。现代模型能被约束成只产出合法的 JSON,这就把 LLM 从一个聊天机器人,变成了一个你的代码可以依赖的部件。结构化输出,是语言与软件之间的那座桥。
没有魔法词。一个好的 prompt 是一份清楚的任务简报——角色、任务、约束、例子。
当应用动真格时,功夫就从斟酌 prompt 的措辞,转向组装对的 context。这才是真正的功夫——「context engineering」。
难的是你往窗口里放什么
一位律师赢下官司,靠的不是巧妙的措辞,而是把恰好对的文件、按对的顺序、不夹一份无关的,交到法官手里。
「prompt engineering」讲的是措辞;context engineering 讲的是为每一次调用,把对的信息——相关的事实、历史与工具——组装进那个窗口。模型的答案,只能好到你摆在它面前的东西那个程度。大多数质量问题,是 context 问题,而不是措辞问题。
相关性胜过完整性
一份锋利的一页纸简报,胜过一坨两百页的倾倒——读者能找到信号,而不是淹死在里头。
context 不是越多越好。每一个 token 都该挣得它的位置:无关的文本会稀释模型的注意力、花掉真金白银,而且在长 context 里实际上会抬高产生幻觉的概率。功夫在于挑出那几样要紧的,而不是把一切可能有用的都塞进去。
上下文窗口是一份预算
一个有重量上限的行李箱——你只装你真正会用到的,而不是整个衣柜,因为那里有一个硬性的封顶和一笔超重费。
窗口是有限的,而每一个 token 都要花掉延迟和钱。所以你要刻意地去花它:裁剪历史、把旧的总结掉、只检索此刻相关的。把 context 当作一份稀缺的预算——而不是一个无底的倾倒场——正是把一个玩具和一个产品区分开来的东西。
prompt engineering 是措辞。context engineering 是文件。质量住在第二个里。
模型不知道你的数据,也不知道它训练截止之后的任何事。RAG 就是你把事实交给它、让它据以作答的方式——是严肃的 LLM 应用里那个最重要的模式。
RAG:先检索,再作答
一场开卷考试——你不靠记忆,而是先翻出相关的那几页,再照着眼前的东西把答案写出来。
Retrieval-Augmented Generation 的意思是:拿起用户的问题,取出你文档里最相关的那几个片段,把它们放进 context,再让模型照着它们来作答。现在它是照着你真实的数据在工作,而不是它那模糊的记忆。这就是助手如何回答关于你的产品、你的文档、你的知识库的问题。
embeddings 和向量搜索找出对的片段
一位图书管理员,他靠书讲的是什么、而不是靠确切的书名来找书——「跟这个类似的东西」,按含义来找。
要找出相关的片段,你把文档以 embeddings 的形式存进一个向量数据库,再按与问题的相似度来搜索(这正是数据库那门课里的那个引擎)。好的检索是 RAG 的心脏:把对的片段送进去,答案就有了 grounding;把垃圾送进去,模型就会自信满满地照着垃圾作答。
grounding 杀死幻觉——大体上
一位必须为每一句论断都引用来源的记者,比一位凭记忆写稿的记者,捏造的东西要少得多。
RAG 的最大收益是 grounding:因为答案是从检索到的文本里抽出来的,你可以要求引用,并核查那些论断是否真的有据可依。它并没抹掉幻觉,但把它砍掉了一大截——还让你能逮住那些漏网的。一个你能追溯到来源的答案,才是一个你能信任的答案。
垃圾进,自信的垃圾出
把错的文件递给某人、让他总结——他会给你一份对那个错东西的完美总结。
RAG 只有在检索奏效时才奏效。糟糕的切片、孱弱的搜索、陈旧的数据——模型就会忠实地照着错的 context 作答,听起来一样笃定。所以 RAG 里大部分的功夫不在模型上;而在于切片、建索引,以及度量检索质量。先把检索修好,再去怪模型。
别问模型它知道什么。把事实交给它,让它照着那些来作答。
一个 prompt 产出文本。要让模型去做事——搜索、计算、发送、查询——你给它 tool;要让它跨许多步去追求一个目标,你把它放进一个循环。那就是 agent。
tool use:让它调用你的函数
一位聪明的助手,自己够不着文件柜——但他能让你去够,并准确告诉你该抽哪一份。
有了 tool use(function calling),你描述模型可以请求的函数——search_orders、send_email、get_weather——当它想用某一个时,它返回一个结构化的调用,你的代码去执行它,再把结果喂回去。模型决定做什么;你的代码则牢牢掌控怎么做。这就是 LLM 如何越过文本、伸进真实世界。
agent 是放进循环里的模型
一个人在解决问题:思考、采取一个行动、看结果、再思考——一直重复到做完,而不是一锤子买卖。
一个 agent 把模型接进一个循环——推理、调用一个 tool、观察结果、再推理——由 LLM 作为编排者,决定下一步每一步。这让它能处理那些开放式的任务(「研究这个,再起草一封回复」),那是任何单个 prompt 都搞不定的。编程助手和研究机器人,都是这么工作的。
窗口之外的记忆
一个漫长的项目需要一个笔记本——你没法把几个月的工作都装在脑子里,所以你把要紧的写下来,再回头去查。
因为窗口是有限的,agent 需要记忆:笔记、总结,以及可检索的历史,存在 context 之外,在相关时再拉回来。没有它,一个 agent 到了一项长任务的末尾,就会忘了它的开头。记忆,正是把一段聊天,变成某种能跨时间工作的东西。
循环很强大——也是一种隐患
一台扫地机器人,大体上能把屋子打扫干净,但偶尔会卡在某个角落里打转,或者一头扎进泳池。
一个 agent 循环是不可预测的:它会走错路、原地打转、把成本飙上去,或者照着一个糟糕的决定行事。所以你给它拴根绳——步数上限、tool 权限、对高风险动作的人工批准、完整的日志。只在一项任务真的需要许多自适应步骤时,才去够 agent;能用一次调用或一条固定的链搞定时,那样更便宜也更安全。
tool 让模型能行动。循环让它能坚持。两者都需要一根绳——没有限度的能力,就是一种隐患。
一个能跑通一次的 demo 很容易。一个你能信任的系统,要靠那些不起眼的功夫——去度量、去框定、去盯住一个生来就非确定性的部件。
eval:你没法改进你没去度量的东西
一所从不给任何人打分的学校,不知道谁在学、也无从变好。
一个 eval,是为你的 AI 准备的一套测试:带有已知好结果的输入,自动打分——它检索对了文档吗?调用对了 tool 吗?忠实地作答了吗?没有 eval,你就是在凭感觉调 prompt。还要做好面对一个硬道理的准备:做到 80% 的质量很快;从那里一点点磨到 95%,才是大部分的活儿。
guardrails:对输入和输出的边界
保龄球道两侧的护栏——它们不替你把球扔出去,但能让球别掉进沟里。
guardrails 是围着模型的那些核查:进来的路上,挡住 prompt-injection 和越界的请求;出去的路上,过滤不安全的内容,并在它到达用户或另一个系统之前校验格式。它们在模型之前和之后运行,跑在你的代码里——因为你没法指望模型自己管自己。
成本和延迟是设计上的约束
一辆出租车的计价器整趟都在跳——每多一里 context、每多走一步,都加进车费和等待里。
每一个 token 都要花钱和时间,而成本随着你发多少 context、调用多少次而水涨船高。所以你要为它做设计:裁剪并缓存 context、挑一个够好的最小模型,以及别在一次调用就行的地方跑一个 agent 循环。一个太慢或太贵的好答案,不是一个好答案。
幻觉是你要绕着设计的那个风险
你不会把麦克风递给一个才华横溢却不可靠的讲述者、然后不加看管——你会在它付印之前先核实事实。
这里的每一项技术——用 RAG 做 grounding、结构化输出、eval、guardrails、引用——存在的目的,都是为了驾驭一个核心风险:**模型把假话讲得令人信服。**你永远没法彻底除掉它;你把它能发生的地方框起来,在它发生时把它逮住,并且绝不让一句没核实的论断,到达那种「错了代价很高」的地方。
一个 demo 信任模型。一个产品度量它、框定它、盯住它——因为它生来就是非确定性的。
这些模式从简单到复杂层层堆叠。功夫在于,用那个能解决你问题的、最不强大的一个——并且把模型当作一个部件,而不是整个架构。
这架梯子,只爬到你非爬不可的那一级
你不会为了把一个箱子搬过房间,就去订一辆搬家卡车。你把投入,匹配到活儿上。
有一架梯子:一个好的单个 prompt,然后是结构化输出,再然后是它需要你的事实时的 RAG,然后是 tool,最后是任务真的需要许多自适应步骤时的完整 agent 循环。每一级都加上力量、成本,以及新的出错方式。从最底下起步,只在问题逼你时才往上爬——大多数功能,永远用不到最顶上。
LLM 是一个部件,不是那个架构
一辆车有一台强劲的引擎,但它被拴在一道防火墙之后、喂着干净的燃料、四周围着刹车——它不是整辆车。
把模型放在一个接口之后,像对待任何别的依赖一样,围着它的输入输出做校验,并留有换模型、换 provider 的自由。LLM 是你系统里一个强大却不可靠的部件——不是它的根基。(和系统设计里那一课「LLM 是个 adapter,不是那个架构」是同一个道理。)
- 最简单的那一级是什么——prompt、结构化输出、RAG、tool、agent——能解决这个? - 事实从哪儿来——模型的记忆(有风险),还是检索到的、可引用的数据? - 它出错时会怎样,而那个地方,错了是便宜还是昂贵? - 我要怎样 度量质量——eval 是什么? - guardrails 在输入和输出上各是什么? - 它每次调用 花多少钱,又有多慢?
- 一个一个 prompt 就能答的事,却用了一个 agent 循环。 - 对三份你本可以直接 贴进 prompt 的文档,却用了 RAG。 - 凭感觉调 prompt,没有 eval 告诉你它有没有变好。 - 每次调用都把整个知识库发进 context。 - 把模型的输出不加校验就直接送进一个数据库或一封邮件。
- 在你的代码用它之前,输出是结构化且经过校验的。 - 答案是 grounded 且可 引用的,不是凭空抽出来的。 - 你有一个 eval,在一次改动帮了忙还是帮了倒忙时告诉你。 - guardrails 同时坐在输入和输出上。 - 你用了那个奏效的最简单的一级——而模型坐在一个你随时能换掉的接口之后。
用 LLM 构建,靠的不是 prompt 魔法。它是平常的工程——context、检索、校验、eval——围着一个非凡却不可靠的部件。