戰(zhàn):讓 AI 從被動(dòng)問答變主動(dòng)喚醒的自動(dòng)化員工)
1. 從一條命令說起dsh-waker 到底在解決什么問題第一次看到dsh plugin --profile web add dshmarket這條命令的人大概率會(huì)愣一下dsh是什么profile又是什么dshmarket和dsh-waker之間是什么關(guān)系。我剛開始接觸這套東西的時(shí)候也是一頭霧水翻了不少文檔才把整條鏈路串起來。簡單說dsh是一套面向開發(fā)者和效率玩家的命令行工具集它本身提供了一套插件機(jī)制允許你通過plugin add的方式把外部能力掛載進(jìn)來。而dsh-waker就是其中一個(gè)定位非常明確的插件——它的目標(biāo)是把一個(gè)“只會(huì)被動(dòng)等你提問”的 AI變成一個(gè)“會(huì)主動(dòng)來找你干活”的 AI 員工。這個(gè)區(qū)別聽起來好像不大但實(shí)際用起來完全是兩碼事。你平時(shí)用的對話式 AI本質(zhì)上是一個(gè)問答機(jī)器你問一句它答一句你不問它就永遠(yuǎn)沉默。而dsh-waker想做的事情是反過來——它讓 AI 擁有一個(gè)“喚醒”的觸發(fā)機(jī)制可以在特定條件下主動(dòng)發(fā)起任務(wù)、推送結(jié)果、提醒你處理某件事。你可以把它理解成給 AI 裝了一個(gè)鬧鐘加一個(gè)任務(wù)隊(duì)列它不再只是坐在那里等你而是會(huì)在合適的時(shí)間點(diǎn)自己醒過來干活。我之所以對這個(gè)插件感興趣是因?yàn)槲易约旱墓ぷ髁骼镉写罅俊岸〞r(shí)要做但又不值得專門盯著”的事情。比如每天早上要匯總一遍昨天各個(gè)渠道的留言比如某個(gè)數(shù)據(jù)源更新之后要自動(dòng)整理成簡報(bào)比如寫了一半的文檔需要在隔天提醒自己繼續(xù)。這些事情如果全靠手動(dòng)觸發(fā)很容易忘如果寫死成一個(gè)腳本又不夠靈活。dsh-waker提供的正是中間那層——用自然語言描述任務(wù)用插件機(jī)制管理觸發(fā)用 IM 通道把結(jié)果送到你面前。適合讀這篇內(nèi)容的人大概有三類。第一類是已經(jīng)在用dsh這套工具、想進(jìn)一步榨干它能力的效率玩家第二類是對“AI 員工系統(tǒng)”這個(gè)概念感興趣、想看看落地形態(tài)到底長什么樣的開發(fā)者第三類是做 IM 相關(guān)產(chǎn)品、想了解高并發(fā)消息場景下怎么把 AI 能力嵌進(jìn)去的技術(shù)同學(xué)。不管你是哪一類下面這些從實(shí)際折騰里攢出來的經(jīng)驗(yàn)應(yīng)該都能幫你少走點(diǎn)彎路。2. 整體設(shè)計(jì)思路為什么是“插件 喚醒”這套組合2.1 把 AI 當(dāng)員工而不是當(dāng)搜索引擎大部分人第一次接觸 AI 工具腦子里裝的還是搜索引擎的使用習(xí)慣我有個(gè)問題我去查一下。但dsh-waker背后的設(shè)計(jì)哲學(xué)不是這個(gè)。它假設(shè)你有一個(gè)“員工”這個(gè)員工知道你的工作習(xí)慣、知道你關(guān)心什么、知道什么時(shí)候該提醒你。你要做的不是每次都給指令而是把規(guī)則和觸發(fā)條件配置好剩下的交給它。這個(gè)思路的轉(zhuǎn)變很關(guān)鍵。搜索引擎是被動(dòng)的員工是主動(dòng)的。搜索引擎每次都要你重新描述需求員工會(huì)記住上下文。搜索引擎給你一堆鏈接讓你自己篩員工直接給你結(jié)論。dsh-waker在做的就是把 AI 從“搜索框”往“工位”的方向推。我自己的體會(huì)是一旦你習(xí)慣了這種模式就很難回去了。以前我每天早上要花二十分鐘手動(dòng)過一遍各種消息現(xiàn)在這部分時(shí)間基本省下來了因?yàn)閐sh-waker會(huì)在固定時(shí)間把整理好的內(nèi)容推給我。它不是替我做了多復(fù)雜的事就是把“記得去做”這件事從我的腦子里卸載出去了。2.2 插件機(jī)制為什么比內(nèi)置功能更合適有人可能會(huì)問既然喚醒這么有用為什么不直接做進(jìn)dsh主程序里非要搞成插件這個(gè)問題我一開始也想不通后來自己寫了一個(gè)小插件之后才明白。內(nèi)置功能的問題是它必須照顧所有人的需求所以只能做最通用的那部分。但“喚醒”這件事高度依賴個(gè)人場景有人要每天早上八點(diǎn)提醒有人要某個(gè)文件變動(dòng)時(shí)觸發(fā)有人要 IM 里收到特定關(guān)鍵詞時(shí)響應(yīng)。這些需求差異太大塞進(jìn)主程序只會(huì)讓核心變得臃腫。插件機(jī)制的好處是核心保持精簡能力按需加載。你需要喚醒就裝dsh-waker你需要?jiǎng)e的能力就裝別的插件互不干擾。而且插件機(jī)制天然適合迭代。dsh-waker這種偏實(shí)驗(yàn)性的功能放在插件層可以快速試錯(cuò)不用等主程序發(fā)版。我實(shí)測下來插件方式的更新頻率明顯比核心功能快遇到問題反饋之后修復(fù)也及時(shí)。2.3 喚醒的三種典型觸發(fā)模型在實(shí)際使用中dsh-waker的喚醒觸發(fā)大致可以歸成三類理解這三類能幫你更快地設(shè)計(jì)自己的任務(wù)。第一類是時(shí)間觸發(fā)也就是定時(shí)喚醒。這是最直觀的比如每天九點(diǎn)、每周一早上、每隔兩小時(shí)。適合做周期性匯總、例行提醒這類事情。第二類是事件觸發(fā)也就是某個(gè)條件滿足時(shí)喚醒。比如某個(gè)目錄里出現(xiàn)了新文件、某個(gè)接口返回了特定狀態(tài)、IM 里收到了符合規(guī)則的消息。這類觸發(fā)適合做響應(yīng)式的任務(wù)比如收到客戶留言后自動(dòng)分類。第三類是鏈?zhǔn)接|發(fā)也就是一個(gè)任務(wù)完成后喚醒下一個(gè)任務(wù)。這個(gè)稍微復(fù)雜一點(diǎn)但威力也最大。比如先抓取數(shù)據(jù)抓完喚醒整理任務(wù)整理完喚醒推送任務(wù)。整條鏈路串起來就是一個(gè)完整的自動(dòng)化流水線。提示新手建議從時(shí)間觸發(fā)開始跑通之后再嘗試事件觸發(fā)最后再碰鏈?zhǔn)接|發(fā)。一上來就搞鏈?zhǔn)脚挪閱栴}會(huì)很痛苦。2.4 和 IM 結(jié)合的價(jià)值在哪里熱詞里出現(xiàn)了“高并發(fā) IM”“海貍 IM”“CSDN 盒子 IM 網(wǎng)頁版”這些詞說明很多人關(guān)心的是 AI 能力和 IM 通道怎么結(jié)合。dsh-waker在這方面的設(shè)計(jì)思路是AI 負(fù)責(zé)生產(chǎn)內(nèi)容IM 負(fù)責(zé)投遞內(nèi)容。為什么是 IM 而不是郵件或者別的因?yàn)?IM 的到達(dá)率和即時(shí)性是最好的。郵件你可能半天才看一次但 IM 消息基本是秒級觸達(dá)。對于“喚醒”這個(gè)場景來說觸達(dá)速度直接決定了價(jià)值。一個(gè)早上九點(diǎn)該到的提醒如果拖到中午才看到意義就大打折扣了。我在配置的時(shí)候踩過一個(gè)坑一開始把推送頻率設(shè)得太高結(jié)果 IM 里全是機(jī)器人消息反而造成了干擾。后來調(diào)整成“只推真正需要我決策的內(nèi)容”體驗(yàn)才好起來。這個(gè)度需要自己把握沒有標(biāo)準(zhǔn)答案。3. 核心細(xì)節(jié)拆解從安裝到跑通第一個(gè)喚醒任務(wù)3.1 安裝與 profile 配置的關(guān)鍵點(diǎn)回到最開始那條命令dsh plugin --profile web add dshmarket。這里有幾個(gè)細(xì)節(jié)值得展開。--profile web這個(gè)參數(shù)指定的是配置檔案。dsh支持多套 profile你可以理解成多套獨(dú)立的配置環(huán)境。比如你有一套用于日常工作的 profile一套用于實(shí)驗(yàn)的 profile互不影響。這個(gè)設(shè)計(jì)很實(shí)用因?yàn)椴寮b多了之后不同插件之間可能會(huì)有依賴沖突用 profile 隔離能避免很多麻煩。add dshmarket是從插件市場拉取。這里要注意的是插件市場里的插件質(zhì)量參差不齊裝之前最好看一下更新時(shí)間和說明文檔。我遇到過裝了一個(gè)半年沒更新的插件結(jié)果和當(dāng)前版本的核心不兼容排查了半天才發(fā)現(xiàn)是插件的問題。安裝完成之后建議先跑一下dsh plugin list確認(rèn)插件已經(jīng)掛載成功。如果列表里沒有大概率是 profile 選錯(cuò)了或者網(wǎng)絡(luò)拉取失敗了。這一步看起來簡單但很多人卡在這里。3.2 dsh-waker 的配置文件結(jié)構(gòu)dsh-waker的核心是一份配置文件里面定義了“什么時(shí)候喚醒”和“喚醒之后做什么”。我把它拆成三個(gè)部分來理解。第一部分是觸發(fā)器定義。這里寫清楚觸發(fā)條件是時(shí)間還是事件。時(shí)間觸發(fā)用類似 cron 的表達(dá)式事件觸發(fā)用條件判斷。我建議觸發(fā)器命名要清晰比如morning_digest比task1好得多后面排查問題的時(shí)候你會(huì)感謝自己。第二部分是任務(wù)定義。這里描述喚醒之后要執(zhí)行什么。可以是調(diào)用某個(gè) AI 能力可以是執(zhí)行一段腳本也可以是組合多個(gè)步驟。任務(wù)描述盡量用自然語言寫清楚因?yàn)閐sh-waker會(huì)嘗試?yán)斫饽愕囊鈭D。第三部分是投遞定義。這里配置結(jié)果往哪里送??梢运偷?IM可以寫到文件可以調(diào)用 webhook。投遞失敗的重試策略也在這里配。waker: triggers: - name: morning_digest type: schedule cron: 0 9 * * * tasks: - name: digest_task trigger: morning_digest action: summarize_recent_messages delivery: - name: im_push task: digest_task channel: im retry: 3上面這段是簡化后的結(jié)構(gòu)示意實(shí)際配置會(huì)更細(xì)。重點(diǎn)是理解這三層的關(guān)系觸發(fā)器負(fù)責(zé)“什么時(shí)候”任務(wù)負(fù)責(zé)“做什么”投遞負(fù)責(zé)“送到哪”。3.3 喚醒任務(wù)的描述技巧這是我覺得最值得花時(shí)間打磨的部分。同樣一個(gè)任務(wù)描述得好和描述得差執(zhí)行結(jié)果天差地別。差的描述是這樣的“整理一下消息”。問題在于“整理”是個(gè)模糊詞AI 不知道你要的是分類、摘要還是提取待辦。好的描述會(huì)具體很多“把過去 24 小時(shí)內(nèi) IM 里收到的消息按主題分組每組給出一句話摘要并標(biāo)出需要我回復(fù)的條目”。這樣 AI 就知道輸出應(yīng)該長什么樣。我的經(jīng)驗(yàn)是描述里最好包含四個(gè)要素時(shí)間范圍、數(shù)據(jù)來源、處理方式、輸出格式。這四個(gè)說清楚了任務(wù)基本就能穩(wěn)定執(zhí)行。缺了任何一個(gè)結(jié)果都可能飄。還有一個(gè)技巧是給例子。如果你希望輸出是特定格式直接在描述里附一個(gè)樣例比用文字描述格式有效得多。我試過用文字描述表格格式AI 理解得七七八八后來直接貼了一個(gè) Markdown 表格樣例輸出立刻就規(guī)范了。3.4 觸發(fā)頻率與資源消耗的平衡喚醒任務(wù)不是越頻繁越好。每喚醒一次背后都是一次 AI 調(diào)用都有資源消耗。如果觸發(fā)頻率設(shè)得太高不僅浪費(fèi)資源還可能因?yàn)椴l(fā)太多導(dǎo)致任務(wù)排隊(duì)。我的做法是先估算任務(wù)的實(shí)際價(jià)值密度。比如一個(gè)匯總?cè)蝿?wù)如果數(shù)據(jù)源每小時(shí)才更新一次那每小時(shí)喚醒一次就夠了沒必要每分鐘。如果數(shù)據(jù)源是實(shí)時(shí)的那可以適當(dāng)提高頻率但也要考慮 AI 調(diào)用的延遲。實(shí)測下來大部分個(gè)人場景的任務(wù)頻率在每天幾次到每小時(shí)一次之間就夠了。真正需要秒級響應(yīng)的場景其實(shí)很少而且那種場景通常更適合用規(guī)則引擎而不是 AI 來處理。注意配置觸發(fā)頻率的時(shí)候一定要留出任務(wù)執(zhí)行時(shí)間的余量。如果一個(gè)任務(wù)平均要跑 30 秒你把觸發(fā)間隔設(shè)成 20 秒任務(wù)就會(huì)堆積。我踩過這個(gè)坑后來把間隔調(diào)到任務(wù)耗時(shí)的三倍以上才穩(wěn)定。4. 實(shí)操過程手把手跑通一個(gè)完整的喚醒鏈路4.1 環(huán)境準(zhǔn)備與依賴確認(rèn)在動(dòng)手之前先把環(huán)境確認(rèn)一遍。dsh本體要裝好版本不要太舊因?yàn)椴寮C(jī)制在不同版本之間可能有差異。然后確認(rèn) profile 是干凈的避免舊配置干擾。我建議專門建一個(gè)實(shí)驗(yàn)用的 profile比如--profile waker_test在里面折騰。等跑通了再遷移到常用 profile。這樣即使搞壞了也不影響日常使用。依賴方面dsh-waker本身依賴dsh的核心能力另外如果你要用 IM 投遞需要確認(rèn) IM 通道是通的。我一般會(huì)先手動(dòng)發(fā)一條測試消息確認(rèn)通道沒問題再去配喚醒任務(wù)。這個(gè)順序很重要不然任務(wù)跑成功了但消息發(fā)不出去你會(huì)以為是任務(wù)的問題。4.2 第一個(gè)喚醒任務(wù)每日消息匯總拿一個(gè)最實(shí)用的場景來演示每天早上九點(diǎn)把過去一天的消息匯總成簡報(bào)推送到 IM。第一步定義觸發(fā)器。cron 表達(dá)式寫0 9 * * *意思是每天九點(diǎn)整。這里要注意時(shí)區(qū)dsh默認(rèn)用系統(tǒng)時(shí)區(qū)如果你的服務(wù)器時(shí)區(qū)和你不一致要顯式指定。第二步定義任務(wù)。任務(wù)描述我寫成這樣“讀取過去 24 小時(shí)內(nèi) IM 通道收到的所有消息按發(fā)送者分組每組提取關(guān)鍵信息生成一份不超過 500 字的簡報(bào)重點(diǎn)標(biāo)出包含疑問句的消息”。這個(gè)描述把時(shí)間范圍、數(shù)據(jù)來源、處理方式、輸出格式都說清楚了。第三步定義投遞。投遞到 IM設(shè)置重試三次重試間隔 30 秒。這樣即使第一次發(fā)送失敗后面還有機(jī)會(huì)。配置寫完之后先手動(dòng)觸發(fā)一次測試。dsh-waker一般提供手動(dòng)觸發(fā)命令用它跑一遍看看輸出是否符合預(yù)期。如果不符合調(diào)整任務(wù)描述再跑。這個(gè)迭代過程可能要來回幾次別嫌麻煩調(diào)好了之后就能長期穩(wěn)定運(yùn)行。4.3 參數(shù)計(jì)算重試策略怎么定重試策略看起來是個(gè)小配置但定不好會(huì)出問題。我來說說我的計(jì)算邏輯。假設(shè)單次投遞成功率是 95%那么失敗率是 5%。如果重試三次全部失敗的概率是 0.05 的三次方也就是 0.0125%基本可以忽略。所以三次重試對大多數(shù)場景足夠了。重試間隔怎么定太短了沒意義因?yàn)槿绻峭ǖ拦收隙虝r(shí)間重試大概率還是失敗。太長了又影響時(shí)效。我的經(jīng)驗(yàn)是 30 秒到 1 分鐘比較合適給通道一點(diǎn)恢復(fù)時(shí)間又不至于拖太久。如果任務(wù)本身對時(shí)效要求很高比如告警類那可以縮短間隔但重試次數(shù)要相應(yīng)減少避免消息延遲太久才到。這種場景下寧可快速失敗然后走備用通道也不要死等重試。4.4 實(shí)操現(xiàn)場一次完整的調(diào)試記錄我記錄一下自己第一次跑通的全過程給后面的同學(xué)一個(gè)參考。先是裝插件dsh plugin --profile waker_test add dshmarket然后從市場里找到dsh-waker裝上。裝完dsh plugin list確認(rèn)在列表里。然后寫配置。第一版配置我犯了個(gè)錯(cuò)把 cron 寫成了0 9 * * * *多了一個(gè)星號結(jié)果觸發(fā)異常。后來查文檔才知道dsh用的是五段式 cron不是六段式。這個(gè)坑很典型不同工具的 cron 格式不一樣一定要看文檔。改好之后手動(dòng)觸發(fā)任務(wù)跑了但輸出是一堆亂碼。排查發(fā)現(xiàn)是消息里的特殊字符沒處理。在任務(wù)描述里加了一句“過濾掉非文本內(nèi)容”問題解決。最后配投遞第一次發(fā)送失敗因?yàn)?IM 通道的 token 過期了。重新拿了一個(gè) token再跑就成功了。整個(gè)過程花了大概一個(gè)半小時(shí)其中一半時(shí)間花在排查那兩個(gè)坑上。但跑通之后這個(gè)任務(wù)就一直穩(wěn)定運(yùn)行到現(xiàn)在每天早上準(zhǔn)時(shí)給我推簡報(bào)。5. 常見問題與排查技巧實(shí)錄5.1 喚醒不觸發(fā)怎么辦這是最常見的問題。任務(wù)配好了但到點(diǎn)了沒反應(yīng)。排查順序我總結(jié)成三步。先看觸發(fā)器配置。cron 表達(dá)式對不對時(shí)區(qū)對不對profile 選對沒有。這幾個(gè)是最容易出錯(cuò)的。我遇到過配了半天發(fā)現(xiàn)改的是另一個(gè) profile 的配置白折騰。再看插件狀態(tài)。dsh plugin list看看dsh-waker是不是還在有沒有被禁用。有時(shí)候插件會(huì)因?yàn)橐蕾噯栴}自動(dòng)禁用列表里能看到狀態(tài)。最后看日志。dsh一般有日志輸出看看喚醒時(shí)刻有沒有相關(guān)記錄。如果日志里連觸發(fā)記錄都沒有那問題在觸發(fā)器如果有觸發(fā)記錄但任務(wù)沒跑那問題在任務(wù)定義。5.2 任務(wù)執(zhí)行結(jié)果不穩(wěn)定同樣的任務(wù)有時(shí)候輸出很好有時(shí)候一塌糊涂。這個(gè)問題多半出在任務(wù)描述上。描述太模糊是主因。AI 對模糊描述的理解每次可能不一樣導(dǎo)致輸出飄忽。解決辦法是把描述寫具體尤其是輸出格式最好給樣例。另一個(gè)原因是輸入數(shù)據(jù)本身波動(dòng)大。如果數(shù)據(jù)源內(nèi)容差異很大AI 處理起來自然不穩(wěn)定。這種情況可以考慮在任務(wù)里加一步預(yù)處理把輸入規(guī)范化之后再交給 AI。還有一個(gè)容易被忽略的點(diǎn)是模型選擇。不同模型對同一段描述的理解能力不一樣。如果任務(wù)比較復(fù)雜換一個(gè)能力更強(qiáng)的模型可能會(huì)有明顯改善。5.3 IM 投遞失敗排查投遞失敗的原因比較多我整理成一張表方便對照?,F(xiàn)象可能原因排查方法完全沒收到通道配置錯(cuò)誤手動(dòng)發(fā)測試消息確認(rèn)通道偶爾收不到觸發(fā)限流檢查發(fā)送頻率是否超限收到亂碼編碼問題檢查消息編碼設(shè)置收到但格式亂內(nèi)容含特殊字符在任務(wù)里加過濾步驟延遲很久才到重試間隔太長縮短重試間隔或減少重試次數(shù)這張表是我踩坑踩出來的基本覆蓋了大部分情況。遇到問題先對號入座能省不少時(shí)間。5.4 高頻喚醒導(dǎo)致的資源問題如果喚醒頻率設(shè)得太高會(huì)遇到資源問題。表現(xiàn)是任務(wù)開始排隊(duì)后面的任務(wù)等前面的跑完才執(zhí)行整體延遲越來越大。解決辦法有兩個(gè)方向。一是降低頻率把不必要的喚醒砍掉。二是優(yōu)化任務(wù)本身讓它跑得更快。比如把一個(gè)大任務(wù)拆成幾個(gè)小任務(wù)并行執(zhí)行。我自己的做法是給每個(gè)任務(wù)記錄執(zhí)行耗時(shí)定期 review。如果發(fā)現(xiàn)某個(gè)任務(wù)耗時(shí)明顯變長就去看看是不是數(shù)據(jù)量漲了或者描述需要優(yōu)化了。這個(gè)習(xí)慣幫我提前發(fā)現(xiàn)了好幾次潛在問題。提示給任務(wù)加一個(gè)超時(shí)設(shè)置。如果一個(gè)任務(wù)超過預(yù)期時(shí)間還沒跑完直接終止避免它卡住后面的任務(wù)。超時(shí)時(shí)間設(shè)成平均耗時(shí)的三到五倍比較合適。5.5 插件沖突的處理經(jīng)驗(yàn)插件裝多了之后沖突是難免的。表現(xiàn)可能是某個(gè)插件突然不工作或者dsh啟動(dòng)變慢。我的處理原則是保持插件數(shù)量精簡不用的及時(shí)卸載。定期用dsh plugin list過一遍看看有沒有裝了但從來沒用的。如果懷疑是沖突可以用 profile 隔離來定位。把可疑的插件單獨(dú)裝到一個(gè)干凈 profile 里看問題還在不在。如果在那就是插件本身的問題如果不在那就是和其他插件沖突。遇到?jīng)_突不要硬扛先卸載可疑插件確認(rèn)dsh恢復(fù)正常再一個(gè)一個(gè)加回來定位到具體是哪個(gè)插件引起的。這個(gè)過程有點(diǎn)繁瑣但比瞎猜有效。6. 進(jìn)階玩法把喚醒鏈路串成自動(dòng)化流水線6.1 鏈?zhǔn)絾拘训脑O(shè)計(jì)模式單個(gè)喚醒任務(wù)解決的是單點(diǎn)問題鏈?zhǔn)絾拘呀鉀Q的是流程問題。設(shè)計(jì)鏈?zhǔn)絾拘训臅r(shí)候我建議先把整個(gè)流程畫出來標(biāo)清楚每一步的輸入和輸出然后再對應(yīng)到喚醒任務(wù)上。比如一個(gè)內(nèi)容處理流程抓取內(nèi)容、清洗內(nèi)容、生成摘要、推送到 IM。這四步可以對應(yīng)四個(gè)喚醒任務(wù)前一個(gè)的輸出是后一個(gè)的輸入。串起來之后你只需要觸發(fā)第一個(gè)后面的自動(dòng)跑完。鏈?zhǔn)絾拘训年P(guān)鍵是錯(cuò)誤處理。如果中間某一步失敗了后面的步驟怎么辦我的做法是每一步都記錄狀態(tài)失敗的時(shí)候暫停鏈路推送一條告警等我手動(dòng)處理。這樣不會(huì)因?yàn)橐徊绞?dǎo)致整個(gè)流程亂掉。6.2 和文檔處理能力結(jié)合熱詞里有人問“dsh 實(shí)現(xiàn)讀取 world、pdf 等文檔內(nèi)容該如何實(shí)現(xiàn)”這其實(shí)可以和dsh-waker結(jié)合出一個(gè)很實(shí)用的場景。設(shè)想一下你有一個(gè)目錄里面會(huì)不斷有新文檔進(jìn)來。你配一個(gè)事件觸發(fā)的喚醒任務(wù)監(jiān)控這個(gè)目錄。一旦有新文檔喚醒一個(gè)處理任務(wù)讀取文檔內(nèi)容提取關(guān)鍵信息生成摘要推送到 IM。整個(gè)過程全自動(dòng)你只需要在 IM 里看結(jié)果。這個(gè)場景我在實(shí)際工作中用過處理的是各種報(bào)告文檔。以前要手動(dòng)打開一個(gè)個(gè)看現(xiàn)在自動(dòng)匯總效率提升很明顯。文檔讀取這塊dsh本身有相關(guān)能力配合dsh-waker的觸發(fā)機(jī)制就能串起來。6.3 多任務(wù)并發(fā)的調(diào)度思路當(dāng)喚醒任務(wù)多起來之后調(diào)度就成了問題。如果所有任務(wù)都在同一時(shí)間觸發(fā)資源會(huì)瞬間吃緊。我的做法是錯(cuò)峰。把定時(shí)任務(wù)的時(shí)間點(diǎn)錯(cuò)開比如匯總?cè)蝿?wù)放在整點(diǎn)提醒任務(wù)放在半點(diǎn)清理任務(wù)放在凌晨。這樣資源使用比較平滑。對于事件觸發(fā)的任務(wù)可以加一個(gè)隊(duì)列機(jī)制。任務(wù)進(jìn)來先排隊(duì)按順序執(zhí)行避免并發(fā)太多。dsh-waker本身可能不帶隊(duì)列但可以通過配置或者外部腳本來實(shí)現(xiàn)。還有一個(gè)技巧是給任務(wù)分優(yōu)先級。重要的任務(wù)優(yōu)先執(zhí)行不重要的可以延后。這個(gè)在任務(wù)多的時(shí)候特別有用能保證關(guān)鍵任務(wù)不被拖累。6.4 喚醒日志的分析與優(yōu)化日志是個(gè)寶庫但很多人不看。我養(yǎng)成了一個(gè)習(xí)慣每周花十分鐘過一遍喚醒日志看看有沒有異常。重點(diǎn)看幾個(gè)指標(biāo)觸發(fā)次數(shù)、成功次數(shù)、平均耗時(shí)、失敗原因分布。如果發(fā)現(xiàn)某個(gè)任務(wù)失敗率偏高就去優(yōu)化它。如果發(fā)現(xiàn)某個(gè)任務(wù)耗時(shí)越來越長就去看看是不是數(shù)據(jù)量漲了。有一次我從日志里發(fā)現(xiàn)一個(gè)任務(wù)每天觸發(fā)但輸出從來沒人看果斷把它關(guān)了。這種“僵尸任務(wù)”很常見定期清理能省不少資源。日志分析還能幫你發(fā)現(xiàn)新的自動(dòng)化機(jī)會(huì)。比如你發(fā)現(xiàn)某個(gè)操作每周都要手動(dòng)做那就可以考慮配一個(gè)喚醒任務(wù)把它自動(dòng)化掉。7. 我踩過的坑和攢下的經(jīng)驗(yàn)7.1 關(guān)于任務(wù)描述的幾條鐵律折騰了這么久我總結(jié)出幾條關(guān)于任務(wù)描述的鐵律分享出來。第一條永遠(yuǎn)不要用“整理一下”“處理一下”這種模糊動(dòng)詞。換成具體的動(dòng)作比如“按主題分組”“提取待辦項(xiàng)”“生成摘要”。第二條輸出格式一定要明確。能用樣例就用樣例樣例比文字描述有效十倍。第三條給任務(wù)起個(gè)能看懂的名字。morning_digest比task1好weekly_report比w2好。名字清晰后面維護(hù)的時(shí)候省心。第四條描述里帶上邊界條件。比如“如果消息少于 5 條就只列出標(biāo)題不生成摘要”。邊界條件能避免任務(wù)在異常情況下輸出奇怪的結(jié)果。7.2 關(guān)于頻率設(shè)置的實(shí)戰(zhàn)心得頻率設(shè)置這件事我的心得是“寧低勿高”。一開始設(shè)低一點(diǎn)觀察一段時(shí)間確實(shí)需要再往上調(diào)。反過來設(shè)高了再往下降中間浪費(fèi)的資源就白費(fèi)了。另外不同任務(wù)的頻率要區(qū)別對待。匯總類任務(wù)可以低頻提醒類任務(wù)可以中頻告警類任務(wù)才需要高頻。不要所有任務(wù)都用同一個(gè)頻率。還有一個(gè)細(xì)節(jié)是避開整點(diǎn)。很多系統(tǒng)都在整點(diǎn)做事情整點(diǎn)觸發(fā)容易撞車。我一般把任務(wù)設(shè)在整點(diǎn)后幾分鐘比如九點(diǎn)零三分避開高峰。7.3 關(guān)于插件管理的經(jīng)驗(yàn)插件管理這塊我的原則是“少而精”。裝之前先想清楚這個(gè)插件解決什么問題解決不了就不裝。裝了之后定期 review不用的及時(shí)卸。更新插件要謹(jǐn)慎。新版本可能引入新問題尤其是核心插件。我一般會(huì)先在測試 profile 里更新跑幾天沒問題再更新到常用 profile。遇到插件問題先看文檔再看 issue最后再自己排查。很多問題別人已經(jīng)遇到過了搜一下能省很多時(shí)間。7.4 關(guān)于 IM 推送的體驗(yàn)優(yōu)化IM 推送的體驗(yàn)很重要推得不好會(huì)變成騷擾。我的優(yōu)化經(jīng)驗(yàn)有這么幾條。一是控制頻率。同一個(gè)任務(wù)一天推太多次用戶會(huì)煩。我一般把匯總類任務(wù)控制在每天一到兩次。二是內(nèi)容要精煉。IM 消息太長沒人看盡量控制在手機(jī)一屏能看完。詳細(xì)內(nèi)容可以放鏈接或者附件。三是格式要清晰。用標(biāo)題、列表、加粗把重點(diǎn)標(biāo)出來讓人一眼能看到關(guān)鍵信息。四是提供反饋入口。如果推送內(nèi)容有問題用戶能方便地反饋這樣你才能持續(xù)優(yōu)化。7.5 后續(xù)可以擴(kuò)展的方向這套東西跑通之后能擴(kuò)展的方向其實(shí)很多。一個(gè)是接入更多數(shù)據(jù)源。現(xiàn)在處理的是 IM 消息以后可以接入郵件、文檔、網(wǎng)頁等各種來源讓 AI 員工看到的信息更全面。一個(gè)是增加更多動(dòng)作?,F(xiàn)在主要是推送以后可以讓 AI 員工直接執(zhí)行操作比如回復(fù)消息、創(chuàng)建任務(wù)、更新文檔。一個(gè)是做多員工協(xié)作。一個(gè) AI 員工處理一類事情多個(gè)員工之間可以互相喚醒、傳遞任務(wù)形成一個(gè)完整的自動(dòng)化團(tuán)隊(duì)。這些方向我自己也在慢慢嘗試等有成熟經(jīng)驗(yàn)了再分享出來。目前這套dsh-waker的用法已經(jīng)足夠覆蓋大部分個(gè)人和小團(tuán)隊(duì)的自動(dòng)化需求了。