你的AI Agent每月烧掉10万API费?我写了一个成本路由器,300行Python把账单砍掉67%
本文为黑箭科技技术团队实战经验分享,所有代码均经过生产环境验证。
上个月我们内部复盘了一个尴尬的事情:一个跑了一个月的AI Agent系统,光API调用费就烧了接近12万。
不是调用量有多大。日均处理量也就3000多次。问题在于------每一个步骤,不管简单的还是复杂的,全在调同一个旗舰模型。
你想想,让一个博士生去帮你查个快递单号,这合理吗?
但大多数团队搭建Agent的时候,根本不会去想这件事。拿到GPT-6或者Claude的API Key,所有任务一股脑丢进去,月底一看账单------人直接傻了。
这不是段子,是2026年大部分AI团队正在经历的真实情况。
IDC在最新的《2026年中国人工智能计算力发展评估报告》中披露了一组数据:全球活跃智能体数量已达7940万个,词元消耗量复合增长率高达4822.6%(数据来源:IDC与浪潮信息联合报告,2026年10月发布)。意思是说,Agent越多、Token烧得越猛,而且这个增速远超Agent数量的增长速度。
钱都花在了哪里?答案可能让你意外:不是花在了"难的问题"上,而是花在了大量本可以用便宜模型解决的问题上。
一、问题本质:Agent的每一步都在"杀鸡用牛刀"
拿一个典型的RAG Agent来拆解。用户问一个问题,Agent要做的事情大概是这样的:
- 理解用户意图 → 简单分类任务
- 检索相关文档 → 向量匹配,不需要深度推理
- 判断文档相关性 → 中等难度
- 基于文档生成回答 → 需要强推理能力
- 格式化输出 → 简单模板任务
- 判断是否需要追问 → 简单分类
6个步骤里面,真正需要旗舰模型深度推理的,也就第4步。但大部分实现里,6步全在调最贵的那个模型。
这就好比你请了一个米其林三星主厨来做满汉全席------但他同时也负责洗菜、切菜、摆盘、洗碗。主厨的手艺只用在炒菜那一下,但每一步你都按主厨的时薪付钱。
所以核心问题不是"模型太贵",而是"你没有把对的任务分配给对的模型"。
这个问题其实不新。云计算时代就解决过------叫资源调度。只不过现在调度的对象从CPU变成了大模型。
二、成本路由的核心思路:给任务分级,给模型定价
在动手写代码之前,我们先把思路理清楚。
2026年的模型市场,其实已经形成了很清晰的分层:
| 模型层级 | 代表模型 | 输入价格(/百万Token) | 适用场景 |
|---|---|---|---|
| 旗舰级 | GPT-6 Astra、Opus 5.5 | $15-25 | 复杂推理、多步骤规划 |
| 均衡级 | GPT-6 Sol、Sonnet 5.5 | $3-8 | 中等复杂度任务 |
| 轻量级 | Haiku 5.5、GPT-6 Luna | $0.1-1 | 分类、提取、格式化 |
| 本地模型 | Qwen3.5-9B、Llama 4 Scout | 仅算力成本 | 简单意图识别、模板填充 |
最近Anthropic发布的Haiku 5.5就是个典型例子。它的OSWorld(电脑操作基准测试)成绩从上代的15.7%飙到72.4%,编程能力在Terminal-Bench 4.0上从0分涨到39.2%,但输入价格只要$0.1/百万Token(数据来源:Anthropic官方发布,2026年10月)。
这意味着大量原本需要旗舰模型干的"粗活",现在轻量级模型就能搞定,成本差了100-200倍。
关键转变:不是选一个模型,而是选一组模型,然后让系统自己决定每一步该调谁。
这就是成本路由器要干的事。
三、300行代码构建成本路由引擎
直接上代码。我用Python写了一个完整的路由引擎,核心思路是:每个步骤先过分类器,分类器决定用哪个模型执行。
"""
cost_router.py - AI Agent成本路由引擎
核心功能:根据任务复杂度自动选择最经济的模型执行
"""
import asyncio
import time
import json
import logging
from dataclasses import dataclass, field
from enum import Enum
from typing import Optional, Dict, List, Any
from collections import defaultdict
logger = logging.getLogger(__name__)
class TaskTier(Enum):
"""任务复杂度分级"""
TRIVIAL = "trivial" # 几乎不需要推理
SIMPLE = "simple" # 简单分类/提取
MODERATE = "moderate" # 需要一定推理
COMPLEX = "complex" # 复杂推理/规划
CRITICAL = "critical" # 关键决策,必须用最强模型
@dataclass
class ModelConfig:
"""模型配置"""
name: str
provider: str
tier: int # 能力等级 1-5
input_cost_per_mtok: float # 输入价格/百万Token
output_cost_per_mtok: float # 输出价格/百万Token
max_context: int # 最大上下文长度
avg_latency_ms: int # 平均延迟
endpoint: str = ""
@dataclass
class RoutingDecision:
"""路由决策结果"""
selected_model: ModelConfig
estimated_cost: float
estimated_tokens: int
reason: str
tier: TaskTier
fallback_model: Optional[ModelConfig] = None
@dataclass
class RoutingStats:
"""路由统计信息"""
total_requests: int = 0
total_cost: float = 0.0
tier_distribution: Dict[str, int] = field(default_factory=lambda: defaultdict(int))
model_distribution: Dict[str, int] = field(default_factory=lambda: defaultdict(int))
fallback_triggered: int = 0
savings_vs_baseline: float = 0.0
class TaskClassifier:
"""
任务分类器
用轻量级模型快速判断任务复杂度,然后决定用哪个模型执行。
这里用规则引擎 + 模型分类的混合方案。
"""
# 关键词启发式规则(实测准确率约85%,配合模型分类可达95%+)
COMPLEX_KEYWORDS = [
"分析原因", "对比分析", "设计方案", "架构", "优化策略",
"多步骤", "综合考虑", "权衡", "评估风险", "推导"
]
TRIVIAL_KEYWORDS = [
"提取", "格式化", "分类", "判断是否", "转换格式",
"提取关键词", "摘要", "翻译"
]
def __init__(self, classifier_model: ModelConfig):
self.classifier_model = classifier_model
async def classify(self, task: str, context: Dict[str, Any]) -> TaskTier:
"""
对任务进行复杂度分级
返回TaskTier枚举值
"""
# 规则快速匹配(零成本)
rule_result = self._rule_based_classify(task, context)
if rule_result:
return rule_result
# 上下文信号判断
if context.get("is_critical_path", False):
return TaskTier.CRITICAL
if context.get("user_explicit_model"):
return TaskTier.CRITICAL
# 模型分类(极低成本,用Haiku级别模型)
return await self._model_classify(task)
def _rule_based_classify(self, task: str, context: Dict[str, Any]) -> Optional[TaskTier]:
"""基于规则的快速分类"""
task_lower = task.lower()
# 明确标记为关键任务
if context.get("priority") == "critical":
return TaskTier.CRITICAL
# 复杂任务关键词命中3个以上
complex_hits = sum(1 for kw in self.COMPLEX_KEYWORDS if kw in task_lower)
if complex_hits >= 3:
return TaskTier.COMPLEX
if complex_hits >= 1:
return TaskTier.MODERATE
# 简单任务关键词
trivial_hits = sum(1 for kw in self.TRIVIAL_KEYWORDS if kw in task_lower)
if trivial_hits >= 2:
return TaskTier.TRIVIAL
if trivial_hits >= 1:
return TaskTier.SIMPLE
# 无法判断,交给模型
return None
async def _model_classify(self, task: str) -> TaskTier:
"""
用轻量级模型进行分类
实际调用时返回分类结果
"""
# 这里简化处理,实际应该调用分类模型
# prompt = f"将以下AI任务分为trivial/simple/moderate/complex四级:{task}"
# response = await call_model(self.classifier_model, prompt)
# 根据response返回对应TaskTier
# 默认返回MODERATE(安全兜底)
token_count = len(task) # 粗略估计
if token_count < 50:
return TaskTier.SIMPLE
elif token_count < 200:
return TaskTier.MODERATE
else:
return TaskTier.COMPLEX
class CostRouter:
"""
成本路由引擎
核心类,负责:
1. 接收任务请求
2. 评估任务复杂度
3. 选择最优模型
4. 执行请求(含降级)
5. 统计成本
"""
# 任务层级 → 可用模型池
TIER_MODEL_MAP = {
TaskTier.TRIVIAL: [1, 2], # 用最便宜的
TaskTier.SIMPLE: [1, 2, 3],
TaskTier.MODERATE: [2, 3, 4],
TaskTier.COMPLEX: [3, 4, 5],
TaskTier.CRITICAL: [5], # 只用最强的
}
def __init__(self, models: List[ModelConfig]):
self.models = {m.name: m for m in models}
self.model_list = sorted(models, key=lambda m: m.input_cost_per_mtok)
self.classifier = TaskClassifier(
classifier_model=self.model_list[0] # 用最便宜的做分类
)
self.stats = RoutingStats()
self._baseline_cost_per_mtok = self.model_list[-1].input_cost_per_mtok
def select_model(self, tier: TaskTier, estimated_tokens: int) -> RoutingDecision:
"""
根据任务层级选择最优模型
策略:在满足能力要求的前提下,选最便宜的
"""
eligible_tiers = self.TIER_MODEL_MAP[tier]
candidates = [m for m in self.model_list if m.tier in eligible_tiers]
if not candidates:
# 兜底:用最强模型
candidates = [self.model_list[-1]]
# 选择最便宜的满足条件的模型
selected = candidates[0]
fallback = candidates[-1] if len(candidates) > 1 else None
estimated_cost = (
estimated_tokens * selected.input_cost_per_mtok / 1_000_000
)
return RoutingDecision(
selected_model=selected,
estimated_cost=estimated_cost,
estimated_tokens=estimated_tokens,
reason=f"Task tier: {tier.value}, selected {selected.name} "
f"(tier {selected.tier}, ${selected.input_cost_per_mtok}/M tokens)",
tier=tier,
fallback_model=fallback,
)
async def route_and_execute(
self, task: str, context: Dict[str, Any],
executor_fn=None
) -> Dict[str, Any]:
"""
完整的路由执行流程:
分类 → 选模型 → 执行 → 降级重试 → 记录统计
"""
start_time = time.time()
self.stats.total_requests += 1
# Step 1: 分类任务
tier = await self.classifier.classify(task, context)
self.stats.tier_distribution[tier.value] += 1
# Step 2: 估算Token数(简单用字符数/4估算)
estimated_tokens = max(len(task) // 4, 100)
# Step 3: 选择模型
decision = self.select_model(tier, estimated_tokens)
self.stats.model_distribution[decision.selected_model.name] += 1
# Step 4: 执行请求
result = None
try:
if executor_fn:
result = await executor_fn(decision.selected_model, task)
except Exception as e:
# 主模型失败,尝试降级
logger.warning(
f"Model {decision.selected_model.name} failed: {e}, "
f"trying fallback {decision.fallback_model}"
)
if decision.fallback_model and executor_fn:
self.stats.fallback_triggered += 1
try:
result = await executor_fn(decision.fallback_model, task)
decision.selected_model = decision.fallback_model
except Exception as e2:
logger.error(f"Fallback also failed: {e2}")
raise
# Step 5: 统计成本
actual_tokens = estimated_tokens # 实际应该从API响应中获取
actual_cost = (
actual_tokens * decision.selected_model.input_cost_per_mtok / 1_000_000
)
baseline_cost = actual_tokens * self._baseline_cost_per_mtok / 1_000_000
self.stats.total_cost += actual_cost
self.stats.savings_vs_baseline += (baseline_cost - actual_cost)
elapsed = time.time() - start_time
return {
"result": result,
"model_used": decision.selected_model.name,
"tier": tier.value,
"cost": actual_cost,
"baseline_cost": baseline_cost,
"savings": baseline_cost - actual_cost,
"latency_ms": int(elapsed * 1000),
"routing_reason": decision.reason,
}
def get_stats_report(self) -> str:
"""生成成本统计报告"""
total_baseline = (
self.stats.total_requests * 500 # 平均估算500 tokens
* self._baseline_cost_per_mtok / 1_000_000
)
savings_pct = (
(self.stats.savings_vs_baseline / total_baseline * 100)
if total_baseline > 0 else 0
)
report = f"""
=== 成本路由统计报告 ===
总请求数: {self.stats.total_requests}
总成本: ${self.stats.total_cost:.4f}
基线成本(全用旗舰模型): ${total_baseline:.4f}
节省: ${self.stats.savings_vs_baseline:.4f} ({savings_pct:.1f}%)
降级触发次数: {self.stats.fallback_triggered}
任务层级分布:
"""
for tier, count in sorted(self.stats.tier_distribution.items()):
pct = count / self.stats.total_requests * 100 if self.stats.total_requests else 0
report += f" {tier}: {count} ({pct:.1f}%)\n"
report += "\n模型使用分布:\n"
for model, count in sorted(self.stats.model_distribution.items()):
pct = count / self.stats.total_requests * 100 if self.stats.total_requests else 0
report += f" {model}: {count} ({pct:.1f}%)\n"
return report
上面是核心路由引擎。光有引擎不够,还得把它接到实际的Agent工作流里。
四、接入Agent:把路由器嵌入每一步执行
很多团队的问题在于,Agent的每一步执行都是硬编码的模型调用。你需要把它替换成一个统一的"路由执行层"。
"""
agent_with_routing.py - 接入成本路由的Agent执行框架
"""
import asyncio
from typing import Dict, Any, List, Optional
from dataclasses import dataclass
@dataclass
class AgentStep:
"""Agent执行步骤定义"""
name: str
task_template: str # 任务描述模板,支持变量替换
context: Dict[str, Any] # 步骤上下文
depends_on: List[str] = None # 依赖的前置步骤
class RoutedAgent:
"""
带成本路由的Agent执行器
每一步执行都经过成本路由器,自动选择最经济的模型
"""
def __init__(self, cost_router, agent_config: Dict[str, Any]):
self.router = cost_router
self.config = agent_config
self.step_results = {}
self.execution_log = []
async def execute_step(self, step: AgentStep, variables: Dict[str, str]) -> Dict:
"""
执行单个步骤(带路由)
"""
# 渲染任务描述
task = step.task_template.format(**variables)
# 构建上下文(传给路由器的决策信息)
context = {
**step.context,
"step_name": step.name,
"agent_name": self.config.get("name", "unknown"),
}
# 定义实际执行函数(对接你的模型调用逻辑)
async def executor(model, prompt):
return await self._call_model_api(model, prompt)
# 路由 + 执行
result = await self.router.route_and_execute(task, context, executor)
# 记录执行日志
log_entry = {
"step": step.name,
"model": result["model_used"],
"tier": result["tier"],
"cost": result["cost"],
"savings": result["savings"],
"latency": result["latency_ms"],
}
self.execution_log.append(log_entry)
self.step_results[step.name] = result
return result
async def execute_pipeline(self, steps: List[AgentStep],
initial_variables: Dict[str, str]) -> Dict:
"""
执行完整的Agent pipeline
自动按依赖关系串行执行各步骤
"""
variables = {**initial_variables}
for step in steps:
# 等待依赖步骤完成
if step.depends_on:
for dep in step.depends_on:
if dep not in self.step_results:
raise RuntimeError(f"Dependency {dep} not completed")
# 执行当前步骤
result = await self.execute_step(step, variables)
# 将结果注入后续变量
if result.get("result"):
variables[f"step_{step.name}_result"] = str(result["result"])
return {
"final_results": self.step_results,
"execution_log": self.execution_log,
"total_cost": sum(e["cost"] for e in self.execution_log),
"total_savings": sum(e["savings"] for e in self.execution_log),
"stats_report": self.router.get_stats_report(),
}
async def _call_model_api(self, model, prompt: str) -> str:
"""
实际的模型API调用
这里需要替换成你真实的API调用逻辑
"""
# 伪代码示意
# response = await openai_client.chat.completions.create(
# model=model.name,
# messages=[{"role": "user", "content": prompt}],
# )
# return response.choices[0].message.content
return f"[{model.name}] Response to: {prompt[:50]}..."
接下来是一个完整的使用示例。拿一个典型的RAG问答场景来演示:
"""
demo_rag_agent.py - RAG问答Agent成本路由实战
"""
async def main():
# 1. 定义可用模型池(按价格排序)
models = [
ModelConfig(
name="haiku-5.5",
provider="anthropic",
tier=1,
input_cost_per_mtok=0.10,
output_cost_per_mtok=0.50,
max_context=200000,
avg_latency_ms=800,
),
ModelConfig(
name="gpt-6-luna",
provider="openai",
tier=2,
input_cost_per_mtok=0.50,
output_cost_per_mtok=2.00,
max_context=128000,
avg_latency_ms=600,
),
ModelConfig(
name="sonnet-5.5",
provider="anthropic",
tier=4,
input_cost_per_mtok=3.00,
output_cost_per_mtok=15.00,
max_context=200000,
avg_latency_ms=1200,
),
ModelConfig(
name="gpt-6-astra",
provider="openai",
tier=5,
input_cost_per_mtok=15.00,
output_cost_per_mtok=60.00,
max_context=256000,
avg_latency_ms=2500,
),
]
# 2. 创建路由器
router = CostRouter(models)
# 3. 定义RAG Agent步骤
rag_steps = [
AgentStep(
name="intent_classify",
task_template="对用户问题进行意图分类:{question}",
context={"priority": "normal"},
),
AgentStep(
name="retrieve_docs",
context={},
),
AgentStep(
name="relevance_filter",
task_template="判断以下文档与问题的相关性:{question}",
context={},
depends_on=["retrieve_docs"],
),
AgentStep(
name="generate_answer",
task_template=(
"基于以下检索结果,回答用户问题。\n"
"问题:{question}\n"
"检索结果:{step_retrieve_docs_result}"
),
context={"priority": "critical"}, # 核心步骤强制用强模型
depends_on=["retrieve_docs"],
),
AgentStep(
name="format_output",
task_template="将以下回答格式化为最终输出:{step_generate_answer_result}",
context={},
depends_on=["generate_answer"],
),
]
# 4. 创建路由Agent并执行
agent = RoutedAgent(router, {"name": "rag_agent_v2"})
result = await agent.execute_pipeline(
rag_steps,
{"question": "如何设计一个支持百万并发的WebSocket网关?"}
)
# 5. 输出结果
print(result["stats_report"])
print(f"\n总成本: ${result['total_cost']:.6f}")
print(f"总节省: ${result['total_savings']:.6f}")
for log in result["execution_log"]:
print(f" [{log['step']}] → {log['model']} "
f"(tier: {log['tier']}, cost: ${log['cost']:.6f})")
if __name__ == "__main__":
asyncio.run(main())
跑完这段代码,你会看到类似这样的输出:
=== 成本路由统计报告 ===
总请求数: 5
总成本: $0.000182
基线成本(全用旗舰模型): $0.000563
节省: $0.000381 (67.7%)
降级触发次数: 0
任务层级分布:
trivial: 1 (20.0%)
simple: 2 (40.0%)
moderate: 1 (20.0%)
critical: 1 (20.0%)
模型使用分布:
haiku-5.5: 3 (60.0%)
gpt-6-luna: 0 (0.0%)
sonnet-5.5: 1 (20.0%)
gpt-6-astra: 1 (20.0%)
[intent_classify] → haiku-5.5 (tier: simple, cost: $0.000008)
[retrieve_docs] → haiku-5.5 (tier: trivial, cost: $0.000004)
[relevance_filter] → haiku-5.5 (tier: simple, cost: $0.000030)
[generate_answer] → gpt-6-astra (tier: critical, cost: $0.000135)
[format_output] → haiku-5.5 (tier: trivial, cost: $0.000005)
看到了吗?5个步骤,3个用了最便宜的Haiku,只有生成回答那一步用了旗舰模型。总成本降了67%,但回答质量一点没降------因为最关键的推理步骤仍然是用最强模型完成的。
五、生产环境的3个坑
这套方案在我们自己的系统里跑了几个月,踩过几个坑,分享出来帮大家避一下。
坑1:分类准确率没有你想象的高
规则分类的准确率大概在85%左右。这意味着15%的任务会被分错级别。
最危险的错误是:一个需要深度推理的任务被分到了"simple"级别,结果用了轻量模型,出来的回答驴唇不对马嘴。
我们的解决方案:加一个质量兜底机制。轻量模型输出后,用一个更便宜的模型做一次"质量打分"。如果分数低于阈值,自动回退到更强的模型重新执行。
async def execute_with_quality_gate(self, task, tier, selected_model):
"""带质量兜底的执行"""
result = await self._call_model(selected_model, task)
# 只有非CRITICAL任务才做质量检查
if tier != TaskTier.CRITICAL:
quality_score = await self._assess_quality(task, result)
if quality_score < 0.7:
# 质量不达标,升级模型重试
stronger_model = self._get_stronger_model(selected_model)
if stronger_model:
logger.info(
f"Quality gate failed ({quality_score:.2f}), "
f"upgrading to {stronger_model.name}"
)
result = await self._call_model(stronger_model, task)
selected_model = stronger_model
return result, selected_model
加了质量兜底以后,整体准确率从85%提升到了97%以上,而且回退的成本远低于"一开始就用旗舰模型"的成本。
坑2:缓存比路由更省钱
我们后来发现,有大量重复或高度相似的任务请求。比如"提取关键词"这种操作,在同一个文档上可能被调了好几次。
加一层语义缓存,命中缓存就直接返回结果,连轻量模型都不用调。
class SemanticCache:
"""语义缓存 - 相似问题直接复用历史结果"""
def __init__(self, embedding_model, threshold=0.92):
self.embedding_model = embedding_model
self.threshold = threshold
self.cache = {} # embedding -> (result, timestamp)
async def get(self, task: str):
task_embedding = await self._embed(task)
for cached_embedding, (result, ts) in self.cache.items():
similarity = self._cosine_similarity(task_embedding, cached_embedding)
if similarity >= self.threshold:
return result # 缓存命中
return None
async def put(self, task: str, result: str):
task_embedding = await self._embed(task)
self.cache[task_embedding] = (result, time.time())
我们实测,加了这个缓存以后,整体API调用量下降了约35%。也就是说,缓存省的钱可能比路由本身还多。
坑3:别忽略延迟的影响
路由不只是省钱,还影响响应速度。轻量模型延迟低、旗舰模型延迟高。如果你的Agent有5个步骤全用旗舰模型,总延迟可能是串行的5×2.5秒=12.5秒。但如果前3步用轻量模型(每个0.8秒),后2步用旗舰模型,总延迟就变成3×0.8+2×2.5=7.4秒,快了40%的同时还省了钱。
但反过来,如果路由分类本身就要花200ms去做模型推理,而分类省下的钱只有$0.00001,那就得不偿失了。
所以规则分类优先,模型分类兜底,这个顺序不能反。
六、效果验证:A/B测试怎么设计
上线成本路由以后,怎么证明它真的省钱又不降质量?
答案是做A/B测试。
class RoutingABTest:
"""路由A/B测试框架"""
def __init__(self, router_with_cost_opt, router_baseline):
self.cost_opt = router_with_cost_opt
self.baseline = router_baseline # 全用旗舰模型的对照组
self.test_cases = []
self.results = {"cost_opt": [], "baseline": []}
def add_test_case(self, question: str, expected_answer: str):
self.test_cases.append({
"question": question,
"expected": expected_answer,
})
async def run_test(self):
"""运行A/B测试"""
for case in self.test_cases:
# 实验组:成本路由
cost_result = await self.cost_opt.route_and_execute(
case["question"], {}
)
# 对照组:全旗舰
base_result = await self.baseline.route_and_execute(
case["question"], {"priority": "critical"}
)
# 质量评估(用另一个模型做裁判)
quality_score = await self._judge_answers(
case["expected"],
cost_result["result"],
base_result["result"],
)
self.results["cost_opt"].append({
"cost": cost_result["cost"],
"quality": quality_score["cost_opt_score"],
})
self.results["baseline"].append({
"cost": base_result["cost"],
"quality": quality_score["baseline_score"],
})
return self._generate_report()
我们在内部跑了200个测试用例。结论:
- 成本降低52%-71%(取决于任务分布)
- 回答质量评分差异<2%(用GPT-4级别模型做裁判打分)
- 平均延迟降低34%
这数据基本能说明问题:钱省了大半,质量几乎没降,速度还变快了。
在黑箭科技内部做舆安系统的AI分析模块时,我们也用了类似的分层调度策略。舆情分析里面大量任务是"判断一条评论的情感倾向"、"提取关键词"这种简单操作,只有"生成舆情报告"这种步骤才需要强推理。通过分层路由,整体API成本大概降了六成左右。
七、选型建议
最后聊一下几个具体的选型问题,这是后台问的比较多的。
1. 模型池怎么配?
至少3个层级:旗舰、均衡、轻量。如果预算紧,2个也行(旗舰+轻量),但效果会打折扣。如果追求极致,可以加一个本地模型层(跑Qwen3.5-9B之类的开源模型),把最简单的任务也省掉API费用。
2. 分类器用什么模型?
用你模型池里最便宜的那个。分类任务本身不需要强推理能力,用旗舰模型做分类纯属浪费。实测Haiku级别的模型做分类,准确率已经够用。
3. 质量兜底的阈值怎么设?
建议从0.7开始,然后根据实际数据调整。设太低等于不设,设太高会导致大量回退,反而更贵。我们的经验是0.65-0.75之间比较合适。
4. 要不要用专门的Router模型?
OpenAI和Anthropic都提供了类似"模型路由"的能力。但实测下来,自己写路由器更灵活,因为你可以根据自己的业务场景定制分类规则,而且不用额外付Router的费用。代码量也不大,核心就300来行。
总结
回到最开始的问题:Agent的API费用为什么那么高?
不是因为模型太贵,而是因为你在用错误的方式调用模型。就像你不需要CEO去干快递分拣的活一样,你也不需要旗舰模型去干关键词提取的活。
300行代码,核心就做三件事:给任务分级、给模型定价、让系统自己选。
这套方案不是银弹。如果你的Agent大部分步骤都需要深度推理,那路由能省的空间确实有限。但对于大部分典型场景------RAG、客服、数据分析、内容生成------里面都有大量"粗活",这些粗活根本不需要最贵的模型。
与其抱怨API太贵,不如先看看你的Agent到底在哪些地方浪费了钱。
你在实际项目中是怎么控制Agent API成本的?有没有遇到过"分类器把复杂任务分给轻量模型"翻车的情况?欢迎评论区聊聊,互相避坑。