稿事節(jié)】HarmonyOS 7 Agent 開發(fā)實戰(zhàn) 07:多 Agent 任務分解與反思)
前幾篇我們一直在打磨單個 Agent01 篇搭好統(tǒng)一的 LLM 底座與重試策略02 篇補上對話記憶03 篇讓模型學會調(diào)工具04 篇用檢索增強讓它有據(jù)可答。但真實任務往往一句話里塞了三件事——“調(diào)研競品輸出對比報告給出落地建議”。讓一個 Agent 一口氣全做完中間步驟會被壓縮錯了也不知道錯在哪。這一篇把鏡頭拉遠在 HarmonyOS 7 上用三個各司其職的角色——規(guī)劃、執(zhí)行、評審——把任務分解 自我反思跑成一條可測試的流水線。先把邊界劃清楚本篇講的是單設備上的多角色任務分解與反思不是跨設備的多智能體協(xié)商。系列后面講 A2A 時智能體之間會對等交換意圖、互相協(xié)商這里的三種角色只是同一個應用里的三段純邏輯彼此不通信、不協(xié)商只有編排器單向調(diào)度它們。這個區(qū)分在架構評審里經(jīng)常被追問值得先講明白。一、為什么分解 反思是 Agent 的基本功大模型直接面對復雜目標的典型癥狀是一步到位想一次性給出最終答案過程不可見結(jié)果不可糾。把目標拆成子任務再逐個執(zhí)行有兩個直接收益可觀測每一步的輸入輸出都是獨立字符串哪個子任務出了問題一目了然頁面可以逐條渲染可糾錯評審角色對結(jié)果打分不滿意就把反饋回灌給規(guī)劃器重新拆解——這就是反思也是本篇標題里反思二字的來源。拿開頭那個目標舉例。直連模式下模型被要求一次輸出競品調(diào)研 對比報告 落地建議往往前兩部分寫得認真第三部分開始敷衍而且你沒法只重做第三部分。分解之后三個子任務各自獨立執(zhí)行、獨立留痕評審發(fā)現(xiàn)落地建議太薄可以精準地只對它重規(guī)劃。粒度帶來的不只是質(zhì)量還有可運維性——這是把大任務變小任務之后最容易被低估的收益。本篇的三個角色全部是確定性純函數(shù)不聯(lián)網(wǎng)、不依賴設備、沒有隱藏狀態(tài)。這帶來一個很實際的工程好處——同樣的邏輯可以在 Node 里鏡像跑斷言做預檢也可以在 DevEco 里用 Hypium 做回歸兩邊結(jié)論互為印證。這是純邏輯分層從 01 篇延續(xù)下來的紅利。二、三個角色各管一段PlannerAgent規(guī)劃decompose(goal)把目標按中英文標點。、;,切成子任務整句里一個分隔符都沒有時回退到固定三步模板保證任何輸入都有一條可執(zhí)行的計劃。exportinterfaceSubTask{id:number;description:string;}constFALLBACK_TEMPLATE:string[][明確目標的邊界與成功標準,拆解為核心可執(zhí)行步驟,執(zhí)行并匯總自檢結(jié)果];exportclassPlannerAgent{decompose(goal:string):SubTask[]{constdescs:string[]this.hasDelimiter(goal)?this.splitGoal(goal):FALLBACK_TEMPLATE.slice();constfinalDescs:string[]descs.length0?descs:FALLBACK_TEMPLATE.slice();consttasks:SubTask[][];for(leti0;ifinalDescs.length;i){tasks.push({id:i1,description:finalDescs[i]});}returntasks;}// hasDelimiter目標中是否出現(xiàn)過任意分隔符// splitGoal逐字符掃描遇分隔符收尾一段空段丟棄首尾空白去除}注意hasDelimiter的判斷維度目標里是否出現(xiàn)過分隔符而不是切完剩幾段。一句沒有標點的話切完只有一段但它需要的不是單步執(zhí)行而是模板兜底的三步走。這個細節(jié)曾讓首版實現(xiàn)把做個年度計劃拆成了一步單測立刻抓住了。WorkerAgent執(zhí)行execute(subtask, context)對單個子任務產(chǎn)出一段結(jié)果。演示里返回確定性的完成[編號]: 描述 - 產(chǎn)出編號真實項目把這一行換成工具調(diào)用或模型推理即可編排層完全不用改。CriticAgent評審review(goal, results)用啟發(fā)式打分——每條結(jié)果非空且長度達到MIN_LEN本例 8 字符記為達標全部達標給滿分 1.0否則按達標比例給分低于 0.6 觸發(fā)needsReplan。完整實現(xiàn)如下exportclassCriticAgent{review(goal:string,results:string[]):CriticVerdict{if(results.length0){return{score:0,needsReplan:true,feedback:沒有任何執(zhí)行結(jié)果需要重規(guī)劃};}letokCount:number0;for(constrofresults){if(r.trim().lengthMIN_LEN){okCount;}}if(okCountresults.length){return{score:1.0,needsReplan:false,feedback:全部子任務產(chǎn)出達標};}constscore:numberokCount/results.length;return{score:score,needsReplan:scoreREPLAN_THRESHOLD,feedback:scoreREPLAN_THRESHOLD?部分產(chǎn)出不足建議重規(guī)劃:大部分達標可交付};}}分數(shù)不是重點feedback才是它會被回灌給規(guī)劃器成為下一輪拆解的輸入。評審器的判決結(jié)構分數(shù)、是否重規(guī)劃、反饋文本是一個純數(shù)據(jù)接口今天用啟發(fā)式實現(xiàn)明天換成大模型評審編排器一行代碼都不用動。三、Orchestrator把三段串成有界循環(huán)exportclassOrchestrator{run(goal:string,maxReplans:number1):OrchestratorResult{letplan:SubTask[]this.planner.decompose(goal);letresults:string[]this.worker.executeAll(plan,);letverdict:CriticVerdictthis.critic.review(goal,results);letreplanned:booleanfalse;letreplanCount:number0;while(verdict.needsReplanreplanCountmaxReplans){replannedtrue;replanCount;constnewGoal:stringgoal反思反饋verdict.feedback;planthis.planner.decompose(newGoal);resultsthis.worker.executeAll(plan,verdict.feedback);verdictthis.critic.review(goal,results);}return{plan,results,score:verdict.score,replanned};}}三個關鍵設計終止性replanCount maxReplans是循環(huán)唯一的繼續(xù)條件評審器再怎么打低分循環(huán)也最多轉(zhuǎn)maxReplans圈。只要這一條在編排器就不可能死循環(huán)反饋回灌重規(guī)劃時把feedback追加到目標字符串里規(guī)劃器下一輪看得見上次差在哪這就是反思閉環(huán)的物理載體依賴注入三個角色都從構造參數(shù)傳入缺省才用默認實現(xiàn)。單測時可以注入一個永遠打低分的 mock 評審器精確驗證恰好重規(guī)劃一次后收斂也能驗證maxReplans3時評審恰好被調(diào)用 4 次。四、在 DevEco 里跑起來演示頁只做一件事輸入目標點運行編排看到計劃、逐條產(chǎn)出、評審分、是否發(fā)生過重規(guī)劃。頁面同時接了一個MockLlmClient——繼承 01 篇的LlmClient底座超時、重試與響應解析照常復用只是不聯(lián)網(wǎng)exportclassMockLlmClientextendsLlmClient{protectedasyncsendOnce(_req:ChatRequest):Promisestring{returnJSON.stringify({choices:[{message:{content:演示已基于編排給出結(jié)論},finish_reason:stop}]});}// buildPayload / buildHeaders / classifyError 按底座契約同樣實現(xiàn)}它把編排結(jié)論轉(zhuǎn)成一句LLM 旁注證明大模型通道隨時可以接進來。真實項目里換成LlmClientFactory.create(openai, {...})即可頁面與編排層的代碼零改動。constorch:OrchestratornewOrchestrator();constresorch.run(this.goal,1);this.planLinesres.plan.map((t):stringt.id. t.description);this.resultLinesres.results;this.replanTextres.replanned?本次發(fā)生了重規(guī)劃:一次通過未觸發(fā)重規(guī)劃;驗證分兩層。Node 鏡像層跑 22 條斷言分隔符切分計數(shù)、無分隔符走模板、空目標兜底、好評分不重規(guī)劃、低分恰好一次重規(guī)劃、maxReplans3時評審恰好 4 次后終止、聚合結(jié)果與計劃一一對應。Hypium 層共 29 個用例覆蓋同一批場景外加底座回歸RetryPolicy 分類與退避、ResponseParser 解析、ConversationStore 裁剪、Agent 編排、ChatUIMessage 映射。兩層都綠才敢說這條流水線是穩(wěn)的。恰好一次重規(guī)劃這條最值得展開它靠注入 mock 評審器實現(xiàn)classLowScoreCriticextendsCriticAgent{calls:number0;review(goal:string,results:string[]):CriticVerdict{this.calls;return{score:0.3,needsReplan:true,feedback:mock 不達標};}}it(低分恰好發(fā)生一次重規(guī)劃后終止,0,(){constcriticnewLowScoreCritic();constresnewOrchestrator({critic}).run(目標一目標二。目標三,1);expect(critic.calls).assertEqual(2);// 初評 重規(guī)劃后復評恰好一輪expect(res.replanned).assertTrue();});評審器被調(diào)用兩次意味著初評一次、重規(guī)劃后復評一次然后循環(huán)條件replanCount maxReplans失敗退出。終止性不是靠希望它停下來而是靠一個可以被斷言的結(jié)構性質(zhì)——這是編排器區(qū)別于隨手寫個 while的地方。運行效果截圖五、從演示到生產(chǎn)把 Worker 換成真活演示版的 Worker 返回占位字符串遷到生產(chǎn)只需三步方法簽名一律不動接入真實執(zhí)行在execute里調(diào)用LlmClient.chat或某個工具把子任務描述組裝進提示詞串起上下文context參數(shù)此時派上用場——把前序子任務的產(chǎn)出拼接進去子任務之間就有了依賴鏈不再是孤島升級評審把啟發(fā)式的MIN_LEN換成大模型評審讓它輸出結(jié)構化的分數(shù)與反饋判決接口CriticVerdict保持不變。唯一要留意的結(jié)構性變化Worker 變成異步后run也隨之變成async但循環(huán)上界maxReplans的寫法原樣保留。換句話說無論三個角色內(nèi)部多復雜有界反思循環(huán)這個骨架是整個編排器的不變量——改血肉別改骨架。六、避坑指南結(jié)合源碼四個最容易踩的雷重規(guī)劃死循環(huán)忘了maxReplans上界評審器持續(xù)打低分時頁面直接卡死。循環(huán)條件必須是replanCount maxReplans且計數(shù)器在進入循環(huán)體時自增別放在循環(huán)末尾反饋空泛feedback 寫結(jié)果不好重新想想規(guī)劃器收到的等于沒有。哪怕啟發(fā)式評審也要輸出哪幾條不達標、差在哪級別的具體描述LLM 評審時同理子任務爆炸用戶目標里有十個逗號就會拆出十步。工程上應給單條計劃設上限比如 8 步超出就合并相鄰步驟否則執(zhí)行成本和 UI 都撐不住評審無標準MIN_LEN與 0.6 閾值要和業(yè)務對齊。閾值定 0.9兩步里錯一步就永遠重規(guī)劃定 0.3評審形同虛設。標準先于代碼定下來寫進測試。還有一條工程習慣值得堅持三個角色保持純函數(shù)。別在 Planner 里偷偷發(fā)請求別在 Critic 里讀數(shù)據(jù)庫。純函數(shù)才能在 Node 里秒級鏡像、在 Hypium 里穩(wěn)定回歸——這也是本系列一以貫之的分層原則底座、編排、UI 各管各的誰也不越界。六、和多智能體協(xié)商的區(qū)別再強調(diào)一次維度本篇任務分解與反思系列后續(xù)A2A 多智能體協(xié)商角色關系編排器單向調(diào)度三段邏輯智能體對等協(xié)商通信方式同進程函數(shù)調(diào)用跨設備、跨進程消息終止條件maxReplans 數(shù)值上界協(xié)商輪次或共識達成典型場景拆解、執(zhí)行、自檢意圖交換、能力發(fā)現(xiàn)一句話概括本篇的三個角色是同一張流程圖上的三站協(xié)商場景里的多個智能體是各自流程圖的主人。搜多 Agent資料時兩者經(jīng)?;煸谝黄鹬v動手前先問自己要的是哪一種。參考與出處HarmonyOS 開發(fā)者官網(wǎng)主頁https://developer.huawei.com/consumer/cn/doc/harmonyos-homeArkTS 語言介紹官方指南https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-overviewUIAbility 與頁面生命周期官方參考https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-app-ability-uiabilityArkUI 聲明式開發(fā)范式官方指南https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-ui-development應用測試框架 Hypium官方指南https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/application-test-framework最后一句讓規(guī)劃的有章法、執(zhí)行的有產(chǎn)出、評審的有標準Agent 才算真正學會了想清楚再做做完再想。