简单讲讲你的Agent项目?
基于大模型实现ReAct模式下的自主规划能力,解决长线任务,学习检索与记忆规划。
我的项目核心就是ReAct框架。ReAct不是让模型一次性吐答案,而是把它塞进一个“思考-行动-观察”的循环里。

实际工程里,这个循环是在代码里用while实现的,每个循环把Thought + Action + Observation 拼成新的上下文喂给模型,直到模型输出Fianl Answer或者达到最大步数限制。每一步的Observation都是真实环境的反馈,不是模型瞎编的-这就是保证了长线任务的可靠性。
2.短期记忆的具体实现方式是什么?
短期记忆在工程上就是上下文窗口里当前正在用的那砣东西。
我采用“滑动窗口 + 触发式总结”策略:

  • 设定一个Token上线阈值(比如模型是16k,我设12k为警戒线);
  • 上下文里始终保留System Prompt + 最近2~3轮完整对话;
  • 一旦总Token超过警戒线,把历史对话丢给一个轻量级总结模型(或者用主模型自己总结),生成一段200~300token的摘要;
  • 然后摘要塞进上下文,替换掉那些被总结的早期轮次。

这里有一个细节,总结不是把对话“翻译”一遍,而是抽取关键信息-用户的目标是什么、已经完成了那些步骤、当前卡在哪、有哪些重要约束。这样才能保证后续对话不跑偏。
什么叫“快到上限了”?对话时怎么逐步叠加的?
“快到上限了”指的是上下文当前累积的Token数逼近了模型接口的硬限制或者你自己设置的安全水位。
对话的叠加逻辑,很多初学者是“覆盖”,其实是“追加”:
轮次1:[System] + [User_1] + [Assistant_1]  假设1500token
轮次2:[System] + [User_1] + [Assistant_1] +  [User_2] + [Assistant_2]  3000token

每一轮都是把新产生的query和Response拼接到已有上下文的末尾,然后整个包裹一起发给模型接口。模型没有“记忆”能力,它每次看到的都是这个拼接后的完整字符串。
所以如果一轮对话里工具调用特别多(比如调了5个工具,每个返回500Token的日志)。那这一轮。可能直接吃掉3000token,很快就把窗口撑爆了

4.如果对话轮次过多,你怎么去做优化?

三层设计

Layer1(System):包含角色设定、工具定义、输出格式约束。这部分绝对不能动,一动Agent的人设就崩了。
Layer2(近期窗口):最近2~3轮完整对话,确保模型对“对当前在干什么”有精准感知。为什么是2~3轮?因为大多数多步任务的核心上下文就在最近几轮里,在往前的已经被执行完了。
Layer3(历史摘要):把更早的对话压缩成一个“进度报告”,包含已完成目标、未完成目标、关键中间结果。
5.什么时候去触发这个总结动作?

触发条件有两个维度:
条件一:阈值触发。我用双阈值策略-硬阈值(接口上限的90%)和软阈值(接口上限的70%)。达到软阈值时,异步生成摘要并缓存;到达硬阈值时,同步阻塞当前对话,强制完成总结后再继续。同步阻塞会影响用户体验,所以软阈值提前准备是关键。

条件二:步数触发。当工具调用次数超过5步还没出结果,说明任务再绕远路,强制总结一次,帮模型“抬起头来看方向”。触发之后的操作不是简单调个API-要把当前上下文完整拷贝一份,再副本上做总结,然后原子性地替换上下文中的历史部分。绝对不能再线程里改到一半就发请求,否则并发场景下数据全乱。

6.是每一轮对话都要去做总结吗?
绝对不是。
每一轮都做总结的话,你会遇到三个问题:

  1. 计算开销爆炸:每次总结都是1次LLM调用,对话到50轮的时候你就的调50次额外的LLM,成本直接翻倍;
  2. 信息衰减加速:摘要再摘要,信息损失是指数级别的。第一轮总结可能保留80%信息,第二轮总结可能只剩60%,到第5轮基本剩“用户问了点啥”;
  3. 延迟不可接受:用户每说一句话都要等2~3秒的总结时间,产品直接凉凉。

只在触发条件满足时才做-平时就是老老实实做追加。

7.假设已进行10轮并做了总结,第11轮开始时,总结怎么处理?是重算还是叠加?
增量叠加,而非全量重算
第10轮结束时,你有一个摘要S_1-10,它已经消耗了比如300token。第11轮的新对话D_11有800token。第11轮开始时,你直接把S_1-10 + D_11拼一起发给模型。
不是把1~11轮全部拿出来重新总结一遍。全量重算的时间复杂度是O(n^2),而且耗费的Token是增量方式的10倍以上。
但这里有一个陷阱:如果S_1-10本身已经占了300Token,加上D_11有到了阈值,第12轮要触发新总结时,你需要对S_1-10 + D_11做一次新的总结,生成S_1-11,然后丢弃S_1-10这本质上是一个分层摘要树,每一层都是对上一层的压缩。

8.如果前10轮都变成了总结,那之前的原始上下文就不需要了吗?
其实原始上下文必须持久化存储,但不发送给模型。
存在数据库里的原始数据有什么用?

  • 审计溯源:当模型给出错误答案时,你得能回放“它当时看到什么”;
  • 摘要重建:如果发现摘要质量太差,可以重新生成,不用从零开始累计;
  • 长期记忆检索:用户的某句关键指令可能在摘要里被压缩丢了,但原始数据里还有,后续按需检索能找回来。

发给模型的永远只是那个压缩后的摘要 + 最近几轮

9.长期记忆可以按需检索召回,具体什么情况下需要检索?

长期记忆检索的触发时机取决于“当前问题对历史信息的依赖程度”:

我在项目里没做知识图谱,所以跨实体的复杂推理检索。
做了知识图谱,还能支持“用户A在3天前提到过的那个项目,和今天这个需求有什么关联”这类高阶检索。

10. 每轮对话都要注入记忆吗?长短期记忆是同时注入吗?

都不是。
短期记忆是常驻上下文-每一轮都在,不需要额外注入,它就在那儿。
长期记忆是按需动态注入-先走意图路由,路由判断需要查历史时,才去向量库去检索Top-K,把检索结果作为前缀拼到当前上下文里。
如果同时注入长短期记忆,那上下文里会塞满无关信息。比如用户问给我订个外卖,你同时把三个月前的聊天记录也塞进去,纯属浪费Token而且增加干扰。

11.如何减少工具过多带来的Token消耗?
工具多了,工具描述(schema)本身就能吃掉你一半的上下文。
举一个例子,一个完整的工具定义(带参数JSON Schema)通常200~5000Token,如果你有30个工具,光tool descriptions就占6000~15000Token,留给对话的就所剩无几了。
我的方案是意图识别+渐进式纰漏

关键数据:50个工具,用完整加载需要50*400=20000Token。用渐进式披露,第一轮50*20=1000Token,第二轮加载3个完整Schema消耗3*400=1200Token。总计2200Token,节省89%。
而且这个方法还有额外好处:模型在第一步看到的精简列表,选择工具的准确率反而上升了-因为干扰项少了,注意力更集中。

你的RAG是用什么技术实现的?
标准的RAG链路,但每一步都有工程细节:
1.文档预处理:按语义边界切分(不是暴力按500字切),用RecursiveCharacterTextSplitter 保留段落完整性,chunksize512,overlap64;
2.Embedding模型:用的是BGE-large-zh-v1.5,1024维,对中文语义支持好;
3.向量索引:存到Mulvus里,建IVF_FLAT索引,平衡速度和召回;
4.检索:query embedding后用余弦相似度召回Top-20;
5.Rerank:用BGE-reranker-v2对Top-20做精细排序,取Top-5送入LLM;
6.生成:把Top-5的原文拼接成上下文,加上如果你不知道就说不知道的instruction,送进主模型。

13.如何判断向量相似度?

本质是计算两个向量在高维空间里的夹角余弦值,值越接近 1 说明方向越一致,语义越相近。

除了余弦相似度,还了解其他相似度算法吗?

欧几里得距离

值域 [0, +∞),越接近 0 越相似。

14. 余弦相似度与欧几里得距离在工程应用中的具体区别是什么?

这道题我跪得最彻底。回来之后我把数学彻底补了一遍。

核心差异不是“一个看方向一个看距离”这么简单——真正的关键在于 Embedding 向量在训练时已经被归一化了。

绝大部分 Embedding 模型(包括 BGE、OpenAI Ada)输出的向量都是 L2 归一化的——也就是每个向量的模长 ||V|| = 1

在归一化前提下,余弦相似度和欧氏距离是数学等价的

所以当你用归一化向量时,按余弦排序和按欧氏排序的结果完全一样

那为什么业界都选余弦不选欧氏?

工程上选余弦的真正原因:余弦相似度在未归一化场景下也能工作,而欧氏在未归一化场景下会被模长差异主导,导致“高频词向量”永远比“低频词向量”距离更近。为了安全,大家都用余弦。

15.项目中一共使用了几个模型?分别是什么?

  1. Embedding 模型(BGE-large-zh) :1024 维,把文本转稠密向量,用于 RAG 索引和检索;
  2. 路由分类模型(BERT-base 微调) :轻量级 110M 参数,跑意图识别——因为它太小了,可以做到毫秒级响应,不占用主模型的宝贵上下文;
  3. 主 LLM(Qwen-72B 或 Claude 3.5) :负责所有推理、规划、生成;
  4. Rerank 模型(BGE-reranker-v2) :Cross-encoder 结构,对召回的 Top-20 做精细打分。

分工明确:小模型干脏活累活(路由、向量化),大模型干脑力活(推理生成),Rerank 做连接

16.如何控制模型的幻觉问题?

分层解释

  • 输入层:RAG 检索到的文档质量是防幻觉的根本。如果召回的都是垃圾,模型再怎么约束都白搭。所以 Rerank 那一步至关重要。
  • 推理层:温度调低到 0.1~0.3,减少模型的“创造性发散”。用 Chain-of-Thought 强制模型在输出最终答案前先写“推理过程”——一旦推理过程出现矛盾,可以在后处理里拦截。
  • 上下文层:System Prompt 里明确写“如果上下文中没有明确信息,直接回答‘我不知道’,不要编造”。实测这句话能降低 30% 的幻觉。
  • 输出层:要求模型在回答中标注引用来源 [Doc_3],后处理里校验这个 Doc_3 是否真的在上下文中。如果引用了不存在的文档,直接拒答。

17.如何观察模型召回了那些块?

这就是 RAG 的可观测性

我在项目里做了一个 “检索审计日志” ,每次 query 都记录四样东西:

  1. Query 原文;
  2. 向量检索召回的 Top-20 文档 ID 及其 cosine 分数;
  3. Rerank 之后的 Top-5 文档 ID 及其 rerank 分数;
  4. 最终拼进上下文的那 5 段原文。

有了这个日志,线上如果出了 bad case,可以直接回放:是检索没召回到相关文档(召回率问题)?还是召回了但 rerank 排下去了(排序问题)?还是召回了也排上去了但模型没用好(生成问题)?

三层归因,一层层查。

18. 最近了解的AI内容?

我说了 OpenClaw 和 Claude Code 源码

OpenClaw 是一个开源 AI 智能体,核心能力是让大模型获得本地 Shell 权限,自主执行终端命令。它的工作流完全是 ReAct 范式,但加了一层安全沙箱——所有系统调用都要经过一个权限审批模块。

19.讲一下Claudecode架构

Claude Code 是 Anthropic 的编码 Agent,背后是 50 万行 TypeScript。它的核心设计理念是 “工具隔离 + 无共享可变状态”

  • 有 40+ 个独立工具模块(文件读写、Bash 执行、代码搜索、测试运行等);
  • 每个工具有自己的输入 Schema、权限级别、执行逻辑;
  • 不存在跨工具共享的全局可变状态——所有状态通过上下文显式传递;
  • 查询引擎会把用户需求转成结构化的工具调用序列,然后在一个循环里顺序执行。

这其实是一种 “微服务化”的 Agent 架构——每个工具可以单独升级、单独测试、单独做权限管控,避免了一个工具出错把整个 Agent 拖垮。

20.Harness知识
 

Harness 是一个 Agent 工程化框架,核心思想是通过 分层规范文档 来约束编码 Agent 的行为:

  • AGENTS.md:定义 Agent 的角色边界和能力范围;
  • ARCHITECTURE:定义代码仓库的架构约束;
  • TASKS.md:定义当前任务拆解。

它的本质是把“提示词工程”升级为“规范工程”——让 Agent 不是靠一段又长又臭的系统提示词来理解任务,而是通过读取结构化文档来获得上下文。这样更可控、更可审计。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐