OpenSource-Hub

open-notebook

애플리케이션

lfnovo/open-notebook

다양한 AI 모델을 지원하는 오픈 소스 프라이버시 노트 애플리케이션.

개요

프라이버시와 유연성에 중점을 둔 오픈소스 셀프호스팅 Notebook LM 대안. 18개 이상의 AI 제공업체, 멀티모달 콘텐츠 및 사용자 정의 가능한 팟캐스트 생성 기능을 지원합니다.

README 미리보기

\n\n\n[![Forks][forks-shield]][forks-url]\n[![Stargazers][stars-shield]][stars-url]\n[![Issues][issues-shield]][issues-url]\n[![MIT License][license-shield]][license-url]\n\n\n\n\n\n\n  \n    \n  \n\n  Open Notebook\n\n  \n    An open source, privacy-focused alternative to Google's Notebook LM!\n    Join our Discord server for help, to share workflow ideas, and suggest features!\n    \n    Checkout our website »\n    \n    \n    📚 Get Started\n    ·\n    📖 User Guide\n    ·\n    ✨ Features\n    ·\n    🚀 Deploy\n  \n\n\n\n\n\n\n\n  \n  Deutsch | \n  Español | \n  français | \n  日本語 | \n  한국어 | \n  Português | \n  Русский | \n  中文\n\n\n## A private, multi-model, 100% local, full-featured alternative to Notebook LM\n\n\n\nIn 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.\n\n**Open Notebook empowers you to:**\n- 🔒 **Control your data** - Keep your research private and secure\n- 🤖 **Choose your AI models** - Support for 18+ providers including OpenAI, Anthropic, Ollama, LM Studio, and more\n- 📚 **Organize multi-modal content** - PDFs, videos, audio, web pages, and more\n- 🎙️ **Generate professional podcasts** - Advanced multi-speaker podcast generation\n- 🔍 **Search intelligently** - Full-text and vector search across all your content\n- 💬 **Chat with context** - AI conversations powered by your research\n- 🌐 **Multi-language UI** - English, Portuguese, Chinese (Simplified & Traditional), Japanese, Russian, and Bengali support\n\nLearn more about our project at [https://www.open-notebook.ai](https://www.open-notebook.ai)\n\n---\n\n## 🆚 Open Notebook vs Google Notebook LM\n\n| Feature | Open Notebook | Google Notebook LM | Advantage |\n|---------|---------------|--------------------|-----------|\n| **Privacy & Control** | Self-hosted, your data | Google cloud only | Complete data sovereignty |\n| **AI Provider Cho

FAQ (5)

문제 해결
소스 채팅 스트리밍에서 이전 답변이 모두 반복되고 새로고침 후 컨텍스트 배지가 사라지는 문제를 해결하려면 어떻게 해야 하나요?

소스 채팅 스트리밍 및 세션 로드 경로의 두 가지 문제를 모두 수정하세요.

1. 스트리밍 중에 체크포인트된 전체 메시지 기록을 전송하지 마세요. api/routers/source_chat.py의 376–384행 근처에서 result["messages"]의 모든 항목을 순회하지 마세요. 최신 AI 메시지만 내보내세요:

last_message = result["messages"][-1]
# last_message에 대해서만 ai_message 이벤트를 내보냅니다

2. 기존 세션이 로드될 때 컨텍스트 인디케이터를 복원하세요. frontend/src/lib/hooks/use-source-chat.ts에서 41–45행 근처의 세션 로드 이펙트를 업데이트하세요:

setContextIndicators(currentSession.context_indicators ?? null);

백엔드는 이미 api/routers/source_chat.py의 GET 세션에서 context_indicators를 반환하고 있으며, 이 훅은 SSE 이벤트를 통해서만 이를 설정하고 있었습니다. 이러한 변경 후에는 후속 스트리밍 답변에 새 답변만 포함되고, 페이지를 새로 고친 후에도 소스 개수가 계속 표시됩니다. main 커밋 3959eb0을 기준으로 검증되었습니다.

원본 Issue #1393
문제 해결
배치 삽입 실패 후 소스가 임베딩된 것으로 보이지만 벡터 검색에서 문서의 일부만 반환되는 이유는 무엇인가요?

배치로 실행된 repo_insert 호출은 원자적이지 않습니다. 첫 번째 이후의 배치가 실패하면 이전에 삽입된 source_embedding 행이 그대로 남습니다. 임베딩 여부 확인이 하나의 행만 조회하기 때문에(LIMIT 1), 해당 소스가 완전히 임베딩된 것으로 잘못 표시됩니다. commands/embedding_commands.py의 embed_source를 수정하여 insert를 try/except로 감싸고, 실패 시 해당 소스의 임베딩을 삭제한 뒤 원래 예외를 다시 발생시키세요:

try:
    await repo_insert(...)
except Exception:
    await db.execute(
        "DELETE FROM source_embedding WHERE source = $source_id",
        {"source_id": source_id},
    )
    raise

이후 배치가 실패하도록 강제하는 테스트를 추가하고, source_embedding에 해당 소스의 행이 0개인지와 원래 예외가 변경 없이 그대로 전파되는지 확인하세요.

원본 Issue #1390
문제 해결
빈 노트북이나 transformation 설명이 새로 고침 후에도 유지되지 않는 문제를 해결하려면 어떻게 해야 하나요?

빈 문자열이 PATCH 요청 전에 제거되고 있습니다. frontend/src/app/(dashboard)/notebooks/components/NotebookHeader.tsx에서 description: description || undefined를 description: description으로 교체하세요. frontend/src/app/(dashboard)/transformations/components/TransformationEditorDialog.tsx의 title 및 description 필드에도 동일한 변경을 적용하세요. 백엔드에서는 api/routers/notebooks.py와 api/routers/transformations.py를 업데이트하여 생략된 필드와 명시적으로 ""로 설정된 필드를 구분하세요. is not None만 확인하는 대신 Pydantic의 model_fields_set 또는 model_dump(exclude_unset=True)를 사용하세요. description: ""를 포함한 PATCH로 확인하세요. 이 경우 필드가 지워져야 하며, description을 생략하면 기존 값이 변경되지 않고 유지되어야 합니다.

원본 Issue #1396
문제 해결
IP가 플래그된 네트워크에서 차단된 YouTube 트랜스크립트 요청을 어떻게 해결하나요?

content-core 2.2 이상을 사용하고 YouTube 쿠키와 레지덴셜 프록시를 구성하세요. YouTube 쿠키를 Netscape cookies.txt 형식으로 내보내고, 파일을 컨테이너에 마운트한 후 다음과 같이 설정하세요:

-e CCORE_YOUTUBE_COOKIES_FILE=/run/secrets/cookies.txt \
-e CCORE_YOUTUBE_PROXY=http://user:password@residential-proxy:port \
-v /path/to/cookies.txt:/run/secrets/cookies.txt:ro

프록시는 트랜스크립트 가져오기, pytubefix 폴백, 제목 조회에 사용됩니다. 레지덴셜 프록시를 사용해야 하며, 데이터센터 프록시는 차단됩니다. 쿠키 파일이 없거나 읽을 수 없으면 ConfigurationError가 발생하므로, 마운트된 경로와 파일 권한을 확인한 후 워커/컨테이너를 다시 시작하세요.

원본 Issue #1439
문제 해결
Open Notebook에서 LLM 호출이 60초 후에 타임아웃되는 문제를 어떻게 해결하나요? 특히 Ollama나 추론 모델을 사용할 때요.

esperanto 2.28+에서는 to_langchain()이 모든 프로바이더에 대해 ESPERANTO_LLM_TIMEOUT을 강제 적용합니다. 설정되어 있지 않으면 실질적인 기본값은 60초이므로, 긴 응답이나 느린 로컬 모델은 실패할 수 있습니다. 이 값의 기본값이 180초로 설정된 Open Notebook 릴리스로 업그레이드하거나, API와 워커를 시작하기 전에 명시적으로 설정하세요:

export ESPERANTO_LLM_TIMEOUT=180

느린 로컬 모델의 경우 더 큰 값을 사용하고 API_CLIENT_TIMEOUT도 함께 늘리되, LLM 타임아웃에 버퍼를 더한 값보다 크게 유지하세요:

export ESPERANTO_LLM_TIMEOUT=600
export API_CLIENT_TIMEOUT=720

코드에서는 모델이 생성되기 전에 다음과 같이 기본값을 적용할 수 있습니다:

os.environ.setdefault("ESPERANTO_LLM_TIMEOUT", "180")

명시적으로 설정된 ESPERANTO_LLM_TIMEOUT이 항상 우선합니다. STT/TTS 타임아웃 변수는 별도이며 esperanto의 300초 기본값으로 유지됩니다.

원본 Issue #1434