Skip to content

预备知识:从零认识 Agent

如果你对 "LLM"、"token"、"工具调用" 这些词还比较陌生,请先读完这一篇。它用大白话 + 类比,把看懂本教程需要的基础概念一次讲清楚。已经熟悉的人可以直接跳过。

一、什么是 LLM(大语言模型)

LLM(Large Language Model,大语言模型)是一个根据前文预测下一个词的程序。你给它一段文字,它就接着往下"编":

输入:  "今天天气真"
输出:  "好"

它实际上是在无数文字上训练出来的概率预测器:给定前面的词,算出下一个最可能的词。反复"预测下一个词"几百次,就拼出了一整句话、一整段文章。

一句话类比:LLM 就像一个"接话茬"高手,你不停喂它上文,它不停往下接。接多了,看起来就像在"回答你的问题"。

@pi/aiStreamFunction 做的事情,本质上就是:把一段上文(会话历史)发给 LLM,再流式地接收它"接话茬"吐出来的词

二、什么是 token

LLM 不直接处理"字",而是把文字切成叫 token 的小块。中文里,一个 token 大致对应一个词或一个常用词片段。

"你好,世界"  →  ["你好", ",", "世界"]   (约 3 个 token)
  • LLM 的输入输出都以 token 计费。
  • @pi/aiUsage 里的 input / output 就是 token 数。
  • 判断"会话会不会太长"靠的就是估算 token 数。

三、上下文窗口(Context Window)

模型一次能"记住"的上文是有限的,这个上限叫上下文窗口

上下文窗口 = 这一次调用模型时,能塞进多少 token
  • 塞得越多,模型越"记得住"之前的对话,但越贵、越慢
  • 一旦超过窗口,就得压缩(pi 的 compaction,见 6.2)或丢弃/总结旧消息。

@pi/aiModel.contextWindow 字段就记录这个上限。

四、Prompt 与 System Prompt

Prompt(提示词) 就是"你发给模型的那段话"。它包含两类:

  • System Prompt(系统提示):对话开始前给模型设的"人设和规则",告诉它"你是谁、要遵守什么"。例如 "你是专业的编码助手,回答要简洁。"
  • User Message / Prompt:用户每一次的具体提问。
System:  你是编码助手,回答简洁。        ← 系统提示(人设规则)
User:    帮我重构一下 utils 模块。       ← 用户提问

@pi/aiContext 结构正好对应:

ts
interface Context {
	systemPrompt?: string;   // 系统提示
	messages: Message[];     // 用户 / 助手 / 工具的对话历史
	tools?: Tool[];          // 可用的工具
}

五、工具调用(Tool Calling / Function Calling)

这是 "Agent 能做事" 的核心。

普通的问答,模型只能"说话"。工具调用让模型能"请求调用某个函数",拿到结果后再继续说话:

User:   帮我算 3 + 4
模型:   我需要调用一个计算工具 → { 工具名: "calculator", 参数: {a:3, b:4} }
程序:   执行 calculator(3,4) → 得到 7
程序:   把"7"作为工具结果回填给模型
模型:   最终回答:"3 + 4 = 7"

关键点:模型只是"提出想调用哪个工具",真正执行工具的是我们自己的程序。模型提供的是"决策"(调用什么、用什么参数),程序提供的是"执行"(真正跑代码)。

  • 模型发来的"工具调用请求"在 pi 里叫 ToolCalltype: "toolCall")。
  • 我们执行完回填的结果叫 toolResult 消息。
  • 模型说"我要调用工具"的信号是 stopReason = "toolUse"

这就是 2.1 核心 Agent 循环 里那个"循环"在反复做的事。

六、什么是 Agent

把上面几块拼起来,就得到 Agent(智能体)

Agent = LLM + 循环 + 工具

它不像普通问答那样"问一句答一句",而是能自己决定:要不要调用工具、调用哪个、调完再怎么办,直到达成目标。

用户:  帮我改一下 README
Agent 内部的循环:
  1. 把整个会话发给 LLM
  2. LLM 说:"我要读 README"  → 程序执行 read 工具
  3. 把读取结果回填给 LLM
  4. LLM 说:"我要写入修改"    → 程序执行 write 工具
  5. 把结果回填
  6. LLM 说:"改好了"(stop)→ 结束

七、ReAct:Agent 循环的经典范式

pi 的循环遵循一个经典范式 ReAct(Reason + Act)

Reason(思考): 模型根据当前上下文决定下一步

Act(行动):    执行一个工具(或直接回答)

Observe(观察): 程序把工具结果回填给模型

(回到 Reason,直到模型认为完成了)

@pi/agent-coreagent-loop.ts 就是这个循环的实现(见 2.1)。

八、流式输出(Streaming)

模型生成是一个字一个字吐出来的,不是一次性。流式就是边生成边把已产出的部分发给接收方,让用户不用干等。

  • pi 用 文字增量 事件(text_delta)逐段推送。
  • TUI 据此实现"打字机效果"(见 5.1)。

九、把概念串起来

现在你再看 pi 的架构图,应该不再陌生了:

@pi/ai            —— 负责"第 1~5 条":把对话发给 LLM,流式接收,统一各家厂商
@pi/agent-core    —— 负责"第 6~7 条":ReAct 循环,决定调哪个工具、执行并回填
@pi/protocol+server+client —— 负责"远程":把会话序列化成字节,跨机器传输
@pi/tui           —— 负责"展示":把流式的增量画到终端
@pi/coding-agent  —— 负责"产品化":存盘、压缩、内置工具、扩展

如果还有疑问


现在,你可以正式开始了。1.1 统一会话消息模型