与 Marimo 的 Akshay Agrawal 共建协作式 AI 开发的未来
摘要
Marimo 的核心押注是:notebook 可以覆盖完整数据工作流,而不只是一次性使用的草稿本。 这个开源 Python 环境把交互式探索与纯 Python 文件结合起来,既能作为脚本运行,也能部署为 Web 应用——这是 Agrawal 试图将“交互式计算最好的部分”与软件工程严谨性融合起来的实践。从首次查询到数据应用,这个扩大的工作流入口也是公司的变现逻辑。
可复现性靠架构保证,而不是靠用户自律。 Marimo 会静态构建跨 cell 的依赖 DAG,并重新运行所有受影响的 cell,包括页面上方的 cell,从而确保“页面上的代码与看到的输出一致”。需求非常现实:JetBrains 研究了 GitHub 上1000万个 Jupyter notebook,发现超过1/3在从头到尾重跑时,无法复现其序列化结果。
出人意料、但极其有力的采用切入口,是对 Git 的兼容性。 Marimo 将 notebook 存储为纯 Python,并保证小幅代码改动对应小幅 diff,而不是把代码和输出埋在一个庞大的 JSON blob 里。Agrawal 原本预计响应式执行或交互式 dataframe 会吸引用户,但他反复听到的却是“它对 Git 很友好”——包括来自此前一直避开 notebook 的软件工程师。
Marimo 抹平了 Streamlit 保留下来的 notebook 到应用之间的交接。 Streamlit 通常在探索完成后才介入,往往是直接把 Jupyter notebook 移植过去;而 Marimo 的每个 notebook 都能直接变成应用,无需转换,并且只重跑依赖某次交互的 cell。Anthony Goldbloom 告诉 Biewald,部署时间从约6小时降至5分钟,因为 notebook 不再需要重写。
2人团队已经搭建出覆盖面颇广的平台,但路线图也在扩大执行负担。 在获得 SLAC National Accelerator Laboratory 2年的资金与反馈后,Agrawal 和联合创始人 Miles 宣布完成种子轮融资并计划招聘。优先事项包括更深入的 SQL 和数据库连接、将高成本 cell 远程执行、基于 Pyodide 和 WebAssembly 的纯浏览器社区云、静态交互式文档,以及更接近 Cursor 的 AI 辅助。
产品纪律之所以重要,是因为放松 Marimo 的约束会破坏其下游价值。 用户要求增加一个开关,临时关闭 DAG、恢复 Jupyter 式自由,但创始人拒绝了:在这种模式下创建的 notebook,可能不再具备可复现性,无法作为可执行脚本运行,也无法部署为应用。“我们不能让你关闭 DAG”既是 UX 取舍,也是 Marimo 试图构建的护城河声明。
精读
1. Marimo 让 notebook 状态显式且可复现
Agrawal 将 notebook 定义为一种交互式计算环境:Python 代码块在 Markdown 旁边呈现图表、张量、训练过程和数据库结果。能够“在处理数据的同时看到数据”,让 notebook 成为科学研究、模型训练、Google Colab、Databricks 和 AWS SageMaker 等场景的核心工具。
其失败模式在于隐藏的执行历史。JetBrains 研究从 GitHub 下载了1000万个 Jupyter notebook,发现超过1/3在从头到尾重跑时,产生的结果不同于已存储的输出;另一篇2019年的论文也得出了类似结论。Agrawal 在 Stanford 攻读博士期间也遇到过同样的问题:“我无法复现你的科学结果。”
Marimo 的保证很简单:“页面上的代码与看到的输出一致。”它会静态解析变量定义和引用,构建 DAG,并更新所有依赖 cell,不受视觉位置影响——更像电子表格,而不是披着外衣的 Python REPL。
Biewald 立即追问:循环依赖怎么办?Agrawal 表示,循环依赖会被禁止并检测出来,Marimo 会识别受影响的 cell 并建议修复方案。Marimo 还内置包管理,Agrawal 认为这可以让 notebook 文件成为自包含、可复现的单元。
2. Pluto 和 Streamlit 提供了产品的两半
Agrawal 的起点,是在 Google Brain 从事 TensorFlow 工作、并完成机器学习与优化方向博士学位后,对工具链进行的一次广泛调研,其中很大一部分涉及开源工具。他最终得出的结论是,自己更喜欢构建“让其他人解决问题的开发者工具,而不是亲自解决这些问题”。
Pluto.jl 提供了响应式执行、无缝 UI 控件和内置包管理;它的采用情况让 Agrawal 确信,Python 也需要一个同类产品。Streamlit 则带来了第二个启发:类似 notebook 的产物可以变成 Web 应用。Marimo 将这两种思路合并到同一个文件中,让探索、可复用工具和部署保持在一起。
尽管 Biewald 提到有报道称 Netflix 在生产环境中使用 notebook,Agrawal 表示自己实习期间“可能一个 notebook 都没用过”,因为他负责的是算法工程,而不是相关工作;Netflix 对他的思考影响也不大。他真正观察到的是:“人们喜欢 notebook,但某种程度上也讨厌它们”,尤其是因为隐藏状态和 JSON 存储。
3. 对 Git 友好,意外成为分发引擎
早期采用主要来自 Hacker News;Agrawal 表示,Marimo 的 Show HN 帖子按这种排名方式计算,曾成为排名第二的 Python Show HN 帖子。近期的分发渠道还包括 Hugging Face 集成,可将 notebook 部署到 Spaces;以及一个基于 WebAssembly 的 playground,用户可以通过链接创建并分享不限数量的 notebook。
Agrawal 原本预计,可复现性、响应式执行或更丰富的数据交互会成为吸引用户的关键。但用户反复提到的却是纯 Python 存储和可读 diff。即使一次演示重点介绍了 SQL 和分析功能,一位商业分析教授最后的结论仍是:“我会使用它,因为它对 Git 很友好。”
Marimo 默认不会将输出存储在 notebook 中,但用户可以把输出快照保存到相邻文件。这样既保留了可浏览的结果,又让代码改动保持清晰,并允许将这些 HTML 文件排除在版本控制之外。
如今的使用场景已经超出数据科学家范围。用户用它探索数据、训练模型、构建周期性分析“迷你应用”,甚至为 EKS 集群搭建 dashboard。Biewald 对此感到意外,因为第一次交互仍然很像传统 notebook;Agrawal 认为,Git 和纯 Python 让这种格式获得了此前避开 notebook 的工程师的信任。
4. 一个产物覆盖应用、SQL、AI 辅助和远程算力
当滑块发生变化时,Streamlit 会重跑整个脚本;Marimo 则只执行 DAG 中的依赖 cell。这样既保留了快速实验能力,也能通过命令行调用隐藏代码,将同一个 notebook 作为应用暴露出来。按照 Goldbloom 描述的工作流,省去 notebook 到 Streamlit 的移植后,部署时间从6小时降至5分钟。
Agrawal 表示,自动执行对于 GPU 训练或 OpenAI endpoint 可能令人担忧,因为用户担心意外触发这些计算。因此,Marimo 提供了惰性运行时:下游 cell 会被标记为过期并显示视觉提示,但要等到用户明确发出命令后才更新。响应式模型得以保留,同时不会意外触发高成本计算。
内置 AI 支持包括 GitHub Copilot、Codeium,以及允许用户自带密钥的生成能力;生成过程会结合 notebook 上下文、dataframe 或附加的 DuckDB schema。目前重构仍以 cell 为单位,Agrawal 表示,更广泛的对话式、接近 Cursor 的编辑能力属于路线图规划。
Marimo 还会在 Python 与嵌入式 SQL 之间构建一张统一的数据流图,使 SQL 能够查询 dataframe,并通过 DuckDB 返回 dataframe。计划中的扩展包括更便捷的 Postgres 和数据库连接、更丰富的列预览,以及混合执行模式——仅将高成本 cell 发送到远程服务器。
5. 商业模式取决于保留 DAG 的约束
Agrawal 的变现逻辑从工作流位置开始。Streamlit 在流程接近末端时介入,只有一小部分项目最终会成为应用;Marimo 则从第一次查询或模型训练开始,并可以一路延伸到部署。由于 notebook 已经在商业平台中承担计算入口,他认为 Marimo 暴露的是“规模大得多”的可变现工作流。
公司最初获得了 SLAC National Accelerator Laboratory 提供的资金,足以让 Agrawal 和 Miles 工作2年。一位熟悉 Jupyter 问题的科学家在听完原型介绍后回应:“我们会付钱让你做出来”,并在开源前提供了早期反馈。接受采访当周,这家2人公司宣布完成种子轮融资。
最难的产品选择,是在用户抵触的情况下坚持可复现性。Marimo 禁止循环依赖,也禁止不同 cell 重复定义全局变量;对于 Jupyter 式“危险模式”的请求,团队同样予以拒绝,因为在这种模式下编写的 notebook 可能无法作为应用或脚本运行。“我们不能让你关闭 DAG。”
Agrawal 提供的退出路径仍然保留这一契约:将探索性代码封装进函数,以创建局部命名空间;或者在变量名前加下划线,使其成为 cell 局部变量,并可在其他位置复用。这种摩擦是有意设计的——正是这些限制让临时草稿更难写,却支撑起下游的全部承诺。