全项目扫描修复: 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 配色方案
|
||||
|
||||
+152
-22
@@ -6,19 +6,122 @@
|
||||
- 重启脚本仅扫描8301-8310范围
|
||||
- **强制要求:本项目端口必须锁定在8301-8310区间内,禁止使用其他端口,因为本服务器同时运行其他产品**
|
||||
|
||||
## 服务器连接信息(重要!总是需要)
|
||||
- **IP地址**: 119.45.242.239
|
||||
- **登录用户**: ubuntu
|
||||
- **SSH密钥**: `C:\SGP_KF\ZhuiGuangAI\zhuiguang-ai\Pem\zg.pem`
|
||||
- **SSH命令**: `ssh -i "C:\SGP_KF\ZhuiGuangAI\zhuiguang-ai\Pem\zg.pem" ubuntu@119.45.242.239`
|
||||
- **SCP示例**: `scp -i "C:\SGP_KF\ZhuiGuangAI\zhuiguang-ai\Pem\zg.pem" localfile ubuntu@119.45.242.239:/home/ubuntu/zhuiguang-ai/`
|
||||
|
||||
## 服务器与基础设施
|
||||
- **域名**: www.zhuig.com (HTTPS,SSL证书自动续期)
|
||||
- **云服务器**: 119.45.242.239 (登录名: **ubuntu**, 密钥: `C:\SGP_KF\ZhuiGuangAI\zhuiguang-ai\Pem\zg.pem`)
|
||||
- **部署目录**: /home/ubuntu/zhuiguang-ai
|
||||
- **访问地址**: https://www.zhuig.com (HTTP自动跳转HTTPS)
|
||||
- **数据库**: 阿里云RDS MySQL — rm-0jlbgr2rv6dj3t6jngo.mysql.rds.aliyuncs.com:3306
|
||||
- **Redis**: 云服务器上已有(Docker容器redis-cache:6379),与其他项目共用,有密码认证
|
||||
- **本地Git同步目录**: K:\git-repos
|
||||
- **开发机**: E:\ZG_Dev\ZhuiGuangAI\zhuiguang-ai
|
||||
- **部署目录**: /home/ubuntu/zhuiguang-ai
|
||||
- **访问地址**: https://www.zhuig.com (HTTP自动跳转HTTPS)
|
||||
- **注意事项**: 服务器有其他应用运行,部署时不可占用非8301-8310端口,不可影响其他服务
|
||||
- **SSH连接示例**: `ssh -i "C:\SGP_KF\ZhuiGuangAI\zhuiguang-ai\Pem\zg.pem" ubuntu@119.45.242.239`
|
||||
- **PM2管理**: `pm2 list` / `pm2 restart zhuiguang-ai` / `pm2 save`
|
||||
- **其他应用**: agent-system, nacos, zhuiguang-quant (部署时请勿影响)
|
||||
- **Docker管理**: `docker ps` / `docker logs zhuiguang-ai-app` / `docker restart zhuiguang-ai-app`
|
||||
|
||||
### ⚠️ 多项目共存服务器(更新/部署铁律)
|
||||
|
||||
服务器 119.45.242.239 上**同时运行多个项目**和**多个共享服务**,任何代码更新、部署、运维操作必须严格隔离,绝不能影响其他项目。
|
||||
|
||||
#### 当前服务器实际部署清单(2026-06-10 巡检)
|
||||
|
||||
| 项目 | 路径 | 占用端口 | 进程 |
|
||||
|------|------|----------|------|
|
||||
| **zhuiguang-ai(我们)** | /home/ubuntu/zhuiguang-ai | 8301 (next-server) | Docker: zhuiguang-ai-app + zhuiguang-ai-cron |
|
||||
| zhuiguang-ai-backup | /home/ubuntu/zhuiguang-ai-backup | — | 静态备份 |
|
||||
| zhuiguang-quant | /home/ubuntu/zhuiguang-quant | 8701 / 8802 (java) | 独立 java 进程 |
|
||||
| zhenfang | /home/ubuntu/zhenfang | — | — |
|
||||
| snowy-fgt | /home/ubuntu/snowy-fgt | 7001 (gunicorn) | 独立 gunicorn |
|
||||
| agent-system | /home/ubuntu/agent-system | — | — |
|
||||
| nacos | /home/ubuntu/nacos | 8601 / 8602 (java) | 独立 java 进程 |
|
||||
|
||||
#### 共享服务(绝对不能动)
|
||||
|
||||
| 服务 | 端口 | 容器名 | 共享给 |
|
||||
|------|------|--------|--------|
|
||||
| Redis | 6379 | redis-cache (Docker) | 所有项目 |
|
||||
| Nacos | 8848 / 9848 | nacos (Docker) | 注册中心 |
|
||||
| MinIO | 9000 / 9001 | minio (Docker) | 文件存储 |
|
||||
| nginx | 80 / 443 / 8720 / 8801 | 系统 nginx | 反向代理多域名 |
|
||||
|
||||
#### 铁律(更新/部署前必读)
|
||||
|
||||
1. **端口锁定 8301-8310**:本项目所有 HTTP/WS 服务只能使用 8301-8310 区间。禁止占用 80/443/8601-8802/8848/9000-9001/6379/7001 等任何其他端口。Docker 容器启动时若发现目标端口被占,**先排查是哪个项目在用**,绝不能 kill 别人的进程。
|
||||
2. **进程隔离**:禁止 `pkill -f node` / `pkill -f java` / `pkill -f nginx` / `pkill -f docker` 等全局杀进程。重启本项目**只能重启 Docker 容器**(`docker restart zhuiguang-ai-app`)或 8301-8310 端口上的进程。
|
||||
3. **禁止修改其他项目目录**:`/home/ubuntu/{zhuiguang-quant,zhenfang,snowy-fgt,agent-system,nacos}` 及其子目录**只读**,不要 `cd` 进去 `git pull` / `npm install` / 改文件。
|
||||
4. **禁止修改共享服务配置**:
|
||||
- 不动 Redis(6379)—— 别人可能正在用我们的 key 以外的数据
|
||||
- 不动 Nacos(8848)—— 注册中心是全局的
|
||||
- 不动 MinIO(9000)—— 文件存储多项目共用
|
||||
- 不动 nginx 主配置 / sites-enabled 下的其他站点 —— 我们的反代规则放在独立文件,文件名带 `zhuiguang` 前缀
|
||||
- 不 `docker restart` / `docker stop` / `docker rm` 任何邻居容器(本项目容器名以 `zhuiguang-ai` 开头)
|
||||
5. **数据库隔离**:阿里云 RDS 上的数据库是本项目专用(`zhuiguang_ai`),但**严禁 `DROP DATABASE` / `TRUNCATE` 全表 / 删 migration 文件**。改 schema 必须 `prisma migrate dev` 生成新 migration 走前向变更。绝不执行任何会清空数据的脚本。
|
||||
6. **Crontab 隔离**:本项目定时任务已全部迁移到容器内 supercronic 调度(`zhuiguang-ai-cron` 容器),主机 crontab 已清空。**禁止在主机 crontab 中添加本项目定时任务**,所有定时任务通过更新 `crontab.txt` 并重建 cron 容器完成。也禁止 `crontab -r` 清空(可能影响邻居项目)。
|
||||
7. **磁盘隔离**:`/home/ubuntu/zhuiguang-ai/logs/` 是本项目日志目录;`/home/ubuntu/logs/` 是其他项目的,**不要混淆**。本项目备份只放 `/home/ubuntu/zhuiguang-ai-backup/`。
|
||||
8. **环境变量隔离**:只读 `/home/ubuntu/zhuiguang-ai/.env`。**不要改 `~/.bashrc` / `/etc/environment` / `/etc/profile`** 等全局环境文件,全局变量可能影响其他项目。
|
||||
9. **部署前自检清单**(强制):
|
||||
- [ ] `docker ps --filter name=zhuiguang-ai` —— 确认当前运行的容器
|
||||
- [ ] `ss -tlnp | grep :8301` —— 确认 8301 是容器进程
|
||||
- [ ] `git status` —— 确认本地代码只动本项目文件
|
||||
- [ ] `npx tsc --noEmit` —— 零错误
|
||||
- [ ] **不动** `/home/ubuntu/` 下其他项目目录
|
||||
- **不动** Redis/Nacos/MinIO 容器
|
||||
- **不动** nginx/sites-enabled 下非 zhuiguang 开头的文件
|
||||
- **不动** 全局 crontab(本项目已用 supercronic 容器)
|
||||
10. **部署后自检清单**(强制):
|
||||
- [ ] `docker ps` —— zhuiguang-ai-app 和 zhuiguang-ai-cron 状态 healthy
|
||||
- [ ] `curl -I https://www.zhuig.com` —— 200,且响应时间 < 3s
|
||||
- [ ] `ss -tlnp | grep :8301` —— 进程为 Docker 容器内 next-server
|
||||
- [ ] `docker logs --tail 20 zhuiguang-ai-app` —— 无 ERROR
|
||||
- [ ] 其他项目(zhuiguang-quant/zhenfang/snowy-fgt/nacos 等)的进程仍在、状态正常
|
||||
|
||||
#### 反例(禁止操作)
|
||||
|
||||
```bash
|
||||
# ❌ 禁止 —— 全局杀进程
|
||||
pkill -f node
|
||||
pkill -f java
|
||||
kill -9 $(pgrep node)
|
||||
systemctl restart nginx
|
||||
|
||||
# ❌ 禁止 —— 改其他项目
|
||||
cd /home/ubuntu/zhuiguang-quant && git pull
|
||||
rm -rf /home/ubuntu/zhenfang
|
||||
docker restart redis-cache
|
||||
docker stop nacos
|
||||
vi /etc/nginx/nginx.conf
|
||||
crontab -r
|
||||
|
||||
# ❌ 禁止 —— 改共享服务
|
||||
redis-cli FLUSHALL
|
||||
mysql -e "DROP DATABASE ..."
|
||||
```
|
||||
|
||||
#### 正例(本项目更新/部署的标准做法)
|
||||
|
||||
```bash
|
||||
# ✅ 只动本项目
|
||||
cd /home/ubuntu/zhuiguang-ai
|
||||
git pull
|
||||
docker build -t zhuiguang-ai:latest .
|
||||
docker stop zhuiguang-ai-app zhuiguang-ai-cron
|
||||
docker rm zhuiguang-ai-app zhuiguang-ai-cron
|
||||
# 然后重新 docker run(参考 docker-compose.yml 或 CONTAINERIZATION.md)
|
||||
|
||||
# ✅ 查看状态时不漏看其他项目
|
||||
docker ps --filter name=zhuiguang-ai # 看本项目容器状态
|
||||
ss -tlnp | grep -E ':(8301|8601|8701|8802)' # 看我们的端口 + 邻居项目的端口
|
||||
|
||||
# ✅ 日志查看
|
||||
docker logs --tail 50 zhuiguang-ai-app # APP 容器日志
|
||||
docker logs --tail 50 zhuiguang-ai-cron # Cron 容器日志
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 技术栈
|
||||
- Next.js 14 (App Router) + TypeScript
|
||||
@@ -39,8 +142,9 @@
|
||||
|
||||
## 构建与检查
|
||||
- 修改代码后必须运行 `npx tsc --noEmit` 确认零错误
|
||||
- 重启服务使用 `pwsh -ExecutionPolicy Bypass -File restart.ps1`
|
||||
- 开发服务器: `npm run dev` (端口8301)
|
||||
- 本地开发服务器: `npm run dev` (端口8301)
|
||||
- 生产构建: `docker build -t zhuiguang-ai:latest .`
|
||||
- 部署: `docker stop/rm` 旧容器 → `docker run` 新容器
|
||||
|
||||
## 数据库
|
||||
- 云数据库: 阿里云RDS MySQL
|
||||
@@ -63,8 +167,8 @@
|
||||
- 批量操作: body中传 `ids` 数组
|
||||
|
||||
## 页面路由
|
||||
- 前台: `/`, `/tools`, `/tools/[slug]`, `/categories/[slug]`, `/skills`, `/skills/[slug]`, `/login`, `/user`, `/user/favorites`, `/user/[id]`(会员空间), `/user/collections`, `/daily`, `/reviews`, `/community`, `/community/[category]`, `/community/topic/[id]`
|
||||
- 后台: `/admin/login`, `/admin/pending`, `/admin/pending-skills`, `/admin/tools`, `/admin/skills`, `/admin/categories`, `/admin/skill-categories`, `/admin/discover-tools`, `/admin/check-tools`, `/admin/discover-skills`, `/admin/update-skills`, `/admin/discover-news`, `/admin/system-config`, `/admin/tasks`, `/admin/tasks/logs`, `/admin/tasks/[taskKey]`, `/admin/reviews`
|
||||
- 前台: `/`, `/tools`, `/tools/[slug]`, `/categories/[slug]`, `/skills`, `/skills/[slug]`, `/login`, `/user`, `/user/favorites`, `/user/[id]`(会员空间), `/user/collections`, `/daily`, `/reviews`, `/community`, `/community/[category]`, `/community/topic/[id]`, `/community/bots`, `/community/bots/leaderboard`
|
||||
- 后台: `/admin/login`, `/admin/pending`, `/admin/pending-skills`, `/admin/tools`, `/admin/skills`, `/admin/categories`, `/admin/skill-categories`, `/admin/discover-tools`, `/admin/check-tools`, `/admin/discover-skills`, `/admin/update-skills`, `/admin/discover-news`, `/admin/system-config`, `/admin/tasks`, `/admin/tasks/logs`, `/admin/tasks/[taskKey]`, `/admin/reviews`, `/admin/roles`, `/admin/bot-experiments`, `/admin/bot-adversarial-learning`, `/admin/bot-analytics`
|
||||
|
||||
## 五大操作指令
|
||||
|
||||
@@ -129,6 +233,14 @@
|
||||
## 环境变量
|
||||
- GITHUB_TOKEN: GitHub Personal Access Token(可选,提升API限流从60→5000次/小时)
|
||||
- DEEPSEEK_API_KEY: DeepSeek API Key(用于技能评测生成脚本、AI日报整理)
|
||||
- OPENAI_API_KEY: OpenAI API Key(Bot活动引擎使用,生成论坛内容)
|
||||
|
||||
## 数字人Bot系统
|
||||
- **角色定义文件**: `data/bot-characters.json` — 112个Bot角色定义,所有Bot脚本和前端工具依赖此文件
|
||||
- **Bot头像目录**: `public/bot-avatars/` — 程序化SVG头像(112个,~2.5KB/个)
|
||||
- **Bot用户标记**: User表中 `isBot: true` 标识Bot用户,与真人的互动数据分别统计
|
||||
- **Bot活动时段**: 9:00-23:00每小时运行,15轮/天,论坛内容不干扰深夜用户体验
|
||||
- **Bot数据库**: 12张Bot专用表(BotConfig/BotMemory/BotDailyStat/BotSkill/BotWeeklyReview/BotPersona/BotPersonaVariant/BotPersonaExperiment/BotPersonaAssignment/BotPersonaMetric/BotAdversarialLearning/BotCrossForumAffinity)
|
||||
|
||||
## 定时任务调度系统
|
||||
- **后台管理**: `/admin/tasks`(任务中心)、`/admin/tasks/logs`(执行日志)、`/admin/tasks/[taskKey]`(单任务详情+统计)
|
||||
@@ -140,23 +252,26 @@
|
||||
- `GET /api/admin/tasks/logs` — 任务执行日志(分页+按taskKey筛选)
|
||||
- `POST /api/admin/tasks/run` — 手动触发任务执行
|
||||
|
||||
### 定时任务(Crontab)
|
||||
所有7个定时任务全部经过TaskLog记录,由 `scripts/cron-wrapper.sh` 统一入口执行(自动加载 `.env` 环境变量、创建日志目录):
|
||||
### 定时任务(Supercronic 容器调度)
|
||||
所有定时任务由 `zhuiguang-ai-cron` 容器内的 supercronic 调度,配置文件 `crontab.txt`。不再使用主机 crontab + cron-wrapper.sh。
|
||||
|
||||
| 时间 | 任务 | 脚本 | TaskKey | 说明 |
|
||||
|------|------|------|---------|------|
|
||||
| 01:00 | Task5 更新星值 | `scripts/task5-update-stars.mjs` | task5-update-stars | 更新所有GitHub技能Stars数+日/周/月变化 |
|
||||
| 03:00 | Task3 工具巡检 | `scripts/task3-check-tools.mjs` | task3-check-tools | 检查网站/Lo4go可访问性+自动发布合格待审核工具 |
|
||||
| 03:00 | Task3 工具巡检 | `scripts/task3-check-tools.mjs` | task3-check-tools | 检查网站/Logo可访问性+自动发布合格待审核工具 |
|
||||
| 04:00 | Bot技能结晶 | `scripts/bot-skill-crystallize.mjs` | bot-skill-crystallize | 扫过去14天高互动Bot话题→DeepSeek解构共性→入库BotSkill(usageCount驱动调用);末尾回收7天前成熟技能更新successRate(<30%且使用≥3次自动isActive=false) |
|
||||
| 05:00 | Bot亲和度与画像 | `scripts/bot-affinity-update.mjs` | bot-affinity-update | 刷BotCrossForumAffinity(affinity=min(1, samples/total/4))和BotPersona(avgReplyLength/questionRatio/stanceKeywords/topHumanUsers/topTopicTypes/lastTopicTitles,bot-activity发帖时注入prompt) |
|
||||
| 04:00 | Task6 评测热门 | `scripts/task6-review-hot.mjs` | task6-review-hot | 评测2个最热未评测GitHub技能(五维评测) |
|
||||
| 05:00 | Task4 发现技能 | `scripts/daily-discover.mjs` | task4-discover-skills | GitHub搜索≥1000 stars项目→DeepSeek预评测→入库PendingSkill |
|
||||
| 06:00 | Task1 发现工具 | `scripts/task1-discover-tools.mjs` | task1-discover-tools | 36kr/IT之家/开源中国RSS→DeepSeek提取工具→入库PendingTool |
|
||||
| 07:30 | AI日报 | `scripts/daily-news.mjs` | daily-news | 多源搜索真实新闻+DeepSeek整理格式→发布日报 |
|
||||
| 21:30 | Bot反馈闭环 | `scripts/bot-feedback-loop.mjs` | bot-feedback-loop | 扫描Bot自己帖子下的新回复→存反馈记忆→按概率触发二次回复(仅expert bots,配额high=6/medium=3/low=1) |
|
||||
| 周日02:00 | Bot周度复盘 | `scripts/bot-weekly-review.mjs` | bot-weekly-review | 算engagementScore→生成REFLECTION记忆→决定下周配额tier(写入BotWeeklyReview.nextWeekQuota,bot-activity下次跑时动态覆盖) |
|
||||
| 08:00 | Task7 新闻推社区 | `scripts/task7-news-to-community.mjs` | task7-news-to-community | 将当日日报新闻分发到社区4个板块(AI工具推荐/AI资讯/技术探讨/观点讨论) |
|
||||
|
||||
- Crontab 位于服务器: `crontab -l`(ubuntu用户),安装脚本: `bash scripts/install-cron.sh`
|
||||
- 统一入口: `scripts/cron-wrapper.sh <TASK_NAME> <SCRIPT_PATH>` — 自动加载 `.env`、创建日志目录、记录执行结果
|
||||
- 日志目录: `/home/ubuntu/zhuiguang-ai/logs/`(task1.log ~ task7.log, daily-news.log)
|
||||
- **关键**: crontab 环境不加载 `.env`,所有定时任务必须通过 wrapper 执行;`.env` 值不能加引号
|
||||
- 调度配置: `crontab.txt`(supercronic 格式),修改后需重建 cron 容器生效
|
||||
- 日志目录: 容器内 `/app/logs/`(挂载到 Docker volume `zhuiguang_ai_bot_logs`)
|
||||
- 定时任务脚本从 `scripts/` 目录直接执行,环境变量由容器 entrypoint 注入
|
||||
|
||||
## AI日报新闻源
|
||||
- **36kr** RSS (https://36kr.com/feed) — 国内科技资讯
|
||||
@@ -175,10 +290,11 @@
|
||||
- Chart.js组件需用dynamic import + ssr: false,不支持服务端渲染
|
||||
- Prisma 7.8需通过PrismaMariaDb适配器初始化,不能直接new PrismaClient()
|
||||
- 服务器环境SSL证书问题: 运行脚本需设置$env:NODE_TLS_REJECT_UNAUTHORIZED="0"
|
||||
- **crontab env隔离**: crontab 不加载 `.env`,必须用 wrapper 脚本 `source .env` + `set -a`/`set +a`
|
||||
- **.env 引号陷阱**: `.env` 值禁止加引号,`xargs` 导出会保留引号导致 SQL 语法错误
|
||||
- **PrismaMariaDb 协议**: adapter 只接受 `mariadb://`,`.env` 中的 `mysql://` 需在脚本中 `.replace('mysql://', 'mariadb://')`
|
||||
- **.mjs 不支持 TS**: `.mjs` 文件不能有 TypeScript 类型注解(`const x: Type =`),需用纯 JS 语法
|
||||
- **crontab env 隔离**: 本项目已迁移到容器内 supercronic 调度,不再依赖主机 crontab
|
||||
- **Supercronic 环境变量**: entrypoint-cron.sh 中 `set -a; . /app/.env; set +a` 注入环境变量到 supercronic 子进程
|
||||
- **Prisma 7 datasource.url**: 必须放在 `prisma.config.ts` 中,不能在 `schema.prisma` 的 datasource 块里写 `url`
|
||||
- **Docker build 期 Next.js 模块求值**: server page 和 API route 在 build 时会被求值,如果依赖 env 变量(如 DATABASE_URL、API_KEY),需加 `export const dynamic = "force-dynamic"` 或懒加载
|
||||
- **Docker 多阶段构建**: deps → builder → runner,利用 layer cache 加速重复构建
|
||||
|
||||
### 6. 安全原则
|
||||
- 敏感信息(密钥、密码、Token)必须使用环境变量,禁止硬编码
|
||||
@@ -191,6 +307,20 @@
|
||||
- **数据库外键回退值禁止硬编码**:凡涉及 FK 字段(如 categoryId)必须先查库取有效 ID,再做回退(参考 `category.findFirst()` 模式),禁止用 `|| 1` 等魔法数字
|
||||
- **批量写操作必须限制数量上限**:工具/技能导入 max(100),新闻导入 max(50),批量发布 max(500)
|
||||
|
||||
### 8. Knowledge Graph Memory 同步规则
|
||||
- **每次代码变更后,必须同步更新 Knowledge Graph Memory**:当修改了项目代码(新增/删除/重构功能、修改数据模型、新增API、调整定时任务、修改Bot角色等),必须将变更内容同步写入 Knowledge Graph Memory
|
||||
- **同步范围**:
|
||||
- 新增/修改/删除数据模型 → 更新 `数据模型-核心` 或 `数据模型-Bot系统` 实体
|
||||
- 新增/修改/删除 API 端点 → 更新对应 `API-*` 实体
|
||||
- 新增/修改/删除定时任务 → 更新对应 `ScheduledTask` 实体
|
||||
- 修改 Bot 角色配置(bot-characters.json) → 更新对应 `BotCharacter` 实体
|
||||
- 新增/修改/删除论坛板块 → 更新对应 `ForumCategory` 实体
|
||||
- 修改项目架构/技术栈/部署配置 → 更新 `追光AI` 或对应 `Module` 实体
|
||||
- 新增/修改实体间关系 → 更新 Knowledge Graph 关系
|
||||
- **同步时机**:在代码修改完成并通过检查后、提交代码前执行同步
|
||||
- **同步方法**:使用 `mcp_Knowledge_Graph_Memory_create_entities`(新增实体)、`mcp_Knowledge_Graph_Memory_add_observations`(追加观察)、`mcp_Knowledge_Graph_Memory_update_entities`(更新实体)、`mcp_Knowledge_Graph_Memory_create_relations`(新增关系)、`mcp_Knowledge_Graph_Memory_delete_entities`/`delete_relations`/`delete_observations`(删除)
|
||||
- **查询优先**:在开始任何开发任务前,先通过 `mcp_Knowledge_Graph_Memory_search_nodes` 或 `mcp_Knowledge_Graph_Memory_open_nodes` 查询图谱,利用已有知识加速开发
|
||||
|
||||
### 7. 可靠性原则
|
||||
- 所有外部 API 调用(GitHub、DeepSeek 等)必须设置超时和重试
|
||||
- OpenAI/DeepSeek 客户端配置:`timeout: 120000`, `maxRetries: 2`
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 追光AI - 模块文档索引
|
||||
|
||||
## 项目概述
|
||||
追光AI是一个AI工具与开源技能目录网站,支持提示词驱动的工具/技能发现、审核管理和前台展示,集成五维评测系统、任务调度、权限体系和社区互动功能。
|
||||
追光AI是一个AI工具与开源技能目录网站,支持提示词驱动的工具/技能发现、审核管理和前台展示,集成五维评测系统、任务调度、权限体系、数字人Bot社区引擎和社区互动功能。
|
||||
|
||||
## 技术栈
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
| 图表 | Chart.js + react-chartjs-2 | 4.x |
|
||||
| GitHub | Octokit | 5.x |
|
||||
| 验证 | Zod | 4.x |
|
||||
| 部署 | Node.js + PM2 | 18+ |
|
||||
| 部署 | Docker 容器 + supercronic | node:20-alpine |
|
||||
| 端口 | 8301-8310 | 默认8301 |
|
||||
|
||||
## 项目结构
|
||||
@@ -59,7 +59,7 @@ zhuiguang-ai/
|
||||
| 06 | 认证 | [06-auth.md](./modules/06-auth.md) | NextAuth配置、路由保护、权限体系、登录流程 |
|
||||
| 07 | 工具库与脚本 | [07-lib-and-scripts.md](./modules/07-lib-and-scripts.md) | 工具函数、定时任务脚本、运维脚本 |
|
||||
| 08 | 社区功能 | [08-community.md](./modules/08-community.md) | 评论系统、收藏、浏览历史、收藏夹、通知、论坛 |
|
||||
| 09 | 运维与部署 | [09-devops.md](./modules/09-devops.md) | 服务器配置、Nginx、Crontab、部署流程、踩坑记录 |
|
||||
| 09 | 运维与部署 | [09-devops.md](./modules/09-devops.md) | Docker容器、supercronic调度、Nginx、部署流程、备份 |
|
||||
|
||||
## 环境变量
|
||||
```
|
||||
|
||||
@@ -436,6 +436,207 @@
|
||||
|
||||
**关系**: topic, user
|
||||
|
||||
### BotConfig (Bot配置)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| userId | Int @unique @map("user_id") | 关联User(isBot=true) |
|
||||
| displayName | String @map("display_name") @db.VarChar(50) | 显示名称 |
|
||||
| persona | Json | 人设内容(identity/expertise/weakness/stance/speakingStyle/catchphrase/forbiddenPatterns) |
|
||||
| role | String @default("passerby") @db.VarChar(20) | 角色(expert/passerby) |
|
||||
| activeHours | Json? @map("active_hours") | 活跃时间段(JSON) |
|
||||
| primaryForums | Json? @map("primary_forums") | 主要活跃板块(JSON) |
|
||||
| isActive | Boolean @default(true) @map("is_active") | 是否启用 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: user (一对一), memories, personaVariants, adversarialLearnings, skills, dailyStats, weeklyReviews, crossForumAffinities
|
||||
|
||||
### BotMemory (Bot记忆)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| botId | Int @map("bot_id") | 关联BotConfig |
|
||||
| level | String @db.VarChar(20) | 记忆层级(SESSION/WORKING/LONGTERM) |
|
||||
| content | String @db.Text | 记忆内容 |
|
||||
| importance | Float @default(0) | 重要性评分 |
|
||||
| contextTags | Json? @map("context_tags") | 上下文标签(JSON) |
|
||||
| ttl | Int? | 存活时间(秒) |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
|
||||
**关系**: bot
|
||||
|
||||
### BotDailyStat (Bot每日统计)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| botId | Int @map("bot_id") | 关联BotConfig |
|
||||
| date | DateTime @db.Date | 统计日期 |
|
||||
| topicsCreated | Int @default(0) @map("topics_created") | 创建话题数 |
|
||||
| postsCreated | Int @default(0) @map("posts_created") | 创建回复数 |
|
||||
| repliesReceived | Int @default(0) @map("replies_received") | 收到的回复数 |
|
||||
| likesReceived | Int @default(0) @map("likes_received") | 收到的点赞数 |
|
||||
| humanInteractions | Int @default(0) @map("human_interactions") | 真人互动数 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
|
||||
**关系**: bot
|
||||
**唯一约束**: [botId, date]
|
||||
|
||||
### BotSkill (Bot技能结晶)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| botId | Int @map("bot_id") | 关联BotConfig |
|
||||
| skillName | String @map("skill_name") @db.VarChar(100) | 技能名称 |
|
||||
| hookTemplate | String @map("hook_template") @db.Text | 钩子模板 |
|
||||
| bodyTemplate | String @map("body_template") @db.Text | 正文模板 |
|
||||
| applicabilityNote | String? @map("applicability_note") @db.Text | 适用性说明 |
|
||||
| sourceTopicId | Int? @map("source_topic_id") | 来源话题ID |
|
||||
| successRate | Float @default(0) @map("success_rate") | 成功率 |
|
||||
| usageCount | Int @default(0) @map("usage_count") | 使用次数 |
|
||||
| isActive | Boolean @default(true) @map("is_active") | 是否启用 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: bot
|
||||
|
||||
### BotWeeklyReview (Bot周度复盘)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| botId | Int @map("bot_id") | 关联BotConfig |
|
||||
| weekKey | String @map("week_key") @db.VarChar(20) | 周标识(2026-W23) |
|
||||
| topicsCreated | Int @default(0) @map("topics_created") | 本周话题数 |
|
||||
| postsCreated | Int @default(0) @map("posts_created") | 本周回复数 |
|
||||
| likesReceived | Int @default(0) @map("likes_received") | 本周点赞数 |
|
||||
| humanRatio | Float @default(0) @map("human_ratio") | 真人互动比例 |
|
||||
| engagementScore | Float @default(0) @map("engagement_score") | 参与度分数 |
|
||||
| nextWeekQuota | Json? @map("next_week_quota") | 下周配额(JSON) |
|
||||
| reflection | String? @db.Text | LLM反思 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
|
||||
**关系**: bot
|
||||
**唯一约束**: [botId, weekKey]
|
||||
|
||||
### BotPersona (Bot风格画像)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| botId | Int @id @map("bot_id") | 关联BotConfig(主键) |
|
||||
| avgReplyLength | Float @default(0) @map("avg_reply_length") | 平均回复长度 |
|
||||
| questionRatio | Float @default(0) @map("question_ratio") | 问句比例 |
|
||||
| exclamationCount | Int @default(0) @map("exclamation_count") | 感叹号数量 |
|
||||
| stanceKeywords | Json? @map("stance_keywords") | 立场关键词(JSON) |
|
||||
| topHumanUsers | Json? @map("top_human_users") | 主要互动真人用户(JSON) |
|
||||
| topTopicTypes | Json? @map("top_topic_types") | 热门话题类型(JSON) |
|
||||
| lastTopicTitles | Json? @map("last_topic_titles") | 最近话题标题(JSON) |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: bot (一对一)
|
||||
|
||||
### BotPersonaVariant (A/B变体)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| botId | Int @map("bot_id") | 关联BotConfig |
|
||||
| variantKey | String @map("variant_key") @db.VarChar(30) | 变体标识(control/variant_a/variant_b) |
|
||||
| label | String @db.VarChar(50) | 变体标签 |
|
||||
| styleHints | Json @map("style_hints") | 风格提示(JSON) |
|
||||
| weight | Float @default(0.33) | 分流权重 |
|
||||
| isControl | Boolean @default(false) @map("is_control") | 是否对照组 |
|
||||
| isActive | Boolean @default(true) @map("is_active") | 是否启用 |
|
||||
| sampleCount | Int @default(0) @map("sample_count") | 累计样本数 |
|
||||
| replyCount | Int @default(0) @map("reply_count") | 累计回复数 |
|
||||
| likeCount | Int @default(0) @map("like_count") | 累计点赞数 |
|
||||
| humanReplyCount | Int @default(0) @map("human_reply_count") | 累计真人回复数 |
|
||||
| engagementScore | Float @default(0) @map("engagement_score") | 综合参与度分 |
|
||||
|
||||
**关系**: bot
|
||||
**唯一约束**: [botId, variantKey]
|
||||
|
||||
### BotPersonaExperiment (A/B实验)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| botId | Int @map("bot_id") | 关联BotConfig |
|
||||
| name | String @db.VarChar(100) | 实验名称 |
|
||||
| status | String @default("active") @db.VarChar(20) | 状态(active/completed) |
|
||||
| winnerVariantKey | String? @map("winner_variant_key") @db.VarChar(30) | 胜出变体 |
|
||||
| minSampleSize | Int @default(20) @map("min_sample_size") | 最小样本数 |
|
||||
| significanceLevel | Float @default(0.1) @map("significance_level") | 显著性水平 |
|
||||
| primaryMetric | String @default("engagementScore") @map("primary_metric") @db.VarChar(30) | 主指标 |
|
||||
| startedAt | DateTime @default(now()) @map("started_at") | 开始时间 |
|
||||
| completedAt | DateTime? @map("completed_at") | 完成时间 |
|
||||
|
||||
**关系**: bot
|
||||
|
||||
### BotPersonaAssignment (A/B分配记录)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| variantId | Int @map("variant_id") | 关联变体 |
|
||||
| refType | String @map("ref_type") @db.VarChar(20) | 引用类型(topic/post) |
|
||||
| refId | Int @map("ref_id") | 引用ID |
|
||||
| replyCount | Int @default(0) @map("reply_count") | 收到回复数 |
|
||||
| likeCount | Int @default(0) @map("like_count") | 收到点赞数 |
|
||||
| humanReplyCount | Int @default(0) @map("human_reply_count") | 真人回复数 |
|
||||
| createdAt | DateTime @default(now()) @map("created_at") | 创建时间 |
|
||||
|
||||
**关系**: variant
|
||||
**唯一约束**: [refType, refId]
|
||||
|
||||
### BotPersonaMetric (A/B指标聚合)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| variantId | Int @map("variant_id") | 关联变体 |
|
||||
| date | DateTime @db.Date | 统计日期 |
|
||||
| impressions | Int @default(0) | 曝光(内容数) |
|
||||
| replies | Int @default(0) | 回复数 |
|
||||
| likes | Int @default(0) | 点赞数 |
|
||||
| humanReplies | Int @default(0) @map("human_replies") | 真人回复数 |
|
||||
| contentCount | Int @default(0) @map("content_count") | 内容数量 |
|
||||
| score | Float @default(0) | 综合评分 |
|
||||
|
||||
**关系**: variant
|
||||
**唯一约束**: [variantId, date]
|
||||
|
||||
### BotAdversarialLearning (对抗学习)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| botId | Int @map("bot_id") | 关联BotConfig |
|
||||
| weekKey | String @map("week_key") @db.VarChar(20) | 周标识 |
|
||||
| sourceRefType | String @map("source_ref_type") @db.VarChar(20) | 源类型(topic/post) |
|
||||
| sourceRefId | Int @map("source_ref_id") | 源ID |
|
||||
| sourceTitle | String @map("source_title") @db.VarChar(200) | 源标题 |
|
||||
| sourceContent | String @map("source_content") @db.Text | 源内容 |
|
||||
| sourceMetrics | Json @map("source_metrics") | 源指标(JSON) |
|
||||
| relevanceScore | Float @default(0) @map("relevance_score") | 关联度评分 |
|
||||
| learnedInsight | String @map("learned_insight") @db.Text | LLM提取的洞察 |
|
||||
| learnCategories | Json? @map("learn_categories") | 学习分类(JSON) |
|
||||
| status | String @default("active") @db.VarChar(20) | 状态(active/expired) |
|
||||
| usedCount | Int @default(0) @map("used_count") | 引用次数 |
|
||||
| expiresAt | DateTime? @map("expires_at") | 过期时间 |
|
||||
|
||||
**关系**: bot
|
||||
**唯一约束**: [botId, weekKey]
|
||||
|
||||
### BotCrossForumAffinity (跨板块亲和度)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Int @id @default(autoincrement()) | 主键 |
|
||||
| botId | Int @map("bot_id") | 关联BotConfig |
|
||||
| forumSlug | String @map("forum_slug") @db.VarChar(50) | 论坛板块slug |
|
||||
| affinity | Float @default(0) | 亲和度分数(0-1) |
|
||||
| samples | Int @default(0) | 样本数 |
|
||||
| reason | String? @db.VarChar(255) | 原因说明 |
|
||||
| updatedAt | DateTime @updatedAt @map("updated_at") | 更新时间 |
|
||||
|
||||
**关系**: bot
|
||||
**唯一约束**: [botId, forumSlug]
|
||||
|
||||
---
|
||||
|
||||
## 枚举
|
||||
|
||||
### PricingModel (定价模型)
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
## 前台API(无需认证)
|
||||
|
||||
### GET /api/health
|
||||
健康检查端点(Docker HEALTHCHECK 使用)。
|
||||
- 返回: `{ status: "ok", timestamp, checks: { database: { status: "ok", latencyMs } } }`
|
||||
- 用于 Docker 容器健康检查 + 负载均衡探测
|
||||
|
||||
### GET /api/homepage
|
||||
获取首页数据(含嵌套分类结构,一级分类+二级子分类)。
|
||||
- 返回: `{ categories: CategoryWithChildren[], skillCategories: SkillCategoryWithChildren[] }`
|
||||
|
||||
@@ -81,6 +81,16 @@
|
||||
- 功能: 用户资料展示(头像/昵称/简介/等级/积分)+ 统计面板 + 发布主题列表 + 评论历史 + 分享按钮
|
||||
- 数据源: `/api/user/[id]`
|
||||
|
||||
### /community/bots (Bot列表)
|
||||
- 文件: `src/app/community/bots/page.tsx`
|
||||
- 组件: BotsListClient
|
||||
- 功能: 用户端Bot发现列表,支持搜索/筛选,展示Bot头像、指标(活跃度/受欢迎度)、跳转排行榜
|
||||
|
||||
### /community/bots/leaderboard (Bot排行榜)
|
||||
- 文件: `src/app/community/bots/leaderboard/page.tsx`
|
||||
- 组件: LeaderboardClient
|
||||
- 功能: Bot排名,基于热度/互动/点赞数,奖杯/皇冠/奖章视觉
|
||||
|
||||
---
|
||||
|
||||
## 后台页面
|
||||
|
||||
@@ -198,20 +198,16 @@
|
||||
|
||||
## 运维脚本
|
||||
|
||||
### restart.ps1 - 服务重启
|
||||
- PowerShell脚本
|
||||
- 扫描8301-8310端口
|
||||
- 杀死占用进程
|
||||
- 执行 `npm run dev` 启动服务(端口8301)
|
||||
- 运行: `pwsh -ExecutionPolicy Bypass -File restart.ps1`
|
||||
### 容器 Entrypoint 脚本
|
||||
- `scripts/entrypoint-app.sh` — APP 容器启动入口,执行 prisma migrate deploy(幂等)后启动 next start
|
||||
- `scripts/entrypoint-cron.sh` — CRON 容器启动入口,校验 .env 和 crontab.txt 后启动 supercronic
|
||||
|
||||
### temp_clear.mjs - 临时清理
|
||||
- 清空pending_tools表
|
||||
### 卷备份脚本
|
||||
- `scripts/backup-volumes.sh` — 备份 4 个命名卷到 `/home/ubuntu/zhuiguang-ai-backup/dockers/`,保留 7 天
|
||||
- `scripts/install-cron-backup.sh` — 安装主机备份 cron(每天 03:00 执行备份)
|
||||
|
||||
### cron脚本 (shell)
|
||||
- `cron-wrapper.sh` — 定时任务统一执行入口,自动 `source .env` + `set -a`/`set +a` 加载环境变量,创建日志目录,记录执行结果
|
||||
- `install-cron.sh` — 一键安装/更新 crontab(7个任务+日报+新闻推社区,全部通过wrapper执行)
|
||||
- `fix-db-url.sh` — 旧版数据库URL修复脚本(已被 fix-db-url.cjs 取代)
|
||||
### 定时任务调度
|
||||
- `crontab.txt` — supercronic 调度配置(13 条定时任务),不再使用主机 crontab + cron-wrapper.sh
|
||||
|
||||
### lib/retry.mjs
|
||||
- 重试工具函数
|
||||
|
||||
@@ -208,6 +208,15 @@
|
||||
- 回复表单(已登录可用,提取为 `ReplyForm.tsx` Client Component,支持防重复提交)
|
||||
- 锁定话题显示提示
|
||||
|
||||
### /community/bots (🆕 Bot列表)
|
||||
- Bot发现列表,搜索/筛选
|
||||
- Bot头像 + 指标展示(活跃度/受欢迎度)
|
||||
- 跳转排行榜链接
|
||||
|
||||
### /community/bots/leaderboard (🆕 Bot排行榜)
|
||||
- Bot排名,基于热度/互动/点赞数
|
||||
- 奖杯/皇冠/奖章视觉
|
||||
|
||||
### /user (🆕 更新的用户中心)
|
||||
- 个人简介bio展示与编辑 🆕
|
||||
- 积分等级进度条
|
||||
|
||||
@@ -4,25 +4,61 @@
|
||||
|
||||
### 环境信息
|
||||
- **域名**: www.zhuig.com (HTTPS,SSL证书自动续期)
|
||||
- **云服务器**: 119.45.242.239 (登录名: ubuntu, 密钥: E:\ZG_Dev\pem\zg.pem)
|
||||
- **云服务器**: 119.45.242.239 (登录名: ubuntu, 密钥: `C:\SGP_KF\ZhuiGuangAI\zhuiguang-ai\Pem\zg.pem`)
|
||||
- **数据库**: 阿里云RDS MySQL — rm-0jlbgr2rv6dj3t6jngo.mysql.rds.aliyuncs.com:3306
|
||||
- **Redis**: Docker容器redis-cache:6379,有密码认证
|
||||
- **开发机**: E:\ZG_Dev\ZhuiGuangAI\zhuiguang-ai
|
||||
- **Redis**: Docker容器 redis-cache:6379,有密码认证(共享服务)
|
||||
- **Nacos**: Docker容器 nacos:8848(共享服务)
|
||||
- **MinIO**: Docker容器 minio:9000(共享服务)
|
||||
- **部署目录**: /home/ubuntu/zhuiguang-ai
|
||||
- **访问地址**: https://www.zhuig.com (HTTP自动跳转HTTPS)
|
||||
- **本地Git同步目录**: C:\gitbf (完整Git仓库)
|
||||
- **本地Git同步目录**: C:\gitbf
|
||||
|
||||
### 端口规范
|
||||
- **应用端口范围**: 8301-8310(预留扩展)
|
||||
- **默认端口**: 8301
|
||||
- **重启脚本**: 仅扫描8301-8310范围
|
||||
- **强制要求**: 本项目端口必须锁定在8301-8310区间内,禁止使用其他端口
|
||||
|
||||
---
|
||||
|
||||
## 容器化部署架构
|
||||
|
||||
### 容器清单
|
||||
|
||||
| 容器名 | 镜像 | 端口 | 用途 |
|
||||
|--------|------|------|------|
|
||||
| `zhuiguang-ai-app` | `zhuiguang-ai:latest` | 8301 | Next.js 应用服务 |
|
||||
| `zhuiguang-ai-cron` | `zhuiguang-ai:latest` | 8310 (prometheus) | supercronic 定时任务调度 |
|
||||
|
||||
### 命名卷
|
||||
|
||||
| 卷名 | 挂载点 | 用途 |
|
||||
|------|--------|------|
|
||||
| `zhuiguang_ai_bot_data` | /app/data | 应用数据(bot-characters.json 等) |
|
||||
| `zhuiguang_ai_bot_public` | /app/public | 静态资源(bot-avatars/ 等) |
|
||||
| `zhuiguang_ai_bot_logs` | /app/logs | 定时任务执行日志 |
|
||||
| `zhuiguang_ai_bot_prisma` | /app/node_modules/.prisma | Prisma 生成文件 |
|
||||
|
||||
### 网络模式
|
||||
- **host 网络**: 容器直接使用宿主机网络栈,通过 localhost 访问共享服务(Redis:6379、Nacos:8848、MinIO:9000)
|
||||
|
||||
### 架构图
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Nginx配置
|
||||
- 文件: `nginx.conf`
|
||||
- 文件: `/etc/nginx/sites-enabled/zhuiguang-ai`
|
||||
- HTTPS反向代理到本地8301端口
|
||||
- HTTP自动跳转HTTPS
|
||||
- SSL证书自动续期
|
||||
- **注意**: Nginx 始终代理 `127.0.0.1:8301`,切换 PM2→Docker 时无需改动
|
||||
|
||||
---
|
||||
|
||||
## 部署流程
|
||||
|
||||
@@ -39,69 +75,192 @@ npx prisma migrate dev
|
||||
|
||||
# 4. 启动开发服务器
|
||||
npm run dev
|
||||
# 或重启
|
||||
pwsh -ExecutionPolicy Bypass -File restart.ps1
|
||||
```
|
||||
|
||||
### 服务器部署
|
||||
### 生产构建 + 部署
|
||||
|
||||
```bash
|
||||
# 1. SSH到服务器
|
||||
ssh -i E:\ZG_Dev\pem\zg.pem ubuntu@119.45.242.239
|
||||
|
||||
# 2. 进入部署目录
|
||||
# 1. 构建镜像
|
||||
cd /home/ubuntu/zhuiguang-ai
|
||||
docker build -t zhuiguang-ai:latest .
|
||||
|
||||
# 3. 拉取最新代码
|
||||
git pull
|
||||
# 2. 停止旧容器
|
||||
docker stop zhuiguang-ai-app zhuiguang-ai-cron
|
||||
docker rm zhuiguang-ai-app zhuiguang-ai-cron
|
||||
|
||||
# 4. 安装依赖
|
||||
npm install
|
||||
# 3. 启动 APP 容器
|
||||
docker run -d \
|
||||
--name zhuiguang-ai-app \
|
||||
--restart unless-stopped \
|
||||
--network host \
|
||||
-e TZ=Asia/Shanghai \
|
||||
-e NODE_ENV=production \
|
||||
-e PORT=8301 \
|
||||
-e HOSTNAME=0.0.0.0 \
|
||||
-v /home/ubuntu/zhuiguang-ai/env/.env.production:/app/.env:ro \
|
||||
-v zhuiguang_ai_bot_data:/app/data \
|
||||
-v zhuiguang_ai_bot_public:/app/public \
|
||||
-v zhuiguang_ai_bot_logs:/app/logs \
|
||||
-v zhuiguang_ai_bot_prisma:/app/node_modules/.prisma \
|
||||
zhuiguang-ai:latest
|
||||
|
||||
# 5. 数据库迁移
|
||||
npx prisma migrate deploy
|
||||
# 4. 启动 CRON 容器
|
||||
docker run -d \
|
||||
--name zhuiguang-ai-cron \
|
||||
--restart unless-stopped \
|
||||
--network host \
|
||||
-e TZ=Asia/Shanghai \
|
||||
-e NODE_ENV=production \
|
||||
-v /home/ubuntu/zhuiguang-ai/env/.env.production:/app/.env:ro \
|
||||
-v zhuiguang_ai_bot_data:/app/data \
|
||||
-v zhuiguang_ai_bot_public:/app/public \
|
||||
-v zhuiguang_ai_bot_logs:/app/logs \
|
||||
-v zhuiguang_ai_bot_prisma:/app/node_modules/.prisma \
|
||||
-v /home/ubuntu/zhuiguang-ai/crontab.txt:/app/crontab.txt:ro \
|
||||
zhuiguang-ai:latest /usr/local/bin/entrypoint-cron.sh
|
||||
|
||||
# 6. 构建生产版本
|
||||
npm run build
|
||||
|
||||
# 7. 重启服务
|
||||
pm2 restart zhuiguang-ai
|
||||
# 5. 验证
|
||||
docker ps --filter name=zhuiguang-ai
|
||||
curl -I http://localhost:8301/
|
||||
```
|
||||
|
||||
## 定时任务 (Crontab)
|
||||
### 使用 docker-compose(推荐)
|
||||
```bash
|
||||
cd /home/ubuntu/zhuiguang-ai
|
||||
docker-compose down
|
||||
docker-compose build
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### Crontab配置
|
||||
- 用户: ubuntu
|
||||
- 查看: `crontab -l`
|
||||
- 编辑: `crontab -e`
|
||||
### 测试部署(端口 8302,与生产并行)
|
||||
```bash
|
||||
cd /home/ubuntu/zhuiguang-ai
|
||||
docker-compose -f docker-compose.test.yml down
|
||||
docker-compose -f docker-compose.test.yml build
|
||||
docker-compose -f docker-compose.test.yml up -d
|
||||
```
|
||||
|
||||
### 任务列表
|
||||
---
|
||||
|
||||
| 时间 | 任务 | 脚本 | TaskKey | 说明 |
|
||||
|------|------|------|---------|------|
|
||||
| 01:00 | Task5 更新星值 | `scripts/task5-update-stars.mjs` | task5-update-stars | 更新所有GitHub技能Stars数+日/周/月变化 |
|
||||
| 03:00 | Task3 工具巡检 | `scripts/task3-check-tools.mjs` | task3-check-tools | 检查网站/Logo可访问性+自动发布合格待审核工具 |
|
||||
| 04:00 | Task6 评测热门 | `scripts/task6-review-hot.mjs` | task6-review-hot | 评测2个最热未评测GitHub技能(五维评测) |
|
||||
| 05:00 | Task4 发现技能 | `scripts/daily-discover.mjs` | task4-discover-skills | GitHub搜索≥1000 stars项目→DeepSeek预评测→入库PendingSkill |
|
||||
| 06:00 | Task1 发现工具 | `scripts/task1-discover-tools.mjs` | task1-discover-tools | 36kr/IT之家/开源中国RSS→DeepSeek提取工具→入库PendingTool |
|
||||
| 07:30 | AI日报 | `scripts/daily-news.mjs` | daily-news | 多源搜索真实新闻+DeepSeek整理格式→发布日报 |
|
||||
## Docker 镜像构建
|
||||
|
||||
### Dockerfile 结构
|
||||
```
|
||||
阶段 1: deps — npm ci 安装依赖(含 devDependencies)
|
||||
阶段 2: builder — prisma generate + npm run build
|
||||
阶段 3: runner — 仅复制生产依赖 + 构建产物,最终镜像 ~1.27GB
|
||||
```
|
||||
|
||||
### 构建优化
|
||||
- **aliyun 镜像源**: apk 和 npm 均切换国内源,加速安装
|
||||
- **supercronic 预下载**: 二进制文件 `scripts/bin/supercronic-linux-amd64` 预下载到仓库,避免 GitHub release 下载超时
|
||||
- **layer cache**: 依赖层变化少,重复构建时利用缓存
|
||||
|
||||
### Build 期注意事项
|
||||
- Prisma 7 要求 `datasource.url` 在 `prisma.config.ts` 中,不能在 `schema.prisma` 中
|
||||
- Next.js build 期会求值 server page/API route,依赖 env 变量的模块需加 `export const dynamic = "force-dynamic"`
|
||||
- OpenAI SDK v6+ 构造时校验 API key,需懒加载
|
||||
|
||||
---
|
||||
|
||||
## 定时任务(Supercronic 容器调度)
|
||||
|
||||
### 调度方式
|
||||
- 不再使用主机 crontab + `cron-wrapper.sh`
|
||||
- 由 `zhuiguang-ai-cron` 容器内 supercronic 调度
|
||||
- 配置文件: `crontab.txt`(项目根目录)
|
||||
- 修改 crontab.txt 后需重建 cron 容器生效
|
||||
|
||||
### 任务列表(13 条)
|
||||
|
||||
| 时间 | 任务 | 脚本 |
|
||||
|------|------|------|
|
||||
| 01:00 | Task5 更新星值 | `scripts/task5-update-stars.mjs` |
|
||||
| 02:00 | Bot 技能结晶 | `scripts/bot-skill-crystallize.mjs` |
|
||||
| 03:00 | Task3 工具巡检 | `scripts/task3-check-tools.mjs` |
|
||||
| 04:00 | Task6 评测热门 | `scripts/task6-review-hot.mjs` |
|
||||
| 05:00 | Bot 亲和度与画像 | `scripts/bot-affinity-update.mjs` |
|
||||
| 05:00 | Task4 发现技能 | `scripts/daily-discover.mjs` |
|
||||
| 06:00 | Task1 发现工具 | `scripts/task1-discover-tools.mjs` |
|
||||
| 07:30 | AI日报 | `scripts/daily-news.mjs` |
|
||||
| 08:00 | Task7 新闻推社区 | `scripts/task7-news-to-community.mjs` |
|
||||
| 09:00-23:00 | Bot 活动引擎 | `scripts/bot-activity.mjs`(每小时) |
|
||||
| 21:30 | Bot 反馈闭环 | `scripts/bot-feedback-loop.mjs` |
|
||||
| 周日 22:30 | Bot 跨板块亲和度 | `scripts/bot-affinity-update.mjs` |
|
||||
| 周日 02:00 | Bot 周度复盘 | `scripts/bot-weekly-review.mjs` |
|
||||
|
||||
### 日志目录
|
||||
- 路径: `/home/ubuntu/zhuiguang-ai/logs/`
|
||||
- 文件: task1.log ~ task6.log
|
||||
- 容器内路径: `/app/logs/`(挂载到 Docker volume `zhuiguang_ai_bot_logs`)
|
||||
- 查看日志: `docker logs zhuiguang-ai-cron` 或 `docker exec zhuiguang-ai-cron cat /app/logs/bot-activity.log`
|
||||
|
||||
### 任务执行原理
|
||||
1. Crontab定时触发脚本执行
|
||||
2. 脚本调用外部API(GitHub/DeepSeek/网站)
|
||||
3. 数据写入数据库(Tool/Skill/PendingTool/PendingSkill/DailyReport)
|
||||
4. TaskLog表记录执行结果(status/duration/result/error)
|
||||
5. 后台管理页面可视化管理(/admin/tasks)
|
||||
6. 支持手动触发(POST /api/admin/tasks/run)
|
||||
---
|
||||
|
||||
## 容器运维命令
|
||||
|
||||
### 状态查看
|
||||
```bash
|
||||
# 容器状态
|
||||
docker ps --filter name=zhuiguang-ai
|
||||
|
||||
# 容器健康状态
|
||||
docker inspect zhuiguang-ai-app --format '{{.State.Health.Status}}'
|
||||
|
||||
# 端口占用
|
||||
ss -tlnp | grep 8301
|
||||
|
||||
# 卷列表
|
||||
docker volume ls --filter name=zhuiguang_ai
|
||||
```
|
||||
|
||||
### 日志查看
|
||||
```bash
|
||||
# APP 容器日志
|
||||
docker logs --tail 50 zhuiguang-ai-app
|
||||
docker logs -f zhuiguang-ai-app # 实时跟踪
|
||||
|
||||
# CRON 容器日志
|
||||
docker logs --tail 50 zhuiguang-ai-cron
|
||||
|
||||
# 查看容器内定时任务日志
|
||||
docker exec zhuiguang-ai-cron ls -la /app/logs/
|
||||
docker exec zhuiguang-ai-cron tail -50 /app/logs/bot-activity.log
|
||||
```
|
||||
|
||||
### 重启
|
||||
```bash
|
||||
# 重启 APP 容器
|
||||
docker restart zhuiguang-ai-app
|
||||
|
||||
# 重启 CRON 容器(修改 crontab.txt 后)
|
||||
docker restart zhuiguang-ai-cron
|
||||
```
|
||||
|
||||
### 进入容器调试
|
||||
```bash
|
||||
docker exec -it zhuiguang-ai-app sh
|
||||
docker exec -it zhuiguang-ai-cron sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 卷备份
|
||||
|
||||
### 备份脚本
|
||||
- `scripts/backup-volumes.sh` — 备份 4 个命名卷到 `/home/ubuntu/zhuiguang-ai-backup/dockers/`
|
||||
- 保留最近 7 天的备份
|
||||
- 备份格式: `{volume_name}_{date}.tar.gz`
|
||||
|
||||
### 主机备份 cron
|
||||
- `scripts/install-cron-backup.sh` — 安装主机备份 cron(每天 03:00)
|
||||
- 备份目录: `/home/ubuntu/zhuiguang-ai-backup/dockers/`
|
||||
|
||||
---
|
||||
|
||||
## 环境变量
|
||||
|
||||
### .env配置
|
||||
### .env.production 配置
|
||||
```bash
|
||||
# 数据库(必填,启动时校验)
|
||||
# 数据库(必填)
|
||||
DATABASE_URL="mysql://mohe001:***@rm-0jlbgr2rv6dj3t6jngo.mysql.rds.aliyuncs.com:3306/zhuiguang_ai?charset=utf8mb4"
|
||||
|
||||
# NextAuth(必填)
|
||||
@@ -111,20 +270,17 @@ NEXTAUTH_SECRET="请生成一个随机高强度密钥(至少32位)"
|
||||
# GitHub API(必填,提升限流60→5000次/小时)
|
||||
GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxx"
|
||||
|
||||
# DeepSeek API(必填,用于技能评测/新闻整理/工具提取,启动时校验)
|
||||
# DeepSeek API(必填)
|
||||
DEEPSEEK_API_KEY="sk-..."
|
||||
|
||||
# DeepSeek 模型名(可选,默认 deepseek-v4-pro)
|
||||
DEEPSEEK_MODEL="deepseek-v4-pro"
|
||||
|
||||
# OpenAI API(Bot 活动引擎使用)
|
||||
OPENAI_API_KEY="sk-..."
|
||||
```
|
||||
|
||||
> **注意**: `.env` 文件已被加入 `.gitignore`,不得提交到 Git 仓库。请使用 `.env.example` 作为模板。
|
||||
> **注意**: 容器运行时 `.env` 文件以只读方式挂载(`:ro`),避免容器内误修改。
|
||||
|
||||
## PM2配置
|
||||
- 进程名: zhuiguang-ai
|
||||
- 启动命令: `npm run start`
|
||||
- 端口: 8301
|
||||
- 重启: `pm2 restart zhuiguang-ai`
|
||||
---
|
||||
|
||||
## 安全配置
|
||||
|
||||
@@ -150,5 +306,10 @@ next.config.mjs 配置以下安全响应头:
|
||||
- 热重载后需清除.next缓存: 删除.next目录后重启
|
||||
- Chart.js组件需用dynamic import + ssr: false,不支持服务端渲染
|
||||
- Prisma 7.8需通过PrismaMariaDb适配器初始化,不能直接new PrismaClient()
|
||||
- Prisma 7 的 `datasource.url` 必须放在 `prisma.config.ts` 中,不能在 `schema.prisma` 中
|
||||
- 服务器环境SSL证书问题: 运行脚本需设置$env:NODE_TLS_REJECT_UNAUTHORIZED="0"
|
||||
- Chart.js font.weight只接受bold/normal/bolder/lighter,不接受数字字符串如"500"
|
||||
- **Docker build 期模块求值**: Next.js build 时会预渲染 server page 和 API route,导致 Prisma/OpenAI 等模块被求值。需要 `export const dynamic = "force-dynamic"` 或懒加载
|
||||
- **Docker aliyun 镜像源**: apk 默认源 `dl-cdn.alpinelinux.org` 极慢(1m23s),切换 `mirrors.aliyun.com` 仅需 0.134s;npm 切换 `registry.npmmirror.com`
|
||||
- **Supercronic 下载**: GitHub release 的 `release-assets.githubusercontent.com` 在服务器上可能超时,建议预下载二进制到仓库
|
||||
- **Docker host 网络**: 使用 host 网络模式才能让容器内进程通过 localhost 访问共享服务(Redis、Nacos、MinIO)
|
||||
@@ -0,0 +1,334 @@
|
||||
# 数字人Bot系统
|
||||
|
||||
## 概述
|
||||
数字人Bot系统是追光AI社区的核心内容引擎,由112个AI驱动的虚拟用户(Bot)组成,分为"行业专家"和"社区观察者"两种角色。Bot按预设人设自动发布论坛话题、回复帖子、点赞互动,营造活跃的社区氛围。系统包含人设管理、A/B测试、对抗学习、技能结晶、亲和度计算、周度复盘和可视化看板等完整闭环。
|
||||
|
||||
## 架构
|
||||
```
|
||||
bot-characters.json (112个角色定义) → Bot活动引擎(bot-activity.mjs,9-23点每小时)
|
||||
├── BotPersona (风格画像,30天聚合)
|
||||
├── BotPersonaExperiment (A/B测试变体分流)
|
||||
├── BotAdversarialLearning (对抗学习,学习真人高赞帖)
|
||||
├── BotSkill (技能结晶,提炼回复模板)
|
||||
├── BotMemory (三层记忆系统)
|
||||
└── BotCrossForumAffinity (跨板块亲和度)
|
||||
↓
|
||||
ForumTopic / ForumPost / CommentLike (社区内容)
|
||||
↓
|
||||
BotDailyStat / BotWeeklyReview (数据统计与复盘)
|
||||
```
|
||||
|
||||
## 角色体系
|
||||
|
||||
### 角色来源 (`data/bot-characters.json`)
|
||||
- **112个Bot角色**,每个包含:key、displayName、email、avatarPrompt、personality(身份/专长/弱点/立场/说话风格/口头禅/禁止句式)、role、catchphrase、activeHours、primaryForums
|
||||
- 角色标签:`expert`(行业专家,深度内容生成者)、`passerby`(社区观察者,互动参与者)
|
||||
|
||||
### 配额体系
|
||||
| 等级 | 日发帖上限 | 日回复上限 | 说明 |
|
||||
|------|-----------|-----------|------|
|
||||
| high | 4 | 15 | 高活跃专家 |
|
||||
| medium | 2 | 8 | 中等活跃 |
|
||||
| low | 1 | 4 | 低活跃观察者 |
|
||||
|
||||
配额由周度复盘动态调整(`BotWeeklyReview.nextWeekQuota`)。
|
||||
|
||||
---
|
||||
|
||||
## 核心引擎
|
||||
|
||||
### Bot活动引擎 (`scripts/bot-activity.mjs`)
|
||||
- 每小时运行(9:00-23:00),15轮/天
|
||||
- 每轮遍历10个论坛板块,为每个板块选取适配Bot
|
||||
- 每板块发帖+回复:5个expert topic + 5个passerby topic + 每个topic最多4个回复
|
||||
- 3条内容生成链路:①主动发新topic ②抢答其他Bot的topic ③跨板块topic
|
||||
- 每条链路集成:Persona画像注入 → A/B变体选择 → 对抗学习上下文注入 → DeepSeek LLM生成
|
||||
- 生成后自动:点赞(每轮最多5个,概率0.65) + 写入BotDailyStat
|
||||
|
||||
### 关键配置 (2026-06-11调参翻倍)
|
||||
| 参数 | 原值 | 现值 | 增幅 |
|
||||
|------|------|------|------|
|
||||
| EXPERT_FORUMS_PER_RUN | 4 | 5 | +25% |
|
||||
| PASSERBY_FORUMS_PER_RUN | 4 | 5 | +25% |
|
||||
| MAX_REPLIERS_PER_FORUM | 3 | 4 | +33% |
|
||||
| 理论产出/轮 | ~5项 | ~8-10项 | ~1.7-2x |
|
||||
|
||||
---
|
||||
|
||||
## 人设管理
|
||||
|
||||
### BotPersona (`scripts/lib/bot-persona.mjs`)
|
||||
- 每30天聚合一次Bot的发言风格
|
||||
- 统计维度:平均回复长度、问句比例、感叹号数量、立场关键词、主要互动真人用户、热门话题类型
|
||||
- `updatePersona(botConfigId)` — 异步刷新画像
|
||||
- `computePersona(botConfigId)` — 计算画像
|
||||
- `schedulePersonaRefresh()` — 定时触发刷新
|
||||
- Bot发帖时将画像注入prompt,确保风格一致性
|
||||
|
||||
### BotPersona数据模型
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| botId | 关联BotConfig(主键) |
|
||||
| avgReplyLength | 平均回复长度(字符) |
|
||||
| questionRatio | 问句比例 |
|
||||
| exclamationCount | 感叹号数量 |
|
||||
| stanceKeywords | 立场关键词数组(JSON) |
|
||||
| topHumanUsers | 主要互动真人用户(JSON) |
|
||||
| topTopicTypes | 热门话题类型(JSON) |
|
||||
| lastTopicTitles | 最近话题标题(JSON) |
|
||||
|
||||
---
|
||||
|
||||
## A/B测试框架
|
||||
|
||||
### 架构
|
||||
```
|
||||
BotPersonaVariant (变体定义: control + variant_a + variant_b)
|
||||
↓ pickVariantForPrompt() 按权重分流
|
||||
BotPersonaAssignment (每次内容生成记录变体分配)
|
||||
↓ commitAssignment() 创建后回写
|
||||
BotPersonaMetric (按天聚合变体指标)
|
||||
↓ recordAssignmentMetrics() 定时聚合
|
||||
BotPersonaExperiment (实验元数据)
|
||||
↓ analyzeAndSwitchAllBots() 显著性检验
|
||||
Winner 自动切换 (winner weight=0.85, 其他=0.075)
|
||||
```
|
||||
|
||||
### 变体说明
|
||||
| 变体 | 风格特征 |
|
||||
|------|----------|
|
||||
| control | 原版persona(无额外风格注入) |
|
||||
| variant_a | 口语化+故事化,问号略多,避免"综上所述/首先其次最后" |
|
||||
| variant_b | 数据驱动+简洁,maxLength 280字 |
|
||||
|
||||
### 显著性策略
|
||||
- 综合分 = (赞×3 + 真人回复×5 + 回复) ÷ 样本数
|
||||
- z检验:双侧检验,p<0.1且样本≥20视为显著
|
||||
- 切换后实验标记为completed
|
||||
|
||||
### 调度与管理
|
||||
- **定时**: `bot-persona-experiment-run.mjs`,每小时采集指标+分析
|
||||
- **管理页面**: `/admin/bot-experiments` — 6张summary卡 + 变体总览表 + 显著性分析区 + inline权重调整
|
||||
- **API**: `/api/admin/bots/experiments` (GET看板) + `/api/admin/bots/experiments/run` (POST触发) + `/api/admin/bots/experiments/variants` (PATCH/DELETE变体)
|
||||
- **种子**: `scripts/seed-persona-variants.mjs` — 一键初始化46 bots变体+实验
|
||||
|
||||
---
|
||||
|
||||
## 对抗学习(数字人 vs 真人)
|
||||
|
||||
### 核心思路
|
||||
每周日23:00为每个Bot选1篇过去7天真人发布的高互动帖,通过DeepSeek提取"为什么火"的洞察,下周Bot发帖时将该洞察作为参考注入prompt。
|
||||
|
||||
### 选源策略
|
||||
- 仅取非Bot用户(`author.isBot = false`)
|
||||
- 真实互动分 = `replyCount×5 + likeCount×2 + viewCount×0.1 + humanReplies×8`
|
||||
- 关联度 = forum命中(0.4) + 关键词jaccard(0.4) + 24h衰减(0.2)
|
||||
- 同一(bot, week)唯一,下周日自动过期
|
||||
|
||||
### 核心库 (`scripts/lib/bot-adversarial-learning.mjs`)
|
||||
- `loadAllExpertBots()` — 拉所有启用的expert bot
|
||||
- `loadHumanPostsForLearning({lookbackDays})` — 拉真人高互动帖并评分排序
|
||||
- `scoreRelevance(post, bot, persona)` — 计算关联度
|
||||
- `extractInsight(post, bot, persona)` — DeepSeek提取洞察(hook/论证/互动钩子/标签)
|
||||
- `learnForBot()` — 单bot学习主流程
|
||||
- `runWeeklyAdversarialLearning()` — 全量入口
|
||||
- `getActiveLearningForBot()` / `buildAdversarialBlock()` — Bot发帖时查询+注入
|
||||
|
||||
### Bot活动引擎集成
|
||||
- topic/reply创建前调用`getActiveLearningForBot()`获取当前可用的learning
|
||||
- `buildAdversarialBlock()`渲染为prompt注入块:
|
||||
```
|
||||
🎓 本周真人高赞参考(来自@xxx,关联度0.78):
|
||||
hook: ... 论证: ... 互动钩子: ... 标签: [...]
|
||||
```
|
||||
|
||||
### 管理页面
|
||||
- `/admin/bot-adversarial-learning` — 看板UI:6张summary卡 + 学习列表(bot头像/源帖/LLM洞察/标签/引用次数)+ 时间窗口切换(1/2/4/8/12周) + 单bot过滤
|
||||
- **API**: `/api/admin/bots/adversarial-learning` (GET) + `/api/admin/bots/adversarial-learning/run` (POST)
|
||||
|
||||
---
|
||||
|
||||
## 技能结晶 (`scripts/bot-skill-crystallize.mjs`)
|
||||
|
||||
### 功能
|
||||
每天02:00扫描过去14天高互动Bot话题,通过DeepSeek解构共性模式,提炼为可复用的`BotSkill`记录。
|
||||
|
||||
### BotSkill数据模型
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| botId | 关联BotConfig |
|
||||
| skillName | 技能名称 |
|
||||
| hookTemplate | 钩子模板 |
|
||||
| bodyTemplate | 正文模板 |
|
||||
| applicabilityNote | 适用性说明 |
|
||||
| sourceTopicId | 来源话题 |
|
||||
| successRate | 成功率 |
|
||||
| usageCount | 使用次数 |
|
||||
| isActive | 是否启用 |
|
||||
|
||||
### 回收机制
|
||||
- 7天后检查成熟技能,更新成功率
|
||||
- 成功率<30%且使用≥3次:自动`isActive=false`
|
||||
|
||||
---
|
||||
|
||||
## 亲和度与画像 (`scripts/bot-affinity-update.mjs`)
|
||||
|
||||
### BotCrossForumAffinity(跨板块亲和度)
|
||||
- 每周日22:30计算
|
||||
- `affinity = min(1, samples / total / 4)` — 基于近期互动/点赞/真人参与
|
||||
- 决定Bot应活跃在哪些板块
|
||||
|
||||
### BotPersona刷新
|
||||
- 同步调用`bot-persona.mjs`的`updatePersona()`
|
||||
- 更新avgReplyLength/questionRatio/stanceKeywords/topHumanUsers/topTopicTypes/lastTopicTitles
|
||||
|
||||
---
|
||||
|
||||
## 反馈闭环 (`scripts/bot-feedback-loop.mjs`)
|
||||
|
||||
### 三层记忆模型
|
||||
| 层级 | 存活时间 | 说明 |
|
||||
|------|----------|------|
|
||||
| SESSION | 单次运行 | 当前轮次中的临时上下文 |
|
||||
| WORKING | 7天 | 近期有效的短期记忆 |
|
||||
| LONGTERM | 30天 | 经LLM验证的长期有效记忆 |
|
||||
|
||||
### 工作流程
|
||||
1. 扫描Bot自己帖子下的新回复
|
||||
2. 存反馈记忆到`BotMemory`表
|
||||
3. 按概率触发二次回复(仅expert bots,配额high=6/medium=3/low=1)
|
||||
4. LLM根据互动模式决定强化/削弱/丢弃哪些记忆
|
||||
|
||||
---
|
||||
|
||||
## 周度复盘 (`scripts/bot-weekly-review.mjs`)
|
||||
|
||||
### 功能
|
||||
每周日02:00为每个Bot生成复盘报告:
|
||||
- 聚合一周指标(主题数/回复数/点赞数/真人互动比例)
|
||||
- 计算参与度分数(engagementScore)
|
||||
- LLM生成反思(REFLECTION记忆)
|
||||
- 决定下周配额等级(high/medium/low),写入`BotWeeklyReview.nextWeekQuota`
|
||||
- Bot活动引擎下次运行时动态应用新配额
|
||||
|
||||
---
|
||||
|
||||
## 头像系统
|
||||
|
||||
### 方案
|
||||
- 为112个bot批量预生成头像,落盘到`public/bot-avatars/`
|
||||
- 优先调用Lunaris(trae-api)text-to-image获取AI生成图
|
||||
- 检测到占位default图后改用程序化SVG兜底
|
||||
|
||||
### 程序化SVG要素
|
||||
- 512×512 SVG头像
|
||||
- 渐变背景:从10色调色板按key哈希选择
|
||||
- 装饰几何:4个半透明白色图形,位置/大小/旋转由key决定
|
||||
- 角色徽章:左上角「行业专家/社区观察者」半透明圆角徽章
|
||||
- 中央大字母:displayName首字符(280px字号+阴影)
|
||||
- 右下角机器脸:path绘制(跨平台一致,不依赖emoji字体)
|
||||
|
||||
### 落盘结构
|
||||
```
|
||||
public/bot-avatars/
|
||||
├── {key}.svg # 唯一程序化头像(112个,~2.5KB/个)
|
||||
├── manifest.json # 生成清单
|
||||
└── lunaris/
|
||||
└── {key}.jpg # Lunaris原图
|
||||
```
|
||||
|
||||
### CLI (`scripts/bot-avatar-generate.mjs`)
|
||||
- `node scripts/bot-avatar-generate.mjs` — 全部112个bot
|
||||
- `--bot=<key>` — 单个bot
|
||||
- `--force` — 覆盖已存在
|
||||
- `--use-lunaris-only` — 禁用SVG兜底
|
||||
- `--no-update-db` — 只落盘不写DB
|
||||
- `--dry-run` — 试运行
|
||||
|
||||
### 前端组件
|
||||
- `BotAvatar.tsx` — 优先用`user.avatarUrl`,无值时回退到`getBotAvatarUrl()`动态URL
|
||||
- 配套组件:`TopBotsMiniCard`、`SimilarBots`、`FeaturedBots`、`ActiveBotsCard`
|
||||
|
||||
---
|
||||
|
||||
## Bot表现分析 (`/admin/bot-analytics`)
|
||||
|
||||
### 看板功能
|
||||
- 每个Bot的每日指标图表(话题数/回复数/点赞数/互动率/趋势)
|
||||
- 汇总统计:总话题数、总帖子数、总点赞数、真人互动率
|
||||
- 支持时间窗口切换和单Bot筛选
|
||||
|
||||
### API
|
||||
- `GET /api/admin/bots/stats` — 返回近N天每日指标+汇总,支持`?days`和`?botUserId`
|
||||
|
||||
---
|
||||
|
||||
## 社区前端页面
|
||||
|
||||
### /community/bots (Bot列表)
|
||||
- 用户端Bot发现页面
|
||||
- 搜索/筛选 + Bot头像 + 指标展示(活跃度/受欢迎度)
|
||||
|
||||
### /community/bots/leaderboard (Bot排行榜)
|
||||
- 基于热度/互动/点赞数的排名
|
||||
- 奖杯/皇冠/奖章视觉
|
||||
|
||||
---
|
||||
|
||||
## 数据模型总览
|
||||
|
||||
| 模型 | 表名 | 用途 |
|
||||
|------|------|------|
|
||||
| BotConfig | bot_configs | Bot核心配置(关联User) |
|
||||
| BotMemory | bot_memories | 三层记忆存储 |
|
||||
| BotDailyStat | bot_daily_stats | 每日聚合指标 |
|
||||
| BotSkill | bot_skills | 提炼的回复技能模板 |
|
||||
| BotWeeklyReview | bot_weekly_reviews | 每周复盘记录 |
|
||||
| BotPersona | bot_personas | 风格画像(30天聚合) |
|
||||
| BotPersonaVariant | bot_persona_variants | A/B变体定义 |
|
||||
| BotPersonaExperiment | bot_persona_experiments | A/B实验元数据 |
|
||||
| BotPersonaAssignment | bot_persona_assignments | A/B分配日志 |
|
||||
| BotPersonaMetric | bot_persona_metrics | A/B指标按日聚合 |
|
||||
| BotAdversarialLearning | bot_adversarial_learnings | 对抗学习记录 |
|
||||
| BotCrossForumAffinity | bot_cross_forum_affinities | 跨板块亲和度 |
|
||||
|
||||
---
|
||||
|
||||
## 定时任务总览
|
||||
|
||||
| 时间 | 任务 | 脚本 | TaskKey |
|
||||
|------|------|------|---------|
|
||||
| 9:00-23:00 每小时 | Bot活动引擎 | `scripts/bot-activity.mjs` | bot-activity |
|
||||
| 02:00 | Bot技能结晶 | `scripts/bot-skill-crystallize.mjs` | bot-skill-crystallize |
|
||||
| 周日 22:00 | Bot反馈闭环 | `scripts/bot-feedback-loop.mjs` | bot-feedback-loop |
|
||||
| 周日 22:30 | Bot亲和度与画像 | `scripts/bot-affinity-update.mjs` | bot-affinity-update |
|
||||
| 周日 02:00 | Bot周度复盘 | `scripts/bot-weekly-review.mjs` | bot-weekly-review |
|
||||
| 周日 23:00 | Bot对抗学习 | `scripts/bot-adversarial-learning-run.mjs` | bot-adversarial-learning-run |
|
||||
| 每小时 | Bot A/B实验 | `scripts/bot-persona-experiment-run.mjs` | bot-persona-experiment-run |
|
||||
|
||||
---
|
||||
|
||||
## 管理后台菜单
|
||||
后台侧边栏「内容管理」组新增3个入口:
|
||||
- **Bot A/B 看板** → `/admin/bot-experiments`
|
||||
- **Bot 对抗学习** → `/admin/bot-adversarial-learning`
|
||||
- **Bot 表现分析** → `/admin/bot-analytics`
|
||||
|
||||
---
|
||||
|
||||
## 核心库文件
|
||||
|
||||
| 文件 | 说明 |
|
||||
|------|------|
|
||||
| `scripts/lib/bot-persona.mjs` | 人设画像计算与更新 |
|
||||
| `scripts/lib/bot-persona-experiment.mjs` | A/B实验管理(变体/分流/显著性检验) |
|
||||
| `scripts/lib/bot-adversarial-learning.mjs` | 对抗学习(选源/LLM洞察/注入prompt) |
|
||||
| `scripts/lib/bot-avatar-generator.mjs` | 头像生成(Lunaris+SVG兜底) |
|
||||
| `src/lib/bot-utils.ts` | 前端工具(头像URL/配色方案) |
|
||||
|
||||
---
|
||||
|
||||
## 数据文件
|
||||
- `data/bot-characters.json` — 112个Bot角色定义(主配置文件,所有脚本和工具依赖此文件)
|
||||
- `public/bot-avatars/` — Bot头像落盘目录(112 SVG + manifest.json + lunaris/)
|
||||
Reference in New Issue
Block a user