关于 alterlab-open-notebook
alterlab-open-notebook 是部署和自动化 Open Notebook 自托管研究工作区的技能,用于整理资料并处理其内容。它涵盖基于来源的对话、搜索、播客生成、内容转换,以及对接可配置 AI 提供方的 REST API 工作流。
主要功能
- 01整理笔记本、来源和笔记
- 02导入文档、媒体、网址和文本
- 03基于来源上下文进行对话
- 04全文或语义搜索
- 05生成多说话人播客
- 06通过 REST API 自动化工作流
适用场景
- 01搭建私有研究工作区
- 02搜索并讨论个人研究资料集
- 03根据笔记本资料生成播客
- 04自动管理来源和笔记
MCP 相关
运行中的 Open Notebook 实例可通过社区维护的 `open-notebook-mcp` 软件包供 MCP 客户端(如 Claude Desktop 和 VS Code)访问。README 提供 `uvx open-notebook-mcp` 及 `OPEN_NOTEBOOK_URL` / `OPEN_NOTEBOOK_PASSWORD` 设置方式。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ alterlab-ieu/ alterlab-academic-skills --skill alterlab-open-notebook安装后在 Claude Code 中输入/alterlab-open-notebook确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonreferences/api_reference.mdarchitecture.mdconfiguration.mdexamples.mdscripts/chat_interaction.pynotebook_management.pysource_ingestion.pytest_open_notebook_skill.py详细介绍
Open Notebook
概述
Open Notebook 是一个开源(MIT)、可自托管的 Google NotebookLM 替代方案,可帮助研究人员整理资料、生成 AI 洞见、创建播客,并围绕文档进行上下文感知对话。它提供完整的 REST API,通过 Esperanto 库支持 18+ 个 AI 提供商,并完全运行在你自己的基础设施上。本技能面向 1.x 系列(截至 2026-09 的 v1.14;Docker 镜像为 lfnovo/open_notebook:v1-latest)。
相比 NotebookLM 的主要优势:
- 完整的 REST API,支持编程访问和自动化
- 可选择 18+ 个 AI 提供商(不局限于 Google 模型),包括完全本地运行的 Ollama / LM Studio
- 支持生成多说话人播客,可自定义 1-4 位说话人
- 数据存储在你自己的机器或服务上
- 开源且可扩展(MIT 许可证)
**数据隐私:**自托管可将笔记本和文件保留在本地,但源文本仍会发送给你配置的云模型提供商。对于敏感或受 IRB 限制的材料,请使用本地提供商(Ollama、LM Studio)或符合你数据协议要求的提供商。
**代码仓库:**https://github.com/lfnovo/open-notebook
何时使用此技能
当用户想要:
- 搭建私有、可自托管的 NotebookLM 风格研究工作区
- 将 PDF、URL、音频/视频或文本导入笔记本,并结合来源上下文进行对话
- 使用全文或向量搜索检索个人研究资料库
- 根据来源生成多说话人播客或自定义转换结果(摘要、方法提取)
- 通过 REST API 自动执行上述任一操作
不适用场景
| 场景 | 改用 |
|---|---|
| 将单个文件一次性转换为 Markdown(无需笔记本、对话或搜索) | alterlab-markitdown |
| 在单个 PDF 中定位并进行跨章节问答 | alterlab-pdf-explore |
| 为多份 PDF 制作每篇论文占一行的证据表 | alterlab-pdf-extract |
| 在 Zotero 文献库中管理参考文献、DOI 或 BibTeX | alterlab-pyzotero |
| 系统性地搜索和筛选新文献 | alterlab-literature-review |
快速开始
前置条件
- Docker 和 Docker Compose v2(OrbStack 和 Docker Desktop 均可;必须能使用
docker compose) - 至少一个 AI 提供商的 API 密钥(也可使用本地 Ollama / LM Studio 免费进行本地推理)
安装
# 1. Download the official compose file (SurrealDB v2 + lfnovo/open_notebook:v1-latest)
curl -o docker-compose.yml https://raw.githubusercontent.com/lfnovo/open-notebook/main/docker-compose.yml
# 2. Set the encryption key: the compose file hard-codes
# OPEN_NOTEBOOK_ENCRYPTION_KEY=change-me-to-a-secret-string, so edit that line
# (exporting a shell variable has no effect on this file)
sed -i.bak "s/change-me-to-a-secret-string/$(openssl rand -hex 32)/" docker-compose.yml
# 3. Launch the services
docker compose up -d
访问应用(启动需等待 15-20 秒):
- **前端 UI:**http://localhost:8502
- **REST API:**http://localhost:5055
- **API 文档:**http://localhost:5055/docs(权威的架构定义)
SurrealDB 默认使用 root:root,且仅绑定到 127.0.0.1。在将实例暴露到本机以外之前,请在 compose 文件旁的 .env 文件中设置 SURREAL_USER / SURREAL_PASSWORD,设置 OPEN_NOTEBOOK_PASSWORD,并让 UI/API 通过 HTTPS 访问。
配置 AI 提供商
在 UI 中打开 Models,选择一个提供商,点击 + Add Configuration,粘贴密钥,点击 Test 测试连接,再点击 Sync Models,然后在 Default Model Assignments 下使用 Auto-Assign Defaults。
或者通过 REST API 配置:
import os
import requests
BASE_URL = "http://localhost:5055/api"
# Only needed when OPEN_NOTEBOOK_PASSWORD is set on the server
HEADERS = {"Authorization": f"Bearer {os.environ['OPEN_NOTEBOOK_PASSWORD']}"} if os.environ.get("OPEN_NOTEBOOK_PASSWORD") else {}
# Add a credential for an AI provider (stored encrypted with OPEN_NOTEBOOK_ENCRYPTION_KEY)
credential = requests.post(f"{BASE_URL}/credentials", headers=HEADERS, json={
"provider": "openai",
"name": "My OpenAI Key",
"api_key": os.environ["OPENAI_API_KEY"],
}).json()
# Discover the provider's models: {"credential_id", "provider", "discovered": [{name, provider, model_type}, ...]}
discovered = requests.post(
f"{BASE_URL}/credentials/{credential['id']}/discover", headers=HEADERS
).json()["discovered"]
# Register them (model_type: language, embedding, text_to_speech, speech_to_text)
requests.post(
f"{BASE_URL}/credentials/{credential['id']}/register-models",
headers=HEADERS,
json={"models": [
{"name": m["name"], "provider": m["provider"], "model_type": m["model_type"]}
for m in discovered if m.get("model_type")
]},
).raise_for_status()
# Fill empty default slots (chat, transformation, large-context, embedding, TTS, STT, tools)
requests.post(f"{BASE_URL}/models/auto-assign", headers=HEADERS)
核心功能
以下代码片段会重复使用上文中的 BASE_URL 和 HEADERS。
笔记本
将研究资料整理到不同的笔记本中,每个笔记本都包含来源、笔记和对话会话。
notebook = requests.post(f"{BASE_URL}/notebooks", headers=HEADERS, json={
"name": "Cancer Genomics Research",
"description": "Literature review on tumor mutational burden",
}).json()
notebook_id = notebook["id"]
来源
导入 PDF、视频、音频、网页、Office 文档或原始文本。POST /api/sources 接受 multipart 表单字段;必须提供 type(link、upload 或 text),设置 embed="true" 后,该来源即可用于向量搜索。
# Add a web URL source (processed in the background)
source = requests.post(f"{BASE_URL}/sources", headers=HEADERS, data={
"type": "link",
"url": "https://arxiv.org/abs/2301.00001",
"notebook_id": notebook_id,
"embed": "true",
"async_processing": "true",
}).json()
# Upload a PDF file
with open("paper.pdf", "rb") as f:
upload = requests.post(
f"{BASE_URL}/sources",
headers=HEADERS,
data={"type": "upload", "notebook_id": notebook_id, "embed": "true"},
files={"file": ("paper.pdf", f, "application/pdf")},
).json()
# Poll background processing: status is queued / running / completed / failed
status = requests.get(f"{BASE_URL}/sources/{source['id']}/status", headers=HEADERS).json()
笔记
创建和管理与笔记本关联的笔记(由人工或 AI 生成)。
requests.post(f"{BASE_URL}/notes", headers=HEADERS, json={
"title": "Key Findings",
"content": "TMB correlates with immunotherapy response in NSCLC...",
"note_type": "human",
"notebook_id": notebook_id,
})
上下文感知聊天
聊天回答以你传入的上下文为依据。使用 /api/chat/context 构建上下文(空的 context_config 会将笔记本中的所有来源和笔记作为简短上下文;每项可设为 "full content"、"insights" 或 "not in context",以进一步细化),然后随消息一并发送。
session = requests.post(f"{BASE_URL}/chat/sessions", headers=HEADERS, json={
"notebook_id": notebook_id,
"title": "TMB Discussion",
}).json()
ctx = requests.post(f"{BASE_URL}/chat/context", headers=HEADERS, json={
"notebook_id": notebook_id,
"context_config": {}, # or {"sources": {source_id: "full content"}, "notes": {...}}
}).json()
reply = requests.post(f"{BASE_URL}/chat/execute", headers=HEADERS, json={
"session_id": session["id"],
"message": "What are the key biomarkers for immunotherapy response?",
"context": ctx["context"],
}).json()
print(reply["messages"][-1]["content"]) # messages: [{id, type: human|ai, content}, ...]
搜索
使用全文搜索("text",默认)或语义搜索("vector",需要嵌入模型)检索所有材料,也可以选择按 notebook_id / notebook_ids 限定范围。
results = requests.post(f"{BASE_URL}/search", headers=HEADERS, json={
"query": "tumor mutational burden immunotherapy",
"type": "vector",
"limit": 10,
"notebook_id": notebook_id,
}).json() # {"results": [...], "total_count": n, "search_type": "vector"}
# Ask a question: the three model IDs are required (see GET /api/models or /api/models/defaults)
defaults = requests.get(f"{BASE_URL}/models/defaults", headers=HEADERS).json()
chat_model = defaults["default_chat_model"]
answer = requests.post(f"{BASE_URL}/search/ask/simple", headers=HEADERS, json={
"question": "How does TMB predict checkpoint inhibitor response?",
"strategy_model": chat_model,
"answer_model": chat_model,
"final_answer_model": chat_model,
"notebook_id": notebook_id,
}).json()["answer"]
POST /api/search/ask 接受相同的请求体,并以 Server-Sent Events 流式传输。
播客生成
根据笔记本生成多位说话人的播客(1-4 位说话人)。配置通过名称引用:单集配置(格式、模型、时长)和说话人配置(语音和人物设定)。
episode_profile = requests.get(f"{BASE_URL}/episode-profiles", headers=HEADERS).json()[0]
job = requests.post(f"{BASE_URL}/podcasts/generate", headers=HEADERS, json={
"episode_profile": episode_profile["name"],
"speaker_profile": episode_profile["speaker_config_name"], # or any name from /api/speaker-profiles
"episode_name": "TMB and immunotherapy",
"notebook_id": notebook_id,
}).json()
# Poll until the job reports "completed" (or "failed")
status = requests.get(f"{BASE_URL}/podcasts/jobs/{job['job_id']}", headers=HEADERS).json()["status"]
# Then locate the episode and download its audio
episodes = requests.get(f"{BASE_URL}/podcasts/episodes", headers=HEADERS).json()
episode = next(e for e in episodes if e["name"] == "TMB and immunotherapy")
audio = requests.get(f"{BASE_URL}/podcasts/episodes/{episode['id']}/audio", headers=HEADERS)
内容转换
对内容应用自定义的 AI 驱动转换,用于摘要、提取和分析。
transform = requests.post(f"{BASE_URL}/transformations", headers=HEADERS, json={
"name": "extract_methods",
"title": "Extract Methods",
"description": "Extract methodology details from papers",
"prompt": "Extract and summarize the methodology section...",
"apply_default": False,
}).json()
result = requests.post(f"{BASE_URL}/transformations/execute", headers=HEADERS, json={
"transformation_id": transform["id"],
"input_text": "...",
# "model_id": "model:...", # optional; defaults to the transformation model
}).json()["output"]
支持的 AI 提供商
Open Notebook 通过 Esperanto 库支持 18+ 个 AI 提供商。以下是部分代表性提供商:
| 提供商 | 大模型 | 嵌入 | 语音转文本 | 文本转语音 |
|---|---|---|---|---|
| OpenAI | 是 | 是 | 是 | 是 |
| Anthropic | 是 | 否 | 否 | 否 |
| Google GenAI | 是 | 是 | 是 | 是 |
| Vertex AI | 是 | 是 | 否 | 是 |
| Ollama | 是 | 是 | 否 | 否 |
| Groq | 是 | 否 | 是 | 否 |
| Mistral | 是 | 是 | 是 | 是 |
| Azure OpenAI | 是 | 是 | 是 | 是 |
| DeepSeek | 是 | 否 | 否 | 否 |
| xAI | 是 | 否 | 否 | 是 |
| OpenRouter | 是 | 是 | 是 | 是 |
| ElevenLabs | 否 | 否 | 是 | 是 |
| Voyage | 否 | 是 | 否 | 否 |
| OpenAI-compatible (LM Studio, vLLM, ...) | 是 | 是 | 是 | 是 |
如需查看完整的最新支持矩阵(包括 oMLX、Perplexity、Deepgram、Cohere、DashScope、MiniMax、Novita),请参阅上游 README。
环境变量
Docker 部署的关键配置变量:
| 变量 | 说明 | 默认值 |
|---|---|---|
OPEN_NOTEBOOK_ENCRYPTION_KEY | **必需。**用于加密已存储的提供商凭据;请保持其稳定(更改或丢失密钥会导致已保存的凭据无法读取) | 无 |
OPEN_NOTEBOOK_PASSWORD | 可选密码;设置后,API 调用需要 Authorization: Bearer <password> | 无 |
SURREAL_URL | SurrealDB 连接 URL | ws://surrealdb:8000/rpc |
SURREAL_USER / SURREAL_PASSWORD | SurrealDB 凭据(在向外部开放实例前,可通过 .env 覆盖) | root / root |
SURREAL_NAMESPACE | 数据库命名空间 | open_notebook |
SURREAL_DATABASE | 数据库名称 | open_notebook |
OPEN_NOTEBOOK_WORKER_MAX_TASKS | 并发后台任务数;使用单块本地 GPU 时设为 1 | 5 |
API 参考
REST API 位于 http://localhost:5055/api,交互式文档位于 /docs。
核心端点组:
/api/notebooks- 笔记本 CRUD、删除预览和来源关联/api/sources- 来源导入、状态、重试、见解和下载/api/notes- 笔记管理/api/chat/sessions、/api/chat/context、/api/chat/execute- 聊天会话、上下文构建和消息/api/search、/api/search/ask、/api/search/ask/simple- 全文/向量搜索和问答/api/podcasts、/api/episode-profiles、/api/speaker-profiles- 播客生成和配置/api/transformations- 内容转换工作流/api/models- 模型注册、默认设置、同步和自动分配/api/credentials- 提供商凭据管理、发现和注册
请求/响应详情请参阅 references/api_reference.md;可运行示例位于 scripts/ 和 references/examples.md。
架构
Open Notebook 使用现代技术栈:
- 后端: 使用 FastAPI 的 Python
- 数据库: SurrealDB(文档型 + 关系型)
- AI 集成: LangChain / LangGraph 和 Esperanto 多提供商库
- 前端: 使用 React 的 Next.js
- 部署: 使用 Docker Compose 和持久卷(
./notebook_data、./surreal_data)
重要说明
- Open Notebook 使用 Docker 部署(也提供供开发使用的源码部署方式)
- 必须配置至少一个 AI 提供商才能使用 AI 功能;向量搜索和 Ask 还需要嵌入模型
- 如需免费本地推理且无需 API 费用,请使用 Ollama 或 LM Studio
- 必须在首次启动前设置
OPEN_NOTEBOOK_ENCRYPTION_KEY,并确保每次重启时保持一致 - 数据存储在绑定挂载的
notebook_data/和surreal_data/文件夹中;请备份这些文件夹 - MCP 客户端(Claude Desktop、VS Code)可通过上游文档提到的社区
open-notebook-mcp包访问运行中的实例(使用OPEN_NOTEBOOK_URL/OPEN_NOTEBOOK_PASSWORD的uvx open-notebook-mcp)
AlterLab Academic Skills 套件的一部分。