系统架构全面评审 - 最终方案与改造路线图
评审对象: Tier6-Model v2.4.4 文档日期: 2026-03-06
一、整体评价
Tier6-Model 的整体架构是合理的。分层后端(L0-L5)清晰、FastAPI+SQLAlchemy 组合成熟、前端 shadcn/ui 组件一致性好。项目在功能实现上已相当完整(并行策略搜索、精评估引擎、实时 Gantt、成本分析)。
问题集中在两个区域:
- 后端有两处数据可靠性风险(双 ORM + 内存泄漏),需立即修复。
- 前端有技术债积累(死依赖、超长文件、全量挂载),应按节奏偿还。
二、前端页面清单(完整)
| # | 页面 | 路由名 | 功能完整度 | 问题 |
|---|---|---|---|---|
| 1 | Dashboard | dashboard | 基本完整 | 无严重问题 |
| 2 | TopologySetup | topology | 功能丰富 | 文件超 400 行 |
| 3 | DeploymentAnalysis | deployment | 完整 | 轻微(状态提升过度) |
| 4 | Results | results | 完整 | 文件超 400 行,state 过多 |
| 5 | Knowledge | knowledge | 基本完整 | 无严重问题 |
| 6 | ThemeLab | theme-lab | 开发调试态 | 应从生产构建移除 |
三、前后端模块清单(完整)
前端模块
frontend/src/
├── pages/ 6 个页面
├── layouts/ MainLayout (Sidebar + 全量挂载容器)
├── contexts/ 5 Context + WorkbenchContext 聚合
├── components/
│ ├── ConfigPanel/ 部署分析配置(最复杂,10+ 子组件)
│ ├── Scene3D/ Three.js 3D 渲染
│ ├── TopologyGraph/ 2D 力导向图
│ ├── KnowledgeGraph/ 知识图谱
│ ├── ui/ shadcn/ui 基础组件
│ └── common/ 通用组件
├── api/ HTTP 客户端分域模块
├── hooks/ 自定义 hooks(WebSocket、定时器、布局等)
├── utils/
│ ├── llmDeployment/ 核心计算工具(types, presets, backendApi, scoreCalculator...)
│ └── topologyGenerator/ 拓扑生成工具
├── workers/ knowledge-graph-worker.ts(Web Worker)
└── data/ 静态知识图谱数据
后端模块
backend/perf_model/
├── main.py FastAPI 应用入口
├── L0_entry/ 入口层
│ ├── api/ 7 个路由模块
│ ├── database.py [主] 新版 ORM(WAL SQLite)
│ ├── storage/ [废弃] 旧版 ORM,应删除
│ ├── tasks.py 内存任务队列(ThreadPoolExecutor)
│ ├── engine.py L1-L5 集成调度
│ ├── compat.py 格式转换层(Gantt/Stats 兼容)
│ ├── config_loader.py YAML 配置加载
│ ├── config_schema.py Pydantic 模型(30+ 个)
│ └── websocket.py WebSocket 广播
├── L1_workload/ 模型/算子定义层
├── L2_arch/ 硬件抽象层
├── L3_mapping/ 并行映射层
├── L4_evaluation/ 评估引擎层(math + g5 双路径)
└── L5_reporting/ 结果格式化层
configs/
├── chips/*.yaml 芯片预设
├── models/*.yaml 模型预设
├── topologies/*.yaml 拓扑预设
└── benchmarks/*.json 测试场景
四、框架与库评估
前端框架评估
| 技术栈 | 评级 | 说明 |
|---|---|---|
| React 18 + TypeScript 5 | A | 合理,与项目规模匹配 |
| Vite 6 | A | 构建工具合理,分 chunk 配置已完成 |
| shadcn/ui + Tailwind | A | 组件一致性好,定制灵活 |
| react-router-dom v7 | F | 安装但零使用,死依赖 |
| three.js + @react-three/fiber | A- | 3D 场景确实需要,lazy 加载已配置 |
| echarts 6 | C+ | 功能强但体积大(~3MB),仅用于 KPI 图表可降级为 recharts |
| d3-force + react-force-graph + react-force-graph-2d | C | 三个力导向相关库,功能高度重叠 |
| flame-chart-js | B+ | Gantt 图无简单替代,保留合理 |
| @tanstack/react-table | B+ | 结果表格使用合理 |
| @dnd-kit | B | 参数拖拽排序,合理 |
| katex | B | 公式展示,合理 |
| Context API(5个Context) | B- | 适合中等规模,但嵌套层级深,可考虑 Zustand |
后端框架评估
| 技术栈 | 评级 | 说明 |
|---|---|---|
| FastAPI + uvicorn | A | 合理,async 路由利用充分 |
| Pydantic v2 | A | 请求验证严格,类型安全 |
| SQLAlchemy 2.0 | A | ORM 合理,WAL 模式配置正确 |
| SQLite(WAL 模式) | B+ | 开发/小规模生产足够,高并发需 PostgreSQL |
| ThreadPoolExecutor 任务队列 | C+ | 内存态,重启丢失任务;不支持分布式 |
| WebSocket + asyncio.Queue | B | 实时推送实现正确,心跳逻辑完善 |
| pyyaml | A | 配置加载合理 |
| 无测试框架 | D | 缺失,需补充 pytest + httpx |
五、问题汇总与优先级
| 问题 | 优先级 | 类别 | 说明 |
|---|---|---|---|
| P0-1: 双 ORM 数据库文件分叉 | P0 | 数据安全 | 旧库与新库并存,两个 DB 文件 |
| P0-2: executor config 更新不生效 | P0 | Bug | PUT 接口静默无效 |
| P0-3: _temp_imports 内存泄漏 | P0 | 稳定性 | 导入 session 从不清理 |
| P1-1: calculate_model_params 使用默认值 | P1 | 规则违反 | config-loading.md |
| P1-2: config_snapshot 向后兼容字段 | P1 | 规则违反 | no-backward-compat.md |
| P1-3: Results/index.tsx 超行 | P1 | 规则违反 | code-style.md,473 行 |
| P1-4: TopologySetup/index.tsx 超行 | P1 | 规则违反 | code-style.md,456 行 |
| P2-1: react-router-dom 死依赖 | P2 | 可维护性 | 移除或使用 |
| P2-2: 全量页面挂载 | P2 | 性能 | 内存浪费,初始化慢 |
| P2-3: Provider 嵌套重渲染 | P2 | 性能 | 高频状态变化时退化 |
| P2-4: 可视化库重叠冗余 | P2 | Bundle 大小 | d3+react-force-graph 两套 |
| P2-5: ThemeLab 暴露在生产 | P2 | 工程质量 | 应条件编译或删除 |
| P2-6: storage/ 旧 ORM 残留 | P2 | 可维护性 | 应删除整个目录 |
| P2-7: 任务队列内存态 | P2 | 可靠性 | 重启丢失任务 |
| P3-1: DATABASE_URL 有 fallback | P3 | 规则边界 | 轻微违反 config-loading |
| P3-2: localStorage 键名不统一 | P3 | 文档一致性 | CLAUDE.md 与代码不符 |
| P3-3: TopologySpec 默认值 | P3 | 规则边界 | 配置加载的默认值问题 |
| P3-4: 无自动化测试 | P3 | 工程质量 | 长期欠债 |
六、可替代方案
方案 A: 页面路由替换(中优先级)
当前方案: CSS 全量挂载 + viewMode 切换 替代方案: React Router v7(已安装)
优点:
- URL 可分享(如直接打开 /results?experiment=123)
- 浏览器前进/后退可用
- 非活跃页面真正卸载,节省内存
- react-router-dom 有效利用,消除死依赖
缺点与应对:
- 知识图谱节点坐标丢失 -> 用 zustand persist / sessionStorage 序列化力导向状态
- 拓扑编辑进度丢失 -> URL 或 context 持久化
- 部署评估进度丢失 -> 已有 WebSocket + 后端轮询,恢复容易
工作量估计: M(1-2 周)
风险: 低(路由已装,无外部依赖变更)
方案 B: 状态管理升级(低优先级)
当前方案: 5 个 React Context 嵌套 替代方案: Zustand(扁平化 store)
优点:
- 消除 Provider 嵌套导致的级联重渲染
- 更好的 TypeScript 推断
- 持久化插件(zustand/middleware/persist)可替代 localStorage 手工同步
缺点:
- 迁移工作量大,当前 Context 分层已较清晰
- 对大多数场景性能影响不显著
工作量估计: L(2-3 周)
风险: 中(状态迁移可能引入回归)
建议: 不急于迁移,除非性能问题可测量
方案 C: 图表库瘦身(低优先级)
当前方案: echarts 6 + d3-force + react-force-graph + react-force-graph-2d 替代方案:
- 将 KPI 图表从 echarts 迁移到 recharts(gzip 后小 ~1MB)
- 合并 react-force-graph + react-force-graph-2d 为 react-force-graph-2d(统一 2D 力导向)
工作量估计: M(1 周)
收益: 减少 bundle ~1-1.5MB
风险: echarts API 与 recharts 差异较大
方案 D: 任务队列持久化(中优先级)
当前方案: 内存 ThreadPoolExecutor 替代方案: SQLite-backed 任务队列(无需引入 Redis)
# 思路:在提交时写入 pending 状态到 EvaluationResult,
# 服务启动时扫描 pending 任务重新提交
class PersistentTaskQueue:
def submit(self, ...):
# 1. 先写 DB status=pending
# 2. 提交到 executor
# 3. 完成后更新 DB status=completed
def recover_on_startup(self):
# 扫描 status=running/pending 的记录,标记为 failed
工作量估计: S(3-5 天)
收益: 重启不丢任务历史(但正在运行的任务仍会中断)
风险: 低
七、改造路线图
Phase 0 — 立即修复(P0,本周内)
优先级最高,不应等待任何其他工作。
0.1 删除旧 storage/ ORM 模块
- 删除
backend/perf_model/L0_entry/storage/目录 - 检查所有 import,确保无代码引用旧模块
- 影响:消除双数据库文件风险
- 回滚:git revert,旧代码无用户依赖
0.2 修复 executor config 更新
PUT /evaluation/config应重建 ThreadPoolExecutor 或明确返回 400 说明"需重启生效"- 最简实现:添加响应字段
"requires_restart": true并记录日志,消除用户误解
0.3 _temp_imports 加 TTL 清理
- 给
_temp_imports的每个 entry 加入写入时间戳 - 每次 GET 操作触发过期清理(简单 LRU,TTL = 30 分钟)
- 或改用
tempfile.NamedTemporaryFile写磁盘,进程退出自动清理
Phase 1 — 规则合规修复(P1,本月内)
1.1 Results/index.tsx 拆分
将 473 行的 Results 页面重构为:
pages/Results/
├── index.tsx (~60 行,仅视图切换逻辑)
├── hooks/
│ ├── useExperimentList.ts (实验列表加载、搜索、分页、批量删除)
│ ├── useImportFlow.ts (导入多步流程状态)
│ └── useEditState.ts (内联编辑状态)
└── components/ (已存在,继续利用)
1.2 TopologySetup/index.tsx 拆分
将 456 行拆分为:
pages/TopologySetup/
├── index.tsx (~80 行,仅容器+布局)
├── hooks/
│ ├── useSiderResize.ts (拖拽宽度逻辑)
│ └── useNodeSelection.ts (节点/链路选中逻辑)
└── NodeDetailCard.tsx (节点详情 + 连接详情卡片,~100行)
1.3 config_snapshot 去重字段
- 删除
tasks.py中的"topology"别名字段 - 前端统一使用
topology_config键名读取 - 联动修改
results.ts中的字段读取逻辑
1.4 calculate_model_params 明确豁免或补全 ValueError
- 方案 A(推荐):在函数顶部添加注释
# 此端点为辅助估算工具,intentionally 使用 defaults并在.claude/rules/config-loading.md中补充豁免场景 - 方案 B:改为必填参数,缺失时 raise ValueError
Phase 2 — 技术债清偿(P2,下季度)
优先级建议:2.6 > 2.1 > 2.5 > 2.2 > 2.4 > 2.3
2.1 移除 react-router-dom 死依赖(或升级为使用它)
如不打算迁移路由:
pnpm remove react-router-dom
如计划迁移路由(推荐):
- 参考方案 A,引入 React Router v7
- 估算:1-2 周,收益明显
2.2 全量挂载改为按需渲染
最小侵入方案(保留知识图谱状态):
// 仅知识图谱保持挂载,其他页面路由懒加载
<Routes>
<Route path="/" element={<Navigate to="/dashboard" />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/topology" element={<TopologySetup />} />
<Route path="/deployment" element={<DeploymentAnalysis />} />
<Route path="/results" element={<Results />} />
<Route path="/knowledge" element={<Knowledge />} />
</Routes>
// 知识图谱如需保持状态,用 display:none 单独处理
2.3 WorkbenchContext 性能优化
短期修复(无需迁移 Zustand):
- 将高频
viewMode变化通过ViewModeContext(已存在)直接消费,不经 WorkbenchContext - 在 WorkbenchInner 中用
useMemo细化各子对象
2.4 可视化库整合
- 移除
react-force-graph(3D 版),仅保留react-force-graph-2d - 评估 echarts → recharts 可行性(KPI 图表、Roofline 图)
2.5 ThemeLab 改为条件编译
// vite.config.ts 提供 VITE_ENABLE_THEME_LAB 标志
{import.meta.env.VITE_ENABLE_THEME_LAB && <ThemeLab />}
2.6 删除 storage/ 旧 ORM(若 Phase 0.1 未一并完成)
2.7 任务队列持久化(可选)
- 参考方案 D,服务启动时将
running状态任务标记为failed - 用户可手动重试,比默默丢失任务好
Phase 3 — 长期改善(P3,按需)
- 补充 pytest 测试:至少覆盖 engine.py、config_loader.py、compat.py 关键路径
- 补充 vitest 前端测试:至少覆盖 scoreCalculator、topologyGenerator 工具函数
- 升级 SQLite → PostgreSQL(当并发用户 > 10 时)
- 统一 localStorage 键名,更新 CLAUDE.md 文档
- TopologySpec 添加 from_config() 工厂方法,去除字段默认值
八、风险与回滚计划
| 改造 | 主要风险 | 回滚方式 |
|---|---|---|
| Phase 0.1 删除旧 ORM | 某处代码仍隐式 import 旧模块导致启动失败 | git revert,影响单个 commit |
| Phase 0.3 _temp_imports TTL | 实现有 bug 导致 import session 被提前清理 | 恢复原无 TTL 逻辑 |
| Phase 1.1/1.2 文件拆分 | hook 边界划分不当导致状态 prop drilling | 特性分支隔离,逐步合并 |
| Phase 1.3 去重字段 | 前端读取旧字段的路径未全部找到 | 用 Grep 全扫后操作,missing 字段会在 TS 编译期报错 |
| Phase 2.2 迁移路由 | 知识图谱节点坐标丢失 | 先 flag 保留旧方案,路由仅用于非知识图谱页面 |
| Phase 2.4 替换 echarts | 图表样式/功能差异 | 保留 echarts 仅替换非关键图表验证 |
九、执行顺序建议
立即(本周):
[x] P0-1: 删除 storage/ 旧 ORM 目录(防数据分叉)
[x] P0-2: executor config 接口明确语义(防用户误解)
[x] P0-3: _temp_imports 加 TTL(防内存泄漏)
近期(本月):
[ ] P1-1/1.2: 豁免 calculate_model_params 规则 or 补 ValueError
[ ] P1-2: 删除 config_snapshot 中 topology 别名字段
[ ] P1-3: Results/index.tsx 拆分(hooks 提取)
[ ] P1-4: TopologySetup/index.tsx 拆分(NodeDetailCard 提取)
中期(下季度):
[ ] P2-1: 决策是否引入 React Router(或移除死依赖)
[ ] P2-5: ThemeLab 条件编译保护
[ ] P2-6: storage/ 清理(若未随 P0-1 一并完成)
长期(按需):
[ ] P2-2: 全量挂载 -> 路由懒加载
[ ] P2-4: 图表库整合
[ ] P3-4: 补充自动化测试
十、结论
Tier6-Model 是一个功能覆盖完善、架构分层清晰的专业平台,主要问题集中在工程规范合规性和少量正确性风险。
- 不需要大型重构:L0-L5 分层、Context 拆分、shadcn/ui 组件体系均属正确决策。
- 需要立即处理的是 P0 的三个正确性/稳定性问题,其余可按节奏推进。
- 最高性价比的长期改善是引入 React Router v7(已安装)替代全量挂载方案,可同时解决 P2-1(死依赖)+ P2-2(内存浪费)+ 用户体验(URL 可分享)三个问题。