跳转至

表情包

系统维护一个表情包库:从聊天中收录、由视觉模型生成语义标签、回复时按情绪选取发送。 本页说明收录流程、标签来源、发送配额、内容审核与封禁机制。

默认状态:收集默认开启、发送默认可用、内容审核默认关闭、容量上限 1000 张。 配置位于 bot.toml[emoji][emoji.cleanup] 两段,亦可在面板「月璃设置」页修改。

收录流程

入库通道有两条:

  • 聊天收集:协议端将图片消息区分为「普通图片」与「表情包」,仅后者入库;普通图片只做描述,永不入库。 collect_enabled = false 时只识别、不入库。
  • 手动投放:将图片文件放入 data/emojis/ 目录(支持 .gif/.jpeg/.jpg/.png/.webp), 下次启动时自动扫描登记。

入库需依次通过三道闸门:封禁表检查(同一图片被封禁过则永久拒绝)、文件大小检查 (max_file_size_mb,默认 5 MB,0 为不限)、内容审核(仅 content_filtration = true 时执行)。

图片文件以内容的 SHA-256 命名,存放于 data/emojis/;库记录保存于数据目录的 memory.db。 每次启动对文件与记录的一致性做全量校验,缺失或不一致将阻止启动,因此不要手动修改该目录下的文件名。

语义标签来源

入库时由视觉模型(复用 vision 任务档)为每张图片生成 3 到 5 个简短的中文情绪词。 内容相同的图片复用既有标签,不重复调用模型。

注意前提条件:标签是入库的必需项。视觉模型不可用(未配置 vision 任务档且未开启图片描述)时, 新表情包无法获得标签,即不能入库;已在库的不受影响。面板上的标签为只读,不提供修改入口; 如需修正标签,删除该条目后让同一图片重新入库生成。

发送与配额

回复中可以附带一张表情包:先确定目标情绪,再从库中选取图片。

  • 发送配额:每次回复窗口内最多发送 1 张,窗口时长沿用群聊的 reply_window_minutes(默认 10 分钟)。 仅在 QQ 出口发送;库为空或窗口内已发送过时,仅使用文字。
  • 选取方式:计算目标情绪与库内标签的语义相似度(使用 embedding 任务档),从最相近的前 10 张中随机选取一张; embedding 不可用时退化为标签文字包含匹配。两种方式均无候选时不发送。
  • 发送前的停顿为固定的 typing.emoji_pick_seconds(默认 1.5 秒),表情包不按字数模拟打字。
  • 发送成功才累计使用次数;使用频繁、近期使用过的图片在淘汰时优先级更低。

容量与淘汰

库存上限 max_count 默认 1000 张(0 为不限)。超限不在聊天路径上处理, 由后台任务按 check_interval_minutes(默认 5 分钟)检查:

  • auto_evict = true(默认):按「最少使用、最久未使用」的顺序淘汰至上限以内,库记录与文件一并删除。
  • auto_evict = false:仅记录告警,不删除任何记录,库存持续增长。

已封禁的记录不占容量、不参与淘汰。

内容审核与封禁

content_filtration 默认关闭。开启后每张入库图片先经视觉模型审查(复用 vision 任务档); 视觉模型不可用、调用失败或结果无法解析时拒绝入库并记录告警,即不放行未经审查的图片。

面板「表情包库」页(路由 /emojis)支持逐条或批量操作:

  • 封禁:按内容哈希写入独立的封禁表,不删除文件与记录,列表中仍可见(可筛选)。 此后同一图片无论由谁发送均无法入库;记录被淘汰、文件被清理后封禁仍然有效。支持解封。
  • 删除:删除记录与文件。删除不等于封禁,同一图片再次出现在聊天中仍会重新入库; 需要永久拒绝时使用封禁。

孤儿文件清理

目录中存在文件而库中无对应记录的称为孤儿文件(例如手动投放后记录被删除)。[emoji.cleanup] 默认开启: 每 6 小时检查一次,删除无记录且修改时间超过 orphan_retention_days(默认 30 天)的文件。 关闭后孤儿文件仅被报告数量,不做删除。一次性手动清理可使用 scripts/maintain/emoji_orphan_cleanup.py,先以 --dry-run 查看清单。

停用方式与影响

  • collect_enabled = false:停止聊天收集,库存不再增长;发送功能不受影响(使用存量)。
  • 仅保留认可的图片:关闭自动收集,清空库存后手动向 data/emojis/ 投放。
  • 表情包无发送总开关;需要完全停止发送时,清空库存即可(无候选时不发送)。