首页
/ Open Notebook:构建可私有部署的多模型 AI 研究笔记本——从 Docker 部署到 Provider 体系的完整技术指南

Open Notebook:构建可私有部署的多模型 AI 研究笔记本——从 Docker 部署到 Provider 体系的完整技术指南

2026-09-05 19:04:50作者:柏廷章Berta

Open Notebook 是一个开源、隐私优先的 Google Notebook LM 替代品,其核心能力在于:支持 18+ 个 AI 供应商、可完全本地化运行、提供 1-4 人声的多讲者播客生成,以及覆盖全部功能的 REST API。本文以仓库根目录 README.md 为骨架,完整继承其快速部署流程与 Provider 支持矩阵,并结合 docker-compose.ymlprovider 注册表源码环境参考文档,讲解每个配置项的实际作用与底层实现,帮助你在两分钟内完成部署,并理解每个参数背后的设计决策。

Open Notebook 笔记本列表页面界面

项目定位:私有化、多模型、全功能的 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/dataopen_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

  1. 进入 Models 页面,选择供应商(OpenAI、Anthropic、Google 等);
  2. 点击 + Add Configuration
  3. 粘贴 API Key 及所需的其他信息,点击 Add Configuration
  4. 点击 Test 测试连通性;
  5. 点击 Sync Models 并勾选要纳入的模型;
  6. Default Model Assignments 下点击 Auto-Assign Defaults,或手动指定各用途使用哪个模型。

完成后即可创建第一个笔记本。README 提示:需要 API Key 可去 OpenAI / Anthropic / Google / Groq(有免费层)等平台申请;想要免费本地 AI,见下文 Ollama 方案。

更多安装选项

Ollama 方案:完全本地、零 API 成本

examples/docker-compose-ollama.yml 在标准两服务之上增加了第三个 ollama 服务(镜像 ollama/ollama:latest,端口 11434,模型持久化到命名卷 ollama_models),并通过环境变量打通:

environment:
  - OLLAMA_API_BASE=http://ollama:11434

该文件的头部注释给出了完整操作序列:

  1. 复制为 docker-compose.yml,修改 OPEN_NOTEBOOK_ENCRYPTION_KEY
  2. docker compose up -d 启动;
  3. 拉取模型:docker exec open_notebook-ollama-1 ollama pull mistral
  4. 在 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 用一个冻结的 ProviderSpec dataclass 描述:namedisplay_namemodalities(默认提供哪些模态)、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.pyTEST_MODELSopen_notebook/ai/model_discovery.pyOPENAI_COMPAT_PROVIDERS、以及 GET /api/providers 接口;
  • 声明顺序即前端展示顺序——GET /api/providersPROVIDERS.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.pyCORS_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 或手写笔记。

进阶能力

api/main.py 的路由注册列表可以看到 REST API 的覆盖范围与上述功能一一对应:notebookssourcesnoteschatsource_chatsearchpodcastsepisode_profilesspeaker_profilestransformationsinsightsmodelscredentialsprovidersembeddingsettingsauthcapabilities 等 20 余个路由模块全部挂载到同一个 FastAPI 应用,且配有统一异常映射(NotFoundErrorRateLimitErrorExternalServiceError 等类型化异常)与最大请求体中间件——这意味着 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.mdworking-with-notes.mdchat-effectively.mdsearch.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.mddocs/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)提供了准确的代码地图。

登录后查看全文
热门项目推荐
相关项目推荐