前言
最近在读 Agentic Design Patterns,结合之前对LLM本质的理解,对于现代人工智能的构造有了更深的理解。 这个技术方向创造了很多前所未闻的名词,不过我认为这些似乎不是什么困难的技术,也许这一系列名词是一条护城河,构成了一座信息壁垒,希望这篇文章能够让你对Agent有更 深入的理解。
总的来说,LLM 无时无刻都在处理各种各样的字符串,代码、写作、聊天这些都是各种各样的带信息的字符串。
现代人工智能的本质
简而言之,LLM 是一个文本补全机器。
LLM 是没有记忆的,每一次要求 LLM 回复都需要把所有历史消息一并发送,随着上下文长度的增加,每次的消息回复越来越昂贵,上下文窗口的长度(Context Window)就是 LLM 记忆的最大长度。 当上下文非常长时,对于下一个token的预测能力会下降,这是因为 LLM 注意力被长上下文所分散从而无法有效利用当前上下文。 为了保证输出质量,上下文的简洁是非常重要的,所以大多数 Agent 都搭配了上下文压缩技术,同时这也是 Prompt Engineering 中保证 Prompt 有效性的关键。
至于基于 LLM 的 Agent 为什么能够与代码、网页等交互,这都要感谢 Harness Engineering。根据 Harness Engineering 的理念, 可以把 Agent 理解为 Model + Harness,上文提到的上下文压缩技术就是 Harness 的一部分。 Harness 中的工具调用是 Agent 的核心能力,Agent 通过工具调用来与外部世界交互,获取信息、执行操作等。曾经的工具调用主要依赖 Prompt Engineering。 开发者需要在 System Message 中描述所有可用工具,并约定模型以特定格式(如 ReAct 的 Action / Action Input)输出工具调用,再由框架解析模型输出并执行对应工具。 后来,现代的 LLM 框架(如 LangChain)和模型服务商(Provider)共同将这一流程标准化。开发者不再需要手动编写工具 Prompt 或解析模型输出,只需定义工具列表,剩余的工具描述注入、工具调用解析、工具执行以及上下文维护等工作,都可以交由 Provider 与 LLM 框架协同完成。
很多人认为,多模态 LLM 与生俱来就拥有识别语音、图像等能力,但实际上并非如此。 早期的多模态系统大多是通过工具调用来实现的:LLM 本身主要负责文本理解和推理,而语音识别、图像理解等能力则由专门的模型完成,再将结果交给 LLM 进行处理。
例如,一个能够理解语音的系统可能会集成 STT(Speech-to-Text)模型,将语音转换为文本后再交给 LLM; 能够理解图像的系统则可能调用 OCR(光学字符识别)、Object Detection(目标检测)、Image Captioning(图像描述)等模型,将视觉信息转换为文本或结构化数据。 对于 Agent 而言,这些模型都可以看作是可调用的工具,从而扩展了 LLM 的能力边界。
随着多模态模型的发展,越来越多的能力开始被集成到模型内部。 现代多模态 LLM 通常会使用视觉编码器(Vision Encoder)、音频编码器(Audio Encoder)等模块,将图像、音频等不同模态转换为统一的 Token 表示, 再与文本 Token 一同输入 Transformer 进行推理。因此,对于模型而言,不同模态最终都表现为一串 Token,只是这些 Token 的来源不同。
那么,我们已经知道了 Agent 是通过 Harness 影响着文本之外的世界的,就不难理解 Agent 协作(Multi-Agent)了。比较广泛使用的一个 Agent 协作设计模式是 Supervisor Agent。 例如在 Coding 场景中,主模型(Supervisor)可能会调用代码编写、代码理解、代码质量检查等子 Agent 来完成任务,主模型则负责编排这些 Agent,在上下文中传递着上一个 Agent 的输出给下一个 Agent, 这样做能够提高资源的利用率,并且让 Workflow 更加可维护。
Multi-Agent 下,我们又该如何选择模型呢?在选择模型时,通常会考虑模型的能力、成本和可用性。不同 Agent 承担的任务不同,对模型的要求也不同。 例如,Codex 会使用能力更强的 GPT 模型完成代码生成,而将上下文压缩等相对简单的任务交给 GPT-mini,以降低整体成本。
表现较好的模型与较差的模型能力差距在哪呢?
正如我上文所说 LLM 是一个文本补全机器,所以模型的能力差距主要体现在文本补全的能力上。假如有这么两个架构、训练方法相同的模型,仅在数据集上有差距。
A模型的数据在编写Rust大量使用 unwrap,而B模型的数据在编写Rust时大量使用 match,那么面对相同的问题,A模型可能会更倾向于使用 unwrap,而B模型则更倾向于使用 match。
这时候,我们会认为B模型在编写Rust时的能力更强,因为它生成的代码更符合 Rust 社区的最佳实践。尽管模型有一定的泛化能力,但如果训练数据质量不高,模型很难稳定地产生高质量输出。
模型能力的上限由模型架构决定,而实际表现更多受训练数据质量和分布影响。
RAG、MCP都是些什么东西?
这一切都是在处理上下文。
RAG
RAG(Retrieval-Augmented Generation,检索增强生成)是一种先检索相关信息, 再利用这些信息辅助 LLM 生成答案的方法。 最简单的例子就是:根据用户的问题检索出几篇相关文档,将这些文档作为 Prompt 的一部分提供给 LLM, 使模型能够基于这些外部知识生成更加准确、相关的回答。
从广义上来说,只要系统先从外部知识源检索信息, 再将检索结果作为上下文提供给 LLM 生成回答,都可以视为一种 RAG。检索源既可以是向量数据库, 也可以是搜索引擎、数据库、API,甚至是负责搜集信息的子 Agent。
RAG 的主要目的是让模型能够利用训练数据之外的知识, 例如最新的信息、企业内部文档或其他私有数据,从而提升回答的准确性、时效性和可验证性。因此,许多 Chat Agent 会先搜索网页, 再结合搜索结果生成答案,这本质上也是一种 RAG。
那么经典的 RAG 是如何工作的呢? 假设你拥有大量文本文档,首先会将文档切分(Chunk)成较小的片段,然后为每个 Chunk 计算向量表示(Embedding), 并存储到向量数据库中。当用户提问时,系统会先将问题向量化,再在向量数据库中进行相似度检索,找到最相关的 Top-K 个文档片段, 并将这些内容作为 Prompt 的上下文提供给 LLM,最终生成回答。
切分文档的方法可以是按 token、段落、语义、甚至是让LLM去切分。如果不切分,过长的文档会占用上下文,降低回复的质量。
近来,出现了一些比较新的RAG方法,例如 GraphRAG,这种RAG就是把文档处理成知识图谱的形式,利用图结构来增强检索和生成的能力。GraphRAG 可以更好地捕捉文档之间的关系,从而提供更丰富的上下文信息给 LLM。
MCP
MCP(Model Context Protocol),简单来说,MCP由三部分组成,MCP Server、MCP Host 和 MCP Client, 目前来说,这是一种被广泛使用的能够让模型调用外部工具,获取外部信息的方法。
如何来理解 MCP 呢?顾名思义,模型上下文协议,我们完全可以把 MCP 看作一种协议。服务端提供固定的接口,客户端遵循协议与服务端进行交互。 MCP Server 提供工具列表、资源和服务等,宿主(MCP Host)初始化时,会让激活的MCP Client拉取工具列表,并在上下文中注入工具描述。MCP Client 通过遵循协议与 MCP Server 进行交互,从而实现工具调用和信息获取。
很多人可能会想,MCP和宿主提供的工具(Function Call)有什么区别呢?Function call 是宿主提供的工具接口,一般只解决一些这个场景下的特定问题, 如 Coding Agent 下,文件读写,执行命令等都属于 Function Call 的范畴。 MCP 则是一个更通用的协议,用于丰富模型的能力,允许模型调用各种工具和服务,从而实现更复杂的任务。 例如,如果一个MCP服务提供了执行代码的能力,那么模型就能够通过MCP实现代码执行的能力,而不必在本地沙盒中实现代码执行的功能。 MCP 往往也是以 Function Call 的形式提供给模型使用。
结语
现代 Agent 的能力并不是来源于 LLM 本身。
LLM 擅长的是文本推理,而 Harness 负责管理上下文、调用工具、检索外部知识、组织多个 Agent 协作。
不必神化这门技术,现代 Agent 的构造其实是对 LLM 的能力进行扩展和优化,使其能够更好地适应复杂的任务和多样化的应用场景。