1. 结论先行

AstrBot 的"某个群用某个人格"不是绑在 QQ 号上的,而是绑在 umo(Unified Message Origin,统一消息来源) 上。

  • 人格内容存在人格系统里(personas 表 / WebUI「人格」页)。
  • "哪个会话用哪个人格"按 umo 存。群聊时 umo 里含群号,私聊时含对方 QQ 号。

所以 QQ 号只是 umo 的一个组成部分,起索引作用;真正的人格定义、默认人格、回退链都是 AstrBot 自己的体系。

2. umo 的格式

定义见 astrbot/core/platform/message_session.py:

def __str__(self) -> str:
    return f"{self.platform_id}:{self.message_type.value}:{self.session_id}"

即 平台实例ID : 消息类型 : 会话号。

实机样例(tx 服务器):

Rap:GroupMessage:588720780      # 平台 Rap(NapCat实例) 的 QQ 群 588720780
Rap:FriendMessage:1808666025    # 平台 Rap 的好友 1808666025
me:GroupMessage:940639703       # 平台 me(另一 NapCat实例) 的群
webchat:FriendMessage:webchat!admin!5f40d7da-...

群聊的 session_id 是群号,不是发言人的 QQ 号。 因此同一个人在 A 群和 B 群是两个不同的 umo,可以挂不同人格。

3. 人格解析链

astrbot/core/persona_mgr.py 的 resolve_selected_persona(umo):

1. 查 preferences 表 scope='umo', scope_id=<umo>, key='session_service_config'
2. 取其中 force_applied_persona_id = session_service_config.get("persona_id")
3. 没命中 → 回落到配置里的 provider_settings.default_personality

它不回落到 QQ 号。会话级覆盖与全局默认之外没有第三层。

session_service_config 除 persona_id 外还可存:

{"session_enabled": true, "llm_enabled": true, "tts_enabled": false, "custom_name": "LT"}

persona_pool(配置项 provider_settings.persona_pool)控制该会话可选的人格范围,["*"] 表示全部可选。

4. 存储位置

AstrBot 4.x 用 SQLite,库在 <data>/data_v4.db。相关表:

表作用
personas人格定义(persona_id / system_prompt / begin_dialogs / tools / skills)
persona_folders人格分组
preferencesscope/scope_id/key/value,scope='umo' 时即会话级配置
platform_sessions平台侧会话登记(session_id / platform_id / is_group)
conversations对话记录,每行也带 persona_id,为空则回落默认
umo_aliasesumo 别名

5. 实机查证(2026-09-17,tx 服务器)

两处易踩的坑:

  1. cmd_config.json 带 UTF-8 BOM,Python 直接 json.load 会抛 Unexpected UTF-8 BOM。要用 encoding="utf-8-sig"。
  2. 该库有 -wal / -shm 文件,别只拷 .db,否则读到旧数据。

当时的实际状态:

人格总数 2:细雨初晴(小晴)、reados-bot(小念)
default_personality = reados-bot          # 全局默认
persona_pool        = ["*"]               # 全部人格可选
平台实例:Rap(aiocqhttp,启用)、me(aiocqhttp,启用)
        小晴 / weixin_personal_qgsb (weixin_oc, 均停用)
已配 session_service_config 的会话 3 个,但都没设 persona_id
→ 结论:当时所有群实际都在用全局默认 reados-bot

即"配了会话设置"≠"配了人格"。会话设置只写开关也会落一行记录,容易误判成已经绑了人格。要确认某群人格,直接查:

SELECT scope_id, value FROM preferences
WHERE key='session_service_config';
-- 看 value 里有没有 "persona_id"

6. 相关笔记


本文归档于个人知识库 · 领域:CS & AI · 模块:04 Project_CS_AI/AI apps