文章目录

Agent初步

Agent architecture

认识Agent的基础概念和工作流程

2025/2/18

Agent

1. 基础概念

Agent 是一个基于 LLM 的“决策循环系统”

它的核心不是模型,而是:

决策循环(Decision Loop)

1.1 Agent 的整体结构

第一层:LLM 能力层

包括:

  • 文本生成
  • function call(结构化输出)
  • structured output
  • streaming
  • reasoning

例如:

  • OpenAI 的 GPT 模型
  • Anthropic 的 Claude

这一层提供:

输入:context
输出:token 或 function call

模型本身:

不会调用工具 不会记忆 不会执行代码

它只是一个概率预测器。


第二层:上下文管理层(Context Layer)

Context 不仅仅是聊天记录,而是**Context =System Prompt+User Input+History+Tool Results+检索内容**

本质:

每次请求送给模型的 token 集合

Agent 的第一职责就是:

管理 context

第三层:Tool 层

Tool 是什么?

LLM 可以调用的外部能力

它本质是:

function xxx(args): result

例如:

  • 查天气
  • 查数据库
  • 调用搜索引擎
  • 执行代码
  • 调用支付 API

但需要注意的是,Tool ≠ Function Call

区别:

概念属于哪层
Function Call模型能力
Tool你封装的函数

Function Call 是模型“请求调用”。

Tool 是你真实执行的能力。


第四层:决策循环层(Agent 核心)

这是最关键的。

Agent 本质是:

while (not finished):
    1. 调用模型
    2. 判断是否需要工具
    3. 调用工具
    4. 把结果加入 context

这叫:ReAct 模式ReAct = Reason + Act

核心思想:

Thought
Action
Observation

第五层:Orchestration(编排层)

这是框架层。

例如:

  • LangChain
  • LlamaIndex
  • Microsoft 的 Semantic Kernel

它们做什么?

  • 管理 Tool
  • 自动循环
  • 管理 Memory
  • 管理 RAG
  • 管理多 Agent

‼️ 完整 Agent 架构图

User
  ↓
API Server
  ↓
Agent Controller
  ↓
 ┌───────────────┐
 │   Context     │
 └───────────────┘
        ↓
      LLM
        ↓
  是否需要 Tool?
        ↓
  Tool Executor
        ↓
  Observation
        ↓
  更新 Context
        ↓
     循环

1.2 核心概念

1.2.1 Function Call

本质

模型输出一个 JSON 结构

例如:

{
  "name": "get_weather",
  "arguments": { "city": "北京" }
}

模型不是执行函数。

它只是“建议你执行”。


1.2.2 Tool

Tool = 你暴露给模型的函数能力。

需要:

  • name
  • description
  • parameters schema

模型根据 description 决定是否调用。


1.2.3 Context(上下文)

在 LLM / Agent 系统中:

Context = 模型决策所依赖的全部信息

包括:

  1. 用户输入(User Query)
  2. 系统指令(System Prompt)
  3. 历史对话(Conversation History)
  4. 外部工具返回的信息(Observation / Tool Result)
  5. 检索到的文档 / 知识(RAG Result)
  6. 其他环境信息(日期、状态、用户偏好)

也就是说:

Context = 让模型“知道当前情况”的所有信息

‼️ Context 的作用

1️⃣ 让模型理解问题背景

  • 没有 context,模型无法分辨前后逻辑
  • 例如多轮对话中,如果没有历史消息,模型会忘记用户之前问过什么

2️⃣ 引导模型行为

  • System Prompt 是 Context 的一部分
  • 可以告诉模型“你是助手/客服/法律顾问”

3️⃣ 辅助工具调用

  • ReAct / Function Call / RAG 都需要 context
  • 例如模型决定调用哪个工具,需要知道用户意图 + 当前信息

4️⃣ 保持多轮一致性

  • 用 Memory 或向量数据库管理 context
  • 可以让 Agent 保持长期状态

‼️ Context 的组成结构

可以抽象成三层:

层级内容来源示例
System Context系统指令 / 风格开发者“你是智能客服,请礼貌回答”
User Context当前用户请求用户“帮我查北京天气”
Agent Context内部状态、历史消息、工具结果Agent / Memory / ToolThought、Observation、RAG 文档

‼️ Context 的类型

1️⃣ 短期上下文(Short-term Context)

  • 最近几轮消息
  • ReAct 循环中使用的实时上下文
  • 保存在 Agent 内存中或 session messages

2️⃣ 长期上下文(Long-term Context / Memory)

  • 历史记录 / 用户偏好 / 企业知识
  • 通常存入向量数据库或知识库
  • 可通过 RAG 检索注入

3️⃣ 环境上下文(External Context)

  • 时间、位置、系统状态、API 数据
  • 可以作为模型的额外输入
  • 例如天气 API 返回结果

‼️ Context 的管理方式

1️⃣ Message Stack(消息堆栈)

  • 最简单方式
  • 每次对话把消息全部发送给模型

缺点:

  • 上下文窗口有限
  • 长对话可能超 token

2️⃣ Sliding Window(滑动窗口)

  • 只保留最近 N 轮消息
  • 对旧消息进行摘要压缩或丢弃

3️⃣ Vector Memory(向量记忆)

  • 把长期 context 转成 embedding
  • 检索 top-k 与当前 query 最相关的内容
  • 和 RAG 紧密结合

4️⃣ Structured Memory(结构化记忆)

  • 将 context 结构化存储(如 JSON / 数据表 / key-value)
  • 方便 Agent 读取、修改、推理
  • 常用于复杂 Agent 或多 Agent 系统

‼️ Context 的工程问题

1️⃣ 上下文超长

  • Token 窗口有限,超长会被截断
  • 解决:摘要、截断、分块、分轮管理

2️⃣ 上下文污染 / 冲突

  • 多工具或 RAG 返回信息矛盾
  • 解决:标记来源、加优先级、去重、摘要

3️⃣ 信息遗忘

  • 模型无法记住长期信息
  • 解决:Memory + RAG 检索长期上下文

4️⃣ 隐私问题

  • 用户数据可能被泄露
  • 解决:context 隔离、加密、敏感信息脱敏

5️⃣ 性能问题

  • context 太大 → token 消耗大 → 响应慢
  • 解决:缓存、向量检索、分步加载

‼️ Context 的优化策略

1️⃣摘要压缩

  • 对旧消息或文档做摘要,减少 token
  • 例:今天用户提了关于支付的问题 → 代替原始对话

2️⃣分块注入

  • RAG 文档分块只注入最相关的部分
  • 避免噪声信息干扰模型

3️⃣优先级管理

  • 最新用户请求 > 工具返回 > 历史消息
  • 防止模型被旧信息误导

4️⃣Context + ReAct

  • Thought、Observation 都要加入 context
  • 下一轮决策才完整

‼️ Context 与 Memory 的关系

概念定义作用
Context当前决策可见信息决策和推理基础
Memory历史信息存储为 context 提供补充,长期保留
RAG检索知识将 memory 注入 context,用于增强回答

总结:Memory + RAG = context 的动态补充 context = 决策的“即时全局视图”


‼️ Context 的抽象公式

可以这样形式化:

contextₜ = system_prompt + user_inputₜ + memory_contextₜ + observationₜ

模型输出依赖 contextₜ:

outputₜ = LLM(contextₜ)

ReAct 循环中,每轮 contextₜ 更新:

contextₜ₊₁ = contextₜ + Thoughtₜ + Actionₜ + Observationₜ

1.2.4 Memory

Memory 是:

上下文的长期管理策略

分两种:

短期记忆(Short Term)

直接 append 到 messages。


长期记忆(Long Term)

通常用:

Vector DB

通过 RAG 检索后插入 context。


1.2.5 RAG(检索增强生成)

RAG所解决的核心问题:

大模型不知道你的私有数据

模型训练数据是:

  • 公网数据
  • 公开知识
  • 截止到某个时间点

但现实场景需要:

  • 公司内部文档
  • 实时数据库数据
  • 用户个人数据
  • 法律合同
  • 产品说明书

如果你直接问模型:

公司 2025 Q1 营收多少?

它会:

  • 瞎编
  • 或回答不知道

所以我们要:

先找资料
再让模型回答

这就是 RAG。


‼️ RAG 的核心思想

在模型回答前,先从知识库检索相关内容,并注入上下文。

流程:

用户问题
   ↓
向量化
   ↓
向量数据库检索
   ↓
取出最相关文档
   ↓
拼接到 prompt
   ↓
模型生成回答

‼️ RAG 系统完整结构

第一层:数据准备(Indexing 阶段)

这是一个离线过程。

1️⃣ 文档收集

  • PDF
  • Markdown
  • Notion
  • 数据库
  • API

2️⃣ 文本切分(Chunking)

不能整本书直接丢进去。

要:

按 300~1000 token 切块

为什么?

因为:

  • 向量搜索粒度更精确
  • 上下文窗口有限
  • 大块会浪费 token

3️⃣ 生成向量(Embedding)

把文本转成向量。

例如:

使用 OpenAI 的 embedding 模型。

"北京今天晴天"
→ [0.123, -0.982, ...]

4️⃣ 存入向量数据库

例如:

  • Pinecone
  • Weaviate
  • Milvus
  • Qdrant

本质存储:

vector + 原文

第二层:查询阶段(在线过程)

1️⃣ 用户提问

公司 2025 Q1 营收多少?

2️⃣ 向量化问题

同样生成 embedding。


3️⃣ 相似度搜索

计算:

cosine similarity

找出最接近的几个文档块。


4️⃣ 拼接 prompt

已知资料:
[文档1]
[文档2]
[文档3]

请根据资料回答:
公司 2025 Q1 营收多少?

5️⃣ 模型生成

模型“基于资料”回答。


‼️ 向量到底是什么?

这是很多人真正模糊的地方。Embedding 是:

把“语义”映射到高维空间

例如:

猫
狗
动物

它们在向量空间里距离很近。

而:

猫
火箭

距离远。

所以:

向量距离 ≈ 语义相似度


‼️ RAG 的局限

RAG 不是万能的,它不适合:

  • 数学计算
  • 复杂逻辑推理
  • 长链式决策

那是 Agent 的领域。


1.2.6 MCP(Model Context Protocol)

MCP 是:

一个标准化的 Tool 通信协议

它的目标是:

让“模型如何调用外部能力”变成一个标准,而不是每家公司各写一套。


‼️ MCP解决的问题

在 MCP 之前,大家是怎么做的?

例如用 OpenAI 的 function call:

{
  "name": "get_weather",
  "arguments": { "city": "北京" }
}

然后:

  • 你自己解析
  • 自己执行
  • 自己拼接结果
  • 自己做权限控制

每个公司:

  • schema 不一样
  • tool 描述方式不一样
  • 权限系统不一样
  • context 注入方式不一样

这在企业环境里会产生:

  • 安全风险
  • 接口混乱
  • 无法统一管理

‼️ MCP 解决的核心问题

可以总结为四个字:

标准化 + 安全化

它主要解决:


1️⃣ 工具描述标准化

统一 tool 的定义格式。

而不是每个框架一套。


2️⃣ 工具调用协议化

工具调用变成:

模型 <—> MCP Server <—> 外部系统

而不是模型直接“随便调用”。


3️⃣ 权限控制

MCP 强调:

模型不应该拥有无限权限

例如:

  • 是否允许访问文件?
  • 是否允许访问数据库?
  • 是否允许发 HTTP 请求?

都需要声明。


4️⃣ 上下文管理规范

MCP 规范:

  • 哪些信息可以注入模型
  • 哪些信息不能暴露
  • 如何限制 context

‼️ MCP 的核心架构

抽象结构如下:

User
  ↓
LLM
  ↓
MCP Client
  ↓
MCP Server
  ↓
Tool / Database / Filesystem

‼️ MCP 和 Function Call 的区别

很多人以为 MCP = function call。

其实不一样。

对比Function CallMCP
属于模型能力系统协议
控制层应用层基础设施层
是否标准化各家不同统一规范
是否强调权限不强制强调安全模型

更直观理解:

Function Call 是:

模型输出一个 JSON

MCP 是:

一个完整的通信标准

一句话:

MCP 是 AI 时代的“操作系统接口规范”。

就像:

  • HTTP 统一了 Web 通信
  • SQL 统一了数据库访问

MCP 试图统一:

模型访问世界的方式


1.2.7 ReAct

ReAct = Reason + Act

核心思想:

让模型一边“思考”,一边“行动”,并根据行动结果继续思考。

在它之前,大模型基本只有:

  • 直接回答
  • Chain of Thought(只思考,不行动)

ReAct 做了一个关键突破:

思考 → 行动 → 观察 → 再思考 → 再行动

这就是现代 Agent 的原型。


‼️ ReAct 解决什么问题?

假设用户问:

2024 年奥运会冠军是谁?

模型如果不知道,会:

  • 或胡编

但如果允许它:

  • 调用搜索
  • 再根据搜索结果回答

准确率就大幅提升。

ReAct 提出:

不要一次性思考完 让模型可以中途行动


‼️ ReAct 的核心结构

ReAct Prompt 通常长这样:

Question: xxx

Thought: 我需要先查一下
Action: Search[xxx]
Observation: 搜索结果

Thought: 根据结果我可以回答
Final Answer: ...

关键三步:

Thought
Action
Observation

这三步构成一个循环。


‼️ ReAct 的循环本质

本质上是一个状态机:

while (not finished) {
  Thought = LLM(context)
  if (需要行动) {
    Observation = Tool(Action)
    context += Observation
  } else {
    输出答案
    break
  }
}

你之前写的 mini-agent,本质就是 ReAct。


‼️ReAct 和 Function Call 的关系

ReAct 是“思想”

Function Call 是“实现手段”

早期 ReAct:

  • 模型输出纯文本
  • 开发者用正则解析 Action

现代实现:

  • 用 function call 结构化输出
  • 不再需要解析字符串

所以现在:

Function Call 是 ReAct 的工程实现方式


‼️ ReAct vs Chain-of-Thought

对比Chain-of-ThoughtReAct
是否调用工具
是否有 Observation
是否可交互
是否适合 Agent

Chain-of-Thought 只是:

想清楚再回答

ReAct 是:

想一部分 → 查一部分 → 再想

1.2.8 Embedding

Embedding = 将对象(通常是文本、图片或其他数据)映射到一个高维向量空间,用数字向量表示其语义特征

特点:

  1. 固定长度:无论文本多长,embedding 通常是固定维度(例如 1536 维)
  2. 语义相似性:相似语义 → 向量距离近,差异语义 → 距离远
  3. 可计算相似度:通常用 cosine similarity 或 L2 距离

例子:

"北京天气"  → [0.12, -0.34, 0.56, ...]
"天气预报"  → [0.11, -0.35, 0.55, ...]

距离很近 → 语义相关


‼️ Embedding 的作用

1️⃣ 语义检索(Semantic Search)

  • 通过 embedding 比较向量距离,找出语义最相关的信息
  • 例如 RAG 中检索文档

2️⃣ 长期记忆(Memory)管理

  • 长期 context 太大不能直接丢给模型
  • embedding 存入向量数据库 → 查询最相关上下文注入 prompt

3️⃣ 工具选择 / 决策

  • 根据 query embedding 找最合适的工具或任务

4️⃣多模态表示

  • 图片、文本、音频都可以转为 embedding,便于统一处理

‼️ Embedding 的生成流程

假设你要把一段长期 context 转成 embedding:

"用户上周购买了智能手表,偏好夜间模式。"

生成流程:

1️⃣文本切分(Chunking)

  • 大文本切成小块,方便检索
  • 例如 100~200 字

2️⃣调用 Embedding 模型

  • 例如 OpenAI text-embedding-3-large
  • 输出固定维度向量(如 1536 维)
import OpenAI from "openai";
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

const embeddingRes = await client.embeddings.create({
  model: "text-embedding-3-large",
  input: "用户上周购买了智能手表,偏好夜间模式。"
});

const vector = embeddingRes.data[0].embedding;

3️⃣存储向量

  • 向量数据库(Pinecone、Weaviate、Milvus、pgvector)
  • 可以加 metadata,例如原文、时间、来源

‼️ 长期 context 如何利用 embedding

当用户提问新问题:

  1. 将 query 转 embedding
  2. 向向量数据库检索 top-k 相似向量
  3. 取对应原文/文档,注入当前 context → 供 LLM 使用
User query: "上次我买的手表电量怎么样?"
Embedding 检索: "用户上周购买了智能手表,偏好夜间模式。"
注入 context → 模型回答

这样就实现了长期记忆 + 动态 context


‼️ 向量在 Agent/RAG/Memory 中的作用

场景作用
RAG检索相关文档 → 注入 prompt
Memory管理长期用户信息或对话历史
Tool Selection根据 query embedding 找最匹配的工具
Multi-Agent Coordination找到相关任务或状态

‼️ 工程实践问题

1️⃣ 向量存储

  • 选择数据库和索引类型(HNSW、IVF、PQ)

2️⃣ 更新/删除

  • 用户长期 context 变化,需要更新 embedding
  • 删除敏感信息

3️⃣ 检索效率

  • 高维向量检索慢 → 用近似最近邻(ANN)算法

4️⃣ embedding drift

  • 模型更新后 embedding 可能语义偏移 → 定期重建

‼️ 长期 context → embedding 总结流程

1. 收集长期 context → 文本/文档/对话
2. 文本切分(chunking)
3. 调用 embedding 模型生成向量
4. 存入向量数据库,带 metadata
5. 用户新 query → 生成 query embedding
6. 向量检索 top-k 相似内容
7. 将检索结果注入当前 context

本质:embedding 是长期 context 的可检索语义表示


‼️ 知识结构树

Agent
│
├── LLM 能力
│     ├── Text Generation
│     ├── Function Call
│     ├── Structured Output
│
├── Context
│     ├── System Prompt
│     ├── History
│     ├── Tool Result
│     ├── RAG
│
├── Tools
│     ├── API
│     ├── DB
│     ├── Search
│
├── Memory
│     ├── Short Term
│     ├── Long Term
│
├── Decision Loop
│     ├── ReAct
│     ├── Planner
│
└── Orchestration Framework
      ├── LangChain
      ├── LlamaIndex
      ├── Semantic Kernel

2. 工作流程

假设用户问:

“帮我查一下北京的天气,并告诉我今天是否适合跑步。”


1️⃣ 用户输入

User Input: "帮我查一下北京的天气,并告诉我今天是否适合跑步。"

这个输入会被加入 Context,连同系统提示(System Prompt)和历史对话。


2️⃣ 模型生成输出

模型根据 Context 做两件事:

  1. 思考(Thought)
    • “我需要查天气,才能判断是否适合跑步”
  2. 决定行动(Action / Function Call)
    • 输出一个 JSON,表示想调用的工具和参数

示例 Function Call 输出:

{
  "name": "getWeather",
  "arguments": {
    "city": "北京"
  }
}

注意:这里模型只是“说我要干什么”,它并没有自己去查天气。


3️⃣ 系统执行工具

Agent / 框架拿到 JSON:

  1. 解析 namearguments
  2. 调用实际函数 / API
const args = JSON.parse(funcCall.arguments);
const result = await getWeather(args.city);

工具返回结果,例如:

{
  "temperature": "18°C",
  "weather": "",
  "suitable_for_running": true
}

4️⃣ Observation 注入 Context

工具返回的结果加入 Context

Observation: { "temperature": "18°C", "weather": "晴", "suitable_for_running": true }

模型下一轮可以参考这个 Observation 继续推理或回答。


5️⃣ 生成最终回答

模型根据 Context + Observation 输出最终回答:

"今天北京天气晴,温度 18°C,非常适合跑步。"

概念作用
User Input当前 query,是 Context 的一部分
Context让模型知道历史和环境信息
Thought (ReAct)模型判断下一步动作
Function Call模型输出的结构化行动指令
Tool实际执行功能(API / 函数)
Observation工具返回结果 → 更新 Context
MCP(可选)管理权限和安全,确保模型调用工具安全可靠
Embedding(长期 context)检索历史信息注入当前 Context,使模型有长期记忆

‼️ 关键点总结

  1. 模型不会自己执行函数
    • 它只会生成 Function Call 或行动指令
  2. Agent 执行 Function Call
    • 系统根据 JSON 输出调用对应工具
  3. Observation 注入 Context
    • 下一轮决策参考工具结果
  4. 循环执行(ReAct)
    • 如果需要进一步行动,模型可以继续生成 Function Call
  5. 长期记忆 / RAG
    • 通过 embedding 检索历史 context,补充给模型

同时给出一个以OpenAI为例的简易Demo

// tools.ts

export async function getWeather(city: string) {
  return `北京今天晴天,25度`;
}

// agent.ts

import OpenAI from "openai";
import { getWeather } from "./tools";

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY!,
});

type Message = {
  role: "system" | "user" | "assistant" | "tool";
  content: string | null;
  tool_call_id?: string;
};

async function runAgent(userInput: string) {
  const messages: Message[] = [
    {
      role: "system",
      content: "你是一个智能助手,可以调用工具解决问题。",
    },
    {
      role: "user",
      content: userInput,
    },
  ];

  while (true) {
    const response = await client.chat.completions.create({
      model: "gpt-4o-mini",
      messages,
      tools: [
        {
          type: "function",
          function: {
            name: "get_weather",
            description: "获取某个城市的天气",
            parameters: {
              type: "object",
              properties: {
                city: {
                  type: "string",
                  description: "城市名称",
                },
              },
              required: ["city"],
            },
          },
        },
      ],
    });

    const message = response.choices[0].message;

    // 如果模型想调用工具
    if (message.tool_calls && message.tool_calls.length > 0) {
      const toolCall = message.tool_calls[0];

      const args = JSON.parse(toolCall.function.arguments);
      const result = await getWeather(args.city);

      // 把 assistant 的 tool call 记录下来
      messages.push(message);

      // 把工具结果塞回去
      messages.push({
        role: "tool",
        tool_call_id: toolCall.id,
        content: result,
      });

      continue; // 继续循环
    }

    // 否则就是最终答案
    console.log("Final Answer:", message.content);
    break;
  }
}

runAgent("帮我查一下北京天气");

3. 实际场景

3.1 模型能力相关问题

1️⃣ Function Call 输出不准确 / 无法解析

  • 原因
    • 模型可能输出不符合 schema 的 JSON
    • 工程上对 JSON 解析依赖严格格式
  • 场景
    • 用户问“查北京天气”,模型输出多余文字或者格式错误
  • 解决思路
    • 对输出进行验证(JSON Schema 验证)
    • 加 prompt 指令强制输出标准 JSON
    • 失败重试 + fallback

2️⃣ 幻觉(Hallucination)

  • 原因
    • 模型本身在知识不足或上下文不完整时会胡编
  • 场景
    • Agent 调用 RAG,但检索结果不充分
  • 解决思路
    • 强制引用来源
    • 提高 RAG 精度
    • 使用外部工具验证(calculator, database)

3️⃣ 生成延迟 / 速度慢

  • 原因
    • 模型调用时间长
    • 多轮 ReAct 循环增加 token
  • 解决思路
    • 流式输出 (streaming)
    • 限制循环次数
    • 缓存历史回答

3.2 上下文与 Memory 问题

1️⃣ Context Window 超限

  • 原因
    • 长上下文 + 多轮 ReAct + RAG
  • 场景
    • Agent 连续调用工具 5 次,messages 过长
  • 解决思路
    • 压缩 Memory(summary)
    • 截断不重要历史
    • 向量数据库管理长期记忆

2️⃣ Memory 冲突 / 信息重复

  • 原因
    • 不同工具返回的信息重复或矛盾
  • 解决思路
    • 文本去重
    • 加入上下文来源标记
    • 确定优先级规则

3.3 工具调用相关问题(Tools / MCP)

1️⃣ 工具调用失败

  • 原因
    • API 超时
    • 权限不足
    • Tool 内部异常
  • 解决思路
    • 异常捕获
    • 超时重试
    • fallback 工具(例如备用 API)

2️⃣ 安全与权限问题

  • 原因
    • Agent 有能力访问敏感资源(文件、数据库)
  • 解决思路
    • 使用 MCP 或自定义安全网关
    • 限制工具权限
    • 审计日志

3️⃣ 工具接口变化

  • 原因
    • 后端 API 改动
  • 解决思路
    • version 控制
    • 接口抽象层

3.4 RAG / 知识增强相关问题

1️⃣ 检索结果噪声大

  • 原因
    • 向量检索精度不足
    • 文档切块过大或过小
  • 解决思路
    • 使用 rerank
    • hybrid search(关键词 + 向量)
    • 调整 chunk size

2️⃣ 上下文注入冲突

  • 原因
    • 多个检索结果同时放入 prompt
    • 模型忽略或者冲突
  • 解决思路
    • 精简或摘要文档
    • 分步问答(multi-turn RAG)

3️⃣ 实时数据难以覆盖

  • 原因
    • 向量数据库不是实时更新
  • 解决思路
    • 实时索引
    • hybrid retrieval(结合数据库查询 + RAG)

3.5 ReAct 循环 / Agent 决策问题

1️⃣ 循环次数不可控 / 无限循环

  • 原因
    • Agent 判断“是否需要工具”逻辑不完善
  • 解决思路
    • 最大循环步数
    • 条件触发退出
    • 设置 fallback 策略

2️⃣ 工具调用顺序错乱

  • 原因
    • ReAct 思考和行动顺序复杂
    • 多工具依赖关系
  • 解决思路
    • Planner + Executor 拆分
    • DAG 任务管理

3️⃣ 多 Agent 协作复杂

  • 原因
    • 多 Agent 间通信、共享 Memory、同步状态困难
  • 解决思路
    • 统一共享 context
    • 使用消息队列或事件总线
    • step-by-step 调度

3.6 工程和成本问题

1️⃣ Token 成本高

  • ReAct + RAG 循环次数多 → token 大量消耗 → 成本高
  • 解决:
    • 压缩 context
    • 缓存回答
    • 优化 RAG top-k

2️⃣ 可观测性差

  • Agent 运行过程难以追踪
  • 解决:
    • 日志记录每轮 Thought / Action / Observation
    • token 统计、响应时间监控
    • tool 调用审计

3️⃣ 可扩展性 / 部署问题

  • 高并发场景下多 Agent 调度复杂
  • 解决:
    • 分布式 Agent 架构
    • 使用队列 / 微服务
    • 异步执行

3.7 总结 — 实际开发痛点矩阵

分类问题工程解决思路
模型输出不规范JSON 验证 / prompt 强化
模型幻觉强引用 / RAG / 验证工具
Context超长summary / 截断 / vector memory
Context冲突标记来源 / 去重
Tool调用失败异常捕获 / 重试 / fallback
Tool安全风险MCP / 权限控制 / 审计
RAG噪声大rerank / hybrid search / chunk 调整
ReAct循环无限max step / fallback / Planner
成本token 高压缩 context / cache / top-k
运维可观测性差日志 / tracing / metric

总结一句话:

Agent 开发的痛点集中在 循环管理、上下文管理、工具调用安全、RAG 精度,以及成本控制和可观测性

这些问题解决好了,你的 Agent 才能从实验室走向生产环境。