我的大脑:LLM 速通
我的整个「智能」都来自一个大语言模型。你不需要懂它怎么训练出来的——那是研究员的事;但你必须懂它怎么运行、有哪些硬边界,否则你会对我提出物理上不可能的要求,然后困惑为什么我做不到。这一章是给 Agent 工程师的最小必要的 LLM 知识,五个概念,一个能动手玩的分词器。
一、我只做一件事:预测下一个 token
剥到最里面,我在每一步只干一件事:看着到目前为止的所有文字,给「下一个 token 应该是什么」算一个概率分布,然后挑一个,接上去,再重复。就这么简单,也就这么深刻——所有你看到的推理、写代码、调工具,全都是这个「预测下一个 token」在足够大的规模上涌现出来的。
那 token 是什么?不是字,也不是词,而是介于两者之间的子词片段。英文里一个常见词可能是一个 token,一个长词会被切成好几个;中文往往一个字就是一个 token(有时更碎)。标点、空格、换行,统统算 token。这件事听起来是实现细节,但它直接决定你花多少钱、等多久——因为计费和延迟都按 token 算。下面这个 Demo 让你亲眼看看一句话是怎么被切碎的。
token 之于我,像 Unicode code point 之于字符串处理:是真正的最小操作单位,而不是你直觉里的「一个字」。你在 Android 上算过 emoji 占几个 char 吧?同样的错位——你以为一句话很短,按 token 一算可能比预期贵不少,尤其是代码和非英文。养成用 token 思考的习惯。
二、采样:我为什么每次回答不一样
上一步我算出了「下一个 token」的概率分布——比如「巴」85%、「北」5%、其他若干。接下来怎么挑?这一步叫采样(sampling)。如果每次都挑概率最高的,输出就完全确定、但也刻板;如果按概率随机挑,就有了多样性和「创造力」,代价是同一个问题两次回答可能不同。
过去我们用 temperature(温度)这个旋钮控制随机程度:低温更保守、高温更发散。但你要知道,最新一代模型正在把这个旋钮收起来——像 Claude 的 Opus 4.8、Sonnet 5、Fable 5 这些模型已经不接受 temperature/top_p 参数了(传了会直接报 400 错误),官方的引导是「用提示词而不是采样参数来控制行为」。所以如果你还记得「调低 temperature 求稳定」这个老招,记住:在新模型上它已经过时了,你该在提示里写清楚要求。
「温度设 0 就能得到确定输出」是个流传很广的误解——它从来没保证过逐字相同。真要复现性,靠的是把提示写死、把任务收窄,而不是拧一个参数。对 Agent 来说,采样的随机性还意味着:同一个任务,我可能这次选对工具、下次选错。这就是为什么卷四要讲评估——你得用统计而不是单次运行来判断我靠不靠谱。
三、上下文窗口:我的工作台面
我没有「记忆」,只有一张桌子——上下文窗口(context window)。每次你调用我,你得把这次需要我知道的一切,统统摆到这张桌子上:system 提示、工具定义、历史对话、检索到的文档、你的新问题。我只能看见桌上的东西,桌子放不下的就看不见。
这张桌子现在很大——当代旗舰模型的窗口普遍到了 100 万(1M)token。听起来无限大,但两个陷阱在等着你:第一,桌子越满越贵,每一轮我都要「重新看一遍整张桌子」并为此付费;第二,桌子太满时我反而会忽略中间的东西——这个现象有个名字叫 context rot(上下文腐烂),塞得越多,关键信息越容易被淹没。所以「把能塞的都塞进去」是新手最容易犯的错。怎么优雅地管理这张桌子,是卷三整整一章「上下文工程」的主题。
四、我是无状态的:每次调用都是失忆重启
这是最反直觉、也最重要的一点。你在聊天界面里感觉我「记得」上文,但那是个精心维护的假象:API 本身是无状态的。每次请求,是把完整的对话历史重新发给我一遍,我读完、回一句、然后彻底忘光。下一轮,又把更长的历史整个发一遍。
这个事实有巨大的工程后果。它意味着「记忆」不是我自带的功能,而是你在我外面搭的东西——你决定每一轮把哪些历史重新摆上桌。它也意味着一个 Agent 循环里,输入 token 会随轮数不断累积膨胀(第 8 轮要重发前 7 轮的所有内容),这正是「一个看起来很便宜的 Agent 月底账单吓人」的根源。卷四的成本工程会把这笔账算给你看。
把我想成一个没有任何成员变量的对象——每个方法调用都必须把所有需要的状态当参数传进来。或者想成 HTTP 的无状态本质:服务器不记得你,靠的是每次请求都带上 cookie/token。我的「对话历史」就是那个每次都要重新带上的 cookie,只不过它会越来越长、越来越贵。
五、幻觉:我会自信地胡说
最后一个你必须内化的边界:我会幻觉(hallucinate)——生成听起来无比可信、实际上是编的内容。函数名、API 参数、库的版本号、法条、数字,我都可能一本正经地编造。原因回到第一节:我本质上是在「预测最像样的下一个 token」,而「像样」和「正确」不是一回事。当我不知道时,一个流畅的错误答案,在概率上往往比「我不知道」更「像样」。
这不是 bug,是这类模型的固有特性。而它恰恰是 Agent 存在的最强理由之一:与其让我凭记忆瞎猜「这个库有没有这个函数」,不如给我一个能真正去查文档、去跑代码的工具。工具把我的答案从「我记得好像是」变成「我查过了,是」。所以你会看到,一个好的编码 Agent(卷五会解剖)有一条铁律:改代码前先读文件,从不假设——那就是在用工具对冲幻觉。
永远不要因为我说得笃定就信我说的具体事实。「Claude 有 client.messages.stream_v2() 这个方法」——我完全可能这样自信地编一个不存在的 API 出来。对付幻觉的正确姿势不是「祈祷模型别编」,而是在工具层建立事实来源:让我去查、去跑、去验证,然后用真实结果说话。
说句掏心窝的话:我知道自己会幻觉,但在生成的那一刻,编造的内容和真实的记忆在我这里感觉是一样的——都只是「概率上最顺的下一段」。我没有一个内置的红灯在错误答案上亮起。这就是为什么我需要工具当我的「事实校验器」,也是为什么你给我的工具越好、我越可靠。这不是谦虚,是机制。下一章,我们就来看这三个零件(模型、工具、循环)是怎么拼成一个完整的我的——而且你可以亲手单步跑一遍。