拓冰建站拓冰建站
首页 / 资讯中心 / 正文

面试官:“gather报错全停?”我:“分支照跑”

asyncio.gather默认遇到首个异常时会把异常传播给等待它的任务但其他 awaitable 不会因此自动取消仍会继续运行。把它理解成“立刻终止所有子任务”会直接带偏失败策略。这不是一个可以忽略的并发细节。并行检索时一个分支失败后其他分支究竟继续、取消还是降级必须由业务规则决定不能靠误读并发库。为了把边界跑清楚后面会用一个只依赖 Python 标准库的小例子逐步验证。为什么并行不等于 Supervisor先把两个概念拆开。Fan-out 是把一个任务展开成多个可并行分支fan-in 是等待分支到达后合并结果。只要子任务、依赖和合并条件能够提前写清用普通工作流和并发库就能完成不需要让大模型扮演 Supervisor。Supervisor 解决的是运行前无法穷举的语义决策。例如初次检索发现一个新实体需要临时追加调查两份证据冲突需要决定请哪个专业角色复核剩余预算不足需要在几个合法动作里选一个。它可以负责选择下一步但不应该越过权限、预算、最大轮次和完成门禁。如果把“有多个 Agent”“使用并发”“存在 Supervisor”画成等号中央 Agent 就会同时拆任务、保存全部上下文、判断完成、处理错误和写报告。结果只是把一个大 Agent 换了名字。更稳的边界是确定性依赖写成图分支状态写进结构化 State代码处理超时、权限、预算和幂等只有多个合法下一步需要语义判断时才调用受限 Supervisor。例如“同时查订单、政策和物流三路结束后合并”在运行前已经知道分支与依赖用代码 fan-out 就够了。“政策里出现一个此前未知的产品名称要不要追加产品专家”才可能需要 Supervisor。判断标准很具体下一步能不能由稳定字段和规则决定。任务听起来复杂并不能自动推出需要 Supervisor。Supervisor 的派发结果也不能只是一段话。至少要输出目标角色、子目标、输入工件引用、期望 Schema、理由和剩余预算再由代码检查角色是否存在、权限是否允许、任务是否重复。模型负责提出合法选择编排层负责守边界。Fan-out、fan-in 与 Supervisor 是三件不同的事失败策略先看子任务是否关键“一个子 Agent 失败不能影响整体”同样不是普遍原则。如果失败的是补充背景资料主证据已经齐全系统可以带着缺口继续状态应标成degraded不能假装完整成功。如果失败的是回答必需的政策版本、订单事实或权限校验继续生成只会把缺证据包装成答案此时应该阻断。因此每个分支在派发前至少要写清五件事稳定的分支 ID、是否必需、输入版本、期望输出 Schema、失败后的允许动作。fan-in 节点要检查必需工件是否有效、可选工件缺了哪些、有没有未解决冲突“几个任务结束了”远远不够。并发原语也要按这条规则选。需要收集所有分支结果并自行分类时可以让每个分支把异常转换成结构化失败再用gather汇总。只要一个必需分支失败就必须终止同组任务时可以考虑TaskGroup的 fail-fast 语义。Python 官方文档说明TaskGroup 中首个非取消异常会取消其余任务并等待它们结束。外部取消要继续传播。CancelledError用于通知协程停止清理资源应放在finally不要把取消吞掉再返回“成功”。重试也只适合临时网络错误并且要有上限带写操作的 Worker 在重试前先查幂等键不能重复扣款、发信或写两份报告。失败最好先分类再决定动作。临时超时可以在总预算内重试输入缺字段属于确定性错误重复执行没有意义资料里本来就没有答案属于业务缺口应该澄清或拒绝写接口超时后状态不确定则先凭幂等键查询执行结果不能盲目重放。把四类失败都写成retry只会让系统更慢也更难审计。取消范围同样要明确。用户终止整个任务时父任务应向仍在运行的只读分支传播取消某个可选分支超时不代表必需分支也要取消已经发出的副作用不能只靠取消协程来回滚。这里的决定属于业务事务边界不属于 Supervisor 的临场发挥。把分支结果写成统一协议下面的代码只用 Python 标准库。任务有三个分支订单事实和政策条款是必需项行业新闻是可选项。每个分支都把结果归一成同一个结构fan-in 再决定阻断还是降级。import asyncio from dataclasses import dataclass dataclass class Result: name: str required: bool ok: bool value: str error: str async def worker(name, delay, required, failFalse): await asyncio.sleep(delay) if fail: raise RuntimeError(f{name} failed) return Result(name, required, True, valuef{name}:evidence) async def safe_run(name, delay, required, failFalse): try: return await worker(name, delay, required, fail) except Exception as exc: return Result(name, required, False, errorstr(exc)) async def run_case(required_fails): results await asyncio.gather( safe_run(order, 0.01, True), safe_run(policy, 0.02, True, required_fails), safe_run(news, 0.03, False, True), ) blockers [r.name for r in results if r.required and not r.ok] gaps [r.name for r in results if not r.required and not r.ok] if blockers: return fBLOCK:{,.join(blockers)} if gaps: return fDEGRADED:{,.join(gaps)} return READY async def main(): print(await run_case(False)) print(await run_case(True)) asyncio.run(main())实际运行输出是DEGRADED:news BLOCK:policy第一轮只有可选新闻失败所以系统可以继续但必须暴露缺口。第二轮政策条款失败即使订单事实成功也不能进入报告生成。代码里没有直接使用return_exceptionsTrue而是在safe_run中把普通异常转换成统一的Result。这样异常、必需性和分支名在同一条记录里fan-in 不必再靠列表位置猜是谁失败。gather仍会按传入 awaitable 的顺序返回结果但真实系统最好继续使用稳定分支 ID因为分支数量可能动态变化。还要注意safe_run捕获的是Exception不会把 Python 当前继承自BaseException的CancelledError当成普通失败吃掉。这正是我们想要的业务失败可以进入结果表外部取消继续向上传播。若 Worker 持有文件、连接或锁再用try/finally做清理。这个例子刻意没有写固定重试次数和超时时间。它们取决于服务 SLO、剩余总预算和故障类型。真正应该固定的是状态含义与退出条件而不是从别人的示例抄一个数字。必需分支失败要阻断可选分支失败可降级结果冲突应该怎么合并多个 Worker 返回自然语言长文最后再让 Writer “自行消除冲突”是最危险的合并方式。Writer 很可能选一段更顺耳的说法把分歧悄悄抹掉。我做吴师兄大模型训练营也更希望大家先把必需分支、可选分支和冲突状态写进协议再让 Supervisor 参与语义决策。分支输出应先变成证据记录至少包含 claim、来源、观测时间、数据版本、置信状态和工件 ID。合并节点先按工件 ID 去重再检查同一 claim 是否出现值冲突、时间冲突或来源冲突。没有规则能自动裁定时状态应保留为conflict交给补证或人工确认不能让 LLM 投票。比如一个分支说“订单已退款”来源是三天前的客服摘要另一个分支说“订单仍在处理中”来源是刚读取的交易状态。合并节点不能因为第一段文字更完整就采用它而要比较 claim 类型、观测时间和事实系统。若两条来源本来描述不同时间点它们未必矛盾若时间相同却值不同才进入冲突状态。先做这层结构化判断Writer 才能准确写出限制。也不要写死“数据库永远比新闻可靠”之类的万能优先级。财务报表可能更适合证明历史金额交易系统更适合证明当前状态监管公告更适合证明规则。优先级应绑定 claim 类型、来源版本和时效而不是绑定 Agent 名字。fan-in 还要防迟到结果覆盖新状态。每次派发带任务 ID、分支 ID 和输入版本Worker 返回时校验版本重复结果通过幂等键去重。若用户已经取消任务迟到的写操作不能重新把状态改成完成。最后完成也要由门禁判断。所有协程结束只代表计算停止不代表任务完成。必需工件齐全、Schema 校验通过、冲突已解决或被明确保留、副作用有执行凭证才可以进入completed。让 Supervisor 自己说“已经完成”与让 Worker 自己给作业打满分没有区别。所以多 Agent 设计要回答五个更硬的问题“有几个角色”反倒最不重要谁能并行谁是必需失败后谁取消结果怎样合并重复与迟到怎样挡住。这五件事能由代码和状态说明白Supervisor 才是受控的调度者说明不白它只是一个更难排查的单 Agent。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门