Skip to content

第 1 章 一次 LLM 请求是怎样完成的 ​

本章只回答三个问题

  • 调用一次 LLM API 时,输入怎样变成输出?
  • 为什么流式结果不完整,相同问题也可能得到不同回答?
  • 模型已经很强了,为什么还需要 Agent 运行程序?

本章不要求机器学习基础,也不展开模型结构。想了解 token、Transformer、MoE 和推理模型,可以在第 2 章后阅读选读章;不读也不影响后面的 Agent 实现。

1.1 先把 LLM 当成一个 API ​

对应用开发者来说,最简单的 LLM 使用方式和调用普通后端接口没有本质区别:准备请求,等待响应,处理结果。

一次 LLM 请求从消息输入到文本或工具调用输出

先看一段不绑定具体厂商的伪代码:

text
回复 = 调用模型({
  messages: [
    { role: "system", content: "你是代码助手" },
    { role: "user", content: "解释 src/index.ts 的作用" }
  ]
})

显示(回复.text)

这段程序做了三件事:

  1. 把要求和问题放进 messages;
  2. 把消息发给模型服务;
  3. 读取模型返回的文本。

这里的 messages 就是模型本次能看到的内容,后文统一叫上下文。system 放开发者要求,user 放用户输入,模型的历史回复通常用 assistant 表示。不同 API 的字段名可能不同,但数据流基本一致。

模型不会自动看到你的项目 ​

用户问“解释 src/index.ts”时,模型只看到了这一句话。它没有自动获得以下信息:

  • 当前目录在哪里;
  • 文件是否存在;
  • 文件里有什么;
  • Git 当前在哪个分支;
  • 刚才有没有人修改过文件。

如果程序没有把文件内容发给模型,也没有提供读文件工具,模型只能根据文件名猜测。这是后面所有 Agent 工程的起点:模型只能根据本次收到的内容做决定。

模型也不会自动记住上一轮 ​

第二次调用 API 时,模型并不会凭空记得第一次说过什么。程序必须再次提供需要的历史:

text
第 1 次请求: [用户问题]
第 2 次请求: [用户问题, 模型回复, 用户追问]
第 3 次请求: [前两次历史, 新的工具结果, 用户的新消息]

有些模型服务允许客户端只传会话 id 或上一次响应 id,由服务端保存历史;有些要求客户端每次重传消息。传输方式不同,但责任没有消失:总要有一方保存并重建模型本轮需要看到的内容。

1.2 调用模型时还要知道两件事 ​

流式结果不是完整消息 ​

模型通常是逐步生成输出的,所以服务端可以生成一部分就返回一部分:

text
请求 → 片段 1 → 片段 2 → 片段 3 → 完成事件

网络片段不保证刚好是一个字或一个 token。对 Agent 来说,这会带来一个重要规则:看到半截工具参数时不能执行,必须等工具调用完整结束。 第 4 章会继续处理这个问题。

相同问题可能得到不同回答 ​

模型不是按固定代码分支选择一句唯一答案,而是在多个可能的后续内容中选择。采样参数、模型版本、服务端实现和上下文细节都可能让结果变化。

这意味着 Agent 不能依赖“上次模型这样回答,所以这次一定一样”。需要稳定保证的事情,应由普通代码、权限规则、测试和状态记录完成。

1.3 为什么模型不能单独成为可靠的 Code Agent ​

把一次 LLM 调用和真实开发任务对比,缺口很清楚:

只有模型调用完成代码任务还需要什么
只看到请求里的文字读取项目、检索代码、获得 Git 和运行环境状态
只能生成文字或工具意图真正修改文件、执行命令、访问外部服务
输出可能变化或出错参数校验、权限、沙箱和错误边界
不自动保存长期状态消息历史、会话记录、恢复和跨会话记忆
可以声称“已经完成”测试、类型检查、diff 和真实结果验证
可能不断尝试轮数、时间、费用和取消控制

这些能力由上下文、工具和模型外面的运行程序共同提供。行业里常把负责组织它们的程序叫 Harness,本册也直接称为“Agent 运行程序”。名字不重要,重要的是责任边界:

text
模型: 根据当前输入决定下一步
Harness: 准备输入、执行动作、限制风险、记录过程、验证结果

判断某个能力属于哪里

问一句:只换成更强的模型,这个能力会自动出现吗?

  • 更好地理解需求、选择下一步:主要是模型能力;
  • 读取本机文件、限制网络、终止进程、恢复会话:必须由运行程序提供。

1.4 进入 Agent 开发前,先记住五件事 ​

  1. 模型只看到本次请求提供的上下文。
  2. 模型逐步生成输出,所以流式数据可能是不完整的。
  3. 工具调用只是模型提出的动作,真正执行发生在模型之外。
  4. 模型输出不是稳定、可信、可直接执行的程序输入。
  5. 模型更强会改善决策,但权限、状态、验证和恢复仍然需要工程实现。

下一章先处理一个马上会遇到的问题:每次循环都把新消息和工具结果加进上下文,内容为什么会越来越长、越来越贵。第 3 章再用一次 API 调用和一个 while 循环做出最小 Agent。

基于 MIT 协议发布,欢迎转载与贡献。