華爲“天才少年”4萬字演講:現在的AI技術要麽無趣,要麽無用-(5)
因此,我們在分段總結的基礎上,再讓大模型分別生成分話題的分類總結和全局的用戶記憶概要。分話題的分類總結,就是根據文本總結內容確定是哪個話題的,然後把相關話題的原有總結內容加上新的聊天記錄,更新這個話題的文本總結。這些分話題的總結也放進數據庫用來做 RAG,但是它在搜索結果排序時候的權重比原始聊天記錄總結更高,因爲分話題的總結信息密度更高。
而全局記憶概要就是一個不斷更新的全局總結,包括用戶的基本信息,興趣愛好和性格特征等。我們知道一般 system prompt 就是一個角色的設定,那麽這個全局記憶概要可以認爲是角色對用戶的核心記憶,每次請求大模型的時候都會帶著。
大模型的輸入包括角色的設定、最近對話、全局記憶概要、經過 RAG 的聊天記錄分段總結和分類總結。這個長期記憶的方案不需要很高的長上下文成本,但在很多場景下都是比較實用的。
現在 AI Agent 對每個用戶的記憶都是隔離的,這樣在多人社交的時候就會遇到很多問題。
比如 Alice 告訴 AI 一個知識,AI 跟 Bob 聊天的時候,現在肯定是不知道這個知識的。但是簡單把所有用戶的記憶都堆在一起,是不是就解決問題了呢?也不是,比如 Alice 告訴 AI 一個秘密,AI 跟 Bob 聊天的時候,一般來說就不應該把這個秘密透露出去的。
因此這裏面就應該有個社交規則的概念。一個人在討論一件事情的時候,會回憶起很多不同人的記憶片段。跟當前正在聊的這個人的記憶片段肯定是最重要的,在 RAG 搜索結果排序的時候應該權重是最高的。但跟其他人的記憶片段也應該檢索出來,並且在生成的時候參考社交規則來決定用不用,該怎麽用。
除了跟多個用戶、多個 Agent 社交,AI Agent 還應該能夠聽從創作者的指示,與創作者共同進化。現在的 AI Agent 都是通過固定的 prompt 加樣例對話的方式來調教,大多數創作者調 prompt 需要花很多時間。我認爲 AI Agent 的創作者應該可以通過聊天的方式塑造 Agent 的個性,就像養電子寵物一樣。
比如某一次聊天 Agent 表現不好,我告訴她不要這麽做了,她就應該記住以後不這麽做了。或者告訴 AI Agent 某一件事情或者某個知識,她也應該能夠在日後的聊天中回憶起來。一種簡單的實現方法就是類似 MemGPT 這樣,當創作者給指示的時候,就把這些指示記錄到小本本上,然後通過 RAG 的方式提取出來。ChatGPT 2024 年 2 月上線的記憶功能就是用簡化版的 MemGPT 方法實現的,它沒有 RAG 這麽複雜,只是把用戶告訴它要記住的內容記錄到小本本上。
記憶並不僅僅是記住知識和過去的交互經曆,我認爲記憶做好了,有可能就是 AI 自我意識的開端。
我們現在的大模型爲什麽沒有自我意識?這並不是自回歸模型本身的鍋,而是 OpenAI API 這種一問一答的用法導致的。ChatGPT 是個多輪問答系統,俗稱聊天機器人,而不是通用智能。
在 OpenAI API 目前的用法中,大模型的輸入是聊天記錄和最近的用戶輸入,組織成用戶消息和 AI 消息一問一答的形式,輸入到大模型。大模型的所有輸出都直接返回給用戶,同時追加到聊天記錄裏。
那麽只看到聊天記錄的這種方法有什麽問題呢?大模型缺少自己的思考。我們人類在思考問題時,有些思考是不輸出到外部的。這就是 Chain-of-Thought(思維鏈)方法爲什麽能夠提升模型性能。此外,所有原始聊天記錄是原汁原味輸入給了大模型,其中的信息沒有經過任何分析和整理,這樣能提取出的只是表面的信息,但很難提取出邏輯深度比較深的信息。
我發現現在很多人天天在研究 prompt 工程,但很少有人嘗試在自回歸模型的輸入輸出格式上做文章。舉個最簡單的例子,OpenAI 有個強制輸出 json 格式的功能,怎麽實現的呢?其實就是在輸出的開頭先放上 “```json” 這個前綴,這樣自回歸模型在預測下一個 token 的時候,就知道後面輸出的一定是 json 代碼。這是比在 prompt 裏面寫上 “請用 json 格式輸出” 或者 “請以 ```json 開頭輸出” 靠譜很多的。
要讓模型有自己的思考,最關鍵的就是要把思考的片段和外界輸入輸出的片段在自回歸模型輸入 token 的層面上就分隔開,就像是現在有 system、user 和 assistant 這些特殊 token,可以增加一個 thought。這個 thought 就是大模型的工作記憶。
我們也應該注意到,目前 OpenAI API 這種模型與世界的交互方式本質上還是批處理式而非流式的,每次 OpenAI API 調用都是無狀態的,需要帶上前面的所有聊天記錄,重複計算所有的 KV Cache。當上下文比較長的時候,這個重複計算 KV Cache 的開銷是相當高的。如果我們把 AI Agent 想象成一個實時與世界交互的人,它其實是不斷在流式接受外界的輸入 token,KV Cache 是一直在 GPU 內存裏或者臨時換出到 CPU 內存裏,這樣 KV Cache 就是 AI Agent 的工作記憶,或者說 AI Agent 的狀態。
那麽工作記憶中應該包括什麽呢?我認爲工作記憶最重要的就是 AI 對自己的感知,以及 AI 對用戶的感知,這兩者缺一不可。
早在 2018 年,我們基于 RNN 這套老方法搞微軟小冰的時候,就做了一個情感系統,其中用一個向量 Eq 表示用戶的狀態,比如用戶在討論的話題、用戶的意圖、情緒狀態,以及年齡、性別、興趣、職業、性格等基本信息。再用一個向量 Er 表示小冰的狀態,也包括正在討論的話題、小冰的意圖、情緒狀態,以及年齡、性別、興趣、職業、性格等基本信息。
這樣一來,雖然語言模型的能力相比今天的大模型是弱爆了,但至少能穩定的回答 “你幾歲了” 這種問題,不會一會兒說自己 18 歲,一會兒說自己 28 歲了。小冰也能夠記住用戶的一些基本信息,不至于感覺每次聊天都很陌生。
今天的很多 AI Agent 卻沒有在工程上做好這些優化,比如 prompt 裏面沒有寫清楚 AI 角色目前的設定,就沒辦法穩定回答自己幾歲;只是記錄最近的聊天記錄而沒有做記憶系統,那也記不住用戶幾歲。
有趣的靈魂:社交能力
下一個問題就是 AI agent 會不會主動關心人。看起來主動關心是個很高級的能力,其實一點也不難。我主動關心老婆,是因爲每天會想起來她好幾次。只要想起來了,結合前面說過的話,就會自然去關心人。
對于 AI 來說,只要讓 AI 有一個內部的思考狀態,也就是前面提到的工作記憶,然後每小時自動喚醒一次就行了。
比如用戶說了第二天要去醫院看病,那麽第二天的時間到了,我告訴大模型當前時間和工作記憶,大模型就會輸出關心人的話,並且更新工作記憶。工作記憶更新之後,大模型知道用戶還沒有回複,就知道不要不斷騷擾用戶。
與之相關的一個問題是 AI Agent 會不會主動聯系用戶,會不會主動開啓話題。
人類有說不完的話題是因爲每個人都有自己的生活,在好朋友面前就是有分享欲的。因此名人的數字分身就相對比較容易做主動分享,因爲名人有很多公開的新聞事件,可以經常分享給用戶。對于一個虛構的人物形象,有可能就需要運營團隊來給虛構形象設計自己的生活了。所以我一直認爲純閑聊很容易導致用戶不知道該聊什麽,AI Agent 一定要有故事性才能長期吸引用戶。
除了分享個人生活,還有很多開啓話題的方式,例如:
分享當前的心情和感受;
分享一下用戶可能感興趣的最新內容,就像抖音的推薦系統;
回憶過去,例如紀念日,美好的回憶;
最笨的方法就是通用的打招呼類問題,比如 “在幹嘛?” “我想你了”。
當然作爲一個高情商的 AI Agent,什麽情況下要關心,什麽情況下要主動分享,是需要跟當前 AI 對用戶和自己的感知相關的。比如如果一個女生對我不感興趣,我卻總是給她一天發很多生活日常,那估計過不了幾天就被拉黑了。同樣,如果 AI Agent 跟用戶還沒聊幾句,就天天給推送內容,用戶只會把它當作廣告。
我自己之前是比較內向的,很少有情緒波動,不會拒絕別人,也害怕被別人拒絕,因此不敢主動追妹子,也從來沒有被妹子拉黑過。還好我很幸運地遇到了合適的妹子,所以才沒有落到 “我今年 30 歲了,跟很多校友一樣,還沒有談過戀愛” 這種地步。現在的 AI Agent 也是跟我一樣沒有情緒波動,不會拒絕用戶,也不會說可能讓人傷心、反感或者生氣的話,因此自然也很難跟用戶主動建立深層的陪伴關系。在虛擬男女友這個賽道上,目前的 AI Agent 産品還是主要靠打擦邊球,還做不到基于信任的長期陪伴。
AI Agent 如何關心人、如何主動開啓話題,是社交技巧的一方面。多個 AI Agent 如何社交,是更難也更有趣的一件事情,比如狼人殺、誰是臥底之類經典的社交推理類遊戲。
狼人殺的核心是隱藏自己的身份,並識破其他人僞裝的身份。隱瞞和欺騙其實是跟 AI 的價值觀不符的,因此有時候 GPT-4 會不配合。特別是狼人殺裏面的 “殺” 字,GPT-4 會說,我是一個 AI 模型,不能殺人。但把 “殺” 字改成 “移除” 或者 “流放”,GPT-4 就可以幹活了。因此我們可以看到,在角色扮演場景下如果 AI 演的入戲,那就是老奶奶漏洞;如果 AI 拒絕演戲,那就沒有完成角色扮演的任務。
這就體現了 AI 在安全性和有用性之間的矛盾。一般我們評估大模型時,都要同時報告這兩個指標。一個什麽都不回答的模型安全性最高,但有用性最低;一個口無遮攔的未對齊模型有用性更強,但是安全性就很低。OpenAI 因爲需要承擔很多社會責任,就需要犧牲一些有用性來換取安全性。Google 是一個更大的公司,政治正確的要求更高,在有用性和安全性之間就更偏向安全性。
要從多輪對話中發現破綻並識破謊言,需要比較強的推理能力,GPT-3.5 級別的模型很難做到,需要 GPT-4 級別的模型。但如果簡單將完整的曆史發言交給大模型,信息分散在大量沒有太多營養的發言和投票中,一些發言之間的邏輯關聯還是很難被發現。因此我們可以采用 MemGPT 的方法,把遊戲狀態和每一輪的發言進行總結,這樣不僅節約 token,還能提高推理效果。
此外,在投票環節下,大模型如果僅僅輸出一個代表玩家編號的數字,經常由于思考深度不足導致胡亂投票。因此,我們可以采用先想後說(Chain of Thought)的方法,首先輸出分析文本,再輸出投票結果。發言環節也是類似的,先輸出分析文本,再簡潔地發言。
狼人殺中的 AI Agent 是按順序發言的,不存在搶麥的問題。那麽如果是幾個 AI Agent 就一個話題自由討論,它們能不能像正常人一樣交流,既不冷場又不互相搶麥?爲了達到比較好的用戶體驗,我們希望不僅僅局限于文字,讓這些 AI Agent 在一個語音會議裏吵架或者演繹劇情,這可以實現嗎?
其實有很多工程的方法可以做,比如首先讓大模型選擇發言角色,再調用對應的角色去發言。這樣相當于增加了發言延遲,但可以徹底避免搶麥或者冷場。更類似真人討論的方法是,各個角色分別以一定的概率發言,遇到搶麥就退讓。或者在發言之前先判斷前面的對話跟當前角色是否相關,不相關就不發言。
但是我們有更根本的一種方法:讓大模型的輸入輸出都變成一個持續的 token 流,而不是像現在 OpenAI 的 API 這樣每次都輸入一個完整的 context。Transformer 模型它本身就是自回歸的,源源不斷地接收從語音識別過來的外部輸入 token,也在不斷接收自己前面內部思考的 token。它可以輸出 token 到外部的語音合成,也可以輸出 token 給自己思考。
當我們把大模型的輸入輸出都變成流式的之後,大模型就變成有狀態的了,也就是 KV Cache 需要持久駐留在 GPU 內。語音輸入 token 的速度一般不超過每秒 5 個,語音合成 token 的速度一般也不超過每秒 5 個,但是大模型本身輸出 token 的速度可以達到每秒 50 個以上。這樣如果 KV Cache 持久駐留在 GPU 內,並且沒有太多內部思考的話,GPU 裏的內存大多數時間是閑置的。
因此可以考慮做持久化 KV Cache,把 KV Cache 從 GPU 內存傳出到 CPU 內存,下一次輸入 token 的時候再把 KV Cache 加載進來。例如對于 7B 模型,用了 GQA 優化之後,典型的 KV Cache 在 100 MB 以下,通過 PCIe 傳出再傳入只需要 10 毫秒。如果我們每秒加載一次 KV Cache 做一次推理,處理一組幾個語音識別出來的輸入 token,不會太影響整個系統的性能。
這樣換入換出的性能損失是比重新輸入上下文,重新計算 KV Cache 更低的。但至今沒有哪家模型推理提供商做這種基于持久化 KV Cache 的 API,我猜測主要是應用場景問題。
大多數類似 ChatGPT 的場景中,用戶與 AI Agent 的交互並不是實時的,有可能 AI 說了一句話後用戶好幾分鍾不說話,這樣持久化 KV Cache 占據大量 CPU 內存空間,就會帶來很大的內存成本。因此這種持久化 KV Cache 最適合的場景也許就是我們剛討論的實時語音聊天,只有輸入流的間隔足夠短,存儲持久化 KV Cache 的開銷可能才更低。因此我認爲 AI Infra 一定要跟應用場景結合,如果沒有好的應用場景驅動,很多 infra 優化都沒法做。
如果我們有 Grace Hopper 這樣的統一內存架構,由于 CPU 內存和 GPU 之間的帶寬大了,持久化 KV Cache 的換入換出代價會更低。但統一內存的容量成本也比主機的 DDR 內存更高,因此會對應用場景的實時性更加挑剔。
上面一頁講的多 Agent 互動方案中,還是依靠語音識別和語音合成來把語音轉換成 token 的。前面我們在多模態大模型方案中分析過,這種方案大概需要 2 秒的延遲,包括停頓檢測 0.5s + 語音識別 0.5s + 大模型 0.5s + 語音合成 0.5s。這裏面每一項都可以優化,比如我們已經優化到 1.5 秒,但是很難優化到 1 秒內。
爲什麽這種語音方案延遲高呢?根本上是因爲語音識別和合成過程需要按句子 “翻譯”,而不完全是流式的。