Open Notebook Windows 原生部署指南:无 Docker/WSL 环境下四服务架构、关键修复与运维实践
本篇基于仓库文档 windows-native.md 展开,面向无法(或不希望)使用 Docker/WSL 的 Windows 用户,完整讲解 Open Notebook 在 Windows 上的原生安装流程、.env 关键配置、四个典型 Windows 兼容性问题的根因与修复方案,以及升级、端口规划与故障排查方法。读完本文,你可以在一台纯净的 Windows(含 ARM64)机器上手动拉起 SurrealDB、API、Worker、Frontend 四服务,并具备独立排查启动故障的能力。
一、适用对象:谁需要"无 Docker"方案
文档明确了三条适用边界,这决定了为什么不走 Docker Compose 安装路线:
- Windows ARM64 用户:Docker Desktop 与 WSL2 在 ARM64 上存在限制;
- 无 Hyper-V 的 Windows 版本:部分精简版/旧版 Windows 不支持虚拟化管理程序,Docker 无法运行;
- 偏好原生安装的用户:架构更简单、调试更直接(报错直接出现在自己的终端里,而不是容器日志中)。
这套方案的核心思路是:用 uv 管理 Python 虚拟环境与依赖,用 scoop/winget 安装系统级组件(Git、Node.js、SurrealDB),再手动在四个终端分别启动服务——Open Notebook 官方并未随仓库发布一键启动脚本,这也是后文所有"手动"命令的由来。
二、前置依赖清单
| 软件 | 安装命令 | 是否必需 |
|---|---|---|
| Git | winget install Git.Git |
是 |
| Python 3.12+ | 由 uv 自动安装(无需单独安装) | 是 |
| Node.js 18+ | winget install OpenJS.NodeJS |
是 |
| uv | pip install uv |
是 |
| SurrealDB | scoop install surrealdb |
是 |
关于 Python 版本有一个值得注意的细节:项目 pyproject.toml 声明 requires-python = ">=3.11,<3.13",因此 uv sync 会自动选择并安装 3.12 系列解释器到 .venv——文档推荐"Python 3.12+"与此一致。你甚至不需要在系统中预装 Python,uv 会按需下载;但也正因如此,Windows 上若已存在多个系统 Python,后续极易踩到"解释器选错"的坑(见第四部分 Issue 1)。
三、快速开始:从零到可访问的完整流程
3.1 克隆代码并初始化环境
cd %USERPROFILE%\Projects # 或你偏好的位置
git clone https://gitcode.com/GitHub_Trending/op/open-notebook
cd open-notebook
uv sync
cd frontend && npm install && cd ..
uv sync:根据 uv.lock 锁文件在.venv中复现完整 Python 依赖(FastAPI、LangGraph、SurrealDB 客户端等);npm install:为 Next.js 前端安装 Node 依赖,前端源码位于 frontend 目录。
3.2 配置 .env(含最关键的一处修改)
把 .env.example 复制为 .env,填入 API Key,然后务必把 SURREAL_URL 的主机名从 localhost 改为 127.0.0.1:
SURREAL_URL="ws://127.0.0.1:8000/rpc"
.env.example 中默认的 SURREAL_URL=ws://surrealdb:8000/rpc 是 docker-compose 网络里的服务名,原生安装时不存在该主机名,必须手工改写。这个"一个词之差"就是文档 Issue 2 的根源,后文详述。
3.3 启动四个服务(各占一个终端)
在 open-notebook 目录下,开四个终端依次执行:
REM 可选:让 Open Notebook 使用独立的数据目录(对应下文 Issue 4)
REM 在每个终端运行前设置,或省略以使用默认 ./data
set DATA_FOLDER=%USERPROFILE%\Projects\open-notebook-data
REM 终端 1 — SurrealDB
surreal start --user root --pass root --bind 127.0.0.1:8000 rocksdb:%DATA_FOLDER%\surrealdb
REM 终端 2 — API
uv run --env-file .env run_api.py
REM 终端 3 — Worker(模块调用方式可规避 Windows "canonicalize" 报错,见 Issue 3)
set PYTHONPATH=%CD%
uv run --env-file .env python -m surreal_commands.cli.worker --import-modules commands
REM 终端 4 — Frontend
cd frontend && npm run dev
四个服务各自的角色:
- SurrealDB(端口 8000):主数据库,rocksdb 文件后端落在
DATA_FOLDER\surrealdb; - API(端口 5055):FastAPI 服务。从入口脚本 run_api.py 可以看到,
API_HOST默认127.0.0.1、API_PORT默认5055、API_RELOAD默认true(开发热重载),最终加载的是 api/main.py 中的api.main:app; - Worker:
surreal-commands后台任务执行器,负责文档处理、播客生成等异步命令。仓库 Makefile 的worker-start目标在 POSIX 系统上用surreal-commands-worker --import-modules commands启动,而 Windows 文档特意改用python -m surreal_commands.cli.worker模块调用形式来规避可执行文件路径解析问题; - Frontend(端口 3000):Next.js 开发服务器。
启动顺序上建议先起 SurrealDB 再起 API。API 启动时会执行迁移等待逻辑:api/main.py 定义了最多 12 次、间隔指数退避(1s→5s 封顶)的数据库可达性探测(_wait_for_database),探测通过后自动执行 SurrealQL 迁移(迁移脚本 已按 23 个版本组织)。因此即使你顺手先启动了 API,它也会自己等待数据库就绪并自动升级 schema。
最后访问 http://127.0.0.1:3000 即进入应用。
四、推荐目录结构:代码与数据严格分离
文档强烈推荐把"源码目录"和"数据目录"分开:
YourProjectsFolder\
├── open-notebook\ # 源码(git clone)
│ ├── .venv\ # Python 虚拟环境(uv 创建)
│ ├── frontend\ # Next.js 前端
│ ├── commands\ # Worker 命令模块
│ └── .env # 你的配置
├── open-notebook-data\ # 数据目录(与代码分离!)
│ ├── surrealdb\ # 数据库文件
│ ├── uploads\ # 上传的文档
│ └── sqlite-db\ # LangGraph 检查点
└── start-open-notebook.bat # 你自建的一键启动脚本(可选)
为什么要分离?核心动机是:更新或重装代码(git pull/重新 clone)时不会误伤数据。数据目录实际存放的正是 open_notebook/config.py 中定义的几个路径:sqlite-db/checkpoints.sqlite(LangGraph 会话检查点)、uploads(上传文件)、podcasts(生成的播客音频)、tiktoken-cache(分词缓存)——这些目录在进程启动时会被自动创建。
可选:一键启动脚本
仓库不附带启动器,但你可以把下面内容保存为 start-open-notebook.bat 双击即用(按需修改 ROOT 与 DATA_ROOT):
@echo off
REM --- 修改这两个路径 ---
set ROOT=%USERPROFILE%\Projects\open-notebook
set DATA_ROOT=%USERPROFILE%\Projects\open-notebook-data
set DATA_FOLDER=%DATA_ROOT%
set PYTHONPATH=%ROOT%
cd /d %ROOT%
start "SurrealDB" surreal start --user root --pass root --bind 127.0.0.1:8000 rocksdb:%DATA_ROOT%\surrealdb
start "API" cmd /k "uv run --env-file .env run_api.py"
start "Worker" cmd /k "uv run --env-file .env python -m surreal_commands.cli.worker --import-modules commands"
start "Frontend" cmd /k "cd /d %ROOT%\frontend && npm run dev"
cmd /k 让每个服务保留独立窗口,方便定位是哪个服务报错。
五、四个 Windows 关键问题:症状、根因与修复
这一节是原生安装方案的精华——四个问题全部来自 Windows 平台特性与项目默认配置之间的冲突。
Issue 1:用错了 Python 版本
症状:
ModuleNotFoundError: No module named 'langgraph.checkpoint.sqlite'
且 traceback 指向系统 Python(例如 C:\Python314\)而非 .venv。
根因:Windows 上常存在多个 Python 版本,venv 的 activate.bat 并不总能正确覆盖系统解释器,于是"明明装好了"却调到了没有依赖的系统 Python。
修复:一律使用 uv run 而不是直接调用 python:
REM 错误:
.venv\Scripts\python.exe run_api.py
REM 正确:
uv run python run_api.py
uv run 保证在当前项目锁定的虚拟环境中执行,绕开系统 PATH 污染。这也是文档全部启动命令都带 uv run 前缀的原因。
Issue 2:数据库健康检查超时(localhost vs 127.0.0.1)
症状:
WARNING: Database health check timed out after 2 seconds
SurrealDB 明明在运行,前端却显示"Database is offline"。
根因:.env 中写的是 localhost,而 SurrealDB 绑定的是 127.0.0.1。在部分 Windows 环境下 localhost 会先解析到 IPv6 的 ::1,与只监听 IPv4 的数据库握手失败。
修复:
# 错误:
SURREAL_URL="ws://localhost:8000/rpc"
# 正确:
SURREAL_URL="ws://127.0.0.1:8000/rpc"
这与 surreal start --bind 127.0.0.1:8000 的绑定地址保持显式一致,是最稳妥的组合。
Issue 3:Worker 报 "Failed to canonicalize script path"
症状:
Failed to canonicalize script path
根因:surreal-commands-worker.exe 这类可执行入口在 Windows 上无法定位项目内的 Python commands 模块包(commands 目录下的任务注册模块)。
修复:改为 Python 模块调用并显式设置 PYTHONPATH:
set PYTHONPATH=%ROOT%
uv run --env-file .env python -m surreal_commands.cli.worker --import-modules commands
--import-modules commands 告诉 worker 加载 commands 包以注册任务处理器;从源码结构看,api/main.py 在 API 进程内也有命令注册动作,而 Worker 进程是这些后台任务的真正执行者,两者缺一不可。
Issue 4:DATA_FOLDER 含反斜杠导致 .env 解析失败
症状:
warning: Failed to parse environment file .env at position X
根因:uv 的 .env 解析器无法正确处理 Windows 反斜杠路径(C:\Users\... 中的转义问题)。
修复:.env 中把 DATA_FOLDER 保持注释状态,改在批处理/终端中用 set 注入:
set DATA_FOLDER=C:\path\to\open-notebook-data
配套改动:让 config.py 读取 DATA_FOLDER 环境变量
当前仓库的 open_notebook/config.py 是硬编码 DATA_FOLDER = "./data"(数据默认落在源码目录内)。文档建议做如下本地修改,使其支持环境变量覆盖:
import os
# ROOT DATA FOLDER - can be overridden via DATA_FOLDER environment variable
DATA_FOLDER = os.environ.get("DATA_FOLDER", "./data")
# Rest of file uses DATA_FOLDER...
改完后,前文所有 set DATA_FOLDER=... 才真正生效,数据才会进入独立的 open-notebook-data 目录。若不修改此文件,服务仍会默认使用 %CD%\data——功能上可用,只是失去了"代码数据分离"的保护。
六、.env 完整配置说明
结合 .env.example 与文档,Windows 原生部署下的关键配置项:
# 数据库 —— 必须使用 127.0.0.1
SURREAL_URL="ws://127.0.0.1:8000/rpc"
SURREAL_USER="root"
SURREAL_PASSWORD="root"
SURREAL_NAMESPACE="open_notebook"
SURREAL_DATABASE="open_notebook"
# 凭证加密密钥(必填项,建议 16 字符以上)
OPEN_NOTEBOOK_ENCRYPTION_KEY=change-me-to-a-secret-string
# AI 提供商 API Key(也可通过 设置页 → API Keys 配置)
OPENAI_API_KEY=your-key-here
ANTHROPIC_API_KEY=your-key-here
GOOGLE_API_KEY=your-key-here
几点源码级的补充说明:
- 加密密钥:api/main.py 在启动时检查
OPEN_NOTEBOOK_ENCRYPTION_KEY,未设置时会打印警告,且"API Key 加密将失败"——这是 .env.example 中标注为 REQUIRED 的项,原生部署时同样不能漏; - API 端口:由 run_api.py 的
API_HOST/API_PORT/API_RELOAD环境变量控制,默认即 127.0.0.1:5055 且开启热重载,无需额外配置; - Worker 并发度:.env.example 提供
OPEN_NOTEBOOK_WORKER_MAX_TASKS(默认 5),本地 LLM/单卡场景可设 1 串行处理;注意该变量在 worker 启动时读取,修改后必须重启 Worker; - AI Key 的位置:优先建议通过前端"设置 → API Keys"配置(加密入库),直接写
.env是可选的兜底方式。
七、AI 模型配置
服务跑起来后,在 Settings 页面添加模型。文档给出的常见模型名(以实际账户可用为准):
| 提供商 | 常用模型 |
|---|---|
| OpenAI | gpt-4o、gpt-4o-mini、gpt-4-turbo、text-embedding-3-small |
| Anthropic | claude-sonnet-4-20250514、claude-3-5-sonnet-20241022、claude-3-5-haiku-20241022 |
gemini-3.5-flash、gemini-2.5-flash、gemini-2.5-pro |
|
| DeepSeek | deepseek-chat、deepseek-reasoner |
若使用本地 Ollama,.env 中可设置 OLLAMA_API_BASE(参见 .env.example),实现 100% 离线运行。
八、升级与维护
新版本发布后,升级流程非常简单——这正是"代码/数据分离"的收益:
cd open-notebook
git pull
uv sync
cd frontend && npm install && cd ..
然后重启全部四个服务。由于 .env 与 open-notebook-data 都在源码目录之外或受 git 保护,升级过程不会丢失任何配置与数据;API 重启时 api/main.py 的迁移逻辑还会自动把数据库 schema 升到最新(若需要,23 个迁移文件均含对应的 _down 回滚脚本)。
九、服务与端口总览
| 服务 | 端口 | URL |
|---|---|---|
| SurrealDB | 8000 | ws://127.0.0.1:8000 |
| API | 5055 | http://127.0.0.1:5055/docs |
| Frontend | 3000 | http://127.0.0.1:3000 |
十、故障排查速查表
服务起不来
- 查端口占用:
netstat -ano | findstr :8000 - 结束冲突进程:
taskkill /F /PID <pid>
前端连不上 API
- 先确认 API 存活:访问 http://127.0.0.1:5055/docs
- 检查
.env中API_URL配置(默认http://localhost:5055,用于 webhook/回调等外部访问)
Worker 不处理任务
- 查看 Worker 窗口报错(绝大多数是
PYTHONPATH未设置或用了错误的解释器,回看 Issue 1/3) - 确认启动命令为
python -m surreal_commands.cli.worker --import-modules commands模块形式
前端提示数据库离线
- 先查
SURREAL_URL是否误用localhost(Issue 2),再看 SurrealDB 终端窗口是否有启动错误。
十一、适用前提与版本说明
- 原文档注明在 Windows 11 ARM64、Open Notebook v1.6.0 上验证过;当前仓库 pyproject.toml 版本为 1.14.0,核心启动链路(
run_api.py、open_notebook/config.py、surreal-commandsworker)与文档描述一致,但升级前仍建议核对 CHANGELOG(CHANGELOG.md)中的破坏性变更; - 本方案要求完全手动管理四个终端进程,适合 ARM64 受限环境或深度调试场景;在标准 x64 + Hyper-V 环境下,Docker Compose 路线(docker-compose.md)依然是官方推荐的首选项;
- 若发现新的 Windows 特有问题,欢迎按仓库贡献规范(CONTRIBUTING.md)反馈解决方案,持续完善这份指南。
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 StartedRust0622
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