当前位置: 首页 > news >正文

AI Agent 推理:从单次对话到多轮工具调用

本文基于昇腾CANN和昇腾NPU,围绕 cann-recipes-infer 仓库的相关技术展开。

AI Agent 的推理模式跟普通对话不一样:模型输出的是一个动作序列——调工具、看结果、再调工具,直到任务完成。这对推理系统的要求从"一次预测"变成了"循环直到停止"。CANN 在 Agent 推理场景下需要做两件事:高吞吐的循环推理 + 工具调用的 Host-Device 交互。

Agent 推理循环的结构

# AI Agent 的典型推理循环——工具调用直到完成classAgentExecutor:""" 一个 Agent 推理单元:模型 + 工具集合 + 停止条件 """def__init__(self,model,tools):self.model=model# LLM 模型self.tools={"search":ToolSearch(),"calc":ToolCalculator(),"code":ToolCodeRunner(),"read":ToolFileReader(),}self.max_turns=10self.history=[]defrun(self,user_query):""" 一次用户请求 = N 轮模型推理 + M 次工具调用 """messages=[{"role":"user","content":user_query}]forturninrange(self.max_turns):# Step 1: 模型推理——生成回复response=self.model.chat(messages)# Step 2: 解析是否要调工具# Agent 模型的输出格式通常是:# <tool_call>{"name": "search", "args": {"query": "..."}}</tool_call>tool_calls=parse_tool_calls(response)ifnottool_calls:# 没有工具调用 → Agent 完成了returnresponse# Step 3: 执行工具调用——Host 侧fortcintool_calls:tool=self.tools[tc["name"]]result=tool.run(tc["args"])# 把工具结果追加给模型messages.append({"role":"tool","tool_call_id":tc["id"],"content":result})# Step 4: 继续下一轮——带着工具结果再次推理return"Agent 达到最大轮数,未完成"

Agent 推理的核心约束:每次工具调用完,KV Cache 要能续上——不能每次重新 Prefill。

KV Cache 续接——避免重复 Prefill

# Agent 推理的关键优化:KV Cache 续接classAgentKVCacheManager:""" 管理 Agent 多轮推理的 KV Cache——不走重复 Prefill """def__init__(self,num_layers,num_heads,head_dim,max_seq=65536):# 预分配一个大的 KV Cache 空间self.kv_pool=torch.empty(num_layers,2,max_seq,num_heads,head_dim,dtype=torch.float16,device="npu")self.current_len=0defextend_with_tool_result(self,tool_result_tokens):""" 工具调用结果追加到已有 Cache 后面 流程: Prefill 阶段(首次):Query → 模型 Cache[0..q_len) 工具调用后:Cache[0..q_len) 不动,新 Cache[q_len..) 追加 """start_pos=self.current_len end_pos=start_pos+len(tool_result_tokens)# 在 CANN 上做"增量 Prefill"# 不是从头算全部,只算新增部分的 K、V# 模型的其他层 Cache 不动new_kv=self.incremental_prefill(tool_result_tokens,start_pos# 告诉模型从哪个位置开始)# 写到预先分配的位置forlayerinrange(num_layers):self.kv_pool[layer,0,start_pos:end_pos]=new_kv[layer,0]self.kv_pool[layer,1,start_pos:end_pos]=new_kv[layer,1]self.current_len=end_posreturnstart_posdefincremental_prefill(self,tokens,start_pos):""" 增量 Prefill——只算新增 Token 的 K、V CANN Runtime 支持这种"从指定位置开始"的执行模式 不需要重新构建整图的 KV Cache """# CANN 上通过 GE 的 Incremental 执行模式# 设置输入位置偏移,模型自动从 start_pos 开始output=model.execute_with_offset(input_ids=tokens,position_offset=start_pos,kv_cache_base=self.kv_pool)returnoutput

Agent 场景下,如果每次工具返回都做完整 Prefill——一个 5 轮 Agent 调用等于 5 个新请求。增量续接后相当于只有第一次是 Prefill,后面 4 次是增量 Prefill + Decode。

CANN 上 Agent 推理的调度

// Agent 场景下的 CANN 推理调度——多 Agent 并行classAgentBatchScheduler{// 同时跑 K 个 Agent,每个 Agent 在不同推理阶段std::vector<AgentState>agents;voidScheduleStep(){// 调度策略:把处于"推理阶段"的 Agent 合并成一个 Batchstd::vector<int>inferring_agents;for(auto&agent:agents){if(agent.phase==AgentPhase::INFERRING){inferring_agents.push_back(agent.id);}}// 合并推理——这些 Agent 都在"等模型输出"// 它们的 KV Cache 长度可能不同,Continuous Batching 策略if(!inferring_agents.empty()){BatchInput batch_input;for(intid:inferring_agents){auto&agent=agents[id];// 每个 Agent 当前只需 Decode 1 个 Tokenbatch_input.input_ids.push_back(agent.next_input_id);// 每个 Agent 的 KV Cache 位置不同batch_input.kv_start_pos.push_back(agent.kv_cache.current_len);batch_input.kv_lengths.push_back(agent.kv_cache.current_len);}// 一次推理出所有 Agent 的下一个 Tokenstd::vector<int>next_tokens=model.batch_infer(batch_input);// 分发结果for(size_t i=0;i<inferring_agents.size();i++){intid=inferring_agents[i];agents[id].last_output=next_tokens[i];agents[id].phase=AgentPhase::PARSING;// 切到解析}}// "解析阶段"的 Agent——检查是否要调工具for(auto&agent:agents){if(agent.phase==AgentPhase::PARSING){agent.CheckToolCall();}}}};

Agent 推理的性能瓶颈不在单次推理快慢,而在整个循环的吞吐。一个 8 轮 Agent 的端到端延迟 = Prefill(80ms) + 8 × Decode(100ms) + 8 × 工具调用(50ms) ≈ 1.5 秒。CANN 的 Continuous Batching + 增量 Prefill 能把多个 Agent 的推理合并,8 个 Agent 并行时吞吐从 0.7 agent/s 提到 3.8 agent/s。

参考仓库

Agent 推理配方

GE 图引擎增量执行

Runtime 显存管理

http://www.jsqmd.com/news/872686/

相关文章:

  • 用Python从零实现Shamir秘密共享:一个密码学小白的实战笔记
  • 用快递分拣站理解图神经网络:50行代码讲透GNN核心原理
  • 热键侦探:3分钟找出Windows系统中偷走你快捷键的“小偷“
  • 2026 IC 托盘高温板五大靠谱供应商权威推荐 - 资讯纵览
  • 北大核心是北京大学图书馆联合众多学术界权威专家鉴定,国内几所大学的图书馆根据期刊的引文率、转载率、文摘率等指标确定的。-3年一更新-下载地址
  • Nodejs 服务端应用集成 Taotoken 多模型 API 的配置指南
  • 手把手教你搞定CH340驱动:Windows 10/11下RS485转USB连接Modbus温度传感器的完整流程
  • 从电影运镜到游戏镜头:手把手教你用Cinemachine实现高级镜头语言(含Dutch Angle等实战配置)
  • 安徽 GEO 优化优质服务商盘点|合肥 AI 搜索优化怎么选? - 行业深度观察C
  • Hermes Agent 框架接入 Taotoken 自定义提供商的具体步骤
  • 从‘打包’到‘拆包’:用Wireshark抓包实战,图解802.11帧聚合(A-MSDU/A-MPDU)的完整生命周期
  • XB1ControllerBatteryIndicator终极指南:5分钟解决Xbox手柄电量焦虑
  • 别再只盯着Doherty了!聊聊手机5G射频PA里那些‘冷门’架构:Push-pull和Balance到底怎么用?
  • BitC,omet(比,特彗,星 ),专为BT下载爱好者打造的纯净工具,突破冷门资源下载瓶颈
  • 军营涉密场景升级:UWB硬件存泄密风险,无感定位数据本地闭环
  • 2025年苏州十大专业短视频代运营推荐榜单,便宜高效服务商推荐 - 资讯纵览
  • 2026 芯片托盘怎么选才靠谱?五大头部厂商 + 硬核标准 - 资讯纵览
  • 2026某同城数据采集实战:图片验证码+短信轰炸防护全解析与避坑指南
  • 别再只会跑瞬态了!PSpice DC Sweep直流扫描保姆级教程,从RC电路到三极管特性曲线
  • 从简单CNN到ResNet18:我是如何一步步把MNIST手写数字识别准确率提到99.5%以上的
  • 2026年粽子真空包装机厂家深度测评:如何为粽子生产匹配最佳方案? - 资讯纵览
  • 三分钟上手:iCloud+匿名邮箱批量生成终极指南
  • 别再只会用`docker system prune`了!聊聊Docker磁盘清理的5个隐藏场景与实战命令
  • 从测速到配置:一份给游戏玩家和直播主的cFosSpeed保姆级网络优化指南
  • Selenium Cookie登录实战:跳过验证码提升测试稳定性
  • 谷歌搜索SEO优化技巧有哪些?删掉废网页让抓取量提升30%
  • 2026南京GEO优化公司深度测评权威TOP5:本土技术实力与实战效果横评 - 小艾信息发布
  • 京东联盟h5st 3.1原理与403精准解决方案
  • 从微服务架构师视角:用Docker+Seata+Nacos搞掂分布式事务,你的配置真的安全吗?
  • VutronMusic:构建现代化跨平台音乐播放器的技术实现方案