From f75aa6e8fbd1f4bc314ad37e5f97ebd2e2c62fc0 Mon Sep 17 00:00:00 2001 From: arch3rPro Date: Tue, 16 Dec 2025 18:54:44 +0800 Subject: [PATCH] =?UTF-8?q?feat(open-notebook):=20=E6=B7=BB=E5=8A=A0Open?= =?UTF-8?q?=20Notebook=E5=BA=94=E7=94=A8=E5=8F=8A=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 + apps/open-notebook/1.2.4/data.yml | 26 ++ apps/open-notebook/1.2.4/docker-compose.yml | 38 +++ apps/open-notebook/1.2.4/docker.env | 259 +++++++++++++++++++ apps/open-notebook/README.md | 124 +++++++++ apps/open-notebook/README_en.md | 129 +++++++++ apps/open-notebook/data.yml | 26 ++ apps/open-notebook/latest/data.yml | 26 ++ apps/open-notebook/latest/docker-compose.yml | 38 +++ apps/open-notebook/latest/docker.env | 259 +++++++++++++++++++ apps/open-notebook/logo.png | Bin 0 -> 48532 bytes 11 files changed, 937 insertions(+) create mode 100644 apps/open-notebook/1.2.4/data.yml create mode 100644 apps/open-notebook/1.2.4/docker-compose.yml create mode 100644 apps/open-notebook/1.2.4/docker.env create mode 100644 apps/open-notebook/README.md create mode 100644 apps/open-notebook/README_en.md create mode 100644 apps/open-notebook/data.yml create mode 100644 apps/open-notebook/latest/data.yml create mode 100644 apps/open-notebook/latest/docker-compose.yml create mode 100644 apps/open-notebook/latest/docker.env create mode 100644 apps/open-notebook/logo.png diff --git a/README.md b/README.md index cb30776..0e2fdb3 100644 --- a/README.md +++ b/README.md @@ -681,6 +681,18 @@ AI驱动的开源代码知识库与文档协作平台,支持多模型、多数 0.4.1 • [官网链接](https://next-ai-drawio.jiang.jp/) + + + + +Open-Notebook +
Open Notebook +
+ +📝 私有的、多模型的Google Notebook LM替代方案,支持多模态内容和AI播客生成 + +1.2.4 • [官网链接](https://www.open-notebook.ai/) + diff --git a/apps/open-notebook/1.2.4/data.yml b/apps/open-notebook/1.2.4/data.yml new file mode 100644 index 0000000..fed6d06 --- /dev/null +++ b/apps/open-notebook/1.2.4/data.yml @@ -0,0 +1,26 @@ +additionalProperties: + formFields: + - default: "8502" + envKey: PANEL_APP_PORT_HTTP + required: true + type: number + labelEn: Port + labelZh: 端口 + edit: true + rule: paramPort + - default: "5055" + envKey: PANEL_APP_PORT_API + required: true + type: number + labelEn: API Port + labelZh: API端口 + edit: true + rule: paramPort + - default: "8000" + envKey: PANEL_APP_PORT_DB + required: true + type: number + labelEn: Database Port + labelZh: 数据库端口 + edit: true + rule: paramPort diff --git a/apps/open-notebook/1.2.4/docker-compose.yml b/apps/open-notebook/1.2.4/docker-compose.yml new file mode 100644 index 0000000..c2aea5d --- /dev/null +++ b/apps/open-notebook/1.2.4/docker-compose.yml @@ -0,0 +1,38 @@ +services: + open_notebook: + image: lfnovo/open_notebook:1.2.4 + ports: + - ${PANEL_APP_PORT_HTTP}:8502 + - ${PANEL_APP_PORT_API}:5055 + env_file: + - ./docker.env + depends_on: + - surrealdb + volumes: + - ./notebook_data:/app/data + restart: always + container_name: ${CONTAINER_NAME} + networks: + - 1panel-network + labels: + createdBy: Apps + surrealdb: + image: surrealdb/surrealdb:v2 + volumes: + - ./surreal_data:/mydata + environment: + - SURREAL_EXPERIMENTAL_GRAPHQL=true + ports: + - ${PANEL_APP_PORT_DB}:8000 + command: start --log info --user root --pass root rocksdb:/mydata/mydatabase.db + pull_policy: always + user: root + restart: always + container_name: ${CONTAINER_NAME}-surrealdb + networks: + - 1panel-network + labels: + createdBy: Apps +networks: + 1panel-network: + external: true diff --git a/apps/open-notebook/1.2.4/docker.env b/apps/open-notebook/1.2.4/docker.env new file mode 100644 index 0000000..6f1d1da --- /dev/null +++ b/apps/open-notebook/1.2.4/docker.env @@ -0,0 +1,259 @@ + +# API CONFIGURATION +# URL where the API can be accessed by the browser +# This setting allows the frontend to connect to the API at runtime (no rebuild needed!) +# +# IMPORTANT: Do NOT include /api at the end - it will be added automatically! +# +# Common scenarios: +# - Docker on localhost: http://localhost:5055 (default, works for most cases) +# - Docker on LAN/remote server: http://192.168.1.100:5055 or http://your-server-ip:5055 +# - Behind reverse proxy with custom domain: https://your-domain.com +# - Behind reverse proxy with subdomain: https://api.your-domain.com +# +# Examples for reverse proxy users: +# - API_URL=https://notebook.example.com (frontend will call https://notebook.example.com/api/*) +# - API_URL=https://api.example.com (frontend will call https://api.example.com/api/*) +# +# Note: If not set, the system will auto-detect based on the incoming request. +# Only set this if you need to override the auto-detection (e.g., reverse proxy scenarios). +API_URL=http://localhost:5055 + +# INTERNAL API URL (Server-Side) +# URL where Next.js server-side should proxy API requests (via rewrites) +# This is DIFFERENT from API_URL which is used by the browser client +# +# INTERNAL_API_URL is used by Next.js rewrites to forward /api/* requests to the FastAPI backend +# API_URL is used by the browser to know where to make API calls +# +# Default: http://localhost:5055 (single-container deployment - both services on same host) +# Override for multi-container: INTERNAL_API_URL=http://api-service:5055 +# +# Common scenarios: +# - Single container (default): Don't set - defaults to http://localhost:5055 +# - Multi-container Docker Compose: INTERNAL_API_URL=http://api:5055 (use service name) +# - Kubernetes/advanced networking: INTERNAL_API_URL=http://api-service.namespace.svc.cluster.local:5055 +# +# Why two variables? +# - API_URL: External/public URL that browsers use (can be https://your-domain.com) +# - INTERNAL_API_URL: Internal container networking URL (usually http://localhost:5055 or service name) +# +# INTERNAL_API_URL=http://localhost:5055 + +# API CLIENT TIMEOUT (in seconds) +# Controls how long the frontend/Streamlit UI waits for API responses +# Increase this if you're using slow AI providers or hardware (Ollama on CPU, remote LM Studio, etc.) +# Default: 300 seconds (5 minutes) - sufficient for most transformation/insight operations +# +# Common scenarios: +# - Fast cloud APIs (OpenAI, Anthropic): 300 seconds is more than enough +# - Local Ollama on GPU: 300 seconds should work fine +# - Local Ollama on CPU: Consider 600 seconds (10 minutes) or more +# - Remote LM Studio over slow network: Consider 900 seconds (15 minutes) +# - Very large documents: May need 900+ seconds +# +# API_CLIENT_TIMEOUT=300 + +# ESPERANTO LLM TIMEOUT (in seconds) +# Controls the timeout for AI model API calls at the Esperanto library level +# This is separate from API_CLIENT_TIMEOUT and applies to the actual LLM provider requests +# Only increase this if you're experiencing timeouts during model inference itself +# Default: 60 seconds (built into Esperanto) +# +# Important: This should generally be LOWER than API_CLIENT_TIMEOUT to allow proper error handling +# +# Common scenarios: +# - Fast cloud APIs (OpenAI, Anthropic, Groq): 60 seconds is sufficient +# - Local Ollama with small models: 120-180 seconds may help +# - Local Ollama with large models on CPU: 300+ seconds +# - Remote or self-hosted LLMs: 180-300 seconds depending on hardware +# +# Note: If transformations complete but you see timeout errors, increase API_CLIENT_TIMEOUT first. +# Only increase ESPERANTO_LLM_TIMEOUT if the model itself is timing out during inference. +# +# ESPERANTO_LLM_TIMEOUT=60 + +# SSL VERIFICATION CONFIGURATION +# Configure SSL certificate verification for local AI providers (Ollama, LM Studio, etc.) +# behind reverse proxies with self-signed certificates +# +# Option 1: Custom CA Bundle (recommended for self-signed certs) +# Point to your CA certificate file to verify SSL while using custom certificates +# ESPERANTO_SSL_CA_BUNDLE=/path/to/your/ca-bundle.pem +# +# Option 2: Disable SSL Verification (development only) +# WARNING: Disabling SSL verification exposes you to man-in-the-middle attacks +# Only use in trusted development/testing environments +# ESPERANTO_SSL_VERIFY=false + +# SECURITY +# Set this to protect your Open Notebook instance with a password (for public hosting) +# OPEN_NOTEBOOK_PASSWORD= + +# OPENAI +# OPENAI_API_KEY= + + +# ANTHROPIC +# ANTHROPIC_API_KEY= + +# GEMINI +# this is the best model for long context and podcast generation +# GOOGLE_API_KEY= +# GEMINI_API_BASE_URL= # Optional: Override default endpoint (for Vertex AI, proxies, etc.) + +# VERTEXAI +# VERTEX_PROJECT=my-google-cloud-project-name +# GOOGLE_APPLICATION_CREDENTIALS=./google-credentials.json +# VERTEX_LOCATION=us-east5 + +# MISTRAL +# MISTRAL_API_KEY= + +# DEEPSEEK +# DEEPSEEK_API_KEY= + +# OLLAMA +# OLLAMA_API_BASE="http://10.20.30.20:11434" + +# OPEN ROUTER +# OPENROUTER_BASE_URL="https://openrouter.ai/api/v1" +# OPENROUTER_API_KEY= + +# GROQ +# GROQ_API_KEY= + +# XAI +# XAI_API_KEY= + +# ELEVENLABS +# Used only by the podcast feature +# ELEVENLABS_API_KEY= + +# TTS BATCH SIZE +# Controls concurrent TTS requests for podcast generation (default: 5) +# Lower values reduce provider load but increase generation time +# Recommended: OpenAI=5, ElevenLabs=2, Google=4, Custom=1 +# TTS_BATCH_SIZE=2 + +# VOYAGE AI +# VOYAGE_API_KEY= + +# OPENAI COMPATIBLE ENDPOINTS +# Generic configuration (applies to all modalities: language, embedding, STT, TTS) +# OPENAI_COMPATIBLE_BASE_URL=http://localhost:1234/v1 +# OPENAI_COMPATIBLE_API_KEY= + +# Mode-specific configuration (overrides generic if set) +# Use these when you want different endpoints for different capabilities +# OPENAI_COMPATIBLE_BASE_URL_LLM=http://localhost:1234/v1 +# OPENAI_COMPATIBLE_API_KEY_LLM= +# OPENAI_COMPATIBLE_BASE_URL_EMBEDDING=http://localhost:8080/v1 +# OPENAI_COMPATIBLE_API_KEY_EMBEDDING= +# OPENAI_COMPATIBLE_BASE_URL_STT=http://localhost:9000/v1 +# OPENAI_COMPATIBLE_API_KEY_STT= +# OPENAI_COMPATIBLE_BASE_URL_TTS=http://localhost:9000/v1 +# OPENAI_COMPATIBLE_API_KEY_TTS= + +# AZURE OPENAI +# Generic configuration (applies to all modalities: language, embedding, STT, TTS) +# AZURE_OPENAI_API_KEY= +# AZURE_OPENAI_ENDPOINT= +# AZURE_OPENAI_API_VERSION=2024-12-01-preview + +# Mode-specific configuration (overrides generic if set) +# Use these when you want different deployments for different AI capabilities +# AZURE_OPENAI_API_KEY_LLM= +# AZURE_OPENAI_ENDPOINT_LLM= +# AZURE_OPENAI_API_VERSION_LLM= + +# AZURE_OPENAI_API_KEY_EMBEDDING= +# AZURE_OPENAI_ENDPOINT_EMBEDDING= +# AZURE_OPENAI_API_VERSION_EMBEDDING= + +# AZURE_OPENAI_API_KEY_STT= +# AZURE_OPENAI_ENDPOINT_STT= +# AZURE_OPENAI_API_VERSION_STT= + +# AZURE_OPENAI_API_KEY_TTS= +# AZURE_OPENAI_ENDPOINT_TTS= +# AZURE_OPENAI_API_VERSION_TTS= + +# USE THIS IF YOU WANT TO DEBUG THE APP ON LANGSMITH +# LANGCHAIN_TRACING_V2=true +# LANGCHAIN_ENDPOINT="https://api.smith.langchain.com" +# LANGCHAIN_API_KEY= +# LANGCHAIN_PROJECT="Open Notebook" + +# CONNECTION DETAILS FOR YOUR SURREAL DB +# New format (preferred) - WebSocket URL +SURREAL_URL="ws://surrealdb/rpc:8000" +SURREAL_USER="root" +SURREAL_PASSWORD="root" +SURREAL_NAMESPACE="open_notebook" +SURREAL_DATABASE="staging" + +# RETRY CONFIGURATION (surreal-commands v1.2.0+) +# Global defaults for all background commands unless explicitly overridden at command level +# These settings help commands automatically recover from transient failures like: +# - Database transaction conflicts during concurrent operations +# - Network timeouts when calling external APIs +# - Rate limits from LLM/embedding providers +# - Temporary resource unavailability + +# Enable/disable retry globally (default: true) +# Set to false to disable retries for all commands (useful for debugging) +SURREAL_COMMANDS_RETRY_ENABLED=true + +# Maximum retry attempts before giving up (default: 3) +# Database operations use 5 attempts (defined per-command) +# API calls use 3 attempts (defined per-command) +SURREAL_COMMANDS_RETRY_MAX_ATTEMPTS=3 + +# Wait strategy between retry attempts (default: exponential_jitter) +# Options: exponential_jitter, exponential, fixed, random +# - exponential_jitter: Recommended - prevents thundering herd during DB conflicts +# - exponential: Good for API rate limits (predictable backoff) +# - fixed: Use for quick recovery scenarios +# - random: Use when you want unpredictable retry timing +SURREAL_COMMANDS_RETRY_WAIT_STRATEGY=exponential_jitter + +# Minimum wait time between retries in seconds (default: 1) +# Database conflicts: 1 second (fast retry for transient issues) +# API rate limits: 5 seconds (wait for quota reset) +SURREAL_COMMANDS_RETRY_WAIT_MIN=1 + +# Maximum wait time between retries in seconds (default: 30) +# Database conflicts: 30 seconds maximum +# API rate limits: 120 seconds maximum (defined per-command) +# Total retry time won't exceed max_attempts * wait_max +SURREAL_COMMANDS_RETRY_WAIT_MAX=30 + +# WORKER CONCURRENCY +# Maximum number of concurrent tasks in the worker pool (default: 5) +# This affects the likelihood of database transaction conflicts during batch operations +# +# Tuning guidelines based on deployment size: +# - Resource-constrained (low CPU/memory): 1-2 workers +# Reduces conflicts and resource usage, but slower processing +# +# - Normal deployment (balanced): 5 workers (RECOMMENDED) +# Good balance between throughput and conflict rate +# Retry logic handles occasional conflicts gracefully +# +# - Large instances (high CPU/memory): 10-20 workers +# Higher throughput but more frequent DB conflicts +# Relies heavily on retry logic with jittered backoff +# +# Note: Higher concurrency increases vectorization speed but also increases +# SurrealDB transaction conflicts. The retry logic with exponential-jitter +# backoff ensures operations complete successfully even at high concurrency. +SURREAL_COMMANDS_MAX_TASKS=5 + +# OPEN_NOTEBOOK_PASSWORD= + +# FIRECRAWL - Get a key at https://firecrawl.dev/ +FIRECRAWL_API_KEY= + +# JINA - Get a key at https://jina.ai/ +JINA_API_KEY= \ No newline at end of file diff --git a/apps/open-notebook/README.md b/apps/open-notebook/README.md new file mode 100644 index 0000000..b0b065a --- /dev/null +++ b/apps/open-notebook/README.md @@ -0,0 +1,124 @@ +# Open Notebook + +一个私有的、多模型的、100% 本地的、功能完整的 Google Notebook LM 替代方案 + +在人工智能主导的世界中,拥有思考🧠和获取新知识💡的能力,不应该成为少数人的特权,也不应该被限制在单一提供商。 + +![](https://img.shields.io/badge/Copyright-arch3rPro-ff9800?style=flat&logo=github&logoColor=white) + +![](https://cdn.jsdelivr.net/gh/xiaoY233/PicList@main/public/assets/open-notebook.png) + +**Open Notebook 赋能您:** +- 🔒 **控制您的数据** - 保持您的研究私密和安全 +- 🤖 **选择您的AI模型** - 支持16+个提供商,包括OpenAI、Anthropic、Ollama、LM Studio等 +- 📚 **组织多模态内容** - PDF、视频、音频、网页等 +- 🎙️ **生成专业播客** - 高级多说话人播客生成 +- 🔍 **智能搜索** - 对所有内容进行全文和向量搜索 +- 💬 **上下文聊天** - AI对话由您的研究驱动 + +在 [https://www.open-notebook.ai](https://www.open-notebook.ai) 了解我们项目的更多信息 + +## 🆚 Open Notebook vs Google Notebook LM + +| 功能 | Open Notebook | Google Notebook LM | 优势 | +|---------|---------------|--------------------|-----------| +| **隐私和控制** | 自托管,您的数据 | 仅限谷歌云 | 完全的数据主权 | +| **AI提供商选择** | 16+提供商(OpenAI、Anthropic、Ollama、LM Studio等) | 仅谷歌模型 | 灵活性和成本优化 | +| **播客说话人** | 1-4个说话人,支持自定义配置 | 仅2个说话人 | 极致的灵活性 | +| **上下文控制** | 3个细粒度级别 | 全有或全无 | 隐私和性能调优 | +| **内容转换** | 自定义和内置 | 有限选项 | 无限的处理能力 | +| **API访问** | 完整REST API | 无API | 完整自动化 | +| **部署** | Docker、云端或本地 | 仅谷歌托管 | 随处部署 | +| **引用** | 带源的完整引用 | 基本引用 | 研究完整性 | +| **定制** | 开源,完全可定制 | 封闭系统 | 无限扩展性 | +| **成本** | 仅支付AI使用费 | 每月订阅+使用量 | 透明可控 | + +**为什么选择Open Notebook?** +- 🔒 **隐私优先**: 您的敏感研究保持完全私密 +- 💰 **成本控制**: 选择更便宜的AI提供商或使用Ollama本地运行 +- 🎙️ **更好的播客**: 完整脚本控制和多说话人灵活性,优于有限的2说话人深度分析格式 +- 🔧 **无限定制**: 根据需要修改、扩展和集成 +- 🌐 **无供应商锁定**: 切换提供商、随处部署、拥有您的数据 + +### Open Notebook 工作原理 + +``` +┌─────────────────────────────────────────────────────────┐ +│ 您的浏览器 │ +│ 访问地址: http://您的服务器IP:8502 │ +└────────────────┬────────────────────────────────────────┘ + │ + ▼ + ┌───────────────┐ + │ 端口 8502 │ ← Next.js 前端(您看到的界面) + │ 前端 │ 同时在内部代理API请求! + └───────┬───────┘ + │ 代理 /api/* 请求 ↓ + ▼ + ┌───────────────┐ + │ 端口 5055 │ ← FastAPI 后端(处理请求) + │ API │ + └───────┬───────┘ + │ + ▼ + ┌───────────────┐ + │ SurrealDB │ ← 数据库(内部,自动配置) + │ (端口 8000) │ + └───────────────┘ +``` + +**关键要点:** +- **v1.1+**: Next.js自动代理 `/api/*` 请求到后端,简化反向代理设置 +- 您的浏览器从端口8502加载前端 +- 前端需要知道在哪里找到API - 远程访问时,设置:`API_URL=http://您的服务器IP:5055` +- **使用反向代理?** 现在您只需要代理到端口8502!请参阅[反向代理指南](docs/deployment/reverse-proxy.md) + +## 提供商支持矩阵 + +感谢 [Esperanto](https://github.com/lfnovo/esperanto) 库,我们开箱即用地支持这些提供商! + +| 提供商 | LLM支持 | 嵌入支持 | 语音转文本 | 文本转语音 | +|--------------|-------------|------------------|----------------|----------------| +| OpenAI | ✅ | ✅ | ✅ | ✅ | +| Anthropic | ✅ | ❌ | ❌ | ❌ | +| Groq | ✅ | ❌ | ✅ | ❌ | +| Google (GenAI) | ✅ | ✅ | ❌ | ✅ | +| Vertex AI | ✅ | ✅ | ❌ | ✅ | +| Ollama | ✅ | ✅ | ❌ | ❌ | +| Perplexity | ✅ | ❌ | ❌ | ❌ | +| ElevenLabs | ❌ | ❌ | ✅ | ✅ | +| Azure OpenAI | ✅ | ✅ | ❌ | ❌ | +| Mistral | ✅ | ✅ | ❌ | ❌ | +| DeepSeek | ✅ | ❌ | ❌ | ❌ | +| Voyage | ❌ | ✅ | ❌ | ❌ | +| xAI | ✅ | ❌ | ❌ | ❌ | +| OpenRouter | ✅ | ❌ | ❌ | ❌ | +| OpenAI 兼容* | ✅ | ❌ | ❌ | ❌ | + +*支持LM Studio和任何OpenAI兼容端点 + +## ✨ 主要功能 + +### 核心能力 +- **🔒 隐私优先**: 您的数据保持在您的控制下 - 无云依赖 +- **🎯 多笔记本组织**: 无缝管理多个研究项目 +- **📚 通用内容支持**: PDF、视频、音频、网页、Office文档等 +- **🤖 多模型AI支持**: 16+提供商,包括OpenAI、Anthropic、Ollama、Google、LM Studio等 +- **🎙️ 专业播客生成**: 带有剧集配置的高级多说话人播客 +- **🔍 智能搜索**: 对所有内容进行全文和向量搜索 +- **💬 上下文感知聊天**: AI对话由您的研究材料驱动 +- **📝 AI辅助笔记**: 生成洞察或手动写笔记 + +### 高级功能 +- **⚡ 推理模型支持**: 对DeepSeek-R1和Qwen3等思考模型的完整支持 +- **🔧 内容转换**: 强大的可自定义操作,用于总结和提取洞察 +- **🌐 完整REST API**: 自定义集成的完整程序化访问 [![API文档](https://img.shields.io/badge/API-文档-blue?style=flat-square)](http://localhost:5055/docs) +- **🔐 可选密码保护**: 通过身份验证保护公共部署 +- **📊 细粒度上下文控制**: 选择与AI模型分享的确切内容 +- **📎 引用**: 获取带有正确源引用的答案 + +### 三栏界面 +1. **源**: 管理所有研究材料 +2. **笔记**: 创建手动或AI生成的笔记 +3. **聊天**: 使用您的内容作为上下文与AI对话 + diff --git a/apps/open-notebook/README_en.md b/apps/open-notebook/README_en.md new file mode 100644 index 0000000..5b8f7a3 --- /dev/null +++ b/apps/open-notebook/README_en.md @@ -0,0 +1,129 @@ +# Open Notebook + +A private, multi-model, 100% local, full-featured alternative to Notebook LM + +In a world dominated by Artificial Intelligence, having the ability to think 🧠 and acquire new knowledge 💡, is a skill that should not be a privilege for a few, nor restricted to a single provider. + +![](https://img.shields.io/badge/Copyright-arch3rPro-ff9800?style=flat&logo=github&logoColor=white) + +![](https://cdn.jsdelivr.net/gh/xiaoY233/PicList@main/public/assets/open-notebook.png) + +**Open Notebook empowers you to:** +- 🔒 **Control your data** - Keep your research private and secure +- 🤖 **Choose your AI models** - Support for 16+ providers including OpenAI, Anthropic, Ollama, LM Studio, and more +- 📚 **Organize multi-modal content** - PDFs, videos, audio, web pages, and more +- 🎙️ **Generate professional podcasts** - Advanced multi-speaker podcast generation +- 🔍 **Search intelligently** - Full-text and vector search across all your content +- 💬 **Chat with context** - AI conversations powered by your research + +Learn more about our project at [https://www.open-notebook.ai](https://www.open-notebook.ai) + +## 🆚 Open Notebook vs Google Notebook LM + +| Feature | Open Notebook | Google Notebook LM | Advantage | +|---------|---------------|--------------------|-----------| +| **Privacy & Control** | Self-hosted, your data | Google cloud only | Complete data sovereignty | +| **AI Provider Choice** | 16+ providers (OpenAI, Anthropic, Ollama, LM Studio, etc.) | Google models only | Flexibility and cost optimization | +| **Podcast Speakers** | 1-4 speakers with custom profiles | 2 speakers only | Extreme flexibility | +| **Context Control** | 3 granular levels | All-or-nothing | Privacy and performance tuning | +| **Content Transformations** | Custom and built-in | Limited options | Unlimited processing power | +| **API Access** | Full REST API | No API | Complete automation | +| **Deployment** | Docker, cloud, or local | Google hosted only | Deploy anywhere | +| **Citations** | Comprehensive with sources | Basic references | Research integrity | +| **Customization** | Open source, fully customizable | Closed system | Unlimited extensibility | +| **Cost** | Pay only for AI usage | Monthly subscription + usage | Transparent and controllable | + +**Why Choose Open Notebook?** +- 🔒 **Privacy First**: Your sensitive research stays completely private +- 💰 **Cost Control**: Choose cheaper AI providers or run locally with Ollama +- 🎙️ **Better Podcasts**: Full script control and multi-speaker flexibility vs limited 2-speaker deep-dive format +- 🔧 **Unlimited Customization**: Modify, extend, and integrate as needed +- 🌐 **No Vendor Lock-in**: Switch providers, deploy anywhere, own your data + + +### How Open Notebook Works + +``` +┌─────────────────────────────────────────────────────────┐ +│ Your Browser │ +│ Access: http://your-server-ip:8502 │ +└────────────────┬────────────────────────────────────────┘ + │ + ▼ + ┌───────────────┐ + │ Port 8502 │ ← Next.js Frontend (what you see) + │ Frontend │ Also proxies API requests internally! + └───────┬───────┘ + │ proxies /api/* requests ↓ + ▼ + ┌───────────────┐ + │ Port 5055 │ ← FastAPI Backend (handles requests) + │ API │ + └───────┬───────┘ + │ + ▼ + ┌───────────────┐ + │ SurrealDB │ ← Database (internal, auto-configured) + │ (Port 8000) │ + └───────────────┘ +``` + +**Key Points:** +- **v1.1+**: Next.js automatically proxies `/api/*` requests to the backend, simplifying reverse proxy setup +- Your browser loads the frontend from port 8502 +- The frontend needs to know where to find the API - when accessing remotely, set: `API_URL=http://your-server-ip:5055` +- **Behind reverse proxy?** You only need to proxy to port 8502 now! See [Reverse Proxy Guide](docs/deployment/reverse-proxy.md) + +## Provider Support Matrix + +Thanks to the [Esperanto](https://github.com/lfnovo/esperanto) library, we support this providers out of the box! + +| Provider | LLM Support | Embedding Support | Speech-to-Text | Text-to-Speech | +|--------------|-------------|------------------|----------------|----------------| +| OpenAI | ✅ | ✅ | ✅ | ✅ | +| Anthropic | ✅ | ❌ | ❌ | ❌ | +| Groq | ✅ | ❌ | ✅ | ❌ | +| Google (GenAI) | ✅ | ✅ | ❌ | ✅ | +| Vertex AI | ✅ | ✅ | ❌ | ✅ | +| Ollama | ✅ | ✅ | ❌ | ❌ | +| Perplexity | ✅ | ❌ | ❌ | ❌ | +| ElevenLabs | ❌ | ❌ | ✅ | ✅ | +| Azure OpenAI | ✅ | ✅ | ❌ | ❌ | +| Mistral | ✅ | ✅ | ❌ | ❌ | +| DeepSeek | ✅ | ❌ | ❌ | ❌ | +| Voyage | ❌ | ✅ | ❌ | ❌ | +| xAI | ✅ | ❌ | ❌ | ❌ | +| OpenRouter | ✅ | ❌ | ❌ | ❌ | +| OpenAI Compatible* | ✅ | ❌ | ❌ | ❌ | + +*Supports LM Studio and any OpenAI-compatible endpoint + +## ✨ Key Features + +### Core Capabilities +- **🔒 Privacy-First**: Your data stays under your control - no cloud dependencies +- **🎯 Multi-Notebook Organization**: Manage multiple research projects seamlessly +- **📚 Universal Content Support**: PDFs, videos, audio, web pages, Office docs, and more +- **🤖 Multi-Model AI Support**: 16+ providers including OpenAI, Anthropic, Ollama, Google, LM Studio, and more +- **🎙️ Professional Podcast Generation**: Advanced multi-speaker podcasts with Episode Profiles +- **🔍 Intelligent Search**: Full-text and vector search across all your content +- **💬 Context-Aware Chat**: AI conversations powered by your research materials +- **📝 AI-Assisted Notes**: Generate insights or write notes manually + +### Advanced Features +- **⚡ Reasoning Model Support**: Full support for thinking models like DeepSeek-R1 and Qwen3 +- **🔧 Content Transformations**: Powerful customizable actions to summarize and extract insights +- **🌐 Comprehensive REST API**: Full programmatic access for custom integrations [![API Docs](https://img.shields.io/badge/API-Documentation-blue?style=flat-square)](http://localhost:5055/docs) +- **🔐 Optional Password Protection**: Secure public deployments with authentication +- **📊 Fine-Grained Context Control**: Choose exactly what to share with AI models +- **📎 Citations**: Get answers with proper source citations + +### Three-Column Interface +1. **Sources**: Manage all your research materials +2. **Notes**: Create manual or AI-generated notes +3. **Chat**: Converse with AI using your content as context + + + + + diff --git a/apps/open-notebook/data.yml b/apps/open-notebook/data.yml new file mode 100644 index 0000000..50526e9 --- /dev/null +++ b/apps/open-notebook/data.yml @@ -0,0 +1,26 @@ +name: Open Notebook +tags: + - 实用工具 + - Web 服务器 +title: 一个开源的、注重隐私的 Google Notebook LM 替代方案! +description: + en: An open source, privacy-focused alternative to Google's Notebook LM! + zh: 一个开源的、注重隐私的 Google Notebook LM 替代方案! +additionalProperties: + key: open-notebook + name: Open Notebook + tags: + - Tool + - Server + shortDescZh: 一个开源的、注重隐私的 Google Notebook LM 替代方案! + shortDescEn: An open source, privacy-focused alternative to Google's Notebook LM! + type: website + crossVersionUpdate: true + limit: 0 + website: https://www.open-notebook.ai + github: https://github.com/lfnovo/open-notebook + document: https://www.open-notebook.ai/get-started.html + memoryRequired: 2048 + architectures: + - amd64 + - arm64 diff --git a/apps/open-notebook/latest/data.yml b/apps/open-notebook/latest/data.yml new file mode 100644 index 0000000..fed6d06 --- /dev/null +++ b/apps/open-notebook/latest/data.yml @@ -0,0 +1,26 @@ +additionalProperties: + formFields: + - default: "8502" + envKey: PANEL_APP_PORT_HTTP + required: true + type: number + labelEn: Port + labelZh: 端口 + edit: true + rule: paramPort + - default: "5055" + envKey: PANEL_APP_PORT_API + required: true + type: number + labelEn: API Port + labelZh: API端口 + edit: true + rule: paramPort + - default: "8000" + envKey: PANEL_APP_PORT_DB + required: true + type: number + labelEn: Database Port + labelZh: 数据库端口 + edit: true + rule: paramPort diff --git a/apps/open-notebook/latest/docker-compose.yml b/apps/open-notebook/latest/docker-compose.yml new file mode 100644 index 0000000..62c75ef --- /dev/null +++ b/apps/open-notebook/latest/docker-compose.yml @@ -0,0 +1,38 @@ +services: + open_notebook: + image: lfnovo/open_notebook:v1-latest + ports: + - ${PANEL_APP_PORT_HTTP}:8502 + - ${PANEL_APP_PORT_API}:5055 + env_file: + - ./docker.env + depends_on: + - surrealdb + volumes: + - ./notebook_data:/app/data + restart: always + container_name: ${CONTAINER_NAME} + networks: + - 1panel-network + labels: + createdBy: Apps + surrealdb: + image: surrealdb/surrealdb:v2 + volumes: + - ./surreal_data:/mydata + environment: + - SURREAL_EXPERIMENTAL_GRAPHQL=true + ports: + - ${PANEL_APP_PORT_DB}:8000 + command: start --log info --user root --pass root rocksdb:/mydata/mydatabase.db + pull_policy: always + user: root + restart: always + container_name: ${CONTAINER_NAME}-surrealdb + networks: + - 1panel-network + labels: + createdBy: Apps +networks: + 1panel-network: + external: true diff --git a/apps/open-notebook/latest/docker.env b/apps/open-notebook/latest/docker.env new file mode 100644 index 0000000..6f1d1da --- /dev/null +++ b/apps/open-notebook/latest/docker.env @@ -0,0 +1,259 @@ + +# API CONFIGURATION +# URL where the API can be accessed by the browser +# This setting allows the frontend to connect to the API at runtime (no rebuild needed!) +# +# IMPORTANT: Do NOT include /api at the end - it will be added automatically! +# +# Common scenarios: +# - Docker on localhost: http://localhost:5055 (default, works for most cases) +# - Docker on LAN/remote server: http://192.168.1.100:5055 or http://your-server-ip:5055 +# - Behind reverse proxy with custom domain: https://your-domain.com +# - Behind reverse proxy with subdomain: https://api.your-domain.com +# +# Examples for reverse proxy users: +# - API_URL=https://notebook.example.com (frontend will call https://notebook.example.com/api/*) +# - API_URL=https://api.example.com (frontend will call https://api.example.com/api/*) +# +# Note: If not set, the system will auto-detect based on the incoming request. +# Only set this if you need to override the auto-detection (e.g., reverse proxy scenarios). +API_URL=http://localhost:5055 + +# INTERNAL API URL (Server-Side) +# URL where Next.js server-side should proxy API requests (via rewrites) +# This is DIFFERENT from API_URL which is used by the browser client +# +# INTERNAL_API_URL is used by Next.js rewrites to forward /api/* requests to the FastAPI backend +# API_URL is used by the browser to know where to make API calls +# +# Default: http://localhost:5055 (single-container deployment - both services on same host) +# Override for multi-container: INTERNAL_API_URL=http://api-service:5055 +# +# Common scenarios: +# - Single container (default): Don't set - defaults to http://localhost:5055 +# - Multi-container Docker Compose: INTERNAL_API_URL=http://api:5055 (use service name) +# - Kubernetes/advanced networking: INTERNAL_API_URL=http://api-service.namespace.svc.cluster.local:5055 +# +# Why two variables? +# - API_URL: External/public URL that browsers use (can be https://your-domain.com) +# - INTERNAL_API_URL: Internal container networking URL (usually http://localhost:5055 or service name) +# +# INTERNAL_API_URL=http://localhost:5055 + +# API CLIENT TIMEOUT (in seconds) +# Controls how long the frontend/Streamlit UI waits for API responses +# Increase this if you're using slow AI providers or hardware (Ollama on CPU, remote LM Studio, etc.) +# Default: 300 seconds (5 minutes) - sufficient for most transformation/insight operations +# +# Common scenarios: +# - Fast cloud APIs (OpenAI, Anthropic): 300 seconds is more than enough +# - Local Ollama on GPU: 300 seconds should work fine +# - Local Ollama on CPU: Consider 600 seconds (10 minutes) or more +# - Remote LM Studio over slow network: Consider 900 seconds (15 minutes) +# - Very large documents: May need 900+ seconds +# +# API_CLIENT_TIMEOUT=300 + +# ESPERANTO LLM TIMEOUT (in seconds) +# Controls the timeout for AI model API calls at the Esperanto library level +# This is separate from API_CLIENT_TIMEOUT and applies to the actual LLM provider requests +# Only increase this if you're experiencing timeouts during model inference itself +# Default: 60 seconds (built into Esperanto) +# +# Important: This should generally be LOWER than API_CLIENT_TIMEOUT to allow proper error handling +# +# Common scenarios: +# - Fast cloud APIs (OpenAI, Anthropic, Groq): 60 seconds is sufficient +# - Local Ollama with small models: 120-180 seconds may help +# - Local Ollama with large models on CPU: 300+ seconds +# - Remote or self-hosted LLMs: 180-300 seconds depending on hardware +# +# Note: If transformations complete but you see timeout errors, increase API_CLIENT_TIMEOUT first. +# Only increase ESPERANTO_LLM_TIMEOUT if the model itself is timing out during inference. +# +# ESPERANTO_LLM_TIMEOUT=60 + +# SSL VERIFICATION CONFIGURATION +# Configure SSL certificate verification for local AI providers (Ollama, LM Studio, etc.) +# behind reverse proxies with self-signed certificates +# +# Option 1: Custom CA Bundle (recommended for self-signed certs) +# Point to your CA certificate file to verify SSL while using custom certificates +# ESPERANTO_SSL_CA_BUNDLE=/path/to/your/ca-bundle.pem +# +# Option 2: Disable SSL Verification (development only) +# WARNING: Disabling SSL verification exposes you to man-in-the-middle attacks +# Only use in trusted development/testing environments +# ESPERANTO_SSL_VERIFY=false + +# SECURITY +# Set this to protect your Open Notebook instance with a password (for public hosting) +# OPEN_NOTEBOOK_PASSWORD= + +# OPENAI +# OPENAI_API_KEY= + + +# ANTHROPIC +# ANTHROPIC_API_KEY= + +# GEMINI +# this is the best model for long context and podcast generation +# GOOGLE_API_KEY= +# GEMINI_API_BASE_URL= # Optional: Override default endpoint (for Vertex AI, proxies, etc.) + +# VERTEXAI +# VERTEX_PROJECT=my-google-cloud-project-name +# GOOGLE_APPLICATION_CREDENTIALS=./google-credentials.json +# VERTEX_LOCATION=us-east5 + +# MISTRAL +# MISTRAL_API_KEY= + +# DEEPSEEK +# DEEPSEEK_API_KEY= + +# OLLAMA +# OLLAMA_API_BASE="http://10.20.30.20:11434" + +# OPEN ROUTER +# OPENROUTER_BASE_URL="https://openrouter.ai/api/v1" +# OPENROUTER_API_KEY= + +# GROQ +# GROQ_API_KEY= + +# XAI +# XAI_API_KEY= + +# ELEVENLABS +# Used only by the podcast feature +# ELEVENLABS_API_KEY= + +# TTS BATCH SIZE +# Controls concurrent TTS requests for podcast generation (default: 5) +# Lower values reduce provider load but increase generation time +# Recommended: OpenAI=5, ElevenLabs=2, Google=4, Custom=1 +# TTS_BATCH_SIZE=2 + +# VOYAGE AI +# VOYAGE_API_KEY= + +# OPENAI COMPATIBLE ENDPOINTS +# Generic configuration (applies to all modalities: language, embedding, STT, TTS) +# OPENAI_COMPATIBLE_BASE_URL=http://localhost:1234/v1 +# OPENAI_COMPATIBLE_API_KEY= + +# Mode-specific configuration (overrides generic if set) +# Use these when you want different endpoints for different capabilities +# OPENAI_COMPATIBLE_BASE_URL_LLM=http://localhost:1234/v1 +# OPENAI_COMPATIBLE_API_KEY_LLM= +# OPENAI_COMPATIBLE_BASE_URL_EMBEDDING=http://localhost:8080/v1 +# OPENAI_COMPATIBLE_API_KEY_EMBEDDING= +# OPENAI_COMPATIBLE_BASE_URL_STT=http://localhost:9000/v1 +# OPENAI_COMPATIBLE_API_KEY_STT= +# OPENAI_COMPATIBLE_BASE_URL_TTS=http://localhost:9000/v1 +# OPENAI_COMPATIBLE_API_KEY_TTS= + +# AZURE OPENAI +# Generic configuration (applies to all modalities: language, embedding, STT, TTS) +# AZURE_OPENAI_API_KEY= +# AZURE_OPENAI_ENDPOINT= +# AZURE_OPENAI_API_VERSION=2024-12-01-preview + +# Mode-specific configuration (overrides generic if set) +# Use these when you want different deployments for different AI capabilities +# AZURE_OPENAI_API_KEY_LLM= +# AZURE_OPENAI_ENDPOINT_LLM= +# AZURE_OPENAI_API_VERSION_LLM= + +# AZURE_OPENAI_API_KEY_EMBEDDING= +# AZURE_OPENAI_ENDPOINT_EMBEDDING= +# AZURE_OPENAI_API_VERSION_EMBEDDING= + +# AZURE_OPENAI_API_KEY_STT= +# AZURE_OPENAI_ENDPOINT_STT= +# AZURE_OPENAI_API_VERSION_STT= + +# AZURE_OPENAI_API_KEY_TTS= +# AZURE_OPENAI_ENDPOINT_TTS= +# AZURE_OPENAI_API_VERSION_TTS= + +# USE THIS IF YOU WANT TO DEBUG THE APP ON LANGSMITH +# LANGCHAIN_TRACING_V2=true +# LANGCHAIN_ENDPOINT="https://api.smith.langchain.com" +# LANGCHAIN_API_KEY= +# LANGCHAIN_PROJECT="Open Notebook" + +# CONNECTION DETAILS FOR YOUR SURREAL DB +# New format (preferred) - WebSocket URL +SURREAL_URL="ws://surrealdb/rpc:8000" +SURREAL_USER="root" +SURREAL_PASSWORD="root" +SURREAL_NAMESPACE="open_notebook" +SURREAL_DATABASE="staging" + +# RETRY CONFIGURATION (surreal-commands v1.2.0+) +# Global defaults for all background commands unless explicitly overridden at command level +# These settings help commands automatically recover from transient failures like: +# - Database transaction conflicts during concurrent operations +# - Network timeouts when calling external APIs +# - Rate limits from LLM/embedding providers +# - Temporary resource unavailability + +# Enable/disable retry globally (default: true) +# Set to false to disable retries for all commands (useful for debugging) +SURREAL_COMMANDS_RETRY_ENABLED=true + +# Maximum retry attempts before giving up (default: 3) +# Database operations use 5 attempts (defined per-command) +# API calls use 3 attempts (defined per-command) +SURREAL_COMMANDS_RETRY_MAX_ATTEMPTS=3 + +# Wait strategy between retry attempts (default: exponential_jitter) +# Options: exponential_jitter, exponential, fixed, random +# - exponential_jitter: Recommended - prevents thundering herd during DB conflicts +# - exponential: Good for API rate limits (predictable backoff) +# - fixed: Use for quick recovery scenarios +# - random: Use when you want unpredictable retry timing +SURREAL_COMMANDS_RETRY_WAIT_STRATEGY=exponential_jitter + +# Minimum wait time between retries in seconds (default: 1) +# Database conflicts: 1 second (fast retry for transient issues) +# API rate limits: 5 seconds (wait for quota reset) +SURREAL_COMMANDS_RETRY_WAIT_MIN=1 + +# Maximum wait time between retries in seconds (default: 30) +# Database conflicts: 30 seconds maximum +# API rate limits: 120 seconds maximum (defined per-command) +# Total retry time won't exceed max_attempts * wait_max +SURREAL_COMMANDS_RETRY_WAIT_MAX=30 + +# WORKER CONCURRENCY +# Maximum number of concurrent tasks in the worker pool (default: 5) +# This affects the likelihood of database transaction conflicts during batch operations +# +# Tuning guidelines based on deployment size: +# - Resource-constrained (low CPU/memory): 1-2 workers +# Reduces conflicts and resource usage, but slower processing +# +# - Normal deployment (balanced): 5 workers (RECOMMENDED) +# Good balance between throughput and conflict rate +# Retry logic handles occasional conflicts gracefully +# +# - Large instances (high CPU/memory): 10-20 workers +# Higher throughput but more frequent DB conflicts +# Relies heavily on retry logic with jittered backoff +# +# Note: Higher concurrency increases vectorization speed but also increases +# SurrealDB transaction conflicts. The retry logic with exponential-jitter +# backoff ensures operations complete successfully even at high concurrency. +SURREAL_COMMANDS_MAX_TASKS=5 + +# OPEN_NOTEBOOK_PASSWORD= + +# FIRECRAWL - Get a key at https://firecrawl.dev/ +FIRECRAWL_API_KEY= + +# JINA - Get a key at https://jina.ai/ +JINA_API_KEY= \ No newline at end of file diff --git a/apps/open-notebook/logo.png b/apps/open-notebook/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0e75264879652a467f4f5dee9975e99768ce1388 GIT binary patch literal 48532 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 literal 0 HcmV?d00001