news 2026/7/26 18:20:32

Agent 产品化的项目复盘:从技术 Demo 到可交付产品的十个关键决策

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agent 产品化的项目复盘:从技术 Demo 到可交付产品的十个关键决策

Agent 产品化的项目复盘:从技术 Demo 到可交付产品的十个关键决策

一、引言

做技术的人容易陷入一个误区:把 Demo 跑通就当成了项目完成。去年参与过一个 Agent 产品的完整交付周期,让我深刻认识到,从一段能跑的 Python 脚本到客户愿意付费的产品,中间隔着的不是代码量,而是十个需要反复权衡的工程决策。这篇文章是对那个项目的复盘,不谈算法创新,只谈落地过程中的真实取舍。

项目背景不算复杂:为一家中型企业的客服部门构建一个智能工单分派 Agent。它需要理解用户意图、匹配历史相似工单、推荐处理方案给人工坐席。技术栈上,我们用 LangChain 做 Agent 编排,FastAPI 做服务层,前端一个轻量 Vue3 面板做坐席交互。听起来很标准的 LLM 应用,但真正扎进去才发现,Demo 和产品的差异不在模型能力上,而在工程基础设施。

下面按照决策的先后顺序,逐一复盘。

二、十个关键决策的复盘

决策一:Agent 架构选型——ReAct 还是 Plan-and-Execute

Demo 阶段用 ReAct 模式跑得很流畅,推理-行动循环能处理大多数单步查询。但上了真实业务数据后,问题暴露了:一个工单分派可能需要查客户历史记录、查产品知识库、查 SLA 规则、生成推荐——这四步如果在单一 ReAct 循环里串行,延迟直接飙到 15 秒以上。

最终选了 Plan-and-Execute + ReAct 的混合模式:先用一个轻量模型做计划分解,把复杂任务拆成子任务列表,再用 ReAct 执行每个子任务,中间结果通过共享上下文传递。

# 计划生成阶段的 Prompt 模板 PLAN_PROMPT = """你是一个工单分派计划生成器。给定以下工单信息,请将处理流程分解为步骤列表。 每个步骤必须包含:步骤名称、所需工具、预期输出。 工单内容:{ticket_content} 客户历史:{customer_context} 请严格按 JSON 格式输出: [ {"step": "意图识别", "tool": "intent_classifier", "output": "intent_label"}, {"step": "历史匹配", "tool": "similarity_search", "output": "top5_tickets"}, ... ] """

这个决策的核心收益不是准确率提升,而是可观测性。计划步骤拆开后,每一步的延迟、成功率、异常都可以独立监控,出问题时能快速定位到具体阶段。

决策二:Prompt 管理——代码内嵌还是配置化

Demo 时所有 Prompt 硬编码在代码里,改一个字就要重新部署。产品化后 Prompt 迭代频率远超代码变更频率,而且不同客户可能有不同的 Prompt 变体。

方案是建一个 Prompt 管理中心,用 YAML 文件管理 Prompt 模板,支持变量注入和版本控制。

# prompts/ticket_assignment/v2.1.yaml version: "2.1" system: | 你是一个{domain}领域的工单分派助手。 当前角色:{agent_role} 处理规则: {rules} **重要**:如果置信度低于0.6,需要标记为"需人工确认"。 user_template: | 工单ID:{ticket_id} 客户等级:{customer_level} 问题描述:{description} 请完成以下步骤: 1. 识别问题类别 2. 匹配历史相似工单(至少3条) 3. 推荐处理方案

配合一个简单的 Python 加载器:

import yaml from pathlib import Path from string import Template class PromptLoader: def __init__(self, base_path: str = "prompts"): self.base = Path(base_path) self._cache = {} def load(self, name: str, version: str = "latest") -> dict: cache_key = f"{name}:{version}" if cache_key not in self._cache: file_path = self.base / name / f"{version}.yaml" if not file_path.exists(): raise FileNotFoundError(f"Prompt {name}:{version} not found") with open(file_path) as f: self._cache[cache_key] = yaml.safe_load(f) return self._cache[cache_key] def render(self, name: str, variables: dict, version: str = "latest") -> tuple[str, str]: prompt = self.load(name, version) system = Template(prompt["system"]).safe_substitute(variables) user = Template(prompt["user_template"]).safe_substitute(variables) return system, user

决策三:工具调用的可靠性保障

Agent 的灵魂是工具调用,但也是出错最多的地方。知识库检索接口偶尔超时、数据库连接池耗尽、第三方 API 限流——这些在 Demo 阶段一个 try-catch 就能兜底,但产品里必须建立系统性的容错机制。

核心策略三板斧:超时控制 + 重试退避 + 降级兜底。

import asyncio from typing import Optional, Callable, Any from functools import wraps class ToolExecutor: def __init__( self, timeout: float = 10.0, max_retries: int = 2, base_delay: float = 1.0 ): self.timeout = timeout self.max_retries = max_retries self.base_delay = base_delay async def execute( self, tool_fn: Callable, args: tuple = (), kwargs: dict = None, fallback: Any = None ) -> dict: kwargs = kwargs or {} last_error = None for attempt in range(self.max_retries + 1): try: result = await asyncio.wait_for( tool_fn(*args, **kwargs), timeout=self.timeout ) return {"status": "success", "data": result, "attempts": attempt + 1} except asyncio.TimeoutError: last_error = "timeout" except Exception as e: last_error = str(e) if attempt < self.max_retries: delay = self.base_delay * (2 ** attempt) await asyncio.sleep(delay) return { "status": "fallback", "data": fallback, "error": last_error, "attempts": self.max_retries + 1 }

决策四:上下文窗口管理

Agent 对话越长,上下文窗口消耗越大,不仅成本上升,推理质量也会下降。真实场景中,一个工单处理可能涉及 10 轮以上的交互。

采用滑动窗口 + 摘要压缩策略:

  • 保留最近 5 轮完整对话
  • 更早的交互自动压缩为摘要
  • 关键信息(客户ID、工单号、分类结果)进入结构化状态
from dataclasses import dataclass, field from typing import List @dataclass class ConversationState: ticket_id: str = "" customer_id: str = "" intent: str = "unknown" confidence: float = 0.0 resolved_step_ids: List[str] = field(default_factory=list) key_findings: List[str] = field(default_factory=list) class ContextManager: MAX_RECENT_TURNS = 5 def __init__(self, summarizer): self.summarizer = summarizer self.state = ConversationState() self.history = [] async def add_turn(self, role: str, content: str) -> None: self.history.append({"role": role, "content": content}) if len(self.history) > self.MAX_RECENT_TURNS * 2: old_turns = self.history[:-self.MAX_RECENT_TURNS * 2] summary = await self.summarizer.summarize(old_turns) self.history = [{"role": "system", "content": f"历史摘要:{summary}"}] + \ self.history[-self.MAX_RECENT_TURNS * 2:] def build_context(self) -> List[dict]: state_desc = f"当前状态:{self.state.__dict__}" return [ {"role": "system", "content": state_desc}, *self.history ]

决策五:评估体系

Demo 阶段靠"感觉"判断 Agent 好不好用,产品化后必须有量化指标。建立了三层评估体系:

  1. 工具级:每次工具调用的成功率、P50/P95 延迟
  2. 任务级:工单分类准确率、方案推荐命中率
  3. 业务级:人工坐席采纳率、处理时长缩减比例

每一层对应不同的告警阈值和优化策略。

决策六到十(简表)

考虑到篇幅,剩余五个决策以要点形式复盘:

决策核心问题最终方案关键教训
六、多租户隔离不同客户的数据和配置隔离数据库级隔离 + Prompt 模板级别隔离不要试图用代码逻辑区分租户
七、流式响应长任务必须有进度反馈SSE 推送步骤进度,前端状态机驱动WebSocket 太重,SSE 够用且运维简单
八、成本控制LLM API 费用增长不可控分级模型策略:规划用小模型、执行用大模型90% 的任务可以用小模型处理
九、权限与安全Agent 可以执行哪些操作白名单机制:工具调用前校验权限范围永远不要给 Agent 写数据库的权限
十、部署与运维如何做到零停机更新蓝绿部署 + Prompt 热加载Prompt 变更不需要重启服务

三、架构总览

整个系统的最终架构如下:

四、关键踩坑记录

坑一:ReAct 的幻觉循环。早期版本里 Agent 有时会陷入"调用工具→得到空结果→再次调用同一工具"的死循环。解法是加最大步数限制和一个简单的去重检测——连续两次相同工具调用直接中断,返回兜底方案。

坑二:Prompt 版本管理混乱。多人协作时经常发生 A 改了 Prompt、B 不知道、线上出现不一致。后来强制要求所有 Prompt 变更走 PR 流程,并且部署脚本自动比对线上版本与仓库版本的差异。

坑三:成本失控的恐慌。上线第一周,GPT-4 API 费用超出预期 3 倍。排查后发现是某些边缘 Case 触发了过长的 Agent 推理链。通过加 Token 消耗预算上限和模型降级策略,成本回归到可控范围。

五、结语

从 Demo 到产品的路,本质上是在可靠性、成本、体验三者之间找平衡。技术方案没有绝对的对错,关键在于在特定场景和资源约束下做出合适的取舍。

十个决策复盘下来,最核心的一点是:越早建立可观测性和评估体系,越能避免凭感觉做决策。数据会告诉你哪里该投入、哪里可以妥协。Agent 产品化不是技术的终点,而是工程化的起点——这一课,写在这个项目的每一个深夜调试和每一次线上事故里。

本文基于真实项目经验撰写,技术栈版本:Python 3.12 / FastAPI 0.110 / LangChain 0.1 / Vue 3.4

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/26 18:18:40

终极WeMod功能解锁指南:快速免费激活高级特性完整方案

终极WeMod功能解锁指南&#xff1a;快速免费激活高级特性完整方案 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer 想要免费解锁WeMod专业版的所有高…

作者头像 李华
网站建设 2026/7/26 18:17:24

AI绘画全链路解决方案Openclaw架构与实战

1. 项目背景与核心价值去年在数字内容创作领域&#xff0c;AI绘画工具的使用率同比增长了320%&#xff0c;但从业者普遍面临三大痛点&#xff1a;工作流碎片化、风格适配性差、批量生产效能低。我们团队开发的Openclaw系统正是针对这些行业痛点设计的全链路解决方案。这个系统的…

作者头像 李华
网站建设 2026/7/26 18:16:38

TMS320C674x浮点DSP:如何实现高精度信号处理与超低功耗的兼得?

1. 项目概述&#xff1a;当高精度信号处理遇上便携式设备在嵌入式系统设计的江湖里&#xff0c;一直有个看似无解的“鱼与熊掌”难题&#xff1a;高精度计算和超低功耗。你要么选一个性能强劲但功耗感人、需要风扇伺候的大家伙&#xff0c;要么选一个省电但算力捉襟见肘的微控制…

作者头像 李华
网站建设 2026/7/26 18:16:07

ZLUDA完全指南:打破NVIDIA垄断,让AMD显卡畅享CUDA生态

ZLUDA完全指南&#xff1a;打破NVIDIA垄断&#xff0c;让AMD显卡畅享CUDA生态 【免费下载链接】ZLUDA CUDA on non-NVIDIA GPUs 项目地址: https://gitcode.com/GitHub_Trending/zl/ZLUDA 还在为昂贵的NVIDIA显卡发愁吗&#xff1f;想要在AMD显卡上运行CUDA应用却苦于兼…

作者头像 李华
网站建设 2026/7/26 18:13:32

CrewAI深度解析:揭秘多智能体协作框架的架构设计与实战应用

CrewAI深度解析&#xff1a;揭秘多智能体协作框架的架构设计与实战应用 【免费下载链接】crewAI Framework for orchestrating role-playing, autonomous AI agents. By fostering collaborative intelligence, CrewAI empowers agents to work together seamlessly, tackling …

作者头像 李华
网站建设 2026/7/26 18:12:38

5分钟掌握QRazyBox:免费开源的二维码修复终极指南

5分钟掌握QRazyBox&#xff1a;免费开源的二维码修复终极指南 【免费下载链接】qrazybox QR Code Analysis and Recovery Toolkit 项目地址: https://gitcode.com/gh_mirrors/qr/qrazybox 你是否曾经遇到过这样的情况&#xff1a;一张重要的二维码因为打印模糊、手机拍摄…

作者头像 李华