MicroFish/PRD.md

739 lines
35 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Foresight 先见之明 — 产品需求文档 (PRD)
> **版本**v0.3.3 — 2026-04-16 CustomGraphBuilder + 一键部署 + CDN SPA 修复
> **基线**:基于 [MiroFish](https://github.com/666ghj/MiroFish) v0.1.2 二次开发,已大量重构。
---
## 1. 产品定位
**Foresight 是一个把"需要预测的未知"变成"可演化的数字沙盘"的群体智能引擎。**
用户上传任何一份"信号"——一段视频文案、一份政策草案、一次金融事件复盘、一段小说背景——Foresight 自动构建该信号所属世界的知识图谱,孵化出几百个有完整人格、记忆、行为模式的虚拟 Agent让他们在虚拟社交平台上自由互动、扩散、对抗、共鸣最后输出一份"如果这件事真的发生,世界会变成什么样"的详尽预测报告。
**核心命题**:让"未来"在数字沙盘里先演练一遍,让决策在百战模拟之后才下刀。
### 三种使用形态
| 形态 | 用户 | 典型问题 | 输出 |
|---|---|---|---|
| **单次预测** | 个人 / 临时项目 | "这条视频发出去会火吗?" | 一份报告 + 可回放的传播沙盘 |
| **建模 + 复用** | 团队长期使用 | "我有一批 200 人的目标受众样本,每周给我跑 5 条新内容看哪个最容易出圈" | 同一批 agent 反复跑不同 initial_posts |
| **多租户 SaaS**v0.4 路线图) | 客户分账户 | "金融预测 / 舆情扩散 / 关系发展 各建一套独立沙盘" | 子账户体系 + 按次计费 + 项目隔离 |
---
## 2. 产品愿景:从工具到平台
### 2.1 v0.3 现状(已实现)
一个**单租户**的端到端预测流水线:上传文档 → 图谱 → 人设 → 配置 → 模拟 → 报告 → 回放 → 互动。
### 2.2 v0.4 目标(下一个大版本)
**Foresight 升级为多领域可定制的预测系统。** 不再只服务"舆情扩散"一个场景,而是抽象为**"任何可被多 agent 互动建模的预测问题"**
| 应用领域 | 输入信号 | Agent 类型 | 预测输出 |
|---|---|---|---|
| **内容传播预测** | 视频逐字稿 / 帖子文案 | 200 个画像各异的目标受众 | 触达率 / 互动率 / 传播路径 / 爆款概率 |
| **舆情扩散预测** | 突发事件 / 政策草案 | 不同立场的意见领袖 + 普通群众 | 舆论走向 / 关键拐点 / 情绪曲线 |
| **金融市场预测** | 财报 / 政策 / 黑天鹅事件 | 散户 / 机构 / 量化 / 媒体 | 价格反应 / 资金流向 / 板块联动 |
| **人际关系发展** | 角色背景 / 起始事件 | 故事中的所有角色 | 关系演化树 / 关键转折 / 多结局 |
| **品牌危机推演** | 危机事件 + 公关方案 | 用户 / 媒体 / 监管 / 竞品 | 不同应对策略下的舆情走向 |
**核心抽象**:每个领域 = 一组(领域语料 + 领域 agent 库 + 领域平台规则 + 领域评估指标。Foresight 提供**通用的工作流编排**,领域知识用配置即可注入。
### 2.3 v0.5 商业化(远期)
- 子账户体系org / user / project 三级权限)
- 按模拟次数 / agent 数 / 报告深度计费
- 模型 fork & 对比模式A/B 内容对比传播效率)
- 数据隔离 + 合规审计
---
## 3. 系统架构v0.3 实际部署)
```
┌─────────────────────┐
│ M-flow记忆系统
│ 踩坑/经验/凭证记录 │
└─────────────────────┘
用户浏览器
├── 前端 (Vue 3 + Vite)
│ 部署:腾讯云 COS + CDN
│ 域名foresight.yizhou.chat
│ 新增页面:/simulation/:id/replayManus 式过程回放)
└── HTTPS → api.foresight.yizhou.chat (Nginx)
└── Backend Flask (5001) 服务器:腾讯云 2C8G
│ OSUbuntu 24.04
│ Python3.11.15 (uv 管理)
│ venv/opt/foresight/backend/.venv-311
├── LLM API智谱 GLM-4-Flash (之前用 MiniMax M2.7,已弃)
│ 用途:本体、画像、配置、报告、模拟决策
│ Endpointhttps://open.bigmodel.cn/api/paas/v4/
├── Knowledge GraphCustomGraphBuilder + Neo4jv0.3.2 替代 Graphiti
│ 部署Docker 容器 neo4j:5.26-community
│ 图谱构建 LLMGLM-4-Flash同主 LLM自带 retry + fallback
│ EmbeddingBAAI/bge-m3 via SiliconFlow仅下游检索用
├── HF Hub Mirrorhf-mirror.com OASIS 推荐模型 twhin-bert-base
└── OASIS 模拟引擎 fork 自 camel-oasis 0.2.5
支持 Twitter / Reddit 双平台并行
🚧 国内平台抽象层v0.4 路线图(抖音/视频号/小红书/微博)
```
### 3.1 关键基础设施决策v0.3 沉淀的经验)
| 决策点 | 当前选择 | 弃用方案 | 原因 |
|---|---|---|---|
| LLM | 智谱 GLM-4-Flash | MiniMax M2.7 / GPT-4o-mini | Flash 单次延迟 0.5-1s128K context |
| 图谱构建 | **CustomGraphBuilder**(自研) | Graphiti + Qwen/GLM | Graphiti 与非 OpenAI LLM 兼容性黑洞(详见附录 C |
| 知识图谱存储 | 自托管 Neo4j | Zep Cloud | 摆脱外部依赖、可控、免月费 |
| Python | 3.11uv 管理) | 系统 3.12 | camel-oasis<3.12 不兼容 3.12 |
| 包源 | 腾讯云 PyPI 镜像 | 直连 PyPI | 国内服务器直连慢 100x |
| HF 模型源 | hf-mirror.com | huggingface.co | 国内服务器连不上 hf 主站 |
| Agent 数甜点 | **200 agents** | 503默认 | 8G 内存上限 + 95% 置信区间足够 |
| 运行参数 | semaphore=100 / 双平台 | semaphore=30 / 单平台 | 8G 升级后可承载 |
---
## 4. 核心功能流水线5 步 + 1 回放)
### Step 1: 知识图谱构建
**输入**上传文档PDF/MD/TXT/DOCX+ 模拟需求自然语言描述
**流程**
1. 文档解析 文本提取
2. LLM 分析全文 生成本体10 个实体类型 + 6-10 个关系类型
3. 文本分块 批量调用 Graphiti 写入 Neo4j
4. 返回图谱可视化节点 +
**API**
- `POST /api/graph/ontology/generate`
- `POST /api/graph/build`
- `GET /api/graph/task/<task_id>`
### Step 2: Agent 人设生成
**输入**已构建的知识图谱
**流程**
1. Neo4j 读取图谱实体与关系
2. 按实体类型筛选调用 LLM 为每个实体生成 OASIS Agent Profile
3. 每个 profile 人设故事 / MBTI / 年龄 / 职业 / 兴趣话题 / 活跃时段 / 互动倾向
4. 实时写入 `reddit_profiles.json` `twitter_profiles.csv`
**新功能**v0.3 新增
- **加速完成按钮**右上角"加速完成"用户可在生成到任意数量时立即停止剩余生成使用已生成的 profile 进入下一步
**API**`POST /api/simulation/prepare`
### Step 3: 模拟配置生成
**输入**profiles + 模拟需求 + 文档原文
**流程**
1. LLM 智能生成时间配置peak hours / off-peak hours / 活跃度系数
2. LLM 智能生成事件配置initial_posts 列表 + 轮次事件
3. LLM 为每个 agent 分配活跃时段互动概率
4. 输出 `simulation_config.json`
### Step 4: 双平台模拟运行
**输入**profiles + simulation_config
**流程**
1. 启动 OASIS Twitter env + Reddit env 并行asyncio.gather
2. 每轮按时间窗口激活若干 agent
3. 每个激活的 agent 调用 LLM 生成行为发帖 / 评论 / 点赞 / 转发 / 关注
4. 实时写入 `twitter/actions.jsonl` `reddit/actions.jsonl`
5. 每平台限制 semaphore=100 防止 API 过载
**性能指标**200 agents 双平台 8G 服务器
- 启动 + tokenizer 加载~30-60s
- 每轮~30-60s取决于活跃 agent
- 15 rounds 完整跑完~10-15 分钟
**API**
- `POST /api/simulation/start` 启动
- `POST /api/simulation/stop` 停止
- `GET /api/simulation/<id>/run-status/detail` 实时状态
**新功能**v0.3 新增
- **后端 SIGTERM 误杀子进程 bug 修复**之前重启 Flask 会连带杀掉正在跑的模拟已通过让 `register_cleanup` 变为 no-op 修复现在可以热更新后端代码不影响运行中的模拟
### Step 5: 报告生成
**输入**完整模拟结果 + 知识图谱
**流程**
1. LLM 规划报告大纲5 个章节
2. 每章节 ReACT 循环推理 工具调用 生成
3. 工具图谱搜索InsightForge / Panorama/ 节点详情 / agent 行为统计
4. 输出结构化 Markdown 报告
**API**`POST /api/report/generate`
> Token 消耗最大的环节,单次完整报告约 80-150K tokens。
### Step 6新增: Manus 式过程回放
**v0.3 新增的核心功能**把整个 Foresight 工作流Step 1-5做成可拖拽 / 可播放的可视化时间线方便给客户合作方自己复盘演示
**界面布局**
```
┌─────────────────────────────────────────────────────┐
│ ← 返回 foresight 回放 sim_xxxx [running] │
├─────────┬──────────────────────────────┬────────────┤
│ 工作流 │ 当前动作(大卡片) │ 全局统计 │
│ 时间线 │ ┌─────────────────────┐ │ │
│ │ │ 👤 90后 (#6) │ │ 总动作 N │
│ ● 步骤1 │ │ 📱 reddit │ │ rounds 8 │
│ │ 文档 │ │ ✏️ CREATE_POST │ │ │
│ │ │ │ "芒格说复利..." │ │ 类型分布 │
│ ● 步骤2 │ └─────────────────────┘ │ POST 85%│
│ │ 图谱 │ │ LIKE 12%│
│ │ │ 动作流(滚动 30 条) │ │
│ ● 步骤3 │ ┌─────────────────────┐ │ Top Agents │
│ │ 人设 │ │ r03 90后 ✏️ ... │ │ 90后 8 │
│ │ │ │ r03 70后 💬 ... │ │ 00后 6 │
│ ● 步骤4 │ │ r04 AI 📤 ... │ │ │
│ │ 配置 │ └─────────────────────┘ │ 平台分布 │
│ │ │ │ TW 17 RD 8 │
│ ● 步骤5 │ │ │
│ 模拟 │ │ │
├─────────┴──────────────────────────────┴────────────┤
│ ⏮ ▶ ⏭ ━━━━━●───── Round 8/15 Day 1 08:00 │
│ 速度 0.5x · 1x · 2x · 5x · 10x │
└─────────────────────────────────────────────────────┘
```
**核心能力**
- 左栏5 步工作流时间线带状态 + 元数据
- 中上当前动作大卡片agent 头像 + 内容 + 平台/类型 tag
- 中下动作流滚动最近 30 可点击跳转
- 右栏聚合统计总数 / 类型分布 bar / Top 8 agents / 平台分布卡
- 底部scrubber 时间轴 + 播放控件 + 5 档速度
**数据源**`GET /api/simulation/:id/replay` 一次性返回所有数据前端无需多次请求
**最新 run 过滤**actions.jsonl append-only 文件多次 run 会累积后端通过扫描最近一次 `simulation_start` 事件的时间戳过滤掉历史 run 残留 actions保证回放只显示最新一次
---
## 4.5 Token 用量追踪与成本估算v0.3 新增 · 内部用)
为了支持后续定价决策和成本控制v0.3 新增 token 追踪模块。**销售给客户的版本需要移除此 blueprint 注册**去掉 `app/__init__.py` 里的 `usage_bp` 即可)。
### 工作机制
- `backend/app/utils/token_tracker.py` 提供进程内全局 stagemodeltokens 计数器
- `LLMClient` 每次 `chat()` 自动 record 一次 `usage.prompt_tokens / completion_tokens`
- API 端点在入口处 `token_tracker.set_stage("step1_ontology")`
- 价格表内置在 `PRICING` 字典覆盖 GLM / SiliconFlow / MiniMax / OpenAI / Anthropic 主流模型
### Stage 命名
| Stage | 触发位置 | 说明 |
|---|---|---|
| `step1_ontology` | `POST /api/graph/ontology/generate` | 文档分析与本体生成 |
| `step2_graph_build` | `POST /api/graph/build` | Graphiti 图谱构建 LLM 提取实体 |
| `step3_prepare` | `POST /api/simulation/prepare` | Profile 生成 + 模拟配置生成 |
| `step4_simulation` | OASIS 子进程**不在 Flask ** | 需要走 `estimate-simulation` API 估算 |
| `step5_report` | `POST /api/report/generate` | 报告 ReACT 多轮调用 |
### API
| 端点 | 用途 |
|---|---|
| `GET /api/usage/summary` | 当前累计统计每个 stage prompt/completion tokens + 估算成本CNY |
| `POST /api/usage/reset` | 清空可指定 stage |
| `GET /api/usage/estimate-simulation?rounds=15&active_agents_per_round=10` | 估算 OASIS 模拟成本无法精确测 |
| `POST /api/usage/set-stage` | 手动切 stage测试用 |
### 局限
1. **OASIS 模拟子进程的 LLM 调用无法被 Flask 进程的 tracker 捕获**camel-ai 用自己的 client)。需要走 estimate API 用经验公式估算
2. **进程重启会丢失数据**如需持久化 `reset()` dump JSON 文件即可
3. **价格表是 2026-04 价格快照**需要定期更新 `PRICING` 字典
### 典型 Foresight 单次完整流水线成本估算200 agents / 15 rounds / GLM-4-Flash
| Stage | Tokens 范围 | CNY 估算 |
|---|---|---|
| Step 1 本体生成 | 5K-15K | 0.001-0.003 |
| Step 2 图谱构建 | 50K-200K | 0.005-0.020 |
| Step 3 Profile + Config | 100K-300K | 0.010-0.030 |
| Step 4 模拟 (15 rounds) | 1M-3M | 0.10-0.30 |
| Step 5 报告生成 | 80K-150K | 0.008-0.015 |
| **合计** | **~1.2M-3.7M** | **~0.12-0.37 ** |
> 关键洞察:**模拟运行 (Step 4) 占总成本的 80%+**,但因为 GLM-4-Flash 单价极低,单次完整流水线 < 0.5 元 RMB。这给定价留了巨大空间以成本 0.5 元 / 次,售价 5-50 元 / 次给客户都是合理的(取决于客户类型与定制化程度)。
---
## 5. v0.4 路线图(下一个大版本要做的事)
按优先级
### P0国内平台抽象层
**痛点**当前 Twitter + Reddit 是欧美社交语境国内 IP / 内容 / 客户都不匹配
**目标**支持抖音 / 视频号 / 小红书 / 微博 / 公众号 5 个国内平台
**两条路径**
| 路径 A快速 MVP2-3 | 路径 B真模拟1-2 |
|---|---|
| 基于 OASIS Reddit 模式 fork 一份"通用国内平台"虚拟实现 | 抛弃 OASIS自研 platform engine |
| 不真正模拟抖音 ML 算法用参数化传播模型 | 真模拟抖音 FYP / 视频号双引擎 / 小红书 tag 聚类 |
| LLM 决定 agent 互动 + 配置文件定义平台规则参数 | 行业报告训练参数 + 黑盒推荐算法逼近 |
| 可申请客户付费试点 | 可申请专利 / 学术发表 |
**先走路径 A**3 周内可演示客户付费数据反哺路径 B
**配置形态(设计稿)**
```json
{
"platforms": [
{
"id": "douyin",
"type": "short_video",
"weight": 0.45,
"rules": {
"recommendation": "fyp_engagement_loop",
"viral_threshold": 0.08,
"interaction_types": ["like", "comment", "share", "follow", "watch_full"],
"key_features": ["video_completion_rate", "comment_density", "share_velocity"]
}
},
{ "id": "xiaohongshu", "type": "lifestyle_feed", "weight": 0.25, "rules": {...} },
{ "id": "wechat_video", "type": "social_graph_video", "weight": 0.15, "rules": {...} },
{ "id": "weibo", "type": "broadcast_micro_blog", "weight": 0.10, "rules": {...} },
{ "id": "wechat_official", "type": "subscription_long_form", "weight": 0.05, "rules": {...} }
]
}
```
### P1模型复用 / Fork 模拟
**痛点**现在每次跑模拟都要走完 Step 1-4重复劳动
**目标**基于已建好的 simulation 一键 fork 一个新版本只换 `event_config.initial_posts` 即可
**功能点**
- "Fork as Template" 按钮
- 模板库保存通过验证的 sim 作为预设
- A/B 对比模式两条新内容并排跑结果并排展示
### P2多租户 SaaS 改造
**功能模块**需要派出 8 个并行 sub-agent 协同开发
| Sub-Agent | 模块 | 任务 |
|---|---|---|
| Architect | 多租户架构 | PostgreSQL schema 隔离 / API gateway / RBAC 设计 |
| Backend Engineer | API 改造 | user_id / org_id / billing 字段所有数据按租户隔离 |
| Frontend Engineer | UI 改造 | 登录 / 注册 / dashboard / 子账户管理界面 |
| Platform Engine | 平台抽象 | 上面 P0 的国内平台抽象层落地 |
| Auth & Security | 认证 | Better Auth / OAuth / API key 发放 |
| Billing | 计费 | 接微信 / 支付宝 / Stripe按模拟次数 / agent 数计费 |
| DevOps | 容器化 | Docker + k8s + 监控 + 扩容策略 |
| PM/Critic | 全程 review | 商业目标对齐 + 架构 review |
### P3稳定性 / 运维改进
- Backend SIGTERM 误杀子进程 bugv0.3 已修
- 子进程心跳超时当前 simulation 子进程挂掉后 state 不会自动更新成 failed需要加心跳检测
- 模拟运行内存预算检查启动前根据 agent + 平台数预估内存超出可用内存时拒绝启动
- Replay actions.jsonl 自动清理每次新 run 启动前清空旧文件避免历史残留
- 多模拟并发支持单服务器同时跑 2-3 sim需要更大内存或更精细资源调度
---
## 6. 技术栈
### 前端
| 技术 | 版本 | 用途 |
|---|---|---|
| Vue 3 | 3.5+ | UI 框架Composition API + script setup |
| Vite | 7.x | 构建工具 |
| Vue Router 4 | - | 路由 |
| vue-i18n | 9.x | 中英双语 |
| D3.js / Force Graph | - | 图谱可视化 |
| 字体 | Space Grotesk + Noto Sans SC + JetBrains Mono | 设计语言 |
### 后端
| 技术 | 版本 | 用途 |
|---|---|---|
| Python | 3.11.15 (uv 管理) | 运行时 |
| Flask | 3.1.3 | Web 框架 |
| OpenAI SDK | - | LLM 客户端兼容智谱/MiniMax/SiliconFlow |
| camel-ai | 0.2.78 | OASIS 依赖 |
| camel-oasis | 0.2.5 | 社交模拟引擎 |
| graphiti-core | - | Neo4j 图谱构建框架 |
| transformers + torch | - | OASIS 内置 twhin-bert-base |
| neo4j-driver | - | Neo4j 客户端 |
### 部署
| 组件 | 平台 | 说明 |
|---|---|---|
| 前端静态 | 腾讯云 COS + CDN | foresight.yizhou.chat |
| SSL 证书 | acme.sh / Let's Encrypt | 自动续期 |
| 后端 | 腾讯云轻量 2C8G Ubuntu 24.04 | api.foresight.yizhou.chat 127.0.0.1:5001 |
| Neo4j | Docker container neo4j:5.26-community | bolt://localhost:7687 |
| 进程管理 | nohup + disown systemd / docker | 启动命令见下 |
**Backend 启动命令**
```bash
cd /opt/foresight/backend && \
nohup ./.venv-311/bin/python run.py --host 0.0.0.0 \
>> logs/server.log 2>&1 < /dev/null & \
disown
```
---
## 7. 配置项
```env
# ========== LLM ==========
# 智谱 GLM-4-Flash高吞吐低延迟OASIS 模拟首选)
LLM_API_KEY=<智谱 API Key>
LLM_BASE_URL=https://open.bigmodel.cn/api/paas/v4/
LLM_MODEL_NAME=glm-4-flash
# 可选升级glm-4-flashx / glm-4-air / glm-4-plus同 endpoint质量↑速度↓
# 双 LLM 加速(可选,让两平台用不同 provider 分摊 RPM
LLM_BOOST_API_KEY=
LLM_BOOST_BASE_URL=
LLM_BOOST_MODEL_NAME=
# ========== Neo4j自托管 Graphiti 后端) ==========
NEO4J_URI=bolt://localhost:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=<密码>
# ========== Graphiti LLM图谱构建 ==========
GRAPHITI_LLM_API_KEY=<SiliconFlow API Key>
GRAPHITI_LLM_BASE_URL=https://api.siliconflow.cn/v1
GRAPHITI_LLM_MODEL=Qwen/Qwen2.5-32B-Instruct
# ========== Embedding ==========
EMBEDDING_API_KEY=<SiliconFlow API Key>
EMBEDDING_BASE_URL=https://api.siliconflow.cn/v1
EMBEDDING_MODEL=BAAI/bge-m3
# ========== HuggingFace 镜像(必填,国内服务器) ==========
HF_ENDPOINT=https://hf-mirror.com
# ========== Flask ==========
FLASK_DEBUG=False
```
---
## 8. v0.3 当前状态与已交付
### v0.3.32026-04-16 CustomGraphBuilder + 一键部署 + CDN 修复)
- [x] **CustomGraphBuilder 替代 Graphiti**v0.3.2 核心交付
- 完全自研的图谱构建器不依赖 graphiti-core
- chunk 单次 LLM 调用Graphiti 需要 4-5 )→ 速度 4-5x
- ThreadPoolExecutor 10 并发 194 chunks 10 分钟降到 ~2 分钟
- 直接用 cypher MERGE Neo4j Graphiti 嵌套 dict / context overflow 等兼容性问题
- 使用 Foresight LLMClient 自带 retry + fallback + token tracker
- 下游 `get_all_nodes / get_all_edges / filter_defined_entities` 完全兼容
- 文件`backend/app/services/custom_graph_builder.py`
- [x] **一键部署脚本** `scripts/deploy.sh`
- `--backend`rsync 语法检查 kill/restart Flask health verify
- `--frontend`vite build coscmd upload tccli CDN purge
- `--full`两个都做
- `--dry-run`预演
- 处理路径空格 / sudo rsync / Flask 存活检查
- [x] **CDN SPA 路由 fallback**
- 问题Vue Router history 模式COS 上子路径全部 404
- 修复`tccli cdn UpdateDomainConfig` 设置 404 302 跳转 `/index.html`
- 永久配置deploy.sh 不需要每次重新设
- [x] **前端首次正式部署到腾讯云 COS**
- `coscmd upload -r dist/ /` bucket `foresight-1317962478`
- CDN purge `tccli cdn PurgePathCache`
- 包含 v0.3 所有前端改动replay UI / 加速完成按钮 / 路由修复
- [x] **Graphiti 兼容层保留**
- graphiti_client.py 中的 5 monkey-patch 保留driver / reranker / embedder / EntityNode / bulk_utils
- 这些只影响旧 Graphiti 代码路径add_episode / add_episodes_batch
- CustomGraphBuilder 完全绕过不受影响
### v0.3.1 hotfix2026-04-15 生产链路打通)
经过一次完整的端到端测试修复了 7 个阻塞生产跑通的 bug
- [x] **Manus 式沉浸视图重构** 回放界面从三栏分析面板 Manus 风格单栏 cinematic 视图
- 顶部 breadcrumb浏览器外壳 + 平台原生帖子卡片Jump to live 按钮live 指示灯
- 右上角 ◫/▦ 可切回三栏分析视图
- 自动轮询sim running 时每 10s 拉数据
- 文件`frontend/src/views/SimulationReplayView.vue`
- [x] **LLM 客户端指数退避重试** 识别 `RateLimitError / 429 / 5xx / 1302 / 超时`5 次重试 124816s 带随机抖动
- 文件`backend/app/utils/llm_client.py`
- [x] **GLM → Qwen 32B 双 LLM 降级 fallback** LLM 重试耗尽后自动切 SiliconFlow Qwen 32B 单次兜底解决 GLM RPM 配额的间歇性限流
- 文件`backend/app/services/ontology_generator.py`
- [x] **Qwen 32B 上下文爆修复** `MAX_TEXT_LENGTH_FOR_LLM` 50000 28000 chars保证 prompt+response < 32768 tokens
- 文件`backend/app/services/ontology_generator.py`
- [x] **Neo4j entity summary flatten** monkey-patch `Neo4jEntityNodeOperations.save/save_bulk`LLM 返回嵌套 dict 时自动取 `.value` 扁平化 Neo4j TypeError
- 文件`backend/app/services/graphiti_client.py`
- [x] **Frontend 无 pending state 路由修复** `/process/new` 访问时无上传状态自动 `router.replace({name:'Home'})` 不再死循环
- 文件`frontend/src/views/MainView.vue`
- [x] **semaphore 100 → 30** OASIS 模拟并发峰值降低避免 GLM 限流雪崩
- 文件`backend/scripts/run_parallel_simulation.py`
### v0.3 完成(本次大版本前的全部更新)
#### 基础设施迁移
- [x] Zep Cloud 自托管 Graphiti + Neo4j脱离外部 SaaS 依赖
- [x] LLM MiniMax M2.7 智谱 GLM-4-Flash速度提升 2-5x
- [x] Python 3.12 3.11.15uv 管理 .venv-311解决 camel-oasis 兼容性
- [x] 服务器从 2C4G 2C8G解决 OOM 崩溃
- [x] 4G swap 总可用内存 ~13G
- [x] 配置 hf-mirror.com解决 twhin-bert-base 下载卡死
#### 性能优化
- [x] semaphore 30 100每轮 2-3x 加速
- [x] 找到 200 agents 内存/性能/统计置信度甜点
- [x] 双平台并行Twitter + Reddit asyncio.gather
#### 新功能
- [x] **Step 2 加速完成按钮**profile 生成中可一键停止剩余用已有进入下一步
- [x] **Manus 式过程回放界面**核心 v0.3 交付
- 后端 `GET /api/simulation/:id/replay` 一次性返回全部回放数据
- 前端 `/simulation/:id/replay` 三栏布局 + scrubber + 5 档播放速度
- 工作流时间线 + 当前动作卡 + 滚动 feed + 聚合统计
- 自动过滤历史 run 残留 actions
#### Bug 修复
- [x] **Backend SIGTERM 误杀模拟子进程 bug**之前重启 Flask 会连带杀子进程现已修复可热更新后端代码不影响正在跑的模拟
- [x] CORS / Neo4j Query / DateTime 序列化等历史 bug
#### 文档与记忆系统
- [x] 部署信息全部归档到 M-flowinfra / lessons / services / credentials
- [x] PRD.md / README.md 重写
### v0.4 待完成(路线图详见 §5
- [ ] **国内平台抽象层**P0)— 抖音 / 视频号 / 小红书 / 微博 / 公众号
- [ ] **Fork 模拟 + A/B 对比**P1)— 模型复用与对比演化
- [ ] **多租户 SaaS 改造**P2)— 子账户体系 + 计费 + 数据隔离
- [ ] **稳定性运维**P3)— 子进程心跳 / 内存预算检查 / 自动清理
---
## 9. 关键文件索引
### 后端
| 路径 | 用途 |
|---|---|
| `backend/run.py` | Flask 入口 |
| `backend/app/__init__.py` | Flask 初始化注意v0.3 已移除 register_cleanup 的破坏性 signal handler |
| `backend/app/api/graph.py` | 图谱构建 API |
| `backend/app/api/simulation.py` | 模拟 / prepare / start / stop / **replay**新增 line ~2005 |
| `backend/app/api/report.py` | 报告生成 API |
| `backend/app/services/ontology_generator.py` | LLM 本体生成 |
| `backend/app/services/graph_builder.py` | Graphiti / Neo4j 图谱构建 |
| `backend/app/services/oasis_profile_generator.py` | Agent 画像生成含加速完成 cancel_check 逻辑 |
| `backend/app/services/simulation_config_generator.py` | 模拟配置生成 |
| `backend/app/services/simulation_manager.py` | 模拟管理 accelerate flag |
| `backend/app/services/simulation_runner.py` | 模拟运行 v0.3 register_cleanup 修复 |
| `backend/app/services/report_agent.py` | 报告 ReACT 生成 |
| `backend/scripts/run_parallel_simulation.py` | 双平台并行模拟脚本semaphore=100 |
### 前端
| 路径 | 用途 |
|---|---|
| `frontend/src/router/index.js` | 路由v0.3 新增 `/simulation/:id/replay` |
| `frontend/src/api/simulation.js` | 模拟相关 API client |
| `frontend/src/views/SimulationReplayView.vue` | **v0.3 新增** Manus 式回放主界面 |
| `frontend/src/views/SimulationView.vue` | 模拟运行界面 |
| `frontend/src/views/SimulationRunView.vue` | 模拟启动界面 |
| `frontend/src/views/ReportView.vue` | 报告查看 |
| `frontend/src/components/Step2EnvSetup.vue` | Step 2 环境设置v0.3 新增加速完成按钮 |
### 部署 / 运维
| 路径 | 说明 |
|---|---|
| `.env` | API Keys 与配置智谱 / Neo4j / SiliconFlow / HF mirror |
| `docker-compose.yml` | Neo4j 容器配置 |
| `~/.claude/projects/.../memory/` | M-flow 记忆系统索引OpenClaw 内部 |
### 服务器(远程)
| 路径 | 说明 |
|---|---|
| `/opt/foresight/backend/` | 后端代码 |
| `/opt/foresight/backend/.venv-311/` | Python 3.11 虚拟环境5.1G |
| `/opt/foresight/backend/uploads/simulations/sim_<id>/` | 单次模拟数据目录 |
| `/opt/foresight/backend/logs/server.log` | Flask 日志 |
| `/opt/foresight/.env` | 服务器配置 |
| `/etc/nginx/sites-enabled/foresight-api` | Nginx 反代配置 |
---
## 10. 已知限制与边界
| 限制 | 说明 | 缓解策略 |
|---|---|---|
| Agent 200双平台 2C8G | 超过会 OOM | 升级 4C16G / 单平台 / 拆分 batch |
| 国内平台未支持 | 当前只有 Twitter+Reddit | v0.4 P0 |
| 单租户 | 多客户共用一套数据 | v0.4 P2 |
| 子进程心跳缺失 | sim 挂了 state 仍是 running | v0.4 P3 |
| 报告生成 Token 消耗大 | 单次 80-150K | 优化 prompt / 缓存图谱搜索结果 |
| 重启 sim 需手动 reset state | 半死 state 阻塞下次启动 | v0.4 P3 force-restart 按钮 |
---
## 附录 Av0.3 关键运维教训
1. **Python 版本约束必须 pre-flight 检查**`requirements.txt` 改动后立刻验证 venv 兼容
2. **国内服务器装包必走腾讯云镜像**`uv pip install --index-url http://mirrors.tencentyun.com/pypi/simple --trusted-host mirrors.tencentyun.com`
3. **HuggingFace 模型必配 `HF_ENDPOINT=https://hf-mirror.com`**否则 OASIS 启动卡死
4. **遇到模拟卡死先看 simulation.log 最后 10 行**不要先猜 LLM
5. **8G 内存只能跑 200 agents 双平台**503 OOM 503 双平台需升级 16G
6. **重启 Flask 不再杀子进程**v0.3 修复后可以安全热更新代码
7. **GLM-4-Flash 是 OASIS 场景的最优 LLM**旗舰模型反而是反向优化每次调用 2-5s 太慢
## 附录 B决策日志
| 日期 | 决策 | 原因 |
|---|---|---|
| 2026-04-13 | Zep Cloud Graphiti+Neo4j | 脱离外部依赖 |
| 2026-04-14 | LLM GLM-4-Flash | MiniMax 速度不够 |
| 2026-04-14 | uv + Python 3.11 重建 venv | camel-oasis 不支持 3.12 |
| 2026-04-14 | 服务器升级 2C8G | 3.6G 跑不动 OASIS |
| 2026-04-14 | hf-mirror.com | 服务器连不上 huggingface |
| 2026-04-15 | 修复 SIGTERM 误杀 bug | 热更新后端不再中断模拟 |
| 2026-04-15 | 200 agents 设为甜点 | 8G 容量 + 95% 置信度足够 |
| 2026-04-15 | 上线 Manus replay UI | 给客户演示 + 复盘工具 |
| 2026-04-15 | v0.4 路线图国内平台 + SaaS | 用户战略需求 |
| 2026-04-16 | v0.3.3 CustomGraphBuilder 替代 Graphiti | Graphiti 兼容性死循环10+ patch 仍无法稳定 |
| 2026-04-16 | 一键部署脚本 deploy.sh | 手动 scp 反复漏文件accelerate 方法都没部署上 |
| 2026-04-16 | CDN SPA fallback 404302 | coscmd 部署后前端所有子路由 404 |
| 2026-04-16 | 图谱构建并发化 (10 workers) | 串行太慢10 分钟 2 分钟 |
| 2026-04-15 | v0.3.1 hotfix7 bug 修复 | 第一次完整 E2E 跑通压力测试 |
| 2026-04-15 | LLM client 加指数退避重试 + LLM fallback | GLM RPM 配额低retry 不够兜底 |
| 2026-04-15 | Replay UI 重构为 Manus cinematic 风格 | 三栏分析面板对客户演示不够"沉浸" |
| 2026-04-15 | semaphore 100 30 | 高并发触发 GLM 限流雪崩 |
## 附录 CGraphiti 弃用记录
v0.3.2 决定用自研 CustomGraphBuilder 替代 Graphiti以下是尝试修复 Graphiti 兼容性的完整过程
### 尝试过的 10 次 Patch
| # | 问题 | Patch 位置 | 结果 |
|---|---|---|---|
| 1 | Qwen 32B 32K context 超窗口 | ontology_generator MAX_TEXT=28000 | 但这不是主问题 |
| 2 | Neo4j TypeError 嵌套 dict | EntityNode.save monkey-patch | Graphiti 不走这条路径 |
| 3 | 同上 | bulk_utils.add_nodes_and_edges_bulk_tx | 也不走这条路径 |
| 4 | 同上 | neo4j AsyncSession.run driver | 终于拦到了 |
| 5 | Qwen 累积上下文爆 60-82K | chunk_size 500250 | 爆的是检索上下文不是 chunk |
| 6 | 同上 | Qwen 72B以为 128K | SiliconFlow 72B 也是 32K |
| 7 | 同上 | 换智谱 GLM-4-Flash 128K | GLM 20015 "parameter invalid" |
| 8 | GLM reranker logprobs 不支持 | patch reranker.rank() | 但不是主路径 |
| 9 | GLM embedder input | patch embedder.create_batch() | 但不是主路径 |
| 10 | GLM extract_nodes 全部 fail | 未找到根因 | 直接测能过生产必挂 |
### 为什么自研是正确决策
1. **Graphiti 为 OpenAI 设计**内部 4-5 LLM 调用路径各自有 OpenAI 特有参数logprobs / structured output / json_schema OpenAI provider 每条路径都是独立陷阱
2. **patch 层次太深**至少 5 EntityNode / bulk_utils / driver / reranker / embedder每层 fix 一个又冒下一个
3. **上下文累积不可控**Graphiti episode 检索机制会从已有图谱拉上下文后续 episode prompt 越来越长32K 模型必爆128K 模型也不是免费的
4. **每 chunk 4-5 次 LLM 调用**extract_nodes + dedupe_nodes + extract_edges + dedupe_edges + community_summary成本和延迟 4-5x
5. **CustomGraphBuilder 只需 1 次调用/chunk**直接 prompt JSON cypher MERGE完全受控
### CustomGraphBuilder 架构
```
输入: 完整文档文本 + ontology 定义
字符级切分 (250 chars, 50 overlap)
ThreadPoolExecutor (10 workers 并发)
↓ 每个 worker:
LLMClient.chat_json(extract prompt) ← 一次调用,自带 retry + fallback
↓ 返回:
{"entities": [...], "relationships": [...]}
串行 MERGE 到 Neo4j (去重 by name + group_id)
输出: {entities_count, edges_count, chunks_processed}
```
### 保留的 Graphiti 代码
`graphiti_client.py` 中的读取方法`get_all_nodes / get_all_edges / get_node / get_node_edges`仍然使用 Neo4j 直接查询**不依赖 Graphiti **。`add_episode / add_episodes_batch` 保留但不再被主流水线调用5 monkey-patch 保留作为安全网
## 附录 D部署流程
### 后端部署(最常用)
```bash
./scripts/deploy.sh # rsync + restart Flask + health verify
./scripts/deploy.sh --no-restart # 只同步代码不重启
```
### 前端部署
```bash
./scripts/deploy.sh --frontend # vite build + coscmd upload + CDN purge
```
### 全量部署
```bash
./scripts/deploy.sh --full # 后端 + 前端
```
### CDN SPA 配置(一次性)
```bash
tccli cdn UpdateDomainConfig --cli-unfold-argument \
--Domain foresight.yizhou.chat \
--ErrorPage.Switch on \
--ErrorPage.PageRules.0.StatusCode 404 \
--ErrorPage.PageRules.0.RedirectCode 302 \
--ErrorPage.PageRules.0.RedirectUrl "https://foresight.yizhou.chat/index.html"
```
### COS 配置
- Bucket: `foresight-1317962478`
- Region: `ap-guangzhou`
- 凭证: `~/.cos.conf`SecretId/SecretKey
- 工具: `coscmd`pip install