蓝耘智能路由结合RPA:混合工单数据的模型自动分发实践
我最近在调一个自动化工单处理的RPA流程每天要跑的数据量不算大30条左右但恰恰是这个量级把我折腾得不轻。原因很简单这30条工单里有的是简短问答有的是报错日志有的是需要摘要的长文还有几条甚至夹着代码片段。如果用同一个模型硬跑要么简单任务浪费算力要么复杂任务质量崩盘如果手动给每条数据指定模型处理完这批数据人都要麻了。后来我换成了“蓝耘智能路由”来做模型分发RPA脚本本身只有一套循环处理30条数据但每一条请求发出后由路由层决定这条数据交给哪个模型推理。脚本的业务代码几乎没动唯一的变化是请求体里多了一个路由字段。整批数据跑完后我统计了一下30条请求全部成功模型分配也确实做到了“按需切换”。这篇文章就把这个方案的选型逻辑、接入方式和踩过的坑完整记录下来给打算用“智能路由 RPA”处理批量数据的同学一个参考。1. 批量小数据也有模型选择困难为什么30条工单比3000条更麻烦先说结论数据量小不等于问题小恰恰因为只有30条每条数据的“个性”才更突出。3000条同质化数据可以用统计规律做批量调优30条混合数据没有这种容错空间每一条都值得单独关心。1.1 30条数据里藏着四种任务单一模型撑不住我手里这批模拟工单大致分成四类数据类型典型内容模型要求客服问答发货时间、退换货政策轻量模型即可快而便宜代码/报错带堆栈的异常日志、Python函数片段需要代码理解能力轻量模型经常胡说长文总结800字以上的投诉说明、会议纪需要长上下文与归纳能力翻译请求中英混杂、需要规范化表达需要语言功底如果全部走轻量模型客服问答没问题但代码片段基本没法看长文总结抓不住重点。如果全部走高能力模型质量是上去了可每条请求都按高性能模型计费成本明显偏高。最要命的是延迟高性能模型处理简单问答的响应时间比轻量模型慢好几倍30条数据跑完要多等不少时间。这个场景的关键不是“能不能处理”而是“值不值”。单条数据的复杂度差异极大流量又是手动可见的30条正好适合用“路由”来做模型分诊而不是用一把锤子钉所有钉子。1.2 在RPA脚本里写if/else选模型为什么是反模式第一反应最容易想到的解法是在RPA脚本里写判断if Traceback in text or def in text: model code-model elif len(text) 800: model long-text-model else: model light-model这种“看着很直接”的方案实际维护起来非常难受。第一判断条件会和真实的业务数据耦合——一旦出现新的数据类型比如用户上传了JSON配置你就得再加一条分支第二这些分支逻辑藏在脚本深处改模型名称、调阈值都要重新走一遍RPA的发布流程第三多分支脚本很难测试你没法快速确认“同一份数据在不同路由判断下到底走的哪条路径”。正确的做法是把“选模型”这个决策从RPA脚本中剥离出去交给路由层。RPA脚本只负责循环、发请求、拿结果路由层根据请求内容智能分发。这正是“同一个脚本自动切换模型”的本质——切换逻辑不在脚本里而在请求和目标模型之间的那个“智能中间层”。2. 蓝耘智能路由的分诊机制规则命中、特征打分和自动降级路由层要解决的核心问题是替调用方回答“这条请求应该给谁”。蓝耘智能路由内部做的事情我理解下来分成三个层级规则命中、特征打分、自动降级。下面分别展开。2.1 分诊第一层规则命中让代码去该去的模型第一层是规则引擎它靠关键词、正则表达式和数据格式识别来匹配请求。比如我在实际测试中发现当输入文本里有def、import、Traceback、Exception这类特征时路由会直接命中“代码专项”规则把请求分配给代码理解能力更强的模型。这种硬规则的好处是确定性高、速度快适合特征明显的请求。我做过一组判定示例路由层的匹配逻辑大致如下请求特征判定方式路由结果包含Traceback或def代码特征正则代码专项模型包含“翻译成英文”等指令关键词词典语言处理模型文本长度超过2000字符长度规则长文本模型全文是简短问句长度 关键词规则轻量通用模型具体到我的RPA脚本来自工单的报错日志带有File xxx.py, line N的格式正好命中正则路由直接指向代码模型省去了特征打分的过程。这一层主要解决“一看就知道该去哪”的请求。2.2 分诊第二层特征打分给“说不清类别”的请求定档规则没有命中的请求比如一段普通的客诉文本、一篇混合中英文的说明往往没有太强的关键词特征。这时候路由层会给请求做特征打分。打分项主要是文本长度、语言复杂度、是否存在结构化内容、任务语义与模型能力的匹配度。打分逻辑可以类比成医院的分诊护士不发烧不咳嗽的普通问诊去普通门诊高烧加胸痛就得去专科。路由层的打分器给每个特征一个权重汇总后得出一个“复杂度档位”再把请求分到对应能力的模型。比如低于40走轻量模型40到70走长文本模型高于70走高能力模型。这个阈值在蓝耘的路由策略里是可以调整的后面第三章我会给出一个简化配置示例。我第一次看到这个设计时有点疑虑打分逻辑靠谱吗会不会把简单问答误判成复杂任务实际跑下来发现30条数据的判定结果基本符合预期。原因是打分规则是显式的不是黑盒模型只要特征权重设置合理结果有迹可循。尤其对中小批量数据来说这种“可解释路由”比端到端训练的复杂模型更实用。2.3 自动降级与兜底主模型翻车时的处理顺序路由层还有一条后路自动降级。它会在主模型超时、返回异常或触发配额限制时按预设的回退顺序切换到备用模型。我在配置里给的回退顺序是先切到CPU占用更低、响应更稳的模型再切到通用模型保证请求最终有结果。这是很多人容易忽略的部分。单模型API调用时失败了可以直接报错让RPA重跑但多模型场景下路由层可以在内部完成重试调用方完全无感知。蓝耘智能路由的响应里会记录“是否发生过降级”我在日志里能看到某条数据实际用了哪个模型以及是否走了备用路径。这种透明机制对排查问题非常重要。3. RPA脚本接入请求层加一个字段业务代码零感知接入过程比我想象中简单。我原以为要在RPA脚本里引入SDK、配置客户端、处理鉴权实际上只要把原来的模型调用地址换成蓝耘统一入口请求体里加一个model_route字段就行。下面是我在模拟项目X里实际用的简化示例。3.1 最小改动示例一个HTTP请求多一个 route 字段RPA脚本的核心是循环读取30条数据然后调用模型推理。我用Python示例展示其他语言逻辑相同import requests ROUTE_URL https://router.example/v1/chat ROUTE_KEY ${ROUTE_API_KEY} # 从环境变量读取不要硬编码 def ask_model(user_text: str) - tuple[str, str]: resp requests.post( ROUTE_URL, headers{Authorization: fBearer {ROUTE_KEY}}, json{ model_route: auto, messages: [{role: user, content: user_text}], temperature: 0.3, }, timeout30, ) data resp.json() choices data[choices][0][message][content] routed_model data.get(model_routed, unknown) return choices, routed_model # RPA 主流程循环处理30条数据 for record in batch_data: reply, route ask_model(record[content]) log_result(record[id], route, reply)和前一套写死的方案相比改动只有两个地方一是URL换成了统一路由入口二是请求体里多了model_route: auto。“auto”的含义是让路由层根据内容自动决定用什么模型你也可以显式指定model_route: code-model或model_route: long-text-model跳过路由判断。如果你用的RPA平台不支持Python脚本而是拖拽式组件也没关系——大多数RPA工具的“HTTP请求”组件都能在JSON请求体里手动加字段无非是把上面这段逻辑拆成“构造请求体 → 发送请求 → 解析返回JSON”三步。3.2 响应里的 model_routed 字段把路由决策透明化这个字段我非常喜欢。普通模型API的响应只会告诉你“推理结果”不会告诉你“这个结果是由哪套模型逻辑产出的”。蓝耘的响应里多了一个model_routed它把路由决策直接暴露给调用方。这意味着处理完30条数据后我可以清楚地知道每一条实际用了什么模型。哪些走了轻量模型、哪些走了长文本模型一清二楚。万一某条数据处理结果质量很差我能沿着日志回查“哦这条因为文本短被判成了轻量档。”这种透明度在对接RPA时太重要了——脚本无感知切换模型不代表人不可以感知。3.3 为什么要这样设计模型版本更新与RPA脚本解耦接入之前我一直在想一个问题模型服务商升级模型、调整价格、下线旧版本会不会导致RPA脚本又要跟着改答案是蓝耘这种路由设计恰好解决了这个痛点。路由策略在服务端维护不在RPA脚本里维护。模型A被替换成新版本、某类请求判定阈值调整、回退顺序变化这些都是路由层的配置更新。RPA脚本里的循环逻辑和请求字段完全不用动。这也是“同一个脚本自动切换模型”这句话真正的价值业务循环无感知模型调度端自适应。这里我补充一个配置示例展示路由策略可以按需求调{ route_policy: { default: auto, fallback_order: [code-model, long-text-model, light-model], timeout_ms: 15000, score_threshold: { light_max: 40, longtext_min: 40, longtext_max: 70, high_min: 70 } } }阈值调整会影响分诊结果但RPA侧无需任何改动。我实际测试中对部分长文本工单把longtext_max从70调到65发现更多中等长度文本被分流到轻量模型整体耗时下降个别复杂文本质量略有波动。这种策略调优只能靠真实数据反复验证不能拍脑袋。4. 30条混合数据的路由实测四类任务的模型分配与耗时表现接入完成后我用一批30条的模拟工单数据做了完整验证。这里把数据和结果整理出来方便你对照参考。需要说明的是数据量和耗时只代表我这次的测试环境不能当成标准基线但足以观察路由判定的稳定性。4.1 30条数据的构成与路由结果这批数据我刻意混了类型模拟真实的工单池类别条数实际路由模型平均响应时间质量评估客服问答14轻量通用模型0.4s回答完整无明显错误代码/报错6代码专项模型3.1s能定位报错根因建议可用长文总结7长文本模型5.8s摘要结构清晰重点保留多语言翻译3语言处理模型1.2s表达自然无夹生翻译整批数据总耗时大约3分半30条全部成功没有超时和降级。从结果看路由分诊符合预期高复杂度任务全部分到了对应的高能力模型低复杂度任务没有浪费计算资源。如果你也打算做同样验证建议先在脚本里记录每条数据的 length字符数、是否命中关键词、耗时、model_routed 四个字段然后按模型分组统计。这样可以看到路由决策是否符合你的业务预期而不是只能凭感觉判断。4.2 两条典型数据的完整处理记录挑两条有代表性的数据展示路由决策的过程。第一条数据是工单里的报错日志内容包含File batch_job.py, line 42, in process和KeyError: order_id。路由层通过正则命中“代码特征”→分配代码专项模型。最终返回的结果给出了完整的修复建议质量远超我把这条数据丢给轻量模型的答案。第二条数据是一段860字的中文投诉文本内容是对配送服务的多段描述没有明显的代码或翻译特征。路由层经过特征打分len860 超过阈值综合评分落在“长文本档”分配到长文本模型。返回的摘要把投诉核心、时间线、诉求点拆得很清楚没有漏关键信息。这两条记录说明一个规律路由判定基于可解释的特征而不是玄学。只要你能预判某类数据该去哪个模型就能通过调整规则和阈值让路由行为与预期一致。5. 多模型自动切换最容易踩的五个坑从超时误杀到账目不清方案跑通只是第一步真正花时间的其实是排错。这套“路由 RPA”的组合在落地过程中我踩了下面几个坑每一个都在文档里找不到现成答案。5.1 超时设置太短高性能模型被“误杀”刚开始我在RPA脚本里给所有请求设了统一的5秒超时。实测后发现代码模型处理复杂请求时经常需要10秒以上导致明明路由已经选对了模型却因为客户端提前断开而失败。更麻烦的是RPA遇到超时会重试重试请求又会被路由层当作新请求处理造成重复调用。解决办法是给路由请求设置更宽的超时上限比如30秒并把超时逻辑放在路由层而不是RPA脚本层。蓝耘支持在路由策略里配timeout_ms让路由层根据模型档位动态设置超时。主模型超过设定时间后路由层内部先做降级再返回结果RPA只感知到一次完整请求。5.2 轻量模型额度也不高并发限制与429处理有一个反直觉的点轻量模型虽然价格便宜但很多服务对单key的并发数限制反而更严因为大家都觉得它便宜都往那边打。我处理30条数据时没有做并发是一条一条串行跑的结果中途还是遇到了429限流。解决方案是在RPA脚本里加重试逻辑最好带指数退避import time def ask_model_with_retry(text, max_retries3): for attempt in range(max_retries): try: return ask_model(text) except requests.exceptions.HTTPError as err: if err.response.status_code 429 and attempt max_retries - 1: time.sleep(2 ** attempt) continue raise虽然30条数据量不大但多模型混合路由下的限流行为更像是“多个独立API的聚合”不能按单一API的配额经验来预估重试机制是必须的。5.3 路由日志不落盘事后只能靠猜接入初期我没有记录每条数据的路由结果只记录了最终回答。后来遇到一条长文总结质量不佳我想复盘它走了哪个模型发现完全没有依据。重新翻RPA运行日志也只能看到“调用成功”看不到模型分配信息。现在我的RPA流程里会强制落一个路由审计表数据ID、字符长度、命中规则、特征分、实际路由模型、是否降级、耗时。跑完30条后我一查表就能定位问题。这个习惯强烈建议从一开始就养成不要等出了问题再补。5.4 脱敏顺序别搞反路由层也经手你的数据RPA处理的工单数据有时包含手机号、身份证号等敏感信息。路由层本身会读取请求内容来做判断和转发所以数据送到路由层之前脱敏就要完成而不是等返回结果后再处理。顺序一旦反了敏感信息就会在路由日志里留下痕迹。我在模拟项目里对涉及个人信息文本的处理是先把手机号替换为占位符再发给路由层import re def mask_pii(text: str) - str: text re.sub(r1[3-9]\d{9}, [手机号], text) text re.sub(r\d{17}[\dXx], [证件号], text) return text这一步要加在RPA调用模型之前不能在拿到响应后才做。如果你处理的不是敏感数据可以忽略但只要有涉及顺序错了就不好补救了。5.5 重跑任务要幂等避免重复调用重复计费RPA任务有个特点失败重跑很常见。如果请求没有幂等机制一次失败重跑可能造成同一份数据被重复调多次计费跟着翻倍。给请求加幂等键是最直接的方案。我在每次请求时带一个X-Request-ID值为“任务批次号 数据ID”的组合。路由层收到重复的请求ID时可以识别重试避免重复计费。这个字段在模型直接调用场景里不常用但“路由 RPA”这种多次重跑的组合里非常有必要。我在实际跑完这批数据后会把每次请求的model_routed和时间戳单独拉出来按模型分组统计一眼就能看出哪些类型的工单主要消耗了哪个模型、平均时延如何。这个统计小习惯比任何监控面板都更贴合中小批量RPA任务的调优场景推荐你也试试。