改善角色扮演 AI chatbot 的使用体验

7 月,笔者在 Fraq  的基础上编写了 chatsalt  插件,这是一个相对独立的角色扮演 AI 聊天机器人插件,在 tairitsu-bot  的基础上简化而成。笔者并不想过多涉及 AI 领域的专有名词,仅从普通开发者的视角,介绍一些改善 AI chatbot 表现使用体验的心得。

选择合适的模型

角色扮演类 AI chatbot 对 AI 最大的要求并不是高智商,而是响应速度。如果从发起对话到回复之间的时长超过 10 秒钟,用户的使用体验就会大打折扣。此外,模型在中文语境下的表现,以及对角色扮演情景的遵循程度,也是选择模型的重要因素。综合各种因素,笔者最终选择了 Gemini Flash 系列模型,例如 gemini-3.7-flash。它的综合表现最好,首字时间(TTFT)最短,并且每秒输出的 token 数目(TPS)超过 100,十分适合角色扮演 AI chatbot 的工作情景。

为什么不选其他模型?以下是笔者对于尝试过的模型的个人观点,仅供参考。

将消息喂给 AI

如何将用户的提问以及私聊/群聊的上下文喂给 AI?Milky  表示消息内容的方式是 JSON 对象,其中含有大量不利于 AI 集中注意力并且浪费 token 的元信息(例如 file_id,这是一个很长的类 Base64 字符串),因此笔者在 Fraq 的 AI 插件中编写了 xmlify 系列方法,将消息转化为结构化的 XML 文本,主要的处理有:

由于 xmlify 的预处理并不需要考虑反序列化问题,因此只需要尽可能提高处理后的消息内容对于 AI 的可读性即可。当然,这样的处理也有副作用,AI 会更加倾向于生成含 XML 格式的回复,并且用 prompt 抑制回复的效果并不明显。

让 AI 学会拒绝

并不是所有问题都有答案,也并不是所有问题都应该给出答案。对于一些明显态度不友好、不尊重 AI 所扮演的角色或者包含钓鱼成分(诱导发言)的问题,应该让 AI chatbot 静默拒绝回答。输出 0 个 token 通常不是 AI 的一贯风格,因此 chatsalt 在系统提示词中让 AI 输出前缀为 no_reply 的句子来表达拒绝,而 no_reply 后面所跟的句子就是拒绝的理由。此外,chatsalt 还一并设计了 WebUI,AI 静默拒绝的问题会以警告的形式出现在页面上。

给 AI 打开视窗

一个除了模型知识库和提示词之外一无所知、“两耳不闻窗外事”的智能体自然是没法讨人喜欢的,因此笔者在编写 chatsalt 的过程中多次考虑了网络搜索工具的实现方式:

最后,笔者的眼光落在了 Codex App,它具有一定的互联网搜索能力。通过查阅文档,笔者发现 Codex App 实际上是使用了 OpenAI Responses API 的内置 web_search 工具进行搜索。除 GPT 系列模型之外,DeepSeek V4 系列的模型也同样支持这一内置工具。因此笔者将这一特性封装成了 chatsalt 的内置工具,它向一个用户配置的支持 Responses API 的模型发送特定 prompt,并且将返回的文本直接作为搜索结果,这大大提升了 chatsalt 回应用户提问的能力。

增加状态反馈

正如机械键盘在按下之后会有清脆的回弹声一般,如果 AI chatbot 在接受用户提问之后一声不吭直到作出回复,也会降低使用体验。QQ 平台在过去两年增加了类似 Telegram 等国际 IM 软件的“表情回应”功能,具体而言,就是在群聊环境下,其他账号可以在用户的消息下“贴”若干个表情进行一种类似“表态”的活动。这一机制同样也可以为 AI chatbot 所用;chatsalt 在用户提问、调用识图工具、调用网络搜索工具、拒绝回答、API 调用出错的时间节点,都会给用户的消息作出不同的表情回应;事实证明,这样的小改进的确增加了用户的参与感,也让开发者能够清晰地看到模型在一个 Loop 中的具体活动。

CC BY-NC 4.0 2026 © Wesley Young.