Local AI · DGX Spark

Reading Review Knowledge Base

Ask a book a question, get a cited answer.
Semantic search across 173 books' summaries and full text — local embedding × local LLM.

2026 RAG + Local Embedding 100% on-prem
Reading Review Knowledge Base — live interface

The live interface — captured with Playwright

Why build one

Forgetting a book right after finishing it is normal, and re-reading takes too long. Note-taking apps can store summaries, but they can't answer a question — figuring out which book covered a given idea still means relying on memory or manual searching.

Obsidian already held hundreds of book summaries, plus the full text of purchased ebooks. Sync both to the DGX Spark, chunk and embed them, and it becomes a personal knowledge base you can actually question.

The hardest part is honesty: if a book isn't in the library, the LLM must not make up an answer from vague recollection.

How it works: the journey of one question

From syncing a book summary to one cited answer — six things happen in between.

01

Summaries and full text sync in

Book summary notes in Obsidian, plus the full text of purchased ebooks, sync down to the DGX Spark locally.

02

Chunking

Markdown is split along its heading structure, with overly long sections chunked further to keep each piece semantically whole.

03

Local embedding

qwen3-embedding:0.6b turns each chunk into a 1024-dimension vector, with a content-hash incremental cache — only files that actually changed get recomputed.

04

A one-time full-text build

The full text of 173 books splits into 30,224 chunks; the first full embedding pass took about 39 minutes, and incremental caching handles the deltas afterward.

05

Semantic retrieval at query time

The question is embedded, then retrieval mixes summaries and full text in a fixed half-and-half split — a naive blend would let the much larger full text drown out the summaries.

06

The local LLM answers

It generates a Chinese answer from the retrieved passages, with a forced citation to the book title. Pure-LLM features — quiz generation, insights, translation — route through a LiteLLM gateway instead, and every call shares one queue so requests never fight each other for local resources and time out.

Deep dive: retrieval mechanics and the knowledge graph

Two phases: the library gets built into a vector index offline; at query time, retrieval happens live, gets blended, and a local LLM generates a cited answer.

Building the index (offline, one-time)

Library sources

Obsidian summaries + decrypted Readmoo full text

SOURCE

Chunking

summaries split by heading, full text by chapter

CHUNK

Vector embedding

qwen3-embedding · Ollama, local

1024-dim vectors
stored in sqlite + npy

VECTOR

Query (real time)

Question vectorized

the same embedding model

VECTOR

Semantic retrieval

summaries + full text, blended half-and-half

top-k most relevant passages

RETRIEVAL

LLM answers

qwythos:9b · Spark Gateway

generates from retrieved passages
forced citation to book title

ANSWER

Answer with citations

Traditional Chinese + sourced passages noted

CITED

Auto-review

Randomly samples a passage from the library → the 9B model writes 3 questions → answers them itself, like a podcast walking you through review.

Knowledge graph

Each book's vector is the mean of all its passage embeddings; books with high similarity get an edge, mapping the semantic relationships between books.

Why fully on-prem

Reading notes are private data — embedding, retrieval, and generation all happen on our own GB10, with no cloud API in the loop.

171

book summaries indexed

30,224

full-text chunks (173 books)

~39min

one-time full-text embedding build

1024

dim embedding vectors

Key design decisions

Half summary, half full text

Summaries give structure, full text gives original evidence. A naive blend lets the much larger full text drown out the summaries, so the split is fixed half-and-half — both always show up.

Retrieval honesty comes first

If a book isn't in the library, the answer says so plainly instead of letting the LLM guess from vague recollection — better no answer than a made-up one.

Every LLM call shares one queue

Q&A, quiz generation, insights, and translation all run through a single queue, so concurrent requests never fight for local resources and time out.

English translations pre-rendered in the background

Common content is translated ahead of time in the background, so clicking the button feels instant instead of triggering a wait.

Architecture

Frontend

live-filtering title combobox
auto-generated review quizzes
knowledge graph (vanilla canvas, force-directed)

Embedding

qwen3-embedding:0.6b
1024-dim vectors
content-hash incremental cache

Retrieval

half summary, half full text
semantic search
forced book-title citations

LLM

local LLM handles Q&A
LiteLLM gateway for quizzes/insights/translation
single queue, no concurrency

The live tool is locked behind Basic Auth — this page shares the architecture and design.