# 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_ENABLE/WEB_USERNAME/WEB_PASSWORD/WEB_SECRET_KEY) ├── web.py Web 管理后台后端(/galgame_card/api/*,JWT 登录,仿 learning_chat) ├── web/index.html 管理后台前端(单文件,无需构建) ├── DESIGN.md 设计定稿(数据模型/流水线/九段协议/证据纪律) └── CLAUDE.md 本文件 ``` **Web 管理后台**:`http://:/galgame_card`(默认 admin/galgame,可在 .env 改 WEB_*)。功能:群开关、参与者增删、语料/印象/画像浏览与删除、清空群数据。路由在 `@driver.on_startup` 里注册,改后端需重启 bot。 ## 核心设计(速览,细节见 DESIGN.md) 1. **两级闸门**:群开关 `persona_group.enabled`(默认关)+ 个人 opt-in `persona_user`,都过才采集 2. **两级流水线**:语料 →(攒够 N 条)→ 印象(LLM 自然语言,增量中间层)→(攒够 M 条)→ 画像(九段 markdown,版本化) 3. **消息五维**:内容 / 谁发的 / 发给谁(回复/@)/ 几点发的 / 被回复内容快照——只存治理后纯文本 4. **脱敏四层**(`desensitize()`):明确模式(最长优先排序防截胡)→ 定位式(同条关键词+值)→ 跨条语境(关键词在附近消息)→ 兜底(保守替换) 5. **九段画像协议**:身份印象/性格特征/说话风格/口头禅语录/兴趣话题/相处模式/时间画像/样貌参考(虚构)/不确定信息 6. **总结路径不进消息 handler**:LLM 调用只在调度器触发,防延迟/限流 ## 开发命令 ```bash # 跑本插件测试(治理层纯函数,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`(本插件未设置,走默认库) ## 开发注意事项(踩过的坑) 0. **⚠️ 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)。 1. **`on_message` 必须 `block=False`**:否则事件流被拦截,群里其他插件全废 2. **只收群消息**:handler 参数注解 `GroupMessageEvent`(类型注解即过滤器) 3. **脱敏正则排序**:身份证/银行卡必须在手机号之前,否则手机号截胡身份证数字段 4. **定位式替换只替换值、保留关键词**:`密码是 xyz789` → `密码是 [密码]`,关键词不能丢 5. **测试不能裸 import 包**:`__init__.py` 触发 NoneBot 初始化,用 importlib 按路径加载 processor(见 `tests/test_persona_processor.py`,与 test_rate_limit 同款) 6. **总结/印象生成**:绝不在消息 handler 里调 LLM,走调度层(apscheduler) 7. **仓储并发**:`add_summary` 版本自增有并发撞 UNIQUE 风险,调度层加锁保护 ## 当前进度 - ✅ 数据层:五表 + 仓储(含群开关、滚动淘汰、版本自增) - ✅ 采集层:消息路径(监控→鉴权→治理→脱敏→采样→落库) - ✅ Web 管理后台:/galgame_card(群开关、参与者、数据浏览/清理;Chrome 已实测) - ⏳ QQ 命令集:`开启人设采集` / `加入人设` / `退出人设` / `查看人设`(Web 已覆盖同等功能,QQ 命令可选做) - ⏳ 总结路径:LLM 客户端、印象生成、九段画像生成、调度触发 - ⏳ 呈现层:人物卡展示/图片渲染 ## 待决策点 - 触发阈值(印象 ≥50 条新语料 / 画像 ≥5 条新印象,⏳ 待调) - 脱敏兜底位数(裸数字 ≥6 位默认替换 `[账号]`,保守优先;误杀多可提到 8 位,动 `BARE_DIGITS_RE`) - 密保答案场景(中文值正则误杀率高,方案待定) - 命令名与权限(超管/群主)