AI名词

0 阅读1小时+

我的认知

一切皆是对 LLM 输入/输出的加工

你总结得非常精准——我们现在学的所有技术,本质上都是在做两件事

  1. 输入加工:把用户原始的、模糊的需求,转化成 LLM 能理解、能执行的精确指令(Prompt)。
  2. 输出加工:把 LLM 生成的原始文本,解析、验证、转换成用户需要的最终结果。
技术/概念本质输入加工输出加工
RAG把外部知识库的信息,加工成 Prompt 中的“上下文”将检索到的文档片段拼接到用户问题前面让 LLM 基于这些事实生成答案,减少幻觉
Function Calling把工具描述加工成 Prompt,再把 LLM 输出的工具指令解析成实际调用将工具的名称、描述、参数结构写入 System Prompt解析 LLM 输出的 Action(如 get_weather),触发实际函数
MCP标准化工具的发现和调用,本质上也是输入输出格式的统一加工客户端通过 MCP 获取工具列表,转换成 LLM 能理解的格式服务器执行工具后,将结果加工成 LLM 能读的 Observation
SKILLs把业务专家的经验加工成标准化的执行流程在 System Prompt 中注入完整的步骤、规则、注意事项确保 LLM 的输出符合业务规范(如固定的报表格式)
Agent (ReAct)把“思考-行动-观察”的循环规则加工成 Prompt,再把每一步的结果解析并拼回对话用 System Prompt 定义思考格式(Thought/Action/Observation)解析每一步的 Action,执行工具,将 Observation 拼回对话
记忆模块把对话历史加工成当前 Prompt 的一部分短期记忆:拼接近期对话;长期记忆:检索相关历史拼入(间接作用)让 LLM 生成更连贯、个性化的回答
输出解析器纯粹的输出加工把 LLM 返回的文本解析成 JSON、Pydantic 对象等结构
LCEL把输入输出加工的流程用统一语法编排起来用 `` 串联各种加工步骤用 `` 串联各种加工步骤
评估监控对 LLM 的输出进行二次质检对 LLM 回答进行打分、校验,发现异常

🧠 为什么会是这样?

因为 LLM 本质上是一个“文本进,文本出”的超级预测引擎。它内部是黑盒,它只懂文本。为了让这个“文本引擎”完成复杂的业务任务,我们必须:

  1. 在输入侧:把所有业务信息(知识、工具、历史、规则)都翻译成它懂的语言——也就是精心构造的 Prompt。
  2. 在输出侧:把它吐出来的“原始文本”翻译回业务系统能用的语言——也就是结构化数据、工具调用、数据库操作。

所以,整个 AI 应用开发,就是围绕 LLM 这个核心,搭建一套双向翻译系统

deepseek_mermaid_20260309_222686.png

deepseek_mermaid_20260309_d2ad8b.png

RAG 是什么?

RAG 是 Retrieval-Augmented Generation 的缩写,中文叫检索增强生成

通俗地说:让大模型在回答问题之前,先“查资料”,再“开口”。 让 LLM 能够实时查阅外部知识库(比如最新的网页、公司文档、数据库),然后基于查到的真实资料来回答。尽量避免大模型出现所谓的幻觉

RAG 的工作原理(三步走)

整个过程就像学生参加“开卷考试”:

  1. 索引(准备资料) :提前把各种文档(比如公司手册、维基百科)切分成片段,向量化,存入向量数据库。
  2. 检索(查资料) :用户问一个问题(比如“RAG 怎么用?”)。系统先把问题也转换成向量,然后去向量数据库里搜索最相关的几个片段(这里可能用到混合搜索,既匹配关键词又匹配语义)。
  3. 生成(写答案) :把用户的问题 + 检索到的相关片段,一起塞给大模型,并提示它:“请根据这些资料回答问题”。大模型就会基于提供的资料,生成一个有理有据的答案,而不是凭空想象。

RAG 的关键组件(和你之前了解的概念完美对应)

  • 知识库(文档) :原始的 PDF、网页、数据库。

  • 文本切分器:把长文切成合适的小块。

  • 嵌入模型:把文本块变成向量(计算机可以理解的多维数组)。

  • 向量数据库:存储向量并支持快速检索(类比于数据库)。

  • 检索器:执行搜索(可以用混合搜索来提升精度)。

  • 大语言模型(LLM) :根据问题+检索结果,生成最终答案。

  • 向量库 & 嵌入模型:嵌入模型将文本转换为多维数组(向量),存入向量库。计算机通过比较向量间的距离(如余弦相似度)来衡量语义相似度,从而实现语义检索。

  • 余弦相似度:通过计算两个向量在高维空间中的夹角余弦值(0°表示完全相同,90°表示不相关 180°代表意思相反)来判断语义相似度,是向量检索的核心算法。

多维数组当维度达到一定值(比如 768 或 1024)后,再增加维度带来的效果提升会逐渐变小。因此很多主流模型选择 768 或 1024 作为平衡点。

实际选择建议:
如果做通用知识库检索,用 1024 或 1536 维的模型通常就足够了;如果做实时对话系统且数据量巨大,可以考虑 384 维的轻量模型来降低成本。

客服RAG的核心架构(5层结构)

第一层:知识库准备(预处理阶段)

这是基础,质量决定了RAG效果的天花板。

  • 数据源

    • 非结构化:产品说明书、帮助文档(PDF/Word)、过往的客服对话记录(这部分非常有价值,包含了真实用户的各种问法)、培训手册。
    • 半结构化:FAQ(常见问题解答)、商品库(规格、价格)。
    • 结构化:订单系统、物流系统(实时数据)。
  • 处理流程

    • 清洗:去掉对话记录里的语气词、重复信息。
    • 切分:你之前关心的切分问题,在客服场景里通常采用层级切分。比如,把一个产品的帮助文档,按"产品线 → 功能模块 → 具体操作步骤"进行切分,保证每个片段语义完整。
    • 向量化:将这些片段转换成向量,存入向量数据库。
第二层:用户意图识别与路由

用户发来一句话:"我的订单怎么还没到?"

系统首先要判断:这是查知识还是要办事

  • 意图识别:可以用一个轻量级的分类模型,或者直接让大模型判断。

    • 如果是"查知识" :比如"怎么退款?",走下面的RAG检索流程。
    • 如果是"要办事" :比如"帮我改一下收货地址"、"我要退货",则触发 Function Calling / MCP,调用后台API去执行操作。
    • 如果是闲聊:比如"你好",可以走预设的欢迎语。
第三层:混合检索(你之前问过的重点)

当判断用户是来问问题后,系统开始找答案。为了确保准确率,不会只用向量搜索。

  • 多路召回

    • 向量检索:找语义相似的内容(比如用户说"东西坏了",知识库里写的是"产品质量问题",向量能匹配上)。
    • 关键词检索:利用ES(Elasticsearch)进行精确匹配,尤其对产品型号(iPhone 15 Pro)、订单号这种专有名词,必须精确命中。
    • 知识图谱:如果有,可以用于多跳问答。比如用户问"iPhone 15 Pro支持快充吗?",系统需要知道"iPhone 15 Pro"属于哪类产品,快充协议是什么,然后从图谱里找到关系。
  • 重排序

    • 多路召回可能会拿回几十个候选片段。
    • 用一个专门的重排序模型(Reranker) ,把这些候选片段和用户问题放在一起,再进行一次更精细的相关性打分,选出最相关的3-5个片段。
第四层:答案生成(大模型登场)

把用户的问题和筛选出的相关片段,一起交给大模型,并配上精心设计的提示词。

提示词示例:

text

复制下载

你是一个专业的客服助手。请基于以下参考资料,回答用户的问题。
要求:
1. 如果参考资料里有答案,请用礼貌、专业的语气回答。
2. 如果参考资料里没有答案,请直接说“我没有查到相关信息,请尝试换个问法或联系人工客服”,不要编造。
3. 如果问题涉及订单号、手机号等个人信息,提醒用户注意保护隐私。
4. 回答结束时,可以提供1-2个相关的后续问题建议。

参考资料:
{这里放入检索到的3个片段}

用户问题:{用户输入}
第五层:对接业务系统与人工(闭环)

AI生成答案后,怎么给到用户?

  • 纯AI模式:直接回复给用户。适用于FAQ类问题。

  • 人机协同模式(辅助人工)

    • AI生成的答案和推荐的知识,不直接发给用户,而是弹窗显示在人工客服的操作界面上
    • 人工客服看一眼,觉得没问题,点击"发送";觉得有问题,可以修改后再发送。
    • 这是一个非常重要的兜底策略,既能保证准确率,又能让人工客服感受到AI是在帮自己,而不是抢自己的工作。
  • 反馈循环

    • 用户是否满意?可以对回答点👍或👎。
    • 客服是否采纳了AI的建议?
    • 这些反馈数据收集起来,用于评估RAG效果,发现哪些问题答不好,进而优化知识库或检索策略。

MCP 是什么?

MCP 是由 Anthropic 发起并开源的开放协议,全称是 Model Context Protocol(模型上下文协议)。它的目标是统一 AI 应用程序与外部数据源、工具之间的通信方式

你可以把它理解为 AI 世界的  “USB-C 接口” ——无论你用什么 AI 客户端(比如 Claude Desktop、IDE 插件、自定义应用),只要它支持 MCP,就可以通过一套标准的方式,连接到任何实现了 MCP 协议的“工具服务器”(比如本地文件系统、数据库、API 服务、搜索引擎等),并自动发现和使用这些工具。

MCP 解决了什么问题?

在没有 MCP 之前,如果你想给 AI 接入一个自定义工具(比如查询公司内部数据库),你需要:

  • 为每个 AI 模型单独写一套工具描述(OpenAI 的 function calling 格式、Anthropic 的 tool use 格式……)。
  • 每次新增工具,都要修改 AI 客户端的代码,重新部署。
  • 工具与客户端紧耦合,无法复用。

MCP 希望解耦:让工具开发者只写一次“MCP 服务器”,就能被所有支持 MCP 的 AI 客户端使用;AI 客户端也只需实现 MCP 协议,就能无缝接入成千上万的工具生态。

MCP 的核心组件

  1. MCP 客户端:AI 应用(如 Claude Desktop、聊天机器人后端)负责连接用户和服务器。

  2. MCP 服务器:一个轻量级程序,封装了具体的能力(如读取本地文件、查询天气 API、操作数据库)。服务器通过 MCP 协议暴露三样东西:

    • 资源:可读的数据(如文件内容、表格)。
    • 工具:可执行的函数(如 send_emailget_weather)。
    • 提示词模板:可复用的对话模板。
  3. 协议:基于 JSON-RPC 的消息格式,定义了客户端与服务器如何握手、如何发现能力、如何调用工具、如何传输结果。

deepseek_mermaid_20260226_d09163.png

MCP 客户端

MCP客户端不是一个简单的数据管道,它内嵌于AI应用(主机)中,是连接AI模型与外部世界的智能调度与管理中心。它的核心工作可以概括为以下几点:

  • 1. 连接的建立与管理者:根据配置,启动、连接并维护与一个或多个MCP服务端的独立通信通道。
  • 2. 能力的发现与注册者:在连接建立后,主动向服务端查询其提供的工具(Tools)清单,并将这些工具的能力(名称、描述、参数格式)在本地注册和缓存起来。
  • 3. 协议的翻译与适配器:这是最核心的适配工作。它需要将AI模型(如OpenAI、Claude、文心一言)特有的Function Calling格式,与MCP服务端统一的JSON-RPC格式进行双向转换。
  • 4. 调用的执行与流程控制器:接收AI模型发出的工具调用指令,找到正确的服务端连接,发起调用请求,并将服务端返回的结果反馈给AI模型,完成一次完整的“思考-行动-反馈”循环。
  • 5. 安全的守卫者:管理认证信息(如API密钥),在执行调用前进行权限校验,确保操作的安全性。

MCP客户端流程

deepseek_mermaid_20260226_dd3856.png

  • 连接与发现(步骤1-4)

    • 通信协议:客户端通过stdio(用于本地进程间通信)或SSE (Server-Sent Events) (用于远程HTTP通信)与服务端建立1:1连接。启动时,它会发送一个标准化的 initialize 请求,与服务端协商协议版本和能力。
    • 工具发现:初始化后,客户端会发送 tools/list 请求。服务端返回一个包含工具名称、描述和输入参数(JSON Schema)的清单。客户端会将这些信息缓存起来,供后续使用。
  • 协议转换与模型交互(步骤5-7, 11-12)

    • 当用户提问后,客户端需要将缓存的MCP工具列表,动态转换成目标大模型(如文心一言的ernie-4.0-turbo-8k)所能识别的tools参数格式。
    • 当模型返回工具调用指令后,客户端需要解析这个模型特有的格式,提取出工具名和参数。
  • 稳健的进程管理(步骤8-10)

    • 这是客户端底层非常关键的一环,尤其对于通过stdio连接的本地服务端。一个成熟的客户端需要能稳健地处理这些服务端子进程。例如,它能过滤掉服务端进程可能输出的非协议信息(如print调试语句),防止这些“噪声”污染JSON-RPC通信信道。
    • 当需要调用工具时,客户端将模型指令转换为MCP协议的JSON-RPC请求,通过预建立的连接发送给正确的服务端。请求中还可以包含context信息(如用户ID、会话ID),以便服务端进行更精准的操作。

MCP客户端远非一个简单的数据管道。它是一个智能的适配层,负责将AI模型与外部世界连接起来。它不仅要管理服务端的生命周期、发现并理解其能力,更要将AI模型的思考“翻译”成服务端能执行的指令,再将执行结果“反馈”给AI模型以形成最终答案。它背后是协议转换、进程管理、上下文传递等一系列复杂但精密的工程实现,确保了整个系统的稳健、安全和可扩展性

MCP 服务端

MCP服务端的底层原理可以概括为:一个遵循JSON-RPC 2.0规范,通过特定传输方式,负责处理来自客户端的标准化请求、路由到具体业务逻辑并返回结果的后端程序

deepseek_mermaid_20260226_0c81b5.png

四层核心原理详解

结合上图,我们来看看服务端底层的这四个层面是如何协同工作的。

1. 协议层:以JSON-RPC 2.0为“通用语言”

这是MCP服务端的基石。它并不创造新协议,而是建立在成熟的JSON-RPC 2.0规范之上。这意味着客户端和服务端之间的所有通信,都是通过结构化的JSON消息来完成的。一个典型的请求消息会包含method(要调用的方法,如tools/call)、params(参数,包含工具名name和入参arguments)和id(请求标识)。服务端的核心任务之一,就是精确地解析这些JSON消息,并构建出符合规范的响应。

2. 发现层:通过“能力宣告”让客户端了解自己

服务端不能被动地等着被调用,它需要主动告诉客户端“我能做什么”。这就是能力发现(Capability Discovery) 机制。在连接初始化阶段,服务端会通过tools/list这个预定义的method,向客户端返回一个详细的工具清单。这个清单里包含了每个工具的名字、功能描述,以及最重要的——输入参数的JSON Schema(一种描述数据格式的规范),它精确地定义了工具需要什么样的输入。这样,客户端就能知道在什么情况下、用什么参数来调用哪个工具。

3. 执行层:从“协议请求”到“业务逻辑”的路由

这是服务端“真正干活”的部分,也是和你之前理解的“常规服务”最接近的一层。当协议处理层解析完客户端的tools/call请求后,会提取出namearguments。然后,一个内部的 “工具路由器” 会根据name,将请求和参数分发给事先注册好的、对应的业务函数。这个函数可以是任何你能想到的逻辑:查询数据库、调用第三方REST API、读写文件、执行计算等等。函数执行完毕后,结果会被返回给协议层进行封装。

4. 通信层:通过stdio或HTTP(S)作为传输载体

服务端需要通过网络或进程管道来收发消息,这由传输层(Transport) 负责。MCP主要定义了两种标准传输方式:

  • stdio (标准输入/输出) :主要用于本地通信。服务端作为客户端的子进程启动,双方通过标准输入输出流进行JSON-RPC消息的交换。这种方式简单、安全,适合与桌面应用(如Claude Desktop)集成。
  • Streamable HTTP:用于远程通信。服务端作为一个独立的HTTP服务运行。它通过一个HTTP端点,支持客户端发送请求,并能通过SSE (Server-Sent Events, 服务器推送事件)  等技术将服务器的数据实时推送给客户端,适合部署在云端。

💡 高级特性:不仅仅是单向调用

除了上述基础,MCP服务端还有一些更强大的能力:

  • 上下文传递(Context Propagation) :客户端在每次请求中可以携带一个context对象,里面包含用户ID、会话ID等信息。服务端在执行工具函数时,可以读取这个context来做权限校验或记录日志,实现有状态的交互。
  • 采样(Sampling) :这是一个更高级的特性。它允许服务端在处理请求的过程中,反过来向客户端请求调用大语言模型。例如,一个数据分析服务端可以在获取到原始数据后,通过采样机制请求客户端的LLM来生成数据摘要,从而实现更复杂的智能工作流

关键点在于:

  • 一个AI应用(主机)可以创建多个客户端实例,每个客户端独立连接到一个服务端。
  • 每个MCP客户端和它对应的MCP服务端之间,是一条独占的通信通道——这就是“1:1”的意思。
  • 但整体上看,是一个主机连接多个服务端,形成“1:N”的关系。

为什么这样设计?

这种“每个通道独占”的设计有几个重要的好处:

考虑维度解释
隔离性如果服务端1崩溃了,只影响它自己的那条通道。服务端2的通道依然正常,你还可以继续查数据库。
安全性每个服务端的凭证(API密钥、数据库密码)只在自己的通道内使用,不会混在一起,降低了泄漏风险。
通信简化不需要在同一个通道里做复杂的“多路复用”,协议实现更简单、更稳定。
资源控制可以独立控制每个通道的速率、超时等参数,精细化管理。

在真实的MCP实现中(比如Claude Desktop),当你配置多个MCP服务端时:

  1. 启动时:Claude Desktop会为每个配置好的服务端启动一个独立的子进程(服务端实例),并建立一个对应的客户端通道。
  2. 运行时:当AI需要调用某个工具时,它会通过对应的那个客户端通道发送请求。
  3. 多工具调用:如果一次回答需要同时调用多个工具(比如先查文件、再查数据库),AI会分别通过不同的通道并行发送请求,互不干扰。

一种常见的扩展模式

虽然基础是“1:1”,但社区也发展出了一些扩展模式来满足更复杂的需求:

  • MCP Router(路由器) :一个中间层,它作为一个“超级客户端”连接多个服务端,对外提供一个统一的接入点。这样你的应用只需要维护一个客户端连接,就能访问多个服务端的能力。
  • 服务端聚合:有些服务端本身可以聚合多个功能(比如一个服务端同时提供文件访问、数据库查询、API调用),这样你只需要一个客户端连接它,就能获得多种工具。 天气查询 MCP 服务器

1. 连接与初始化

客户端启动时,会通过 stdio 或 HTTP 连接服务器,并发送一个 initialize 请求,协商协议版本和能力。

客户端 → 服务器(请求)

json

复制下载

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-06-18",
    "clientInfo": {
      "name": "my-ai-client",
      "version": "1.0.0"
    },
    "capabilities": {
      "sampling": {},
      "roots": {
        "listChanged": true
      }
    }
  }
}

服务器 → 客户端(响应)

json

复制下载

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-06-18",
    "serverInfo": {
      "name": "weather-server",
      "version": "1.0.0"
    },
    "capabilities": {
      "tools": {
        "listChanged": true
      },
      "resources": {
        "subscribe": true,
        "listChanged": true
      }
    }
  }
}

初始化完成后,客户端发送一个 notifications/initialized 通知,表示准备就绪。

客户端 → 服务器(通知)

json

复制下载

{
  "jsonrpc": "2.0",
  "method": "notifications/initialized"
}

2. 发现工具列表

客户端想知道服务器提供了哪些工具,于是发送 tools/list 请求。

客户端 → 服务器(请求)

json

复制下载

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list"
}

服务器 → 客户端(响应)

json

复制下载

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "get_forecast",
        "description": "获取指定城市未来几天的天气预报",
        "inputSchema": {
          "type": "object",
          "properties": {
            "city": {
              "type": "string",
              "description": "城市名称,例如 '北京'、'上海'"
            },
            "days": {
              "type": "integer",
              "description": "预报天数,默认3",
              "minimum": 1,
              "maximum": 7
            }
          },
          "required": ["city"]
        },
        "outputSchema": {
          "type": "object",
          "properties": {
            "city": { "type": "string" },
            "forecast": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "date": { "type": "string" },
                  "condition": { "type": "string" },
                  "temperature": {
                    "type": "object",
                    "properties": {
                      "high": { "type": "number" },
                      "low": { "type": "number" }
                    }
                  }
                }
              }
            }
          }
        }
      }
    ]
  }
}

客户端现在知道了工具的存在以及它的输入/输出格式。


3. 用户提问,模型决定调用工具

假设用户问:“北京明天天气怎么样?” AI 模型根据 Function Calling 能力,决定调用 get_forecast。客户端将模型的调用意图转化为 MCP 的 tools/call 请求。

客户端 → 服务器(请求)

json

复制下载

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "get_forecast",
    "arguments": {
      "city": "北京",
      "days": 1
    }
  }
}

4. 服务器执行工具并返回结果

天气 MCP 服务器收到请求后,调用真实的天气 API,获取数据,然后按照 MCP 协议返回结果。这里利用了结构化输出特性。

服务器 → 客户端(响应)

json

复制下载

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "structuredContent": {
      "city": "北京",
      "forecast": [
        {
          "date": "2025-03-26",
          "condition": "晴",
          "temperature": {
            "high": 18,
            "low": 5
          }
        }
      ]
    },
    "content": [
      {
        "type": "text",
        "text": "北京明天(3月26日)晴,最高温度18℃,最低温度5℃。"
      }
    ]
  }
}

这里 structuredContent 是结构化数据,供客户端程序化使用;content 是自然语言描述,可直接展示给用户或 AI。


5. 客户端将结果返回给 AI 模型

客户端收到工具结果后,将其作为 tool 消息发送给 AI 模型(以 OpenAI 格式为例):

json

复制下载

{
  "role": "tool",
  "tool_call_id": "call_abc123",
  "content": "北京明天(3月26日)晴,最高温度18℃,最低温度5℃。"
}

AI 模型结合上下文,生成最终回答给用户。

Function Calling 是什么?

Function Calling 是 AI 模型(如 OpenAI 的 GPT、Anthropic 的 Claude 等)提供的一项核心能力。它允许你将自定义的工具或函数描述给模型,模型在回答问题时,可以根据需要,智能地选择调用哪个函数,并返回一个结构化的调用请求

简单来说:让 AI 模型学会“按说明书使用工具”

Function Calling 的工作流程(三步走)

我们拆解一下具体步骤,以 OpenAI 的 API 为例:

第一步:定义函数(写说明书)

你在调用 OpenAI 的 API 时,在请求里加上 tools 参数,描述你的工具有哪些、怎么用。

json

复制下载

{
  "model": "gpt-4",
  "messages": [{"role": "user", "content": "北京明天天气怎么样?"}],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "获取指定城市的天气信息",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "城市名,比如 北京、上海"
            }
          },
          "required": ["location"]
        }
      }
    }
  ]
}

第二步:模型决策并返回指令

OpenAI 的模型看到用户问题和你的工具列表,如果它觉得需要用到 get_weather,它会返回一个特殊的响应,而不是直接返回文本

json

复制下载

{
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": null,  // 注意,content 是空的
        "tool_calls": [
          {
            "id": "call_123",
            "type": "function",
            "function": {
              "name": "get_weather",
              "arguments": "{"location":"北京"}"  // 模型生成的参数
            }
          }
        ]
      }
    }
  ]
}

第三步:客户端执行并返回结果

你的代码(客户端)收到这个响应后:

  1. 解析:取出 name 和 arguments
  2. 路由:根据 name,找到真正的 get_weather 函数并执行(调用天气 API、查数据库等)。
  3. 获取结果:得到天气数据,比如 { "temperature": 22, "condition": "晴" }
  4. 送回模型:再调用一次 API,把工具执行结果以 tool 角色的消息发回去。

json

复制下载

{
  "model": "gpt-4",
  "messages": [
    {"role": "user", "content": "北京明天天气怎么样?"},
    {"role": "assistant", "tool_calls": [...]},  // 上一步的调用记录
    {"role": "tool", "tool_call_id": "call_123", "content": "{"temperature": 22, "condition": ""}"}
  ]
}

第四步:模型生成最终答案

模型看到工具返回的结果,生成自然语言回答:

“北京明天天气晴朗,气温 22 摄氏度。”

Function Calling 的几个关键点

  1. 模型不执行代码,只输出指令

    • 这是安全和灵活的核心。执行权永远在你手里,你可以做任何操作(调 API、查数据库、写文件),模型只负责“建议”。
  2. 需要两次 API 调用

    • 第一次:模型返回工具调用指令。
    • 第二次:你把工具结果送回模型,模型生成最终回答。
  3. 函数描述要清晰

    • 函数名、描述、参数说明写得越清楚,模型选择越准确。这有点像写提示词,只是换成了结构化格式。
  4. 支持并行调用

    • 模型可以在一次响应中要求同时调用多个函数(比如查天气 + 查机票)。
  • Function Calling 是 AI 模型的能力:当模型觉得需要调用外部工具时,它会输出一个结构化的“调用请求”(函数名+参数)。这是模型本身具备的功能,由模型提供商(OpenAI、Anthropic 等)在模型层实现。
  • MCP 是 AI 客户端与工具之间的通信标准:它定义了“模型生成的调用请求”如何从客户端传递到具体的工具执行,以及结果如何返回。

它们不是替代关系,而是不同层次的分工:

Function CallingMCP
层级模型层(AI 模型内部)应用层(AI 客户端与外部系统之间)
职责决定“要不要调用工具”并输出调用参数将调用请求“路由”到正确的工具并执行
定义方模型提供商(如 OpenAI API 的 tools 参数)开放协议(由 Anthropic 发起,社区共建)
是否依赖具体模型是,不同模型格式不同否,协议统一,与模型无关
典型作用让模型“理解”有哪些工具可用,并“表达”调用意图让客户端“连接”任意工具,并“执行”调用

到底什么是 Skills?

Skills 就是让大模型按照某种特定的方法论去行动的机制

image.png 一个标准SKILL的完整组件构成如下表所示:

组件核心功能关键内容
元数据 (Metadata)作为SKILL的“目录”或“岗位名称”,用于AI发现和决策-1-3SKILL的名称、描述、适用场景及触发条件
指令 (Instruction)作为SKILL的“操作手册”,定义AI执行任务的核心流程和逻辑-1-3-6具体的操作步骤、判断逻辑、输入/输出约束及风格规则
资源 (Resource)作为SKILL的“附录”和“工具包”,为指令执行提供数据和工具支持-1-3-6参考文档、可执行脚本、静态资产(如图片、模板)
1. 元数据 (Metadata):让AI“知道”你

元数据是AI在不加载整个SKILL的情况下就能看到的信息,通常位于SKILL.md文件的开头。它的作用是让AI能够将用户的任务与正确的SKILL匹配起来,类似一本技能目录。

  • 名称 (name) :SKILL的唯一标识,如 invoice-processor
  • 描述 (description) :清晰说明该SKILL的用途,帮助AI判断何时调用,例如:“用于处理供应商发票、费用报销单或付款凭证的提取和验证。”
  • 触发条件:定义在什么情况下应该激活此SKILL。
2. 指令 (Instruction):给AI的“操作手册”

这是SKILL的核心执行逻辑,同样写在SKILL.md中,但仅在AI确定调用此SKILL时才会被加载到上下文中。它指导AI“如何一步步完成工作”。

  • 工作流程:以清晰的步骤定义任务流程,例如:

    1. 读取发票PDF文件。
    2. 提取供应商名称、发票号、日期等字段。
    3. 根据验证规则进行校验。
    4. 按指定格式输出JSON。
  • 操作指南:包含处理任务时的特殊规则、注意事项或风格要求。

  • 索引逻辑:对于复杂任务,指令中只保留核心逻辑,并通过“索引”的方式,引导AI在需要时去读取references文件夹中的详细规范。

3. 资源 (Resource):AI的“工具箱”

资源层为SKILL的执行提供具体的数据和工具支持。这部分遵循“按需加载”原则,AI只在执行到特定步骤时,才会去读取或调用它们,从而有效控制Token消耗。它通常由以下三个子目录构成:

  • references/ (参考文档) :存放详细的规范、数据映射或规则文件。例如,在发票处理SKILL中,field-mappings.md定义了发票上的字段应如何映射到系统的数据结构,validation-rules.md则列出了所有的校验规则。这些文件被AI读取,作为执行依据。
  • scripts/ (可执行脚本) :存放预先编写好的程序脚本(如 extract_data.py)。AI本身不读取脚本内容,而是在满足条件时触发执行该脚本,从而完成精确、可靠的操作,不占用上下文Token。
  • assets/ (静态资产) :存放AI在执行任务时需要参考但不修改的确定性资源,如公司Logo、固定模板、示例图片等。将这些资源放入assets并用确定性资源替代概率性生成,能显著提升输出结果的稳定性。

一个典型的SKILL目录结构如下:

invoice-processor/                # SKILL 根目录
├── SKILL.md                       # 包含元数据和核心指令
├── references/                     # 参考文档目录
│   ├── field-mappings.md          # 字段映射规范(AI按需读取)
│   └── validation-rules.md        # 验证规则(AI按需读取)
└── scripts/                        # 可执行脚本目录
    └── extract_data.py             # PDF数据提取脚本(AI触发执行)

在这种结构下,AI的工作流程非常清晰:

  1. 任务匹配:通过SKILL.md的元数据,AI判断当前任务需要调用 invoice-processor
  2. 加载指令:系统将SKILL.md中的指令部分加载到AI的上下文,AI据此制定工作计划。
  3. 执行与查阅:在执行到“提取数据”步骤时,AI触发 scripts/extract_data.py 运行。在“验证数据”时,AI读取 references/validation-rules.md 中的规则来进行判断。
  4. 完成输出:最终,AI整合所有信息,完成发票处理任务。
生成途径一句话描述适合谁核心步骤
1. 对话式创建像聊天一样,把你的工作流程说给AI听,让它帮你打包成技能。非技术用户、业务专家自然对话 → AI拆解 → 自动生成并打包
2. 手动构建按照官方规范,自己动手创建文件夹、编写文件,完全掌控细节。开发者、追求精细控制者理解架构 → 规划内容 → 编写核心 → 集成与测试
3. 工具辅助生成用“技能生成器”这个高级工具,通过自然语言描述,自动生成技能脚手架。开发者、追求效率者配置工具 → 自然语言描述 → 审查并完善 → 部署

SKILLs和Tools在实践中如何配合使用?可以结合具体场景说明。

核心考点:考察对两个概念协同关系的理解。

参考答案思路(以客服场景为例):
在一个客服RAG系统中:

  • Tools(工具层) :原子能力,如query_order(查订单)、refund_apply(申请退款)、search_knowledge(搜索知识库)

  • SKILLs(技能层) :封装完整业务流程

    • handle_refund SKILL:定义处理退款的完整流程(验证订单状态 → 检查退款条件 → 调用refund_apply工具 → 生成回复)
    • troubleshoot_product SKILL:定义故障排查步骤(询问症状 → 搜索知识库 → 推荐解决方案)

配合方式:SKILLs在指令中定义“在哪个步骤调用哪个Tool”,把多个原子操作组合成完整业务流程

如果系统中有超过30个SKILLs,直接把所有SKILL描述都传给AI模型会有什么问题?如何解决?

核心考点:考察对AI上下文限制的理解和工程优化能力。

参考答案思路
问题:把所有SKILL描述都传给模型,会占用大量上下文token,导致:

  • 成本大幅上升
  • 模型可能“看不过来”,忽略部分SKILL
  • 核心任务可用的上下文空间被挤占

解决方案

  • 分层路由:设计一个“SKILL管理器”Agent,先粗粒度分类,再路由到具体SKILL
  • 动态加载:只把与当前任务最相关的SKILL描述传给模型(通过向量检索或规则匹配)
  • SKILL目录:给SKILLs设计清晰的元数据(名称、简短描述),让模型先基于元数据选择,再加载完整SKILL

Agent

Agent(智能体)  是当前AI领域最前沿、最综合的概念,可以把它理解为  “一个有自主行动能力的AI大脑” 。你之前了解的RAG、Skills、Function Calling、MCP,实际上都是构建Agent的“零部件”。 Agent是一个能够感知环境、进行决策、并执行动作以实现特定目标的自主系统。在大模型背景下,Agent通常以大语言模型(LLM)为核心控制器,结合规划能力、记忆模块和工具使用能力,去完成复杂的任务。

Agent的四大核心组件

deepseek_mermaid_20260226_54e531.png

1. 感知模块

  • 职责:接收用户输入(文本、语音、图像等),进行意图识别、实体抽取、情感分析等预处理。
  • 依赖技术:LLM本身的多模态能力、提示工程、少量分类模型。

2. 大脑(核心控制器)

  • 职责:LLM作为“思考中枢”,负责规划、推理、决策。它决定“下一步该做什么”,并调用其他模块。

  • 关键技术

    • 思维链(Chain-of-Thought, CoT) :让模型逐步推理,而不是直接给答案。
    • ReAct模式:将思考(Reason)行动(Act) 交错进行,每步思考后可能执行一个动作,再观察结果继续思考。
    • 自我反思(Self-reflection) :Agent能评估自己的行动效果,遇到错误时调整策略。

3. 记忆模块

  • 短期记忆:当前对话的上下文(通过LLM的上下文窗口实现)。
  • 长期记忆:存储历史经验、用户偏好、领域知识等。通常用向量数据库实现(你熟悉的RAG技术),需要时检索相关记忆注入大脑。
  • 记忆的读写:Agent可以主动写入重要信息(如“用户喜欢清淡口味”),也能在决策时查询相关记忆。

4. 行动模块

  • 职责:执行大脑的决策,与外部环境交互。

  • 依赖你之前学的

    • Function Calling:调用具体的工具函数(如查天气、订票)。
    • MCP:通过标准化协议连接各种工具服务器,实现动态工具发现和调用。
    • Skills:执行封装好的复杂流程(如“处理投诉”Skill内部可能包含多个步骤和工具调用)。

工程师在感知模块的“可做之事”

感知模块的核心任务可以概括为:把用户的原始输入(文本、语音、图像等),转换成Agent大脑(LLM)能够准确理解和处理的结构化信息

工作领域具体可做之事目的
输入清洗拼写纠错、敏感信息过滤、语言检测提高输入质量,保障安全,节省token
意图识别设计few-shot提示、混合规则/小模型、处理多轮指代准确理解用户目的,输出结构化信息
多模态处理集成ASR/OCR服务、配置热词、版面分析拓展Agent的输入感知能力
工程保障超时降级、结果缓存、AB测试平台提升系统的稳定性、效率和可优化性

大脑模块的核心工作

工作领域具体可做之事目的
规划能力设计ReAct提示词、实现循环控制、引导思维链/思维树让Agent能分解复杂任务,有步骤地执行
决策机制优化工具描述、设计意图-工具映射、处理多工具调用让Agent能准确选择工具,高效完成任务
记忆整合设计记忆读写触发逻辑、集成向量检索让Agent具备长期记忆,实现个性化交互
反思纠错设计自我反思提示、实现错误处理与重试流程提升Agent的鲁棒性和可靠性
系统提示编写并持续迭代高质量的系统提示词奠定Agent所有行为的基础框架

大脑模块是Agent的“灵魂”所在。作为工程师,你通过提示词工程、流程设计和各种增强技术,将通用的LLM塑造成能解决特定领域复杂问题的智能体。

主流的大模型框架(如LangChain、LlamaIndex、AutoGen、CrewAI等)主要聚焦的就是“大脑模块”的工作,同时也会为其他模块(记忆、行动)提供便利的接入方式。 大脑模块的核心职责是:规划、决策、控制循环。这些恰恰是框架提供的最核心价值:

大脑模块的职责框架提供的对应能力(以LangChain为例)
规划(Planning)内置的Chain(链)和Agent抽象,支持思维链(CoT)、ReAct等规划模式。
决策(Decision Making)AgentExecutor 负责解析LLM输出的Action,决定调用哪个工具,并将Observation反馈给LLM,自动维护整个“思考-行动”循环。
工具选择统一的Tool接口,开发者只需注册工具,框架负责将工具描述传给LLM,并处理调用。
记忆整合提供Memory组件(如向量存储、对话缓冲区),自动将记忆注入上下文。
多步推理支持复杂的SequentialChainRouterChain等,编排多步骤任务。

Agent的底层原理

Agent的工作流程通常是一个循环,称为  “感知-规划-行动-观察”循环(或称 ReAct循环

底层关键技术详解

1. ReAct 模式

这是Agent最核心的思维模式。它将推理痕迹(Thought)动作(Action) 交替输出。例如:

text

复制下载

Thought: 用户需要找聚会场地,我应该先搜索附近的场地。
Action: search_venues(location="北京", capacity=8, budget=2000)
Observation: 返回了3个符合条件的场地。
Thought: 第一个场地评论不错,但需要确认是否有餐饮服务。
Action: get_venue_details(venue_id=101)
...

模型通过这样的文本交互,一步步推进任务。

2. 规划与子目标分解

复杂任务需要分解成多个可执行的子任务。这可以通过:

  • 思维树(Tree-of-Thoughts) :探索多种可能的分解路径,选择最优。
  • LLM作为规划器:直接提示模型“请将任务分解为步骤”。
3. 自我反思与纠错

Agent在执行过程中可能失败(如工具调用出错、结果不符合预期)。高级Agent会:

  • 记录失败原因
  • 调整策略重试
  • 甚至向用户请求澄清
4. 记忆的读写机制
  • 写入:Agent可以在对话中主动将重要信息写入长期记忆(如调用save_memory工具)。
  • 读取:在规划阶段,Agent可以检索与当前任务相关的历史记忆,利用RAG技术。
5. 工具使用的统一接口

你之前学的Function CallingMCP正是为此而生。Agent通过它们:

  • 发现可用工具(MCP的tools/list
  • 按需调用(Function Calling的tool_calls
  • 处理结果

思维链(Chain-of-Thought, CoT) 和 ReAct模式(Reason + Act)

它们就像AI的两种思考方式:CoT是让AI学会“自言自语”地推理,ReAct则是让AI在推理的同时,还能动手执行外部操作。  下面这张表可以先帮你建立直观印象:

维度思维链 (Chain-of-Thought, CoT)ReAct 模式 (Reason + Act)
核心思想在给出答案前,显式地生成中间的推理步骤在推理的同时,与外部环境(如工具、API)交互并获取反馈。
关键词思考、推理、解释思考、行动、观察
工作方式让模型把黑盒的思考过程,变成白盒的推理链输出出来。通过“思考 (Thought) → 行动 (Action) → 观察 (Observation) ”的循环来推进任务。
主要目标提升复杂推理任务的准确性可解释性(如数学、常识推理)id=5312247)。让模型能够解决需要多步推理和与外部世界交互的复杂任务(如信息查询、操作软件)。
与外部世界关系不直接交互,完全依赖模型的内部知识。紧密交互,通过调用工具来获取实时信息并执行动作。
典型应用数学应用题、复杂逻辑推理、代码生成。需要实时信息的问答(如“今天的天气”)、网页自动化操作、充当智能体(Agent)。
思维链 (Chain-of-Thought, CoT):让AI学会“自言自语”地思考

简单来说,思维链就是引导大模型在给出最终答案之前,生成一系列中间的推理步骤

1. 它是如何工作的?

CoT的核心是通过提示工程(Prompt Engineering)  来激发模型的推理能力,主要有两种方式

  • 少样本学习(Few-shot CoT) :在提示词里给模型提供几个包含“问题-推理过程-答案”的完整示例,让模型学会这种“分步思考”的模式。
  • 零样本学习(Zero-shot CoT) :更简单,只需要在问题后面加上一句“让我们一步一步地思考”,就能显著提升模型在复杂任务上的表现。这背后的原理是,这句话触发了模型在训练中学到的、按步骤生成答案的模式。
2. 它带来了什么效果?

实验数据表明,CoT技术能让大模型在推理任务上的准确率提升30%-50% 。更重要的是,它让模型的“思考过程”变得可解释、可调试,我们能看清它是在哪一步犯错的

ReAct模式 (Reason + Act):让AI能“边想边做”

如果说CoT让AI学会了思考,那么ReAct则在此基础上,赋予了它 “动手”的能力。ReAct这个名称本身就很传神,它是  “Reasoning”(推理)和“Acting”(行动)  的结合体

1. 核心机制:“思考-行动-观察”循环

ReAct的工作方式是一个清晰的循环:

  • 思考 (Thought) :模型首先“自言自语”,分析当前状态,规划下一步该做什么。
  • 行动 (Action) :根据思考,模型调用一个外部工具或API来执行具体动作,比如执行一次搜索Search[xxx]或调用计算器Calculator[1+2]
  • 观察 (Observation) :系统执行完动作后,将结果(如搜索结果、API返回值)反馈给模型。
  • 循环:模型根据“观察”到的新信息,再次进入“思考”,如此反复,直到能给出最终答案
2. 为什么它如此重要?
  • 突破知识边界:ReAct让模型能实时查询外部信息,解决了模型知识“过期”或“不足”的问题。
  • 降低幻觉:通过工具返回的事实来验证和修正自己的推理,能有效减少胡说八道。
  • 实现复杂任务:它是构建AI Agent的基础模式,让AI能真正完成订票、查询、分析等需要多步操作的真实任务

CoT和ReAct并非替代关系,而是递进和互补的。

  • CoT是ReAct的“思想内核” :ReAct中的“Thought”环节,本质上就是一个微型的、面向当前步骤的CoT。
  • ReAct是CoT的“手脚延伸” :ReAct在CoT的基础上,增加了“Action”和“Observation”环节,让思考不再局限于“空想”,而是能与现实世界互动,并根据反馈动态调整计划

自我反思

“自我反思”在工程上实现的核心,就是让Agent拥有一个  “纠错-记忆”的闭环。它不只是让模型口头承认错误,而是要能定位错误、生成修正方案,并把经验存下来用于未来

Reflection(即时自我批判)

这是一种轻量级的实现,就像给每个任务配了一个临时的“校对员”,主要针对单次任务的输出进行优化

交互内自我批判:最常见的模式是  “生成 -> 批判 -> 修正”  的单次或少数几次循环。例如,你可以通过一个精心设计的提示词,让LLM在给出答案后,立即进行自我检查

技术要点

  • 批判标准:需要定义明确的批判维度,如正确性、完整性、成本、延迟等[-3]
  • 成本控制:为了避免无限的反思循环和无谓的token消耗,工程上需要设置最大迭代次数,或当批判结果满足预设阈值(如置信度 > 0.9)时提前退出

Reflexion(持久化学习与记忆)

这是一种更强大的实现,旨在让Agent能够“吃一堑,长一智”。它的核心是将反思的结果沉淀下来,形成一个不断进化的经验知识库,供未来的任务参考。这可以拆解为三个核心环节:

  1. 记忆结构设计:关键在于存储什么。一个好的“经验教训”不应只是文本,而应是结构化的数据,方便检索和应用。一个典型的记忆条目可能包含:

    • 任务签名 (Task Signature) :任务的唯一标识或特征向量(例如,一个复杂任务的Embedding)。
    • 失败模式 (Failure Pattern) :描述哪里出错了(例如,“日期解析失败”)。
    • 补救措施 (Remedy) :总结出的正确做法或解决方案(例如,“对于模糊日期,先检测地区格式”)。
    • 置信度得分 (Confidence Score) :这条经验的可靠程度。
  2. 记忆的写入(经验沉淀) :在任务执行完毕后,如果任务失败或结果不理想,就触发一次“复盘”。系统会提取上述的结构化信息,并存入向量数据库或图数据库中。有些研究(如GUI-Reflection)甚至通过自动化数据管道,从成功的轨迹中逆向构造出“错误-修正”的样本数据,用于模型微调,从而习得反思能力。

  3. 记忆的读取与应用(指导未来) :当Agent开始执行一个新任务时,它会首先根据当前任务的特征(任务签名)去记忆库中检索最相关的历史经验。检索到的经验会作为系统提示词或上下文的一部分注入给LLM,指导其在新任务中避开曾经的坑

场景推荐方案理由
原型开发、内部工具单模型自我批判快速、简单、成本低
面向用户的通用产品单模型自检 + 特定条件触发专门检查平衡成本与质量
金融、医疗等高风险领域多模型交叉验证 + 人工抽检准确性优先
学术研究、复杂推理多智能体辩论架构探索能力上限
资源受限环境只用单模型,但优化批判提示词在限制内最大化效果

Agent记忆模块

记忆模块是Agent的“经验存储库”,让AI不仅能“思考”,还能“记住过去”

记忆的分类:短期 vs 长期

在工程上,我们通常将记忆分为两类,它们存储方式、生命周期和用途都不同:

类型别称生命周期存储介质主要作用
短期记忆工作记忆、对话上下文一次会话(几轮对话)内存(如列表、缓存)保持当前对话的连贯性,理解指代
长期记忆知识记忆、经验库跨会话、永久向量数据库、图数据库、关系数据库记住用户偏好、历史事实、任务经验

二、短期记忆:对话上下文管理

短期记忆就是当前会话的“工作区” ,通常包含最近几轮的用户消息和Agent回复。它的核心任务是让Agent能理解“你刚才说的”和“我之前提过的”。

2.1 实现方式

最朴素的方式是维护一个消息列表,每次请求时把整个列表传给LLM。但随着对话变长,会遇到两个问题:

  • Token超限:LLM上下文窗口有限(如4k、8k、128k tokens)
  • 成本飙升:长文本每次调用都收费
2.2 工程优化策略
策略做法适用场景
滑动窗口只保留最近N轮对话(如最近10轮)通用对话,对早期信息依赖弱
对话摘要定期将旧对话压缩成摘要,替换原始内容需要长期记忆但不想保留细节
关键信息提取提取重要实体/事实存入长期记忆,丢弃原文问答型Agent,只关心事实
混合策略窗口+摘要:保留最近几轮+之前对话的摘要大多数生产系统

三、长期记忆:让Agent拥有“永生记忆”

长期记忆使Agent能记住跨会话的用户信息、领域知识、甚至自己过去的经验(如反思结果)。实现上分为存储检索两部分。

3.1 存储结构
记忆类型存储格式检索方式典型场景
事实性记忆键值对 (key-value)精确查询用户姓名、生日、配置选项
语义记忆向量 (embedding)相似度检索用户兴趣、对话片段、知识库
结构性记忆图 (节点+关系)图查询实体关系、知识图谱
经验性记忆向量+元数据相似度+过滤反思教训、成功案例

常用技术栈

  • 向量数据库:Pinecone、Weaviate、Qdrant、Milvus,或轻量的Chroma、LanceDB
  • 关系数据库:PostgreSQL(配合pgvector)、SQLite(配合sqlite-vss)
  • 图数据库:Neo4j、Dgraph
3.2 记忆的写入(记什么?何时记?)

这是工程难点——需要决定哪些信息值得永久保存。常见策略:

  • 显式用户指令:用户明确说“记住我喜欢靠窗的座位”
  • 关键信息提取:对话中检测到新的实体/偏好(如通过NER或LLM判断)
  • 任务完成总结:任务结束后,将关键结果存入记忆(如“上次查询了iPhone 15价格”)
  • 失败反思:将错误教训存入记忆(如Reflexion模式)
记忆类型可选技术选型考量因素
短期记忆Redis、内存缓存、简单的列表访问速度、容量上限、是否需要持久化
长期记忆(向量化)Chroma(本地)、Pinecone(云)、Milvus(自托管)、Qdrant数据规模、查询性能、成本、运维复杂度
长期记忆(结构化)PostgreSQL(+pgvector)、MongoDB是否需要混合查询(向量+结构化过滤)、事务支持
长期记忆(关系型)Neo4j、Dgraph实体间关联复杂,需要图遍历

1. 向量化存储

向量化存储是指将文本、图像等非结构化数据通过嵌入模型(Embedding Model)转换为固定长度的向量(如 384维、1536维),然后将这些向量存储到专门的向量数据库中。查询时,将查询内容也转换为向量,通过计算向量间的相似度(如余弦相似度)来检索最相关的内容。

工作原理
  • 写入:记忆内容 → 嵌入模型 → 向量 → 存入向量库,同时可附加元数据(如时间戳、用户ID)。
  • 读取:用户查询 → 嵌入模型 → 查询向量 → 向量库进行近似最近邻搜索 → 返回最相似的记忆片段。
适用场景
  • 语义搜索:需要根据意思找记忆,而非精确匹配(如“用户上次提到喜欢的餐厅风格”)。
  • 开放域问答:从大量非结构化对话历史中检索相关片段。
  • 个性化推荐:基于用户历史兴趣向量推荐内容。
  • 反思经验检索:Reflexion中存储失败教训,按语义相似度检索。
优点
  • 能捕捉语义相似性,即使关键词不匹配也能找到相关内容。
  • 适合处理海量非结构化文本。
  • 查询速度快(近似最近邻搜索)。
缺点
  • 需要提前用嵌入模型向量化,有计算成本。
  • 语义边界可能模糊,检索结果需要重排序来提升精度。
  • 缺乏精确匹配能力(如按日期、ID精确查找)。

2. 结构化存储

结构化存储是指将记忆以键值对表格行文档的形式组织,每条记忆有明确的字段定义。查询时可以通过精确条件(如 user_id = 123)或范围条件进行过滤。

工作原理
  • 写入:将提取的结构化信息(如用户姓名、偏好设置)存入数据库的特定字段。
  • 读取:通过查询语言(SQL、MongoDB查询语法)按字段值精确或范围检索。
适用场景
  • 用户显式信息:姓名、生日、联系方式、配置选项。
  • 事实性记忆:“用户上次购买的商品ID”、“会员等级”。
  • 对话状态:当前会话的临时变量(虽然属于短期记忆,但有时也需持久化)。
  • 元数据存储:用于向量化记忆的过滤条件(如按时间范围检索向量)。
优点
  • 查询精确,支持复杂条件组合(AND/OR、范围、排序)。
  • 事务支持,保证数据一致性。
  • 成熟的技术栈,运维工具丰富。
缺点
  • 不擅长语义搜索,无法处理“意思相近但表述不同”的查询。
  • 需要预先定义schema,扩展性相对较弱。
  • 对非结构化文本支持差(除非配合全文索引,但效果不如向量)。

关系性存储(图存储)

关系性存储(图存储)是指将记忆表示为节点关系,节点代表实体(如人、地点、事物),关系代表实体之间的连接(如“喜欢”、“位于”、“购买过”)。查询时通过图遍历算法来发现关联路径。

工作原理
  • 写入:从对话中提取实体和关系,创建/更新图节点和边。
  • 读取:通过图查询语言(如Cypher)进行模式匹配,查找多跳关系。
适用场景
  • 知识图谱构建:需要存储实体间的复杂关联(如“张三的同事李四的妻子是王五”)。
  • 多跳推理:Agent需要推导间接关系(如“推荐张三的朋友可能喜欢的餐厅”)。
  • 社交关系:用户之间的关系网络。
  • 业务逻辑规则:如权限继承、产品分类层级。
优点
  • 擅长处理深度关联和多跳查询。
  • 直观地表示复杂关系网络。
  • 支持灵活的图算法(如最短路径、社区发现)。
缺点
  • 对简单查询(如单实体属性)可能过度设计。
  • 学习曲线较陡(需要掌握图查询语言)。
  • 水平扩展相对复杂。
维度向量化存储结构化存储关系性存储(图)
数据本质非结构化文本/图像的语义向量结构化的事实/属性实体间的复杂关联
查询方式语义相似度搜索精确匹配/范围过滤图遍历/模式匹配
典型场景对话历史检索、兴趣匹配用户配置、交易记录社交图谱、知识推理
优点语义理解强,检索灵活精确、可靠、事务支持深度关联查询强大
缺点缺乏精确性,需重排序无法语义匹配,schema固定学习成本高,简单查询笨重
常用技术Pinecone, Milvus, ChromaPostgreSQL, Redis, MongoDBNeo4j, Neptune
实际项目中的组合策略

在一个成熟的Agent系统中,这三种存储往往同时存在,各司其职

  • 向量化存储:负责对话历史、用户兴趣、反思经验的语义检索。
  • 结构化存储:负责用户基本资料、配置选项、精确的事实记录。
  • 关系性存储:负责用户社交关系、知识图谱、复杂的业务规则链。

例如,当用户问“推荐一个和我口味相似的朋友喜欢的餐厅”:

  • 图存储找出“口味相似的朋友”;
  • 结构化存储获取这些朋友的餐厅历史记录;
  • 向量化存储从餐厅描述中筛选符合当前偏好的语义。

这种组合能最大化发挥每种存储的优势,让Agent既懂语义,又精确,还能推理复杂关系。

 Agent评估监控

为什么Agent需要专门的评估监控?

传统软件监控关注的是系统健康(CPU、内存、错误率),而Agent监控除了这些,还必须关注行为质量——因为Agent的输出不是预设的,而是动态生成的。你需要回答:

  • 它做对了吗? (最终答案的正确性)
  • 它做得高效吗? (用了多少步?花了多少token?)
  • 它为什么这么做? (当出错时,是哪一步思考出了问题?)
  • 它能更好吗? (如何从失败中学习?)

二、可观测性三大支柱在Agent中的体现

支柱在Agent中的含义示例
日志 (Logs)记录Agent的每一步思考、行动、观察每个Thought/Action/Observation的完整文本
指标 (Metrics)聚合的数值化度量成功率、平均步数、工具调用次数、token消耗
追踪 (Traces)串联一次完整请求的调用链从用户输入到最终回答,经过的LLM调用、工具调用序列

Agent评估监控的核心工作

1. 链路追踪:记录“思考-行动”全过程

Agent的运行是一个多步循环,每一步都可能出错。你需要能像放电影一样回放整个过程。

具体实现

  • 为每个会话/请求生成唯一Trace ID,贯穿始终

  • 记录每个步骤

    • 用户输入
    • 系统提示词(可能包含记忆、工具描述)
    • LLM的每次输出(包括Thought和Action)
    • 工具调用的请求和响应
    • 最终答案
  • 存储为可检索的结构化数据(如JSON Lines存入对象存储,或导入日志系统)

指标定义:从海量数据中提炼关键信号

你需要定义一套衡量Agent质量的指标,并持续采集。

基础指标

  • 任务成功率:最终答案是否满足用户需求(需要人工或自动评估)
  • 平均响应时间:从收到请求到返回完整答案的耗时
  • token消耗:每次请求的总token数(输入+输出),直接关联成本
  • 工具调用次数:平均调用几个工具,是否有无效调用

质量指标

  • 步数效率:实际步数 vs 预期最少步数(比如明明一步能查完,却绕了三步)
  • 工具选择准确率:在需要调用工具的场景下,选对了工具吗?
  • 错误恢复率:当工具调用失败时,Agent能正确处理的比例
  • 用户反馈分:点赞/点踩、后续是否继续咨询等
3. 评估自动化:让机器评判“好坏”

你不能靠人工看每一条日志来评估。需要建立自动评估流水线

常用方法

  • 规则检查:如答案是否包含“我不知道”但本应知道,或是否包含敏感词
  • 模型打分:用更强或专门的LLM(如GPT-4作为裁判)对输出进行评分
  • 对比测试:将输出与预期答案(如果有)计算相似度(ROUGE、BLEU、语义相似度)
  • A/B测试:比较不同提示词、不同模型版本的效果差异
可视化与告警:让数据驱动决策

采集的数据要变成可理解的看板,并在异常时通知你。

常用工具

  • LangSmith:专为LLM应用设计的可观测平台,自动追踪链式调用,提供评估和调试界面
  • Weights & Biases (WandB) :适合记录实验指标,对比不同版本
  • 传统监控组合:Prometheus + Grafana(指标)+ Loki(日志)+ Tempo(追踪)
  • 自定义看板:用Streamlit/Flask快速搭建内部调试面板

你需要关注

  • 成功率趋势:是否随着版本更新而下降?
  • 成本趋势:token消耗是否异常上涨?
  • 慢请求追踪:哪些请求耗时特别长?是工具调用慢还是LLM思考久?
  • 失败模式聚类:自动将失败案例按错误类型分组,找出高频问题
维度传统微服务监控AI应用监控
核心关注点服务是否活着?响应快不快?报错多不多?模型输出的结果好不好?  推理过程对不对?
主要指标QPS、延迟、错误率、CPU/内存使用率答案正确率、步数效率、工具选择准确率、幻觉率
异常定义5xx错误、超时、资源饱和答非所问、逻辑错误、有害内容、浪费token
排查方式查看日志、调用链、 metrics需要回放思考过程(Trace)、评估语义质量

大模型框架

框架类别框架名称一句话总结核心价值与你之前所学知识的对应关系
核心应用框架LangChain全能型“乐高工厂”,提供构建 LLM 应用的全套组件。抽象并标准化 Tools, Memory, Chains, Agent 等模块,并提供 LCEL 和 LangGraph 进行复杂流程编排 。将我们讨论的所有模块(感知、大脑、记忆、工具)  都变成了可插拔的标准件。
LlamaIndex专精 RAG 的“数据检索大师”,聚焦于数据和索引。围绕 Document/Node/Index 提供了一套完整的 RAG 数据处理和检索链路,让连接私有数据变得极其简单 。完美对应 长期记忆(向量化存储)  模块,并提供了标准化的实现。
多智能体协作框架AutoGen微软出品的“专业协调员”,让 Agent 通过对话协同工作。允许多个 Agent 通过对话交流,自主分工、调用工具,共同解决复杂问题 。对应 大脑模块 在复杂任务下的多智能体协作形式。
CrewAI角色扮演的“AI 梦之队”,像组建团队一样组建 AI。通过定义不同的角色、目标和任务,让 AI 像人类团队一样分工协作 。对应 大脑模块 的高级规划和角色分工
底层服务与部署框架vLLM极致吞吐的“性能发动机”,通过 PagedAttention 技术提升并发。通过创新的 PagedAttention 技术大幅提升显存利用率和并发处理能力,吞吐量领先 。为 工具模块 和 大脑模块 提供高性能、低成本的算力支持
TGI稳定可靠的“生产老兵”,Hugging Face 出品,开箱即用。与 HF 生态无缝集成,提供量化、流式输出等企业级功能,部署简单、运行稳定 。为 工具模块 和 大脑模块 提供稳定、可靠的推理服务

LangChain

LangChain 本质上是一个“胶水框架”,它的核心原理可以概括为:提供一套标准化的接口和组件,让你能用“乐高积木”的方式,把大模型和各种工具、数据、逻辑拼接起来,构建复杂的 AI 应用

它不是为了取代之前学的那些概念(如 RAG、Agent),而是为它们提供了工程化的最佳实践和实现方式

LangChain 的定位:AI 应用的“积木盒”

deepseek_mermaid_20260303_408cc5.png LangChain 的定位:它位于你的应用代码和各种基础设施(模型、数据)之间,通过标准化的组件和编排语言,让你能灵活地构建上层应用 LangChain 的定位:它位于你的应用代码和各种基础设施(模型、数据)之间,通过标准化的组件和编排语言,让你能灵活地构建上层应用-8

🧱 第一层:六大标准化组件

模块类别核心作用与你已学知识的对应
模型 I/O标准化地管理模型调用、提示词模板和输出解析。对应大脑模块与外界交互的“语言”部分。
检索 (Retrieval)处理数据加载、切分、向量化和检索,是 RAG 的核心。对应长期记忆(向量化存储)  和 RAG 的实现。
链 (Chains)将多个组件(如提示词、模型、其他链)组合成一个可复用的任务流程。对应大脑模块固定的、确定的流程编排。
代理 (Agents)实现 ReAct 等循环,让 LLM 动态决策并调用工具。对应大脑模块动态的、需决策的核心循环。
记忆 (Memory)在链或代理的多次调用之间传递和存储状态。对应短期记忆长期记忆的管理。
工具 (Tools)封装外部服务或 API,让代理可以调用。对应行动模块,即具体的 Tools

🔗 第二层:核心编排语言 LCEL

这是 LangChain 最新也是最核心的设计精髓。LCEL(LangChain Expression Language)是一种声明式的、基于管道操作符(|)的语法,用来组合上述各种组件。

  • 核心逻辑输入 | 组件A | 组件B | 组件C。前一个组件的输出会自动成为下一个组件的输入。

  • 示例:一个简单的问答链可以这样构建:

    chain = prompt_template | model | output_parser
    

    这行代码就完成了一个完整流程:格式化提示词 -> 调用模型 -> 解析输出。

  • 为什么重要:LCEL 让构建复杂流程变得像搭积木一样简单和直观。它提供了“开箱即用”的可靠性,自动支持流式输出、异步调用、重试和跟踪等高级功能。

🚀 第三层:从链到图的进化(LangGraph)

当你需要构建更复杂、非线性的应用(如带循环、分支或多智能体协作的 Agent)时,基础的链就不够用了。LangGraph 应运而生。

  • 核心思想:LangGraph 将应用看作一个图(Graph) 。节点是你要执行的步骤(可以是一个函数、一个 LCEL 链或一个 Agent),边是节点之间的流转逻辑和控制条件。
  • 适用场景:它非常适合构建需要精细控制的 Agent 工作流。实际上,LangChain 的 Agent 底层就是基于 LangGraph 实现的-3。你可以从简单的 Agent 入门,当需要更高级的自定义时,再深入到 LangGraph。

📊 额外的生产利器:LangSmith

当我们聊到 评估监控 时,LangSmith 就是 LangChain 生态给出的答案-2。它是一个生产级平台,专门用于:

  • 追踪 (Tracing) :可视化地记录 Agent 的每一步“思考-行动-观察”循环。
  • 调试与评估:查看详细的调用链、输入输出、token 消耗,并对不同版本的应用进行对比评估。
  • 监控:上线后持续监控应用性能和质量。

原理总结:一个层层递进的体系

你可以把 LangChain 的原理理解为一个从具体到抽象的金字塔体系

  1. 底层:提供各种标准化组件(模型、工具、记忆...),帮你把“零件”准备好。
  2. 中层:通过 LCEL 这个“魔法胶水”,让你能轻松地将零件组合成确定性的流程(链)
  3. 高层:对于需要动态决策的复杂流程,提供了 Agent 和 LangGraph,让你能构建出带循环和判断的非线性应用。
  4. 塔尖:最后,用 LangSmith 这个“监控室”来观察、评估和优化整个应用的运行。

LangChain记忆模块

LangChain的记忆模块是一个分层管理系统,其核心原理可以概括为:为LLM提供一个动态扩展的“外脑”,使其能够突破单次对话的上下文限制,通过“短期快速存取”和“长期语义检索”两种方式,维持对话的连贯性并积累知识

deepseek_mermaid_20260306_f9e78d.png

短期记忆 vs. 长期记忆:原理与实现对比
特性短期记忆 (Short-term Memory)长期记忆 (Long-term Memory)
核心原理缓存与滑动窗口。将最近的对话历史直接拼接到提示词(Prompt)中,让LLM“看到”刚刚发生了什么。向量化与语义检索。将历史信息通过嵌入模型转化为向量存入数据库,新问题来时,通过语义相似度召回最相关的信息,再注入提示词。
典型组件ConversationBufferMemory(完整缓存)、ConversationBufferWindowMemory(窗口缓存)、ConversationSummaryMemory(摘要缓存)、结合LangGraphStoreVectorStoreRetrieverMemory、结合LangGraphStore
数据存储内存 (RAM) 。以键值对或列表形式存在。外部向量数据库(如Chroma、Pinecone、FAISS)或支持向量检索的传统数据库(如MongoDB、PostgreSQL)。
生命周期一次会话。对话结束或窗口滑动后,数据即被清除。跨会话、持久化。信息可以被永久保存,供未来所有对话使用。
数据形式原始文本消息。文本的向量表示 + 原始文本 + 元数据(时间戳、用户ID等)。
会计场景示例Agent与用户正在核对上个月的三笔报销单,它需要记住刚刚核对了哪几笔。Agent记得用户“张三”习惯在报销单的“备注”栏填写项目编号,下次帮他处理时就能自动按此格式操作。
短期记忆组件
记忆组件核心原理工作方式优点缺点推荐使用场景(含会计示例)
ConversationBufferMemory完整缓存将整个对话历史原封不动地保存在内存中,每次请求时将所有消息拼接到提示词中。- 信息无损失 - 实现简单,适合调试- 对话一长,token 消耗巨大 - 可能超出模型上下文窗口短对话(如单次发票咨询) - 开发测试阶段快速验证
ConversationBufferWindowMemory滑动窗口只保留最近 K 轮对话,超出窗口的旧消息被丢弃。- 控制 token 长度,防止无限增长 - 保留最关键的最新上下文- 关键信息可能因窗口限制而丢失多步操作流程(如报销审批:每一步依赖前一步结果) - 会计场景:核对多张发票时,只需记住最近几轮的核对状态
ConversationSummaryMemory摘要缓存每次交互后让 LLM 对历史进行摘要总结,将摘要作为上下文保留。- 极大压缩 token - 保留核心信息,适合超长对话- 有信息丢失风险 - 每次对话后需额外 LLM 调用,增加延迟和成本超长会话(如月度账务咨询,需持续记住项目背景) - 会计场景:跨日期的审计问答,需记住前期讨论的关键点

AgentExecutor

AgentExecutor 是 LangChain 中驱动 Agent 运转的“心脏”或“大脑执行官”。它负责维护我们之前深入讨论过的 ReAct 循环(思考-行动-观察),让大模型能够动态决策、调用工具,并最终完成任务

1. AgentExecutor 的核心职责:执行“思考-行动-观察”循环

deepseek_mermaid_20260306_b1d523.png

  1. 输入:接收用户问题和当前状态(对话历史、已获取的信息)。

  2. 思考:调用 LLM,要求模型以特定格式输出(通常包含 Thought 和 Action)。

  3. 判断:解析 LLM 的输出:

    • 如果是 Final Answer,则结束循环,返回结果给用户。
    • 如果是 Action(如 get_weather 工具调用),则执行对应的工具。
  4. 观察:将工具执行的结果(Observation)拼接到对话中。

  5. 循环:带着新的 Observation 回到步骤 2,让 LLM 继续思考下一步,直到输出 Final Answer 或达到最大迭代次数。

2. AgentExecutor 具体是什么?
  • 它是一个循环控制器:AgentExecutor 本身不执行工具,也不直接调用LLM,而是协调这两者。它从 LLM 拿到指令,调用你注册好的工具,把结果喂回去,再让 LLM 继续,如此反复。
  • 它是一个状态维护者:在多次调用之间,它需要维护完整的对话历史(包括 ThoughtActionObservation),确保 LLM 拥有完整的上下文。
  • 它是一个安全阀:它内置了最大迭代次数限制,防止 Agent 陷入无限循环。它还会处理一些异常情况,比如工具调用失败时如何反馈给 LLM。

总结:AgentExecutor 就是你之前理解的“解析与循环控制”这个概念的工程化实现。它把思考-行动-观察的循环固化成一个可复用的组件,让你无需手动处理每次 LLM 调用和工具执行的衔接。在 LangChain 中,它是所有 Agent 变体的共同执行引擎。

核心逻辑:就是 ReAct 循环

用最简单的伪代码描述,AgentExecutor 的核心就是一个 while 循环

python

复制下载

def agent_executor(user_input):
    # 初始化:把用户输入和可用工具告诉模型
    messages = [system_prompt, human_input]
    
    while iteration < max_iterations:
        # 1. 思考(Reason):调用 LLM,获取下一步指令
        llm_output = llm.invoke(messages)
        
        # 2. 解析输出
        if llm_output.contains("Final Answer"):
            return llm_output.final_answer   # 结束循环
            
        # 3. 行动(Act):如果是 Action,解析出工具名和参数
        action = parse_action(llm_output)    # 例如 {"tool": "get_weather", "args": {"city": "北京"}}
        
        # 4. 观察(Observe):执行工具,获取结果
        observation = tools[action.tool].run(action.args)
        
        # 5. 将观察结果拼回对话,继续循环
        messages.append(observation)
        iteration += 1
        
    return "已达最大迭代次数,任务可能未完成"
补充:LangGraph 是 AgentExecutor 的进化版

当你需要更精细的控制(比如分支、循环、人机交互)时,LangGraph 提供了更底层的图执行引擎。可以理解为:

  • AgentExecutor = 固定流程的循环控制器(适合大多数场景)
  • LangGraph = 可自定义流程的图执行器(适合复杂业务流)

LangChain Expression Language (LCEL)

LCEL 是一种声明式的、基于管道操作符 | 的语言,用于将 LangChain 的各种组件(提示词、模型、解析器、检索器等)组合成可执行的流水线(Chain)。

AI 世界的 Unix 管道——就像在命令行里用 | 把多个命令串起来一样,LCEL 让你用同样的思维方式组装 AI 组件

# Unix 管道:一个命令的输出是下一个命令的输入
cat file.txt | grep "error" | sort | uniq -c

# LCEL 管道:一个组件的输出是下一个组件的输入
chain = prompt | model | output_parser

你能解决什么问题:用简洁的代码构建可复用的链,比如将检索、提示、模型调用、输出解析组合成一个 RAG 链,并支持流式输出、异步执行、重试等高级特性。

LCEL 的核心语法

1. 最基本的管道:组件1 | 组件2 | 组件3

这是 LCEL 最核心的用法。每个组件都必须是 Runnable(可运行对象),LangChain 的大部分核心组件都已经实现了 Runnable 接口

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

# 1. 定义组件
prompt = ChatPromptTemplate.from_template("讲一个关于 {topic} 的笑话")
model = ChatOpenAI(model="gpt-4")
parser = StrOutputParser()

# 2. 用 | 组合成链
chain = prompt | model | parser

# 3. 调用链
result = chain.invoke({"topic": "程序员"})
print(result)
2. 更复杂的组合:RunnableParallel 和 RunnablePassthrough

当你需要并行处理保留原始输入时,可以使用这两个工具

from langchain_core.runnables import RunnableParallel, RunnablePassthrough

# 创建一个并行任务:同时做两件事
parallel_chain = RunnableParallel(
    # 任务1:调用检索器获取上下文
    context = retriever,
    # 任务2:把原始问题原样传递下去
    question = RunnablePassthrough()
)

# 组合进完整流程
rag_chain = parallel_chain | prompt | model | parser

LCEL 的底层原理:Runnable 协议

LCEL 能工作的基础是 Runnable 协议——所有用 | 连接的组件都必须实现这个统一的接口 Runnable 接口定义了四个核心方法,这意味着你构建的任何 LCEL 链都自动获得这些能力:

方法作用适用场景
.invoke()同步调用普通的单次请求
.ainvoke()异步调用需要并发处理多个请求
.stream()流式输出逐字返回生成结果,提升用户体验
.batch()批量处理同时处理多个输入,提高吞吐量

AI Agent 上下文管理

1. 什么是上下文管理?

在 AI Agent 中,上下文 是指 Agent 在处理用户请求时所依赖的全部信息,包括:

  • 对话历史:用户和 Agent 之间的历史消息。
  • 状态信息:当前任务进度、已执行的操作、中间结果。
  • 外部知识:从知识库检索到的相关文档、记忆。
  • 工具定义:可用的工具及其描述。
  • 用户偏好:长期记忆中存储的个人化信息。

上下文管理 就是对这些信息的 收集、组织、存储、检索、更新和裁剪 的过程,确保 LLM 在每次调用时都能获得最相关、最必要的上下文,同时不超过模型的上下文窗口限制。

2. 为什么上下文管理如此重要?

挑战无良好管理的后果管理良好的价值
LLM 上下文窗口有限长对话被截断,丢失关键信息通过摘要或检索保留核心内容
无关信息干扰模型被噪声干扰,回答质量下降只注入最相关的上下文
成本爆炸每次请求都塞入大量 token减少 token 消耗,降低成本
多轮一致性Agent 忘记之前的约定保持对话连贯性
个性化缺失每次都是“陌生人”记住用户偏好,提供个性化服务

3. 上下文管理的四层体系

deepseek_mermaid_20260310_642ea0.png

第一层:短期对话上下文
  • 内容:最近几轮用户和 Agent 的对话。

  • 管理策略

    • 滑动窗口:保留最近 K 轮对话(如 ConversationBufferWindowMemory)。
    • 对话摘要:当对话过长时,用 LLM 生成摘要替换旧对话(如 ConversationSummaryMemory)。
    • 混合策略:保留最近 N 轮 + 之前对话的摘要。
  • LangChain 实现ConversationBufferWindowMemoryConversationSummaryMemoryConversationTokenBufferMemory

第二层:任务状态上下文
  • 内容:当前多步任务中的进度、已收集的信息、中间结果。

  • 管理策略

    • 状态对象:维护一个状态字典,在每一步更新。
    • 图状态管理:LangGraph 的 StateGraph 自动管理节点间的状态传递。
    • 工具调用结果:每次工具返回的 Observation 拼接到上下文中。
  • LangChain 实现AgentExecutor 内部维护消息列表,LangGraph 的 State

第三层:长期记忆上下文
  • 内容:跨会话的用户信息、偏好、历史经验。

  • 管理策略

    • 向量存储:将重要信息向量化,需要时语义检索。
    • 结构化存储:用户属性用键值对存储。
    • 写入时机:用户显式告知、关键信息提取、任务完成总结。
  • LangChain 实现VectorStoreRetrieverMemoryEntityMemory

第四层:外部知识上下文
  • 内容:从知识库、文档、API 实时检索的信息。

  • 管理策略

    • RAG:每次请求时检索相关文档片段。
    • 工具调用结果:工具返回的数据作为临时知识。
    • 缓存:相同查询可缓存检索结果。
  • LangChain 实现:检索器组件、create_retrieval_chain

 缓存机制对比:常规业务 vs AI Agent 场景

维度常规业务缓存(如 Web 应用)AI Agent 缓存核心差异
缓存对象数据库查询结果、API 响应、计算密集型结果嵌入向量、大模型响应、检索结果AI 场景缓存的是“语义计算结果”而非确定性数据
缓存粒度通常是完整的响应(如用户信息、商品详情)可以是分块缓存(如文本块的嵌入)或完整结果缓存更细粒度,需要组合使用
缓存键设计基于请求参数(如 user_id=123基于语义内容(文本的哈希值或内容本身)相同文本在不同请求中应返回相同嵌入
一致性要求强一致性(用户修改后需立即更新)弱一致性可接受(模型版本升级可能导致嵌入变化)AI 缓存可以容忍一定程度的“过时”
失效策略基于时间(TTL)或主动失效(更新时删除)基于模型版本业务规则(如简历更新)失效条件更复杂
命中率考量高重复性请求(如热门商品页)相同或相似文本的重用(如常见问题)语义相似性也可能命中(需要近似匹配缓存)

AI Agent 场景的特殊缓存设计

1. 嵌入向量缓存(最常用)

from functools import lru_cache

@lru_cache(maxsize=1024)
def cached_embedding(text: str) -> list[float]:
    """缓存文本的嵌入向量,相同文本只调用一次 API"""
    return _get_embedding(text)  # 原生 API 调用

适用场景:同一份简历的不同检索查询可能用到相同的查询文本,或者多份简历中有相同的关键词(如“项目管理”)。

2. 检索结果缓存

# 缓存检索到的文本块,避免重复检索
retrieval_cache = {}  # 可用 Redis 等替代

def get_cached_retrieval(query_embedding_hash: str, resume_id: str) -> list[str] | None:
    cache_key = f"{resume_id}:{query_embedding_hash}"
    return retrieval_cache.get(cache_key)

def set_cached_retrieval(query_embedding_hash: str, resume_id: str, chunks: list[str]):
    cache_key = f"{resume_id}:{query_embedding_hash}"
    retrieval_cache[cache_key] = chunks  # 可设置 TTL

完整评价结果缓存

def get_cached_evaluation(resume_id: str, industry: str, role: str) -> ResumeEvaluationResult | None:
    """检查是否已有相同输入的评价结果"""
    cache_key = f"eval:{resume_id}:{industry}:{role}"
    return cache.get(cache_key)

def cache_evaluation(resume_id: str, industry: str, role: str, result: ResumeEvaluationResult):
    cache_key = f"eval:{resume_id}:{industry}:{role}"
    cache.set(cache_key, result, ttl=3600)

缓存失效策略的特殊考虑

在 AI 场景中,缓存失效不仅基于时间,还要考虑:

  • 模型版本更新:如果更换了嵌入模型(如从 v2 升到 v3),所有嵌入缓存应失效。
  • 简历内容更新:如果用户重新上传简历,对应 resume_id 的所有缓存应删除。
  • 评价标准变化:如果修改了 prompt 或评分维度,历史评价结果可能不再适用。

解决方案:在缓存键中加入版本号内容哈希

EMBEDDING_MODEL_VERSION = "text-embedding-v3"
CACHE_KEY_PREFIX = f"eval:v1"  # 评价逻辑版本

def get_cache_key(resume_id: str, industry: str, role: str) -> str:
    return f"{CACHE_KEY_PREFIX}:{resume_id}:{industry}:{role}"

image.png

AI 场景缓存更关注语义重用(相同文本的嵌入、相似查询的检索)、细粒度组合(嵌入 + 检索 + 评价),以及版本化失效(模型/提示词升级)。

嵌入批量生成的核心是:

  1. 使用 embed_documents 而非循环调用 embed_query
  2. 结合缓存避免重复计算相同文本
  3. 根据数据规模选择实时批量或离线批量推理

ai agent中的重试与降级

AI 应用(如你的简历系统)面临不同的挑战:

挑战说明示例
调用成本高一次失败可能浪费大量 token 或时间大模型调用中途失败,已消耗的 token 无法挽回
结果不确定性重试可能得到不同结果同样 prompt 两次调用可能输出略有差异
降级结果难替代无法简单用缓存代替实时生成简历评价必须基于最新简历,不能返回旧结果
API 限制多样限流(rate limit)、超时、模型不兼容等阿里云 QPS 限制、模型负载过高
维度常规业务重试/降级AI 应用重试/降级差异点
重试成本低(接口调用轻量)(每次调用消耗 token/时间)AI 重试可能造成更大损失
结果确定性幂等接口,重试结果相同非确定性,重试可能结果不同需考虑结果一致性
降级难度容易(返回缓存/默认值)困难,无法简单用旧结果替代AI 输出高度依赖上下文
超时处理直接失败或重试需权衡等待时间与成本大模型调用可能长达数十秒
限流应对简单等待后重试需精细控制,避免积压AI API 限流更严格

LangSmith vs Prometheus/Grafana 的核心差异

监控维度的根本不同

维度LangSmithPrometheus/Grafana
核心关注点定性监控:模型输入输出、推理逻辑、工具调用链、评估分数定量监控:QPS、延迟、错误率、资源利用率
监控对象Prompt内容、Token消耗、Agent决策路径、RAG检索结果CPU/内存/GPU、网络IO、请求量、服务状态
数据性质语义级数据(结构化日志 + 追踪)时序指标(数值聚合)
典型问题“为什么这个请求回答错误?” “Agent为什么选择了这个工具?” “这个Prompt版本效果如何?”“服务响应变慢了吗?” “GPU利用率是否饱和?” “错误率是否超过阈值?”

一个具体例子:你的简历系统

在你的简历评价系统中,两者的分工应该是:

LangSmith 负责

  • 记录每次评价的完整执行链路:_retrieve → _skills → _evaluate
  • 查看每个节点的输入输出(检索到的证据、信号JSON、最终评价结果)
  • 查看大模型调用详情:Prompt内容、Token消耗、响应时间
  • 对比不同版本的评价效果(如修改Prompt后的变化)

Prometheus/Grafana 负责

  • 监控 /api/resumes/upload 和 /evaluate 接口的QPS、P99延迟
  • 监控嵌入API调用失败率、重试次数
  • 监控Token消耗趋势,预估成本
  • 告警:当错误率超过5%时通知值班工程师

LangSmith 的追踪结束判断机制

1. 根调用(Root Run)的完成

每次请求在 LangChain/LangGraph 中都有一个根调用。在你的简历评价系统中:

  • 根调用evaluate_resume 函数调用
  • 子调用_retrieve → _skills → _evaluate 每个节点的执行

当根调用函数执行完毕并返回结果时,LangSmith 就知道这次请求结束了。

代码层面的表现

def evaluate_resume(resume_id: str, industry: str, role: str) -> ResumeEvaluationResult:
    # 这是根调用开始
    initial_state = {...}
    out = GRAPH.invoke(initial_state)  # 这里面会有多个子调用
    # 当这行执行完毕,返回 result 时,根调用结束
    return out["result"]

2. 回调机制(Callback)

LangChain 内部有一个完善的 回调系统,每次执行开始时都会触发 on_chain_start,结束时触发 on_chain_end

# LangChain 内部简化逻辑
class BaseCallbackHandler:
    def on_chain_start(self, serialized, inputs, **kwargs):
        # 记录开始时间、输入
        pass
    
    def on_chain_end(self, outputs, **kwargs):
        # 记录结束时间、输出,计算耗时
        # 此时知道这个节点执行完毕
        pass
    
    def on_chain_error(self, error, **kwargs):
        # 如果出错,记录错误
        pass

LangSmith 通过注册自己的回调处理器,监听这些事件,从而知道每个节点何时开始、何时结束。

3. 嵌套调用的追踪

对于嵌套调用(比如 GRAPH.invoke 内部又调用多个节点),LangSmith 通过父子关系来追踪:

# 伪代码表示调用栈
evaluate_resume (根调用)
  ├─ GRAPH.invoke (子调用1)
  │    ├─ _retrieve (子调用1.1)
  │    ├─ _skills (子调用1.2)
  │    └─ _evaluate (子调用1.3)
  └─ return result (根调用结束)

只有当所有子调用都完成后,根调用才会结束,此时 LangSmith 知道整个 trace 完成。

4. 异步和流式处理

对于异步或流式输出,LangSmith 的处理更精细:

  • 开始:收到第一个 token 时记录开始
  • 结束:收到最后一个 token 或连接关闭时记录结束
  • 中间状态:可以记录流式输出的片段

5. 超时和错误情况

如果请求异常中断:

  • 错误on_chain_error 被触发,记录错误信息
  • 超时:LangChain 客户端会触发超时异常,同样被回调捕获
  • 手动中断:如果程序被 kill,可能来不及上报,但 LangSmith 会在服务端通过心跳机制发现连接中断

🧠 在你的简历系统中的实际表现

当你运行一次评价请求时,LangSmith 看到的执行树是这样的:

Root Run: evaluate_resume
  ├─ Run: GRAPH.invoke
      ├─ Run: _retrieve
          ├─ Run: _get_embedding (LLM调用)
          └─ Run: search_resume_chunks (工具调用)
      ├─ Run: _skills
          ├─ Run: load_resume_raw_text (文件读取)
          └─ Run: extract_signals_from_text (规则函数)
      └─ Run: _evaluate
           └─ Run: structured.invoke (大模型调用)
  └─ (返回结果)

每个节点都有:

  • 开始时间start_time
  • 结束时间end_time
  • 耗时:自动计算
  • 状态:成功/失败

OpenSpec

规范驱动开发的 AI 编程新范式

它是一套轻量级的规范驱动开发框架,让 AI 成为需求的“执行者”而非“创造者”。通过将规范(Specs)与代码同仓管理,OpenSpec 实现了需求、设计、任务、代码、测试的完整闭环。

OpenSpec 的核心价值

痛点OpenSpec 解法
AI 偏离需求先写规范(Spec),AI 严格按规范生成代码
需求与代码脱节规范与代码同版本管理,自动归档
变更不可追溯每个变更独立目录,完整保留 proposal、design、tasks
团队协作困难规范是“单一事实来源”,评审只需看 proposal + delta
技术债积累强制测试任务,归档前验证,规范随代码演进

目录结构与文件说明

your-project/
├── AGENTS.md                      # 根目录:AI 工作流指引(告诉 AI 何时使用 OpenSpec)
├── openspec/
│   ├── specs/                     # 【真相来源】系统当前已实现的所有能力
│   │   └── [capability]/          # 按能力模块划分
│   │       └── spec.md            # 该能力的规范(BDD格式)
│   │
│   ├── changes/                   # 【施工现场】正在进行中的变更提案
│   │   └── [change-name]/         # 每个变更一个独立目录
│   │       ├── proposal.md        # 为什么要改?改什么?
│   │       ├── design.md          # 技术方案(可选)
│   │       ├── tasks.md           # 实施任务清单
│   │       └── specs/             # 规范增量(相对于 specs/ 的变更补丁)
│   │           └── [capability]/
│   │               └── spec.md
│   │
│   └── changes/archive/           # 【历史档案】已完成的所有变更
│       └── YYYY-MM-DD-[name]/     # 完整保留 proposal、design、tasks、specs
│
├── .cursor/                       # 如果你使用 Cursor,会自动生成 Slash 命令
│   └── commands/
│       ├── opsx-explore.md
│       ├── opsx-ff.md
│       ├── opsx-apply.md
│       └── ...
└── .codebuddy/                    # 如果你使用 CodeBuddy,相关配置会放在这里

关键文件解读

文件内容为什么重要
specs/<capability>/spec.mdBDD 格式的系统行为描述单一事实来源,AI 和人类共享
proposal.md变更的“为什么”和“改什么”评审入口,强制思考价值
tasks.md可执行的 checkbox 任务清单AI 按此逐步实现,进度可追踪
specs/ 增量本次变更新增/修改的场景清晰界定范围,归档时自动合并
AGENTS.mdAI 工作流指令让 AI 自动遵守 OpenSpec 规范
命令用途
/opsx:explore探索模式,与 AI 讨论需求,不产生文件
/opsx:new "功能名"创建变更,逐步引导填写文档
/opsx:ff "功能名"快速模式:一次性生成 proposal、specs、design、tasks
/opsx:continue继续生成下一个缺失的文档(配合 /opsx:new 使用)
/opsx:apply "变更名"开始按 tasks.md 实现代码
/opsx:verify "变更名"验证代码实现与规范是否一致
/opsx:archive "变更名"归档完成的变更

Spec-Driven Development

规范驱动开发(Spec-Driven Development,简称 SDD)是一种以规范(Specification)为核心的软件开发方法论。核心理念是:

在编写任何代码之前,先以机器可读、人类可理解的方式,精确描述系统“应该做什么”,然后将规范作为唯一真相来源,驱动后续的设计、实现、测试和维护。

用一句话概括:规范即代码,代码即规范的实现。

Spec-Driven Development 的解决方案

SDD 通过“规范先行”+“规范即代码”+“AI 可读”三大原则,系统性地解决上述问题:

  • 规范与代码同版本管理:任何时候 checkout 到某个 commit,都能看到当时的完整规范
  • 规范作为 AI 的“合同” :AI 不再是自由发挥,而是严格按规范执行
  • 变更有完整上下文:每个功能都对应独立的 proposal、specs、tasks,可追溯完整决策过程
  • 测试从规范自动生成:规范中的场景(Scenario)直接映射为测试用例
  • 规范是团队的唯一真相来源:产品、开发、测试共享同一份规范

Spec-Driven Development 的核心原则

1. 规范即真相(Specs as Source of Truth)

规范文件是系统行为的唯一权威描述。代码只是规范的实现,文档是规范的派生。

  • 要了解系统能做什么 → 看 specs/
  • 要修改系统行为 → 先修改规范,再修改代码
  • 要评审需求 → 看 proposal.md + 规范增量

2. 规范即代码(Specs as Code)

规范文件与代码文件同级管理,受版本控制,参与 CI/CD:

  • 规范变更必须通过 PR 流程
  • CI 可以自动验证规范格式、检查与代码的一致性
  • 规范文件可以像代码一样进行 diff、review、blame

3. 变更即 PR(Change as PR)

每个功能、重构或 bug 修复,都对应一个独立的变更提案(Change Proposal),包含:

  • proposal.md:为什么要改?(业务价值、影响范围)
  • specs/:规范增量(哪些场景新增/修改)
  • design.md:技术方案(复杂变更需要)
  • tasks.md:可执行的任务清单

4. 增量演进(Incremental Evolution)

系统规范不是一次性写成的,而是随变更增量演进

  • 每个变更只描述增量(新增/修改的场景)
  • 归档时,增量被智能合并到主规范
  • 主规范始终保持完整、干净、可读

5. AI 原生设计(AI-Native)

规范文件的格式和结构经过专门设计,让 AI 能够:

  • 精确理解:BDD(行为驱动开发)格式的场景描述,AI 可准确理解预期行为
  • 可靠执行:tasks.md 的 checkbox 格式,AI 可逐项完成并追踪进度
  • 自主验证:AI 可以对比规范与代码,发现偏差并修正

Spec-Driven Development 的工作流

SDD 通常遵循  “提案 → 规范 → 设计 → 任务 → 实现 → 验证 → 归档”  的七阶段工作流:

各阶段产出物

阶段产出物作用
提案proposal.md记录“为什么改、改什么”
规范specs/ 增量描述系统行为的变化(BDD 格式)
设计design.md技术方案、架构决策(可选)
任务tasks.md可执行的 checkbox 清单
实现代码文件规范的实现
测试测试文件从规范场景映射的测试用例
验证验证报告规范与代码一致性检查
归档归档目录历史决策的完整记录

image.png

  • OpenSpec:负责  “定义契约” ——把需求转化为结构化的规范(Specs)、设计文档(Design)和任务清单(Tasks),回答“我们要做什么、为什么要做”。
  • Superpowers:负责  “执行契约” ——在代码实现阶段强制遵循工程纪律(如 TDD、代码审查、子代理并行工作),确保“我们怎么做才规范、可靠”。

在实际工作流中,你可以先用 OpenSpec 的 /opsx:ff 生成完整的变更提案和任务清单,然后在 Cursor 或 CodeBuddy 中让 Superpowers 的技能(如 TDD、代码审查)接管实施过程,这样既保证了需求的精确性,又保证了代码的规范性和可靠性。