核心原理

大语言模型(LLM)的核心原理讲起来很简单:根据已有的文本,预测下一个 token 出现的概率,这里的 token 是模型处理文本的最小单位,可以简单理解 token 就是输入和输出的文本里的字词

比如你输入「今天天气」,模型会计算所有可能的下一个字的概率分布:「真」的概率 30%,「不」的概率 20%,「很」的概率 15%… 然后从中选一个输出。选完之后,把这个字拼到输入后面,继续预测下一个字,如此反复,就生成了一段完整的文本

所以 LLM 本质上就是一个概率模型,一个字一个字地往外蹦,由于 Transformer 架构的自回归设计,上一轮的输出作为下一轮的输入,所以也只能一个字一个字往外蹦,跟 ChatGPT 聊天时看到回答一个字一个字地出现,不是为了打字机效果,这就是它真实的生成方式

在 LLM 往外输出文本时,会先计算出一组 token 本身的出现概率,再根据几个参数对这些概率进行调整,再最终选择输出哪一个 token

有一个参数叫温度(temperature),控制模型选择 token 时的随机程度,就像热力学熵一样,越高越混乱

温度等于 1 的时候,模型选择 token 时的概率完全等于模型本身计算出的概率,没有任何缩放。温度越低,越会让本来概率高的更高,本来概率低的更低,缩放后的概率就越确定,信息熵越低;温度越高,缩放之后的概率就更随机,分布得更平坦,就更有可能选择到原本概率并不高的 token,输出变得更有创意

还有另一组参数叫做 top P 和 top K,其中 top P 用于配置保留将 token 按概率从高到低排序后前 n 个概率加起来超过 p 的 token 选项,其他的丢弃掉,而 top K 就直接用于保留概率最高的 k 个选项

可能光这样讲比较抽象,可以看看这个在线演示

现在很多比较新的推理模型已经不推荐再去调整这几个参数了,而是提供了更为直观的 Reasoning Effort 参数,用于配置模型的推理预算和思考深度

上下文

另一个重要的概念是上下文(Context)

模型在预测下一个 token 时,依据的就是当前上下文里的所有文本。你输入的问题、当前会话中的历史消息、系统给的背景设定,这些全部拼在一起就构成了上下文

模型本身是没有状态的,至少现在这些给大众使用的还没有,对于同一个模型,不引入随机性的情况下或者说温度设定为0的时候,对于同样的输入,输出几乎永远是一致的

举个例子,你跟 ChatGPT 聊天,第一句说「我叫小明」,然后聊了很多别的话题,最后突然问「我叫什么名字」,它能正确回答「你叫小明」,这不是因为它「记住」了你的名字,而是因为「我叫小明」这句话还在上下文窗口里。模型每次生成回答时,都是依据整个上下文的内容来预测下一个 token 的,所以表现出来是它「记住」了你的名字

但上下文的容量肯定是有限的,一般称这个容量为上下文窗口(Context Window)

由于 Transformer 架构的自注意力机制,每次预测下一个 token 的时候,需要计算上下文中每一个 token 和其他 token 的注意力,如果有 N 个 token,模型就需要计算一个 N * N 的注意力矩阵,计算量是随上下文长度二次方增长的

正是因为上下文窗口是有限的,所以超出窗口的内容就需要被处理掉,常见的做法是压缩(Compaction):让模型把早期的对话总结成一段摘要,保留重要信息,丢掉细节,从而腾出空间

所以如果你和 ChatGPT 聊了特别长的对话,再问最开头的问题,它可能就记不清楚了,因为早期的对话已经被挤出了上下文窗口

所以,最佳实践是一个会话(Session)只聚焦处理一个问题相关的对话,对于新的问题就重新开始一个新的会话,相当于开启了一个全新的上下文窗口

系统提示词

大家对它应该都很熟悉了,本质上是对话开始前给模型的一段指令,会被拼到上下文的最前面

通常用它来作为模型的人物设定,每次生成回答时模型都能读到这段文本,不管用户问什么,它都会在这个「人设」的框架下回答

系统提示词可以在每次调用 API 时指定,当然也就可以让用户自己输入,这就取决于具体的需求,现在很多 AI APP 里提供的那些扮演角色,就都是通过指定不同的系统提示词

很多模型的 API 在调用时传入的文本需要标记不同的角色标签像是 system、user、assistant、tool,模型在训练时学会了对 system 标签的内容赋予更高的服从权重。所以用户通常没法轻易覆盖系统提示词里的规则,当然道高一尺魔高一丈,厂商和用户也一直进行着攻防博弈,这些都是后话

正是因为系统提示词的高优先级,后续的很多扩展都会通过在系统提示词上做文章来实现

另外很重要的一点是,虽然系统提示词有较高的优先级,可用于设置一些业务规则,比如 BRclaw 就通过系统提示词来配置拒绝哪些话题,允许哪些话题,以及设置回复用户时使用什么语言。但不建议用来设置那些高敏感的安全规则,比如用于限制资料泄漏,因为系统提示词对于 LLM 的限制并不绝对,并不永远都可靠,不能作为安全边界,真正需要安全的地方得靠外部系统保证

Chatbot

这个大家都见得多了,普通的聊天 APP,网页上的类似 ChatGPT 这样的一问一答形式的

前面我们说 LLM 是无状态的,那么这些 Chatbot 是怎么记住聊天内容的呢,都是靠的客户端记忆,这里所说的客户端是相对于 LLM API 来说的,也就是 API 的调用者负责存储和带上记忆

比如产生以下的聊天

用户输入:你好呀 (1)

Chatbot: 你好呀!很高兴见到你。请问今天有什么我可以帮你的吗?

用户输入:今天成都的天气怎么样 (2)

Chatbot: 今天成都的天气以晴到多云、持续高温为主

那么调用 LLM API 时传入的消息记录就会像这样

 1(1)
 2[
 3    {"role":"user","content":"你好呀"}
 4]
 5
 6(2)
 7[
 8    {"role":"user","content":"你好呀"},
 9    {"role":"assistant","content":"你好呀!很高兴见到你。请问今天有什么我可以帮你的吗?"},
10    {"role":"user","content":"今天成都的天气怎么样"}
11]

每一次 API 调用都会把以前的所有历史记录给带上,通常大家就把这个消息记录叫做一个会话 Session

那么新开一个 Session 的时候,当然这个消息数组就被清空掉

重新回到某一个 Session,就是再把消息记录加载回来

Agent

LLM 虽然能说会道,但它有一个根本性的限制:输入输出都是基于文本。当然在这里我们先只讨论最简单的文本模型,不讨论多模态的

很经典的举例就是 LLM 只是个缸中大脑,只能依据训练中学到的知识进行回答,且知识还受到训练截止时间的限制,没办法获取到最新的资讯,没办法实际去做事情,没办法对外部造成影响

针对这个情况,大家就开始了尝试,有什么办法能够让 LLM 和外部世界交互

于是就引入了 Agent 的概念,夹在 LLM 和用户中间,辅助 LLM 和外部世界交互,我最早见到的是完全基于提示词的实现,现在经过很多改进但原理也都一样

agent

那么在用户看来,问了一句天气如何,得到了精准的回答,体验就好得多

当然随着技术发展,现在很多主流 LLM API 都原生支持了 Function Calling 和通过 JSON Schema 来描述工具参数,已经不需要自己去构造 prompt 和解析 JSON 这样原始的方案了

既然现在通过 Agent 为 LLM 提供了工具调用的能力,那么 LLM 就可以做很多事情了

现在很多 Agent 的核心代码其实就是如下的一个循环

1while True:
2    LLM(msgs, tools)
3    if has_tool_call:
4        call_tool()
5    else:
6        print_output()
7        break

只要配置上丰富的工具集,比如读写文件,搜索网页,执行命令,Agent 就可以做很多事情

但同样,如果没有对应的工具能够使用,那么无论 LLM 多努力思考,也做不到一些事情

比如 BRclaw 目前只有 search_docs 一个工具,用于查询内部的文档,但有的用户会来问 BTC 的价格,那么 LLM 凭借自己截止到某一天的训练知识和仅有的一个搜索文档工具,它就是把文档搜索穿了,也搜索不到当天的 BTC 价格,于是最后只能瞎说一个

Agent 可靠性与安全边界

给 Agent 配上工具,不代表它就能可靠地把事情做好。LLM 仍然可能选错工具、填错参数,或者误解工具返回的结果。比如用户问「帮我把今天的会议都取消」,模型可能把日期理解错;又比如搜索工具返回了一篇过时的文章,模型也可能把里面的内容当成最新事实

所以在真正做 Agent 时,不能只让模型自己决定一切。模型负责提出工具调用的意图和参数,但实际执行前还应经过确定性的校验和策略控制:参数是否符合 Schema、当前用户是否有权限、目标资源是否在允许范围内。对于发消息、执行命令、删除或修改数据这类有副作用的操作,通常还需要引入 Human-in-the-loop,也就是让用户确认后再执行。工具权限也应遵循最小权限原则,例如只读搜索工具不应该顺带拥有删除文件的能力

另外,Agent 出问题时往往比普通 Chatbot 更难排查,因为一次回答背后可能经过了多轮模型调用和工具调用。因此实际开发中需要做可观测性(Observability):将一次用户请求关联成一条 Trace,记录每一轮模型调用、工具调用、输入输出、参数、耗时、Token 用量、重试和错误信息。这样出了问题才知道是模型理解错了、工具本身出错了,还是上下文里给了错误的信息;也能进一步衡量 Agent 的成功率、延迟和成本

最终,Agent 的能力来自模型、上下文、工具和执行环境的共同配合。其中任何一环不可靠,最终结果就不应该被当成可靠的事实或可靠的操作

实践探索

使用 pydantic_ai 框架,从最简单的 chatbot 慢慢深入,探索 ai agent 的各个功能模块的实现方式

Session,工具 和 MCP,技能,记忆