什么是 AI Agent?和 ChatBot 到底有什么区别
什么是 AI Agent?和 ChatBot 到底有什么区别
很多人第一次听到 “AI Agent” 这个词,第一反应是:这不就是 ChatGPT 换了个名字吗?
说实话,我当初也是这么想的。直到在 NVC 练习平台的开发中,真正把 12 个专职 Agent 跑起来,才意识到这完全是两码事。
先搞清楚 ChatBot 是什么
ChatBot 的本质是问答机器。你问一句,它答一句。不管是规则引擎驱动的老式客服机器人,还是基于大语言模型的现代对话系统,核心逻辑都一样:
用户输入 → 模型处理 → 输出回答
这个过程有几个特点:
- 单轮为主:每次对话相对独立,上下文依赖靠"记忆"拼凑
- 被动响应:你不问,它不说
- 无状态:聊完就忘(除非显式实现记忆)
用代码表示大概是这样:
def chat(user_input: str) -> str:
response = llm.generate(user_input)
return response
简单粗暴,一问一答。
Chain 是什么?比 ChatBot 多一步
Chain(链)是 LangChain 早期的核心概念。它把多个步骤串起来,形成一个固定流程:
def chain(user_input: str) -> str:
# Step 1: 提取关键信息
entities = extract_entities(user_input)
# Step 2: 查询数据库
context = query_database(entities)
# Step 3: 生成回答
response = llm.generate(f"{context}\n\n{user_input}")
return response
Chain 比 ChatBot 强的地方在于:它能做多步处理,调用外部工具。但本质上还是固定流程——你写死了步骤,它按顺序执行。
如果用户的问题不在预设流程内?抱歉,它处理不了。
Agent:能自己决定下一步做什么
Agent 和前两者的根本区别在于自主决策。
Agent 不需要你预先写死流程。它拿到任务后,会自己思考:我需要调用什么工具?获取什么信息?下一步该做什么?
用伪代码表达:
def agent(task: str) -> str:
context = []
while not is_done(task, context):
# 思考下一步
action = think(task, context)
# 执行动作
result = execute(action)
context.append(result)
return summarize(context)
看到那个 while 循环了吗?这就是 Agent 的核心——它能根据当前状态,反复决策、反复执行,直到任务完成。
这个循环有个专业名字:AgentLoop。
Agent 的四个核心组件
一个完整的 Agent 系统,通常包含四个部分:
1. LLM 大脑
负责理解任务、推理决策。这是 Agent 的"智商"来源。
2. Tools(工具)
Agent 能调用的能力。搜索、数据库查询、文件操作、API 调用……工具越多,Agent 能做的事越多。
3. Memory(记忆)
存储历史对话、中间结果、长期知识。没有记忆的 Agent 每次都从零开始。
4. Planning(规划)
把复杂任务拆解成可执行的步骤。这是 Agent 区别于简单工具调用的关键。
画成架构图:
注意那个双向箭头——Brain 会反复和各个组件交互,而不是线性执行。
Perceive → Think → Act:Agent 的工作循环
Agent 的工作遵循一个经典循环:感知 → 思考 → 行动。
在实际代码中,这个循环看起来像这样:
public class AgentLoop {
private final LLM llm;
private final ToolRegistry tools;
private final Memory memory;
public String run(String task) {
List<Message> context = new ArrayList<>();
context.add(new UserMessage(task));
while (true) {
// Think: 让 LLM 决定下一步
AgentResponse response = llm.chat(context, tools.getDefinitions());
// 如果 LLM 决定完成任务,返回结果
if (response.isFinalAnswer()) {
return response.getContent();
}
// Act: 执行工具调用
for (ToolCall call : response.getToolCalls()) {
ToolResult result = tools.execute(call);
context.add(new ToolMessage(result));
memory.save(call, result);
}
}
}
}
这段代码来自我在 NVC 项目中的实际实现。关键点在于:我们关闭了 Spring AI 的自动工具执行,自己控制整个循环。
为什么要这么做?因为自动执行太黑盒了。我想在循环的每一步插入自己的逻辑。
实战:NVC 项目的 12 个 Agent 架构
在 NVC 练习平台中,我们设计了 12 个专职 Agent,每个负责一个特定领域:
| Agent 名称 | 职责 |
|---|---|
| DialogueAgent | 主对话管理 |
| EmotionAgent | 情绪识别与分析 |
| IntentAgent | 用户意图理解 |
| FeedbackAgent | 练习反馈生成 |
| ScoringAgent | 评分计算 |
| HintAgent | 提示生成 |
| SummaryAgent | 对话总结 |
| ContextAgent | 上下文管理 |
| ValidationAgent | 输入校验 |
| TranslationAgent | 多语言支持 |
| AnalyticsAgent | 数据分析 |
| AdminAgent | 管理操作 |
这 12 个 Agent 不是各干各的,而是通过一个编排中枢统一调度。
编排中枢的核心逻辑:
@Component
public class AgentOrchestrator {
private final Map<String, Agent> agents;
private final AgentRouter router;
public String process(String input, SessionContext ctx) {
// 路由到合适的 Agent
List<String> agentSequence = router.route(input, ctx);
String result = input;
for (String agentName : agentSequence) {
Agent agent = agents.get(agentName);
result = agent.process(result, ctx);
}
return result;
}
}
为什么关闭自动工具执行?
Spring AI 提供了很方便的自动工具执行功能——LLM 说要调用什么工具,框架自动帮你调用。
听起来很美好,但实际用起来问题不少:
- 调试困难:工具调用在框架内部发生,你想看中间状态很麻烦
- 控制力弱:想在工具调用前后加逻辑?对不起,框架没给你这个口子
- 错误处理粗糙:工具调用失败了,框架默认直接抛异常,你很难做优雅降级
所以我们选择了手动控制:
// 关闭自动执行
spring.ai.chat.client.tool-auto-execution=false
// 自己控制循环
while (true) {
AgentResponse response = llm.chat(messages, toolDefs);
if (response.hasToolCalls()) {
for (ToolCall call : response.getToolCalls()) {
// 在这里插入 Hook
hookChain.beforeToolCall(call);
ToolResult result = toolRegistry.execute(call);
hookChain.afterToolCall(call, result);
}
}
}
7 层 Hook 链:在循环中插入业务逻辑
手动控制循环最大的好处是:你可以在任何位置插入 Hook。
我们在 AgentLoop 中设计了 7 层 Hook:
public class AgentHookChain {
private final List<AgentHook> hooks = new ArrayList<>();
// 1. 任务开始前
public void beforeTask(String task, SessionContext ctx) {
hooks.forEach(h -> h.onTaskStart(task, ctx));
}
// 2. LLM 调用前
public void beforeLLMCall(List<Message> messages) {
hooks.forEach(h -> h.onBeforeLLM(messages));
}
// 3. LLM 返回后
public void afterLLMCall(AgentResponse response) {
hooks.forEach(h -> h.onAfterLLM(response));
}
// 4. 工具调用前
public void beforeToolCall(ToolCall call) {
hooks.forEach(h -> h.onBeforeTool(call));
}
// 5. 工具调用后
public void afterToolCall(ToolCall call, ToolResult result) {
hooks.forEach(h -> h.onAfterTool(call, result));
}
// 6. 决策点(是否继续循环)
public boolean shouldContinue(AgentState state) {
return hooks.stream().allMatch(h -> h.onDecision(state));
}
// 7. 任务结束后
public void afterTask(String result, SessionContext ctx) {
hooks.forEach(h -> h.onTaskEnd(result, ctx));
}
}
每个 Hook 都是一个扩展点。比如:
- 在
beforeLLMCall中注入系统提示词 - 在
afterToolCall中记录审计日志 - 在
shouldContinue中实现最大轮次限制 - 在
afterTask中触发后续处理
总结一下三者的区别
| 特性 | ChatBot | Chain | Agent |
|---|---|---|---|
| 交互模式 | 单轮问答 | 固定流程 | 自主决策 |
| 工具调用 | 无 | 预设顺序 | 动态决定 |
| 状态管理 | 无状态 | 有限状态 | 完整记忆 |
| 灵活性 | 低 | 中 | 高 |
| 复杂度 | 低 | 中 | 高 |
一句话概括:ChatBot 是问答机器,Chain 是固定流水线,Agent 是能自己想办法的智能体。
写在最后
理解 Agent 和 ChatBot 的区别,不是为了追概念,而是为了在合适的场景选择合适的方案。
简单的问答场景,用 ChatBot 就够了。流程固定的业务,Chain 更省心。只有当任务复杂、需要多步决策、涉及多种工具时,Agent 的价值才真正体现出来。
在 NVC 项目中,12 个 Agent 协同工作的架构让我们能够灵活应对各种练习场景,但也带来了更高的调试和维护成本。这是个权衡——没有银弹,只有适合。
更多推荐



所有评论(0)