:打造有記憶、會(huì)等待的陪伴型AI角色)
「主人歡迎回來我一直在?!埂绻谝欢蜭ive2D模型展示視頻里看到這句臺(tái)詞我猜很多人會(huì)多點(diǎn)幾秒播放時(shí)間。這句話之所以吸引人不只因?yàn)樗鼛榫w更因?yàn)樗凳玖艘粋€(gè)技術(shù)事實(shí)屏幕里的兔子角色是“等”著你回來的。它知道你離開過也認(rèn)得出你回來。這一層的技術(shù)含量和傳統(tǒng)Live2D立繪播放歡迎語完全不同。這里要先把結(jié)論放前面一個(gè)看起來“活過來”的陪伴型AI角色難點(diǎn)不在Live2D模型本身也不只是接一個(gè)大模型接口而在渲染、對(duì)話、記憶、狀態(tài)管理這幾層如何串成一條能持續(xù)運(yùn)轉(zhuǎn)的流水線。換句話說把兔子建模做出來是美術(shù)問題讓兔子開口說話是接口問題讓兔子“一直在”才是系統(tǒng)工程問題。下面從一個(gè)開源項(xiàng)目my_ai_townAI小鎮(zhèn)的視角切入重點(diǎn)拆解這類陪伴型AI角色的構(gòu)成和落地路徑。我沒有把它當(dāng)成一個(gè)達(dá)到生產(chǎn)級(jí)的產(chǎn)品而是當(dāng)成一個(gè)非常典型的工程樣本來分析。目標(biāo)很簡(jiǎn)單如果你也想做一個(gè)自己的Live2D AI兔兔應(yīng)該從哪里開始哪些環(huán)節(jié)最容易翻車。1. 從“歡迎回來”這句臺(tái)詞看AI角色的三層結(jié)構(gòu)這句臺(tái)詞表面上是個(gè)性化設(shè)定實(shí)際上暴露了項(xiàng)目必須具備的三層能力。少了任何一層角色都會(huì)迅速變成“客服”或“電子木偶”。1.1 第一層Live2D決定了角色是“能看到你”還是“只播動(dòng)畫”Live2D本質(zhì)上不是傳統(tǒng)逐幀動(dòng)畫而是一種基于參數(shù)驅(qū)動(dòng)的實(shí)時(shí)形變技術(shù)。一張分層立繪會(huì)拆分出眼睛、嘴、頭發(fā)、手臂、尾巴、耳朵等多個(gè)部件模型師在Cubism里給這些部件綁上參數(shù)。運(yùn)行時(shí)你傳入一個(gè)參數(shù)值比如視線角度、張嘴幅度、頭部旋轉(zhuǎn)SDK就會(huì)實(shí)時(shí)計(jì)算形變并渲染出來。這帶來的最大變化是角色可以“看向光標(biāo)”“看向玩家”“在說話時(shí)微微搖頭”。陪伴型AI兔兔之所以有生命感很大程度來自這類微互動(dòng)。展示視頻里那句“主人歡迎回來”配上兔耳輕動(dòng)不是一個(gè)已經(jīng)錄好的視頻文件在循環(huán)播放而是Live2D實(shí)時(shí)渲染在配合事件觸發(fā)。所以第一層工程其實(shí)是模型資源管理。你需要先拿到一套可運(yùn)行的Live2D模型并確認(rèn)它的版本和SDK兼容性。Live2D v3模型在部分老版本運(yùn)行時(shí)里可能無法加載免費(fèi)模型資源也可能自帶貼圖壓縮、網(wǎng)格綁定等問題。很多新手卡在最開始不是不會(huì)接AI而是模型目錄結(jié)構(gòu)都不完整導(dǎo)致白屏、黑屏或只有頭發(fā)在動(dòng)。1.2 第二層對(duì)話引擎決定了角色“會(huì)不會(huì)說話”如果只有Live2D角色就是一只精致的“電子手辦”。它可以說預(yù)設(shè)臺(tái)詞但沒有任何應(yīng)變能力。要讓角色在你說“今天加班好累”之后回一句貼合情境的話就必須接上大模型對(duì)話鏈路。這里的對(duì)話鏈路不是簡(jiǎn)單調(diào)一次API還要包含角色設(shè)定。你可以把角色卡理解成一份“演員手記”這個(gè)兔子叫什么名字喜好是什么語氣是俏皮還是溫柔會(huì)不會(huì)在你喊它名字時(shí)給出特別回應(yīng)遇到不想答的問題用什么話轉(zhuǎn)移。大模型負(fù)責(zé)根據(jù)這份手記生成文本而角色卡負(fù)責(zé)把行為約束住避免生成內(nèi)容前后矛盾。在實(shí)際架構(gòu)里對(duì)話引擎又有兩個(gè)分支一是純文本生成二是為了驅(qū)動(dòng)Live2D表情而需要的結(jié)構(gòu)化輸出。很多時(shí)候不能只把一句話丟給模型而是要讓模型同時(shí)返回一個(gè)情緒標(biāo)簽或者一段可解析的JSON后面供動(dòng)畫層消費(fèi)。1.3 第三層記憶和狀態(tài)層決定了角色“記不記得你”“我一直在”這句話拋開情感表達(dá)在工程上意味著一件事系統(tǒng)需要有狀態(tài)。它不是一次請(qǐng)求響應(yīng)完就結(jié)束而是要能回答“你剛才去過哪里”“上次聊到哪了”“今天第幾次打招呼”。這就引出了陪伴型AI角色最容易被低估的記憶模塊。簡(jiǎn)單方案是每次對(duì)話都把歷史消息塞進(jìn)上下文窗口但上下文窗口有長(zhǎng)度上限聊天量上來之后要么超限要么早期信息被擠掉。更合理的設(shè)計(jì)是分層記憶短期記憶最近若干輪對(duì)話的原文用于保持對(duì)話連貫。中期摘要每隔一段時(shí)間把早期對(duì)話壓縮成一個(gè)摘要存進(jìn)上下文。長(zhǎng)期檔案把用戶身份、偏好、重要日期、既定事實(shí)寫入獨(dú)立存儲(chǔ)按需讀取。分層記憶背后是成本和體驗(yàn)的平衡。全量保存會(huì)非常耗token也容易讓模型關(guān)注點(diǎn)偏移不保存又會(huì)讓角色每隔半小時(shí)就失憶。一個(gè)陪伴型角色能不能讓人產(chǎn)生“它真的在陪我”的感受記憶層幾乎起決定性作用。2. 從開源項(xiàng)目“AI小鎮(zhèn)”看這類產(chǎn)品的系統(tǒng)設(shè)計(jì)標(biāo)題里的“AI小鎮(zhèn)”不是營(yíng)銷詞它對(duì)應(yīng)了一個(gè)真實(shí)存在的開源項(xiàng)目形態(tài)把多個(gè)AI角色放進(jìn)一個(gè)小型城鎮(zhèn)空間里讓它們各自擁有位置、行為和對(duì)話邏輯。相比單角色桌寵這更像在做一個(gè)Agent模擬環(huán)境。2.1 它像一個(gè)小鎮(zhèn)腳本而不是一個(gè)NPC從項(xiàng)目命名和傳播材料看my_ai_town這類項(xiàng)目更接近“讓AI角色在小鎮(zhèn)中生活”。每個(gè)角色不只是等待某個(gè)用戶打開窗口才運(yùn)轉(zhuǎn)而會(huì)在系統(tǒng)調(diào)度下產(chǎn)生移動(dòng)、相遇、閑聊、任務(wù)。這種設(shè)計(jì)一旦跑起來角色之間會(huì)產(chǎn)生大量自發(fā)生成的內(nèi)容形成一種虛擬社區(qū)的假象。和“單機(jī)陪伴兔兔”相比小鎮(zhèn)模式的價(jià)值是讓角色有了時(shí)間軸和空間感。AI兔兔不只是被動(dòng)響應(yīng)它可能有自己起床、閑逛、回小屋的作息也可能在另一個(gè)角色路過時(shí)說句話。這種主動(dòng)行為模型正是從“聊天機(jī)器人”跨向“虛擬Agent”的重要一步。2.2 一個(gè)角色從“被調(diào)用”到“主動(dòng)生活”需要哪些模塊把參與AI小鎮(zhèn)的單個(gè)角色拆開看它至少由五個(gè)模塊組成對(duì)話引擎負(fù)責(zé)自然語言生成、角色扮演、情感回應(yīng)。動(dòng)畫引擎負(fù)責(zé)Live2D參數(shù)驅(qū)動(dòng)和表情切換。狀態(tài)管理維護(hù)角色當(dāng)前的位置、情緒、行為、任務(wù)。記憶服務(wù)處理短期對(duì)話、長(zhǎng)期檔案、摘要。事件調(diào)度負(fù)責(zé)定時(shí)任務(wù)、隨機(jī)觸發(fā)、角色相遇等主動(dòng)行為。這五個(gè)模塊加在一起才讓角色有“我一直在”的實(shí)感。單角色版本可以砍掉事件調(diào)度只保留對(duì)話和動(dòng)畫小鎮(zhèn)版本則必須把事件調(diào)度放到核心位置否則每個(gè)角色都只是站在原地的NPC。2.3 原型項(xiàng)目的價(jià)值與局限我傾向于把這類開源項(xiàng)目當(dāng)成“高質(zhì)量原型”來看而不是當(dāng)成開箱即用的產(chǎn)品。原因有三第一它把復(fù)雜問題打散了。AI角色、Live2D、記憶、Agent調(diào)度這些概念在一個(gè)項(xiàng)目里互相糾纏如果想分別理解很容易迷失。原型項(xiàng)目把這些模塊放在一個(gè)最小社區(qū)里給閱讀者提供了很好的導(dǎo)航。第二它適合二次開發(fā)但不一定直接可用。開源項(xiàng)目的依賴、路徑、配置往往按作者本機(jī)環(huán)境組織版本一旦變動(dòng)就可能跑不起來。先用小數(shù)據(jù)量驗(yàn)證再改造成自己的場(chǎng)景是更現(xiàn)實(shí)的做法。第三它的可持續(xù)性還不確定。開源Agent小鎮(zhèn)往往處于快速迭代或長(zhǎng)期維護(hù)停滯兩種狀態(tài)之間。拿它做學(xué)習(xí)沒問題拿它做生產(chǎn)環(huán)境前要自己補(bǔ)日志、部署、權(quán)限、數(shù)據(jù)備份和內(nèi)容過濾。3. 搭建一個(gè)陪伴型Live2D角色最小可運(yùn)行鏈路如果不想一上來就做AI小鎮(zhèn)完全可以先從“一只陪伴型兔兔”開始。下面給出一條最小可運(yùn)行的鏈路只保留能跑通的三件事顯示角色、生成對(duì)話、觸發(fā)表情。3.1 前置環(huán)境Live2D運(yùn)行時(shí)、模型文件與LLM接口建議先準(zhǔn)備三樣?xùn)|西環(huán)境項(xiàng)作用常見選項(xiàng)Live2D運(yùn)行時(shí)負(fù)責(zé)加載模型并實(shí)時(shí)渲染Live2D Cubism SDK、Web端運(yùn)行時(shí)、pixi-live2d-display等渲染庫Live2D模型提供角色形象與可驅(qū)動(dòng)參數(shù)官方示例包、創(chuàng)作者免費(fèi)模型、自己綁骨導(dǎo)出的模型LLM接口負(fù)責(zé)文本對(duì)話和情緒輸出OpenAI兼容接口、本地部署大模型、云廠商模型API這里要特別說明Live2D模型資源不只是一個(gè)圖片文件。它通常包含模型目錄、紋理、物理模擬參數(shù)和表達(dá)式文件夾。下載模型之后先確認(rèn)目錄里有moc或moc3、textures、motion等文件夾再放進(jìn)項(xiàng)目里。網(wǎng)上能找到很多“免費(fèi)live2d模型”但真正常見的問題不是找不到模型而是不會(huì)區(qū)分模型版本和授權(quán)范圍。注意不要一開始就嘗試批量效果也不要用生產(chǎn)數(shù)據(jù)庫直接實(shí)驗(yàn)。先準(zhǔn)備一個(gè)測(cè)試目錄把模型、日志和配置放在同一個(gè)項(xiàng)目結(jié)構(gòu)里后面排查問題時(shí)才能快速定位。3.2 從文本輸入到表情觸發(fā)偽代碼示例下面用一個(gè)簡(jiǎn)化結(jié)構(gòu)展示對(duì)話和Live2D怎么聯(lián)動(dòng)# 偽代碼示例僅演示流程不是某個(gè)項(xiàng)目的固定實(shí)現(xiàn) def handle_user_message(user_text): # 1. 從記憶服務(wù)讀取最近上下文和角色檔案 context memory.get_recent_context(role_idrabbit) persona memory.get_persona(role_idrabbit) # 2. 調(diào)用大模型要求返回聊天內(nèi)容和情緒標(biāo)簽 result llm.chat( messagesbuild_messages(persona, context, user_text), temperature0.8, response_format{type: json_object} # 讓模型按結(jié)構(gòu)化格式輸出 ) reply result[reply] emotion result[emotion] # 例如 joy, sad, surprise # 3. 根據(jù)情緒標(biāo)簽觸發(fā)Live2D表情 animator.trigger(emotion) # 4. 把這一輪對(duì)話存入記憶 memory.add(role_idrabbit, useruser_text, assistantreply) return reply這段偽代碼不是某個(gè)項(xiàng)目的完整實(shí)現(xiàn)但已經(jīng)足夠說明結(jié)構(gòu)。中間最關(guān)鍵的兩步是讓模型返回情緒標(biāo)簽以及動(dòng)畫控制器能正確消費(fèi)這個(gè)標(biāo)簽。調(diào)試時(shí)如果發(fā)現(xiàn)角色一直不張嘴或表情永遠(yuǎn)同一個(gè)問題幾乎都出在這兩步的格式?jīng)]對(duì)齊。3.3 從“能對(duì)話”到“會(huì)等人”增加一個(gè)狀態(tài)循環(huán)只做模型調(diào)用兔兔就是個(gè)應(yīng)答機(jī)。要做成陪伴型角色還需要一個(gè)事件循環(huán)。最基礎(chǔ)的設(shè)計(jì)是每過幾秒發(fā)一個(gè)心跳檢查當(dāng)前用戶是否在線、角色是否處于空閑狀態(tài)再?zèng)Q定是否主動(dòng)觸發(fā)動(dòng)作。狀態(tài)循環(huán)可以簡(jiǎn)化成三個(gè)節(jié)點(diǎn)待機(jī)狀態(tài)角色安靜待著但沒有死掉。定時(shí)器觸發(fā)小動(dòng)作比如耳朵輕抖。交互狀態(tài)用戶輸入到達(dá)走完整對(duì)話和表情聯(lián)動(dòng)鏈路。離線狀態(tài)用戶離開后系統(tǒng)把記憶寫入長(zhǎng)期存儲(chǔ)關(guān)閉高資源消耗的實(shí)時(shí)循環(huán)。這樣當(dāng)用戶下次打開窗口時(shí)角色會(huì)從長(zhǎng)期存儲(chǔ)里讀到“上次聊到……”的信息再配合Live2D做出一個(gè)“歡迎回來”的姿態(tài)。你看到的不是一句寫死的臺(tái)詞而是一個(gè)狀態(tài)機(jī)在數(shù)據(jù)驅(qū)動(dòng)下生成的回應(yīng)。3.4 出現(xiàn)問題時(shí)的排查順序從現(xiàn)象定位到鏈路這類項(xiàng)目出問題時(shí)不要盲目改參數(shù)。按下面的順序逐層排查通常能更快找到根因角色完全不回復(fù)先確認(rèn)用戶輸入有沒有到達(dá)后端再檢查API密鑰、網(wǎng)絡(luò)連通性和請(qǐng)求超時(shí)配置。角色有回復(fù)但不動(dòng)畫檢查模型返回結(jié)構(gòu)里有沒有情緒標(biāo)簽以及Live2D動(dòng)畫控制器是否匹配這個(gè)標(biāo)簽的命名。角色加載失敗或白屏優(yōu)先檢查模型格式、SDK版本和資源路徑而不是先懷疑代碼邏輯。角色聊久了開始胡言亂語檢查短期記憶是否溢出、長(zhǎng)期記憶是否寫入了未清洗的噪聲、上下文拼接是否超過窗口上限。這個(gè)排查順序的核心思路是先確定問題發(fā)生在哪一層再?zèng)Q定修哪里。從輸入、到對(duì)話引擎、再到動(dòng)畫和記憶一層一層排除效率遠(yuǎn)高于隨機(jī)試參數(shù)。4. 決定角色“像活人”還是“像客服”的關(guān)鍵參數(shù)很多人在做完最小鏈路后發(fā)現(xiàn)角色雖然能對(duì)話但語氣特別平、情緒表達(dá)很弱、說話像模板。這種差異不在模型能力而在幾個(gè)配置細(xì)節(jié)上。4.1 角色卡不是人設(shè)論文而是行為約束新手常把角色設(shè)定寫成一長(zhǎng)段背景故事它出生在哪里、喜歡什么顏色、經(jīng)歷過什么冒險(xiǎn)。這些信息當(dāng)然有用但大模型只憑背景故事容易生成漂亮但空洞的話。更好的做法是在角色卡里寫行為規(guī)則當(dāng)用戶說“今天好累”時(shí)優(yōu)先表達(dá)關(guān)心不要追問細(xì)節(jié)。每條回答盡量在20到50個(gè)字之間不要長(zhǎng)篇大論。如果用戶提到不喜歡的話題用一句“那我換個(gè)話題”自然結(jié)束。情緒標(biāo)簽必須從給定集合里選不能自己發(fā)明。角色卡的本質(zhì)是產(chǎn)品需求文檔不是人物小傳。你給模型定義的是“在什么場(chǎng)景做什么反應(yīng)”故事背景只是輔助。4.2 上下文、溫度和流式手感就是這樣調(diào)出來的溫度參數(shù)對(duì)陪伴型角色影響很大。溫度偏低回復(fù)穩(wěn)定但容易顯得干巴溫度偏高回復(fù)有驚喜但可能跑偏、重復(fù)或突然離譜。我一般建議在0.7到0.9之間試先跑20條測(cè)試樣本再根據(jù)具體角色微調(diào)。上下文管理更麻煩。陪伴型場(chǎng)景天然有長(zhǎng)時(shí)間對(duì)話需求但“聊得久”和“把歷史全部塞給模型”是兩件事。長(zhǎng)期陪伴需要在每一輪只保留最近的短期對(duì)話把更早的內(nèi)容壓縮成摘要。否則聊到第一百輪時(shí)系統(tǒng)會(huì)因?yàn)樯舷挛某拗苯訄?bào)錯(cuò)或者模型被早期無關(guān)信息干擾。流式輸出也會(huì)影響體驗(yàn)。如果用戶發(fā)一句話后要等兩秒鐘才看到整段文字陪伴感會(huì)大打折扣。用流式輸出可以讓回復(fù)一個(gè)字一個(gè)字地出現(xiàn)在氣泡里同時(shí)讓Live2D先把一個(gè)“正在思考”的表情撐起來等待感會(huì)低很多。4.3 表情解析模型文本怎么映射到Live2D參數(shù)這是整個(gè)鏈路里最容易被忽略的一環(huán)。大模型返回的是文本和情緒標(biāo)簽Live2D需要的是具體參數(shù)值。理想情況下情緒標(biāo)簽應(yīng)該對(duì)應(yīng)一組參數(shù)配置。例如一個(gè)簡(jiǎn)單映射表情緒標(biāo)簽Live2D動(dòng)作參數(shù)變化建議joy耳朵微動(dòng)、嘴角上揚(yáng)嘴巴張開度上調(diào)眉毛下落sad低頭、嘴角下垂頭部角度略低視線向下surprise眼睛放大、嘴型張開眼睛開度大幅上調(diào)idle輕微呼吸擺動(dòng)身體Y軸緩慢上下這層映射需要在動(dòng)畫控制器里維護(hù)。如果項(xiàng)目已經(jīng)定義了表情文件可以直接切換如果沒有就要自己寫一個(gè)簡(jiǎn)單的規(guī)則映射。這一步做得好角色才會(huì)有“表情跟著話走”的自然感。5. 工程化落地時(shí)容易被忽略的四個(gè)邊界最小鏈路跑通之后真正的麻煩才開始。下面是這類項(xiàng)目從“demo”走向“能長(zhǎng)期運(yùn)行”時(shí)最常被忽略的邊界。5.1 模型版本、目錄結(jié)構(gòu)和版權(quán)Live2D模型分為v2、v3、v4等不同版本不同版本對(duì)應(yīng)不同格式和SDK要求。項(xiàng)目的渲染庫不一定能兼容所有格式。落地前要做的第一件事是確認(rèn)模型格式和渲染SDK版本互相匹配。目錄結(jié)構(gòu)也很關(guān)鍵。一個(gè)模型如果缺失貼圖路徑、物理文件或表達(dá)式文件夾加載時(shí)可能直接報(bào)錯(cuò)。還有版權(quán)問題免費(fèi)模型不一定允許二次分發(fā)或商用下載時(shí)最好把授權(quán)說明和模型來源一起保留避免后面做公開項(xiàng)目時(shí)踩坑。5.2 會(huì)話分層不能全塞進(jìn)上下文也不能完全失憶既要避免上下文爆炸又要讓角色記住重要信息比較實(shí)用的方案是設(shè)置“記憶倉庫”。短期記憶放最近20輪對(duì)話按隊(duì)列滾動(dòng)。長(zhǎng)期記憶放用戶偏好、重要事件、角色狀態(tài)每次對(duì)話前篩選相關(guān)片段拼進(jìn)提示詞。定時(shí)任務(wù)定期把短期記憶里的高價(jià)值信息寫入長(zhǎng)期記憶。這樣做的成本可控也能保證角色在長(zhǎng)時(shí)間對(duì)話里保持基本的一致性。一個(gè)很常見的錯(cuò)誤是陪伴型角色運(yùn)行幾天之后開始胡言亂語原因不是模型變笨了而是長(zhǎng)期記憶里寫入了大量未清洗的噪聲導(dǎo)致相關(guān)信息檢索失敗。5.3 內(nèi)容安全情感陪伴類AI必須把邊界做進(jìn)配置情感陪伴是一個(gè)很特殊的場(chǎng)景。用戶會(huì)把角色當(dāng)成傾訴對(duì)象很容易說出帶有強(qiáng)烈情緒、壓力或敏感傾向的內(nèi)容。這類項(xiàng)目不能沒有邊界意識(shí)。工程上至少要做三件事在角色卡里明確敏感輸入的處理方式比如用溫和的話轉(zhuǎn)移話題。在后端增加敏感內(nèi)容過濾或提示詞檢測(cè)攔截不適合繼續(xù)展開的對(duì)話。在日志里保留異常對(duì)話的標(biāo)記方便人工審核和復(fù)盤。注意情感陪伴類AI的內(nèi)容安全不是靠大模型自覺而是在prompt、后端過濾、日志標(biāo)注三處分別生效。角色懂事地避開某些話題和角色突然說出危險(xiǎn)內(nèi)容這兩種體驗(yàn)的天壤之別往往就在這一層配置上。5.4 長(zhǎng)時(shí)間運(yùn)行的性能與穩(wěn)定性Live2D實(shí)時(shí)渲染本身要占一定性能大模型調(diào)用也是高延遲請(qǐng)求。如果角色放在用戶設(shè)備和后端同時(shí)運(yùn)行長(zhǎng)時(shí)間跑會(huì)出現(xiàn)幾個(gè)典型問題內(nèi)存泄漏表情文件、紋理資源被反復(fù)加載但沒釋放運(yùn)行一段時(shí)間后越來越卡。請(qǐng)求超時(shí)LLM接口偶爾響應(yīng)很慢客戶端沒有重試和超時(shí)保護(hù)用戶會(huì)看到角色“死掉”。日志混亂如果沒記錄請(qǐng)求耗時(shí)、錯(cuò)誤碼、重試次數(shù)出問題時(shí)分析半天也定位不到。工程化建議是給外部請(qǐng)求加超時(shí)和重試給Live2D資源做按需加載或定時(shí)釋放給所有關(guān)鍵節(jié)點(diǎn)打日志。這些不是核心功能但恰恰決定了項(xiàng)目能不能長(zhǎng)期放在一起。6. 一條現(xiàn)實(shí)路徑先做最小陪伴再考慮“小鎮(zhèn)”最后把路徑收束成一條可執(zhí)行的建議避免被太多技術(shù)標(biāo)簽淹沒。6.1 如果你只想體驗(yàn)一個(gè)角色就夠最省事的路線是準(zhǔn)備一臺(tái)能跑Live2D的開發(fā)機(jī)安裝模型和渲染依賴。接一個(gè)支持流式輸出的大模型API。先做單個(gè)角色的對(duì)話與表情聯(lián)動(dòng)。增加一個(gè)簡(jiǎn)單的記憶文件和狀態(tài)循環(huán)。這個(gè)階段不需要高并發(fā)不需要多個(gè)角色也不需要復(fù)雜調(diào)度。目標(biāo)就是讓兔兔在你說一句話時(shí)能帶著表情回一句符合角色的話并在你離開一段時(shí)間后說出一句“歡迎回來”。6.2 如果你想做AI小鎮(zhèn)從單角色模擬開始擴(kuò)展如果不想止步在單角色可以按這個(gè)順序演進(jìn)先把單角色跑穩(wěn)日志、記憶、權(quán)限、異常處理都調(diào)好。把對(duì)話引擎改造成可以被多個(gè)角色復(fù)用的服務(wù)。加入角色狀態(tài)管理讓每個(gè)角色擁有獨(dú)立的情緒和位置。加入事件調(diào)度讓角色能按一定頻率產(chǎn)生主動(dòng)行為。最后再用慢速批量測(cè)試驗(yàn)證多角色并發(fā)而不是一開始就把所有角色塞進(jìn)同一個(gè)進(jìn)程。AI小鎮(zhèn)的吸引力在于“多角色的世界里會(huì)發(fā)生什么”但它對(duì)系統(tǒng)的要求遠(yuǎn)比單個(gè)陪伴型角色高。我的經(jīng)驗(yàn)判斷是先做“最小陪伴”再把最小陪伴復(fù)制給第二個(gè)、第三個(gè)角色最后才考慮它們之間的互動(dòng)。順序反過來很容易在調(diào)試期間被并發(fā)問題拖垮。6.3 真正值得長(zhǎng)期投入的是“狀態(tài)驅(qū)動(dòng)的Agent循環(huán)”回到開頭那個(gè)判斷一個(gè)像“活過來”的AI角色真正核心的不是模型名稱也不只是一張Live2D立繪而是狀態(tài)驅(qū)動(dòng)的Agent循環(huán)——角色能接收輸入、調(diào)用能力、更新記憶、觸發(fā)主動(dòng)行為然后回到下一次循環(huán)。當(dāng)你開始用“狀態(tài)機(jī)”“事件循環(huán)”“記憶分層”這些視角去看這類項(xiàng)目時(shí)Live2D兔兔也好AI小鎮(zhèn)也好都不再是炫技展示而是一個(gè)可以持續(xù)迭代的軟件系統(tǒng)。寵物能不能長(zhǎng)期陪伴你最后拼的不是某一幀動(dòng)畫多可愛而是當(dāng)對(duì)話歷史越來越長(zhǎng)、角色越來越多、運(yùn)行時(shí)間越來越久時(shí)整個(gè)系統(tǒng)還能不能穩(wěn)定、清醒、記得你們之前聊過什么。這大概也是“我一直在”這句話從技術(shù)意義上最真實(shí)的解釋。