8827 字
约 29 分钟
1
第2章 什么是AI-Agent

第2章 什么是AI-Agent

来源:https://ai-agent-guide.xiaofuge.cn/chapters/ch02-what-is-agent.html 所属:第一篇-Agent基础


从 ChatBot 到 Agent,AI 应用的范式跃迁

2.1 一个问题引入

如果我问你:ChatGPT 是 AI Agent 吗?

答案是:不是。ChatGPT 是一个出色的 ChatBot(聊天机器人),它能理解你的问题并生成回答。但它不会主动帮你查航班、订外卖、写代码到文件里。

而 AI Agent 可以。

这个区别看似微小,实则是 AI 应用的一次范式跃迁。ChatBot 时代的 AI 是一个"顾问"——你问它答,答案再好也需要你自己去执行。Agent 时代的 AI 是一个"员工"——你交代目标,它自己规划步骤、调用工具、交付结果。从"给你建议"到"替你完成",中间隔着的是与真实世界交互的能力。理解这条分界线,是理解整本书的钥匙。

"ChatBot 回答问题,Agent 解决问题。"

2.2 ChatBot vs Agent:核心区别

我们先通过一个动画来看两者的区别。同样的任务:"帮我查一下明天北京的天气"

注意两者的本质差异不在"回答得好不好",而在闭环是否完整。ChatBot 的闭环止步于"生成文本"——它能告诉你该去查天气,但查的动作要你来做。Agent 的闭环延伸到了"改变外部状态"——它真的调用了天气 API、拿到了数据、甚至可以进一步帮你设提醒。这个"感知→决策→行动→观察"的循环,就是 Agent 区别于一切对话式 AI 的根本特征。

ChatBot

用户:明天北京天气怎么样?

ChatBot:我无法实时查询天气,但你可以...

用户:那帮我订个提醒?

ChatBot:抱歉,我没有这个能力。

→ 只能对话,不能行动

Agent

用户:明天北京天气怎么样?

Agent:[思考] 需要调用天气API

Agent:[工具调用] weather_api("北京", "2026-07-02")

Agent:[观察] 明天北京晴,28°C

→ 明天北京晴,最高28°C。需要我设个提醒吗?

看到了吗?ChatBot 只能"说",Agent 能"做"。这个"做"的能力,来自于 Agent 独有的四个核心模块。

2.3 AI Agent 的四大核心模块

一个完整的 AI Agent 由四个核心模块组成,缺一不可: 🧠 Agent 四模块

1. LLM(大脑) 负责理解、推理、决策。是 Agent 的"智力引擎"。

2. 记忆(Memory) 短期记忆(对话上下文)+ 长期记忆(向量数据库)。

3. 规划(Planning) 将复杂任务拆解为子任务,制定执行计划。

4. 工具(Tools) 调用外部 API、数据库、代码执行器等,实现"行动"。

2.4 Agent 是怎么工作的?

我们来看 Agent 完成一个任务的完整流程。点击"下一步"逐步查看:

1

感知(Perceive)

用户输入"帮我分析一下最近的房价趋势",Agent 通过 LLM 理解用户意图。

← 1 / 5 → 重播

2.5 Agent 的核心闭环

上面的五个步骤可以抽象为一个经典闭环:感知 → 决策 → 行动 → 反馈。这个闭环是所有 Agent 的基础运行模式。

这个闭环并非凭空而来,它源自控制论中的 OODA 循环(Observe-Orient-Decide-Act)。关键在于**"反馈回到感知"这条虚线**——它让 Agent 从"一次性执行"变成"持续修正"。没有这条回边,Agent 就是一个单向流水线,遇到意外就会卡死;有了它,Agent 能在每次行动后观察结果、调整下一步,从而具备容错和自适应能力。这正是 Agent 能处理开放性任务的原因。

这个闭环不断循环,让 Agent 能够处理多步骤、多轮交互的复杂任务。后续章节讲的 ReAct 模式、反思机制,都是在这个闭环基础上的演进。

2.6 Agent vs ChatBot vs Copilot

面试中经常被问到这三者的区别,我们用一张表总结:

三者代表了 AI 应用自主性的三个层级。ChatBot 是被动应答,Copilot 是人机协作(AI 给建议、人来执行),Agent 是自主执行(AI 定计划、AI 去落地)。越往后,AI 的自主性越强、人的参与度越低,但对系统的可靠性和安全性要求也越高。理解这个光谱,能帮你在面试中精准定位产品形态。 | 维度 | ChatBot | Copilot | Agent | | --- | --- | --- | --- | | 核心能力 | 对话回答 | 辅助完成 | 自主完成 | | 自主性 | 无 | 低(需人引导) | 高(自主规划) | | 工具使用 | ✗ | 有限 | ✓ 完整 | | 记忆能力 | 短期 | 短期 | 短期+长期 | | 典型产品 | ChatGPT | GitHub Copilot | Devin, AutoGPT | ## 2.7 从用户输入到输出的完整链路

面试最高频的问题之一:整个 Agent 从用户发出消息到完成任务,中间经历了哪些步骤? 很多面试官会要求你从接收消息开始,一步一步讲清楚每一步做了什么、为什么需要、哪些模块负责。本节把这条链路彻底拆透。

"能画出完整链路图,面试基本稳了。"

🔗 完整 8 步链路

一条完整的 Agent 执行链路,从用户输入到最终输出,包含 8 个核心步骤:

注意:Step 5 → Step 2 的回边表示 Agent 在执行调度后,可能发现需要重新理解意图(比如工具返回了新信息),进入迭代循环。这正是 Agent 与 ChatBot 的核心差异——Agent 不是一条直线,而是可以循环迭代的。 📌 每一步详细说明

Step 1: 用户输入接收 做什么:接收用户的原始消息(文本、图片、语音等),进行预处理(格式化、清洗噪声)。为什么需要:这是 Agent 与外部世界的接口,所有后续步骤都基于此输入。负责模块:输入处理模块 + 消息队列。

Step 2: 意图识别 做什么:理解用户想做什么——是简单问答?是代码修改?还是复杂的多步任务?为什么需要:不同的意图决定不同的执行路径。负责模块:LLM(语义理解)+ 规则引擎(关键词匹配)。

Step 3: 任务分类 做什么:判断任务类型和复杂度等级(简单问答 / 代码解释 / 代码修改 / 复杂开发)。为什么需要:复杂度决定是否需要拆解,类型决定调用哪些工具。负责模块:分类器(LLM 推理或规则引擎)。

Step 4: 任务拆解 做什么:将复杂任务分解为有序的子任务序列,并确定依赖关系和执行顺序。为什么需要:LLM 单次调用无法完成复杂目标,必须拆成可执行的小步骤。负责模块:规划模块(Planning)——详见 2.3 节。

Step 5: 执行调度 做什么:决定先做什么后做什么,何时调用模型推理、何时调用外部工具。为什么需要:资源有限,执行顺序影响效率和结果质量。负责模块:调度器(Scheduler)——详见 2.9 节。

Step 6: 工具调用 做什么:通过 Function Calling / MCP 协议调用外部工具(搜索引擎、数据库、代码执行器、API 等)。为什么需要:LLM 本身无法查天气、执行代码、读写文件,必须借助工具。负责模块:工具模块(Tools)+ Function Calling 接口。

Step 7: 结果整合 做什么:收集各子步骤的输出(模型推理结果 + 工具返回数据),整合为逻辑连贯的完整答案。为什么需要:多步执行的结果是碎片化的,必须缝合才能形成有意义的回复。负责模块:LLM(结果合成)+ 记忆模块(中间结果缓存)。

Step 8: 输出返回 做什么:格式化最终结果(文本、表格、代码块、图表等),返回给用户。同时将本次交互存入记忆。为什么需要:用户体验取决于输出质量;记忆存入为下次交互提供上下文。负责模块:格式化引擎 + 记忆写入模块。

来看一段模拟完整链路执行的代码:

Python TypeScript Go Java

# 模拟 Agent 完整执行链路

class AgentChain:
    def __init__(self):
        self.llm = LLMEngine()       # Step 2/5/7 的核心引擎
        self.memory = MemoryStore()   # 记忆模块
        self.tools = ToolRegistry()   # Step 6 的工具集
        self.classifier = TaskClassifier()  # Step 3 分类器
        self.planner = TaskPlanner()        # Step 4 规划器

    def run(self, user_input):
        # Step 1: 用户输入接收
        raw_msg = InputHandler.receive(user_input)
        print(f"[Step1] 收到原始消息: {raw_msg}")

        # Step 2: 意图识别
        intent = self.llm.identify_intent(raw_msg)
        print(f"[Step2] 意图识别结果: {intent}")  # e.g. "数据分析"

        # Step 3: 任务分类
        task_type, complexity = self.classifier.classify(intent)
        print(f"[Step3] 任务类型={task_type}, 复杂度={complexity}")

        # Step 4: 任务拆解(仅复杂任务)
        if complexity == "complex":
            sub_tasks = self.planner.decompose(raw_msg, intent)
            print(f"[Step4] 拆解为 {len(sub_tasks)} 个子任务")
        else:
            sub_tasks = [raw_msg]  # 简单任务无需拆解
            print(f"[Step4] 简单任务,无需拆解")

        # Step 5: 执行调度
        schedule = self.llm.schedule(sub_tasks, self.tools.available_tools())
        print(f"[Step5] 调度计划: {schedule}")

        results = []
        for task in schedule:
            # Step 6: 工具调用(需要时)
            if task.need_tool:
                tool_result = self.tools.call(task.tool_name, task.tool_args)
                print(f"[Step6] 工具 {task.tool_name} 返回: {tool_result}")
                results.append(tool_result)
            else:
                # 纯模型推理
                model_result = self.llm.reason(task.prompt)
                print(f"[Step5→推理] 模型推理结果: {model_result}")
                results.append(model_result)

        # Step 7: 结果整合
        final_answer = self.llm.synthesize(results, original_intent=intent)
        print(f"[Step7] 整合完成: {final_answer}")

        # Step 8: 输出返回
        formatted = OutputFormatter.format(final_answer)
        self.memory.save_interaction(raw_msg, intent, formatted)
        print(f"[Step8] 输出返回给用户")
        return formatted

# 执行示例
agent = AgentChain()
result = agent.run("帮我分析最近北京房价趋势")
# [Step1] 收到原始消息: 帮我分析最近北京房价趋势
# [Step2] 意图识别结果: 数据分析
# [Step3] 任务类型=complex, 复杂度=complex
# [Step4] 拆解为 3 个子任务
# [Step5] 调度计划: [search_housing_data → analyze_trend → generate_report]
# [Step6] 工具 search_api 返回: {...房价数据...}
# [Step5→推理] 模型推理结果: 一线城市环比下降2%
# [Step7] 整合完成: 北京房价分析报告
# [Step8] 输出返回给用户
// 模拟 Agent 完整执行链路

class AgentChain {
  private llm = new LLMEngine();       // Step 2/5/7 的核心引擎
  private memory = new MemoryStore();   // 记忆模块
  private tools = new ToolRegistry();   // Step 6 的工具集
  private classifier = new TaskClassifier();  // Step 3 分类器
  private planner = new TaskPlanner();        // Step 4 规划器

  run(userInput: string): string {
    // Step 1: 用户输入接收
    const rawMsg = InputHandler.receive(userInput);
    console.log(`[Step1] 收到原始消息: ${rawMsg}`);

    // Step 2: 意图识别
    const intent = this.llm.identifyIntent(rawMsg);
    console.log(`[Step2] 意图识别结果: ${intent}`);

    // Step 3: 任务分类
    const { taskType, complexity } = this.classifier.classify(intent);
    console.log(`[Step3] 任务类型=${taskType}, 复杂度=${complexity}`);

    // Step 4: 任务拆解(仅复杂任务)
    let subTasks: string[];
    if (complexity === 'complex') {
      subTasks = this.planner.decompose(rawMsg, intent);
      console.log(`[Step4] 拆解为 ${subTasks.length} 个子任务`);
    } else {
      subTasks = [rawMsg];
      console.log('[Step4] 简单任务,无需拆解');
    }

    // Step 5: 执行调度
    const schedule = this.llm.schedule(subTasks, this.tools.availableTools());
    console.log(`[Step5] 调度计划: ${schedule}`);

    const results: any[] = [];
    for (const task of schedule) {
      // Step 6: 工具调用(需要时)
      if (task.needTool) {
        const toolResult = this.tools.call(task.toolName, task.toolArgs);
        console.log(`[Step6] 工具 ${task.toolName} 返回: ${toolResult}`);
        results.push(toolResult);
      } else {
        // 纯模型推理
        const modelResult = this.llm.reason(task.prompt);
        console.log(`[Step5→推理] 模型推理结果: ${modelResult}`);
        results.push(modelResult);
      }
    }

    // Step 7: 结果整合
    const finalAnswer = this.llm.synthesize(results, intent);
    console.log(`[Step7] 整合完成: ${finalAnswer}`);

    // Step 8: 输出返回
    const formatted = OutputFormatter.format(finalAnswer);
    this.memory.saveInteraction(rawMsg, intent, formatted);
    console.log('[Step8] 输出返回给用户');
    return formatted;
  }
}

// 执行示例
const agent = new AgentChain();
const result = agent.run('帮我分析最近北京房价趋势');
// 模拟 Agent 完整执行链路

package main

import "fmt"

// AgentChain Agent 执行链路
type AgentChain struct {
	llm        *LLMEngine
	memory     *MemoryStore
	tools      *ToolRegistry
	classifier *TaskClassifier
	planner    *TaskPlanner
}

func NewAgentChain() *AgentChain {
	return &AgentChain{
		llm:        NewLLMEngine(),
		memory:     NewMemoryStore(),
		tools:      NewToolRegistry(),
		classifier: NewTaskClassifier(),
		planner:    NewTaskPlanner(),
	}
}

func (a *AgentChain) Run(userInput string) string {
	// Step 1: 用户输入接收
	rawMsg := InputHandlerReceive(userInput)
	fmt.Printf("[Step1] 收到原始消息: %s\n", rawMsg)

	// Step 2: 意图识别
	intent := a.llm.IdentifyIntent(rawMsg)
	fmt.Printf("[Step2] 意图识别结果: %v\n", intent)

	// Step 3: 任务分类
	taskType, complexity := a.classifier.Classify(intent)
	fmt.Printf("[Step3] 任务类型=%s, 复杂度=%s\n", taskType, complexity)

	// Step 4: 任务拆解
	var subTasks []string
	if complexity == "complex" {
		subTasks = a.planner.Decompose(rawMsg, intent)
		fmt.Printf("[Step4] 拆解为 %d 个子任务\n", len(subTasks))
	} else {
		subTasks = []string{rawMsg}
		fmt.Println("[Step4] 简单任务,无需拆解")
	}

	// Step 5: 执行调度
	schedule := a.llm.Schedule(subTasks, a.tools.AvailableTools())
	fmt.Printf("[Step5] 调度计划: %v\n", schedule)

	var results []interface{}
	for _, task := range schedule {
		// Step 6: 工具调用
		if task.NeedTool {
			toolResult := a.tools.Call(task.ToolName, task.ToolArgs)
			fmt.Printf("[Step6] 工具 %s 返回: %v\n", task.ToolName, toolResult)
			results = append(results, toolResult)
		} else {
			modelResult := a.llm.Reason(task.Prompt)
			fmt.Printf("[Step5→推理] 模型推理结果: %v\n", modelResult)
			results = append(results, modelResult)
		}
	}

	// Step 7: 结果整合
	finalAnswer := a.llm.Synthesize(results, intent)
	fmt.Printf("[Step7] 整合完成: %s\n", finalAnswer)

	// Step 8: 输出返回
	formatted := OutputFormatterFormat(finalAnswer)
	a.memory.SaveInteraction(rawMsg, intent, formatted)
	fmt.Println("[Step8] 输出返回给用户")
	return formatted
}

func main() {
	agent := NewAgentChain()
	result := agent.Run("帮我分析最近北京房价趋势")
	fmt.Println(result)
}
// 模拟 Agent 完整执行链路

public class AgentChain {
    private LLMEngine llm = new LLMEngine();           // Step 2/5/7 的核心引擎
    private MemoryStore memory = new MemoryStore();     // 记忆模块
    private ToolRegistry tools = new ToolRegistry();    // Step 6 的工具集
    private TaskClassifier classifier = new TaskClassifier(); // Step 3 分类器
    private TaskPlanner planner = new TaskPlanner();         // Step 4 规划器

    public String run(String userInput) {
        // Step 1: 用户输入接收
        String rawMsg = InputHandler.receive(userInput);
        System.out.println("[Step1] 收到原始消息: " + rawMsg);

        // Step 2: 意图识别
        Intent intent = llm.identifyIntent(rawMsg);
        System.out.println("[Step2] 意图识别结果: " + intent);

        // Step 3: 任务分类
        ClassifyResult result = classifier.classify(intent);
        System.out.printf("[Step3] 任务类型=%s, 复杂度=%s%n", result.taskType, result.complexity);

        // Step 4: 任务拆解
        List subTasks;
        if ("complex".equals(result.complexity)) {
            subTasks = planner.decompose(rawMsg, intent);
            System.out.printf("[Step4] 拆解为 %d 个子任务%n", subTasks.size());
        } else {
            subTasks = List.of(rawMsg);
            System.out.println("[Step4] 简单任务,无需拆解");
        }

        // Step 5: 执行调度
        List schedule = llm.schedule(subTasks, tools.availableTools());
        System.out.println("[Step5] 调度计划: " + schedule);

        List results = new ArrayList<>();
        for (Task task : schedule) {
            // Step 6: 工具调用
            if (task.needTool) {
                Object toolResult = tools.call(task.toolName, task.toolArgs);
                System.out.printf("[Step6] 工具 %s 返回: %s%n", task.toolName, toolResult);
                results.add(toolResult);
            } else {
                // 纯模型推理
                Object modelResult = llm.reason(task.prompt);
                System.out.printf("[Step5→推理] 模型推理结果: %s%n", modelResult);
                results.add(modelResult);
            }
        }

        // Step 7: 结果整合
        String finalAnswer = llm.synthesize(results, intent);
        System.out.println("[Step7] 整合完成: " + finalAnswer);

        // Step 8: 输出返回
        String formatted = OutputFormatter.format(finalAnswer);
        memory.saveInteraction(rawMsg, intent, formatted);
        System.out.println("[Step8] 输出返回给用户");
        return formatted;
    }

    public static void main(String[] args) {
        AgentChain agent = new AgentChain();
        String result = agent.run("帮我分析最近北京房价趋势");
    }
}

代码中每一步都打印了日志,你可以清楚地看到一条消息从进入 Agent 到变成最终输出,走过了哪些节点。面试时,能讲出这 8 步并解释每步的作用,就是满分回答。

2.8 意图识别与任务分类

Step 2(意图识别)和 Step 3(任务分类)是整条链路的分叉点——Agent 能否走上正确的执行路径,取决于这两步做得好不好。面试中经常追问:Agent 怎么理解用户意图?怎么判断任务复杂度?

🎯 三种意图识别方法

意图识别的三种方法对比 | 方法 | 原理 | 优点 | 缺点 | 适用场景 | | --- | --- | --- | --- | --- | | 关键词匹配 | 匹配预设关键词,如"天气"→查询意图 | 速度快,成本低 | 粗粒度,误判率高 | 简单指令型交互 | | 语义理解 | 通过 LLM 深层理解用户表达的真实意图 | 精准,能理解隐含意图 | 成本高,延迟大 | 复杂多意图场景 | | 模式识别 | 基于历史对话模式匹配相似意图 | 利用经验,越用越准 | 依赖数据量,新意图难识别 | 高频重复场景 | 实际工程中,三者通常组合使用:先用关键词匹配快速筛选常见意图,命中后直接走快速路径;没命中则交给 LLM 做语义理解;长期积累的模式数据用于优化匹配规则。这就是分层意图识别策略。

Python TypeScript Go Java

# 分层意图识别:关键词 → 语义 → 模式

def identify_intent(user_input, context):
    # 第一层:关键词匹配(快路径)
    keyword_intent = match_keywords(user_input)
    if keyword_intent and keyword_intent.confidence > 0.9:
        return keyword_intent  # 高置信度,直接返回

    # 第二层:语义理解(慢路径)
    semantic_intent = llm_understand_intent(user_input, context)
    if semantic_intent.confidence > 0.7:
        # 记录新模式,丰富规则库
        pattern_db.record(user_input, semantic_intent)
        return semantic_intent

    # 第三层:模式识别(兜底)
    pattern_intent = match_patterns(user_input, pattern_db)
    return pattern_intent or semantic_intent

# 示例
print(identify_intent("明天天气咋样", []))
# → Intent(type="查询", sub_type="天气", confidence=0.95)  # 关键词命中

print(identify_intent("我项目里这段代码跑不通,帮我看看", []))
# → Intent(type="代码修改", confidence=0.85)  # 语义理解命中
// 分层意图识别:关键词 → 语义 → 模式

function identifyIntent(userInput: string, context: Context[]): Intent {
  // 第一层:关键词匹配(快路径)
  const keywordIntent = matchKeywords(userInput);
  if (keywordIntent && keywordIntent.confidence > 0.9) {
    return keywordIntent;  // 高置信度,直接返回
  }

  // 第二层:语义理解(慢路径)
  const semanticIntent = llmUnderstandIntent(userInput, context);
  if (semanticIntent.confidence > 0.7) {
    // 记录新模式,丰富规则库
    patternDB.record(userInput, semanticIntent);
    return semanticIntent;
  }

  // 第三层:模式识别(兜底)
  const patternIntent = matchPatterns(userInput, patternDB);
  return patternIntent || semanticIntent;
}

// 示例
console.log(identifyIntent('明天天气咋样', []));
// → Intent(type="查询", subType="天气", confidence=0.95)  // 关键词命中

console.log(identifyIntent('我项目里这段代码跑不通,帮我看看', []));
// → Intent(type="代码修改", confidence=0.85)  // 语义理解命中
// 分层意图识别:关键词 → 语义 → 模式

package main

// Intent 意图
type Intent struct {
	Type       string
	SubType   string
	Confidence float64
}

func identifyIntent(userInput string, context []Context) Intent {
	// 第一层:关键词匹配(快路径)
	keywordIntent := matchKeywords(userInput)
	if keywordIntent.Confidence > 0.9 {
		return keywordIntent // 高置信度,直接返回
	}

	// 第二层:语义理解(慢路径)
	semanticIntent := llmUnderstandIntent(userInput, context)
	if semanticIntent.Confidence > 0.7 {
		// 记录新模式,丰富规则库
		patternDB.Record(userInput, semanticIntent)
		return semanticIntent
	}

	// 第三层:模式识别(兜底)
	patternIntent := matchPatterns(userInput, patternDB)
	if patternIntent.Confidence > 0 {
		return patternIntent
	}
	return semanticIntent
}
// 分层意图识别:关键词 → 语义 → 模式

public class IntentIdentifier {

    public Intent identifyIntent(String userInput, List context) {
        // 第一层:关键词匹配(快路径)
        Intent keywordIntent = matchKeywords(userInput);
        if (keywordIntent != null && keywordIntent.getConfidence() > 0.9) {
            return keywordIntent;  // 高置信度,直接返回
        }

        // 第二层:语义理解(慢路径)
        Intent semanticIntent = llmUnderstandIntent(userInput, context);
        if (semanticIntent.getConfidence() > 0.7) {
            // 记录新模式,丰富规则库
            patternDB.record(userInput, semanticIntent);
            return semanticIntent;
        }

        // 第三层:模式识别(兜底)
        Intent patternIntent = matchPatterns(userInput, patternDB);
        return patternIntent != null ? patternIntent : semanticIntent;
    }
}

📊 任务分类矩阵

意图识别之后,Agent 需要对任务进行分类,决定执行策略。不同的任务类型对应不同的处理路径:

任务分类矩阵:类型 → 策略 → 路径 | 任务类型 | 典型输入 | 执行策略 | 链路路径 | 复杂度 | | --- | --- | --- | --- | --- | | 简单问答 | "Python 的 list 怎么排序?" | 直接回答 | Step 1→2→3→5→7→8 | 低 | | 代码解释 | "这段代码在做什么?" | 分析 + 输出说明 | Step 1→2→3→5→7→8 | 中 | | 代码修改 | "把这段代码改成异步版本" | 理解+定位+修改 | Step 1→2→3→4→5→6→7→8 | 中高 | | 复杂开发 | "帮我搭建一个 REST API 项目" | Step 1→2→3→4→5→6→7→8(多轮循环) | 高 | 关键观察:简单问答可以跳过 Step 4(任务拆解)和 Step 6(工具调用),直接走快速路径。而复杂开发任务必须走完全部 8 步,且 Step 5→2 的迭代循环可能执行多轮。

🔀 分类决策流程图

Python TypeScript Go Java

# 任务分类器:判断复杂度并选择执行路径

class TaskClassifier:
    # 关键词 → 复杂度的映射规则
    COMPLEXITY_RULES = {
        "简单问答": {
            "keywords": ["是什么", "怎么用", "区别", "概念"],
            "path": "direct_answer",
            "complexity": "low"
        },
        "代码解释": {
            "keywords": ["这段代码", "什么意思", "解释一下"],
            "path": "analyze_explain",
            "complexity": "medium"
        },
        "代码修改": {
            "keywords": ["修改", "改成", "优化", "修复", "重构"],
            "path": "locate_modify",
            "complexity": "medium_high"
        },
        "复杂开发": {
            "keywords": ["搭建", "实现", "开发", "创建项目", "从零开始"],
            "path": "decompose_execute",
            "complexity": "high"
        }
    }

    def classify(self, intent):
        # 规则匹配 + LLM 兜底
        for task_type, rule in self.COMPLEXITY_RULES.items():
            if any(kw in intent.raw_input for kw in rule["keywords"]):
                return task_type, rule["complexity"], rule["path"]

        # 规则未命中,交给 LLM 判断
        llm_result = self.llm_classify(intent)
        return llm_result.type, llm_result.complexity, llm_result.path

# 示例
classifier = TaskClassifier()
print(classifier.classify(Intent(raw_input="Python list 怎么排序?")))
# → ("简单问答", "low", "direct_answer")

print(classifier.classify(Intent(raw_input="帮我搭建一个 REST API")))
# → ("复杂开发", "high", "decompose_execute")
// 任务分类器:判断复杂度并选择执行路径

const COMPLEXITY_RULES: Record = {
  '简单问答': {
    keywords: ['是什么', '怎么用', '区别', '概念'],
    path: 'direct_answer',
    complexity: 'low'
  },
  '代码解释': {
    keywords: ['这段代码', '什么意思', '解释一下'],
    path: 'analyze_explain',
    complexity: 'medium'
  },
  '代码修改': {
    keywords: ['修改', '改成', '优化', '修复', '重构'],
    path: 'locate_modify',
    complexity: 'medium_high'
  },
  '复杂开发': {
    keywords: ['搭建', '实现', '开发', '创建项目', '从零开始'],
    path: 'decompose_execute',
    complexity: 'high'
  }
};

function classify(intent: Intent): ClassifyResult {
  // 规则匹配
  for (const [taskType, rule] of Object.entries(COMPLEXITY_RULES)) {
    if (rule.keywords.some(kw => intent.rawInput.includes(kw))) {
      return { taskType, complexity: rule.complexity, path: rule.path };
    }
  }
  // 规则未命中,交给 LLM 判断
  return llmClassify(intent);
}

// 示例
console.log(classify({ rawInput: 'Python list 怎么排序?' }));
// → { taskType: '简单问答', complexity: 'low', path: 'direct_answer' }

console.log(classify({ rawInput: '帮我搭建一个 REST API' }));
// → { taskType: '复杂开发', complexity: 'high', path: 'decompose_execute' }
// 任务分类器:判断复杂度并选择执行路径

package main

// ComplexityRule 复杂度规则
type ComplexityRule struct {
	Keywords   []string
	Path       string
	Complexity string
}

// TaskClassifier 任务分类器
type TaskClassifier struct {
	rules map[string]ComplexityRule
}

func NewTaskClassifier() *TaskClassifier {
	return &TaskClassifier{
		rules: map[string]ComplexityRule{
			"简单问答": {Keywords: []string{"是什么", "怎么用", "区别", "��念"}, Path: "direct_answer", Complexity: "low"},
			"代码解释": {Keywords: []string{"这段代码", "什么意思", "解释一下"}, Path: "analyze_explain", Complexity: "medium"},
			"代码修改": {Keywords: []string{"修改", "改成", "优化", "修复", "重构"}, Path: "locate_modify", Complexity: "medium_high"},
			"复杂开发": {Keywords: []string{"搭建", "实现", "开发", "创建项目", "从零开始"}, Path: "decompose_execute", Complexity: "high"},
		},
	}
}

func (c *TaskClassifier) Classify(intent Intent) (taskType, complexity, path string) {
	// 规则匹配
	for name, rule := range c.rules {
		for _, kw := range rule.Keywords {
			if strings.Contains(intent.RawInput, kw) {
				return name, rule.Complexity, rule.Path
			}
		}
	}
	// 规则未命中,交给 LLM 判断
	return llmClassify(intent)
}
// 任务分类器:判断复杂度并选择执行路径

import java.util.*;

public class TaskClassifier {

    private static final Map COMPLEXITY_RULES = new HashMap<>();

    static {
        COMPLEXITY_RULES.put("简单问答", new ComplexityRule(
            Arrays.asList("是什么", "怎么用", "区别", "概念"), "direct_answer", "low"));
        COMPLEXITY_RULES.put("代码解释", new ComplexityRule(
            Arrays.asList("这段代码", "什么意思", "解释一下"), "analyze_explain", "medium"));
        COMPLEXITY_RULES.put("代码修改", new ComplexityRule(
            Arrays.asList("修改", "改成", "优化", "修复", "重构"), "locate_modify", "medium_high"));
        COMPLEXITY_RULES.put("复杂开发", new ComplexityRule(
            Arrays.asList("搭建", "实现", "开发", "创建项目", "从零开始"), "decompose_execute", "high"));
    }

    public ClassifyResult classify(Intent intent) {
        // 规则匹配
        for (Map.Entry entry : COMPLEXITY_RULES.entrySet()) {
            String taskType = entry.getKey();
            ComplexityRule rule = entry.getValue();
            for (String kw : rule.keywords) {
                if (intent.getRawInput().contains(kw)) {
                    return new ClassifyResult(taskType, rule.complexity, rule.path);
                }
            }
        }
        // 规则未命中,交给 LLM 判断
        return llmClassify(intent);
    }

    static class ComplexityRule {
        List keywords;
        String path;
        String complexity;
        ComplexityRule(List keywords, String path, String complexity) {
            this.keywords = keywords;
            this.path = path;
            this.complexity = complexity;
        }
    }
}

2.9 执行调度决策

Agent 拿到子任务列表后,下一步是执行调度——决定先做什么后做什么,什么时候该调用模型(推理/理解/生成文本),什么时候该调用工具(搜索/计算/文件操作)。这是 1.7 链路中 Step 5 的核心逻辑。

"调度器的质量,决定了 Agent 是'聪明地做事'还是'笨拙地乱撞'。"

🌳 调度决策树

调度决策的核心逻辑可以用一棵决策树描述: ⚡ 模型 vs 工具:何时调用谁?

调用模型(LLM)

  • 理解用户意图和上下文
  • 逻辑推理和因果分析
  • 生成文本、代码、创意内容
  • 结果整合与格式化
  • 判断下一步做什么

调用工具(Tools)

  • 搜索实时信息(天气、新闻)
  • 执行代码(运行、测试)
  • 读写文件(磁盘操作)
  • 调用外部 API(支付、数据库)
  • 数学计算(高精度运算)

一个关键原则:模型擅长"思考",工具擅长"行动"。调度器的核心职责就是判断当前子任务属于哪一类,把任务分给最合适的执行者。

Python TypeScript Go Java

# 调度器实现:根据任务特征分配执行路径

class Scheduler:
    def __init__(self, llm, tools):
        self.llm = llm
        self.tools = tools

    def dispatch(self, sub_task):
        """根据子任务特征,决定调用模型还是工具"""

        # 判断1:是否需要外部数据?
        if sub_task.requires_external_data:
            # 搜索、数据库查询、API调用 → 工具
            tool_name = self._select_tool(sub_task)
            result = self.tools.call(tool_name, sub_task.params)
            print(f"[调度] 工具执行: {tool_name} → {result}")
            return result

        # 判断2:是否需要逻辑推理?
        if sub_task.requires_reasoning:
            # 分析、推理、决策 → 模型
            result = self.llm.reason(sub_task.prompt)
            print(f"[调度] 模型推理: {sub_task.prompt} → {result}")
            return result

        # 判断3:是否需要格式化输出?
        if sub_task.requires_formatting:
            result = self.llm.format(sub_task.raw_output)
            print(f"[调度] 模型格式化 → {result}")
            return result

        # 判断4:是否需要验证结果?
        if sub_task.requires_verification:
            # 交叉验证:先工具获取事实,再模型判断一致性
            tool_result = self.tools.call("verify", sub_task.params)
            model_result = self.llm.reason(
                f"验证以下结果是否合理: {tool_result}"
            )
            print(f"[调度] 交叉验证 → 工具:{tool_result}, 模型:{model_result}")
            return model_result

        # 默认:模型处理
        return self.llm.reason(sub_task.prompt)

    def _select_tool(self, sub_task):
        """根据任务类型选择最合适的工具"""
        tool_map = {
            "search": "search_api",
            "database": "db_query",
            "code_execution": "code_runner",
            "file_operation": "file_handler",
            "calculation": "calculator"
        }
        return tool_map.get(sub_task.tool_type, "general_tool")

# 执行示例
scheduler = Scheduler(LLMEngine(), ToolRegistry())

# 搜索类任务 → 调用工具
scheduler.dispatch(SubTask(type="search", requires_external_data=True))
# [调度] 工具执行: search_api → {"北京房价": ...}

# 推理类任务 → 调用模型
scheduler.dispatch(SubTask(type="analyze", requires_reasoning=True))
# [调度] 模型推理: 分析房价趋势 → 一线城市环比下降2%

# 验证类任务 → 工具+模型
scheduler.dispatch(SubTask(type="verify", requires_verification=True))
# [调度] 交叉验证 → 工具:数据查询结果, 模型:验证通过
// 调度器实现:根据任务特征分配执行路径

class Scheduler {
  constructor(private llm: LLMEngine, private tools: ToolRegistry) {}

  dispatch(subTask: SubTask): any {
    // 判断1:是否需要外部数据?
    if (subTask.requiresExternalData) {
      const toolName = this.selectTool(subTask);
      const result = this.tools.call(toolName, subTask.params);
      console.log(`[调度] 工具执行: ${toolName} → ${result}`);
      return result;
    }

    // 判断2:是否需要逻辑推理?
    if (subTask.requiresReasoning) {
      const result = this.llm.reason(subTask.prompt);
      console.log(`[调度] 模型推理: ${subTask.prompt} → ${result}`);
      return result;
    }

    // 判断3:是否需要格式化输出?
    if (subTask.requiresFormatting) {
      const result = this.llm.format(subTask.rawOutput);
      console.log(`[调度] 模型格式化 → ${result}`);
      return result;
    }

    // 判断4:是否需要验证结果?
    if (subTask.requiresVerification) {
      const toolResult = this.tools.call('verify', subTask.params);
      const modelResult = this.llm.reason(`验证以下结果是否合理: ${toolResult}`);
      console.log(`[调度] 交叉验证 → 工具:${toolResult}, 模型:${modelResult}`);
      return modelResult;
    }

    // 默认:模型处理
    return this.llm.reason(subTask.prompt);
  }

  private selectTool(subTask: SubTask): string {
    const toolMap: Record = {
      search: 'search_api',
      database: 'db_query',
      code_execution: 'code_runner',
      file_operation: 'file_handler',
      calculation: 'calculator'
    };
    return toolMap[subTask.toolType] || 'general_tool';
  }
}
// 调度器实现:根据任务特征分配执行路径

package main

// Scheduler 调度器
type Scheduler struct {
	llm   *LLMEngine
	tools *ToolRegistry
}

func (s *Scheduler) Dispatch(subTask *SubTask) interface{} {
	// 判断1:是否需要外部数据?
	if subTask.RequiresExternalData {
		toolName := s.selectTool(subTask)
		result := s.tools.Call(toolName, subTask.Params)
		fmt.Printf("[调度] 工具执行: %s → %v\n", toolName, result)
		return result
	}

	// 判断2:是否需要逻辑推理?
	if subTask.RequiresReasoning {
		result := s.llm.Reason(subTask.Prompt)
		fmt.Printf("[调度] 模型推理: %s → %v\n", subTask.Prompt, result)
		return result
	}

	// 判断3:是否需要格式化输出?
	if subTask.RequiresFormatting {
		result := s.llm.Format(subTask.RawOutput)
		fmt.Printf("[调度] 模型格式化 → %v\n", result)
		return result
	}

	// 判断4:是否需要验证结果?
	if subTask.RequiresVerification {
		toolResult := s.tools.Call("verify", subTask.Params)
		modelResult := s.llm.Reason(fmt.Sprintf("验证以下结果是否合理: %v", toolResult))
		fmt.Printf("[调度] 交叉验证 → 工具:%v, 模型:%v\n", toolResult, modelResult)
		return modelResult
	}

	// 默认:模型处理
	return s.llm.Reason(subTask.Prompt)
}

func (s *Scheduler) selectTool(subTask *SubTask) string {
	toolMap := map[string]string{
		"search":          "search_api",
		"database":        "db_query",
		"code_execution":  "code_runner",
		"file_operation":  "file_handler",
		"calculation":     "calculator",
	}
	if name, ok := toolMap[subTask.ToolType]; ok {
		return name
	}
	return "general_tool"
}
// 调度器实现:根据任务特征分配执行路径

public class Scheduler {
    private final LLMEngine llm;
    private final ToolRegistry tools;

    public Scheduler(LLMEngine llm, ToolRegistry tools) {
        this.llm = llm;
        this.tools = tools;
    }

    public Object dispatch(SubTask subTask) {
        // 判断1:是否需要外部数据?
        if (subTask.requiresExternalData) {
            String toolName = selectTool(subTask);
            Object result = tools.call(toolName, subTask.params);
            System.out.printf("[调度] 工具执行: %s → %s%n", toolName, result);
            return result;
        }

        // 判断2:是否需要逻辑推理?
        if (subTask.requiresReasoning) {
            Object result = llm.reason(subTask.prompt);
            System.out.printf("[调度] 模型推理: %s → %s%n", subTask.prompt, result);
            return result;
        }

        // 判断3:是否需要格式化输出?
        if (subTask.requiresFormatting) {
            Object result = llm.format(subTask.rawOutput);
            System.out.printf("[调度] 模型格式化 → %s%n", result);
            return result;
        }

        // 判断4:是否需要验证结果?
        if (subTask.requiresVerification) {
            Object toolResult = tools.call("verify", subTask.params);
            Object modelResult = llm.reason("验证以下结果是否合理: " + toolResult);
            System.out.printf("[调度] 交叉验证 → 工具:%s, 模型:%s%n", toolResult, modelResult);
            return modelResult;
        }

        // 默认:模型处理
        return llm.reason(subTask.prompt);
    }

    private String selectTool(SubTask subTask) {
        return switch (subTask.toolType) {
            case "search" -> "search_api";
            case "database" -> "db_query";
            case "code_execution" -> "code_runner";
            case "file_operation" -> "file_handler";
            case "calculation" -> "calculator";
            default -> "general_tool";
        };
    }
}

调度器的核心价值在于避免无谓的调用:如果用户只是问"Python 怎么排序",不需要调用搜索工具,模型直接回答即可;如果用户问"北京明天天气",模型无法知道实时数据,必须调用工具。调度器就是在做这个判断。 📋 八股总结 — 面试高频考点

Q1: 什么是 AI Agent?它和 ChatBot 的本质区别是什么?

AI Agent 是一种能够感知环境、自主规划、使用工具、采取行动来完成目标的 AI 系统。

本质区别在于:自主性。ChatBot 只能被动回答���题(输入→输出),Agent 能主动拆解任务、调用工具、多步执行(感知→规划→行动→反馈)。ChatBot 是"嘴",Agent 是"手+脑"。

Q2: AI Agent 的四大核心模块是什么?分别有什么作用?

① LLM(大脑):理解意图、推理决策、生成回答

② 记忆(Memory):短期记忆保存对话上下文,长期记忆通过向量库存储经验

③ 规划(Planning):将复杂目标拆解为可执行的子任务序列

④ 工具(Tools):调用外部 API、代码执行器、数据库等,实现"行动"能力

四者协同构成 Agent 的完整能力闭环。缺了 LLM 没有智力,缺了记忆没有连贯性,缺了规划只能做简单任务,缺了工具无法与外部世界交互。

Q3: Agent 的"感知-决策-行动-反馈"闭环是什么意思?

这是 Agent 运行的基本范式:

感知:接收用户输入或环境变化

决策:LLM 推理分析,决定下一步做什么

行动:调用工具执行具体操作

反馈:观察行动结果,更新状态,决定是否继续循环

这个闭环可以多轮循环,使 Agent 能处理需要多个步骤才能完成的复杂任务。ReAct 模式(第5章)就是这个闭环的经典实现。

Q4: Agent、ChatBot、Copilot 三者的区别?面试怎么答?

ChatBot:被动对话,只能回答,不能行动。如 ChatGPT。

Copilot:辅助人类完成工作,人在主导,AI 是工具。如 GitHub Copilot。

Agent:自主完成目标,AI 主导,人可监督。能独立规划、决策、执行。

关键区别在于自主性程度:ChatBot 无自主性,Copilot 低自主性(人主导),Agent 高自主性(AI 主导)。

Q5: 为什么说 2025-2026 年是 Agent 元年?技术条件发生了什么变化?

几个关键条件同时成熟:

① LLM 能力跃升:GPT-4o、Claude 3.5、Gemini 2.0 推理能力大幅提升,足以支撑复杂规划

② Function Calling 标准化:OpenAI 等原生支持工具调用,不再需要 hack

③ MCP 协议:工具调用标准化,跨框架复用成为可能

④ 框架成熟:LangGraph、CrewAI、Google ADK、Spring AI 等生产级框架涌现

⑤ 成本下降:模型调用成本大幅降低,多轮 Agent 调用经济可行

Q6: 从用户输入到 Agent 输出,完整链路包含哪些步骤?每步的作用是什么?

完整 8 步链路:

① 用户输入接收:接收原始消息,预处理清洗

② 意图识别:理解用户想做什么(问答/修改/开发),决定执行路径

③ 任务分类:判断任务类型和复杂度,决定是否需要拆解

④ 任务拆解:将复杂任务分解为子任务序列(仅复杂任务需要)

⑤ 执行调度:决定何时调用模型、何时调用工具,安排执行顺序

⑥ 工具调用:通过 Function Calling/MCP 调用外部工具获取数据或执行操作

⑦ 结果整合:收集各步骤输出,缝合为完整答案

⑧ 输出返回:格式化结果返回用户,同时存入记忆

关键:Step 5→2 的回边表示迭代循环,Agent 不是单程直线,而是可以循环调整的。

Q7: Agent 如何判断一个任务是简单问答还是需要多步执行?判断依据是什么?

通过意图识别 + 任务分类两步判断:

意图识别有三种方法:关键词匹配(快但粗糙)、语义理解(精准但成本高)、模式识别(利用历史经验)。实际工程中三者组合使用,形成分层识别策略。

任务分类依据四个维度:

① 是否需要外部数据?(需要 → 至少涉及工具调用)

② 是否需要多步操作?(需要 → 必须任务拆解)

③ 输入的复杂度?(单句问答 → 简单,长文+多要求 → 复杂)

④ 是否有依赖关系?(步骤间有先后依赖 → 复杂调度)

简单问答:跳过拆解和工具调用,直接回答。复杂任务:走完 8 步链路,可能多轮迭代。

Q8: Agent 的调度器如何决定"调用模型"还是"调用工具"?

调度决策的核心原则:模型擅长思考,工具擅长行动

决策树的四个判断节点:

① 需要外部数据?→ 调用工具(搜索/数据库/API)

② 需要逻辑推理?→ 调用模型(理解/分析/生成)

③ 需要格式化输出?→ 调用模型(润色/排版)

④ 需要验证结果?→ 工具+模型交叉验证(工具获取事实,模型判断一致性)

实际工程中,调度器还考虑成本和延迟:简单意图先用关键词快速路由(低成本),复杂意图才走完整 LLM 推理链路(高成本但精准)。

第2章 什么是AI-Agent
http://www.clxhxhhr.top/posts/705/
作者
clxstart
发布于
2026-09-18
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。