2025年,AI 应用开发早已跨越“Demo 演示”的阶段,如何将基于大语言模型(LLM)的智能代理(Agent)打造成高并发、低延迟、可观测的生产级服务,成为摆在每一位 AI 工程师面前的硬骨头。本文不讨论单一框架的用法,而是从工程架构视角出发,结合我们自研 AI 产品(支持多 Agent 协作与工具调用)的落地经验,系统性拆解生产环境中必须攻克的四大核心痛点:任务编排的确定性保障、异构模型网关与高可用容灾、语义层缓存加速、以及全链路可观测性建设。全文包含详细的架构图(Mermaid)、核心代码片段(Python/Go)及压测数据对比,旨在为正在将 AI 产品推向生产的开发者提供一份可落地的工程参考。
在过去半年中,我们调研了数百个基于 RAG 或 Agent 的开源项目,发现一个惊人的共性:90% 的项目在 Jupyter Notebook 中运行完美,但在上线首周便因超时、幻觉循环、成本失控或模型限流而崩溃。
原因很简单:学术界关注 效果(Effectiveness) ,而工业界首先要求 稳定性(Stability)与性价比(Efficiency)。
本文将围绕下图的整体分层架构展开,详细阐述我们是如何将平均响应延迟从 6.2 秒压缩至 2.1 秒,并将因模型 API 故障引起的服务不可用时间降低 99.7% 的。
Agent 最大的魅力在于其“自主决策”,但这也是生产环境最大的噩梦。我们经常遇到模型在 ReAct 循环中陷入死胡同(例如反复调用 search 工具且参数不变)。
为了避免模型输出无效指令,我们不在提示词中“建议” JSON 格式,而是在推理阶段使用 约束解码(Constrained Decoding)。以下是我们基于 Pydantic 和 Llama.cpp 的实践:
from pydantic import BaseModel, Field
from typing import Literal, Optional
import json
class AgentAction(BaseModel):
thought: str = Field(description="当前推理思路")
tool_name: Literal["search_web", "calculate", "click_element", "finished"]
tool_input: dict = Field(description="工具参数,必须符合对应工具的 JSON Schema")
confidence: float = Field(ge=0.0, le=1.0, description="置信度评分")
# 在推理时,将 schema 转为字符串强塞给 system prompt,并在后端增加一层正则/JSON 修复层
def parse_llm_output(raw: str) -> AgentAction:
try:
# 提取 JSON 块
if "```json" in raw:
raw = raw.split("```json")[1].split("```")[0]
return AgentAction(**json.loads(raw))
except (json.JSONDecodeError, ValidationError) as e:
# 降级策略:使用正则二次提取,或返回预定义的“重试”动作
return AgentAction(thought="解析失败", tool_name="retry", tool_input={}, confidence=0.1)我们引入了有限状态机(FSM)来管理 Agent 的生命周期,不再单纯依赖模型输出的 finished 标志。
from enum import Enum, auto
class AgentState(Enum):
INIT = auto()
THINKING = auto()
ACTING = auto()
OBSERVING = auto()
FINISHED = auto()
ERROR = auto()
class AgentRuntime:
def __init__(self, max_steps=10, max_same_action_attempts=3):
self.max_steps = max_steps
self.action_history = [] # 存储动作指纹
def should_terminate(self, state, current_action):
# 1. 步数超限
if len(self.action_history) >= self.max_steps:
return True, "Max steps exceeded"
# 2. 重复动作检测(hash 碰撞)
action_hash = hash(f"{current_action.tool_name}_{json.dumps(current_action.tool_input)}")
recent_actions = self.action_history[-self.max_same_action_attempts:]
if all(h == action_hash for h in recent_actions):
return True, "Repeated action detected, breaking loop"
return False, None这种硬编码的工程限制,比依赖模型“自觉”结束要可靠得多。
AI 产品对第三方 API(如 OpenAI、Anthropic)的依赖是最大的单点故障。我们自研了 Model Gateway 作为中间层,核心解决两个问题:异构响应格式统一与自动故障转移。
不同的厂商 API 格式不同(OpenAI 的 tools 字段、Anthropic 的 tool_use 块)。我们在网关层将其抽象为统一的内部 ChatRequest 和 ChatResponse:
// Go 实现示例
type UnifiedChatRequest struct {
Messages []Message `json:"messages"`
Tools []ToolDef `json:"tools"`
MaxTokens int `json:"max_tokens"`
}
type ProviderAdapter interface {
ConvertRequest(req *UnifiedChatRequest) (interface{}, error)
ConvertResponse(raw interface{}) (*UnifiedChatResponse, error)
}
// OpenAI 适配器实现
type OpenAIBuilder struct{}
func (o *OpenAIBuilder) ConvertRequest(req *UnifiedChatRequest) interface{} {
return openai.ChatCompletionRequest{
Messages: convertMessages(req.Messages),
Tools: convertTools(req.Tools),
MaxTokens: req.MaxTokens,
}
}我们基于 Token Bucket(令牌桶) 进行限流,并引入了指数退避重试。当主力模型(如 GPT-4o)返回 429 或 5xx 时,自动在 100ms 内 切换到备用模型(如 DeepSeek-V3 或 Claude 3.7 Sonnet)。
# 配置策略
retry_policy:
max_attempts: 3
backoff_base: 2 # 指数退避基数为2
backoff_cap: 30 # 最大退避30秒
fallback_policy:
priority_list:
- provider: "gpt-4o"
weight: 80
timeout: 15s
- provider: "claude-3.7"
weight: 15
timeout: 20s
- provider: "deepseek-local"
weight: 5
timeout: 30s
# 健康检查:连续失败3次则标记为不健康,冷却60秒
circuit_breaker:
failure_threshold: 3
recovery_timeout: 60s效果数据:在上线首周,OpenAI 发生两次大规模抖动,网关自动切换使客户端错误率仅从 0.2% 上升至 0.5%,无感知中断。
在 AI 产品中,LLM 调用成本占总成本的 60%-80%。我们观察到,在客服、文档问答等场景中,用户问法虽不同,但语义高度相似。传统的 KV 缓存(精确匹配)无效,必须引入 语义缓存(Semantic Cache)。
import numpy as np
from redis import Redis
from pymilvus import Collection
class SemanticCache:
def __init__(self, redis_client: Redis, milvus_collection: Collection, threshold=0.92):
self.redis = redis_client
self.milvus = milvus_collection
self.threshold = threshold
async def get(self, query: str, embedding: np.ndarray):
# 1. 精确匹配
exact_key = f"cache:exact:{hash(query)}"
if cached := self.redis.get(exact_key):
return cached
# 2. 语义匹配
search_results = self.milvus.search(
data=[embedding.tolist()],
anns_field="embedding",
param={"metric_type": "COSINE", "params": {"nprobe": 16}},
limit=1
)
if search_results and search_results[0].score > self.threshold:
hit_id = search_results[0].id
# 更新精确缓存(热数据预热)
self.redis.setex(exact_key, 3600, self.milvus.get(hit_id)["response"])
return self.milvus.get(hit_id)["response"]
return None注意:语义缓存最大的陷阱是 TTL 淘汰导致的模型偏见。我们设置缓存有效期仅为 10 分钟(针对实时数据)至 24 小时(针对静态知识),确保在重要数据更新后,缓存不会成为“幻觉放大器”。
AI Agent 的调试远比传统微服务复杂,因为错误可能源于:模型幻觉 > 上下文截断 > 工具返回异常 > 解析逻辑 Bug。
我们为每一次完整的用户会话(Session)生成唯一的 TraceID,并强制在调用模型、执行工具、更新记忆时都插入 Span。
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
@tracer.start_as_current_span("llm_inference")
def call_llm(messages):
span = trace.get_current_span()
span.set_attributes({
"llm.model": "gpt-4o",
"llm.max_tokens": 4096,
"llm.temperature": 0.1
})
# 记录 token 消耗
response = ...
span.set_attribute("llm.usage.prompt_tokens", response.usage.prompt_tokens)
span.set_attribute("llm.usage.completion_tokens", response.usage.completion_tokens)
return response
@tracer.start_as_current_span("tool_execution")
def execute_tool(name, params):
span = trace.get_current_span()
span.set_attribute("tool.name", name)
span.set_attribute("tool.params", json.dumps(params))
result = ...
# 记录工具返回值的长度,便于排查截断
span.set_attribute("tool.result_length", len(str(result)))
return result我们定义了三个核心 SLI(服务水平指标)并接入 Prometheus/Grafana:
我们使用 Locust 模拟了 500 并发用户,对优化前后的系统进行了对比(单 Agent 处理复杂的电商售后任务,含 3 次工具调用)。
指标 | V1.0(直连模型+无缓存) | V2.0(网关+语义缓存+熔断) | 提升幅度 |
|---|---|---|---|
P95 响应延迟 | 12.4s | 3.8s | ↓ 69.4% |
P99 响应延迟 | 22.1s | 6.1s | ↓ 72.4% |
API 调用成功率 | 94.2% | 99.87% | ↑ 5.6% |
单次请求成本 | $0.045 | $0.011 | ↓ 75.6% |
缓存命中率 | 0% | 62.3% | - |
压测发现,语义缓存在处理“查询天气”、“公司制度问答”等高频场景时表现优异,但在涉及个性化用户 ID(如“查询我的订单”)时命中率下降。我们的解决方案是:在 Prompt 预处理阶段剥离敏感变量,仅缓存意图模板,极大提升了泛化命中率。
idempotent: true,否则务必人工介入。AI 产品的工程化绝非简单的“调包调参”,而是一场涉及分布式系统、运维、数据工程与机器学习的跨领域博弈。OpenClaw 代表了开源 Agent 能力的广度,而本文分享的架构实践,则聚焦于生产环境下的深度与韧性。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。