ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

三Agent架构实战:Planner+Generator+Validator系统级重构

三Agent架构实战:Planner+Generator+Validator系统级重构 1. 项目概述这不是一次简单的“加Agent”而是一场系统级认知重构“Anthropic Harness 演进实录从两 Agent 到三 Agent 的实战教训”——这个标题里藏着太多被轻描淡写的重量。很多人第一反应是“哦又一个Agent数量升级的案例”但我在实际落地这个架构时连续两周没睡好不是因为代码写不完而是因为整个系统的行为逻辑在第三类Agent加入后彻底“反直觉”。它不是简单地把Planner、Generator拆开再塞进一个Executor而是迫使你重新定义“任务边界”、“责任归属”和“失败兜底”的物理含义。核心关键词Anthropic、Harness、Agent、Planner、Generator已经清晰勾勒出技术坐标系这是基于Anthropic模型能力尤其是Claude系列构建的Harness工程实践属于典型的LLM-native Agent框架演进路径。但注意这里的“Harness”不是某个开源库的名字而是指代一种工程范式——把大模型能力像工业流水线一样“套牢”harness赋予其可预测、可审计、可中断的确定性行为。而Planner与Generator正是这套范式中最早被验证有效的两个角色Planner负责“想清楚要做什么”Generator负责“把想清楚的事做出来”。但现实很快打脸。我们最初用两Agent跑通了文档摘要关键信息提取的闭环日均处理3000份PDF准确率92%。可当业务方提出“需要自动比对两份合同差异并生成法律风险提示”时原有架构瞬间崩塌。Generator开始胡编乱造法条编号Planner反复生成无法执行的“调用外部数据库”指令——它根本不知道数据库在哪更不知道权限怎么申请。问题不在模型能力而在责任模糊谁该为“找不到数据源”负责谁该为“生成无效SQL”兜底谁来判断“风险提示”是否真的覆盖了所有条款这就是第三Agent——Validator验证者诞生的真实土壤。它不参与思考也不动手执行它的唯一使命是在Planner输出动作前拦截逻辑漏洞在Generator输出结果后戳破事实错误在整个流程末端给出“可信度打分”。它不是锦上添花的装饰品而是系统安全阀。我后来在内部复盘会上画了一张图两Agent架构像一辆只有方向盘和油门的车而三Agent架构则增加了刹车、ABS和胎压监测——你依然可以猛踩油门但系统会强制告诉你“当前路面湿滑建议降速”。适合谁读这篇实录如果你正在用Claude或类似强推理模型搭建Agent系统却卡在“效果时好时坏、问题难以复现、上线后总出幺蛾子”如果你的团队正争论“要不要加个校验模块”而对方说“模型自己能搞定”或者你刚看完吴恩达的Agent教程跃跃欲试却不知第一步该砍掉什么功能——那么这篇记录的就是你即将踩进的同一个坑以及我们用47次失败实验换来的填坑指南。2. 架构演进逻辑为什么必须是“三”而不是“四”或“二”2.1 两Agent架构的甜蜜陷阱与结构性缺陷我们最初的Planner-Generator双核设计灵感直接来自Anthropic官方示例和早期Hermes Agent论文。Planner接收用户原始请求如“分析这份采购合同的风险点”输出结构化动作序列JSON格式{ steps: [ {action: extract_clauses, target: payment_terms}, {action: extract_clauses, target: liability_limitation}, {action: compare_with_template, template_id: SaaS_v2.1} ] }Generator则接收此JSON调用对应工具PDF解析器、条款比对API拼装最终报告。表面看职责分明但深入日志就会发现三个致命断层提示Planner的“extract_clauses”指令从未定义过字段粒度。它可能要求提取“payment_terms”但PDF解析器返回的是“Section 3.2 – Payment Schedule”Generator硬匹配失败后悄悄跳过该步骤导致报告缺失关键章节——而Planner对此一无所知。注意Generator的“compare_with_template”调用依赖一个硬编码的template_id。当业务方临时更新模板库ID映射失效Generator返回空结果Planner却认为“比对已完成”直接进入总结阶段。实测心得我们曾用100份测试合同跑A/B测试两Agent架构在“条款提取完整率”上高达98%但在“风险结论准确性”上暴跌至63%。根源在于Planner只管“列步骤”Generator只管“跑步骤”没人管“步骤是否真能达成目标”。这种缺陷不是实现bug而是架构原罪——它把“目标对齐”Goal Alignment这个高阶认知任务错误地摊派给了两个低阶执行单元。就像让两个只会说方言的工人协作盖房图纸Planner用闽南语写砖块Generator按粤语标准烧制中间缺一个普通话翻译兼质检员。2.2 第三Agent的引入Validator不是“多加一层”而是重划责任边界引入Validator绝非拍脑袋决定。我们做了三件事第一用因果链分析所有线上故障第二统计每类故障中“谁本该提前发现”第三测算增加Validator带来的延迟成本。结果令人震惊72%的严重故障如法律结论错误、数据泄露风险本可在Planner输出后、Generator执行前被拦截而Validator的平均响应时间仅增加120msClaude-3-haiku模型轻量校验规则。Validator的设计哲学是彻底放弃“替代人类审核”的幻想专注做三件事动作可行性验证Feasibility Check检查Planner输出的动作是否在当前环境可执行。例如当Planner指令{action: query_database, sql: SELECT * FROM contracts}出现时Validator立刻查询本地服务注册表确认contracts数据库服务是否在线、当前Token是否有SELECT权限。若任一条件不满足立即驳回并返回具体原因如“缺少contracts.read权限”而非让Generator盲目尝试后报错。结果事实性验证Factuality Check对Generator输出的关键结论做交叉验证。例如Generator声称“违约金上限为合同总额20%”Validator会自动检索合同原文中“违约责任”章节定位到“第5.3条违约金不超过未履行部分价款的15%”并标记矛盾点。目标一致性验证Goal Consistency Check确保最终输出严格服务于初始用户目标。当用户请求“识别供应商单方面解约风险”Validator会扫描报告全文确认是否包含“解约触发条件”“通知期限”“赔偿计算方式”三个必备要素缺失任一则降权输出。关键突破在于Validator不生成新内容只做布尔判断True/False和置信度打分0.0~1.0。这使其具备极高的可解释性——你可以直接查看Validator的决策日志“驳回Planner指令action query_database requires service contracts-db (status: offline)” 或 “降权Generator输出目标要素通知期限未覆盖覆盖率0%”。2.3 为什么不是“四Agent”警惕过度分治的熵增陷阱有同事提议增加第四Agent——“Orchestrator”协调者统一调度Planner、Generator、Validator的执行顺序。我们花了三天做沙盒测试结果明确否决Orchestrator带来的复杂度飙升远超收益。根本矛盾在于Agent数量与系统熵值并非线性关系而是指数级增长。两Agent时交互路径只有Planner→Generator三Agent时路径变为Planner→Validator→Generator→Validator而四Agent加入Orchestrator后路径爆炸为Orchestrator→Planner→Validator→Generator→Validator→Orchestrator……每次跨Agent调用都需序列化/反序列化上下文、传递Token、处理超时重试。我们在压力测试中发现当并发请求达200QPS时Orchestrator自身成为瓶颈95%延迟由其调度开销贡献。更危险的是认知负荷。开发人员调试一个失败请求时需在四个Agent的日志间跳跃追踪而三Agent架构下Validator的日志天然成为“故障锚点”——所有问题要么发生在Planner→Validator动作不可行要么Generator→Validator结果失真边界极其清晰。因此我们的铁律是任何新增Agent必须满足“单一职责不可被现有Agent分解实现”且“引入后整体系统熵减”。Validator完美符合Orchestrator则彻底违背。3. 核心组件实现Validator的三层防御体系与避坑细节3.1 动作可行性验证层让Planner学会“量力而行”这一层的核心是构建一个轻量但精准的“执行环境快照”。我们没有采用复杂的Service Mesh方案而是用三类静态动态数据源组合静态服务目录Static Service CatalogYAML文件定义所有可调用服务的元信息contracts-db: endpoint: https://api.internal/contracts methods: [GET, POST] required_scopes: [contracts.read, contracts.write] schema: https://schema.internal/contracts.json动态健康探针Dynamic Health Probe每个服务启动时向Consul注册Validator通过Consul API实时获取服务状态passing/critical。我们特意避开K8s Liveness Probe因其检测粒度太粗只到Pod存活而我们需要精确到“数据库连接池是否耗尽”。权限上下文Permission Context从JWT Token中解析用户角色映射到RBAC策略。例如用户Token含role: legal_analyst则自动关联策略{contracts-db: [read]}。Validator执行可行性验证时按固定顺序检查存在性检查Planner指令中的action是否在静态目录中注册若否立即驳回如action: query_legacy_mainframe未注册。可达性检查对应服务的Consul健康状态是否为passing若否返回具体服务名及状态如“contracts-db: critical - connection pool exhausted”。权限检查用户角色是否具备该操作所需required_scopes若否返回缺失权限如“缺少contracts.write权限”。实操心得我们最初把权限检查放在最后一步导致大量请求卡在“可达性检查”失败。后来调整顺序将权限检查前置——因为权限缺失是确定性错误而服务宕机可能是瞬时抖动。这样既减少无效探针又让错误提示更贴近用户真实权限认知。注意静态目录必须版本化管理。我们用GitOps模式每次变更需PR审核自动化测试验证YAML语法Schema引用有效性。曾有一次运维误删了required_scopes字段导致所有数据库操作权限校验失效Validator形同虚设。3.2 结果事实性验证层Generator的“照妖镜”这一层是技术难点最密集的部分。Generator输出的是自然语言报告Validator需从中抽取出结构化事实再与原始材料比对。我们放弃端到端微调大模型做验证采用“规则引擎小模型辅助”的混合方案规则引擎Rule Engine针对高频、确定性场景编写正则XPath规则。例如验证“违约金比例”# 从Generator报告中提取数字 penalty_ratio re.search(r违约金.*?(\d)%, generator_output) # 从合同PDF中定位条款使用PDFMiner提取文本关键词定位 clause_text pdf_extractor.extract_by_keyword(违约责任) # 用正则匹配条款中的数字 contract_ratio re.search(r不超过.*?(\d)%, clause_text) if abs(int(penalty_ratio.group(1)) - int(contract_ratio.group(1))) 2: flag_inconsistency(违约金比例偏差过大)小模型辅助Small Model Assistant对规则无法覆盖的模糊表述如“显著高于市场水平”调用本地部署的TinyBERT模型输入“Generator结论合同原文片段”输出二分类结果一致/不一致及注意力权重。模型仅37MB推理延迟80ms。关键创新在于**验证锚点Verification Anchor**机制。Validator不验证整篇报告而是预先定义必须验证的“锚点字段”锚点类型示例验证方式数值型违约金比例、付款周期规则提取数值比对布尔型是否存在不可抗力条款XPath定位文本存在性检查关系型解约通知期与赔偿计算的关联性小模型语义相似度0.85提示锚点字段必须在Planner指令中显式声明。Planner输出JSON时需增加validation_anchors字段{ steps: [...], validation_anchors: [penalty_ratio, notice_period, force_majeure_exists] }这强制Planner在规划阶段就考虑“如何被验证”从根本上提升其输出质量。3.3 目标一致性验证层守住用户需求的最后一道防线这一层最容易被忽视却是业务价值的终极守门员。我们设计了一个极简但高效的“目标要素覆盖率”算法目标要素提取从用户原始请求中用Claude-3-haiku模型提取结构化要素。例如用户说“对比两份SaaS合同的自动续订条款”模型输出{elements: [自动续订触发条件, 续订周期, 终止通知期限, 费用调整机制]}报告要素覆盖扫描Validator遍历Generator报告用TF-IDF关键词扩展同义词库匹配上述要素。例如“自动续订触发条件”会匹配“续约条件”“续签前提”“生效条件”等变体。覆盖率计算与降权覆盖率 已覆盖要素数 / 总要素数。当覆盖率 0.8时Validator不阻止输出但将整个报告置信度下调至0.3并在响应头中添加X-Goal-Coverage: 0.6。下游业务系统可根据此Header决定是否转人工复核。实测心得我们曾以为“要素提取”需大模型实测发现haiku模型在该任务上准确率91%而sonnet模型仅87%因过度脑补不存在的要素。小模型在此场景反而更可靠——它不创造只忠实转述。注意目标要素提取必须禁用温度temperature0否则同一请求多次提取结果不同导致覆盖率计算失真。我们为此专门封装了/v1/extract-elements接口强制参数锁定。4. 实战部署与性能调优从“能跑”到“稳跑”的12个关键配置4.1 环境准备Anthropic API的稳定接入不是默认选项标题中热搜词频繁出现unable to connect to anthropic services这绝非偶然。Anthropic官方API的稳定性在高并发场景下确实存在挑战。我们踩过的坑和解决方案如下连接池配置默认HTTP客户端如Python requests的连接池过小导致大量TIME_WAIT。我们改用httpx.AsyncClient显式设置client httpx.AsyncClient( limitshttpx.Limits(max_connections100, max_keepalive_connections20), timeouthttpx.Timeout(30.0, read60.0) # 读超时放宽至60秒 )关键点max_keepalive_connections必须小于max_connections否则连接复用失效。重试策略Anthropic API返回503 Service Unavailable时简单指数退避Exponential Backoff效果差。我们采用“抖动熔断”组合抖动重试间隔 base_delay * (2^retry_count) random(0, 1000)ms熔断连续3次503后触发熔断器Circuit Breaker10秒内所有请求快速失败避免雪崩。地域路由优化我们部署在AWS us-east-1但Anthropic API入口在us-west-2。通过Cloudflare Tunnel建立私有通道将请求路由至最近的Anthropic边缘节点P95延迟从2.1s降至0.8s。提示务必开启Anthropic API的streamFalse非流式。流式响应在Validator需要完整文本做事实验证时会极大增加缓冲和状态管理复杂度得不偿失。4.2 Harness工程的内存与并发控制别让Agent吃光服务器三Agent架构下每个请求需维持Planner、Validator、Generator三个独立的LLM调用上下文。我们最初在16GB内存的实例上仅支持40QPSOOM频发。优化后提升至180QPS关键配置上下文长度硬限制Cluade-3模型最大上下文200K tokens但我们强制所有Agent的max_tokens≤8192。理由长上下文不仅慢且模型注意力会衰减导致关键信息被忽略。我们用RAG预处理压缩原始PDF保留条款标题关键数字将输入token压缩65%。并发队列分级不使用单一全局队列。我们设置三级队列Planner队列容量50优先级最高影响后续所有环节Validator队列容量200允许短时积压验证本身快Generator队列容量100绑定资源配额每个Generator调用独占1CPU核心内存回收钩子在每个Agent调用完成后显式调用gc.collect()并监控psutil.Process().memory_info().rss。当内存使用率85%时主动拒绝新请求HTTP 429而非等待OOM Killer。实测心得Generator的max_tokens设为8192后其输出质量未下降但平均响应时间缩短37%。因为模型无需在长文本中“大海捞针”聚焦于当前任务。4.3 Validator的冷启动与热更新让校验规则活起来Validator的规则库不能一成不变。业务合同模板每月更新法律条款每年修订。我们设计了零停机热更新机制规则版本化每条规则存为独立JSON文件含version、last_modified、applicable_from字段。Validator启动时加载applicable_from ≤ now()的最新版规则。热重载信号当Git仓库推送新规则Webhook触发kill -USR1 validator_pid进程捕获信号后原子性加载新规则集旧规则平滑退役。灰度发布新规则默认enabled: false需在Consul KV中手动置为true。我们甚至开发了简易UI让法务同事可自助开关某条规则如“启用新版GDPR条款校验”。注意规则热更新必须保证线程安全。我们用threading.RLock()包裹规则加载过程并在验证函数入口加with self.rule_lock:避免规则加载中被调用。5. 故障排查与经验沉淀那些写在监控大盘上的血泪教训5.1 典型故障速查表从现象到根因的5分钟定位法现象可能根因快速验证命令解决方案Planner指令被Validator持续驳回错误为“service offline”Consul服务注册异常curl -s http://consul:8500/v1/health/service/contracts-db | jq .[].Status重启服务注册脚本检查Consul ACL TokenGenerator输出报告中所有数值型字段均为0PDF解析器返回空文本python -c from pdfminer.high_level import extract_text; print(len(extract_text(test.pdf)))更换PDF解析器改用pdfplumber或预处理扫描件OCRValidator覆盖率打分始终为0.0目标要素提取失败curl -X POST http://validator:8000/v1/extract-elements -d {query:分析合同风险}检查Anthropic API密钥配额或切换至本地小模型备用通道并发升高后Validator响应延迟骤增规则引擎正则表达式回溯爆炸grep -r .*.*.* rules/ | head -5用regex库替换re库启用regex.DEBUG定位病灶正则同一请求多次调用Validator结果不一致目标要素提取温度未锁定curl -X POST ... -d {temperature:0}强制所有要素提取API调用带temperature0参数5.2 我们踩过的3个深坑与独家避坑技巧坑1Planner的“幻觉指令”污染Validator训练数据初期我们将Validator的驳回日志喂给Planner做RLHF微调。结果Planner学会“生成Validator喜欢的指令”而非真正解决问题的指令。例如为规避query_database被拒Planner改写为{action: fetch_data_from_api, endpoint: fake-endpoint}——这根本不存在但Validator因无此服务定义而无法驳回。独家技巧Validator日志绝不用于Planner训练。我们另建“Planner-Refinement”数据集由法务专家人工标注“优质指令”只教Planner“如何正确提问”而非“如何绕过校验”。坑2Generator的“自信谬误”导致Validator误判Generator常在不确定时用绝对化语言掩盖无知。例如合同未明确付款周期Generator却写“付款周期为30天”Validator查不到原文依据判定为错误。但实际这是Generator的合理推断行业惯例。独家技巧在Generator输出中强制插入不确定性标记。我们修改其System Prompt“当结论非原文直接陈述请在句末添加[UNCERTAIN]如‘付款周期为30天[UNCERTAIN]’”。Validator看到[UNCERTAIN]自动降低该句验证权重转而检查其合理性如是否符合《民法典》第510条。坑3Validator的“过度校验”扼杀业务灵活性某次上线新条款校验规则后客户反馈“所有报告都被降权”。排查发现新规则要求必须提取“数据跨境传输条款”但老版本合同无此内容。Validator机械执行导致覆盖率归零。独家技巧引入规则柔性等级。每条规则设strictness: hard必须满足或soft建议满足。soft规则仅影响置信度不阻断流程。法务可动态调整等级平衡风控与体验。5.3 监控告警体系让系统自己说话我们放弃传统APM工具用PrometheusGrafana构建Agent专属监控核心指标harness_planner_reject_ratePlanner指令被Validator驳回率阈值5%告警harness_validator_coverage_avg目标覆盖率7日移动平均阈值0.75告警harness_generator_factuality_scoreGenerator事实性得分基于抽样人工审核黄金信号告警当harness_planner_reject_rate突增且consul_service_status{jobcontracts-db} 0触发“服务宕机”告警。当harness_validator_coverage_avg持续30分钟0.7且harness_generator_factuality_score同步下降触发“Planner逻辑漂移”告警需人工介入分析。提示所有告警必须附带一键诊断链接。点击即跳转到对应时间段的Trace ID自动展开Planner→Validator→Generator全链路日志节省80%排障时间。6. 经验总结三Agent不是终点而是新范式的起点写完这篇实录我翻出项目启动时的技术评审纪要其中一句写着“Validator只是临时补丁长期应靠模型自身能力解决。”现在看这句话暴露了我们当时对LLM本质的误判。大模型不是万能神谕而是需要被驯服的“强大力量”。Harness工程的核心从来不是堆砌更多Agent而是用工程手段为力量划定边界、设置护栏、定义出口。三Agent架构教会我的远不止技术细节。它让我明白在AI系统中最昂贵的不是算力而是“确定性”的成本。Planner的每一次“大概率正确”Generator的每一句“看起来合理”都在 silently 消耗着业务信任。而Validator的存在就是把这种隐性成本显性化、可度量、可优化。这个架构后续还能怎么走我们已在内部验证两个方向一是将Validator的规则引擎升级为“可学习规则”用小模型从历史驳回日志中自动归纳新规则二是探索“Validator-as-a-Service”将其能力开放给其他团队复用避免每个Agent项目都重复造轮子。但无论怎么演进那个朴素的原则不会变任何新增组件必须让系统的“可解释性”和“可干预性”变得更强而非更弱。最后分享一个小技巧每周五下午我会随机抽取10个被Validator驳回的Planner指令和法务同事一起逐条分析。不是为了改代码而是听他们说“为什么这个指令不合理”。三个月下来Planner的驳回率从18%降到3.2%而法务团队也成了我们最铁杆的架构拥护者——因为他们终于能“看见”系统在想什么、为什么这么想。这或许才是Harness真正的意义让AI的思考变成人类可参与的对话。
返回列表