RESEARCH WORKSPACE / DESIGN & ENGINEERING
从问题到可重跑的研究项目
个人版网页科研智能体:设计、开发与运维指南
面向构建数理理论与大数据研究工具的开发者。目标是帮助一位研究者完成有边界的工作:整理问题与数据,编写并运行计算,修改结果,导出可以继续使用的项目。全文是一份参考设计,不表示 Exobrain 已经实现这些能力。
个人版指每个项目由一位用户拥有。一个公开服务仍可能服务许多个人账号,因此身份校验、用户数据隔离和资源预算不能省略。本文不设计团队角色、多人共同编辑或企业审批流程。
先把一项真实研究任务做完整,再把反复出现的步骤沉淀成产品。
01Persona:两类研究者,一条工作路径
从具体任务定义 persona,比从“科研人员”这个宽泛标签开始更实用。
| 用户 | 带来的材料 | 希望得到的结果 |
|---|---|---|
| 数理理论研究者 | 方程、参数、假设、一小段 Python | 参数扫描、数值解、误差分析、可编辑图表 |
| 数据研究者 | CSV/Parquet、数据字典、一个分析问题 | 数据概览、清洗脚本、统计结果、可重跑报告 |
例如,前者研究一个动力系统在不同参数下的轨迹,后者分析一批观测数据中的分组差异。两者都需要控制假设和参数,而不是只收到一段看似合理的解释。
正在绘制图形,下方可查看源码。
查看 Mermaid 源码
flowchart TD
T[数理研究者:方程与参数] --> P[创建个人项目]
D[数据研究者:数据与问题] --> P
P --> I[上传文件或编辑 Markdown / Python]
I --> C[确认目标、输入与资源预算]
C --> A[Agent 提出计算方案]
A --> H{用户是否接受方案}
H -->|修改| C
H -->|接受| R[运行计算并展示进度]
R --> V[查看图表、代码、错误与运行记录]
V --> E{继续修改还是导出}
E -->|改参数或代码| I
E -->|导出| X[下载可重跑的研究项目]图中的确认点只放在需要人判断的地方。已授权范围内的普通计算可以连续执行;扩大预算、上传数据到新目的地或覆盖重要产物,应重新确认。错误后保留输入和日志,让用户继续工作。
第一阶段不接湿实验设备,不承诺自动科研发现,也不要求把论文转换成形式化证明。优先交付一个能修改、能重跑的计算任务。
02界面:聊天旁边必须有工作对象
建议采用三个区域:项目文件、对话与任务进度、编辑器与结果预览。小屏幕可切换区域,不强塞三个窄栏。
聊天负责解释意图;文件记录实际工作;运行记录说明哪些代码产生了哪些结果。用户手动修改脚本后,下一轮 agent 必须读取当前文件版本,不能只依赖旧聊天上下文。
assistant-ui 的位置
assistant-ui 的 ExternalStoreRuntime允许应用保留自己的消息状态,通过适配器连接聊天组件。对于已有 Python 后端、已有消息流的 Exobrain,这是比整体重写更小的试验范围。
先接通发送、流式输出、停止、失败重试、文件引用与工具结果,再考虑更丰富的交互。项目文件和执行结果仍由应用维护。使用 LangGraph 库并不自动具备其服务端 API,不能假设任意 LangGraph UI 适配器都可直接接入。
编辑与接受改动
Markdown 与 Python 编辑器可以分别使用成熟的文本编辑组件;初期无需实现完整 IDE。agent 输出候选文件,界面显示差异,用户按文档接受或拒绝。记录候选文件基于哪个旧版本;如果用户已经改过原文件,就提示冲突。
一次变更同时修改脚本和参数时,可以整批接受。恢复旧版本应创建一次新的版本记录,避免抹掉后续修改。逐行接受、实时共同编辑和任意 Notebook 内核,都可以后置。
事件协议先于漂亮气泡
建议消息流至少区分 message、tool_started、tool_finished、artifact_created、run_status、error。每条持久事件有 run_id 与递增 seq。SSE 重连时按 seq 补发,前端去重;断开浏览器连接不等于取消计算。取消必须走独立接口,并传到 worker 与执行环境。
03架构:把网页服务和计算分开
一个可运营的最小系统可以有五部分:网页、API、后台 worker、数据库、对象存储。模型和隔离计算环境通过供应商适配层接入。
正在绘制图形,下方可查看源码。
查看 Mermaid 源码
flowchart TD
U[浏览器:assistant-ui / 编辑器 / 图表] -->|HTTPS / SSE| API[API:身份、项目、任务、事件]
API --> DB[(PostgreSQL:项目 / 版本 / 任务 / 事件)]
API --> Q[持久任务队列]
Q --> W[Worker:LangGraph 编排]
W --> DB
W --> L[模型适配器 → LLM 服务]
W --> S[Runner 适配器 → 隔离 CPU 沙箱]
W --> B[批任务适配器 → GPU / 大内存计算]
S -->|限定输入与输出| O[(对象存储:数据 / 脚本 / 产物)]
B -->|分区数据与结果| O
API -->|授权上传与下载| O
W -->|任务状态与资源统计| M[日志 / 指标 / 告警]
J[定期清理与超时回收] --> S
J --> B
J --> DB队列是逻辑职责,不一定要新增 Redis。低并发时可以用 PostgreSQL 任务表配合租约和安全领取机制;任务规模扩大后再换专门队列。API 与 worker 可以共用代码仓库,但长时间计算不应占住网页请求。
执行器只获得当前任务允许的文件与短时访问凭据。数据库连接、完整对象存储密钥和模型供应商管理密钥留在控制服务中。个人版项目也要按登录用户校验所有文件、任务和下载请求。
最小接口
| 接口示意 | 职责 |
|---|---|
| POST /projects | 创建个人项目 |
| POST /projects/:id/uploads | 校验归属,签发限定对象的上传地址 |
| POST /projects/:id/runs | 冻结输入版本、记录预算,返回 run_id |
| GET /runs/:id/events?after=seq | 获取持久事件并接续 SSE |
| POST /runs/:id/cancel | 请求取消,直到执行器确认后进入终态 |
| POST /artifacts/:id/versions | 带 base_version 保存新版本,拒绝静默覆盖 |
| GET /runs/:id/export | 生成下载包或返回异步打包任务 |
这些是设计契约,不是现有 Exobrain API。创建运行带幂等键,避免页面重试意外启动两份昂贵计算。
04ER:文件、聊天和运行分别保存
聊天是解释与交互记录。Artifact 是逻辑文件;ArtifactVersion 是它的一份不可变内容。Run 则是一轮实际执行,必须引用具体输入版本,而不是一个会继续变化的文件名。
正在绘制图形,下方可查看源码。
查看 Mermaid 源码
erDiagram
USER ||--o{ PROJECT : owns
PROJECT ||--o{ THREAD : contains
THREAD ||--o{ MESSAGE : contains
PROJECT ||--o{ ARTIFACT : contains
ARTIFACT ||--|{ ARTIFACT_VERSION : has
THREAD ||--o{ RUN : starts
RUN ||--o{ RUN_EVENT : emits
RUN ||--o{ RUN_ARTIFACT : records
ARTIFACT_VERSION ||--o{ RUN_ARTIFACT : referenced_by
USER {
uuid id PK
}
PROJECT {
uuid id PK
uuid owner_id FK
string title
}
THREAD {
uuid id PK
uuid project_id FK
}
MESSAGE {
uuid id PK
uuid thread_id FK
json content_parts
}
ARTIFACT {
uuid id PK
uuid project_id FK
string logical_path
}
ARTIFACT_VERSION {
uuid id PK
uuid artifact_id FK
string object_key
string content_hash
}
RUN {
uuid id PK
uuid thread_id FK
string status
json execution_spec
}
RUN_EVENT {
uuid run_id FK
int seq
json payload
}
RUN_ARTIFACT {
uuid run_id FK
uuid version_id FK
string role
}约束比字段数量重要:RUN_EVENT 的 (run_id, seq) 唯一;RUN_ARTIFACT 的 role 区分 input、output 与 log;同一关联里的运行与文件必须属于同一个项目。Artifact 的逻辑路径在项目内唯一。跨用户访问必须在服务端拒绝,不能依赖前端隐藏按钮。
execution_spec 保存环境镜像摘要、模型配置、提示词版本、参数、种子、资源上限和供应商任务标识。大型数据、日志正文与图像放对象存储,数据库只存索引和引用。聊天摘要用于节省上下文,但不能代替运行证据。
这里没有 team、membership 或企业角色表。未来是否引入这些对象,取决于真实需求。
05LangGraph:围绕一次有边界的运行
图的状态应是可序列化的任务数据,例如 project_id、run_id、input_versions、task_kind、plan、budget、attempt、job_id、outputs 与 error。不要把数据库连接或供应商密钥放进 checkpoint。
正在绘制图形,下方可查看源码。
查看 Mermaid 源码
flowchart TD
A[START:读取项目与输入版本] --> B{信息是否足够}
B -->|否| C[请求澄清 / interrupt]
C -->|用户补充后 resume| A
B -->|是| D{需要指定资料吗}
D -->|已收录| E[按需检索]
D -->|不需要| F[生成回答或计算方案]
D -->|未收录| G[说明来源缺口]
G --> C
E --> F
F --> H{是否需要执行}
H -->|否| Z[保存回复与引用 / END]
H -->|是| I[校验工具、参数、预算与能力]
I --> J{需要用户批准吗}
J -->|是| K[interrupt:等待批准]
K -->|批准| L[幂等提交计算任务]
K -->|拒绝| X[取消 / END]
J -->|已授权| L
L --> M[持久化 job_id / 等待结果]
M --> N{执行结果}
N -->|成功| O[检查输出并保存产物]
N -->|可修复且有剩余预算| P[增加 attempt / 修正代码]
P --> I
N -->|不可恢复或预算耗尽| Y[保存错误与部分产物 / END]
O --> Z这是建议流程,不是现有 Exobrain graph 的导出。计算任务返回后还需检查空文件、NaN、数据列、样本数、单位或数值收敛等;程序退出码为零只是其中一个信号。
LangGraph persistence支持保存运行状态,interrupts用于暂停等待外部输入。生产环境需要持久化 checkpointer 和稳定的 thread_id;调用 compile 本身不会自动完成部署与恢复设计。
人工暂停应发生在产生副作用之前。恢复可能重跑节点,因此提交计算、创建文件版本等操作要用 run_id 与步骤标识去重。checkpoint 中保存远程 job_id,重启后查询原任务,避免重新创建。
不要同时让托管 agent 与自己的 graph 都无限重试同一件事。选择一个层负责迭代与预算控制,另一层通过明确的任务契约接入。
06简单选型:先选职责,再选品牌
LLM:一主一备,按任务选能力
| 用途 | 起步选择 | 关注点 |
|---|---|---|
| 任务分类、来源判断 | 轻量、低延迟模型,简单规则先行 | 输出结构稳定,错误时能澄清 |
| 方案与代码生成 | 工具调用和代码能力较好的主模型 | 当前任务完成率、修改次数、延迟与总成本 |
| 难题处理 | 明确触发后升级模型或思考预算 | 上限可控,不把每轮聊天都升级 |
| 检索向量 | 与语言、领域和索引匹配的 embedding | 模型变化需要兼容或重建索引 |
起步只接一个实际可用的模型供应商,记录模型标识和配置;确有稳定性需求再加备选。OpenAI、方舟或百炼都可以是候选,选择取决于可用地区、数据要求、工具调用兼容性和自己的任务样例,不在本文给出永久排名。
大模型处理数据字典、抽样、聚合结果与必要文件片段。不要把整张大表塞进上下文。模型输出的工具参数由服务端校验,不能由提示词替代执行边界。
UI、存储与编排的建议起点
| 层 | 建议起点 | 暂缓 |
|---|---|---|
| Web UI | React + assistant-ui 适配现有消息流 | 重写整个 workspace |
| 编辑 | Markdown / Python 文本编辑与文件级 diff | 逐行合并、完整 IDE |
| 后端 | Python API + 独立 worker | 多个语言重复实现同一工具 |
| 编排 | 有分支与暂停需求时采用 LangGraph | 为每个函数都创建 agent |
| 数据 | PostgreSQL + S3 兼容对象存储 | 大文件写数据库或 Git |
| 检索 | 只有明确资料需求才建索引 | 对所有问题强制 RAG |
执行环境:microVM 是隔离选项
Vercel Sandbox官方说明使用 Firecracker microVM;E2B提供可编程沙箱;Railway Sandboxes提供隔离执行环境。部署在 Railway 的 API 可以通过供应商 SDK 调用外部执行服务,不必与网页同一个进程或机器。
选择前用自己的 Python 依赖和文件任务验证:启动时间、内存、绝对超时、网络策略、文件回传、失败清理、地区与计费。不要仅凭“沙箱”二字认定隔离技术相同;百炼 Managed Agents 文档描述的是云端容器环境,也不能自动当作 microVM。
个人产品通常没有必要自己运维 Firecracker 宿主集群。优先使用成熟服务,但把 create、execute、status、cancel、collect、destroy 收敛到自己的小接口,保存可导出的文件与运行记录。
07科学环境与大数据:运行前知道能力
依赖分层,避免一个镜像包办所有任务
SciencePro 在研究者提供的对话中自述预装了大量 Python 包。该清单是单次会话的自述,本文未独立核验版本或数量。它提醒我们:包数量不等于任务能力,更不等于 GPU 可用。
建议起步准备三个环境规格,按任务选择并固定版本:
- 基础 CPU: SymPy、NumPy、SciPy、pandas、matplotlib,完成符号、数值与小中型数据分析。
- 数据分析: 按需要加入 DuckDB、Arrow/Parquet、Polars,优先列裁剪、过滤、分批与磁盘执行。
- 深度学习: 按任务选择 PyTorch 或其他框架,区分 CPU 与 GPU 环境,避免默认装齐所有大型框架。
这些是包类别建议,不是已验证的兼容版本组合。发布镜像前运行依赖解析、导入测试和代表性计算,记录锁文件与镜像摘要。不能假设数百个包在同一环境中长期兼容。
没有 GPU,深度学习库仍然可以工作
PyTorch、TensorFlow 可以执行 CPU 运算、小模型推理与小规模训练。GPU 主要改变可承担的工作量和速度。nvidia-smi 失败可能来自工具缺失、驱动或设备不可见;它不说明所有 GPU 后端、其他运行规格或整个平台都不存在 GPU。
更好的产品设计是由受信任的运行器发布一份经过探测的能力清单。以下字段和值仅为示意:
{
"environment": "science-cpu-v1",
"python": "pinned-by-image",
"accelerator": "cpu",
"memory_mb": 4096,
"max_runtime_seconds": 300,
"internet": "restricted",
"packages_manifest": "sha256:...",
"tools": { "python": true, "lean": false }
}
硬件分配与框架能否使用硬件要分别检查,例如 PyTorch 的 CUDA 可用性、实际的小算子运行和驱动兼容性。未知状态就写 unknown,不由 LLM 编造。
研究者需要知道自己获准使用的 CPU/GPU、内存和工具状态,不需要宿主内部地址或密钥。提供受限诊断工具比靠系统提示词禁止谈论配置更可靠。一次对话愿意回答环境问题,也不能据此判定发生了越权或沙箱逃逸。
大数据需要移动计算,而不是把数据塞进聊天
先读取 schema、行数估计、缺失率和小样本,再生成计算计划。数据以分区 Parquet 等形式保留在对象存储;计算尽可能靠近数据。对超过单机内存的任务,使用磁盘执行、分块处理或提交外部批任务,避免直接全量加载到 pandas。
长时 GPU/大内存任务走单独的批任务接口,返回 job_id,让用户离线后任务仍可查询。普通聊天沙箱不能因为装了 torch 就承担大模型训练。上传、下载、解压与输出均有大小限制;数据传输、对象存储和失败重试也计入成本。
08开发与运维:让失败可恢复
从一个垂直闭环开始:上传一个小数据集 → 生成并编辑脚本 → 在 CPU 环境运行 → 展示结果 → 修改参数重跑 → 导出。先不要同时建设 GPU 平台、团队协作和自动论文写作。
运行状态是产品的一部分
建议状态包括 queued、running、waiting_user、succeeded、failed、cancelled、timed_out。cancel_requested 可以作为过渡状态;只有远端停止确认后才显示已取消。worker 用心跳和租约表明自己仍在处理;租约失效后先核对远端 job,再决定恢复或终止。
| 失效场景 | 产品行为与工程处理 |
|---|---|
| SSE 断开 | 显示重新连接,按事件序号补发,不重复创建任务 |
| worker 重启 | 从持久状态恢复,查询已有远端 job |
| 代码出错 | 保存 stderr 和脚本版本,有限次数修复后交给用户 |
| 超时或预算耗尽 | 停止新调用,取消执行器,保存可用的部分产物 |
| 产物回传失败 | 保留暂存引用,在限定期限内重试收集 |
| 沙箱遗留 | 定期回收器按任务终态与绝对期限清理 |
最小可观测性
结构化日志统一携带 request_id、project_id、run_id、step 与 provider_job_id。记录队列等待、模型调用时长、计算时间、token 用量、退出码和产物大小。默认不记录完整私有数据、密钥或未经筛选的提示词。
告警先覆盖队列积压、异常失败率、超时任务、孤立沙箱与预算耗尽。诊断时应能从一条失败运行追到模型、执行器和文件版本;采用哪一种追踪平台是后续选择。
发布前要验证的完整路径
用少量固定任务覆盖正常计算、语法错误、依赖缺失、超时、用户取消、浏览器重连与 worker 重启。对有明确答案的数值任务设置容差,对数据分析检查样本数与列类型。它们验证系统行为,不宣称自动认证科学结论。
开发与生产分开配置;数据库迁移保持兼容;提示词、模型配置和镜像版本可以回退。备份数据库和重要对象,并实际测试恢复。成本预算同时限制模型、运行时长、并发、存储与外部传输,不能只统计 token。
默认关闭任意外网访问,确有需要时按目的地授权;依赖尽量在镜像构建阶段安装。代码执行不携带应用密钥,下载结果按文件类型安全展示。模型可以提议动作,服务端负责决定动作能否执行。
09托管平台与自研:保留有用的产品层
通用聊天、文件处理、代码执行和 agent 循环,越来越适合购买或复用。仅仅把这些功能再包装一遍,产品的替代风险很高。
截至 2026-09-21,OpenAI 官方文档说明 Assistants API 已在 2026-08-26 下线,新接入应使用 Responses API。迁移说明
百炼 Managed Agents 官方文档列出会话状态、云端容器、工具执行和持久事件;方舟也提供 Managed Agents 及相关能力。平台已经覆盖的基础设施,不必为了“拥有技术栈”重新造一遍。百炼官方文档、方舟官方产品入口
| 优先购买或复用 | 值得自己掌握 |
|---|---|
| 模型、常规工具循环、沙箱、对象存储、基础聊天组件 | 用户任务定义与科研工作流程 |
| 通用检索与文件处理基础设施 | 输入数据、假设、参数和结果的对应关系 |
| 托管计算与任务执行 | 可编辑、可重跑、可导出的项目契约 |
| 通用运行监控能力 | 领域检查、故障解释与用户工作衔接 |
版本管理和可复现性也不是天然独有优势。是否值得做成产品,取决于具体用户是否因此少走步骤、减少手工修正,并愿意继续使用。
接近用户的实施工作,可以帮助发现这些重复需求:先用现成平台完成真实任务,再把重复出现的导入、计算、编辑与导出步骤做成小产品。若每次需求都完全不同,适合继续作为实施服务;若稳定流程反复出现,再扩大产品投入。
10可移植项目的最小形态
research-project/
README.md # 问题、入口与重跑方法
assumptions.md # 假设、单位和适用范围
analysis.py # 当前分析脚本
parameters.json # 参数和随机种子
environment.lock # 依赖与环境版本
manifest.json # 文件哈希、来源、许可与版本
data/README.md # 数据取得方式;大数据可保留引用
runs/run-001/
execution.json # 输入版本、环境、预算与退出状态
stdout.txt
figures/
results.parquet
大文件引用必须说明访问方法、版本与校验方式,不导出长期访问密钥。受限制的数据可能不能公开,也可能无法由其他人直接取得;导出时应明确这些条件。
同一脚本重跑与让 agent 重新生成脚本不同。记录种子、环境与参数有助于重跑,但远程模型、外部数据及数值后端的变化仍可能改变结果。
这个产品的完成标准,是用户能带走自己的研究工作,并继续修改和运行。