全项目扫描修复: Docker数据卷修复+安全requireAdmin+12页SEO+API白名单+脚本超时+常量提取+假数据删除
This commit is contained in:
+341
@@ -1,5 +1,346 @@
|
||||
# 追光AI 变更日志
|
||||
|
||||
## 2026-06-11 容器化生产切换 + 旧部署清理
|
||||
|
||||
### 🎯 目标
|
||||
容器测试验证通过后,直接切换生产环境,完全替换 PM2 + 主机 crontab。
|
||||
|
||||
### 🚀 生产切换
|
||||
1. **停止 PM2**:`pm2 delete zhuiguang-ai` + `pm2 kill`,删除 `.pm2` 目录
|
||||
2. **部署生产容器**:`zhuiguang-ai-app`(端口 8301)+ `zhuiguang-ai-cron`(supercronic 13 条定时任务)
|
||||
3. **清空主机 crontab**:`crontab -r`,全部由容器 supercronic 接管
|
||||
4. **Nginx 零改动**:一直代理 `127.0.0.1:8301`,只是后端从 PM2 换成了 Docker
|
||||
|
||||
### 🧹 旧部署清理
|
||||
| 删除项 | 说明 |
|
||||
|--------|------|
|
||||
| `node_modules/`、`.next/` | 旧构建产物 |
|
||||
| `logs/`、`data/` | 旧 PM2 日志/数据(已由 Docker volume 接管) |
|
||||
| `daily-discover.mjs`、`daily-news.mjs`、`task1~task6*.mjs`、`temp_clear.mjs` | 旧 cron 脚本(已由 supercronic 容器调度) |
|
||||
| `cron-wrapper.sh`、`install-cron.sh` | 旧 crontab 管理脚本 |
|
||||
| `restart.ps1` | Windows 本地重启脚本(不再适用) |
|
||||
| `nginx.conf` | 旧 nginx 配置(服务器使用独立 sites-enabled) |
|
||||
| `05-ai-discovery.md` 等 8 个旧文档 | 已由 `.trae/specs/` 统一管理 |
|
||||
| `.backup-2026-06-03/`、`e2e/`、`_skill-prompts/` | 旧备份/测试/提示词目录 |
|
||||
| 测试 Docker 卷(4 个) | `zhuiguang_ai_test_*` 卷 |
|
||||
|
||||
### 🔧 Build 修复(Prisma 7 兼容)
|
||||
- `prisma/schema.prisma`:移除 `datasource.url`(Prisma 7 要求 URL 在 `prisma.config.ts` 中)
|
||||
- 6 个 route/page 加 `export const dynamic = "force-dynamic"` 防止 build 期模块求值
|
||||
- 3 个 OpenAI route 改懒加载 `getOpenAI()` 防止构造时校验 key
|
||||
- Dockerfile 切换 aliyun 镜像源 + npmmirror,supercronic 预下载 COPY 替代 curl
|
||||
|
||||
### 📦 新增文件
|
||||
- `Dockerfile` — 多阶段构建(deps → builder → runner)
|
||||
- `docker-compose.yml` — 2 服务(app + cron)+ 4 命名卷
|
||||
- `docker-compose.test.yml` — 测试部署(端口 8302)
|
||||
- `crontab.txt` — supercronic 调度表,13 条定时任务
|
||||
- `scripts/entrypoint-app.sh` — APP 容器入口(prisma migrate + next start)
|
||||
- `scripts/entrypoint-cron.sh` — CRON 容器入口(supercronic)
|
||||
- `scripts/backup-volumes.sh` — 卷备份脚本
|
||||
- `scripts/install-cron-backup.sh` — 主机备份 cron 安装
|
||||
- `scripts/bin/supercronic-linux-amd64` — 预下载二进制(13MB)
|
||||
- `docs/CONTAINERIZATION.md` — 容器化部署文档
|
||||
- `src/app/api/health/route.ts` — 健康检查 API(Docker HEALTHCHECK)
|
||||
|
||||
### 🏗️ 最终架构
|
||||
```
|
||||
Nginx (443) → 127.0.0.1:8301 → zhuiguang-ai-app (Docker, host 网络)
|
||||
Cron → zhuiguang-ai-cron (Docker, supercronic, host 网络)
|
||||
共享卷: data / public / logs / prisma (命名卷)
|
||||
外部: 阿里云 RDS / 共享 Redis / 共享 Nacos / 共享 MinIO
|
||||
```
|
||||
|
||||
### ✅ 验证
|
||||
- 容器内 `next-server` 运行正常,端口 8301 监听
|
||||
- `/`、`/tools`、`/skills`、`/login` 全部 HTTP 200
|
||||
- `/api/health` 返回 `{"status":"ok"}`,数据库连接 81ms
|
||||
- `/api/forum/categories` 返回完整分类数据
|
||||
- Cron 容器 13 条定时任务已加载,supercronic 正常运行
|
||||
- PM2 完全清理:无进程、无 daemon、无 dump、无 `.pm2` 目录
|
||||
- 主机 crontab 已清空
|
||||
|
||||
---
|
||||
|
||||
## 2026-06-11 全量容器化(Docker Compose 编排 + supercronic 调度)
|
||||
|
||||
### 🎯 目标
|
||||
服务器上 3+ 邻居项目(zhuiguang-quant/zhenfang/snowy-fgt/agent-system)+ 3 个共享 Docker 服务(redis-cache/nacos/minio),本项目评估后决定全量容器化。
|
||||
|
||||
### 📦 新增文件
|
||||
- `Dockerfile` — 多阶段构建(deps → builder → runner),node:20-alpine,最终镜像 ~300MB
|
||||
- `.dockerignore` — 排除 node_modules / .next / logs / data / 调试脚本
|
||||
- `docker-compose.yml` — 2 个服务(app + cron)+ 4 个命名卷
|
||||
- `crontab.txt` — supercronic 调度表,13 个定时任务
|
||||
- `scripts/entrypoint-app.sh` — APP 启动入口(prisma migrate + next start)
|
||||
- `scripts/entrypoint-cron.sh` — CRON 启动入口(supercronic)
|
||||
- `scripts/backup-volumes.sh` — 卷备份(4 个命名卷 → /home/ubuntu/zhuiguang-ai-backup/dockers/)
|
||||
- `scripts/install-cron-backup.sh` — host 备份 cron 安装
|
||||
- `docs/CONTAINERIZATION.md` — 部署文档(架构 / 部署步骤 / 运维命令 / 回滚方案)
|
||||
|
||||
### 🏗️ 架构
|
||||
```
|
||||
zhuiguang-ai-app (Next.js, 端口 8301, host 网络)
|
||||
│
|
||||
zhuiguang-ai-cron (supercronic, host 网络)
|
||||
│
|
||||
共享卷: data / public / logs / prisma
|
||||
外部访问: 阿里云 RDS / 共享 Redis / 共享 Nacos / 共享 MinIO
|
||||
```
|
||||
|
||||
### ✅ 验证
|
||||
- shell 脚本 `bash -n` 全部通过
|
||||
- `docker-compose config --quiet` 解析通过
|
||||
- 服务器 `docker build` **已尝试但因邻居项目 `/opt/zhui-guang/deploy` 同时跑 2 个 --no-cache build 抢占 docker daemon 资源,被卡住**
|
||||
- 计划:等邻居项目 build 跑完后再试,或换 buildx 提速
|
||||
|
||||
### 🔧 第二次 Build 成功(解决 3 个网络/构建问题)
|
||||
1. **apk 源极慢**(`dl-cdn.alpinelinux.org` 1m23s vs `mirrors.aliyun.com` 0.134s)
|
||||
- Dockerfile 加 `sed -i 's|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g' /etc/apk/repositories`
|
||||
- npm 也切到 `registry.npmmirror.com`
|
||||
2. **GitHub release 下载超时**(supercronic 二进制从 release-assets.githubusercontent.com 拉不动)
|
||||
- 预下载到 `scripts/bin/supercronic-linux-amd64`(SHA1 已验证)
|
||||
- Dockerfile 用 `COPY` 而不是 `curl` 下载
|
||||
3. **Next.js build 期 page data collection 触发模块求值**(OpenAI SDK v6+ 构造时校验 key、Prisma 校验 mariadb URL)
|
||||
- 3 个 OpenAI route → 懒加载 client + `export const dynamic = "force-dynamic"`
|
||||
- 2 个 server page (`/`、`/skills`) + 1 个 API (`/api/forum/categories`) → 加 `export const dynamic = "force-dynamic"`
|
||||
- Dockerfile build env 注入占位 `DEEPSEEK_API_KEY` / `OPENAI_API_KEY`
|
||||
4. **COPY 命令语法错误**(`COPY --from=builder X Y 2>/dev/null || true` 不是合法 COPY 语法)
|
||||
- 改为直接 COPY(这些配置文件项目里都有)
|
||||
|
||||
### ✅ Build 成功
|
||||
```
|
||||
Successfully built fc5862d68119
|
||||
Successfully tagged zhuiguang-ai:test
|
||||
Image: zhuiguang-ai:test (1.27GB)
|
||||
- /usr/local/bin/supercronic-linux-amd64 ✓
|
||||
- /app/.next/BUILD_ID ✓
|
||||
- /app/.next/app-build-manifest.json ✓
|
||||
Entrypoint: /sbin/tini -- /usr/local/bin/entrypoint-app.sh
|
||||
```
|
||||
构建用时:~3 分钟(含全部 45 步)
|
||||
|
||||
### ⏳ 待办
|
||||
- 切到 buildx 重新 build(速度比传统 builder 快 3-5 倍)
|
||||
- 暂不切生产(PM2 当前 7+ 天 0 重启,验证完容器再切)
|
||||
- 切生产时保留 PM2 镜像,24h 监控无问题后才 `pm2 delete`
|
||||
|
||||
## 2026-06-11 论坛发帖量翻倍 + 服务器部署同步
|
||||
|
||||
### 📈 调参(翻倍论坛内容)
|
||||
- **scripts/bot-activity.mjs**
|
||||
- `EXPERT_FORUMS_PER_RUN`: 4 → **5**(+25%)
|
||||
- `PASSERBY_FORUMS_PER_RUN`: 4 → **5**(+25%)
|
||||
- `MAX_REPLIERS_PER_FORUM`: slice(0, 3) → **slice(0, 4)**(+33%)
|
||||
- `QUOTA`:
|
||||
- high: topicPerDay 3→**4**, replyPerDay 10→**15**
|
||||
- medium: topicPerDay 1→**2**, replyPerDay 5→**8**
|
||||
- low: topicPerDay 0→**1**, replyPerDay 2→**4**
|
||||
- `BOT_LIKE_CONFIG`: MAX_LIKES_PER_RUN 3→**5**, PROBABILITY_PER_BOT 0.6→0.65
|
||||
- 跑批节奏不变:9-23 每整点 15 轮/天
|
||||
- **理论产出**:原 5 项/轮 → 现 8-10 项/轮,约 1.7-2x
|
||||
|
||||
### 🛠️ 部署同步(修复 Prisma 模型未注册)
|
||||
- 服务器原本是 v1 schema,跑了简单版 bot-activity.mjs(无 BotDailyStat 等新模型)
|
||||
- 部署本次需要:
|
||||
1. 推送新 `scripts/bot-activity.mjs`(带 v2 逻辑)
|
||||
2. 推送新 `scripts/lib/{bot-persona,bot-persona-experiment,bot-adversarial-learning}.mjs`(旧服务器没这几个 lib)
|
||||
3. 推送新 `prisma/schema.prisma`(v2)
|
||||
4. 服务器 `npx prisma generate` 重新生成 client
|
||||
- ✅ 部署完后,1 次手动跑产出 9 个 expert topic/reply + 8 个 passerby topic,A/B variants 正常分配,persona 异步刷新触发
|
||||
|
||||
### 📜 cron 注释更新
|
||||
- scripts/install-cron.sh 中 bot-activity 一行注释改为「5+5=10 板块+4 回复/板块+5 点赞」
|
||||
|
||||
### 🧪 验证
|
||||
- 服务器 17:33 一次跑:5 expert + 5 passerby 板块都处理,9 个 topic + 多个 reply,🅰️ variant 分配成功
|
||||
- 之前服务器 schema 落后导致 `prisma.botDailyStat` 为 undefined(已修)
|
||||
|
||||
## 2026-06-08 数字人头像 / 主页(Lunaris 工具生成 + 落盘)
|
||||
|
||||
|
||||
### 🟢 核心功能
|
||||
为 112 个 bot 批量预生成头像:先调 Lunaris(trae-api)拿 AI 图,识别到占位 default 后改用程序化 SVG 兜底(按 key 哈希生成唯一调色板 + 几何装饰 + displayName 首字),落盘到 `public/bot-avatars/`,回写 `User.avatarUrl`。
|
||||
|
||||
### 📦 核心库
|
||||
- **scripts/lib/bot-avatar-generator.mjs**
|
||||
- `hashKey(key)` / `pickFromKey(key, max)` / `keyToBytes(key)` — 稳定哈希(用于 SVG 几何定位)
|
||||
- `PALETTE` — 10 色调色板(与 `src/lib/bot-utils.ts` 的 `getBotColorScheme` 视觉一致)
|
||||
- `pickPalette(key)` — 按 key 选调色板
|
||||
- `fetchLunarisImage(avatarPrompt, {size, timeout})` — 调 Lunaris API(`https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image`)
|
||||
- `isLunarisDefault(buffer)` — SHA-256 前 10 位匹配 `e330cd0232` 即视为占位
|
||||
- `generateSvgAvatar({key, displayName, persona})` — 512×512 SVG 头像:渐变背景 + 4 个装饰几何(位置/大小/旋转由 key 决定)+ 角色徽章(行业专家/社区观察者)+ 中央大字 initial + 右下角机器脸(path 绘制不依赖 emoji 字体)
|
||||
- `generateForBot(character, opts)` — 单 bot 生成主流程(Lunaris 拉取 → 占位检测 → 落盘 SVG/JPG → 返回 metadata)
|
||||
- `generateForAll(opts)` — 全量入口(遍历 112 个 character → 写库 → 写 manifest)
|
||||
- 工具常量:`BOT_DATA_PATH` / `AVATAR_DIR` / `LUNARIS_DIR` / `LUNARIS_DEFAULT_HASH_PREFIX`
|
||||
|
||||
### 🤖 批量生成 CLI
|
||||
- **scripts/bot-avatar-generate.mjs** — 调度入口
|
||||
- `node scripts/bot-avatar-generate.mjs` — 全部 112 个 bot 一次性生成
|
||||
- `--bot=<key>` — 单个 bot
|
||||
- `--force` — 覆盖已存在
|
||||
- `--use-lunaris-only` — 禁用 SVG 兜底(当前 Lunaris 全是 default,不推荐)
|
||||
- `--no-update-db` — 只落盘不写 User.avatarUrl
|
||||
- `--dry-run` — 试运行
|
||||
- `--delay=<ms>` — bot 间隔(默认 200ms)
|
||||
|
||||
### 🗂️ 落盘结构
|
||||
```
|
||||
public/bot-avatars/
|
||||
├── {key}.svg # 唯一程序化头像(112 个,~2.5KB/个,总 278KB)
|
||||
├── manifest.json # 生成清单(generatedAt / total / succeeded / failed / avatars[])
|
||||
└── lunaris/
|
||||
└── {key}.jpg # Lunaris 拉取的原图(111 个;后续 Lunaris 支持按 prompt 生成时可切回)
|
||||
```
|
||||
|
||||
### 🎨 SVG 设计要素
|
||||
- 渐变背景:从 10 色调色板里按 key 哈希选
|
||||
- 装饰图形:4 个半透明白色几何(圆/方/多边形),位置/大小/旋转由 key 决定
|
||||
- 角色徽章:左上角「行业专家 / 社区观察者」半透明圆角徽章
|
||||
- 中央大字母:displayName 首字符(280px 字号 + 阴影)
|
||||
- 右下角:白色圆形底 + 紫色机器脸(path 绘制,跨平台一致)
|
||||
|
||||
### 🔁 兼容性
|
||||
- 现有 `src/components/forum/BotAvatar.tsx` 优先用 `user.avatarUrl`,无值时回退到 `getBotAvatarUrl()`(仍走 Lunaris 动态 URL)
|
||||
- 现在 DB 里 112 个 bot 都有 `avatarUrl = /bot-avatars/{key}.svg`,会直接用本地 SVG
|
||||
- 当 Lunaris 真正支持按 prompt 生成时,重跑 `node scripts/bot-avatar-generate.mjs --force --use-lunaris-only` 即可切回 AI 生成的版本
|
||||
|
||||
### 📊 验证结果
|
||||
| 项目 | 结果 |
|
||||
|------|------|
|
||||
| SVG 文件 | 112 个生成成功(278KB 总计) |
|
||||
| Lunaris 调用 | 111 次成功(1 个因首次运行被中断缺失,已用上次结果) |
|
||||
| Lunaris 占位检测 | 100% 命中,全部走 SVG 兜底 |
|
||||
| DB 更新 | 112/112 bot `avatarUrl` 已指向 `/bot-avatars/{key}.svg` |
|
||||
| 唯一性 | 每个 SVG SHA-256 hash 独立(key → 调色板 + 几何位置 完全确定) |
|
||||
| 全程耗时 | 77 秒(延迟 50ms + Lunaris 平均 700ms/bot) |
|
||||
|
||||
### 📁 变更统计
|
||||
| 类型 | 数量 |
|
||||
|------|------|
|
||||
| 新增文件 | 2 个(lib + CLI)+ 224 个产物(112 SVG + 111 JPG + 1 manifest) |
|
||||
| 修改文件 | 0(纯增量,无破坏性改动) |
|
||||
|
||||
---
|
||||
|
||||
## 2026-06-07 Bot 对抗学习(数字人 vs 真人)
|
||||
|
||||
### 🟢 核心功能
|
||||
每周日 23:00 自动给每个 bot 选 1 篇过去 7 天真人发布的高互动帖(forum topic / post),通过 LLM 提取"为什么火"的洞察,下周 bot 发帖/回复时把这条洞察作为参考。下次生成内容时会优先选 status=active、且 learnedAt 最近的学习作为"灵感"。
|
||||
|
||||
### 🗄️ 数据模型(1 张新表)
|
||||
- **prisma/schema.prisma** — 新增 `BotAdversarialLearning`(含 `bot_id` / `week_key` / `source_ref_type` / `source_metrics` JSON / `relevance_score` / `learned_insight` / `learn_categories` / `status` / `used_count` / `expires_at`)
|
||||
- **prisma/migrations/20260607010000_bot_adversarial_learning/** — 建表 SQL
|
||||
- 关键约束:`@@unique([botId, weekKey])` 同一 bot 同一周只学 1 篇;过期时间到自动 `status=expired`
|
||||
|
||||
### 📦 核心库
|
||||
- **scripts/lib/bot-adversarial-learning.mjs**
|
||||
- `loadAllExpertBots()` — 拉所有启用的 expert bot
|
||||
- `loadHumanPostsForLearning({lookbackDays})` — 拉过去 N 天真人 topic,score = reply×5 + like×2 + view×0.1 + humanReply×8,取 topK
|
||||
- `scoreRelevance(post, bot, persona)` — 算关联度(forum 命中 + 关键词重叠 + 时间衰减)
|
||||
- `extractInsight(post, bot, persona)` — 调用 DeepSeek 提取"为什么火"的结构化洞察(hook / 论证 / 互动钩子 / 标签)
|
||||
- `learnForBot(user, config, persona, {weekKey, lookbackDays})` — 单 bot 学习主流程(选源 → 算分 → LLM 提取 → upsert)
|
||||
- `runWeeklyAdversarialLearning(options)` — 全量入口(遍历 bots → 跑学习 → 把过期 learning 标 expired)
|
||||
- `getActiveLearningForBot(botConfigId)` — bot 发帖前查询当前可用的 learning
|
||||
- `markLearningUsed(learningId)` — 引用后 used_count++
|
||||
- `buildAdversarialBlock(learning)` — 把 learning 渲染成 prompt 注入块
|
||||
- `getISOWeekKey(d?)` — 计算 "2026-W23" 形式的周键
|
||||
|
||||
### 🤖 Bot 活动引擎集成
|
||||
- **scripts/bot-activity.mjs** — topic / reply 创建前 `getActiveLearningForBot()`,把 `adversarialBlock` 注入 prompt;创建后 `markLearningUsed()`
|
||||
- 3 处接入:① 主动发新 topic ② 抢答其他 bot 的 topic ③ 跨板块 topic
|
||||
- prompt 块形如:「🎓 本周真人高赞参考(来自@xxx,关联度0.78):hook: ... 论证: ... 互动钩子: ... 标签: [...]」
|
||||
|
||||
### ⏰ 调度任务
|
||||
- **scripts/bot-adversarial-learning-run.mjs** — 调度入口,支持 `--week=YYYY-Www` / `--force` / `--bot=xxx` / `--lookback=7`
|
||||
- **scripts/seed-task-configs.mjs** — 注册 taskKey `bot-adversarial-learning-run`,cron `0 23 * * 0`(每周日 23:00)
|
||||
- **scripts/install-cron.sh** — 追加 15 号任务 `0 23 * * 0 bash $WRAPPER bot-adversarial-learning-run`
|
||||
- 学习后自动给 `expires_at = learned_at + 7d`,过期由下一次调度清标
|
||||
|
||||
### 🖥️ 管理后台看板
|
||||
- **src/app/api/admin/bots/adversarial-learning/route.ts** — GET 看板数据(支持 `weeks` / `botUserId` 参数,附 source topic / 板块 / 作者 enrich)
|
||||
- **src/app/api/admin/bots/adversarial-learning/run/route.ts** — POST 手动触发(支持 `mode=run|reset`,reset 删除指定 bot 当周 learning)
|
||||
- **src/app/(admin)/admin/bot-adversarial-learning/page.tsx** + **BotAdversarialLearningClient.tsx** — 看板 UI
|
||||
- 顶部 6 张 summary 卡(总学习数 / 活跃 / 已用 / 平均关联度 / bot 数 / 周期数)
|
||||
- 学习列表(含 bot 头像 / 源帖标题 / 作者 / 关联度 / LLM 洞察 / 标签 / 引用次数)
|
||||
- 顶部时间窗口切换(1/2/4/8/12 周)+ 单 bot 过滤
|
||||
- 「手动跑一次 / 重跑 / 刷新」三个动作
|
||||
- **src/app/(admin)/admin/layout.tsx** — 新增菜单 "Bot 对抗学习" 入口(紧邻 A/B 看板)
|
||||
|
||||
### 🎯 选源策略
|
||||
- 仅取非 bot 用户(`author.isBot = false`)
|
||||
- 真实互动分 = `replyCount×5 + likeCount×2 + viewCount×0.1 + humanReplies×8`(真人回复权重最高)
|
||||
- 关联度 = forum 命中(0.4)+ 关键词 jaccard(0.4)+ 24h 衰减(0.2)
|
||||
- 同一 (bot, week) 唯一,周日 23:00 跑,下周日自动过期
|
||||
|
||||
### 📁 变更统计
|
||||
| 类型 | 数量 |
|
||||
|------|------|
|
||||
| 新增文件 | 5 个(lib / run / migration / API route / admin page+client) |
|
||||
| 修改文件 | 4 个(schema.prisma / bot-activity.mjs / seed-task-configs.mjs / install-cron.sh / admin/layout.tsx) |
|
||||
| 验证 | tsc 零错误;模拟高赞帖 → learning 写入 → 下次 bot 发帖注入 prompt 全部跑通 |
|
||||
|
||||
---
|
||||
|
||||
## 2026-06-07 Bot 人设 A/B 测试框架(数字人内容策略优化)
|
||||
|
||||
### 🟢 核心功能
|
||||
为每个 bot 同时跑 2-3 个 persona 变体(control + 风格化变体),按权重分流到 topic/post 创建链路,采集真实互动数据后用 z 检验判断 winner,自动提升 winner 权重并降低其他变体。
|
||||
|
||||
### 🗄️ 数据模型(4 张新表)
|
||||
- **prisma/schema.prisma** — 新增 `BotPersonaVariant` / `BotPersonaExperiment` / `BotPersonaAssignment` / `BotPersonaMetric`
|
||||
- **prisma/migrations/20260607000000_bot_persona_ab_test/** — 建表 SQL
|
||||
- 关键字段:变体 `weight` / `isControl` / `isActive` / `styleHints`(JSON) / 累计 `sampleCount` / `likeCount` / `humanReplyCount` / `engagementScore`
|
||||
|
||||
### 📦 核心库
|
||||
- **scripts/lib/bot-persona-experiment.mjs**
|
||||
- `ensureBotVariants(botConfigId)` — 给 bot 派生 control + variant_a(口语+故事) + variant_b(数据+简洁) 3 个变体
|
||||
- `ensureExperiment(botConfigId)` — 启动/复用该 bot 的 A/B 实验
|
||||
- `pickVariantForPrompt(botConfigId)` + `commitAssignment()` — 轻量版分流(先生成内容再写库)
|
||||
- `pickAndAssignVariant()` — 一步版分流
|
||||
- `buildVariantPersonaBlock(variant)` — 把 `styleHints` 渲染成注入 prompt 的 block
|
||||
- `recordAssignmentMetrics()` — ① 拉 assignment → 回填真实 reply/like/humanReply/impression ② 按 (variantId, date) 聚合到 metrics 表 ③ 回写变体累计统计
|
||||
- `analyzeBotVariants()` — 双比例 z 检验(p<0.1, sample≥20)
|
||||
- `analyzeAndSwitchAllBots()` — 遍历所有 bot,发现 winner 后把权重提升到 0.85、其他降到 0.075,experiment → completed
|
||||
|
||||
### 🤖 Bot 活动引擎集成
|
||||
- **scripts/bot-activity.mjs** — topic / reply 创建前 `pickVariantForPrompt()`,创建后 `commitAssignment()`,并把 `variantBlock` 注入 prompt
|
||||
- 3 处接入:① 主动发新 topic ② 抢答其他 bot 的 topic ③ 跨板块 topic
|
||||
|
||||
### ⏰ 调度任务
|
||||
- **scripts/bot-persona-experiment-run.mjs** — 调度入口,支持 `--lookback=7` / `--no-switch` / `--metrics-only` / `--analyze-only`
|
||||
- **scripts/seed-task-configs.mjs** — 注册 taskKey `bot-persona-experiment-run`,cron `45 */4 * * *`
|
||||
- **scripts/install-cron.sh** — 追加 14 号任务 `45 */4 * * * bash $WRAPPER bot-persona-experiment-run ... --lookback=7`
|
||||
- **scripts/seed-persona-variants.mjs** — 一键为所有 bot 初始化变体 + 实验(已运行 46 bots / 46 experiments / 15 新建变体)
|
||||
|
||||
### 🖥️ 管理后台看板
|
||||
- **src/app/api/admin/bots/experiments/route.ts** — GET 看板数据(变体 / 实验 / 显著性分析)
|
||||
- **src/app/api/admin/bots/experiments/run/route.ts** — POST 手动触发调度(`mode=all|metrics|analyze`)
|
||||
- **src/app/api/admin/bots/experiments/variants/route.ts** — PATCH 改权重 / 启停 / 重置样本,DELETE 删除变体
|
||||
- **src/app/(admin)/admin/bot-experiments/page.tsx** + **BotExperimentsClient.tsx** — 看板 UI
|
||||
- 顶部 6 张 summary 卡(bots / 变体 / 活跃实验 / winners / 样本 / 互动)
|
||||
- 显著性分析区(按 bot 折叠展开,含 control / 各变体 z-score / p-value / winner 徽章)
|
||||
- 变体权重 / 启用 / 重置样本的 inline 操作
|
||||
- 实验时间线表 + 变体总览表(按综合分排序)
|
||||
- "采指标" / "采指标+切换 winner" / "刷新" 三个动作按钮
|
||||
- **src/app/(admin)/admin/layout.tsx** — 新增菜单 "Bot A/B 看板" 入口(内容管理组)
|
||||
|
||||
### 📈 显著性策略
|
||||
- 控制组:每个 bot 的 `isControl=true` 变体(默认 control = 原版 persona)
|
||||
- 实验组:variant_a(口语+故事,问号略多,避免"综上所述/首先其次最后")+ variant_b(数据驱动+简洁,maxLength 280 字)
|
||||
- 综合分 = (赞×3 + 真人回复×5 + 回复) ÷ 样本数
|
||||
- z 检验:双侧检验,p<0.1 且样本≥20 视为显著
|
||||
- 切换:winner weight=0.85,其他活跃变体 weight=0.075,experiment 标记 completed
|
||||
|
||||
### 📁 变更统计
|
||||
| 类型 | 数量 |
|
||||
|------|------|
|
||||
| 新增文件 | 9 个(lib/experiment、run、seed、migration、3 个 API、2 个 admin page、CHANGELOG) |
|
||||
| 修改文件 | 4 个(schema.prisma / bot-activity.mjs / seed-task-configs.mjs / install-cron.sh / admin/layout.tsx) |
|
||||
| 验证 | tsc 零错误;seed 跑通 46 bots / 15 新建变体;scheduler 调度器触发无错 |
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-28 UI优化 + 社区页面修复
|
||||
|
||||
### 🟡 HeroBanner 新增 orange 配色方案
|
||||
|
||||
Reference in New Issue
Block a user