Open Notebook:构建可私有部署的多模型 AI 研究笔记本——从 Docker 部署到 Provider 体系的完整技术指南
Open Notebook 是一个开源、隐私优先的 Google Notebook LM 替代品,其核心能力在于:支持 18+ 个 AI 供应商、可完全本地化运行、提供 1-4 人声的多讲者播客生成,以及覆盖全部功能的 REST API。本文以仓库根目录 README.md 为骨架,完整继承其快速部署流程与 Provider 支持矩阵,并结合 docker-compose.yml、provider 注册表源码 与 环境参考文档,讲解每个配置项的实际作用与底层实现,帮助你在两分钟内完成部署,并理解每个参数背后的设计决策。
项目定位:私有化、多模型、全功能的 Notebook LM 替代方案
Open Notebook 解决的核心问题是"把 AI 辅助研究的控制权交还用户":数据自托管、AI 供应商自选、内容类型不受限。README 中给出的与 Google Notebook LM 的功能对比表清晰地界定了它的能力边界:
| 功能 | Open Notebook | Google Notebook LM | 优势点 |
|---|---|---|---|
| 隐私与控制 | 自托管,数据归自己 | 仅 Google 云 | 完整的数据主权 |
| AI 供应商选择 | 18+ 供应商(OpenAI、Anthropic、Ollama、LM Studio 等) | 仅 Google 模型 | 灵活性与成本优化 |
| 播客讲者 | 1-4 人声,支持自定义 Profile | 仅 2 人声 | 极大的灵活性 |
| 内容转换(Transformations) | 自定义 + 内置 | 选项有限 | 无上限的处理能力 |
| API 访问 | 完整 REST API | 无 API | 完整的自动化能力 |
| 部署方式 | Docker、云或本地 | 仅 Google 托管 | 可部署到任何位置 |
| 引用(Citations) | 基础引用(持续改进中) | 完善的来源引用 | 研究完整性 |
| 可定制性 | 开源,完全可定制 | 闭源系统 | 无限制的可扩展性 |
| 成本 | 仅为 AI 用量付费 | 免费层 + 月订阅 | 透明可控 |
选择 Open Notebook 的核心理由(README 原文归纳):隐私优先——敏感研究资料完全私有;成本控制——可以选更便宜的供应商,或直接用 Ollama 本地运行;播客能力——完整脚本控制 + 多讲者灵活性,而非仅限双人对谈格式;无限定制——源码可修改、可集成;无供应商锁定——随时切换供应商、部署在任意位置、拥有自己的数据。
当前技术栈由 README 与 CONTRIBUTING.md 共同确认:Python、FastAPI(后端与 REST API)、Next.js + React(前端)、SurrealDB(数据库)、LangChain(AI 编排)。这一组合决定了它的部署形态——一个容器内运行 Web 应用,另配一个 SurrealDB 容器,数据通过卷挂载持久化。
五分钟快速开始:Docker Compose 部署
前提条件
仅需安装 Docker Desktop,仅此一项。API Key 稍后在 Web 界面中配置,部署阶段不需要任何密钥。
第一步:获取 docker-compose.yml
方式 A:直接下载仓库中的 compose 文件:
curl -o docker-compose.yml https://raw.githubusercontent.com/lfnovo/open-notebook/main/docker-compose.yml
方式 B:手动创建。仓库根目录的 docker-compose.yml 是两个服务的完整定义,核心结构如下(保留了原文档中的安全注释,这些注释对正确理解部署边界至关重要):
services:
surrealdb:
image: surrealdb/surrealdb:v2
# 凭据默认 root:root,用于零配置的本地部署。暴露到网络前,
# 请在 .env 中设置 SURREAL_USER / SURREAL_PASSWORD——
# 它们同时作用于下方 open_notebook 服务,保证两侧始终同步。
# 使用 list(exec) 形式确保每个插值都是单个参数——
# 否则含空格口令会被拆成多个参数。
command: ["start", "--log", "info", "--user", "${SURREAL_USER:-root}", "--pass", "${SURREAL_PASSWORD:-root}", "rocksdb:/mydata/mydatabase.db"]
user: root # Linux 上 bind mount 需要
ports:
# 仅绑定 localhost:open_notebook 服务通过内部 compose 网络访问它,
# 宿主机端口纯粹用于本地调试(Surrealist、surreal sql 等)。
# 暴露到 0.0.0.0 会让任何能访问宿主机的人用默认 root:root 连入。
- "127.0.0.1:8000:8000"
volumes:
- ./surreal_data:/mydata
environment:
- SURREAL_EXPERIMENTAL_GRAPHQL=true
restart: always
pull_policy: always
open_notebook:
image: lfnovo/open_notebook:v1-latest
ports:
- "8502:8502" # Web UI
- "5055:5055" # REST API
environment:
# 必填:改为你自己的密钥串
# 用于加密数据库中存储的 API Key
- OPEN_NOTEBOOK_ENCRYPTION_KEY=change-me-to-a-secret-string
# 数据库连接。SURREAL_USER / SURREAL_PASSWORD 本地默认 root:root;
# 暴露实例前在 .env 中覆盖(与上方 surrealdb 服务使用同一组值)。
- SURREAL_URL=ws://surrealdb:8000/rpc
- SURREAL_USER=${SURREAL_USER:-root}
- SURREAL_PASSWORD=${SURREAL_PASSWORD:-root}
- SURREAL_NAMESPACE=open_notebook
- SURREAL_DATABASE=open_notebook
volumes:
- ./notebook_data:/app/data
depends_on:
- surrealdb
restart: always
pull_policy: always
这份 compose 文件的几个设计细节值得注意,且都能在仓库中相互印证:
- SurrealDB 端口只绑定 127.0.0.1:应用通过 compose 内部网络以
ws://surrealdb:8000/rpc直连数据库,宿主机端口 8000 仅供surreal sql、Surrealist 等本地调试。这是默认凭据root:root前提下的安全底线,生产暴露场景必须先在.env中设置SURREAL_USER/SURREAL_PASSWORD。 - 两个持久化卷:
./surreal_data存数据库文件(RocksDB 引擎),./notebook_data映射到容器内/app/data。open_notebook/config.py 中的DATA_FOLDER进一步揭示了这个目录的内部结构:data/sqlite-db(LangGraph checkpoint)、data/uploads(上传的源文件)、data/podcasts(生成的播客音频)、data/tiktoken-cache(tokenizer 缓存),这些路径与 open_notebook/config.py 的目录常量一一对应,备份数据卷即完成整机数据迁移。 SURREAL_EXPERIMENTAL_GRAPHQL=true:开启 SurrealDB 的 GraphQL 实验特性,供应用侧查询使用。pull_policy: always:两个镜像都强制检查更新,v1-latest标签意味着滚动更新由镜像拉取驱动。
第二步:设置加密密钥
编辑 docker-compose.yml,将:
- OPEN_NOTEBOOK_ENCRYPTION_KEY=change-me-to-a-secret-string
改为任意保密字符串,例如 my-super-secret-key-123。
这个变量为什么必填、底层做了什么,可以从 open_notebook/utils/encryption.py 得到源码级确认:
- 该密钥用于字段级加密数据库中存储的 API Key(credentials 系统),未配置时服务无法完成凭据读写;
- 密钥本身接受任意字符串——系统通过 SHA-256 从它派生出 Fernet 密钥,因此可以设一个简单口令;
- 加密算法为 Fernet(AES-128-CBC + HMAC-SHA256 认证加密),加密后入库、读取时解密;
- 还支持 Docker secrets 模式:设置
OPEN_NOTEBOOK_ENCRYPTION_KEY_FILE指向一个文件,程序优先从文件读取(见该文件的get_secret_from_env()),适合不想把密钥写进 compose/环境变量列表的部署。
docs/5-CONFIGURATION/environment-reference.md 中同样将 OPEN_NOTEBOOK_ENCRYPTION_KEY 标记为 Required: Yes,并说明其支持 _FILE 后缀的 Docker secrets 用法。
第三步:启动服务
docker compose up -d
等待 15-20 秒后访问 http://localhost:8502 进入 Web UI。
第四步:在界面中配置 AI Provider
- 进入 Models 页面,选择供应商(OpenAI、Anthropic、Google 等);
- 点击 + Add Configuration;
- 粘贴 API Key 及所需的其他信息,点击 Add Configuration;
- 点击 Test 测试连通性;
- 点击 Sync Models 并勾选要纳入的模型;
- 在 Default Model Assignments 下点击 Auto-Assign Defaults,或手动指定各用途使用哪个模型。
完成后即可创建第一个笔记本。README 提示:需要 API Key 可去 OpenAI / Anthropic / Google / Groq(有免费层)等平台申请;想要免费本地 AI,见下文 Ollama 方案。
更多安装选项
- 带 Ollama(免费本地 AI):examples/docker-compose-ollama.yml,零 API 成本本地跑模型;
- 从源码构建(开发者):docs/1-INSTALLATION/from-source.md;
- 完整安装指南(所有部署场景):docs/1-INSTALLATION/index.md。
Ollama 方案:完全本地、零 API 成本
examples/docker-compose-ollama.yml 在标准两服务之上增加了第三个 ollama 服务(镜像 ollama/ollama:latest,端口 11434,模型持久化到命名卷 ollama_models),并通过环境变量打通:
environment:
- OLLAMA_API_BASE=http://ollama:11434
该文件的头部注释给出了完整操作序列:
- 复制为
docker-compose.yml,修改OPEN_NOTEBOOK_ENCRYPTION_KEY; docker compose up -d启动;- 拉取模型:
docker exec open_notebook-ollama-1 ollama pull mistral; - 在 UI 中配置 Ollama:Settings → API Keys → Add Ollama,URL 填
http://ollama:11434。
从源码结构看,Ollama 被注册为 language + embedding 双模态 provider(见下文 Provider 矩阵),即它既能当聊天模型也能当向量化引擎,支撑"完全本地"的 RAG 链路——docs/0-START-HERE/quick-start-local.md 提供了更完整的本地化启动指南(Ollama / LM Studio,完全私有)。
Provider 支持体系:一张矩阵与一个注册表
README 给出的 Provider Support Matrix(基于 Esperanto 库,开箱即用)如下,四个维度分别对应笔记本的四大 AI 能力:语言模型(聊天/转换)、Embedding(向量搜索)、语音转文本(音频源处理)、文本转语音(播客合成):
| Provider | LLM | Embedding | Speech-to-Text | Text-to-Speech |
|---|---|---|---|---|
| OpenAI | ✅ | ✅ | ✅ | ✅ |
| Anthropic | ✅ | ❌ | ❌ | ❌ |
| Groq | ✅ | ❌ | ✅ | ❌ |
| Google (GenAI) | ✅ | ✅ | ✅ | ✅ |
| Vertex AI | ✅ | ✅ | ❌ | ✅ |
| Ollama | ✅ | ✅ | ❌ | ❌ |
| oMLX | ✅ | ✅ | ❌ | ❌ |
| Perplexity | ✅ | ❌ | ❌ | ❌ |
| ElevenLabs | ❌ | ❌ | ✅ | ✅ |
| Deepgram | ❌ | ❌ | ✅ | ✅ |
| Azure OpenAI | ✅ | ✅ | ✅ | ✅ |
| Mistral | ✅ | ✅ | ✅ | ✅ |
| DeepSeek | ✅ | ❌ | ❌ | ❌ |
| Cohere | ✅ | ✅ | ❌ | ❌ |
| Voyage | ❌ | ✅ | ❌ | ❌ |
| xAI | ✅ | ❌ | ❌ | ✅ |
| OpenRouter | ✅ | ✅ | ✅ | ✅ |
| DashScope (Qwen) | ✅ | ❌ | ❌ | ❌ |
| MiniMax | ✅ | ❌ | ❌ | ❌ |
| Novita | ✅ | ❌ | ❌ | ❌ |
| PayPerQ (PPQ) | ✅ | ✅ | ✅ | ✅ |
| OpenAI Compatible* | ✅ | ✅ | ✅ | ✅ |
* OpenAI Compatible 覆盖 LM Studio 及任何 OpenAI 兼容端点;README 特别注明:Apple Silicon 上的 oMLX 优先使用原生 oMLX provider 而非兼容模式,配置见 docs/5-CONFIGURATION/omlx.md。
这张矩阵并非手工维护的文档,而是由单一数据源驱动。open_notebook/ai/provider_registry.py 是该体系的"唯一事实来源"(single source of truth),值得细看:
- 每个 provider 用一个冻结的
ProviderSpecdataclass 描述:name、display_name、modalities(默认提供哪些模态)、required_env/required_any_env/optional_env(基于环境变量的迁移配置)、test_model(连接测试用的最便宜模型)、openai_compat_discovery_url(暴露 OpenAI 兼容GET /models端点的发现地址)等; - 该注册表派生出多个后端表面:
api/credentials_service.py的环境变量配置与模态表、open_notebook/ai/connection_tester.py的TEST_MODELS、open_notebook/ai/model_discovery.py的OPENAI_COMPAT_PROVIDERS、以及GET /api/providers接口; - 声明顺序即前端展示顺序——
GET /api/providers按PROVIDERS.values()的声明顺序返回,前端运行时消费该接口,因此新增 provider 时前端无需改动; - 模块刻意设计为"纯数据",不 import 项目内任何其他模块,避免循环依赖;且
_build_registry()在导入期拒绝重复名称(重复会直接抛ValueError),从结构上杜绝配置漂移。
源码注释还点明了一个刻意保留的人工步骤:api/models.py 中的 SupportedProvider Literal 类型无法在运行时从字典构造,添加 provider 时需手工同步这一处——并由 tests/test_credential_provider_validation.py 的测试强制执行一致性。
注册表中的实现细节也解释了矩阵中若干"非对称"格子的成因。例如:Cohere 使用原生 v2 API(/v2/chat、/v2/embed)而非 OpenAI 兼容协议,因此没有 openai_compat_discovery_url,模型发现走 Esperanto 的定制路径;oMLX 的 base URL 由用户自定(默认 http://localhost:11435/v1)、API Key 可选,发现逻辑与 openai_compatible 类似而非固定 URL 表;Voyage 与 ElevenLabs、Deepgram 一样是单模态专精型(纯 Embedding / 纯语音),这正是"18+ 供应商"能拼出完整多模态能力地图的方式——聊天、向量化、STT、TTS 可以由不同供应商组合承担。
端口拓扑与关键运行参数
README 的 compose 文件确定了三个端口的职责划分,这也是排障时的第一张地图:
| 端口 | 服务 | 用途 |
|---|---|---|
| 8502 | open_notebook | Web UI(Next.js 前端) |
| 5055 | open_notebook | REST API(文档位于容器内 /docs,OpenAPI) |
| 8000 | surrealdb | 数据库 RPC,仅绑定 127.0.0.1,供本地调试 |
围绕这三个入口,仓库中还有若干直接影响运行行为的参数,建议在部署时一并了解(完整清单见 docs/5-CONFIGURATION/environment-reference.md):
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
OPEN_NOTEBOOK_ENCRYPTION_KEY |
是 | 无 | 加密数据库中凭据的密钥串,支持 _FILE 后缀 |
OPEN_NOTEBOOK_PASSWORD |
否 | 无 | 给实例加密码保护,公开部署时建议设置(见 docs/5-CONFIGURATION/security.md) |
OPEN_NOTEBOOK_MAX_UPLOAD_SIZE_MB |
否 | 100 | API 接受的最大请求体(MB),在认证/路由前强制;上传大音视频时需调大,且要同步调大反向代理(如 nginx client_max_body_size)的限值 |
OPEN_NOTEBOOK_WORKER_MAX_TASKS |
否 | 5 | 后台 worker 并发处理的任务数上限(源处理、embedding、播客)。单 GPU / 本地 LLM 场景建议设为 1 串行处理,避免并行请求压垮模型 |
CORS_ORIGINS |
否 | * |
允许调用 API 的来源白名单,自定义域名/反代部署时应显式设置;改动需重启 |
OPEN_NOTEBOOK_ENABLE_DOCLING / OPEN_NOTEBOOK_ENABLE_CRAWL4AI |
否 | false |
首次启动时安装重型抽取运行时:Docling(文档引擎 + OCR + 图片源,ML 栈较大)与 Crawl4AI(本地网页抓取,内置 Chromium) |
关于 OPEN_NOTEBOOK_WORKER_MAX_TASKS,compose 文件中的注释与 supervisord.conf 的传递链一致:它在 worker 进程启动时从进程环境读取(以 --max-tasks 传入 worker),所以 Docker 部署下要写在 environment: 里;而本地 make worker-start / dev-init.sh 启动路径下,需在 shell 中 export,只写进 .env 是不生效的——这是该参数最容易被误配置的地方。
CORS 的默认宽松(*)也有源码依据:api/main.py 中 CORS_ORIGINS 未设置时解析为通配,并且刻意区分"显式设置 *"与"未设置"两种情况,防止通配来源与 credentials 组合形成反射式 Origin 行为;生产部署应显式收紧(该文件在模块加载时解析一次,修改后需重启)。
核心功能全景
README 的 Key Features 一节列出的能力,可以在仓库结构中找到对应的实现与文档落点,便于按需深入:
核心能力
- 隐私优先:无云依赖,数据留在自托管环境;
- 多笔记本组织:多个研究项目并行管理(docs/2-CORE-CONCEPTS/notebooks-sources-notes.md);
- 通用内容支持:PDF、视频、音频、网页、Office 文档等;
- 多模型 AI:18+ 供应商,OpenAI、Anthropic、Ollama、Google、LM Studio 等;
- 专业播客生成:多讲者播客 + Episode Profiles(docs/2-CORE-CONCEPTS/podcasts-explained.md);
- 智能搜索:全文 + 向量双通道检索(docs/3-USER-GUIDE/search.md);
- 上下文感知聊天:以研究资料驱动的 AI 对话;
- AI 辅助笔记:生成 insights 或手写笔记。
进阶能力
- 推理模型支持:完整支持 DeepSeek-R1、Qwen3 等 thinking 模型;
- 内容转换(Transformations):可自定义的摘要/洞察提取动作(docs/3-USER-GUIDE/transformations.md);
- 完整 REST API:全功能编程访问,OpenAPI 文档随 API 服务暴露在
/docs(参考 docs/7-DEVELOPMENT/api-reference.md); - 可选密码保护:面向公开部署的认证(docs/5-CONFIGURATION/security.md);
- 细粒度上下文控制:精确选择共享给 AI 模型的内容;
- 引用(Citations):回答附带来源引用(docs/3-USER-GUIDE/citations.md)。
从 api/main.py 的路由注册列表可以看到 REST API 的覆盖范围与上述功能一一对应:notebooks、sources、notes、chat、source_chat、search、podcasts、episode_profiles、speaker_profiles、transformations、insights、models、credentials、providers、embedding、settings、auth、capabilities 等 20 余个路由模块全部挂载到同一个 FastAPI 应用,且配有统一异常映射(NotFoundError、RateLimitError、ExternalServiceError 等类型化异常)与最大请求体中间件——这意味着 UI 能做的操作基本都能通过 5055 端口的 REST 接口复现,这是"完整自动化"一格的工程基础。
路线图与文档导航
README 的 Roadmap 部分给出了方向性信息(以下为当前仓库声明状态,非承诺时间表):
计划中:实时前端更新(Live Front-End Updates)、异步处理(更快 UI)、跨笔记本复用源(Cross-Notebook Sources)、书签集成。
已完成:Next.js 前端(替代此前的 Streamlit,见 docs/7-DEVELOPMENT/decisions/ADR-003-streamlit-to-nextjs.md 决策记录)、完整 REST API、18+ 多模型支持、带 Episode Profiles 的高级播客生成器、内容转换、增强引用、笔记本内多聊天会话。
仓库文档体系按"由浅入深"编号组织,可作为延伸阅读地图:
| 场景 | 入口 |
|---|---|
| 项目介绍 | docs/0-START-HERE/index.md |
| OpenAI 五分钟上手 | docs/0-START-HERE/quick-start-openai.md |
| 全本地运行(Ollama/LM Studio) | docs/0-START-HERE/quick-start-local.md |
| 外部 Ollama 接入 | docs/0-START-HERE/quick-start-external-ollama.md |
| 完整安装(所有部署场景) | docs/1-INSTALLATION/index.md |
| 界面总览 | docs/3-USER-GUIDE/interface-overview.md |
| 加源、笔记、高效聊天、搜索 | docs/3-USER-GUIDE/adding-sources.md、working-with-notes.md、chat-effectively.md、search.md |
| AI 模型配置 | docs/4-AI-PROVIDERS/index.md |
| MCP 集成(Claude Desktop、VS Code 等 MCP 客户端) | docs/5-CONFIGURATION/mcp-integration.md |
| REST API 参考 | docs/7-DEVELOPMENT/api-reference.md |
| 安全(密码保护与隐私) | docs/5-CONFIGURATION/security.md |
| 项目愿景与原则 | VISION.md |
| 开发者文档(架构、贡献、决策记录) | docs/7-DEVELOPMENT/index.md |
| 排障(5 分钟快速修复) | docs/6-TROUBLESHOOTING/quick-fixes.md |
项目以 MIT 协议开源,详见 LICENSE;贡献流程与 AI 辅助贡献规范见 CONTRIBUTING.md 和 docs/7-DEVELOPMENT/contributing.md。
小结
Open Notebook 的价值主张可以压缩为三条工程决策:数据与模型选择权归用户(自托管 + 18+ 供应商)、能力全量开放(播客、转换、搜索、引用全部走同一个 REST API 暴露)、本地化零成本路径真实可用(Ollama 方案下语言模型与 Embedding 完全不出局域网)。其部署面只有两个容器与一个必填的加密密钥变量,而 docker-compose.yml 中每一条安全注释(127.0.0.1 端口绑定、默认凭据的覆盖方式、加密密钥的用途)都指明了生产暴露前必须检查的边界。理解 provider_registry.py 的单一注册表设计与 encryption.py 的 Fernet 字段级加密,就理解了这个项目"供应商可扩展、凭据可安全持久化"两大设计支柱的落点,也为二次开发或自动化集成(基于 5055 端口的 API)提供了准确的代码地图。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
