agent或许最有一舞

25 年 12 月 14 日 星期日
2214 字
12 分钟

本来我应该会更早的着手写点agent相关的内容,但因我尝试agent的时候恰好是心理脱敏期往应用层面学习的时候,便没有心力来写点东西,这也算agent元年的最后一舞了吧

唱衰agent

agent开发从各个角度都有人进行分析,经典的便是大厂开发老登:“agent没有什么值得学的”;他是对的,agent确实没什么值得学的,但是agent给人们带来了一个很新的视角,也就是我们可以把非常局限性的对话大模型转换成工具调用和依赖的新天地,尝试,而非学习它,这是我的个人观感

巨大的状态机

1. 最底层:物理硬件状态机(原始的“无情执行”)

  • 状态:整个计算集群(GPU、CPU、内存、网络)的所有比特——权重张量、kv cache、寄存器、网卡缓冲区、时钟信号。
  • 迁移函数:每个时钟周期,硬件无条件执行矩阵乘法、加法、负载/存储指令。
  • 初始状态:服务器上电 → BIOS/UEFI → 加载推理框架 → 模型权重加载。
  • 这就是整个系统的“物理现实”:没有魔法,只有比特翻转。

2. 虚拟化层一:LLM 自回归生成状态机(单步 token 迁移)

  • 在硬件状态机之上,推理框架虚拟化出一个确定性的自回归状态机
  • 状态:当前 kv cache + 已生成 token 序列(即对话历史)。
  • 迁移函数:给定当前状态,执行一次前向传播 → 计算下一个 token 分布 → 采样/贪婪选择一个 token → 追加到状态。
  • 循环:重复迁移直到 EOS 或长度上限。
  • 这一层把硬件的并行矩阵运算“翻译”成“预测下一个 token”的语义行为,相当于编译器把高级语言翻译成机器码。

3. 虚拟化层二:单用户对话状态机(多步 Agent 推理)

  • 在自回归状态机之上,Agent 框架(如 ReAct、工具调用、思考链)虚拟化出一个更高阶的状态机

  • 状态:完整的对话历史(user message + assistant response + 工具结果)+ 当前思考步骤。

  • 迁移函数

    • LLM 生成一个“动作”(最终回答 / 工具调用 / 中间思考)。
    • 如果是工具调用 → 暂停当前状态机 → 跳转到外部工具子状态机(工具执行相当于另一个独立状态机)→ 工具结果追加回状态 → 继续迁移。
  • 整个对话轨迹:一条由用户输入触发的长链迁移,直到用户满意或会话结束。

  • 这一层把“单 token 迁移”抽象成“单轮推理迁移”,实现了工具使用、规划、多步思考。

4. 虚拟化层三:多用户平台状态机(操作系统级管理器)

  • 在多个单用户对话状态机之上,服务平台(后端调度系统)虚拟化出一个状态机的管理者,完全对应操作系统的角色。

  • 状态:所有活跃会话的集合(每个会话的 kv cache、历史、用户 ID、优先级)。

  • 迁移函数

    (调度器):

    • 非确定性地选择一个会话 → 加载其 kv cache 到 GPU → 执行若干步自回归迁移(生成部分响应)→ 保存状态 → 卸载。
    • 并发请求 → 队列 + 负载均衡。
    • Streaming → 每完成一步迁移就立即 I/O 输出一个 token。
  • 虚拟化效果:每个用户感觉自己独占一个无限智能的 Agent,实际是时分复用 + 空间复用 GPU 资源。

  • 非确定性来源(温度采样 + 调度顺序)对应 OS 进程调度的非确定性。

5. 最外层:包含用户的闭环巨型状态机(人机交互的终极统一)

  • 把用户也纳入状态,就形成真正的闭环巨大状态机

  • 状态:平台所有内部状态 + 用户大脑中的“对话上下文记忆” + 用户屏幕上显示的历史消息。

  • 迁移函数

    • 用户阅读 Agent 输出 → 在大脑中执行“思考迁移” → 输入新消息 → 通过网络追加到平台状态 → 触发平台内部多层迁移 → 生成新输出 → 更新用户屏幕状态。
  • 整个系统轨迹:从第一个用户消息开始,无限长的交互链,直到用户关闭页面。

  • 用户的“思考”虽不完全可计算,但从系统外部看,整个闭环的行为仍然可以用状态机描述(只是迁移函数部分是黑箱——人类大脑)。

从不同的视角,我们可以有不同的收获

设计原则

从状态机的视角来解读其实是不正确的,因为本身llm的输出和思考就是玄学,但是那是他们基模训练工程师的事,和我们又有什么关系呢~,状态是唯一携带信息的载体,丢失状态=丢失记忆,因此,使用结构化历史的思路就非常直观(system/user/tool/assistant),与此同时,为了确保迁移函数的确定性,对temperature的调整也值得考虑,对关键的路径采用temperature=0,以及为了确保有限的动作空间,采用ReAct模式(Thought->Action->Observation->...->Final Answer),强制状态迁移。。。很多东西还没想好

从agent组成来看,我们可以简单的分为planning,memory,action来考虑,但是planning太难了,所以不讨论

memory在大多数时候是值得我们探究的,以及对于开发工程师来说,我们需要的硬件和memory的交互方式,上下文压缩,历史总结,以及话题flag,我们需要让memory符合用户心中所想,在用户是never feedback的条件下,话题的转变就是flag的逻辑,不同的话题对应不同的flag,随着话题的推进,将前文flag的memory总结,然后逐渐释放,为何agent,chat用的大模型明显区别是,我们大多数时候不太会存在不活跃会话这个概念,对于前文完整找回的支持并不一定要适配?(个人胡言乱语)

action更多的是对工具的理解和应用,相信大神懂得比我多得多,大多时候是技术细节和业务理解,我们很难量化

细节

任务边界

你要先想清楚:

Agent 类型:是一次性任务?多轮对话?还是长时间运行(Minutes / Hours)?

容错机制:是否允许多步骤?允许中途失败?允许重试?

给 Agent 设置硬边界

  • 最大 Step 数;最大 Token 数;最大工具调用次数;最大运行时间

状态(State)—— Agent 和 LLM 的本质差异

LLM 是无状态的,Agent 必须是有状态的

你必须设计一个清晰的状态结构,例如:

typescript
interface AgentState {
  goal: string
  current_step: number
  scratchpad: string[] // 思考过程
  tool_results: Record<string, any>
  memory_refs: string[] // 引用记忆
}

必须考虑

  • 状态存在哪里?(内存 / 磁盘 / Redis?);崩溃后能不能恢复?(持久化);多 Agent 并发会不会串数据?

思考 vs 执行(极其重要)

一个成熟 Agent 至少分三种阶段:

阶段描述
Thinking / Planning模型内部的推理、规划
Acting / Tool Call调用外部工具、API
Responding最终回复给用户的内容

如果你不区分:

  • 模型会把中间推理暴露给用户,显得啰嗦且不专业。
  • 或者模型自己把自己误导(把思考当成结果)。

工程上常见做法: 使用特殊的 XML 标签或分隔符来隔离不同阶段:

xml
<analysis>
... (思考过程)
</analysis>

<action>
tool_call(...)
</action>

<final>
Here is the answer...
</final>

工具系统(Tooling)设计

值得考虑的是:

  • 性质:同步还是异步?有无副作用(Side Effects)?;异常处理:工具失败了怎么办?(重试?报错?跳过?);结果形态:全量返回?摘要返回?还是结构化数据?

  • 输入 Schema 清晰:模型能准确理解参数。

  • 失败可感知:报错信息要能指导模型修正。

  • 输出可控:避免输出过大的文本撑爆 Context。


控制流(什么时候停?)

Agent (虽然这更像基模平a的事):

  • 什么时候任务完成?;什么时候彻底失败?;什么时候该反问用户?

常见终止条件:

  • 达成目标(由 LLM 自行判断或外部校验);无可用工具(陷入死胡同);达到最大 Step / Token 限制;连续多次失败(避免死循环)。

可观测性(Observability)

我写了一个agent-sdk(链接...(还没放喵))


结语

不知道说什么,反正agent没必要花太多时间就是,bye~

文章标题:agent或许最有一舞

文章作者:io-wy

文章链接:https://io-wy.github.io/posts/agent%E5%90%8E%E4%B8%80%E8%88%9E[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。