发布时间:2026/9/5 2:28:26
动手做一个会调用工具的 AI Agent:多模型路由与工具编排实战 2026 年被称为「智能体落地元年」但真正能稳定干活的 Agent难点往往不在模型本身而在「怎么把模型、工具、上下文编排到一起」。本文用一个可运行的例子讲清楚 Agent 的工程骨架以及为什么在真实项目里我们通常不直接裸连单个模型而是加一层模型路由。一、为什么 Agent 需要「多模型路由」很多初学 Agent 的同学会默认一个 Agent 一个模型 一堆 prompt。这在 demo 阶段没问题一上生产就暴露问题长任务推理用旗舰模型更稳但成本高海量短问答 / 分类 / 抽取用轻量模型就够了硬上旗舰是浪费钱中文长文档摘要某些模型表现更好代码生成又是另一批模型领先单一供应商有可用率风险需要故障转移。所以真实项目里Agent 内部通常不是「一个模型打到死」而是有一层模型路由model routing根据任务类型、输入长度、预算把请求派给最合适的模型。# agent/router.py # 根据任务特征选择后端模型统一通过接入层发出请求 # 接入层负责密钥管理、限流、故障转移业务代码不关心具体供应商 # 注册一个统一接入层示例https://www.moyu.info/register?affCRB8 from enum import Enum class TaskKind(Enum): REASONING reasoning # 复杂推理用旗舰模型 CODEGEN codegen # 代码生成用代码强的模型 EXTRACT extract # 短文本抽取用轻量模型 SUMMARY_CN summary_cn # 中文长文摘要 ROUTING_TABLE { TaskKind.REASONING: gpt-5, TaskKind.CODEGEN: claude-4-sonnet, TaskKind.EXTRACT: gpt-5-mini, TaskKind.SUMMARY_CN: deepseek-v4, } def select_model(task: TaskKind) - str: return ROUTING_TABLE[task]路由表本身很简单麻烦的是后端怎么接。下面展开。二、Agent 的核心骨架循环 工具一个最小可用的 Agent本质是「模型调用 ↔ 工具执行」的循环。这里用 OpenAI 兼容的接口格式主流接入层都支持这套协议换供应商不用改业务代码# agent/run.py import json from agent.router import select_model, TaskKind def call_chat(model: str, messages: list, tools: list None) - dict: # 统一走接入层base_url 指向你的接入网关 # 业务侧只传 model 名 messages密钥在接入层统一管理 return gateway_chat(modelmodel, messagesmessages, toolstools) def run_agent(user_input: str, tools: list): messages [{role: user, content: user_input}] for _ in range(8): # 最多 8 轮工具调用 task classify(user_input) # 简单场景可直接指定 model select_model(task) resp call_chat(model, messages, tools) if resp.get(tool_calls): for call in resp[tool_calls]: result execute_tool(call, tools) messages.append({role: tool, content: result}) else: return resp[content] return 超过最大轮次关键点model字段是动态的。同一个 Agent推理用gpt-5抽字段用gpt-5-mini代码用claude-4-sonnet中文摘要用deepseek-v4。如果每次都去各家官网申请密钥、拼不同 SDK代码会很快腐烂。这就是为什么工程上会引入一层统一接入业务代码只认model字符串密钥、配额、限流、重试、故障转移都在接入层做换模型、加模型、切供应商业务零改动。三、工具怎么定义才不踩坑工具function calling是 Agent 的「手」。定义工具时三个常见坑1. 参数 schema 太松{ name: query_orders, parameters: { type: object, properties: { status: {type: string, description: 订单状态} } } }status不写枚举模型可能传「已付款」「已支付」「paid」三种东西下游解析崩溃。一定要写enum。2. 工具太多导致模型选错一次性塞 30 个工具弱模型会选错。按场景做工具分组或先让模型「选工具组」再「选具体工具」。3. 工具执行没有超时与兜底模型可能生成无限循环的工具调用。上面run_agent里的range(8)就是兜底生产环境还要加单次执行超时。四、上下文怎么管Agent 跑几轮后messages会爆。常用策略滑动窗口只保留最近 N 条压缩记忆把早期对话 summarize 成一条外部记忆把事实写进向量库 / KV用时再取。简单实现def compress_history(messages: list, threshold: int 12) - list: if len(messages) threshold: return messages early, recent messages[:-6], messages[-6:] summary call_chat(gpt-5-mini, [{role: user, content: f用三句话总结对话: {early}}]) return [{role: system, content: f历史摘要: {summary}}] recent注意这里压缩用的也是轻量模型进一步省钱。五、接入层选型直连 vs 聚合真实项目里「模型接入」有几种做法各有取舍方案优点缺点适合场景各家官网直连最直接密钥散落、无统一限流、供应商绑定只用一个模型自建轻量代理可控、可加审计要自己维护可用性有基础设施团队聚合接入层一套协议接多模型、统一配额多一层依赖多模型 / 成本敏感聚合接入层把多家供应商的接口收敛成统一协议业务侧切换模型只改一个字符串还能集中做限流、计费和故障转移。市面上这类方案不少从开源自建到托管服务都有选的时候看清楚是否支持你需要的模型、是否支持自定义模型服务地址、计费是否透明。六、小结一个能稳定干活的 Agent技术含量有一半在「编排」而不是「模型」用模型路由按任务分流别让旗舰模型干抽字段的活业务代码只认model字符串密钥与故障转移交给接入层工具 schema 写死枚举、控制数量、加超时上下文用滑动窗口 摘要压缩别让messages无限涨。把这几件事做对Agent 从 demo 到生产的距离会短很多。

相关新闻

2026/8/31 14:40:10

纯追踪算法:从几何模型到参数调优的工程实践

1. 纯追踪算法基础:从自行车模型到几何推导 第一次接触纯追踪算法时,我被它优雅的几何特性惊艳到了。这个算法的核心思想其实很简单——让车辆像骑自行车那样,沿着一条经过目标点的圆弧行驶。但要把这个直觉转化为数学公式,我们需…

2026/9/2 9:12:34

Rust Option类型解析

Rust Option类型:优雅处理“空值”的哲学与实践在编程世界中,“空值”处理一直是个棘手的问题。传统的null引用被许多语言广泛使用,却也是无数运行时错误的根源。Rust语言的设计者们对此有着深刻的理解,他们创造了一种更为安全的替…

2026/9/2 21:43:52

分布式事务解决方案Saga与TCC模式详解

分布式事务解决方案:Saga与TCC模式详解在微服务架构与分布式系统日益普及的今天,数据一致性问题成为开发者必须面对的核心挑战之一。传统的单体应用中,我们依赖数据库的ACID事务来保证数据一致性。然而在分布式环境中,业务逻辑和数…

2026/9/5 2:24:56

STM32智能家居语音控制系统:从外设开发到仿真调试全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/5 2:24:56

AI编程工作流实战:三层架构搭建与自动化提效指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/5 2:24:56

一阶低通滤波截止频率怎么选?从物理意义到工程实践全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/5 2:24:55

Kubuntu 26 中文输入法配置指南:Fcitx5 从安装到实战

1. 背景 kubuntu26安装系统后,无法使用中文输入法飞书、谷歌浏览器等应用无法使用中文输入法 2. 安装 # 安装 Fcitx5 核心、拼音引擎、所有前端支持及配置工具 sudo apt install fcitx5 fcitx5-chinese-addons fcitx5-frontend-gtk2 fcitx5-frontend-gtk3 fcitx5-fr…

2026/9/5 2:19:55

手写数字识别毕业设计全流程指南:从模型构建到工程部署

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/3 18:28:26

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/9/3 14:29:47

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/9/3 14:30:35

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/9/5 0:04:47

流式背压机制:避免前端渲染卡死与内存暴涨的滑动窗口限流

流式背压机制:避免前端渲染卡死与内存暴涨的滑动窗口限流在大模型流式输出(Streaming)与智能体实时推流的架构中,生产环境中经常出现一种“上下游生产消费速率严重失衡”的极端情况: 生产端极速产出:大模型…

2026/9/3 20:43:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/3 17:51:43

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/3 21:06:57

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…