Haven的小空间

白酱:给 QQ 群养一个有人设的 AI,然后撞上了风控的墙

2 min read

我有几个常驻的 QQ 群,聊动画、聊 galgame,热闹的时候一天几百条。某天冒出个念头:能不能给群里塞一个有人设的 AI,平时能搭话、问到番剧能顺手查一下,像个真在群里的人。

于是有了白酱。这篇记一下怎么把她搭起来,以及——本以为最难的是 AI 那一层,结果真正把我卡住整整一周的,是一个机房 IP。

两层架构:协议归协议,AI 归 AI

QQ 没有官方的第三方 bot 接口,所以要让程序收发 QQ 消息,得靠社区的协议层实现。我用的是 NapCat——一个无头的 QQ 客户端,登录后把消息按 OneBot 标准协议吐出来。

AI 那一层我没自己写编排,用了 AstrBot:它负责接 OneBot 消息、管多模型、跑插件、维护会话和人设。两者之间用 OneBot v11 的反向 WebSocket 连——NapCat 当客户端,主动连 AstrBot。

这个「协议层和 AI 层分开」的设计后来证明特别值。因为它们解耦,我可以把两层放在不同机器上,单独重启、单独排查。后面那场风控拉锯里,这个边界帮了大忙。

人设白酱:克制比堆料更难

白酱的性格写在一段 system prompt 里:温柔随和的女孩、回复精简、句末不加标点、不自称 AI、有自己的 ACG 喜好。

调人设最反直觉的一点是:克制比堆料难得多。最早的 prompt 很短,结果她说话像个标准客服,每句都「呢~」「哦~」加一堆感叹号问号,AI 味十足。我反复往里加约束——禁用感叹号和问号、句末不加标点、回复别超过两三句——她才慢慢有了点「群友」的样子,而不是「助手」的样子。

人设存在数据库里,改 prompt 是直接更新一条记录、实时生效,不用重启。这让调性格变成一件可以快速试错的事:改一句、在群里发两条看看、再改。

多模型和插件:把「查东西」交给 AI 自己

白酱背后挂了几个模型,默认走 DeepSeek,也配了 Gemini 备选,用一个限管理员的命令随时切。这里踩了个有意思的坑:DeepSeek 的新版是推理模型,如果给的输出长度上限太小,它会把额度全用在「思考」上、最终正文反而空了。

最让我满意的是自己写的一个番剧/galgame 查询插件。它给 AI 暴露了几个工具:查 Bangumi(动画番剧)和 VNDB(视觉小说/galgame)。关键在于我没有做成「输入命令才查」,而是注册成 AI 的 function-calling 工具——也就是说,当群里有人随口问「XX 这部新番怎么样」,白酱会自己判断该不该去查、查完再用自己的口吻回答。体验上她不像个查询机器人,更像一个「正好知道去哪查」的朋友。

那些不起眼但很关键的打磨

真正让一个 bot 从「能跑」到「能用」的,往往是一堆不起眼的细节:

  • 白名单:只在我指定的那几个群响应,别处一律装死,避免被乱拉进群刷流量。
  • 命令权限:AstrBot 自带的一堆管理命令(重置会话、切模型、改配置之类)默认谁都能调。我打了个补丁把它们全限制成只有管理员能用,普通成员误触直接静默忽略,连「你没权限」都不回——免得破坏她的人设。
  • 每人独立会话:群里白酱记的是「我和你」的对话,不会把别人的话题串进来。
  • 记忆:在会话窗口之外,单独做了一层持久的「用户事实」记忆——白酱能记住某个人喜欢什么,下次自然带出来,而不是每次都失忆。

这些没一个是「核心功能」,但少了哪个,她都会从「群友」掉回「机器人」。

然后,撞上了风控的墙

bot 跑起来了,人设也满意了,我以为最难的部分已经过去。结果真正的麻烦才开始:QQ 把白酱反复踢下线。

日志里是冷冰冰的「登录已失效」。一开始我以为是登录态没存好,折腾了半天持久化,没用。查到最后,根因很清楚也很无奈:问题出在 IP。

QQ 的反 bot 逻辑有个朴素但有效的假设——真人是从家庭住宅宽带上 QQ 的,而一个 24 小时在线、跑在机房(数据中心)IP 上的连接,几乎就是在脑门上写「我是 bot」。我的 bot 一开始跑在海外服务器,后来为了 IP 离得近一点迁到了国内云主机——但只要是机房 IP,就逃不过这个判定。客户端层面那些「隐藏自己是程序」的设置,治标不治本,因为它们改不了 IP 这个最硬的信号。

我试过一些缓解办法,把出口流量绕一圈走到一个住宅性质的 IP 上。有改善——存活时间从一小时出头拉长到两个多小时,差不多三倍——但仍然不是根治,到点照样被踢。链路本身也很脆:多级串联,任何一环抖一下整条就断。

这里我就不展开具体怎么绕了。一来公开站点不适合写这种东西,二来我后来想明白了:和平台的反滥用机制硬碰硬,方向本身就是错的。

结论:顺着规则,而不是对抗规则

真正合理的解法其实朴素得有点好笑——让白酱从我自己家里的住宅 IP 上线就行

因为那才是诚实的信号:我自己的号,从我自己家的宽带登录,本质上和我平时用手机刷 QQ 没区别,风控自然没理由为难。具体做法是找一个能常年开机的小设备(旧手机、树莓派、软路由、迷你主机都行)放在家里跑协议层,AI 那一层还留在云上——前面那个「两层解耦」的架构,到这里刚好用得上:只把协议层搬回家,AI 层一行不用动。

所以这个项目现在处于暂停状态,等我回家把那个小设备装好再继续。我没有继续在云上和风控死磕——不是磕不动,是想明白了不值得:与其花心思伪装成真人,不如真的用真人的方式上线。

一点感想

做白酱最大的意外,是难点的位置和我预想的完全相反。

我以为难的是 AI——挑模型、调人设、写插件。结果这些反而是最顺、最有成就感的部分,框架成熟、反馈即时、改一句就能看到她性格的变化。真正把我卡住的,是底层那些和 AI 毫无关系的东西:一个 IP 算不算「真人」、一条链路稳不稳、一个账号在不在线。

这大概是自托管项目的常态:上层的乐趣是显性的,底层的债是隐性的,而最后拖住你的,往往是后者。但也正是这些底层的坑,逼着我把「为什么 QQ 这么判定」「住宅 IP 和机房 IP 到底差在哪」这些平时根本不会去想的事,从头到尾搞明白了一遍。

白酱还没正式回到群里。但等她回来的时候,会是从一个对她来说「正确」的地方上线。