GPT-6 Astra、Sol 与 Luna 为 Microsoft Foundry 中的生产级 AI Agent 提供了更多模型选择。真正影响上线效果的,并不是简单挑出一个“最强模型”,而是根据复杂工作流、高并发请求和风险等级建立可测量、可切换的模型路由机制。
由于现有摘要没有给出三款模型的具体上下文窗口、价格、延迟或工具调用能力,下面不会预设谁更快、谁更强,而是给出一套可以直接用于工程评估的落地方法。
不要按名字猜能力,用任务集做选择
生产环境中的模型选型至少要同时观察五个维度:
| 维度 | 建议指标 | 典型问题 |
|---|---|---|
| 任务质量 | 成功率、人工评分、事实错误率 | Agent 是否真正完成了目标 |
| 工具调用 | 参数正确率、调用成功率、重试次数 | 是否会选错工具或构造错误参数 |
| 延迟 | P50、P95、P99 | 高峰期是否拖慢整个工作流 |
| 成本 | 单次任务成本、每个成功任务成本 | 便宜的调用是否因重试反而更贵 |
| 稳定性 | 超时率、限流率、输出格式合规率 | 能否长期维持服务等级目标 |
评测时不要只发送几条通用问答。应从真实业务日志中脱敏抽取任务,例如:
- 需要一次回答即可完成的分类、提取和摘要;
- 包含检索、数据库查询或外部 API 的多步任务;
- 需要生成并校验结构化 JSON 的任务;
- 涉及退款、权限变更或代码执行的高风险任务;
- 接近并发与配额上限的批量任务。
Astra、Sol 和 Luna 都应运行同一套数据集。只有这样,路由决策才来自测量结果,而不是模型名称或单次演示。
生产 Agent 应拆成工作流,而不是一次大调用
复杂 Agent 通常包含规划、执行、验证和总结等阶段。每个阶段的需求并不相同:规划可能更看重多步推理,批量提取更在意吞吐量,最终验证则要求稳定遵守规则。
可以将工作流抽象为三类路由:
volume:短请求、低风险、请求量大的任务;complex:长上下文、多步骤或需要多次工具调用的任务;review:影响资金、权限、发布或客户承诺的任务。
这里的路由名称不是对 Astra、Sol、Luna 能力的官方定义。上线前应通过基准测试,把三个 Foundry 部署 ID 分别配置到最合适的路由;同一模型也可以同时承担多个角色。
这种解耦还有一个直接收益:模型升级或配额变化时,只需修改配置,不必改写 Agent 的业务代码。
可直接改造的 Python 模型路由器
下面示例假设你使用的是兼容聊天补全消息结构的 Microsoft Foundry 推理端点。不同项目的 URL、认证头和响应字段可能不同,运行前请以实际部署页面提供的调用格式为准。
将以下内容保存为 agent_router.py:
import json
import os
import sys
import time
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen
ENDPOINT = os.environ['FOUNDRY_CHAT_URL']
API_KEY = os.environ['FOUNDRY_API_KEY']
AUTH_MODE = os.getenv('FOUNDRY_AUTH_MODE', 'api-key')
# 这些值应填写 Foundry 中真实的部署 ID。
# 根据自己的基准测试,让 Astra、Sol、Luna 对应到合适的路由。
MODELS = {
'volume': os.environ['MODEL_VOLUME'],
'complex': os.environ['MODEL_COMPLEX'],
'review': os.environ['MODEL_REVIEW'],
}
def choose_route(text: str, expected_steps: int, risk: str) -> str:
if risk == 'high':
return 'review'
if expected_steps >= 4 or len(text) >= 6000:
return 'complex'
return 'volume'
def call_model(model: str, prompt: str, attempts: int = 3) -> dict:
payload = {
'model': model,
'messages': [
{
'role': 'system',
'content': 'You are a production assistant. Be precise and do not invent tool results.'
},
{'role': 'user', 'content': prompt},
],
'temperature': 0.2,
'max_tokens': 800,
}
headers = {'Content-Type': 'application/json'}
if AUTH_MODE == 'bearer':
headers['Authorization'] = f'Bearer {API_KEY}'
else:
headers['api-key'] = API_KEY
body = json.dumps(payload).encode('utf-8')
for attempt in range(attempts):
request = Request(ENDPOINT, data=body, headers=headers, method='POST')
started = time.perf_counter()
try:
with urlopen(request, timeout=60) as response:
result = json.loads(response.read().decode('utf-8'))
result['_latency_ms'] = round(
(time.perf_counter() - started) * 1000, 1
)
return result
except HTTPError as exc:
retryable = exc.code == 429 or 500 <= exc.code < 600
if not retryable or attempt == attempts - 1:
detail = exc.read().decode('utf-8', errors='replace')
raise RuntimeError(f'Foundry HTTP {exc.code}: {detail}') from exc
except URLError as exc:
if attempt == attempts - 1:
raise RuntimeError(f'Foundry network error: {exc}') from exc
time.sleep(2 ** attempt)
raise RuntimeError('Request failed without a response')
def main() -> None:
prompt = ' '.join(sys.argv[1:]).strip()
if not prompt:
raise SystemExit('Usage: python agent_router.py "your task"')
steps = int(os.getenv('TASK_EXPECTED_STEPS', '1'))
risk = os.getenv('TASK_RISK', 'low').lower()
route = choose_route(prompt, steps, risk)
model = MODELS[route]
result = call_model(model, prompt)
print(json.dumps({
'route': route,
'model': model,
'latency_ms': result.pop('_latency_ms'),
'response': result,
}, ensure_ascii=False, indent=2))
if __name__ == '__main__':
main()
配置部署信息后运行:
export FOUNDRY_CHAT_URL='https://YOUR-ENDPOINT.example/chat/completions'
export FOUNDRY_API_KEY='replace-with-your-key'
export FOUNDRY_AUTH_MODE='api-key'
export MODEL_VOLUME='your-benchmarked-deployment-id'
export MODEL_COMPLEX='your-benchmarked-deployment-id'
export MODEL_REVIEW='your-benchmarked-deployment-id'
TASK_EXPECTED_STEPS=2 TASK_RISK=low \
python agent_router.py '从这段客户反馈中提取产品名、问题类型和紧急程度,并返回 JSON。'
如果实际端点使用部署名而不是请求体中的 model 字段,可以删除该字段,并把部署 ID 放入 URL。生产环境还应使用密钥管理服务或托管身份,不要把 API Key 写进代码仓库。
路由之后,还要补上可观测性与安全边界
模型路由解决的是“调用谁”,并不能单独解决生产可靠性。每次执行至少应记录以下字段:
{
"trace_id": "01J...",
"workflow": "support-ticket-triage",
"route": "complex",
"model_deployment": "deployment-id",
"latency_ms": 1840,
"input_tokens": 2130,
"output_tokens": 380,
"tool_calls": 2,
"retries": 0,
"result": "success"
}
不要记录未经处理的敏感提示词、个人信息或工具凭据。对于能修改数据、发送邮件、执行代码或产生资金影响的 Agent,还应增加:
- 工具参数白名单和 JSON Schema 校验;
- 最小权限身份,不让模型直接持有长期凭据;
- 高风险操作的人类确认或独立验证步骤;
- 超时、限流、指数退避和熔断机制;
- 防止提示词注入的内容隔离与工具授权检查;
- 模型不可用时的降级路径,而不是无限重试。
上线前的决策清单
引入 Astra、Sol 和 Luna 时,可以按下面的顺序推进:
- 用真实、脱敏的业务任务建立固定评测集;
- 对三款模型测量质量、延迟、成本和工具调用成功率;
- 用部署配置表达路由,不在代码中硬编码模型能力假设;
- 对高风险操作设置验证器或人工审批;
- 为 429、5xx、超时和配额耗尽设计降级方案;
- 保存模型版本、提示词版本和评测结果,避免升级后静默退化;
- 先用少量流量灰度发布,再逐步提高比例。
多模型的价值不在于让架构图出现更多方框,而在于把质量、吞吐量、延迟和风险变成可独立调节的工程参数。对生产 Agent 而言,最稳妥的策略通常不是永久押注某一个模型,而是让 Astra、Sol 与 Luna 在同一套评测、路由和监控体系中接受持续验证。