一文講透AI Agent開發(fā)中的human-in-the-loop
前段時間確實有點忙,好久沒有發(fā)文了。不過最近有好多AI技術(shù)方面的想法要跟大家分享:-)
今天我們主要聊一聊在AI Agent開發(fā)中非常重要的一個特性:human-in-the-loop。
為什么需要human-in-the-loop?
我們在以前的文章中曾經(jīng)討論過在AI Agent開發(fā)中確定性和自主性的關(guān)系問題。自主性帶來智能的行為和新的可能性,但軟件的交付需要為客戶提供確定性。這兩者可以說是一對矛盾。
于是,在Agent的執(zhí)行過程中引入人工確認,就成了消除不確定性的一種思路。想象一個做自動化運維的Agent,它在決定往生產(chǎn)環(huán)境部署一個服務(wù)之前,很可能需要獲得管理員的核準(zhǔn)才能繼續(xù)運行。再想象一個做客戶關(guān)系維護的Agent,它自動閱讀了客戶郵件,然后撰寫了一封回復(fù)郵件,這個時候它在真正發(fā)送這封郵件之前,可能也需要先經(jīng)過人工審核才能發(fā)送。而且,審核人員如果覺得郵件內(nèi)容有欠妥的地方,可能還會給出具體的修改建議。Agent就可以根據(jù)人類建議對郵件內(nèi)容進行修改,然后再繼續(xù)執(zhí)行。
AI的產(chǎn)品形式早已不再局限于chat式的一問一答。很多Agent可以長時間運行,比如,在連續(xù)運行幾分鐘甚至幾小時后向人類交付結(jié)果。在企業(yè)環(huán)境下,你可以把這種新型的AI Agent想象成一個數(shù)字員工。它在業(yè)務(wù)水平上可能只有實習(xí)生的水平,但明顯的優(yōu)勢就是不怕累,可以不眠不休地干著重復(fù)性的工作。
當(dāng)然,它在行為方式上也跟實習(xí)生類似。想象公司里來了一名實習(xí)生,領(lǐng)導(dǎo)讓你帶著他干活。于是你交給了他一項任務(wù),他就跑到旁邊默默地去干了。在干的過程中,他碰到了一個棘手的問題,卡住了。他就會來找你請教,這個情況應(yīng)該怎么處理。這個時候,你只需要給他一些指導(dǎo),他就又重新投入到工作中去了。你要做的,只是提供必要的指導(dǎo),而不用親自動手去完成所有的事情,負擔(dān)果然減輕了不少啊。如果這名實習(xí)生是一個虛擬的AI Agent呢?那么,它主動來找你提供指導(dǎo),就是一種human-in-the-loop。作為一名虛擬的“實習(xí)生”,這個AI Agent在運行過程中如果碰到棘手的問題,或者待決斷的問題,它就會停下來,然后通過各種渠道(比如IM、郵件)來找你。等到你有空了,回復(fù)它一下,并提供必要的處理指令,它就繼續(xù)干活兒去了。
從抽象層面來看,在這樣的一個處理過程中,人類被AI Agent牽涉其中,成為了Agent為了完成其自主操作的其中一環(huán)。這也是為什么這個機制稱為human-in-the-loop。人類在提供核準(zhǔn)或者指導(dǎo)意見的時候,我們一方面可以看做是,人類為AI Agent的運行提供了更具體、更準(zhǔn)確的上下文;另一方面也可以看做是,AI把人當(dāng)做了“工具”,它在必要的時候(通常是比較難處理的時候),把人類當(dāng)做一個工具來調(diào)用了(而且這個工具相當(dāng)智能和權(quán)威)。
跟實現(xiàn)有關(guān)的技術(shù)因素
現(xiàn)在,我們來思考一下,如何在技術(shù)層面來實現(xiàn)這種human-in-the-loop的機制。有哪些關(guān)鍵的技術(shù)因素需要考慮?
根據(jù)上一節(jié)的描述,AI Agent需要在執(zhí)行過程中“停下來”,然后在跟人類完成交互后,再繼續(xù)運行。有人可能會說,很多編程語言都有await的機制,是不是用await就能實現(xiàn)“停下來再繼續(xù)運行”的效果?
這當(dāng)然不是問題的全部。我們需要到真正的生產(chǎn)環(huán)境中去考慮這個問題。在生產(chǎn)環(huán)境中,有一些復(fù)雜的系統(tǒng)架構(gòu)方面的因素需要考慮。其中有兩個因素,對于如何實現(xiàn)human-in-the-loop有關(guān)鍵的影響:
- 第一個是分布式。
- 第二個是用戶和AI Agent之間的通道性質(zhì)。
我們先來討論第一個因素——“分布式”架構(gòu)的影響。一般來說,生產(chǎn)環(huán)境都不止一臺服務(wù)器,很可能是一個包含多個機器節(jié)點的Agent集群。如下圖,左邊是server端,右邊是client端。
圖片
從上圖我們發(fā)現(xiàn),一個human-in-the-loop交互是由server端主動發(fā)起的。這跟傳統(tǒng)的互聯(lián)網(wǎng)應(yīng)用開發(fā)不太一樣。
假設(shè)一個AI Agent運行在節(jié)點A上。它在執(zhí)行過程中發(fā)生了某種特殊事件,于是發(fā)起了一個human-in-the-loop的交互。也就是說,它通過某種通道向client端發(fā)送request,請求人類的介入。假設(shè)用戶收到了來自Agent的這個請求,并給出了自己的反饋 (feedback) 。接下來,client端需要把這個feedback發(fā)送回server端。由于server端有多個服務(wù)器節(jié)點,一般來說,來自client端的網(wǎng)絡(luò)請求會被隨機分配到某個服務(wù)器節(jié)點上。這樣就會導(dǎo)致,來自client的feedback信息,未必會落在當(dāng)初發(fā)起human-in-the-loop請求的節(jié)點A上;同時,節(jié)點A由于收不到feedback而沒法把human-in-the-loop繼續(xù)下去。
之所以會出現(xiàn)上面的問題,除了分布式集群帶來的影響之外,還有一個原因是,用戶和AI Agent之間的通信通道沒有能夠做到會話保持 (session sticky) 。根據(jù)場景和運行環(huán)境的不同,用戶和AI Agent之間的通道性質(zhì)可能呈現(xiàn)很大的差異。下面是幾種典型的情況:
- 第一種情況,client端和server端之間使用HTTP協(xié)議通信。這種情況下,請求必須由client端主動發(fā)起,server端才能夠執(zhí)行并做出響應(yīng)。顯然這種情況是沒法支持上圖中AI Agent主動向client端發(fā)起請求的。
- 第二種情況,client端和server端之間使用某種長連接進行通信(比如WebSocket)。這種情況下,不管是client端還是server端,都可以隨時向?qū)Ψ街鲃影l(fā)起請求。而且,在上圖中client端發(fā)回server端的feedback,仍然會沿著長連接發(fā)到節(jié)點A。用戶和AI Agent之間,很容易在一條長連接上做到會話保持,也就比較容易支持human-in-the-loop這種由Agent主動發(fā)起的交互。下圖展示了這種情況下的human-in-the-loop交互。
圖片
針對以上兩種情況,還有一些技術(shù)實現(xiàn)上需要注意的地方。
首先對于第一種情況,我們在AI應(yīng)用開發(fā)中經(jīng)常使用的SSE技術(shù) (Server-Sent Events) ,它屬于HTTP協(xié)議,也具備一定的「server push」的能力,但仍然支持不了讓AI Agent主動發(fā)起請求。原因在于,SSE依賴client端先建立起同server端的連接之后,server端才能向這個連接進行push。換句話說,SSE本質(zhì)上其實還是由client主動發(fā)起交互的,用于實現(xiàn)一些流式的效果,但server端不能隨時發(fā)起一個交互(至少在一個常規(guī)的實現(xiàn)中是這樣的)。
還有一個需要注意的地方是,Agent集群外面可能存在一個網(wǎng)關(guān),所有client都通過這個網(wǎng)關(guān)與后面的server建立連接。這時候,要實現(xiàn)server主動發(fā)起交互并且做到會話保持,首先要求client和網(wǎng)關(guān)之間是某種長連接,其次還要求網(wǎng)關(guān)具備會話保持的能力,有能力將server主動發(fā)起的request和來自client的feedback保持在一個會話內(nèi)。這樣,整個human-in-the-loop的流程才能由節(jié)點A來全部完成。
不管怎么說,在以上這兩種情況下,用戶和AI Agent之間的通信通道對于開發(fā)者來說,還是可控的。但還有第三種情況,這個通道是由第三方提供的,它的性質(zhì)是開發(fā)人員控制不了的。如下圖:
圖片
- 第三種情況,client端和server端之間通過某種異步通信網(wǎng)絡(luò)進行通信。這種通信網(wǎng)絡(luò),一般來說是由第三方提供的。比如說,用戶可能通過IM窗口跟Agent進行交互。這時候,client端和server端之間自然建立不起長連接。節(jié)點A發(fā)起的human-in-the-loop的request,其對應(yīng)的feedback也大概率無法保證仍然由節(jié)點A接收到。
考慮到以上這些因素,服務(wù)端對于human-in-the-loop的實現(xiàn),就需要不同的技術(shù)方案。
兩種技術(shù)方案
我們把前面幾種情況分成兩類:
(1)client端和server端之間具備長連接的條件,且能夠做到會話保持的。主要是第二種情況。
(2)client端和server端之間無法保持會話的。包括第一種情況和第三種情況。
對于(1),我們可以利用長連接和會話保持的優(yōu)勢,讓server端的一個節(jié)點完成human-in-the-loop的整個交互過程。這樣server端的實現(xiàn)就會簡單很多。以Python語言為例,human-in-the-loop的機制可以這樣實現(xiàn):
- Agent通過長連接向用戶發(fā)送一個交互請求。
- Agent使用await機制等待在一個future對象上,即,等待client端響應(yīng)。
- 用戶處理這個請求,給出核準(zhǔn)或指導(dǎo)意見,client端以feedback的形式,通過長連接發(fā)回給Agent所在的server節(jié)點。
- server節(jié)點的上層代碼為前面的future對象設(shè)置結(jié)果。
- Agent從等待future對象的狀態(tài)中恢復(fù),并從future對象中拿到用戶的feedback。
- Agent基于用戶的feedback繼續(xù)執(zhí)行。一個human-in-the-loop的過程結(jié)束。
當(dāng)然,這種實現(xiàn)方式對于基礎(chǔ)設(shè)施存在比較高的要求,維護長連接和保持會話,通常不是那么容易的事。而且,系統(tǒng)本身維持長連接也是有成本的。
對于(2),client端和server端無法保持會話,來自用戶的feedback可能落在任意server節(jié)點上。這時只有一種辦法:對Agent的整個運行狀態(tài)進行序列化、持久化、反序列化。整個技術(shù)處理流程較復(fù)雜,如下:
- Agent向用戶發(fā)送一個交互請求。
- Agent將內(nèi)部運行狀態(tài)進行序列化,并停止運行。
- server節(jié)點的上層代碼將Agent序列化后的數(shù)據(jù)存入DB,完成持久化。同時,已經(jīng)停止的Agent實例,不再需要保持在內(nèi)存中。
- 用戶處理這個請求,給出核準(zhǔn)或指導(dǎo)意見,client端以feedback的形式,發(fā)回到server端任意一個節(jié)點上。
- 收到feedback的節(jié)點從DB中加載前面序列化的數(shù)據(jù),并在內(nèi)存中反序列化,重新創(chuàng)建出Agent實例。注意,這個Agent實例保持了運行狀態(tài),它知道自己下一步該從哪里繼續(xù)運行。
- 反序列化后的Agent從之前中斷的地方恢復(fù),并拿到來自用戶的feedback。
- Agent基于用戶的feedback繼續(xù)執(zhí)行。一個human-in-the-loop的過程結(jié)束。
關(guān)于序列化和反序列化
有人可能會問,什么是序列化和反序列化呢?簡單來說,序列化是把一個內(nèi)存對象轉(zhuǎn)成一串bytes或string的過程;而反序列化是從一串bytes或string中恢復(fù)一個內(nèi)存對象的過程。
不得不說的是,把一個復(fù)雜對象進行序列化和反序列化,不是一件容易的事。為什么這么說呢?難度來源于對象之間的關(guān)系:
- 一個復(fù)雜的對象,可能引用了其他對象;而其他對象又引用了更多對象。
- 面向?qū)ο缶幊處淼膍ethod和對象實例之間的綁定關(guān)系,也為序列化和反序列化帶來了諸多麻煩。
假設(shè)僅僅是對于某個數(shù)據(jù)對象進行序列化和反序列化,情況可能尚在可控范圍內(nèi)。數(shù)據(jù)對象通常只包含數(shù)據(jù)字段,數(shù)據(jù)對象之間的引用關(guān)系一般也呈現(xiàn)單向的引用關(guān)系。但讓問題更復(fù)雜的是,Agent對象不僅僅是一個數(shù)據(jù)對象,它更是一個包含運行行為的運行時對象。運行時對象之間,可能存在錯綜復(fù)雜的引用關(guān)系。
總之,我們必須謹慎地選擇,把哪些信息放到序列化的數(shù)據(jù)之中,哪些不放。通常來說,應(yīng)該只序列化那些必要的、動態(tài)的數(shù)據(jù),而其他信息可以盡量保留在代碼中。以后有機會了我們再仔細展開這個話題。
小結(jié)
今天我們探討了human-in-the-loop這種機制,它出現(xiàn)的技術(shù)背景、兩種不同的實現(xiàn)思路,以及中間的成本和難點。

































