AI之-nodejs编写agent基本脚手架
概念
构建 AI Agent,本质上是围绕 LLM(大语言模型) 打造一个具备“感知-思考-行动”循环的系统
ReAct
思考–>行动
其实他是个循环,于是:【思考–>行动】—>【观察(其实又是一轮思考)】—>行动】—>【观察(其实也是思考)—>输出(没下一步行动了)】
就是”思考–>行动“的循环。
分场景思考设计
不同类型 Agent 逻辑:
基础对话 Agent:只使用 LLM + 短期记忆
工具调用 Agent:LLM + 记忆 + Tools(最常用)
自主规划 Agent:多步骤任务拆解(写报告、做方案)
工作流 Agent:固定流程执行(审批、数据处理)—-我的宝宝起名字感觉像这种,连短期记忆都没有,就是固定流程执行,借助LLM做了个总结和分析而已。
其实不同场景下agent的逻辑我感觉是不一样的。我感觉自主规划和工具调用才是需要ReAct的吧。
骨架代码示范
https://www.doubao.com/chat/38421895086981378
大概要:
- 拼凑系统提示词,写清楚:模型的输入格式,输出必须如果是调用工具或skill则必须用json格式。这样才能靠代码判断。
且告诉模型tools列表以及skills列表。
tools列表(包含mcp)应该是靠通过某中央服务器获取mcp列表,或者咱代码手写注入的。
skill则通过解析skills目录下的skills拿到所有skill markdown的描述。 - 编写while循环(注意控制循环最大次数),基本流程就是:系统提示词加用户提示词提交大模型思考,思考结果做判断—>若是skill或者tool就调用,若是最终结果就跳出循环返回。
- 每轮循环末尾把本次提交给模型的内容以及模型的返回添加到临时记忆数组。
架构上怎么harness
工具调用:让AI能调用外部API、搜索工具、数据库等
知识增强:通过RAG检索让AI拥有最新、最专业的信息
智能体编排:让多个AI Agent协作完成复杂任务 (疑问:skill和mcp不够么?难道是为了搞新上下文轻装上阵)
记忆管理:管理对话历史、长期记忆
Harness是”道”(理念和方法论).Hermes是”器”(具体工具和实现)。所有AI智能体都需要Harness来可靠运行,而Hermes是其中一种优秀的开源选择。
历史记录传递
历史对话记录有时候会被称作“context”。但其实广义的context上下文窗口是包含整个跟大模型交互的所有内容了(例如系统提示词等等)。
不过我们大概知道这些概念的区别就行了。直到什么场景下说出来的时候他代表什么即可。
关于如何给大模型传递历史记录,我们在工程上需要考虑:
如何保存历史记录
如何传递历史记录给大模型
历史上下文过多时候如何处理。
第一上下文太多会撑爆窗口,第二他会浪费token资源,第三也会引起LLM思考性能下降。
思考模式实现
生产环境:考虑两阶段推理,可控性更好
复杂推理:使用ReAct或思维树模式
https://yuanbao.tencent.com/chat/naQivTmsDa/3c3fdd22-79c6-4163-81c7-6f8494d517b0
RAG检索
假设一次提问后,ai的回答是2000个字的回答,假设里面引用了10处我博客的内容,10处内容分别对应到我8篇博客文章。
但我在想,你rag检索的时候通常不是只检索top3么,那岂不是无论怎样你只会给ai大模型3个检索结果片段? 那如果我的提问问题就是希望基于我博客里的一些内容来回答,仅仅靠3处rag向量结果那岂不是非常单薄?意味着大量内容都是ai编造的,只有3句话是真的来自我的博客。是这么理解吗?一般怎么解决这种问题的—即要怎样让ai的回答都是基于我真实博客内容的回答,而不是仅仅有3句短短的句子是来自我的博客。
你的直觉非常敏锐,这正是 RAG(检索增强生成)从“玩具级”迈向“生产级”时最核心的工程痛点。
如果你只是死板地取 $k=3$(Top-3),而你的问题又很宏大(比如“总结我过去一年对 React Fiber 的所有思考”),那么 AI 确实会面临“巧妇难为无米之炊”的尴尬,导致回答内容要么单薄,要么开始胡编乱造。
在实际的 R&D 工程实践中,我们有四种标准方案来解决“信息量不足”的问题:
1. 动态调整 $k$ 值与 Rerank(重排序)技术
不要只检索 3 个片段,先“海选”再“精选”。
单纯的向量检索(Vector Search)是基于语义相似度的,有时候它找得并不准。
- 做法:初筛阶段我们取 $k=50$ 甚至 $k=100$。
- 重排序(Rerank):引入一个专门的 Reranker 模型(比如 BGE-Reranker)。这个模型计算量大但极度精准,它会从这 50 个片段里,重新打分,选出最核心的 5-10 个片段。
- 效果:这样喂给大模型的数据质量会大幅提升,信息量也从“3 句话”变成了“3000 字”的高浓度素材。
2. 父子文档检索 (Parent Document Retrieval)
这是解决“断章取义”的神技。
- 痛点:为了检索准,我们通常把博客切得很碎(比如 200 字一段)。但 200 字往往讲不清楚一个复杂的逻辑。
- 方案:
- 我们在数据库里存两套:子片段(200字,用于检索)和父文档(2000字全文或大段落)。
- 当系统通过子片段命中目标时,它不把子片段给 AI,而是根据元数据(Metadata)找到它所属的父文档全文喂给 AI。
- 效果:AI 拿到的不再是碎纸片,而是逻辑完整的整页书。
3. 混合检索 (Hybrid Search)
向量检索(语义)和 关键词检索(BM25)的结合。
- 如果你问的是“Fiber 里的
workInProgress变量”,向量检索可能因为语义模糊找不准,但关键词检索能精准定位到所有出现过这个变量的代码段。 - 将两种检索结果融合,能保证 AI 既懂你的“意思”,又拿到了“硬核数据”。
4. 提示词工程:强制“基于事实”
如果 AI 还在编造,那是因为你的 System Prompt 约束力不够。你需要给它戴上“脚镣”:
严格指令:
- 你只能使用【参考资料】中的信息回答。
- 如果资料不足以支持回答,请直接说“我的博客库中目前没有关于此细节的记录”,严禁发挥。
- 如果发现资料中有冲突,请罗列不同时期的观点。
真实世界的工程配置建议
既然你的语料库有 150 万字,你可以参考这个配置逻辑:
- 切片策略:采用 300-500 字/片段,设置 10% 的 Overlap(重叠)。重叠是为了防止某个核心知识点刚好被切断在两个片段中间。
- Top-K 选择:不要吝啬。现在的 API 窗口很大,你可以尝试 $k=10$ 到 $k=15$。15 个片段大约 5000-8000 字,这对于 GPT-4o 来说处理起来非常轻松。
- 引用校验:在输出中强制要求模型给出
[原文片段 ID]。这样你在前端可以做个校验,如果没有对应的 ID,就通过 UI 提醒用户“部分内容为 AI 生成”。
总结
RAG 不是为了限制 AI 的发挥,而是为了给它的发挥提供足够厚的“地基”。 当你的 $k$ 足够大(比如 $k=10$),且每个 $k$ 都带有丰富的上下文(Parent Document),你会发现 AI 写的 2000 字回答里,每一段都能在你的博客里找到原型。
这种“喂饭”的方式,你觉得在你目前的后端逻辑里,实现 Reranker 或者父子文档检索,哪一个的开发成本更高?
前端的渲染
流式markdown实现
思考阶段输出
回答阶段输出
多模态?
短期记忆
openai新接口打算让提问变成有状态的,例如v1/responses API 就会帮你记住对话上下文(Context),你下一次请求只需要传一个 response_id,而不需要把整个长长的对话历史(Monorepo 的代码、报错日志等)重复传一遍。这能极大降低你的 Token 成本和带宽压力
“状态”无法跨模型/跨平台。
这样岂不是把大模型变成了有状态?但我感觉他可能仅仅是厂商给做了个临时记忆协助而已。
而且这种厂商的记忆依然有缺点:
- “有状态”是有生命周期的(TTL)。OpenAI 帮你记住的 Context 通常是有有效期的(比如 24 小时或更短)。它适合你当前这一场“Debug 激战”,但不适合跨越几周的项目开发。你的 EverKnow 数字化身需要的是长达数月的记忆,这依然需要你用向量数据库(RAG)或私有数据库来实现。
- 窗口限制(Context Window)依然存在。即便服务器帮你记住了状态,模型总的 Token 窗口限制(比如 128k 或 200k)依然没变。如果你传了 10 万 Token 的代码,第二次请求加了新功能。第三次、第四次……对话堆积到上限时,模型依然会“失忆”。你的记忆系统职责: 你依然需要通过 Summarization(总结)或 Recursive Selection(递归选择)来修剪上下文,只把最重要的东西存入状态。
- “状态”无法跨模型/跨平台。如果你在 v1/responses 里用 GPT-5.4 Pro 存了一个状态,当你发现这个 Bug 需要换成 o3 来推理时,这个 response_id 往往是不通用的。你依然需要一份属于你自己的“标准格式记忆”,以便在不同模型间平滑切换。
长期记忆和知识库怎么搞
我在使用gemini的时候,会发现我每个新对话里面,他貌似还能知道我在之前对话问了啥。甚至他好像还知道我是干技术岗位的。
咱们在做一些智能体的时候,是不是也可以类似于”传统机器学习里给用户打标签“或”收集用户兴趣“的方式,给用户打上一些兴趣偏好的标签。从而在未来回答用户问题的时候”风格“、”口味“等更符合用户的习惯呢?
估计可以的。
然后我就发现了harmess,这不把我的疑问都给干完了么:
Hermes(爱马仕智能体)
Hermes(常被戏称为”爱马仕”)是一个具体的开源AI智能体框架,由硅谷AI实验室Nous Research开发。
核心特点:
- 自我进化:口号是”the agent that grows with you”(与你一同成长的Agent)
- 学习闭环:能从已完成任务中自动提炼经验,打包成可复用的”技能卡”
- 持久记忆:拥有多层记忆系统,跨会话记住用户偏好和习惯
- 产品化:MiniMax等公司基于Hermes构建了云端自我进化AI助手
除了我想到的长期记忆、用户画像。人家hermes还搞了”技能沉淀(把经验沉淀成skill)“。
知识库
长期记忆: 向量数据库(RAG),存储外部知识或长期经验。
一个成熟的 Agent 系统通常会这么干:
同时去向量数据库和 ES 里搜。
用 RRF (Reciprocal Rank Fusion) 算法把两边的结果合并。
这样既能搜到“西红柿”的语义,也能搜到“A123-B”这个特定的产品序列号。
https://gemini.google.com/app/85a4e2495a2a123d
元宝提供的不错
https://yuanbao.tencent.com/chat/naQivTmsDa/93b79c32-12a5-4f74-bbb9-684c2dfd96e0