[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-79885":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":12,"openIssues":14,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":14,"stars7d":14,"stars30d":15,"stars90d":14,"forks30d":14,"starsTrendScore":14,"compositeScore":16,"rankGlobal":10,"rankLanguage":10,"license":17,"archived":18,"fork":18,"defaultBranch":19,"hasWiki":20,"hasPages":18,"topics":21,"createdAt":10,"pushedAt":10,"updatedAt":22,"readmeContent":23,"aiSummary":24,"trendingCount":14,"starSnapshotCount":14,"syncStatus":25,"lastSyncTime":26,"discoverSource":27},79885,"nano-NotebookLM","ArthurYangX\u002Fnano-NotebookLM","ArthurYangX","An open-source AI study assistant that turns course materials into notes, knowledge graphs, cited answers, and exam prep questions.","",null,"Python",1,15,0,104,53.61,"Apache License 2.0",false,"main",true,[],"2026-06-11 04:06:55","\u003Cdiv align=\"center\">\n\n# nano-NotebookLM\n\n**A self-hosted, open-source study assistant — chat with citations, structured LaTeX notes, exam-prep with a self-evolving question bank, and an editable knowledge graph.**\n\n[![License: Apache 2.0](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLicense-Apache_2.0-blue.svg)](LICENSE)\n[![Python 3.10+](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fpython-3.10+-blue.svg)](https:\u002F\u002Fwww.python.org\u002Fdownloads\u002F)\n[![Tests](https:\u002F\u002Fgithub.com\u002FArthurYangX\u002Fnano-NotebookLM\u002Factions\u002Fworkflows\u002Ftest.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002FArthurYangX\u002Fnano-NotebookLM\u002Factions\u002Fworkflows\u002Ftest.yml)\n[![Code style](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fcode%20style-black-000000.svg)](https:\u002F\u002Fgithub.com\u002Fpsf\u002Fblack)\n[![PRs welcome](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FPRs-welcome-brightgreen.svg)](CONTRIBUTING.md)\n\nEnglish | [简体中文](README.zh-CN.md)\n\n\u003Csub>Not affiliated with Google. NotebookLM is a trademark of Google LLC.\u003C\u002Fsub>\n\nhttps:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F39469b3a-fddf-4341-8671-39aae9775176\n\n\u003C\u002Fdiv>\n\n---\n\n## Overview\n\nUpload course PDFs \u002F PPTX \u002F DOCX \u002F Markdown → automatic knowledge graph\n+ vector index → chat with **page-accurate citations**, structured\nLaTeX notes, practice quizzes, exam prep with a **self-evolving question\nbank**, and an editable mind map.\n\nBring your own model: **DeepSeek · OpenAI · Anthropic Claude · Gemini\n· and 11+ more** named cloud providers, or any local runner that speaks\nOpenAI's `\u002Fv1\u002Fchat\u002Fcompletions` (**Ollama \u002F vLLM \u002F LM Studio \u002F\nllama.cpp**). See the [Provider matrix](#provider-matrix) for the full\nlist.\n\n---\n\n## Quick Start\n\n```bash\n# 1. clone + install (uv is ~10× faster than pip; either works)\ngit clone https:\u002F\u002Fgithub.com\u002FArthurYangX\u002Fnano-NotebookLM && cd nano-NotebookLM\nuv venv && source .venv\u002Fbin\u002Factivate && uv pip install -e \".[test]\"\n# or: python -m venv .venv && source .venv\u002Fbin\u002Factivate && pip install -e \".[test]\"\n\n# 2. configure — copy the template and fill AT LEAST ONE LLM key\n#    (OPENAI_API_KEY, or ANTHROPIC_API_KEY, or LOCAL_LLM_BASE_URL+LOCAL_LLM_MODEL)\ncp .env.example .env\n\n# 3. run (Ctrl-C to stop; or use .\u002Fdev.sh below to manage as a background process)\npython api\u002Fserver.py\n```\n\n### → Open [`http:\u002F\u002Flocalhost:8000`](http:\u002F\u002Flocalhost:8000) in your browser\n\nThen click the **⚙ Settings** gear (top-right of the topbar) to manage\nLLM providers — add or swap a provider, switch the active default, or\nhit **Test** for a 5-second connectivity ping. All without restarting\nthe server. The `.env` values you just filled in seed the first row;\nonce Settings exists, the UI is the source of truth (writes go to\n`artifacts\u002Fproviders.json`).\n\n---\n\nPrefer a managed lifecycle? `.\u002Fdev.sh` wraps the same commands:\n\n```bash\n.\u002Fdev.sh install   # creates .venv + installs deps + seeds .env\n.\u002Fdev.sh up        # starts the server in background, waits for \u002Fapi\u002Fhealth\n.\u002Fdev.sh status    # pid + \u002Fapi\u002Fstatus snapshot\n.\u002Fdev.sh logs      # tail \u002Ftmp\u002Fnano-nlm.log\n.\u002Fdev.sh down      # stops the server\n```\n\n> Install `uv` for ~10× faster setup:\n> `curl -LsSf https:\u002F\u002Fastral.sh\u002Fuv\u002Finstall.sh | sh` — full docs at\n> \u003Chttps:\u002F\u002Fdocs.astral.sh\u002Fuv\u002Fgetting-started\u002Finstallation\u002F>.\n> Plain `pip` works identically if you'd rather skip it.\n\n#### Optional extras (only install what you need)\n\n| What | Install | Without it |\n|---|---|---|\n| **MinerU** — OCR \u002F layout-aware PDF extractor for scanned slides | `uv pip install -e \".[mineru]\"` (heavy: ~3-5GB w\u002F models) | Upload `engine=mineru` returns an error; `engine=pymupdf` (default) still works |\n| **tectonic** — LaTeX → PDF compiler for Notes export | `brew install tectonic` \u002F `apt install tectonic` | \"Export PDF\" button is hidden; in-browser KaTeX preview still works |\n| **LibreOffice** (`soffice`) — `.pptx` → PDF sidecar for MinerU | `brew install --cask libreoffice` \u002F `apt install libreoffice` | `.pptx` with `engine=mineru` silently falls back to python-pptx (no OCR) |\n\nGPU: MinerU auto-detects CUDA on Linux (1–2 s\u002Fpage); Apple Silicon\ndefaults to CPU (~12 s\u002Fpage) — auto-detect never picks MPS because the\npipeline backend hangs there. Override with\n`MINERU_DEVICE_MODE=cuda|cpu|mps` in `.env`. **Escape hatch**: if CUDA\nis detected but breaks at runtime (stale driver \u002F OOM), set\n`MINERU_DEVICE_MODE=cpu` to force CPU.\n\n> **Network requirement.** The frontend loads React \u002F KaTeX \u002F d3-force\n> \u002F CodeMirror \u002F IBM Plex fonts from public CDNs (jsdelivr, unpkg,\n> esm.sh, Google Fonts) — first page-load needs internet. Fully\n> air-gapped deployments will need to vendor those assets locally.\n\n> Looking for architecture and code map? See [`CLAUDE.md`](CLAUDE.md).\n> Want to contribute? See [`CONTRIBUTING.md`](CONTRIBUTING.md).\n\n---\n\n## Why nano-NotebookLM\n\n| Capability                                | nano-NotebookLM   | [open-notebook](https:\u002F\u002Fgithub.com\u002Flfnovo\u002Fopen-notebook) | Google NotebookLM | ChatGPT (upload PDF) |\n|-------------------------------------------|:-----------------:|:-----------------:|:-----------------:|:--------------------:|\n| Fully self-hosted, your data never leaves | ✅                | ✅                | ❌                | ❌                   |\n| Bring your own LLM (cloud or local)       | ✅ 20+ providers (any OpenAI-compatible endpoint) | ✅ 18+ providers  | ❌ Gemini only    | ❌ OpenAI only       |\n| **Page-accurate citations**, click to jump | ✅               | ⚠️ basic refs     | ✅                | ⚠️ inline quote only |\n| Editable knowledge graph                  | ✅                | ❌                | ❌                | ❌                   |\n| LaTeX notes (KaTeX + tectonic PDF)        | ✅                | ❌                | ❌                | ❌                   |\n| Exam prep with self-evolving question bank | ✅               | ❌                | ❌                | ❌                   |\n| Background upload pipeline, resumable     | ✅                | ⚠️ async, no stages | ✅              | ⚠️ session-bound     |\n| Cross-course retrieval                    | ✅                | ⚠️ within-notebook only | ❌          | ❌                   |\n| Podcast \u002F multi-speaker audio generation  | ❌                | ✅                | ✅ (2-speaker)    | ❌                   |\n| Audio \u002F video \u002F web-page ingestion        | 🔜 future (today: PDF\u002FPPTX\u002FDOCX\u002FMD) | ✅            | ✅                | ⚠️ varies            |\n| Cost at scale                             | Local GPU \u002F API   | Local GPU \u002F API   | Free tier capped  | Subscription         |\n\n> **Choosing between nano-NotebookLM and open-notebook:** **open-notebook** is strong at multi-modal ingestion (audio \u002F video \u002F web) and podcast generation. **nano-NotebookLM** is strong at the deep-reading loop — page-accurate citations into a built-in PDF reader, an editable knowledge graph, LaTeX notes (KaTeX + tectonic PDF), and an exam-prep mode that grows a question bank around the topics you got wrong. Provider coverage is comparable — both are OpenAI-compatible, so any `\u002Fv1\u002Fchat\u002Fcompletions` endpoint plugs into either.\n\n---\n\n## Features\n\n- **Chat with page-accurate citations** — RAG (BM25 + FAISS + RRF) +\n  knowledge-graph retriever (concept-cosine seed + BFS hop expansion).\n  Every answer links back to the source page in the built-in PDF reader.\n- **LaTeX notes** — per-source-file streaming generation with a global\n  review pass. KaTeX in the browser; optional `tectonic` compile to PDF.\n- **Practice quizzes + Exam Prep** — generates questions, grades them,\n  and **auto-generates variants of the ones you got wrong** so the bank\n  grows in the directions you actually need.\n- **Editable knowledge graph** — d3-force layout with relation filters,\n  double-click edit, shift-drag to connect, `N` to add child, `Del` to\n  remove. Edits persist as an overlay so re-extraction never clobbers\n  your work.\n- **Reader** — built-in PDF \u002F PPTX preview, click any citation chip in a\n  chat answer or note to jump to the exact page.\n- **Background upload pipeline** — close the tab and come back; the\n  ingest job keeps running.\n\n### See it in action\n\n\u003Ctable>\n\u003Ctr>\n\u003Ctd width=\"50%\" valign=\"top\">\n  \u003Cimg src=\"docs\u002Fscreenshots\u002Fnotes.png\" alt=\"LaTeX Notes\">\n  \u003Cbr>\u003Cb>LaTeX Notes\u003C\u002Fb> — per-file streaming generation, KaTeX preview, click any citation chip to jump to the source page.\n\u003C\u002Ftd>\n\u003Ctd width=\"50%\" valign=\"top\">\n  \u003Cimg src=\"docs\u002Fscreenshots\u002Fmindmap.png\" alt=\"Knowledge Graph\">\n  \u003Cbr>\u003Cb>Knowledge Graph\u003C\u002Fb> — d3-force layout with relation filters (part-of \u002F depends-on \u002F related \u002F example-of). Edit overlay survives re-extraction.\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd width=\"50%\" valign=\"top\">\n  \u003Cimg src=\"docs\u002Fscreenshots\u002Fexam-prep.png\" alt=\"Exam Prep\">\n  \u003Cbr>\u003Cb>Exam Prep\u003C\u002Fb> — topics weighted by mastery; wrong answers auto-spawn variant questions so the bank grows where you need it.\n\u003C\u002Ftd>\n\u003Ctd width=\"50%\" valign=\"top\">\n  \u003Cimg src=\"docs\u002Fscreenshots\u002Fchat-citations.png\" alt=\"Chat with cited sources\">\n  \u003Cbr>\u003Cb>Chat with cited sources\u003C\u002Fb> — every answer ends with chips like \u003Ccode>ch3.pdf, Page 32\u002F51\u003C\u002Fcode> pointing at the exact source file and page; click to jump there. Bilingual sectioned format (课件覆盖 \u002F 补充背景) makes it explicit which part came from your slides vs general background.\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\n---\n\n## Provider matrix\n\n| Provider              | Type             | `OPENAI_BASE_URL`                                              | Suggested model                              |\n|-----------------------|------------------|----------------------------------------------------------------|----------------------------------------------|\n| **[DeepSeek](https:\u002F\u002Fapi-docs.deepseek.com\u002F) ★ (used during development)** | Cloud, compat | `https:\u002F\u002Fapi.deepseek.com\u002Fv1`                                  | `deepseek-v4-pro`                            |\n| [OpenAI](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference)               | Cloud, native    | `https:\u002F\u002Fapi.openai.com\u002Fv1`                                    | `gpt-4o-mini`                                |\n| [Anthropic Claude](https:\u002F\u002Fdocs.anthropic.com\u002Fen\u002Fapi\u002Fgetting-started)  | Cloud, native    | *(uses Anthropic SDK)*                                         | `claude-sonnet-4-5`                          |\n| [Moonshot (Kimi)](https:\u002F\u002Fplatform.moonshot.cn\u002Fdocs)                   | Cloud, compat    | `https:\u002F\u002Fapi.moonshot.cn\u002Fv1`                                   | `moonshot-v1-8k`                             |\n| [Zhipu GLM](https:\u002F\u002Fdocs.bigmodel.cn\u002F)                                 | Cloud, compat    | `https:\u002F\u002Fopen.bigmodel.cn\u002Fapi\u002Fpaas\u002Fv4`                         | `glm-4-flash`                                |\n| [MiniMax](https:\u002F\u002Fwww.minimax.io\u002Fplatform_overview)                    | Cloud, compat    | `https:\u002F\u002Fapi.minimax.chat\u002Fv1`                                  | `abab6.5-chat`                               |\n| [Groq](https:\u002F\u002Fconsole.groq.com\u002Fdocs\u002Fquickstart)                       | Cloud, compat    | `https:\u002F\u002Fapi.groq.com\u002Fopenai\u002Fv1`                               | `llama-3.3-70b-versatile`                    |\n| [Together](https:\u002F\u002Fdocs.together.ai\u002Fdocs\u002Fopenai-api-compatibility)     | Cloud, compat    | `https:\u002F\u002Fapi.together.xyz\u002Fv1`                                  | `meta-llama\u002FLlama-3.3-70B-Instruct-Turbo`    |\n| [Gemini (OpenAI mode)](https:\u002F\u002Fai.google.dev\u002Fgemini-api\u002Fdocs\u002Fopenai)   | Cloud, compat    | `https:\u002F\u002Fgenerativelanguage.googleapis.com\u002Fv1beta\u002Fopenai\u002F`     | `gemini-2.0-flash`                           |\n| [xAI (Grok)](https:\u002F\u002Fdocs.x.ai\u002Fdocs\u002Foverview)                          | Cloud, compat    | `https:\u002F\u002Fapi.x.ai\u002Fv1`                                          | `grok-4`                                     |\n| [OpenRouter](https:\u002F\u002Fopenrouter.ai\u002Fdocs\u002Fquickstart)                    | Cloud, compat    | `https:\u002F\u002Fopenrouter.ai\u002Fapi\u002Fv1`                                 | `openai\u002Fgpt-4o-mini` *(any `vendor\u002Fmodel` id)* |\n| [Perplexity](https:\u002F\u002Fdocs.perplexity.ai\u002Fgetting-started\u002Fquickstart)    | Cloud, compat    | `https:\u002F\u002Fapi.perplexity.ai` *(no `\u002Fv1`)*                       | `sonar-pro`                                  |\n| [Mistral](https:\u002F\u002Fdocs.mistral.ai\u002Fapi\u002F)                                | Cloud, compat    | `https:\u002F\u002Fapi.mistral.ai\u002Fv1`                                    | `mistral-large-latest`                       |\n| [DashScope (Qwen)](https:\u002F\u002Fwww.alibabacloud.com\u002Fhelp\u002Fen\u002Fmodel-studio\u002Fcompatibility-of-openai-with-dashscope) | Cloud, compat | `https:\u002F\u002Fdashscope-intl.aliyuncs.com\u002Fcompatible-mode\u002Fv1` | `qwen-plus`                                  |\n| [Fireworks](https:\u002F\u002Fdocs.fireworks.ai\u002Fgetting-started\u002Fquickstart)      | Cloud, compat    | `https:\u002F\u002Fapi.fireworks.ai\u002Finference\u002Fv1`                        | `accounts\u002Ffireworks\u002Fmodels\u002Fdeepseek-v3p1`    |\n| [SiliconFlow](https:\u002F\u002Fdocs.siliconflow.cn\u002Fen\u002Fuserguide\u002Fquickstart)     | Cloud, compat    | `https:\u002F\u002Fapi.siliconflow.cn\u002Fv1`                                | `Qwen\u002FQwen2.5-72B-Instruct`                  |\n| [Cerebras](https:\u002F\u002Finference-docs.cerebras.ai\u002Fintroduction)            | Cloud, compat    | `https:\u002F\u002Fapi.cerebras.ai\u002Fv1`                                   | `llama-3.3-70b`                              |\n| **[Ollama](https:\u002F\u002Follama.com\u002Flibrary) ★**                             | Local            | `http:\u002F\u002Flocalhost:11434\u002Fv1`                                    | `qwen3:14b` *(suggested as open source model)*     |\n| **[vLLM](https:\u002F\u002Fdocs.vllm.ai\u002Fen\u002Flatest\u002F)**                            | Local            | `http:\u002F\u002Flocalhost:8001\u002Fv1` *(pick any free port; **not** 8000 — that's the app server)* | `Qwen\u002FQwen2.5-7B-Instruct`                   |\n| **[LM Studio](https:\u002F\u002Flmstudio.ai\u002Fdocs\u002Fapp\u002Fapi)**                      | Local            | `http:\u002F\u002Flocalhost:1234\u002Fv1`                                     | *(model loaded in LM Studio)*                |\n| **[llama.cpp server](https:\u002F\u002Fgithub.com\u002Fggml-org\u002Fllama.cpp\u002Fblob\u002Fmaster\u002Ftools\u002Fserver\u002FREADME.md)** | Local | `http:\u002F\u002Flocalhost:8080\u002Fv1`                                     | *(GGUF model loaded)*                        |\n\nYou can mix freely — add a cloud OpenAI key for high-quality KG\nextraction, point chat at a local 7B for privacy, and the Settings UI\nswaps between them per-task without restart.\n\n### Editing providers from the UI (no restart)\n\n`.env` is **just the first-boot seed**. On first start the server\nsynthesises `artifacts\u002Fproviders.json` from your env vars and from then\non the Settings page is the source of truth: add a second\nOpenAI-compatible endpoint, swap a model, set the active default, or\none-click **Test → 5s ping** — all without restarting. Keys can stay in\n`.env` (`api_key_ref: env:VAR`) or be stored inline if you prefer\n(`api_key_ref: literal:sk-…`; written 0o600, never echoed in any\nresponse).\n\n| Endpoint                                    | Purpose                              |\n|---------------------------------------------|--------------------------------------|\n| `GET    \u002Fapi\u002Fproviders`                     | List configured providers (redacted) |\n| `PUT    \u002Fapi\u002Fproviders\u002F{id}`                | Create or update                     |\n| `DELETE \u002Fapi\u002Fproviders\u002F{id}`                | Remove (refuses default \u002F last row)  |\n| `POST   \u002Fapi\u002Fproviders\u002F{id}\u002Ftest`           | 5-token ping with 5s timeout         |\n| `POST   \u002Fapi\u002Fproviders\u002Fdefault`             | Switch active default                |\n\n---\n\n## Embeddings\n\nThree switchable presets, picked from the Settings UI (no restart, no\ndestructive rebuild — each preset gets its own FAISS namespace under\n`indices\u002Ffaiss\u002F\u003Cpreset>\u002F`, so toggling is a path-route):\n\n| Preset         | Model                                            | Notes                                       |\n|----------------|--------------------------------------------------|---------------------------------------------|\n| `local_mini`   | `paraphrase-multilingual-MiniLM-L12-v2`          | Offline, 50+ languages, CJK-friendly (default) |\n| `openai_large` | `text-embedding-3-large`                         | Best cross-lingual quality, costs money     |\n| `bge_m3`       | `BAAI\u002Fbge-m3`                                    | Strong CJK + EN, runs locally (heavier)     |\n\nThe first switch to a never-used preset kicks off a one-shot background\nrebuild of every course's index; the banner in the topbar tracks\nprogress. Switching back to an already-built preset is instant.\n\nThe env vars in `.env.example` (`EMBEDDING_MODE` \u002F `EMBEDDING_MODEL` \u002F\n`EMBEDDING_API_*`) only seed the first-run default — once the Settings\npreset is set, it wins.\n\n---\n\n## Main API endpoints\n\n| Endpoint                                    | Purpose                                                                     |\n|---------------------------------------------|-----------------------------------------------------------------------------|\n| `POST \u002Fapi\u002Fchat`                            | RAG + KG retrieval chat with citations and intent routing.                  |\n| `POST \u002Fapi\u002Fagent\u002Fstream`                    | Multi-turn tool-calling agent (NDJSON stream).                              |\n| `POST \u002Fapi\u002Fnotes\u002Ffull-course\u002Fstream`        | Per-file LaTeX note generation with review pass; incremental cache.         |\n| `POST \u002Fapi\u002Fquiz`                            | Practice quiz generation.                                                   |\n| `POST \u002Fapi\u002Fexam-prep\u002F*`                     | Topic planning, question seeding, quiz draw, submit + auto-variant.         |\n| `GET\u002FPOST \u002Fapi\u002Fmindmap\u002F{course_id}`         | Knowledge graph read; student edit ops.                                     |\n| `POST \u002Fapi\u002Fupload\u002F{course_id}`              | Upload files; returns `{task_id, course_id}` immediately.                   |\n| `GET  \u002Fapi\u002Fupload\u002Fstatus\u002F{task_id}`         | Poll background ingest progress (resume on tab reopen).                     |\n| `GET  \u002Fapi\u002Fstatus`                          | Configured backends, embedding mode, version, latency p50.                  |\n\nExample:\n\n```bash\ncurl -X POST http:\u002F\u002Flocalhost:8000\u002Fapi\u002Fchat \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"question\": \"What is a receptive field?\", \"course_id\": null, \"backend\": \"openai-main\"}'\n```\n\n`backend` is optional — set it to any provider id from\n`GET \u002Fapi\u002Fproviders` (e.g. `\"openai-main\"`, `\"claude-main\"`, or a\nuser-added `\"openai-alt\"`) to override the default routing for a single\ncall. Unknown ids fall back to the active default with a server-side\nwarn log, so a stale localStorage chip value won't 422 mid-conversation.\n\n---\n\n## Project layout\n\n```\napi\u002Fserver.py            FastAPI entry point\nfrontend\u002F                React 18 (CDN, no build), served statically\nnano_notebooklm\u002F\n  ├── ai\u002F                LLM router + openai\u002Fclaude\u002Flocal backends\n  ├── ingest\u002F            PDF\u002FPPTX\u002FDOCX extractors + chunking\n  ├── kb\u002F                FAISS + BM25 + RRF hybrid + graph search\n  ├── kg\u002F                Two-stage knowledge graph extraction\n  ├── skills\u002F            QA, notes, quiz, exam-prep, report, mastery\n  └── orchestrator\u002F      Skill routing, multi-turn agent loop, memory\nscripts\u002F                 ingest + index + embedding helpers\ntests\u002F                   pytest suite — runs offline, no LLM keys needed\nartifacts\u002F               (gitignored) per-course chunks, indices, KG, notes\ndocs\u002Fscreenshots\u002F        README assets\n```\n\n---\n\n## Development\n\n```bash\nuv pip install -e \".[test]\"    # or: pip install -e \".[test]\"\npytest                         # unit + API smoke; no LLM keys required\npytest tests\u002Ftest_api_smoke.py # quick subset\n```\n\nThe frontend has no build step — it's React via the CDN and Babel\nstandalone. Just edit a `.jsx` file and refresh the browser.\n\nSee [`CONTRIBUTING.md`](CONTRIBUTING.md) for the contributor checklist\nand [`CLAUDE.md`](CLAUDE.md) for the code-map \u002F conventions.\n\n---\n\n## Roadmap\n\nRecently shipped:\n\n- Background upload pipeline with NDJSON stage events\n- UI-managed provider matrix (add \u002F swap \u002F test without restart)\n- Three-tier embedding presets (local MiniLM \u002F OpenAI 3-large \u002F BGE-M3)\n- MinerU OCR ingest for scanned PDFs\n- Multi-turn chat with history-aware query rewriting\n- Selection-driven notes generation (per-file checkbox, incremental cache)\n- Central i18n table (`frontend\u002Fi18n.js`) — full zh + en UI parity\n\nPlanned (issues welcome):\n\n- Web URL as a source type (fetch + readable-content extraction, then through the existing chunk \u002F embed \u002F KG pipeline)\n- Vite build option (opt-in, CDN stays default)\n- Mastery-driven exam-prep difficulty curve\n- Cross-course graph linking\n\n---\n\n## Production notes\n\nnano-NotebookLM is designed for **single-user \u002F small-team self-hosting**.\nThere is no authentication, no rate limiting, no multi-tenant isolation,\nand no persistent task queue. If you expose it on the public internet:\n\n- Put it behind a reverse proxy with HTTP basic auth (or OAuth).\n- Disable `force=true` regen endpoints externally — they call the LLM\n  on demand without per-IP throttling.\n- Move `artifacts\u002F` to a persistent volume.\n\n---\n\n## License\n\nReleased under the [Apache License 2.0](LICENSE). Free to use, modify,\nand redistribute — including in commercial products — provided the\noriginal copyright notice, license text, and `NOTICE` file are retained,\nand any modified files are marked as changed. See [`NOTICE`](NOTICE) for\nattribution requirements.\n\n## Acknowledgements\n\n- Inspired by Google's [NotebookLM](https:\u002F\u002Fnotebooklm.google.com\u002F).\n  **Not affiliated with Google.** NotebookLM is a trademark of Google LLC.\n- Naming convention follows [`nanoGPT`](https:\u002F\u002Fgithub.com\u002Fkarpathy\u002FnanoGPT)\n  and [`nano-vLLM`](https:\u002F\u002Fgithub.com\u002FGeeeekExplorer\u002Fnano-vllm) —\n  small, self-hosted, single-file-friendly homages.\n- Knowledge graph layout: [d3-force](https:\u002F\u002Fgithub.com\u002Fd3\u002Fd3-force).\n- PDF rendering: [PyMuPDF](https:\u002F\u002Fpymupdf.readthedocs.io\u002F) for\n  extraction, [PDF.js](https:\u002F\u002Fmozilla.github.io\u002Fpdf.js\u002F) in the browser.\n  LaTeX → PDF via [tectonic](https:\u002F\u002Ftectonic-typesetting.github.io\u002F).\n- Embeddings: [sentence-transformers](https:\u002F\u002Fwww.sbert.net\u002F),\n  multilingual MiniLM-L12-v2 default.\n- OCR for scanned PDFs: [MinerU](https:\u002F\u002Fgithub.com\u002Fopendatalab\u002FMinerU).\n","nano-NotebookLM 是一个开源的AI学习助手，能够将课程材料转化为笔记、知识图谱、引用答案和备考题目。该项目使用Python编写，支持多种语言模型如DeepSeek、OpenAI等，并允许用户自定义本地或云端模型。它通过构建矢量索引实现精确到页面的引用对话，生成结构化的LaTeX笔记，以及基于不断更新的问题库进行练习测验。此外，项目还提供了一个可编辑的知识图谱功能，便于用户整理和扩展知识点。适用于需要高效处理大量学习资料并希望利用AI技术辅助理解与复习的学习者。",2,"2026-06-11 03:58:24","CREATED_QUERY"]