跳到正文

Agent任务规划+工具调用原理

任务规划、工具调用与结果反思的实现要点

原题:请设计并实现一个基于大语言模型的简单Agent系统,要求具备任务规划、工具调用和结果反思的能力

Prompt工程 · 腾讯真题

30 秒回答

  1. ReAct思维链设计(Thought-Action-Observation循环)
  2. 工具注册与动态调用机制
  3. 反思模块的实现(检查工具结果、自我修正)
  4. 状态管理与上下文维护

回答与解析

答案要点

  • ReAct思维链设计(Thought-Action-Observation循环)
  • 工具注册与动态调用机制
  • 反思模块的实现(检查工具结果、自我修正)
  • 状态管理与上下文维护
  • 错误处理与重试策略

核心架构:ReAct 循环

Agent = LLM + 工具 + 记忆 + 控制循环,采用 Thought → Action → Observation → ... → Finish 的推理模式。


关键模块实现

1. 工具注册与调用

class ToolRegistry:
    def __init__(self):
        self.tools = {}
    
    def register(self, name, func, description, params):
        self.tools[name] = {
            "func": func, "desc": description, 
            "params": params  # JSON Schema
        }
    
    def get_tool_prompt(self):
        # 生成工具描述给LLM
        return "\n".join([
            f"{name}: {t['desc']}, 参数: {t['params']}"
            for name, t in self.tools.items()
        ])
    
    def execute(self, name, args):
        return self.tools[name]["func"](**args)

2. ReAct 核心循环

class ReActAgent:
    def __init__(self, llm, tools: ToolRegistry, max_steps=10):
        self.llm = llm
        self.tools = tools
        self.max_steps = max_steps
        self.memory = []  # 历史记录
    
    def run(self, task: str) -> str:
        self.memory.append(f"任务: {task}")
        
        for step in range(self.max_steps):
            # 构造Prompt:任务 + 工具说明 + 历史 + 输出格式要求
            prompt = self._build_prompt()
            
            # LLM输出结构化思考
            response = self.llm.generate(prompt, stop=["Observation:"])
            thought, action, action_input = self._parse(response)
            
            self.memory.append(f"Thought: {thought}")
            
            # 反思检查:是否需要调用工具
            if action == "Finish":
                return action_input  # 最终答案
            
            # 执行工具
            try:
                obs = self.tools.execute(action, json.loads(action_input))
                self.memory.append(f"Action: {action}[{action_input}]")
                self.memory.append(f"Observation: {obs}")
            except Exception as e:
                # 错误反馈给LLM自我修正
                self.memory.append(f"Observation: 错误: {str(e)}")
        
        return "达到最大步数,未完成"

3. 反思模块(关键)

def reflect(self, step_result: dict) -> bool:
    """检查是否需要回溯或修正"""
    reflection_prompt = f"""
    上一步结果: {step_result}
    请判断: 1) 结果是否满足预期 2) 是否需要调整策略
    输出: Continue / Retry / Backtrack / Finish
    """
    decision = self.llm.generate(reflection_prompt)
    return self._handle_decision(decision)

设计要点

模块 核心机制
规划 LLM自主分解任务,每步生成Thought
工具调用 结构化输出(JSON/特定格式)+ 动态路由
反思 结果验证 + 错误反馈 + 策略调整
记忆 滑动窗口上下文,关键信息摘要

生产优化:工具结果缓存、并行工具调用、超时熔断、人机协同确认。

口语版讲法(约4分钟)

  • 一句话定位:Agent本质是LLM+工具+记忆+控制循环
  • ReAct循环:Thought-Action-Observation不断迭代
  • 工具注册与动态调用:结构化描述让LLM自主选工具
  • 反思模块:检查结果、错误反馈、自我修正
  • 落地风险:工具结果不可靠、循环失控、记忆溢出

这道题问的是Agent系统,说白了就是怎么让大模型不光能聊天,还能自主完成任务。核心框架就是ReAct循环,Thought、Action、Observation三步反复迭代,直到给出最终答案。

具体说一下,我设计一个Agent,先得有工具注册中心。比如客服场景,用户要退款,Agent得查订单、算金额、调用退款接口。每个工具我都注册进去,名字、功能描述、参数格式,用JSON Schema描述清楚。这样LLM看到提示就知道有哪些工具可用,怎么用。

然后核心循环来了。每次我先让LLM输出一个Thought,就是它打算怎么做,再输出Action和Action Input,就是调哪个工具、传什么参数。比如它想查订单号,就输出Action: query order, Input: {"order id": "123"}。我解析这个结构化输出,去执行工具,拿到Observation,也就是结果。如果结果正常,就把Thought、Action、Observation都追加到记忆里,继续下一轮。如果LLM输出Finish,那就返回最终答案。

这里有个坑,就是工具调用可能出错。比如订单号不存在,接口超时,或者LLM自己写错了参数。所以我做了错误处理,把异常信息也当成Observation塞回去,让LLM自己反思修正。比如它发现查不到订单,可能会换个订单号,或者问用户要更多信息。

再一个关键点是反思模块。每步执行完,我不是无脑往下走,而是让LLM判断结果是否合理。比如它调了库存查询,发现库存不足,那它得反思:是换个仓库,还是通知用户缺货?这个反思可以驱动它回溯、重试或者调整策略。说白了就是让模型自己检查自己的作业。

但真正落地,我特别关注几个风险。 一是工具返回的结果可能不可靠,比如第三方接口返回了脏数据,Agent会信以为真,导致后续全错。所以我会加一个验证步骤,对关键结果做格式校验和业务规则检查。二是循环可能失控,LLM在错误路径上越绕越深,所以我设了最大步数,超时就熔断,返回中间结果或者报错。三是记忆太长会超Token,我会用滑动窗口,只保留最近几轮,或者对历史做摘要压缩。

另外有个延伸点,就是当Agent需要同时调多个工具时,比如查订单的同时还要查用户信用分,我倾向于让LLM先规划一个子任务列表,再并行执行,而不是串行一步步走。这样能大幅提升效率,但对LLM的规划能力要求更高,也更容易出错。

所以我会把Agent看成LLM能力的外延,核心不是模型多强,而是控制循环和工具链的鲁棒性。我更倾向先搭一个简单但可靠的ReAct框架,再逐步加反思、并行、缓存这些优化,而不是一开始就上复杂架构。

关键一句:当Agent需要同时调多个工具时,先规划子任务列表再并行执行,能提升效率但增加复杂度。

面试官还可能这样问

  1. 问法 1 · 场景切入

    假设你在做一个智能客服Agent,用户说‘帮我查一下上个月的订单’,Agent需要先调用订单查询工具,查到之后发现用户还想‘统计一下退款占比’,这时候它得自己规划下一步调用统计工具。你如果来实现这个能力,核心的循环机制怎么设计?

  2. 问法 2 · 层层追问

    Agent怎么知道什么时候该调用工具?……调用完工具拿到结果后,如果发现结果不对或者不够,它怎么自我修正?……这个循环你怎么抽象成代码?

  3. 问法 3 · 直球架构

    设计一个基于LLM的Agent系统,核心是ReAct循环,要求包含任务规划、工具调用和结果反思。你从整体架构开始,讲一下状态管理、工具注册、反思模块的具体实现,以及异常重试怎么处理?

同模块相关题目