合:30條數(shù)據(jù)批量處理的自動化實踐)
1. 從30條數(shù)據(jù)的批量處理說起為什么需要智能路由手里有一批數(shù)據(jù)要處理30條說多不多說少不少。如果純手工一條條跑半小時就沒了而且中間還得盯著萬一某條數(shù)據(jù)觸發(fā)了模型的限流或者響應(yīng)超時整條流水線就卡在那里。這種場景在RPA機器人流程自動化的實際落地中太常見了——數(shù)據(jù)量不大但重復性極高人工做純屬浪費生命。我最初的做法很樸素寫一個Python腳本循環(huán)30次每次調(diào)用同一個模型接口拿到結(jié)果寫回表格。跑通之后確實省事了但問題很快暴露出來。同一個模型連續(xù)調(diào)用30次有時候會遇到響應(yīng)變慢、偶爾報錯的情況尤其是當這30條數(shù)據(jù)的類型差異比較大的時候——有的適合通用模型有的需要更強的推理能力有的只是簡單的文本清洗。用一個模型硬扛所有任務(wù)就像拿一把錘子擰所有螺絲能擰但效率和質(zhì)量都打折扣。這時候“智能路由”的概念就派上用場了。所謂智能路由核心思路是根據(jù)每條數(shù)據(jù)的特征動態(tài)選擇最合適的模型來處理。比如短文本分類用輕量模型就夠了長文本摘要可能需要上下文窗口更大的模型涉及邏輯推理的任務(wù)則要路由到推理能力更強的模型上。藍耘智能路由提供的正是這種能力——它對外暴露一個統(tǒng)一的調(diào)用入口內(nèi)部根據(jù)你設(shè)定的策略自動分發(fā)請求到不同的模型后端。把這套機制和RPA結(jié)合起來價值就很明顯了。RPA負責“手”的部分——打開表格、讀取數(shù)據(jù)、寫入結(jié)果、處理異常彈窗智能路由負責“腦”的部分——判斷每條數(shù)據(jù)該用哪個模型、自動切換、失敗重試。兩者配合30條數(shù)據(jù)的處理就從一個脆弱的單模型循環(huán)變成了一個有彈性、有冗余的自動化流水線。這篇文章適合兩類人看一類是已經(jīng)在用RPA做業(yè)務(wù)流程自動化但遇到模型調(diào)用瓶頸的從業(yè)者另一類是想了解智能路由在實際項目中怎么落地、怎么和腳本配合的技術(shù)人員。我會把整個方案的搭建過程、關(guān)鍵決策點、踩過的坑都攤開來講代碼和配置直接給到能跑的程度。2. 藍耘智能路由的接入方式與模型切換邏輯2.1 統(tǒng)一入口背后的路由策略配置藍耘智能路由最核心的價值在于它把多個模型的調(diào)用統(tǒng)一成了一個入口。你不需要在代碼里維護一堆不同廠商的SDK和API Key只需要面向一個端點發(fā)請求路由層幫你做分發(fā)。這個設(shè)計思路和API網(wǎng)關(guān)很像但多了“智能”的部分——它不只是轉(zhuǎn)發(fā)還會根據(jù)你配置的策略做決策。路由策略的配置通常有幾種維度。第一種是按任務(wù)類型路由比如你在請求里帶一個task_type字段路由層根據(jù)這個字段映射到對應(yīng)的模型。第二種是按數(shù)據(jù)特征路由比如根據(jù)輸入文本的長度、語言、是否包含代碼塊等特征自動判斷。第三種是按優(yōu)先級和成本路由比如優(yōu)先走便宜的模型失敗或置信度低時再升級到更強的模型。我在這個項目里用的是第一種和第二種的結(jié)合。30條數(shù)據(jù)里我預先給每條打了一個簡單的標簽——simple、standard、complex。simple走輕量模型standard走通用模型complex走推理增強模型。這個標簽可以手工標注也可以用規(guī)則自動生成比如文本長度超過500字且包含“分析”“推理”等關(guān)鍵詞的就標為complex。配置大概長這樣routing: rules: - match: task_type: simple target: model-lite - match: task_type: standard target: model-general - match: task_type: complex target: model-reasoning fallback: model-general retry: max_attempts: 3 backoff: exponential這個配置文件放在路由層的管理界面或者通過API下發(fā)都可以。關(guān)鍵是fallback字段——當主模型不可用時自動降級到備用模型保證流水線不中斷。retry部分定義了重試策略指數(shù)退避意味著第一次失敗等1秒第二次等2秒第三次等4秒避免短時間內(nèi)反復沖擊同一個后端。2.2 在Python腳本中調(diào)用路由接口的完整寫法配置好路由策略之后Python腳本這邊其實很簡單。你只需要把請求發(fā)到路由層的統(tǒng)一端點帶上必要的元數(shù)據(jù)剩下的交給路由層處理。下面是我實際用的調(diào)用封裝import requests import time import json ROUTER_ENDPOINT https://api.lanyun-router.example.com/v1/chat/completions API_KEY your-api-key-here def call_with_routing(prompt, task_typestandard, max_retries3): headers { Authorization: fBearer {API_KEY}, Content-Type: application/json } payload { messages: [{role: user, content: prompt}], task_type: task_type, routing_strategy: auto } for attempt in range(max_retries): try: resp requests.post( ROUTER_ENDPOINT, headersheaders, jsonpayload, timeout60 ) if resp.status_code 200: data resp.json() return { success: True, content: data[choices][0][message][content], model_used: data.get(model, unknown), attempts: attempt 1 } else: print(f請求失敗狀態(tài)碼 {resp.status_code}第 {attempt1} 次嘗試) except requests.exceptions.Timeout: print(f請求超時第 {attempt1} 次嘗試) except requests.exceptions.RequestException as e: print(f請求異常{e}第 {attempt1} 次嘗試) if attempt max_retries - 1: wait 2 ** attempt time.sleep(wait) return {success: False, content: None, model_used: None, attempts: max_retries}這段代碼有幾個細節(jié)值得說。task_type字段是路由層做決策的依據(jù)你傳什么值取決于你在路由策略里怎么定義的。routing_strategy設(shè)為auto表示讓路由層自己判斷如果你有明確的偏好可以改成具體策略名。超時設(shè)了60秒因為有些復雜任務(wù)確實需要更長的處理時間設(shè)太短會導致不必要的重試。返回值里我特意帶了model_used字段這樣在后續(xù)分析時能知道每條數(shù)據(jù)實際走了哪個模型。這個信息在調(diào)試和優(yōu)化階段非常有用——如果發(fā)現(xiàn)某類數(shù)據(jù)總是被路由到不合適的模型上就可以回頭調(diào)整路由規(guī)則。2.3 模型自動切換的觸發(fā)條件與降級機制自動切換模型這件事聽起來很智能但實際落地時你需要明確“什么時候切”。我在項目里定義了三種觸發(fā)條件。第一種是顯式路由就是前面說的根據(jù)task_type字段直接指定。這是最可控的方式適合你對數(shù)據(jù)特征有清晰認知的場景。第二種是失敗降級。當主模型返回錯誤碼比如429限流、503服務(wù)不可用或者超時路由層自動把請求轉(zhuǎn)發(fā)到備用模型。這個切換對調(diào)用方是透明的腳本層面不需要做額外處理只需要在重試邏輯里等待路由層返回結(jié)果。第三種是質(zhì)量降級。這個稍微復雜一些——當模型返回的內(nèi)容置信度低于閾值或者格式不符合預期比如要求返回JSON但返回了純文本路由層可以自動升級到更強的模型重新處理。這個機制需要你在路由層配置質(zhì)量校驗規(guī)則比如用正則表達式檢查返回格式或者用一個輕量分類器判斷返回內(nèi)容是否合格。注意質(zhì)量降級會帶來額外的調(diào)用成本和時間開銷建議只在關(guān)鍵任務(wù)上啟用。對于30條數(shù)據(jù)這種小批量場景我一般只開前兩種第三種留給對準確性要求極高的場景。降級鏈的設(shè)計也有講究。我通常配三級主模型 → 同級別備用模型 → 降級模型。比如complex任務(wù)的主模型是推理增強版?zhèn)溆檬峭瑥S商的通用版最后兜底是輕量版。這樣即使推理增強版整體不可用任務(wù)也不會完全失敗只是質(zhì)量可能略有下降。3. RPA與腳本的配合30條數(shù)據(jù)流水線的搭建過程3.1 數(shù)據(jù)讀取、任務(wù)分發(fā)與結(jié)果回寫的分工RPA和Python腳本在這個方案里的分工需要提前想清楚否則很容易出現(xiàn)“兩邊都在做同一件事”的混亂。我的劃分原則是RPA負責所有和界面、文件、系統(tǒng)交互的操作Python腳本負責所有和模型調(diào)用、數(shù)據(jù)處理相關(guān)的邏輯。具體到30條數(shù)據(jù)的場景RPA做這幾件事打開Excel或數(shù)據(jù)庫客戶端讀取30條待處理數(shù)據(jù)把數(shù)據(jù)傳遞給Python腳本可以通過命令行參數(shù)、臨時文件或消息隊列等待腳本處理完成然后把結(jié)果寫回表格的對應(yīng)列最后關(guān)閉應(yīng)用或保存文件。Python腳本做這幾件事接收RPA傳來的數(shù)據(jù)根據(jù)預設(shè)規(guī)則給每條數(shù)據(jù)打task_type標簽調(diào)用藍耘智能路由接口處理返回結(jié)果把結(jié)果整理成RPA能識別的格式返回。這種分工的好處是職責清晰。RPA工具比如影刀RPA擅長的是界面操作和流程編排它的Python集成能力雖然不錯但如果你把復雜的模型調(diào)用邏輯全塞進RPA的腳本節(jié)點里調(diào)試和維護都會很痛苦。反過來Python腳本擅長數(shù)據(jù)處理和API調(diào)用但讓它去操作Excel界面或者處理彈窗那就是自找麻煩。實際搭建時我用的是“RPA調(diào)用Python腳本 臨時JSON文件交換數(shù)據(jù)”的方式。RPA把30條數(shù)據(jù)寫到一個input.json文件里然后執(zhí)行python process.py --input input.json --output output.json腳本跑完后RPA讀取output.json把結(jié)果逐條寫回表格。這個方式比命令行傳參更穩(wěn)定因為30條數(shù)據(jù)序列化后體積不小直接傳參容易遇到長度限制或轉(zhuǎn)義問題。3.2 用Python處理批量數(shù)據(jù)的核心循環(huán)與異常捕獲腳本這邊的核心邏輯是一個循環(huán)但循環(huán)里要做的事情比想象中多。下面是我實際用的處理流程import json import sys import argparse from concurrent.futures import ThreadPoolExecutor, as_completed def classify_task(item): text item.get(content, ) if len(text) 100: return simple elif any(kw in text for kw in [分析, 推理, 對比, 評估]): return complex else: return standard def process_single(item): task_type classify_task(item) prompt build_prompt(item, task_type) result call_with_routing(prompt, task_typetask_type) return { id: item[id], task_type: task_type, result: result[content], model_used: result[model_used], success: result[success] } def main(): parser argparse.ArgumentParser() parser.add_argument(--input, requiredTrue) parser.add_argument(--output, requiredTrue) parser.add_argument(--workers, typeint, default3) args parser.parse_args() with open(args.input, r, encodingutf-8) as f: items json.load(f) results [] with ThreadPoolExecutor(max_workersargs.workers) as executor: futures {executor.submit(process_single, item): item for item in items} for future in as_completed(futures): item futures[future] try: results.append(future.result()) except Exception as e: results.append({ id: item[id], task_type: unknown, result: None, model_used: None, success: False, error: str(e) }) results.sort(keylambda x: x[id]) with open(args.output, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2) if __name__ __main__: main()這里有幾個關(guān)鍵決策。第一用了ThreadPoolExecutor而不是串行循環(huán)。30條數(shù)據(jù)如果串行處理每條平均3秒總共90秒用3個并發(fā)理論上30秒就能跑完。但并發(fā)數(shù)不能設(shè)太高因為路由層和后端模型都有速率限制設(shè)成3到5比較穩(wěn)妥。第二異常捕獲放在了future.result()那一層。這樣即使某條數(shù)據(jù)處理失敗也不會影響其他數(shù)據(jù)的處理失敗的那條會記錄錯誤信息后續(xù)可以單獨重跑。第三結(jié)果按id排序后再寫入。并發(fā)處理的完成順序是不確定的如果不排序回寫到表格時就會亂序RPA那邊匹配起來很麻煩。3.3 并發(fā)數(shù)、超時時間與重試次數(shù)的參數(shù)調(diào)優(yōu)參數(shù)調(diào)優(yōu)這部分我踩過不少坑。最開始我把并發(fā)數(shù)設(shè)成10想著越快越好結(jié)果路由層直接返回429限流一半的請求失敗了。后來降到3穩(wěn)定跑完但速度不夠理想。最終我通過幾次測試找到了一個平衡點。參數(shù)初始值調(diào)整后調(diào)整理由并發(fā)數(shù)103避免觸發(fā)路由層限流單次超時30秒60秒復雜任務(wù)需要更長處理時間最大重試5次3次減少無效重試失敗快速暴露退避基數(shù)1秒2秒給后端足夠的恢復時間超時時間的設(shè)置需要根據(jù)任務(wù)類型區(qū)分。simple任務(wù)一般5秒內(nèi)返回設(shè)30秒綽綽有余complex任務(wù)可能需要30到50秒設(shè)60秒比較安全。我在代碼里沒有做區(qū)分統(tǒng)一設(shè)了60秒因為超時設(shè)長了只是浪費等待時間設(shè)短了會導致不必要的重試后者代價更大。重試次數(shù)從5次降到3次是因為我發(fā)現(xiàn)很多失敗是“確定性失敗”——比如輸入格式不對、API Key過期這種失敗重試100次也沒用。3次足夠覆蓋偶發(fā)的網(wǎng)絡(luò)抖動和服務(wù)端瞬時故障。實操心得在正式跑30條數(shù)據(jù)之前先用2到3條數(shù)據(jù)做一次全流程測試確認路由策略、并發(fā)參數(shù)、結(jié)果回寫都正常再批量跑。這個習慣幫我省了很多返工時間。4. 實測中遇到的五個典型問題與排查過程4.1 路由策略不生效請求全部走了默認模型第一次跑通腳本后我查看model_used字段發(fā)現(xiàn)30條數(shù)據(jù)全部走了model-general我配置的simple和complex路由完全沒生效。這個問題排查了大概二十分鐘。第一步檢查請求體。確認task_type字段確實傳了而且值和配置文件里的match條件一致。打印出來的請求體顯示task_type是simple沒問題。第二步檢查路由配置。登錄路由管理界面發(fā)現(xiàn)配置確實保存了但狀態(tài)是“草稿”而不是“已發(fā)布”。原來藍耘智能路由的配置需要顯式發(fā)布才會生效我改完配置后直接關(guān)了頁面沒有點發(fā)布按鈕。第三步發(fā)布配置后重新跑model_used字段開始出現(xiàn)不同的值了。這個問題說起來很簡單但如果不檢查路由層的配置狀態(tài)光看腳本代碼是找不到原因的。4.2 并發(fā)請求觸發(fā)限流429錯誤的處理方式并發(fā)數(shù)設(shè)成10的那次日志里大量出現(xiàn)429狀態(tài)碼。429的意思是“請求過多”說明路由層或后端模型有速率限制。我當時的處理方式是簡單重試但效果不好因為重試的請求又加劇了限流。正確的做法是“退避 降并發(fā)”。我在代碼里加了指數(shù)退避同時把并發(fā)數(shù)從10降到3。另外路由層本身也有隊列機制當請求超過速率限制時它會自動排隊而不是直接拒絕。但這個隊列有容量上限超過之后還是會返回429。所以最根本的解決辦法還是控制并發(fā)數(shù)。后來我總結(jié)了一個經(jīng)驗對于30條數(shù)據(jù)這種規(guī)模并發(fā)數(shù)設(shè)3是最穩(wěn)妥的。如果數(shù)據(jù)量增加到100條以上可以考慮設(shè)5但需要觀察路由層的限流閾值。不同模型后端的限流策略不一樣輕量模型通常寬松一些推理增強模型則比較嚴格。4.3 返回格式不一致不同模型的輸出結(jié)構(gòu)差異這個問題比較隱蔽。輕量模型和推理增強模型返回的內(nèi)容格式不完全一樣。輕量模型傾向于返回純文本推理增強模型有時候會返回帶Markdown格式的內(nèi)容比如用**加粗關(guān)鍵詞、用-列要點。我的腳本原本假設(shè)所有返回都是純文本直接寫回表格結(jié)果表格里出現(xiàn)了一堆Markdown符號。解決辦法是在腳本里加一個后處理步驟根據(jù)model_used字段做格式歸一化。如果模型返回了Markdown就用正則表達式去掉格式符號或者用strip()方法清理首尾空白。更穩(wěn)妥的方式是在prompt里明確要求“返回純文本不要使用任何Markdown格式”但實際測試下來模型并不總是遵守這個指令所以后處理還是必要的。import re def normalize_output(text): if text is None: return text re.sub(r\*\*(.?)\*\*, r\1, text) text re.sub(r^[-*]\s, , text, flagsre.MULTILINE) text re.sub(r(.?), r\1, text) return text.strip()這個歸一化函數(shù)不追求完美只處理最常見的幾種格式符號。如果你對輸出格式要求很嚴格建議在路由層配置輸出校驗規(guī)則讓不符合格式的返回觸發(fā)質(zhì)量降級。4.4 腳本在RPA中調(diào)用時路徑與編碼的坑RPA調(diào)用Python腳本時工作目錄和編碼是兩個高頻問題。我第一次在影刀RPA里調(diào)用腳本時報了“文件找不到”的錯誤。原因是RPA執(zhí)行腳本時的工作目錄不是腳本所在目錄而是RPA自己的安裝目錄。解決辦法是在RPA的命令里用絕對路徑或者在腳本開頭用os.chdir(os.path.dirname(os.path.abspath(__file__)))切換工作目錄。編碼問題更隱蔽。Windows系統(tǒng)默認編碼是GBK而我的JSON文件是UTF-8。RPA寫input.json時用了GBK腳本讀取時用UTF-8結(jié)果中文全部亂碼。解決辦法是在RPA和腳本兩邊都顯式指定UTF-8編碼。RPA那邊在寫文件時設(shè)置編碼參數(shù)腳本這邊在open()里加encodingutf-8。注意如果你的數(shù)據(jù)里包含emoji或其他特殊字符GBK編碼會直接報錯。統(tǒng)一用UTF-8是最省心的做法。4.5 處理結(jié)果回寫表格時的數(shù)據(jù)錯位問題并發(fā)處理導致的結(jié)果亂序我在前面提過用排序解決。但還有一個更隱蔽的錯位問題RPA讀取output.json后按順序逐條寫回表格但如果某條數(shù)據(jù)在腳本里處理失敗了output.json里仍然有這條記錄只是result字段是null。RPA如果不做判斷直接把null寫進表格就會覆蓋掉原始數(shù)據(jù)。我的處理方式是在RPA的回寫環(huán)節(jié)加一個條件判斷只有當success為true時才寫回結(jié)果否則在備注列標記“處理失敗”保留原始數(shù)據(jù)不動。這樣即使部分數(shù)據(jù)失敗也不會破壞原始表格的完整性。另外回寫時的行號匹配也要注意。我用的是id字段做匹配而不是行號。因為RPA讀取數(shù)據(jù)時可能做了篩選或排序行號不一定和原始表格一致。用唯一id匹配是最可靠的方式。5. 從30條到300條這套方案的擴展性與優(yōu)化方向5.1 批量規(guī)模增大后的分片與隊列策略30條數(shù)據(jù)用線程池并發(fā)處理沒問題但如果數(shù)據(jù)量增加到300條甚至更多就需要考慮分片和隊列了。一次性把300條全部提交到線程池會導致大量請求同時涌向路由層觸發(fā)限流的概率大大增加。我的做法是把數(shù)據(jù)分成多個批次每批30到50條批次之間加一個短暫的間隔。這個邏輯可以用一個簡單的循環(huán)實現(xiàn)def process_in_batches(items, batch_size30, interval5): all_results [] for i in range(0, len(items), batch_size): batch items[i:ibatch_size] batch_results process_batch(batch) all_results.extend(batch_results) if i batch_size len(items): time.sleep(interval) return all_results更優(yōu)雅的方式是用消息隊列比如把每條數(shù)據(jù)作為一個消息推送到隊列里消費者按固定速率從隊列取消息處理。這樣天然實現(xiàn)了速率控制而且支持斷點續(xù)傳——如果處理到一半腳本崩潰了重啟后從隊列里繼續(xù)取就行不需要重新處理已經(jīng)完成的數(shù)據(jù)。對于300條這個規(guī)模我傾向于用“分片 斷點續(xù)傳”的方案。每處理完一批就把結(jié)果寫入一個帶時間戳的中間文件全部處理完后再合并。這樣即使中途出問題也能從上次中斷的地方繼續(xù)。5.2 路由策略的精細化按成本、延遲、質(zhì)量三維度權(quán)衡當數(shù)據(jù)量增大后路由策略的優(yōu)化空間就體現(xiàn)出來了。30條數(shù)據(jù)時成本差異不明顯300條數(shù)據(jù)時不同模型的調(diào)用成本差距可能達到數(shù)倍。這時候就需要在成本、延遲、質(zhì)量之間做權(quán)衡。我的做法是給每個任務(wù)類型定義一個“優(yōu)先級”。simple任務(wù)優(yōu)先考慮成本和延遲complex任務(wù)優(yōu)先考慮質(zhì)量standard任務(wù)取中間值。路由層支持按優(yōu)先級選擇模型你可以在配置里給每個模型打上成本、延遲、質(zhì)量的評分然后讓路由層根據(jù)任務(wù)優(yōu)先級自動選擇。任務(wù)類型成本權(quán)重延遲權(quán)重質(zhì)量權(quán)重推薦模型simple0.60.30.1輕量模型standard0.30.30.4通用模型complex0.10.20.7推理增強模型這個權(quán)重表不是固定的需要根據(jù)實際業(yè)務(wù)需求調(diào)整。如果你的業(yè)務(wù)對響應(yīng)時間極其敏感就把延遲權(quán)重調(diào)高如果對準確性要求極高就把質(zhì)量權(quán)重調(diào)高。5.3 日志、監(jiān)控與失敗重跑機制的設(shè)計數(shù)據(jù)量小的時候出錯了看一眼日志就能定位。數(shù)據(jù)量大了之后沒有完善的日志和監(jiān)控排查問題就是大海撈針。我在腳本里加了結(jié)構(gòu)化日志每條數(shù)據(jù)的處理過程都記錄以下信息數(shù)據(jù)ID、任務(wù)類型、使用的模型、請求耗時、重試次數(shù)、最終狀態(tài)。import logging import json logging.basicConfig( levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s, handlers[ logging.FileHandler(process.log, encodingutf-8), logging.StreamHandler() ] ) def log_result(item_id, task_type, model_used, elapsed, attempts, success): logging.info(json.dumps({ id: item_id, task_type: task_type, model: model_used, elapsed_ms: int(elapsed * 1000), attempts: attempts, success: success }, ensure_asciiFalse))有了這些日志你可以很容易地統(tǒng)計出哪個模型的平均耗時最長、哪類任務(wù)的重試率最高、哪個時間段失敗率集中。這些數(shù)據(jù)是后續(xù)優(yōu)化的依據(jù)。失敗重跑機制也很重要。我通常會在全部處理完成后掃描一遍結(jié)果把success為false的記錄提取出來單獨重跑一次。重跑時可以把并發(fā)數(shù)降到1超時時間延長到120秒給這些“困難戶”更寬松的處理條件。如果重跑仍然失敗就標記為“需人工介入”不再自動重試。5.4 什么場景適合這套方案什么場景不適合這套“智能路由 RPA Python腳本”的方案最適合的場景是數(shù)據(jù)量在幾十到幾百條之間任務(wù)類型有差異對處理質(zhì)量有一定要求但又不值得為此搭建一套完整的微服務(wù)架構(gòu)。它的優(yōu)勢是搭建快、成本低、靈活可調(diào)。不適合的場景也很明確。如果數(shù)據(jù)量在10條以下手工處理可能比寫腳本更快沒必要上這套方案。如果數(shù)據(jù)量在幾千條以上線程池和文件交換的方式就會成為瓶頸需要考慮消息隊列和分布式處理。如果所有數(shù)據(jù)的類型完全一致不需要路由切換那直接用單一模型調(diào)用就行智能路由反而增加了復雜度。還有一個容易被忽略的點這套方案對RPA的穩(wěn)定性有依賴。如果RPA流程本身不穩(wěn)定比如界面元素定位經(jīng)常失敗、彈窗處理不完善那么即使模型調(diào)用部分做得再好整體流水線也會頻繁中斷。所以在實施這套方案之前先確保RPA流程本身是穩(wěn)定的。6. 幾個讓我少走彎路的實操習慣第一個習慣是“先跑通一條再跑通一批”。不管方案設(shè)計得多完美先用一條數(shù)據(jù)走完全流程確認輸入、路由、調(diào)用、返回、回寫每個環(huán)節(jié)都正常再擴展到30條。這個習慣幫我發(fā)現(xiàn)了不少“設(shè)計時沒想到、跑起來才暴露”的問題比如編碼問題、路徑問題、格式問題。第二個習慣是“保留原始數(shù)據(jù)不動”。處理結(jié)果寫回表格時永遠不要覆蓋原始數(shù)據(jù)列。新增一列寫結(jié)果再加一列寫狀態(tài)和使用的模型。這樣即使處理出錯原始數(shù)據(jù)還在可以隨時重跑。第三個習慣是“給每條數(shù)據(jù)留痕”。model_used、attempts、elapsed_ms這些字段看起來不起眼但在優(yōu)化階段非常有用。你能清楚地知道每條數(shù)據(jù)走了哪個模型、重試了幾次、花了多長時間。沒有這些數(shù)據(jù)優(yōu)化就是憑感覺。第四個習慣是“配置和代碼分離”。路由策略、并發(fā)數(shù)、超時時間這些參數(shù)不要硬編碼在腳本里放到配置文件或環(huán)境變量里。這樣調(diào)整參數(shù)時不需要改代碼也不需要重新測試腳本邏輯。第五個習慣是“失敗是常態(tài)不是異?!?。在分布式調(diào)用中網(wǎng)絡(luò)抖動、服務(wù)限流、超時都是正?,F(xiàn)象。腳本的設(shè)計目標不是“永遠不失敗”而是“失敗后能自動恢復恢復不了能快速定位”。把失敗處理當成核心邏輯的一部分來寫而不是事后補丁。