![]()
到目前为止,您已经构建了在笔记本内笔记本电脑上运行的代理,由 az login 和少量环境变量驱动。这确实是学习的正确方法。但这并不是运行一个在凌晨3点有上千客户依赖的代理的正确方法。
本课将介绍“它在我的机器上能运行”与“它能在生产环境中可靠且经济地运行”之间的差距。我们通过使用 Microsoft Foundry 和 Microsoft Foundry Agent Service 填补这道差距,并通过构建一个具有工具、检索、记忆、评估和监控功能的真实客户支持代理实现这一目标。
本课将涵盖:
完成本课后,您将了解如何:
本课假设您已完成之前的课程并熟悉:
您还需要:
az login 认证的 Azure CLI。requirements.txt 包。原型代理和生产代理共享相同的核心循环——推理、调用工具、响应。改变的是包装在该循环周围的所有内容。模型大约占生产代理的20%;其余80%是运营骨架。
| 关注点 | 原型 | 生产 |
|---|---|---|
| 托管 | 运行在你的笔记本内 | 作为托管服务运行,支持版本控制与发布 |
| 身份 | 你的 az login 令牌 |
托管身份,带有范围限定的 RBAC |
| 状态 | 内存中,重启失效 | 外部化(线程存储、记忆服务) |
| 失败 | 你能看到回溯信息 | 重试、降级、死信、告警 |
| 成本 | “几分钱” | 按请求跟踪,路由,缓存,预算管理 |
| 质量 | 你肉眼检查输出 | 每次发布前自动评估 |
| 信任 | 你批准每个操作 | 策略 + 人工介入对风险操作审批 |
记住这张表。下面的每个部分都对应于表中的一行。
常用三种模式,且经常组合使用。
代理对象存在于你的应用进程中。你的代码直接调用模型提供者;推理循环在你的服务里运行。这是之前所有课程采纳的方式。
代理被注册为资源在 Microsoft Foundry 中。Foundry 托管推理循环,存储线程,执行内容安全和 RBAC,且使代理在 Foundry 门户中可见。你的应用成为一个轻客户端,创建线程和读取响应。
多个代理(及工具)组成一个带有显式控制流的图——顺序步骤、分支、人类审批节点、以及可暂停和恢复的持久检查点。这是 Microsoft Agent Framework 工作流 功能在部署规模上的应用。
flowchart TB
subgraph P1[客户端托管]
A1[您的应用进程] --> M1[模型提供者]
end
subgraph P2[托管代理]
A2[精简客户端] --> F2[Foundry 代理服务]
F2 --> M2[模型 + 工具 + 线程存储]
end
subgraph P3[代理工作流]
A3[协调器] --> S1[分诊代理]
S1 --> S2[解析代理]
S2 --> H[人工审批节点]
H --> S3[行动代理]
end
部署代理不是一次性的 push 操作,而是一个循环,它看起来很像软件发布周期,因为它确实就是这样。
flowchart LR
Create[创建 / 作者] --> Version[版本]
Version --> Evaluate[离线评估]
Evaluate -->|通过关卡| Deploy[部署托管]
Evaluate -->|未通过关卡| Create
Deploy --> Observe[在线观察]
Observe --> Improve[收集失败]
Improve --> Create
Deploy --> Retire[退役旧版本]
核心思想,继承自第10课:离线评估是门槛,而非事后考虑。 新版本代理只有通过你的评估标准才会发布。在线可观测性将现实失败反馈回离线测试集,这就是整个循环。
扩展代理与扩展无状态 Web API 不同,因为每个请求可能触发多次昂贵的模型和工具调用。以下四种技术承担了大部分负载。
无状态请求处理。 不在进程内存中保存任何针对单一用户的状态。将对话线程持久化在 Foundry 线程存储或记忆服务中,以便任一实例均可处理任一请求。这是实现水平扩展的关键——增加实例,无需粘性会话。
模型路由。 并非所有请求都需要你最强(且最贵)的模型。将简单请求——意图分类、简短事实回答——路由到体积较小、响应更快的模型,将大型模型保留给真正的推理任务。Foundry 的 Model Router 可以协助你完成,也可以自己实现轻量级分类器。实验中你将构建自定义版本。
响应缓存。 很多支持查询几乎重复(“我如何重置密码?”)。缓存常见问题答案,直接返回缓存内容,无需调用模型。即使是适度的缓存命中率也能显著降低成本和延迟。
并发与背压。 模型提供者有限流。限制并发度,使用指数退避重试,优雅失败(排队的「我们正在处理」响应胜过 500 错误)。
flowchart LR
Q[用户查询] --> C{缓存命中?}
C -->|是| R[返回缓存答案]
C -->|否| Router{复杂度?}
Router -->|简单| SLM[小模型]
Router -->|复杂| LLM[大模型]
SLM --> Out[响应]
LLM --> Out
Out --> Store[缓存 + 跟踪]
不可见的就无法操作。如第10课所述,Microsoft Agent Framework 天生发出 OpenTelemetry 跟踪——每一次模型调用、工具调用和编排步骤都成为一个跨度。在生产中,你将这些跨度导出到 Microsoft Foundry(或任何兼容 OTel 的后台)以便你能:
from agent_framework.observability import get_tracer
tracer = get_tracer()
with tracer.start_as_current_span("support_request") as span:
span.set_attribute("customer.tier", "enterprise")
span.set_attribute("routed.model", "gpt-5-nano")
# 代理执行在此跨度内自动跟踪
类似 customer.tier 和 routed.model 这样的属性将一大批跟踪转化为可回答的问题(“企业客户是否被过于频繁地路由到小模型?”)。
生产代理的成本主要由 Token 决定。以下三种杠杆,按影响力排序:
评估门和成本控制是两个角度看待同一学科:评估设定质量下限,路由和缓存努力将成本保持尽可能靠近该下限。
治理。 托管代理继承 Foundry 的 RBAC、内容安全和审计日志。给每个代理分配只读知识库、范围限定票务 API 访问等最小权限的托管身份。
人工介入。 一些操作后果重大,不能完全自动化——退款、账户删除、升级法律团队。Microsoft Agent Framework 支持 审批必需 工具:代理提出动作,执行暂停,人类审批或拒绝,工作流恢复。第6课介绍了这项原始功能;这里部署它。
生产中的 MCP。 MCP 让代理通过标准接口调用外部工具。生产环境中,将每个 MCP 服务器视为不可信边界:固定服务器版本,使用范围限定身份运行,验证输出,绝不暴露机密。MCP 服务器是依赖项,需要补丁管理、审计和限流。
flowchart TB
subgraph Dev[开发架构]
D1[笔记本] --> D2[代理框架]
D2 --> D3[模型提供者]
D2 --> D4[本地工具]
end
subgraph Deploy[部署架构]
E1[持续集成流水线] --> E2[评估门槛]
E2 -->|通过| E3[Foundry 代理服务]
E3 --> E4[版本化托管代理]
end
subgraph Run[运行时架构]
F1[客户端应用] --> F2[托管代理]
F2 --> F3[模型路由器]
F2 --> F4[Azure AI 搜索 RAG]
F2 --> F5[内存服务]
F2 --> F6[MCP 工具]
F2 --> F7[OTel -> Foundry 追踪]
F2 --> F8[人工审批]
end
这三张图 — 开发、部署、运行时 — 展示了同一代理在生命周期中的三个阶段。接下来的实验引导你构建它。
打开 code_samples/16-python-agent-framework.ipynb 并完整操作。你将组装一个具有所有生产考量的 Contoso 客户支持代理:
笔记本结构化,确保每个生产考量为自包含且可运行的部分。其核心是路由加缓存的请求处理器:
async def handle_support_request(query: str, customer_id: str) -> str:
# 1. 尽可能从缓存提供服务。
cached = response_cache.get(normalize(query))
if cached:
return cached
# 2. 根据复杂度进行路由以控制成本。
model = "gpt-5-nano" if is_simple(query) else "gpt-5-mini"
# 3. 在追踪跨度内运行代理以便观察。
with tracer.start_as_current_span("support_request") as span:
span.set_attribute("routed.model", model)
span.set_attribute("customer.id", customer_id)
response = await support_agent.run(query, model=model)
# 4. 缓存并返回。
response_cache.set(normalize(query), response.text)
return response.text
保护发布的评估门如下:
async def evaluation_gate(agent, test_cases, threshold: float = 0.8) -> bool:
passed = 0
for case in test_cases:
result = await agent.run(case["input"])
if score_response(result.text, case["expected"]) >= 0.8:
passed += 1
pass_rate = passed / len(test_cases)
print(f"Evaluation pass rate: {pass_rate:.0%} (gate: {threshold:.0%})")
return pass_rate >= threshold # 仅当门通过时才部署
逐行阅读 — 笔记本将原始组件保持小巧,避免隐藏在框架调用之后。
上述评估门在线下针对代理对象运行。代理作为托管代理部署后,你还需要更便宜的检测:部署的端点是否真正响应?
“成功部署”只证明控制平面接受定义——不证明代理能响应。缺依赖、错误路由或失效连接可能导致绿灯部署但无响应。冒烟测试能够在部署秒级内捕获这一点,且无需全套评估的成本。
本仓库提供基于 AI Smoke Test GitHub Action 的现成冒烟测试管道:
tests/lesson-16-smoke-tests.json 包含 Contoso 支持代理的提示和断言(有根据的政策答案、订单查询、主题相关以及多轮线程连续性)。其他课程代理的目录紧随其旁,详见 tests/README.md。.github/workflows/smoke-test.yml 通过 Azure OIDC 登录,向代理的 Responses 端点 POST 每个提示,任何断言失败则让任务失败。- name: Smoke-test hosted agent
uses: JFolberth/ai-smoketest@v1
with:
project_endpoint: $
agent_name: ContosoSupportAgent
tests_file: tests/lesson-16-smoke-tests.json
在您的代理部署后,从 Actions 选项卡运行它,提供您的 Foundry 项目端点和代理名称。联合身份需要在 Foundry 项目范围内具有 Azure AI User 角色。可以将层级视为金字塔结构:冒烟测试(是否可访问且有响应?)在每次部署时运行,离线评估(是否足够好到可以发布?)在升级前运行,在线评估(在实际环境中表现如何?)则持续运行。
在进入作业之前测试您的理解。
1. 一个生产代理中“模型”的大致比例是多少,其余部分是什么?
2. 什么时候会选择托管代理而非客户端托管代理?
3. 为什么可扩展代理在其自身进程内存中必须是无状态的?
4. 模型路由解决了什么问题,它与评估有什么关系?
5. 什么是“评估门”,它在生命周期中处于哪个位置?
6. 为什么 MCP 服务器在生产环境中应被视为不可信边界?
7. 哪个单一变更通常对生产代理成本影响最大,为什么?
8. 像 customer.tier 和 routed.model 这样的跨度属性在可观察性中扮演什么角色?
采用实验中的客户支持代理,并针对特定场景进行加固:面向 SaaS 公司的订阅计费支持代理。
您的提交应包括:
get_subscription_status、get_invoice 以及 issue_credit(超过 50 美元的信用额度需要人工批准)。在 markdown 单元中写一小段文字,说明您选择了哪条模型路由规则,以及如何用真实流量验证它。没有唯一正确答案——评估重点是您是否合理连接了生产关注点。
在本课中,您利用 Microsoft Foundry 将代理从原型推进到生产:
下一课将走相反的路径:您将把代理从云端缩小到单台开发者机器,并完全本地运行。
免责声明: 本文件由 AI 翻译服务 Co-op Translator 翻译完成。尽管我们力求准确,但请注意,自动翻译可能包含错误或不准确之处。原始语言版文件应视为权威来源。对于重要信息,建议使用专业人工翻译。我们对因使用本翻译而产生的任何误解或误释不承担责任。