Agent 部署与运维
# Agent 部署与运维
从 Demo 到生产——部署、监控、灰度、CI/CD 全流程
# 19.1 Demo 能跑 ≠ 生产能用
在 Jupyter Notebook 里跑通一个 Agent Demo 只需要 30 分钟。但把它放到生产环境,面对真实用户、真实流量、真实故障,需要解决完全不同的问题。
🧪 Demo 级 Agent
- 单进程、单用户、无并发
- API Key 硬编码在代码里
- 没有日志,出了问题靠 print
- LLM 报错就直接崩溃
- 无限流、无重试、无超时
- 更新代码需要停机
🏭 生产级 Agent
- 多实例、负载均衡、高可用
- 密钥管理(Vault / KMS)
- 全链路日志 + 可观测性
- 优雅降级 + 自动重试 + 超时控制
- 限流 + 熔断 + 步数控制
- 蓝绿部署 / 灰度发布 / 滚动更新
# 19.2 生产级 Agent 部署架构
🏗️ 推荐架构:API Gateway + Agent Service + LLM Proxy
🌐 API Gateway (Nginx / Kong) — SSL 终止、限流、认证、请求路由
🤖 Agent Service (多实例) — Python/Java 服务,处理 Agent 逻辑,无状态可水平扩展
🔗 LLM Proxy (自建网关) — 多模型路由、Key 轮换、缓存、降级、成本统计
💾 数据层 — Redis(会话/缓存)+ PostgreSQL(持久化)+ 向量数据库(RAG)
📊 监控层 — Prometheus(指标)+ Grafana(大屏)+ LangSmith/Langfuse(Trace)
# Dockerfile 模板
FROM python:3.11-slim
# 时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 安装依赖
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制代码
COPY . .
# 健康检查
HEALTHCHECK \
CMD curl -f http://localhost:8080/health || exit 1
# 启动
EXPOSE 8080
CMD ["gunicorn", "--bind", "0.0.0.0:8080", "--workers", "4", \
"--timeout", "120", "--access-logfile", "-", "app:app"]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Docker Compose 部署
version: '3.8'
services:
agent-app:
build: .
container_name: agent-app
restart: on-failure:3 # 最多重启 3 次
ports:
- "8080:8080"
environment:
- REDIS_URL=redis://redis:6379
- DB_URL=postgresql://user:pass@postgres:5432/agent
- LLM_API_KEY=${LLM_API_KEY} # 从 .env 读取
- ENV=production
depends_on:
redis:
condition: service_healthy
postgres:
condition: service_healthy
deploy:
resources:
limits:
memory: 2G
cpus: '2.0'
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
postgres:
image: postgres:16
environment:
POSTGRES_DB: agent
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
healthcheck:
test: ["CMD", "pg_isready"]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 19.3 CI/CD:持续集成与持续部署
Agent 的 CI/CD 与传统软件不同,需要额外关注 Prompt 版本管理 和 评估回归。
CI/CD 流程: 📝 代码提交 → 🧪 单元测试 → 📊 评估回归 → 🐳 构建镜像 → 🚀 灰度发布 → 📈 全量上线
🔑 Agent CI/CD 的特殊环节:评估回归 传统 CI 只跑单元测试(assert x == y)。Agent CI 需要额外跑 评估数据集(EDD),确保 Prompt 修改没有导致回答质量下降。如果评估分数低于阈值,CI 自动阻止发布。
name: Agent CI/CD
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# 1. 单元测试
- name: Run Unit Tests
run: |
pip install -r requirements.txt
pytest tests/ --cov=app --cov-report=xml
# 2. Agent 评估回归(关键!)
- name: Run Evaluation Regression
env:
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
run: |
python -m eval.run_eval \
--dataset eval/datasets/prod.json \
--threshold 0.85 \
--report eval/report.json
# 如果评估分数 < 0.85,CI 失败,阻止发布
# 3. 构建 Docker 镜像
- name: Build Docker Image
run: |
docker build -t my-agent:${{ github.sha }} .
docker tag my-agent:${{ github.sha }} my-agent:latest
# 4. 灰度部署(10% 流量)
- name: Deploy Canary
run: |
./scripts/deploy.sh --canary --image my-agent:${{ github.sha }}
# 5. 等待观察 5 分钟
- name: Canary Observation
run: sleep 300
# 6. 检查灰度指标,决定全量 or 回滚
- name: Promote or Rollback
run: |
METRICS=$(./scripts/check_canary.sh)
if [ "$METRICS" = "healthy" ]; then
./scripts/deploy.sh --full --image my-agent:${{ github.sha }}
else
./scripts/rollback.sh
exit 1
fi
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 19.4 灰度发布策略
Agent 的输出有随机性,新版本可能有未知问题。灰度发布让你 先给一小部分用户用新版本,观察指标正常后再全量。
| 策略 | 方式 | 适合场景 |
|---|---|---|
| 蓝绿部署 | 两套环境,一键切换 | 快速回滚、停机时间零 |
| 金丝雀发布 | 新版先承接 5%-10% 流量 | Agent 版本升级 |
| A/B 测试 | 按用户分组,对比指标 | Prompt 效果对比 |
| 影子发布 | 新版处理真实请求但不返回结果 | 验证新 Agent 无副作用 |
# 金丝雀发布实现
# 10% 流量到新版本,90% 到旧版本
upstream agent_v1 {
server agent-v1:8080;
}
upstream agent_v2 {
server agent-v2:8080;
}
# 按用户 ID 哈希分配,同一用户始终命中同一版本
split_clients "${remote_addr}${http_user_id}" $agent_backend {
10% agent_v2; # 10% 用户走新版本
* agent_v1; # 90% 用户走旧版本
}
server {
listen 80;
location /api/agent {
proxy_pass http://$agent_backend;
proxy_set_header X-Canary $agent_backend;
add_header X-Agent-Version $agent_backend;
}
# 紧急回滚:把 10% 改成 0%
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 19.5 监控与告警体系
生产环境必须做到 5 分钟发现、5 分钟定位、5 分钟恢复。没有监控的 Agent 就像闭眼开车。
| 监控层 | 指标 | 工具 | 告警阈值 |
|---|---|---|---|
| 系统层 | CPU/内存/磁盘/网络 | Prometheus + Node Exporter | CPU > 80% |
| 应用层 | QPS/延迟/错误率 | Prometheus + Grafana | P99 > 10s |
| Agent层 | 成功率/步数/Token消耗 | LangSmith / Langfuse | 成功率 < 85% |
| LLM层 | API延迟/配额/费用 | 自定义 LLM Proxy | 费用 > 预算 80% |
| 业务层 | 用户满意度/投诉率 | 反馈系统 | 差评率 > 5% |
from prometheus_client import Counter, Histogram, Gauge
# Agent 指标定义
agent_requests = Counter(
'agent_requests_total',
'Total agent requests',
['chapter', 'status'] # 标签:章节、状态(success/fail)
)
agent_latency = Histogram(
'agent_latency_seconds',
'Agent response latency',
['chapter'],
buckets=[0.5, 1, 2, 5, 10, 30, 60, 120] # 延迟分桶
)
agent_tokens = Counter(
'agent_tokens_total',
'Total tokens consumed',
['model', 'type'] # 模型、类型(input/output)
)
agent_steps = Histogram(
'agent_steps_count',
'Number of steps per request',
buckets=[1, 3, 5, 10, 15, 20]
)
# 在 Agent 执行流程中埋点
def handle_request(user_input, chapter):
start = time.time()
try:
result = agent.invoke(user_input)
agent_requests.labels(chapter=chapter, status='success').inc()
return result
except Exception as e:
agent_requests.labels(chapter=chapter, status='fail').inc()
raise
finally:
agent_latency.labels(chapter=chapter).observe(time.time() - start)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 19.6 成本优化策略
Agent 的最大成本是 LLM API 调用费用。一个不加优化的 Agent,月账单可能从 $100 飙到 $10,000。
💰 五大成本优化策略
1. 模型分级路由 — 简单问题用 mini 模型($0.15/M),复杂问题才用旗舰模型($5/M)。80% 问题用 mini 解决,成本降 5-10 倍。
2. 语义缓存 — 用向量相似度判断"是否问过类似问题",命中缓存直接返回,不再调用 LLM。命中率 20-40%。
3. Prompt 压缩 — 精简 System Prompt,去掉不必要的示例和说明。每省 1000 Token = 每次省 $0.01-0.05。
4. 步数控制 — 限制 Agent 最大步数(如 10 步),避免无限循环烧 Token。每多一步 = 一次完整 LLM 调用。
5. 批量处理 — 多个独立任务合并为一次 LLM 调用(batch)。OpenAI Batch API 半价,适合非实时场景。
def route_model(query: str, has_tools: bool) -> str:
"""根据问题复杂度选择模型"""
# 简单问答 → mini 模型(便宜 30 倍)
if not has_tools and len(query) < 100:
return "gpt-4o-mini"
# 需要工具调用 → 标准模型
if has_tools and not is_complex_task(query):
return "gpt-4o"
# 复杂推理 → 旗舰模型
return "claude-3.5-sonnet"
# 成本对比(每百万 Token):
# gpt-4o-mini: $0.15 ← 80% 请求用这个
# gpt-4o: $2.50 ← 15% 请求用这个
# claude-3.5: $3.00 ← 5% 请求用这个
#
# 不分级:100% 用 gpt-4o = $2.50/M
# 分级后:80%×$0.15 + 15%×$2.50 + 5%×$3.00 = $0.57/M
# 节省 77%!
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import numpy as np
class SemanticCache:
"""基于向量相似度的缓存"""
def __init__(self, threshold=0.95):
self.cache = {} # {query_vector: response}
self.threshold = threshold # 相似度阈值
def get(self, query: str) -> str | None:
query_vec = embeddings.embed_query(query)
for cached_vec, response in self.cache.items():
similarity = cosine_similarity(query_vec, cached_vec)
if similarity > self.threshold:
return response # 缓存命中
return None # 未命中
def set(self, query: str, response: str):
vec = embeddings.embed_query(query)
self.cache[vec] = response
# 使用
cache = SemanticCache(threshold=0.95)
def chat(query):
# 先查缓存
cached = cache.get(query)
if cached:
return cached # 命中,不调用 LLM
# 未命中,调用 LLM
response = llm.invoke(query)
cache.set(query, response)
return response
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 面试八股
Q:Demo 级 Agent 和生产级 Agent 的区别是什么?
A: Demo 关注功能跑通:单进程、无并发、无监控、无重试。生产级关注可靠运行:多实例高可用、限流熔断、全链路监控、优雅降级、灰度发布、成本控制。面试关键:能说出 Demo 的 5 个缺陷和对应的生产级解决方案(密钥管理、日志监控、错误重试、超时控制、资源限制)。
Q:Agent 的 CI/CD 和传统软件有什么不同?
A: 最大的区别是 评估回归。传统 CI 跑单元测试(assert),Agent CI 额外要跑评估数据集(EDD),确保 Prompt 修改没有导致回答质量下降。如果评估分数低于阈值(如 0.85),CI 自动阻止发布。这是因为 Agent 输出有随机性,代码逻辑没变但 Prompt 变了可能导致行为退化。
Q:什么是金丝雀发布?Agent 为什么需要它?
A: 金丝雀发布:新版本先承接 5-10% 流量,观察指标正常后再全量。Agent 需要它因为:① LLM 输出有随机性,测试集无法覆盖所有情况;② Prompt 微调可能有副作用;③ 新工具可能有未知的失败模式。金丝雀发布让问题影响范围最小化,发现问题可以快速回滚。
Q:Agent 的监控体系应该包含哪些层面?
A: 五层监控:① 系统层(CPU/内存/磁盘);② 应用层(QPS/延迟/错误率);③ Agent层(成功率/步数/Token消耗,用 LangSmith/Langfuse);④ LLM层(API延迟/配额/费用);⑤ 业务层(用户满意度/投诉率)。每层设定告警阈值,实现 5 分钟发现-定位-恢复。
Q:如何优化 Agent 的 LLM API 成本?
A: ① 模型分级路由:80% 简单问题用 mini 模型($0.15/M),复杂问题才用旗舰模型,成本降 5-10 倍;② 语义缓存:相似问题命中缓存直接返回,命中率 20-40%;③ Prompt 压缩:精简 System Prompt;④ 步数控制:限制最大步数防止烧 Token;⑤ 批量处理:非实时任务用 Batch API(半价)。
# 课后练习
# 第 1 题(单选)
Agent CI/CD 相比传统软件 CI/CD 最大的区别是?
A. 需要构建 Docker 镜像 B. 需要跑评估回归(EDD),确保 Prompt 修改没有降低回答质量 C. 需要单元测试 D. 需要代码审查
答案与解析
答案:B
Agent CI/CD 额外需要评估回归(EDD),用评估数据集验证回答质量。代码逻辑没变但 Prompt 变了可能导致行为退化,传统的 assert 测试无法覆盖。
# 第 2 题(单选)
金丝雀发布的策略是?
A. 一次性全量切换到新版本 B. 新版本先承接 5-10% 流量,观察指标正常后再全量 C. 两套环境同时运行,手动切换 D. 新版本处理请求但不返回结果给用户
答案与解析
答案:B
金丝雀发布:新版先承接小比例流量(5-10%),观察指标正常后逐步扩大到全量。问题影响范围最小化,发现异常可快速回滚。
# 第 3 题(多选)
生产级 Agent 监控体系应该包含哪些层面?(多选)
A. 系统层(CPU/内存/磁盘) B. 应用层(QPS/延迟/错误率) C. Agent层(成功率/步数/Token消耗) D. 代码注释覆盖率
答案与解析
答案:A、B、C
五层监控:系统层、应用层、Agent层、LLM层、业务层。代码注释覆盖率不是运维监控指标。
# 第 4 题(单选)
模型分级路由如何降低成本?
A. 所有请求都用最便宜的模型 B. 80% 简单问题用 mini 模型,复杂问题才用旗舰模型,成本降 5-10 倍 C. 不使用 LLM,改用规则引擎 D. 只在夜间调用 LLM API
答案与解析
答案:B
分级路由:简单问题用 mini($0.15/M),复杂问题用旗舰($5/M)。80% 请求用 mini,综合成本可降 5-10 倍。
# 第 5 题(单选)
语义缓存的作用是?
A. 缓存 LLM 模型参数,加快推理 B. 用向量相似度判断"是否问过类似问题",命中则直接返回不调 LLM C. 压缩 Prompt 减少 Token D. 缓存工具调用结果
答案与解析
答案:B
语义缓存:将用户问题的向量化后比对,相似度超过阈值(如 0.95)则返回缓存的回答,不再调用 LLM。命中率 20-40%,直接省掉对应的 API 费用。
# 第 6 题(多选)
Agent 的成本优化策略包括?(多选)
A. 模型分级路由(简单问题用 mini) B. 语义缓存(相似问题不重复调 LLM) C. 步数控制(限制最大步数防烧 Token) D. 增加 LLM 参数量
答案与解析
答案:A、B、C
模型分级、语义缓存、步数控制都是有效成本优化策略。增加 LLM 参数量反而增加成本。
# 第 7 题(单选)
Docker Compose 中 restart: on-failure:3 的含义是?
A. 容器每天重启 3 次 B. 容器失败时自动重启,最多重试 3 次 C. 运行 3 个容器副本 D. 容器 3 秒后自动重启
答案与解析
答案:B
on-failure:3 表示容器因错误退出时自动重启,最多重试 3 次。超过 3 次不再重启,防止无限重启循环。