Open Notebook 从源码安装与开发环境搭建:四个进程、一条 Makefile 的全链路实践
本文基于 open-notebook 仓库的 docs/1-INSTALLATION/from-source.md 展开,面向开发者和贡献者,完整讲解如何从源码克隆仓库、安装 Python/前端依赖、启动 SurrealDB、API、后台 Worker 与 Next.js 前端这四个进程,并覆盖 Conda 备选方案、环境变量配置、代码质量检查与常见故障排查。读完本文,你能够独立跑起 open-notebook 的完整开发环境,理解每个 Make 目标背后的真实命令,并在遇到端口、依赖、数据库连接等问题时快速定位原因。
一、前置条件
从源码运行 open-notebook 需要同时具备 Python 后端、Node.js 前端和容器化数据库三类运行环境,原文档给出的完整清单如下:
| 依赖 | 版本要求 | 用途 |
|---|---|---|
| Python | 3.11+ | 运行 FastAPI 后端与后台任务 |
| Node.js | 18+ | 运行 Next.js 前端开发服务器 |
| Git | 任意现代版本 | 克隆仓库 |
| Docker | 任意稳定版 | 运行 SurrealDB |
| uv | 最新版 | Python 包管理器(curl -LsSf https://astral.sh/uv/install.sh | sh) |
| AI 服务商 | OpenAI 等 API key | 或者用 Ollama 本地模型免费使用 |
版本约束可以从仓库配置中得到更精确的印证:
- pyproject.toml 中声明
requires-python = ">=3.11,<3.13",即 Python 3.11 或 3.12,3.13 暂不受支持; - 仓库根目录的
.python-version固定为3.12,uv sync会依据它创建隔离的虚拟环境; - frontend/package.json 使用 Next.js 16、React 19 与 Tailwind CSS 4,这些现代版本要求 Node.js 18 以上;
- Makefile 的
api、lint、worker等目标全部以uv run开头,所以 uv 是开发工作流的硬性前提,而不只是可选项。
二、克隆仓库
git clone https://gitcode.com/GitHub_Trending/op/open-notebook.git
cd open-notebook
# 如果是你自己的 fork:克隆后把原仓库添加为 upstream remote,
# 便于持续同步上游更新
git remote add upstream <原仓库地址>
仓库的顶层布局与后续四个进程一一对应:api/ 与 open_notebook/ 是 Python 后端,commands/ 是 Worker 消费的背景任务定义,frontend/ 是 Next.js 应用,Makefile 则把所有启动命令收拢成统一入口。
三、安装 Python 依赖
uv sync
uv pip install python-magic
uv sync依据 pyproject.toml 解析并安装主依赖与 dev 依赖组(dev 组包含mypy、pytest、ruff等,供后文的代码质量检查使用),同时生成.venv虚拟环境。关键依赖包括fastapi、uvicorn、langchain/langgraph、surrealdb以及承担后台任务调度的surreal-commands。uv pip install python-magic是文档要求额外安装的文件类型识别库,用于内容处理链路判断上传文件的 MIME 类型。- pyproject.toml 末尾的
[tool.uv] override-dependencies强制pillow>=12.2.0,注释说明了原因:moviepy(经podcast-creator间接引入)对 Pillow 的上限约束会拖入存在安全公告的旧版本,而音频播客流水线实际不会触碰 Pillow 的视频模块。
3.1 备选:Conda 方案
如果你习惯用 Conda 管理环境,可以用下面步骤替代标准 uv sync:
# 创建并激活环境
conda create -n open-notebook python=3.11 -y
conda activate open-notebook
# 在 conda 内安装 uv,保持与 Makefile 的兼容
conda install -c conda-forge uv nodejs -y
# 同步依赖
uv sync
关键点:在 Conda 环境内安装
uv,是为了让make start-all、make api等所有以uv run开头的 Make 目标继续无缝工作——否则 Make 在找不到uv时会直接失败。
四、启动 SurrealDB
数据库不随源码运行,而是通过 Docker 单独拉起:
# 终端 1
make database
# 等价于:docker compose up surrealdb
对应 Makefile 中的目标:
database:
docker compose up -d surrealdb
make database 实际读取仓库根目录的 docker-compose.yml,其中 surrealdb 服务的要点:
- 镜像为
surrealdb/surrealdb:v2,以 RocksDB 文件引擎启动,数据落在/mydata(映射到宿主机./surreal_data); - 默认凭据为
root:root,通过SURREAL_USER/SURREAL_PASSWORD环境变量覆盖; - 端口绑定为
127.0.0.1:8000:8000——只监听本机,因为宿主机上的 API 进程走localhost:8000即可访问,绑定0.0.0.0会配合默认凭据造成暴露风险; - 开启了
SURREAL_EXPERIMENTAL_GRAPHQL=true实验特性。
数据库端口 8000 与后文 API 端口 5055、前端 3000 共同构成三个默认访问地址,这也是排查"端口冲突"类问题时要记牢的对照表。
五、配置环境变量
cp .env.example .env
# 编辑 .env,至少设置:
# OPEN_NOTEBOOK_ENCRYPTION_KEY=my-secret-key
仓库提供的 .env.example 是一份带完整注释的模板,值得逐项了解:
必选项
OPEN_NOTEBOOK_ENCRYPTION_KEY:用于加密存储在数据库中的 API 凭据,建议至少 16 位随机字符串。API 启动时通过 api/main.py 引入的get_secret_from_env读取该密钥,密钥缺失或不一致会直接影响凭据的加解密。
数据库连接(默认值配合 docker-compose.yml 使用)
SURREAL_URL=ws://surrealdb:8000/rpc、SURREAL_USER、SURREAL_PASSWORD、SURREAL_NAMESPACE、SURREAL_DATABASE。- 需要注意:默认值
ws://surrealdb:8000/rpc使用的是 compose 内部网络的服务名。源码方式下 API 直接运行在宿主机上,从源码结构看应把SURREAL_URL调整为ws://localhost:8000/rpc才能与docker compose up起在宿主机上的 SurrealDB 连通——这是原文档没有展开、但实操中最容易踩到的差异点。
可选项(均被注释,按需打开)
- 各服务商 API key(
OPENAI_API_KEY、ANTHROPIC_API_KEY、GOOGLE_API_KEY、GROQ_API_KEY等):.env与 UI 二选一,官方推荐走 UI(Security → API Keys / Manage → Models),因为凭据会加密落库并可随时在界面上测试连接; - 内容处理参数
CHUNK_SIZE=1500/CHUNK_OVERLAP=150; OPEN_NOTEBOOK_WORKER_MAX_TASKS:Worker 并发任务数,默认 5,单 GPU/本地 LLM 场景建议设为 1 避免模型被并行请求压垮;OPEN_NOTEBOOK_MAX_UPLOAD_SIZE_MB:上传/请求体大小上限,默认 100MB;OPEN_NOTEBOOK_PASSWORD:实例访问密码,不设置则完全关闭认证;- 代理配置
HTTP_PROXY/HTTPS_PROXY/NO_PROXY:企业网络下NO_PROXY必须包含surrealdb、host.docker.internal等内部主机,否则数据库 websocket 会被隧道化导致 API/Worker 启动失败(应用侧也会自动注入这些主机作为兜底,api/main.py 中ensure_internal_no_proxy()就在load_dotenv()之后、触碰数据库之前执行这一保护)。
启动应用后,AI 服务商的正式配置通过浏览器界面完成(见第七节),.env 里的手动 key 只是备选路径。
六、启动 API、Worker 与前端
6.1 启动 API(终端 2)
make api
# 等价于:uv run --env-file .env uvicorn api.main:app --host 0.0.0.0 --port 5055
Makefile 中该目标的真实命令是 uv run --env-file .env run_api.py,而 run_api.py 是薄封装:读取 API_HOST(默认 127.0.0.1)、API_PORT(默认 5055)、API_RELOAD(默认 true,开发热重载)三个环境变量后调用 uvicorn.run("api.main:app", ...)。
api/main.py 的启动链路还包含几个值得了解的动作:
load_dotenv()加载.env;ensure_internal_no_proxy()保证 SurrealDB websocket 不被 HTTP 代理拦截;- 注册
PasswordAuthMiddleware与MaxBodySizeMiddleware(对应OPEN_NOTEBOOK_PASSWORD与上传大小限制); - 通过
AsyncMigrationManager在 API 启动时自动执行数据库迁移——所以原文档"Check database migrations(Auto-run on API startup)"不需要任何手动操作,迁移脚本位于 open_notebook/database/migrations/ 目录。
6.2 启动 Worker(终端 3)
make worker
# 等价于:uv run --env-file .env surreal-commands-worker --import-modules commands
这一步不能省略:源文件与笔记的处理(内容抽取、嵌入、洞察生成)被分派为后台任务,由一个独立的 worker 进程消费。没有它,每个 source 会永远停留在 Source processing status: CommandStatus.NEW 状态,界面上只会看到"处理中"。
Makefile 的 worker-start 目标还比文档示例多传了一个参数:
uv run --env-file .env surreal-commands-worker --import-modules commands \
--max-tasks "${OPEN_NOTEBOOK_WORKER_MAX_TASKS:-5}"
即并发度默认 5、可被 OPEN_NOTEBOOK_WORKER_MAX_TASKS 覆盖,与 .env.example 中的说明一致。--import-modules commands 指向仓库根目录的 commands/ 包,其中 source_commands.py、embedding_commands.py、podcast_commands.py 就是被 Worker 消费的任务实现。
6.3 启动前端(终端 4)
cd frontend && npm install && npm run dev
前端开发服务器跑在 3000 端口。这里有一个让源码部署"看起来更简单"的机制:frontend/next.config.ts 配置了 rewrite,把 /api/* 的请求代理到 INTERNAL_API_URL(默认 http://localhost:5055)对应的 FastAPI 后端,并顺带把代理体大小上限提到 100MB。也就是说浏览器只跟 3000 端口的 Next.js 说话,API 调用由它内部转发——多容器部署时改 INTERNAL_API_URL 即可。
6.4 访问地址
| 服务 | 地址 |
|---|---|
| 前端界面 | http://localhost:3000 |
| API 文档(FastAPI 自动生成) | http://localhost:5055/docs |
| SurrealDB | http://localhost:8000 |
make start-all可一键拉起 Database + API + Worker + Frontend;上面分四步单独启动,目的是让你能看到每个进程自己的日志,便于调试。需要说明:从当前 Makefile 的源码结构看,start-all目标引用了docker-compose.dev.yml,而该文件并不在仓库中,若你的环境缺少它导致启动中断,按本文四步单独启动即可达成同等效果。配套的make status(查看四个服务状态)、make stop-all(停止全部服务)可用于日常管理。
七、通过 UI 配置 AI 服务商
服务全部就绪后,按原文档的五步走界面配置:
- 打开 http://localhost:3000;
- 进入 Manage → Models(设置页的"模型"部分);
- 点击 Add Credential → 选择服务商 → 粘贴 API key;
- 点击 Save,然后点击 Test Connection 验证连通性;
- 点击 Discover Models → Register Models。
这套流程的底层实现位于 open_notebook/ai/:connection_tester.py 提供各服务商的连接测试,model_discovery.py 负责拉取模型列表,provider_registry.py 统一管理已注册模型。凭据保存后即被 OPEN_NOTEBOOK_ENCRYPTION_KEY 加密落库,之后在聊天、播客等场景中选择模型即可直接使用。
八、开发工作流:代码质量与测试
8.1 格式化与类型检查
# 格式化 + lint Python
make ruff
# 等价于:ruff check . --fix
# 类型检查
make lint
# 等价于:uv run python -m mypy .
规则同样定义在 pyproject.toml:ruff 行宽 88、启用 E/F/I 规则集并忽略 E501(行过长)、E402(模块级导入不在顶部)等;mypy 的附加配置在 mypy.ini。
8.2 运行测试
uv run pytest tests/
test/ 目录包含约 50 个测试文件,覆盖 API 路由、凭据、播客路径安全、URL 校验、上传竞态等主题,配合 conftest.py 中的共享 fixture 运行。
8.3 常用命令速查
# 启动全部服务
make start-all
# 查看 API 文档
open http://localhost:5055/docs
# 数据库迁移:API 启动时自动执行,无需手动操作
# 清理各类缓存目录(__pycache__、.mypy_cache、.ruff_cache 等)
# 当前仓库 Makefile 中的实际目标名为 clean-cache
make clean-cache
原文档中的 make clean 在当前 Makefile 中对应的目标是 clean-cache,它清理的是 Python/mypy/ruff/pytest 缓存而非用户数据。此外 Makefile 还提供 worker-stop / worker-restart,方便在改动 commands/ 任务代码后重启 Worker 而无需整条流水线重来。
九、故障排查
Python 版本过旧
python --version # 检查版本
uv sync --python 3.11 # 强制指定 Python 版本重建环境
npm: command not found
说明 Node.js 未安装或未进入 PATH,安装 Node.js 18+ 后重试;使用 Conda 方案的用户确认 conda install -c conda-forge nodejs 已执行。
数据库连接错误
docker ps # 确认 surrealdb 容器在运行
docker logs surrealdb # 查看容器日志
同时检查 .env 中 SURREAL_URL 是否指向正确地址(源码直跑场景应为 ws://localhost:8000/rpc),以及代理环境下 NO_PROXY 是否包含 surrealdb。
端口 5055 被占用
# 换端口启动 API
uv run uvicorn api.main:app --port 5056
也可以利用 run_api.py 的环境变量机制:export API_PORT=5056 API_HOST=0.0.0.0 后执行 make api。注意换端口后前端 rewrite 默认仍指向 5055,需要同时设置 INTERNAL_API_URL 或改回默认端口。
十、下一步
完成源码安装后,建议按原文档的指引继续深入:
更细粒度的环境变量、本地 STT/TTS、MCP 集成等高级配置,可参考 docs/5-CONFIGURATION/ 目录下的专题文档(如 环境变量参考)。
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 StartedRust0623
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