# **技术设计文档:工具 C \- 科研数据编辑器 (V7 云端沙箱抗风险版)** | 文档类型 | Technical Design Document (TDD) | | :---- | :---- | | **对应原型** | **工具C\_科研数据编辑器\_原型设计\_V6\_修复版.html** | | **版本** | **V7.1** (完整收录架构决策 ADR 与红队风险对策) | | **状态** | Final Standard | | **核心目标** | 构建一个高可靠的云端 Python 数据清洗平台。在保障“数据不出域”的前提下,通过 Apache Arrow 和样式分离技术,解决服务端执行带来的延迟与格式丢失问题。 | ## **1\. 总体架构设计 (System Architecture)** 鉴于文件大小限制 (\<20MB) 和脱敏前提,采用 “Node.js BFF \+ Python Microservice” 架构。 V7 核心升级: 引入 Apache Arrow 作为前后端数据交换标准,替代低效的 Excel 文件反复读写,将单次交互延迟从 8s 降低至 0.5s。 ### **1.1 架构拓扑图 (V7 优化版)** graph TD subgraph Client\_Layer \[用户端\] ReactApp\[React 19 \+ AG Grid\] ArrowClient\[Apache Arrow JS\] end subgraph Aliyun\_SAE \[阿里云 Serverless 应用引擎\] BFF\[Node.js Web 服务 (Fastify)\] PythonService\[Python 计算微服务 (FastAPI)\] end subgraph Cache\_Layer \[高速缓存层\] Redis\_Session\[Redis (存 DataFrame Arrow 序列化)\] end subgraph AI\_PaaS \[AI 能力层\] Dify\[Dify 编排引擎\] DeepSeek\[DeepSeek-V3 模型\] end subgraph Cloud\_Infra \[持久化层\] OSS\[对象存储 (存 Excel 底板)\] RDS\[RDS PostgreSQL (存元数据)\] end %% 交互流 User\[用户\] \--\>|1. 上传| BFF BFF \--\>|2. 存原始Excel| OSS BFF \--\>|3. 预热 Session| PythonService PythonService \--\>|4. 加载并转为 Arrow| Redis\_Session User \--\>|5. AI 指令| Dify Dify \--\>|6. Python 代码| BFF BFF \--\>|7. 发送代码| PythonService PythonService \--\>|8. 读取 Arrow (内存)| Redis\_Session PythonService \--\>|9. Pandas 执行| PythonService PythonService \--\>|10. 写回 Arrow| Redis\_Session PythonService \--\>|11. 返回 Preview 数据 (JSON/Arrow)| ReactApp User \--\>|12. 导出/保存| BFF BFF \--\>|13. 触发合并| PythonService PythonService \--\>|14. 读OSS底板 \+ 填入数据| OSS ## **2\. 关键架构决策记录 (ADR)** 本节记录了为何从“前端 Pyodide”转向“后端沙箱”的决策过程,供团队参考。 ### **决策点:前端运行 (WASM) vs 后端运行 (Server-side)** | 维度 | 方案 A:前端 Pyodide (WASM) | 方案 B:后端 Python (本方案) | 决策结论 | | :---- | :---- | :---- | :---- | | **启动延迟** | **极慢 (15s+)**。需下载 \~20MB 引擎包,用户体验极差。 | **秒开**。环境在服务器预热,即开即用。 | **后端胜** | | **交互延迟** | **极快 (\< 0.1s)**。本地内存操作,无网络开销。 | **中等 (0.5s)**。通过 Apache Arrow 优化后可接受。 | 前端胜 | | **稳定性** | **高风险**。浏览器 Tab 内存有限,易 OOM 崩溃。 | **高稳定**。服务器内存充足,容器隔离,崩溃不影响前端。 | **后端胜** | | **库支持** | **有限**。不支持部分 C 扩展库 (如复杂统计库)。 | **无限**。标准 Linux 环境,生态完整。 | **后端胜** | | **开发难度** | **极高**。需处理 JS-Python 通信、内存管理。 | **低**。标准 Web API 开发。 | **后端胜** | **结论:** 鉴于“数据已脱敏”且“文件较小”,**后端执行方案** 在稳定性、兼容性和开发成本上全面胜出。 ## **3\. 技术选型与融合 (Tech Stack Fusion)** ### **3.1 核心组件更新** | 领域 | 选型 | V7 新增理由 | | :---- | :---- | :---- | | **数据交换** | **Apache Arrow** | **关键升级**。用于 Python 和 Node.js/前端之间的高性能数据传输,避免 JSON 序列化开销,**解决 IO 延迟核心**。 | | **Excel 处理** | **openpyxl** | 替代纯 Pandas。用于在导出时**保留原始 Excel 样式**(如颜色、边框),**解决格式丢失核心**。 | | **会话缓存** | **Redis** | 用于暂存用户的 DataFrame (序列化为 Parquet/Arrow),避免每次操作都去 OSS 读文件。 | | **计算服务** | **FastAPI \+ Celery** | 引入 Celery 处理异步任务,防止长计算阻塞 HTTP 线程。 | ## **4\. 逆向风险评估与对策 (Red Teaming Analysis)** 本节详细记录了“红队测试”中发现的潜在致命风险及其工程化解决方案。 ### **风险一:交互延迟的“体感崩塌”** * **逆向拷问:** 每次 AI 操作都走 OSS 下载 \-\> Pandas 读取 \-\> 计算 \-\> 上传,单次耗时可能超过 8秒,用户无法忍受。 * **V7 解决方案:** **Session 驻留模式 (Memory-Resident)** 1. **初始化:** 用户上传 Excel 后,后端将其加载为 DataFrame,并序列化为 **Arrow** 格式存入 Redis (TTL 30min)。 2. **增量交互:** 前端发送指令,Python 从 Redis 读取 Arrow 数据(毫秒级),执行 Pandas 计算,将结果写回 Redis。 3. **轻量反馈:** 计算完成后,只返回 **前 100 行预览数据** 给前端 AG Grid 渲染。 4. **效果:** 耗时缩短至 **0.5s \- 1s**。 ### **风险二:Excel 格式丢失 (The Format Loss)** * **逆向拷问:** Pandas 的 to\_excel 会重置所有单元格样式,医生标注的颜色和批注会丢失。 * **V7 解决方案:** **底板分离策略 (Template Separation)** 1. **上传时:** 将原始 Excel 标记为 **"Style Template" (样式底板)**,永久保存在 OSS。 2. **计算时:** 只在内存/Redis 中处理纯数据 (Values),不关心样式。 3. **导出时:** 使用 openpyxl 加载“样式底板”,将内存中的新数据**填入**到底板的对应坐标中,保留未修改区域的背景色和批注。 ### **风险三:状态同步的“双写冲突”** * **逆向拷问:** 用户手动修改了第 5 行,同时 AI 删除了第 5 行,导致数据状态不一致。 * **V7 解决方案:** **UI 互斥锁 (UI Locking)** * 当 AI 正在生成代码或后端正在计算时,AG Grid 强制进入 **readOnly** 模式,并在界面显示 "AI 正在处理..." 遮罩,**物理层面上禁止并发操作**。 ### **风险四:安全沙箱逃逸** * **逆向拷问:** AI 生成了 import os; os.system('rm \-rf /')。 * **V7 解决方案:** **AST 静态分析 \+ 容器隔离** * **预检:** 在执行 exec() 前,使用 Python ast 模块扫描代码树,检测到 import os 等关键词直接抛出异常。 * **资源限额:** 使用 Python resource 模块限制单次执行的 CPU 时间 (10s) 和 内存 (1GB)。 ## **5\. 数据库设计 (元数据层)** 新增 TaskAudit 表用于记录每一次 AI 操作的上下文,便于回滚和审计。 model TaskAudit { id String @id @default(uuid()) datasetId String version Int // 操作后的版本号 actionType String // "AI\_CODE" or "MANUAL\_EDIT" prompt String? // 用户的自然语言指令 code String? // AI 生成的 Python 代码 executionTime Int // 执行耗时 (ms) status String // SUCCESS / FAILED createdAt DateTime @default(now()) } ## **6\. API 接口定义 (V7 优化)** * POST /api/session/init: 上传文件,初始化 Redis Session,返回 sessionId。 * POST /api/session/execute: * **Input:** { sessionId, code, version } * **Output:** { previewData: ArrowBase64, newVersion: int, logs: string } * **说明:** 仅返回预览数据,不生成 Excel 文件。 * POST /api/session/save: * **Input:** { sessionId } * **Output:** { downloadUrl } * **说明:** 触发 openpyxl 合并逻辑,生成最终 Excel 并上传 OSS。 ## **7\. 开发分工建议** * **Python 组 (重中之重):** * 实现 Arrow \<-\> Pandas 的序列化逻辑。 * 封装 openpyxl 的样式回填逻辑。 * 搭建 FastAPI \+ Redis 环境。 * **Node.js 组:** * 负责 Dify 转发和鉴权。 * **前端组:** * 集成 apache-arrow JS 库,解析后端返回的二进制流并在 AG Grid 展示。 * 实现“AI 处理中”的全屏锁定交互。