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