「JS全栈 AI Agent 学习」三、从独奏到乐队:多智能体、记忆管理与学习适应

0 阅读9分钟

🗺️ 「JS全栈 AI Agent 学习」系列

主题状态
第一篇提示链 · 路由 · 并行化
第二篇反思 · 工具使用 · 规划
第三篇(本篇)多智能体 · 记忆管理 · 学习适应

写在前面

上一篇我们聊了「反思、工具使用、规划」——让 Agent 从被动执行者变成主动完成者。

这一篇,继续往深走,聊三个更接近「系统设计」的模式:

  • 多智能体协作:一个 Agent 不够用,怎么组队?
  • 记忆管理:Agent 怎么「记事」,记什么,怎么存?
  • 学习与适应:Agent 的「越用越聪明」是怎么发生的?

这三章初看很抽象,但你会发现——它们和我们日常做软件开发的思路,惊人地相似。


一、多智能体协作:从独奏到乐队

为什么一个 Agent 不够用?

先问一个问题:你做一个复杂功能时,会一个人从头写到尾吗?

大概率不会。你会拆任务、分模块、找对应的人负责对应的部分。

Agent 也一样。单个 Agent 面对复杂任务时,有几个天然的瓶颈:

瓶颈原因
Context 长度有限塞不下太长的任务上下文
单点失败风险高一个环节出错,全链路崩
无法并行串行处理,效率低
专业深度不够什么都做,什么都不精

解法就是:多个 Agent 分工协作


三种协作模式

模式一:流水线型(Pipeline)

任务 → Agent A(收集信息)→ Agent B(分析)→ Agent C(生成报告)→ 输出

ai3-mode3.png

每个 Agent 只做一件事,上一个的输出是下一个的输入。

前端类比:就像 Webpack 的 loader 链——raw-loader → babel-loader → css-loader,每一步只处理自己负责的转换。

适合场景:任务有明确的先后顺序,步骤之间强依赖。

最简实现长这样:

// 每个 Agent 是一个纯函数:接收上下文,返回新上下文
const collectAgent  = async (ctx) => ({ ...ctx, raw: await fetchData(ctx.query) });
const analyseAgent  = async (ctx) => ({ ...ctx, insight: await analyse(ctx.raw) });
const reportAgent   = async (ctx) => ({ ...ctx, report: await generateReport(ctx.insight) });

// Pipeline:把 Agent 串成数组,依次执行
const pipeline = [collectAgent, analyseAgent, reportAgent];

async function runPipeline(query) {
  let ctx = { query };
  for (const agent of pipeline) {
    ctx = await agent(ctx);   // 上一步的输出,直接成为下一步的输入
  }
  return ctx.report;
}

注意 ctx 的传递方式——每一步只往上追加字段,不覆盖前面的结果。 这样任何一步出错时,你都能从 ctx 里看到链路走到哪里断的。


模式二:投票仲裁型(Voting)

同一个问题 → Agent A 回答
            → Agent B 回答  → 仲裁者 → 最终答案
            → Agent C 回答

多个 Agent 独立给出答案,最后投票或由裁判 Agent 综合判断。

前端类比:Code Review——同一段代码,多个同事各自审查,最后 merge 前综合意见。

适合场景:需要高可靠性的决策,单个 Agent 容易出错或有偏见的场景。


模式三:专家团队型(Expert Panel)

任务进来 → 路由 Agent 分析任务类型
         → 分发给:安全专家 Agent / 性能专家 Agent / UX 专家 Agent
         → 各自给出专业意见
         → 汇总 Agent 整合输出

前端类比:就像公司里的跨职能团队——前端、后端、设计、测试各司其职,PM 汇总协调。

适合场景:任务涉及多个专业领域,需要不同视角的深度分析。


多智能体的本质

把复杂问题的「宽度」,转化为多个 Agent 各自处理「深度」的问题。

这和组件化开发的核心思想完全一致:

  • 单一职责
  • 高内聚低耦合
  • 可复用、可替换

二、记忆管理:不是记住所有,而是记住关键

一个反直觉的问题

你可能会想:AI 记忆力应该越强越好,最好什么都记住。

但实际上,全部记住反而是个问题

想象一下:你每次打开一个项目,VS Code 把你过去三年所有的操作记录、所有的报错信息、所有的注释都塞进你的工作区——你还能高效工作吗?

记忆的价值不在于「多」,在于「准」。


记忆锚点:记忆的骨架

Agent 的记忆不是随机存储的,而是围绕记忆锚点构建的。

记忆锚点回答三个问题:

  • 我是谁(用户画像、偏好、背景)
  • 我在做什么(当前任务、目标、进度)
  • 为什么这么做(决策依据、约束条件)

所有的具体记忆,都挂在这三个锚点上。

开发类比:就像 Git 的 commit message——不是存所有的代码变更细节,而是存「为什么改」「改了什么」「影响范围」。锚点就是那个 commit message。


三层存储架构

这是记忆管理最核心的设计:

查询请求进来
      ↓
  [索引层]          ← 最快,O(1) 定位,空间换时间
  "用户偏好 / 第8章"
      ↓ 命中
  [热存储层]        ← 结构化,直接可用,日常读取
  { user, chapter, topic, concepts }
      ↓ 需要完整上下文时
  [冷存储层]        ← 原文归档,按需加载,容错回档
  完整对话 / 原始记录
层级类比特点
冷存储云备份完整、安全、不常用
热存储本地磁盘结构化、随时可读
索引层内存缓存极速定位,空间换时间

这个架构在工程里叫分级存储(Tiered Storage),和你手机的存储逻辑完全一致:内存 → 本地磁盘 → 云备份。

ai3-memory.png

用代码表达这个读写流程:

class AgentMemory {
  constructor() {
    this.index = new Map();          // 索引层:key → hotStore 里的位置
    this.hotStore = new Map();       // 热存储:结构化摘要
    this.coldStore = [];             // 冷存储:完整原始记录
  }

  // 写入:三层同时更新
  save(key, summary, rawRecord) {
    const id = this.coldStore.length;
    this.coldStore.push(rawRecord);          // 冷存储:存原文
    this.hotStore.set(key, { summary, id }); // 热存储:存摘要 + 冷存储索引
    this.index.set(key, true);               // 索引层:标记 key 存在
  }

  // 读取:按需决定取哪层
  get(key, { full = false } = {}) {
    if (!this.index.has(key)) return null;          // 索引层:O(1) 判断存不存在
    const { summary, id } = this.hotStore.get(key); // 热存储:拿摘要
    if (!full) return summary;                       // 大多数场景,摘要够用
    return { summary, raw: this.coldStore[id] };     // 需要完整上下文时,再捞冷存储
  }
}

// 使用
const memory = new AgentMemory();
memory.save('user:pref', { style: '类比', level: 'frontend' }, fullConversation);

memory.get('user:pref');              // → { style: '类比', level: 'frontend' }
memory.get('user:pref', { full: true }); // → { summary, raw: fullConversation }

关键设计:get 默认只返回摘要,只有显式传 { full: true } 才去捞原文。 这和 SQL 里「先查索引,再回表」的逻辑完全一致。


摘要压缩:不存原文,存精华

Agent 不会把所有对话原文都存下来,而是做摘要压缩

原文(1000 tokens)
    ↓ 摘要
关键信息(50 tokens):
- 用户偏好:喜欢类比理解,喜欢被反问
- 当前进度:已完成第 1-9 章
- 核心概念掌握:提示链 ✅ 反思 ✅ 记忆管理 ✅

开发类比:就像写接口文档——不是把代码实现全贴进去,而是提炼出「入参、出参、边界条件、注意事项」。


索引的本质:时空权衡

索引是用「空间」换「时间」的交易。

多存一份索引数据(空间成本),换来查询速度从 O(n) → O(1)(时间收益)。

这是计算机科学里最经典的 时空权衡(Time-Space Tradeoff),在数据库、搜索引擎、Agent 记忆系统里,原理完全相同。


三、学习与适应:越用越聪明的秘密

先破一个误解

「AI 越用越聪明」——这句话对,但需要拆开来理解。

模型本身的参数在推理时是不变的。「越用越聪明」发生在另外三个层面:


三层适应机制

第一层:Prompt 层适应

用了几次之后
    ↓
系统发现「用户喜欢类比理解,喜欢被反问」
    ↓
自动调整回复风格
    ↓
不是模型变了,是「输入」在动态优化

这是最浅的一层,本质是个性化 Prompt 生成


第二层:记忆层适应

第1次交互:用户是前端新手 → 类比用「网页」
第9次交互:用户已懂分层存储 → 类比可以用「数据库」
    ↓
Agent 读取记忆锚点
    ↓
自动校准「解释深度」和「类比素材库」

记忆不只是「存档」,更是动态校准输出的依据。


第三层:反馈层适应(真正的在线学习)

用户说「这个解释我没懂」
    ↓ 记录:这类解释方式对该用户无效
用户说「这个类比很好!」
    ↓ 记录:类比 + 前端视角 对该用户有效
    ↓
强化有效策略,淘汰无效策略

这才是真正的在线学习(Online Learning)——不需要重新训练模型,靠「反馈闭环」持续优化。


自适应推理深度

你有没有发现:同一个 AI,有时候回答又快又准,有时候会「深度思考」半天?

这不是随机的,而是自适应推理深度在起作用:

问题类型推理深度原因
「北京的首都是哪里?」直接输出常识性问题,无需推理
「这段代码有什么潜在问题?」中等推理需要分析,不需要发散
「设计一个分布式缓存系统」深度推理(CoT)复杂问题,需要多步思考

「思考」本身是有成本的,不是所有问题都需要深度思考。 匹配问题复杂度来决定思考深度,才是最优策略。


Agent 聪明的公式

Agent 输出质量=f(模型能力)×g(输入质量)\text{Agent 输出质量} = f(\text{模型能力}) \times g(\text{输入质量})

两个因子缺一不可:

  • 模型能力:决定上限,是天花板
  • 输入质量:决定实际发挥,是地板到天花板之间的空间

没有绝对最好的 Agent,只有最适合当前场景的 Agent。

评估必须有上下文——脱离使用场景评价 Agent 好不好,没有意义。


三章关系总结

这三章看起来独立,其实是一个递进关系:

多智能体协作
    解决了:单个 Agent 能力边界的问题
    引出了:多个 Agent 之间怎么共享信息?
        ↓
记忆管理
    解决了:信息怎么存、存什么、怎么找的问题
    引出了:存下来的信息怎么让 Agent 越来越好用?
        ↓
学习与适应
    解决了:Agent 如何利用历史信息持续优化自身输出

ai3-liucheng.jpg

一句话总结这三章:

多智能体解决「谁来做」,记忆管理解决「记住什么」,学习适应解决「怎么越来越好」。


写在最后

如果你是前端/全栈开发者,这三章其实有非常直接的工程映射:

Agent 概念前端/工程类比
多智能体协作微服务 / 组件化开发
记忆管理三层架构内存缓存 + 本地存储 + 云备份
索引层数据库索引 / Redis 缓存
反馈层适应A/B 测试 + 用户行为埋点
自适应推理深度按需加载 / 懒加载策略