AI Agent的本质是能够感知环境、自主决策并执行行动的智能实体。与传统AI系统最大的区别在于Agent具有自主性、反应性、目标导向和学习能力,它不再是简单的工具,而是能够主动规划和完成复杂任务的智能体。从1997年击败国际象棋世界冠军的IBM“深蓝”,到2011年苹果推出的个人助理Siri,都展示了Agent在特定领域的强大能力,关键的转折点发生在2023年左右,大语言模型LLM的出现为Agent提供了强大的通用理解和推理能力,使其不再局限于单一任务。
Agent 架构模式
- 组成组件
Agent:智能代理,它是一个能够感知环境、做出决策并执行动作的软件实体(比起LLM只能“回答问题”,Agent可以真正地“执行任务”)。在LLM语境中,Agent通常利用LLM作为大脑,来理解用户输入、决定需要执行的动作(比如调用工具)、处理工具返回的结果并生成响应。
LLM(大语言模型):如GPT系列,是Agent的核心,负责理解自然语言、进行推理和生成文本。
Tool:工具,是Agent可以调用的函数,用于执行特定任务,比如查询数据库、调用API。Tool扩展了Agent的能力,使其能够获取实时信息或执行具体操作。Function Calling:函数调用,是LLM的一种能力,允许模型根据用户输入决定何时以及如何调用哪个函数(Tool),并以结构化格式(如JSON)输出函数调用参数。然后由外部系统执行该函数。
Prompt:提示词,是引导LLM生成期望输出的文本。在Agent中,Prompt通常包含系统指令(定义Agent的角色和能力)、用户输入、对话历史以及工具描述等。RAG(检索增强生成):通过从外部知识库检索相关信息,并将其作为上下文提供给LLM,从而生成更准确、更相关的回答。MCP(模型上下文协议):MCP可以包含本地tools和外部API,但通常 MCP更强调于将工具(无论是本地tools还是外部API)以标准化的上下文协议暴露给AI模型。MCP可以看作是一个中间层,它将工具抽象成标准的接口,使得AI Agent可以通过统一的协议来调用这些工具,从而实现模型与工具之间的解耦。 - 一个典型的工作流程如下:
用户输入自然语言请求。
Agent将用户输入、对话历史、可用的工具描述(通过Function Calling定义)以及系统提示词组合成一个Prompt,发送给LLM。
LLM根据Prompt判断是否需要调用工具。如果需要,LLM会返回一个函数调用请求(包括函数名和参数)。
Agent解析LLM返回的函数调用请求,并执行对应的工具(Tool)。
工具执行后返回结果,Agent将工具执行结果作为上下文,再次调用LLM,生成最终的自然语言响应。
Agent将响应返回给用户。
在这个过程中,RAG可以在第一步之前或之中介入,通过检索外部知识库来增强Prompt的上下文。
- a demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#### main.py
from pydantic_ai.models.gemini import GeminiModel
from pydantic_ai import Agent
from dotenv import load_dotenv
import tools
# 模型API Key等可以写到.env文件 并加载到环境变量
load_dotenv()
model = GeminiModel("gemini-2.5-flash-preview-04-17")
# 将llm模型、系统prompt、工具tools “注册” 到 Agent
agent = Agent(model,
system_prompt="You are an experienced programmer",
tools=[tools.read_file, tools.list_files])
def main():
history = []
while True:
# eg. Input: list and read file. base on your konwledge tell me what lang each file use.
user_input = input("Input: ")
# 将用户输入、历史对话(上下文)发给 agent 并记录本次对话(短期记忆)
resp = agent.run_sync(user_input,
message_history=history)
history = list(resp.all_messages())
print(resp.output)
if __name__ == "__main__":
main()1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#### tools.py
from pathlib import Path
import os
base_dir = Path("./test")
def read_file(name: str) -> str:
# docstring 帮助模型理解 tools
"""Return file content. If not exist, return error message.
"""
print(f"(read_file {name})")
try:
with open(base_dir / name, "r") as f:
content = f.read()
return content
except Exception as e:
return f"An error occurred: {e}"
def list_files() -> list[str]:
print("(list_file)")
file_list = []
for item in base_dir.rglob("*"):
if item.is_file():
file_list.append(str(item.relative_to(base_dir)))
return file_list
MCP
MCP 可以看作是一个中间层,它将工具抽象成标准的接口,使得AI Agent可以通过统一的协议来调用这些工具,从而实现模型与工具之间的解耦。MCP 可以包含本地tools和外部API,但通常 MCP更强调于将工具(无论是本地tools还是外部API)以标准化的上下文协议暴露给AI模型。
- Agent通过集成的MCP Client向MCP Server发送请求,调用工具。因此,Agent不再直接调用具体的工具函数,而是可以使用任何符合MCP协议的工具,无论工具是本地还是远程。MCP模式下,我们不再直接注册这些Tools到Agent(如传统框架LangChain),而是注册MCP Client(可以看作是Tools的抽象层),然后Agent通过MCP Client来动态获取MCP Server提供的Tools列表,并在需要时调用它们。
示例流程:
步骤1:启动一个MCP Server,它提供了一些工具(例如,天气查询、计算器等)。
步骤2:在Agent框架中,配置MCP Client,并连接到该MCP Server。
步骤3:Agent在需要时,通过MCP Client查询MCP Server提供了哪些工具。
步骤4:当用户提问时,Agent决定调用哪个工具,然后通过MCP Client发送调用请求给MCP Server。
步骤5:MCP Server执行工具,并将结果返回给MCP Client,然后Agent接收结果并生成最终回答。? - MCP代表了AI应用架构的演进方向,从紧耦合的工具注册转向松耦合的工具治理,特别适合企业级AI应用的复杂集成场景。
RAG
RAG 的核心思想是:在让大模型回答问题之前,先从一个外部的、可随时更新的知识库中检索相关信息,然后将这些“新鲜”信息作为上下文和问题一起交给模型,从而引导模型生成更准确、及时且可追溯的答案。它能有效减少模型“幻觉”(即胡编乱造),让AI应用在知识密集型任务中变得真正可靠。以及,它能帮助构建专业领域专家对话机器人。
一个典型的RAG系统工作流程包含三个关键阶段:
- 知识库索引构建(Indexing)
这是准备阶段,目的是将您的私有知识库“灌输”进向量数据库。
文档解析与分块:首先,系统会解析各种格式的文档(如PDF、Word、HTML),将其转换为纯文本。然后,根据语义或结构将长文本切分成大小适宜的“文本块”(Chunks),以适应模型上下文长度限制。
向量化(Embedding):使用嵌入模型将每个文本块转换为一个高维向量(一组数字)。这个向量就像是文本在数学空间中的“坐标”,语义相近的文本,其向量在空间中的距离也更近。
向量存储:将这些向量及其对应的原始文本块、元数据(如来源、标题)一并存入向量数据库。 - 实时检索(Retrieval)
当用户提出问题时,系统执行以下操作:
使用相同的嵌入模型将用户问题也转换为一个向量。
将这个“问题向量”送入向量数据库,进行相似性搜索。数据库会快速找出与问题向量最相似的K个“文档向量”。
为了提高检索质量,常采用混合检索策略,结合语义向量搜索和传统关键词搜索,并利用重排序模型对初步结果进行精细排序,以提升准确性。 - 增强生成(Generation)
提示词增强:将检索到的最相关的文本块作为上下文,与用户的原始问题一起组合成一个结构化的提示词(Prompt)。
智能生成:将这个富含信息的提示词发送给LLM,基于您提供的权威上下文,而非仅凭其内部可能过时的知识,来生成最终答案
Agent流程编排
业务逻辑
LangChain
LangChain 是一个功能强大的大语言模型应用开发框架。与Spring在Java后端开发中的定位类似。
https://python.langchain.com/docs/concepts/
https://arxiv.org/abs/2302.07842
LangChain 包:通过 pip 命令(类似于Java的Maven或Gradle)安装到项目中,避免重复造轮子。
LangGraph
LangGraph 核心认知:用“有向图”构建智能体的新一代框架,是 用于构建有状态、多步骤、多分支智能体(Agent) 的框架,核心是将 Agent 的行为拆解为节点(Nodes) 和边(Edges),用有向图(Directed Graph) 替代老版本的“线性循环” 以支持更复杂的流程编排。
LangGraph 可以理解为:给 Agent 设计“流程图”的工具,而老版本 ReAct Agent 只是这个流程图中最基础的“单循环分支”。
https://docs.langchain.com/oss/python/langgraph/overview
- LangGraph 核心概念解析(多节点、边是关键)
- 核心基础:状态(State)
- 作用:整个图的“共享内存”,所有节点都能读写这个状态(比如用户问题、LLM 思考结果、工具调用结果、最终回答等)。
- 举例:在你之前的 CMDB Agent 中,状态里会包含:
1
2
3
4
5{
"messages": [{"role": "user", "content": "显示运行中的Linux服务器"},
{"role": "ai", "content": "思考过程+工具调用指令"},
{"role": "tool", "content": "工具调用结果"}]
} - 特点:状态是持久化的(通过 Checkpoint 如
InMemorySaver),支持中断、恢复、回溯(比如多轮对话的上下文保留)。
- 最小执行单元:节点(Node)
- 定义:图的最小操作单元,对应一个具体的功能(比如调用 LLM、调用工具、格式化回答、清洗用户问题)。
- 类型(实际开发中常见):
- LLM 节点:调用大模型生成思考结果或工具调用指令(比如你之前看到的“分析问题+工具选择”)。
- 工具调用节点:执行具体的工具函数(比如
cmdb_search、cmdb_query)。 - 预处理/后处理节点:清洗用户问题、格式化最终回答。
- 判断节点:根据状态判断流程走向(比如“是否需要继续调用工具?”)。
- 多节点的价值:你可以把 Agent 的复杂行为拆分成多个独立节点,比如:
用户输入清洗节点→LLM 思考节点→CMDB 工具节点→日志工具节点→回答格式化节点
- 流程的灵魂:边(Edge)
- 定义:节点之间的连接关系,定义流程的走向。LangGraph 支持三种边,这也是“多分支”的核心:
- 普通边(Direct Edge):直接从 A 节点跳转到 B 节点(比如“清洗节点”执行完,直接到“LLM 思考节点”)。
- 条件边(Conditional Edge):根据状态的内容判断跳转方向(最核心的“多分支”能力)。
- 举例:LLM 输出“需要调用 CMDB 工具”,则跳转到
cmdb_search节点;如果输出“需要调用日志工具”,则跳转到log_search节点;如果输出“无需调用工具”,则跳转到“回答节点”。
- 举例:LLM 输出“需要调用 CMDB 工具”,则跳转到
- 入口/出口边:定义图的开始节点(比如用户输入节点)和结束节点(比如回答节点)。
- 多边的价值:打破了老版本“单一循环”的限制,支持分支、并行、循环等复杂流程。
- 关键能力:检查点(Checkpoint)
- 作用:记录图的执行状态,支持中断、恢复、回溯(比如你之前用的
InMemorySaver就是内存级的检查点,还可以用 Redis、SQL 实现持久化)。 - 场景:多轮对话中,用户可以“回退”到上一步,或 Agent 崩溃后恢复执行。
- 作用:记录图的执行状态,支持中断、恢复、回溯(比如你之前用的
- 核心基础:状态(State)
- LangGraph 中 Agent 与 Tools 的工作机制(结合你的 CMDB 例子)
以你之前的“显示运行中的 Linux 服务器”为例,LangGraph 的执行流程可以拆解为一个极简的有向图:核心细节:1
2
3
4
5
6
7
8
9[入口节点:用户输入]
↓(普通边)
[LLM 思考节点]:分析问题,生成工具调用指令(cmdb_search + 入参)
↓(条件边:判断需要调用工具)
[工具调用节点]:执行 cmdb_search,将结果写回状态
↓(条件边:判断无需继续调用工具)
[LLM 回答节点]:基于工具结果生成最终回答
↓(普通边)
[出口节点:输出回答]- 状态驱动:所有节点都通过状态交互,没有直接的函数调用——LLM 节点从状态中读用户问题,工具节点从状态中读工具调用指令,执行后写回结果。
- 工具的解耦:工具本身是独立的函数(如
cmdb_search),LangGraph 只通过工具调用节点统一管理,支持多工具的动态选择和调用。 - 循环执行:通过条件边实现“思考→工具→再思考→再工具”的循环(比如用户问“查生产主机并统计数量”,可能需要先调用
cmdb_search,再调用cmdb_query统计)。
- LangGraph vs 老版本 ReAct Agent(核心区别)
老版本 ReAct Agent(LangChain v0.x 的AgentExecutor)是 LangGraph 的简化版,两者的核心差异在于流程的编排能力:维度 老版本 ReAct Agent(AgentExecutor) LangGraph 架构基础 线性循环(Single Loop) 有向图(Directed Graph) 节点/边 无物理节点拆分,只有“思考→工具”的逻辑两步;无多分支边,只有单一循环。 支持多节点、多类型边(条件边、普通边),可编排复杂流程。 状态管理 临时状态(每次循环重新生成,无持久化) 统一的状态对象,支持持久化、回溯(Checkpoint)。 流程灵活性 只能“思考→工具→思考”的单一循环,多工具需按顺序调用(一次一个)。 支持多分支(比如不同工具的并行调用)、条件跳转、中断恢复。 扩展性 扩展复杂流程(如多工具并行)需要大量自定义代码。 通过图的编排即可实现,无需修改核心逻辑。 老版本 ReAct Agent 的核心是 AgentExecutor的单一循环:它的“节点”只是逻辑上的两步(思考、工具),没有物理上的节点拆分,也没有多分支的边——即使有多个工具,也只能按顺序单次调用(一次调一个),无法实现并行或多分支跳转。1
2
3
4
5
6
7
8
9
10while True:
# 1. 调用 LLM 生成思考结果和工具调用指令
llm_output = llm.invoke(状态)
# 2. 判断是否需要调用工具
if 需要调用工具:
tool_result = tool.invoke(llm_output 中的指令)
# 将工具结果加入状态,继续循环
else:
# 生成最终回答,退出循环
break
比如:
老版本要实现“查生产主机+查今日告警”,只能先调用cmdb_search,再调用alert_search,通过多次循环实现。
LangGraph 可以通过多节点和条件边,甚至并行执行这两个工具(比如同时调用 CMDB 和告警工具,提升效率)。 - 五、总结:为什么需要 LangGraph?
- 从“单一循环”到“复杂图”:老版本 Agent 适合简单的单工具循环场景,而 LangGraph 适合需要复杂流程编排的场景(比如多工具、多分支、有状态的智能体)。
- 可视化与可维护性:将 Agent 的行为拆解为节点和边,流程更清晰,便于调试和维护(比如你之前看到的“两轮 LLM 调用”,在 LangGraph 中就是两个节点的执行)。
- 生产级能力:Checkpoint、状态持久化、中断恢复等能力,让 LangGraph 更适合生产环境的部署。
Spring AI
集成到Java