5.4 KiB
5.4 KiB
CLAUDE.md — 群聊人设卡插件开发文档
本文件是本插件内开发的唯一入口文档;需要项目全局信息(Poetry 命令、启动方式、测试约定)时再查项目根目录的 CLAUDE.md。详细设计定稿见同目录 DESIGN.md。
插件概述
基于群聊语料蒸馏群成员的形象风格,生成 galgame 风格人物卡(九段画像)。
- 目标:生成"人的画像",不是关系网分析;样貌参考为虚构,永远带标注
- 隐私硬约束:只采集 opt-in 成员;敏感数据本地正则替换为占位符,绝不经过 LLM
- 维度隔离:每个
(group_id, user_id)是独立人设,跨群不混
目录结构
nonebot_plugin_galgame_card/
├── __init__.py 入口层:on_message 采集器(鉴权/采样/调治理落库)
├── models.py 数据层:五张表(persona_group/user/chat_log/impression/summary)
├── repository.py 数据层:仓储(来源无关,所有读写唯一入口)
├── processor.py 治理层:纯函数(五维提取/噪声/脱敏),可单测
├── config.py 插件配置(仅图片识别开关等;Web 鉴权统一走 /hub)
├── web_hub.py Web API 子应用(挂载到 /api/galgame_card,auth=hexi.web_hub.web_auth)
├── DESIGN.md 设计定稿(数据模型/流水线/九段协议/证据纪律)
└── CLAUDE.md 本文件
Web 管理后台:已嵌入统一管理台 /hub/,前端由 hexi/web 渲染,API 挂载到 /api/galgame_card,鉴权与 /hub 共用 hexi.web_hub.web_auth(OAuth2 + SQLite)。功能:群开关、参与者增删、语料/印象/画像浏览与删除、清空群数据。改后端需重启 bot。
核心设计(速览,细节见 DESIGN.md)
- 两级闸门:群开关
persona_group.enabled(默认关)+ 个人 opt-inpersona_user,都过才采集 - 两级流水线:语料 →(攒够 N 条)→ 印象(LLM 自然语言,增量中间层)→(攒够 M 条)→ 画像(九段 markdown,版本化)
- 消息五维:内容 / 谁发的 / 发给谁(回复/@)/ 几点发的 / 被回复内容快照——只存治理后纯文本
- 脱敏四层(
desensitize()):明确模式(最长优先排序防截胡)→ 定位式(同条关键词+值)→ 跨条语境(关键词在附近消息)→ 兜底(保守替换) - 九段画像协议:身份印象/性格特征/说话风格/口头禅语录/兴趣话题/相处模式/时间画像/样貌参考(虚构)/不确定信息
- 总结路径不进消息 handler:LLM 调用只在调度器触发,防延迟/限流
开发命令
# 跑本插件测试(治理层纯函数,9+ 个用例)
poetry run pytest tests/test_persona_processor.py
# 全量测试
poetry run pytest
# 启动/重启验证:PyCharm 的 "start bot" 运行配置(勿用 bat 脚本)
数据库
- orm 默认库:
data/nonebot_plugin_orm/db.sqlite3(不是hexi/data/data.db) - 建表:bot 启动时 orm 自动 create_all(新表加在
models.py里即可,重启生效) - 配置键是
SQLALCHEMY_DATABASE_URL(本插件未设置,走默认库)
开发注意事项(踩过的坑)
- ⚠️ orm 启动自动同步会清空表数据:
.env里ALEMBIC_STARTUP_CHECK=false时,nonebot_plugin_orm 每次启动都 autogenerate 同步数据库模式,模型一有变更(改 models.py)就会重建表、清空全部数据(2026-08-11 实测踩坑,全表被清)。已在本插件__init__.py导入期把migrate.sync替换为安全空操作。今后 schema 演进只准通过repository.ensure_schema()显式 ALTER,改完 models.py 后要在重启前手动执行对应 ALTER(或加进 ensure_schema)。 on_message必须block=False:否则事件流被拦截,群里其他插件全废- 只收群消息:handler 参数注解
GroupMessageEvent(类型注解即过滤器) - 脱敏正则排序:身份证/银行卡必须在手机号之前,否则手机号截胡身份证数字段
- 定位式替换只替换值、保留关键词:
密码是 xyz789→密码是 [密码],关键词不能丢 - 测试不能裸 import 包:
__init__.py触发 NoneBot 初始化,用 importlib 按路径加载 processor(见tests/test_persona_processor.py,与 test_rate_limit 同款) - 总结/印象生成:绝不在消息 handler 里调 LLM,走调度层(apscheduler)
- 仓储并发:
add_summary版本自增有并发撞 UNIQUE 风险,调度层加锁保护
当前进度
- ✅ 数据层:五表 + 仓储(含群开关、滚动淘汰、版本自增)
- ✅ 采集层:消息路径(监控→鉴权→治理→脱敏→采样→落库)
- ✅ Web 管理后台:嵌入 /hub(/api/galgame_card + hexi/web 页面;群开关、参与者、数据浏览/清理)
- ⏳ QQ 命令集:
开启人设采集/加入人设/退出人设/查看人设(Web 已覆盖同等功能,QQ 命令可选做) - ⏳ 总结路径:LLM 客户端、印象生成、九段画像生成、调度触发
- ⏳ 呈现层:人物卡展示/图片渲染
待决策点
- 触发阈值(印象 ≥50 条新语料 / 画像 ≥5 条新印象,⏳ 待调)
- 脱敏兜底位数(裸数字 ≥6 位默认替换
[账号],保守优先;误杀多可提到 8 位,动BARE_DIGITS_RE) - 密保答案场景(中文值正则误杀率高,方案待定)
- 命令名与权限(超管/群主)