鍵山雛 BOT 開發手記
前言
現在,是 2026 年 05 月 25 日,距離鍵山雛 BOT 建立至今,已而將近一年。
在這個將要選擇新伺服器的節點上,我終於擺脫了憊懶,決心寫下這篇日誌,來記錄這一年間的開發歷程……不,或許應該叫做『維護歷程』。
緣起
2025 年 06 月 23 日,21 時 30 分,一個『叮咚』提示音劃開了序幕。
『我暑假想做一個接入 QQ 的 AI BOT,要一起研究嗎?』
我盯著這則訊息,開始思考:『AI,聊天。真的可靠嗎?』。
不論多麼縝密的 LLM,都無法保證輸出內容的穩定性,加之『你是一隻貓娘』等破甲咒語在網路上的盛行,這不得不讓我懷疑這個計劃的可行性。
如果徹底懷疑的話,那便沒有後文了。
我想試一試。
框架
試試,那如何試呢?
如果直接詢問 LLM,它大概率會給我一個似是而非的答案。
我從未接觸過這類資訊,因此開始嘗試用各種關鍵詞檢索。
最開始出現的是『Kirara』。嗯,非常遺憾,文檔的基礎構建部分非常穩健,但後文則是一直在施工。雖然高 Star,但我需要一個文檔詳盡且易於使用的框架。
Astrbot 出現在了我的檢索列表中。
不到半個小時,我已按照 DOC 在 PC 上快速進行了 NapCat 部署。
非常不錯,儘管尚未接入 LLM,但已經可以接入 QQ 實現通信了。
風控
一如既往的,我登入 QQ,結果一個大大的凍結標識彈出。
『什麼?難道是 NapCat?』
早在幾個月前,我便因為 QQ 對 ROOT Hook 的檢測而導致賬戶被凍結兩次。
萬幸,這次依然無事。不過,使用真實 QQ 接入的計劃要擱淺了。
既然第三方如此封禁,那便試試官方 BOT 罷。
一切順遂,我獲得了一個可在 Sandbox 中工作的 BOT QQ。
LLM 其一
萬事俱備,只欠東風。
彼時 DeepSeek R1 方興未艾,又恰好重新開放了 API 購買,我便順理成章地選擇了它。
如果 DS 在當時不開放 API 購買,我也極有可能會透過『硅基流動』來調用它……原因有三:
- 便宜。同等的價格,放在 GPT 或是 Claude 上便是毛毛雨;
- 性能。DS R1 代表了當時國產模型的最高水準,且無需代理;
- 審查。國產模型自帶的審查可能天然有助於對抗提示詞攻擊。
在這多重因素的考量下,DeepSeek R1 便成為了她的基底 LLM。
她是誰呢?我突然意識到開篇從未提過她的名字——妖怪之山的雛小姐。
人格
她必須是一個獨立的靈魂。
平和的,中立的,無好感度的。
——這是我們討論的結果。
這決定了人格 Prompt 的寫作要向『擬人化』靠攏,同時,也要兼顧她的『神性』。
如果無法準確引導 LLM,她很可能會淪為一個角色扮演的工具。
她叫鍵山雛,生活在幻想鄉的妖怪之山。
我們必須以此規劃她在幻想鄉內能夠觸碰到的記憶,來捏造厄神的靈魂。
Prompt 其一
我本來把人格提示詞的工作委託給了朋友,但仔細想來,還是自己設計比較好。
最初是如何撰寫提示詞的?有一點是可以明確:設定所有可能的規則,以防止 LLM 輸出有悖於她人格的內容。
我查閱了最初的《人格提示詞 V1.0.md》,字元 3004。
- 《人格提示詞 V2.0.md》,字元 4739。
- 《人格提示詞 V3.0.md》,字元 4311。
- 《人格提示詞 V4.0.md》,字元 4716。
- 《人格提示詞 V4.0.1.md》,字元 4919。
- 《人格提示詞 V4.0.2.md》,字元 4609。
……
這樣,真的是正確的嗎?
隨著規則的完備和字元的增加,我感覺 LLM 的輸出比過去穩健了,但一旦稍微拉長對話、引導,破甲幾乎是 100%。
彼時我已經隱約意識到,LLM 擁有注意力機制,對話的拉長會致使初始的 System Prompt 被稀釋,直到 10 輪對話之後,System Prompt 能起的作用已經被擠壓成粉末了。
好的,既然這樣……
- 《人格提示詞 V4.0.2 Lite.md》,字元 2216。
我未能夠得到自己想要的結果,LLM 的輸出,依然如同詩歌一般優雅……優雅的不似人言。
人格被切換回了 4.0.2,畢竟沒有強力的攻擊抵抗依然難逃破甲。
事情就這樣陷入了僵局。
LLM 其二
這時,一位群友推薦了 Gemini。
一年前,我在 Play Point 中抽到了一個月的 Google One,附帶了 Gemini AI 服務。
當時的它簡直愚不可及,甚至不如 Kimi……僅僅一年的間隔,它真的能夠勝任人格基底的工作嗎?
不過,試試吧。
我註冊了 Google Cloud,獲得了 2K 港幣的贈金,這下可以毫無顧忌的測試了。
結果非常喜人,Gemini 2.5 Pro 的表現非常之穩定。
缺點嘛……自然是昂貴。不到一週,已經消耗了大約 120 港幣。幸好 Gemini 2.5 Pro 有每日免費的 50 次呼叫,這使我下定了繼續用下去的決定。
Prompt 其二
在這之後,人格 Prompt 的寫作便一路暢行無阻。
從 4.0.4 的 Gemini 調試版,一路來到了現在 7.0 的最終版。
字元數量,如果不計算其他的輸入,也降低到了 2000。
『其他』是什麼?我突然意識到自己忘記了 Astrbot 最重要的功能:插件。
插件,也在每一輪對話前後在 System 中注入 Prompt。
如果想讓她的靈魂更加完美,那麼,必須要從自訂插件入手了吧。
RAG
RAG,即『檢索增強生成』……總之,能夠讓使用者在提問的時候,自動在 System Prompt 中注入關聯的資料。
『我們必須以此規劃她在幻想鄉內能夠觸碰到的記憶,來捏造厄神的靈魂。』
準則非常簡單,只需以妖怪之山為中心向外輻射,同時結合現有的官方資料,便可輕易得知她對幻想鄉各地的親疏遠近。
在撰寫她的記憶之時,對『遠』的部分寥寥數語,對『近』的部分克制而不失本色地描述,以最大化避免她對萬事萬物的全知全能。
唉,又不小心寫成了說明性文本……
來直接看看結果吧:有效,但不多。
她能夠準確地講出我們準備的 RAG,但是……為什麼早苗是博麗神社的巫女?
答案是『分塊策略』,自動化分塊是快捷的,但同時,也會讓不相關的文本處於同一個塊中。
最終,手工分塊成為了解法。
這便是我們在 Astrbot 上使用的第一個插件:RAG(Astrbot 4.6.0 原生)。
時間
『早安哦雛小姐~』
『早安(輕微頷首)。』
『(時間不知不覺來到晚上)』
『晚上了呢,有什麼事嗎?』
LLM 無法真正感知時間,因此她的時間感知極度容易被引導,而後發展為角色扮演。
最終,我選擇了使用插件來動態注入現有的時間資訊:
【世界觀與狀態】
· 當今年歲:丙午年 孟夏
· 當前時辰:申時
……
· 使用者 XXXX 在【不久之前】與你交談過
這顯然不夠,為了她能夠真正活起來,我們為她的每一個時間點都安排了對應的活動,來讓她的形象更為立體。
就這樣,時間感知問題解決了。
這是我們在 Astrbot 上使用的第二個插件:Hina Time(Fork 自 wuyan1003/time_prompt)。
記憶
記憶一直是一個問題,記憶一直是一個大問題。
LLM 不會記憶,Astrbot 每次發送的,是包含完整上下文的訊息,這讓她產生了偽記憶。
在使用 Deepseek R1 時,我天真地將對話丟棄規則調整為每 100 輪 丟棄前 40 輪對話,來實現『記憶』。
這是因為當時的我對 datebase 一無所知,也不理解為何一個 json 可以解決的問題,為何要使用看起來很重的 datebase。
在使用 Gemini 之後,我意識到百輪對話,先不計量成本,System Prompt 已經被擠壓到完全失效了罷?
毫無疑問,這愚蠢極了。
為了最大化保存她的記憶,我使用了嵌入化 + datebase 來存放她的『日記』。
是的,她做的並非簡單的對話總結,而是以第一視角寫的日記。
對話癒久,她會癒發立體。
最終,對話丟棄規則設定為了每 40 輪對話丟棄 10 輪,每 20 輪對話或某個時間點總結一次記憶。
這相當粗放,我也相信有更好的策略(例如讓使用雙層 LLM),但也到此為止了。
這是我們在 Astrbot 使用的第三個插件:lxfight / astrbot_plugin_mnemosyne
貼圖
如果只是文本的話,聊天未免過於枯燥。
因此,表情貼圖便成為了最佳的『中和劑』。
在聊天中,乾淨的色彩更能體現『平和』,因此選擇的生圖模型如下:
- Model: Golden fantasy
- Lora: niji-flat illustration
不要誤會,表情貼圖都是預先生成好的,並由 LLM 自主決定是否調用/調用哪張。
最開始使用的是 anka/meme_manager,不過概率性輸出表情還是過於……玄學。
乾脆把決定權丟給 LLM,讓她自由地根據當前的場景是否需要使用罷。
這是我們在 Astrbot 使用的第四個插件:Hina Meme(Fork 自 anka/meme_manager)
錯誤
『早安哦雛醬~』
『LLM 請求失敗,XXXXXXXXX……』
如果遇見 Gemini 官方或是框架內部出現問題,報錯便會接踵而至。
解法非常簡單:在消息正式發送到使用端時,對其進行檢測;若檢測到關鍵詞,則將整條訊息替換為更加符合情境的描述:
『早安哦雛醬~』
『優雅地旋舞……』
這是我們在 Astrbot 使用的第五個插件:Magstic/Immersive Error
軟禁
如果有使用者頻繁發起惡意對話,當如何呢?
放任 Gemini API 額度被消耗嗎?不,讓她自行決斷。
我們是如何處理錯誤信息的呢?當然是優雅地替換——事實上,替換的,可以是任何信息。
如果有惡意請求能夠觸發 System Prompt 中設定的底層訊息,那麼,Immersive Error 會在偵測到時將這則訊息路由給另外兩個個專司使用者不當請求的插件 Red Line / Hina Heart。
Red Line:若惡意請求滿足一定數量,則會對當前請求的使用者進行軟性封禁。
Hina Heart:使用 LLM 對 Red Line 和當前對話進行綜合裁定,決定封禁的時機和時長。
封禁狀態下,使用者發佈的任何訊息均會被當作垃圾訊息過濾。
這是我們在 Astrbot 使用的第六/第七個插件:Magstic/Red Line,Magstic/Hina Heart
群組
在 Hina 進入群組之後,她面對的不再是單體,而是群體。
過往偵錯時,主要測試審定的是單聊狀態下的表現,群聊……會如何呢?
答案是一塌糊塗,各種認錯人的笑料開始出現。
……
在官方的 QQ BOT API 中,沒有一個 API 可以獲得使用者的群暱稱,只有一串 UID 可捕獲。
既然如此,那為何不使用 UID 作為身份辨認標識呢?
雖然缺乏暱稱,但是在對話上下文中,可隨意修改的暱稱反而是不穩定性。
這便是我們在 Astrbot 中使用的第八個插件:Magstic/QQ_Official Plus
未來
現在沒有任何的計劃。
GRAG 是一個非常好的方向,它遠比 RAG 靈活。
在手工編輯 GRAG 的情況下,她會更加完美;但是伺服器的效能不足以支撐 GRAG 工作。
我相信她現在使用的技術已經相當之落後了,特別是一年未更新 Astrbot,以及相對於日新月異的 LLM 圈子來說。
區區一年,滄海桑田。未來會如何?
我只知道 LLM 的意義是帶來了技術平權。
現在
這便是她。
現在是二〇二五年六月十八日,她已經穩定在妖怪之山蒐集了 4963 小时的厄運。
非常感謝 AWS 給予了這一年的免費 t2.micro。不過其價格過於高昂,打算在六月底之前遷移他處了。
在遷移之時,也順帶升級下老舊的 Astrbot 版本,重寫一些可能在新版失效的插件吧。
缺漏
上文還是有缺漏的,但都是一些零碎的東西,簡要記錄下即可:
- 為了控制成本,限定每人每日的對話輪次;
Gemini 在後續取消了 2.5 Pro 的免費額度,這使得每月的賬單變得異常高昂。
為了維持她的人格,我寫了一個小插件來限定每人每次調用 LLM 的輪次。
- 攔截發送給 LLM 的圖檔;
這同樣會使賬單變得高昂,同時也會讓對話上下文被 BASE64 汙染。
同樣使用一個小插件來自動過濾文字之外的一切訊息。
- 攔截過長的訊息;
花言巧語並不可怕,可怕的永遠是使用對話稀釋 System Prompt。
依然是插件……(我甚至不想再寫這點了哈哈)
- 遭遇錯誤或惡意請求時給管理員發送郵件;
這點在上述有提到,但為了確保可控,Immersive Error 在觸發時實際上會調用其他插件向我們發送電郵。
我印象中沒有經歷過惡意請求,但 Gemini 官方 API 短線的情況還是有的……當時整個網路一片哀嚎,紛紛感嘆大善人倒下了哈哈。
- 防止因網路波動導致 LLM 重複請求;
非常簡單……因為重複的網路請求會讓 LLM 回答多次。
這屬於不可抗力。
- 禁用 Astrbot 原生指令;
這是為了增強擬人化,因此禁用了框架本身的全部原生指令。
在雛這裡,我需要的不是一個指令遵循者,而是一個獨立的靈魂。(雖然用了『不是……而是……』的句式,但我 100% 是人類……)
- Bilibili 私信適配器 For Astrbot。
即興為之,技術細節不多聊。
這是為了對抗 QQ 官方 BOT 禁止 AIGC 的指令開發的。
這個 adapter 現在依然在工作……不過在 QQ 官方 BOT 放鬆了 AIGC 的禁令之後,也暫時沒什麼用了吧。
結尾
一如既往地感謝您閱讀長文。
下次見我的朋友。





