Skip to main content

Local Knowledge (RAG) workspace

Import documents, ask questions, and inspect the passages used by the answer.

Knowledge workspace with a real local Qwen answer and PDF sources This recipe develops the retrieve-then-generate idea from PR #159 using the bundled Eole UI.

The retrieval stack uses LangChain's PDF loader and tokenizer-aware text splitter, its Chroma integration, and google/embeddinggemma-2 through Sentence Transformers. EmbeddingGemma runs text-only in FP32 on the answer model’s GPU by default, with vision/audio encoders disabled. Enable Use CPU for embeddings in the Sources panel to move it off the GPU and release its cached GPU memory. Existing collections remain usable without reindexing. The switch applies to indexing and query embeddings; GPU operations share the workspace inference lock. A CUDA-free server must enable the CPU option. Its eager attention avoids interference from Eole's global CUDA SDPA backend settings. Qwen3.8-27B-INT4 generates answers on the GPU through Eole, using configured MTP when eligible. No external LLM API, LangGraph agent, or cloud vector database is used.

Relationship to the original prototype​

This workspace supersedes the basic RAG demonstration in PR #159: load documents → split → embed/index in Chroma → retrieve context → generate with Eole. It uses the same overall pipeline, with deliberate differences:

  • Explicit EmbeddingGemma 2 embeddings and token-based chunks replace Chroma's default embeddings and character-based chunks.
  • Retrieval supplies the top five ranked passages directly. The prototype instead selected the best match and its immediately preceding/following chunks.
  • Collections live in server memory; the prototype used a persistent Chroma directory.
  • The interactive workspace adds multiple documents, streamed answers, follow-up questions, collection management and inspectable source references.

The prototype's disk persistence and neighboring-chunk expansion are not implemented here. Closing it as superseded does not imply identical retrieval results.

Install and start​

EmbeddingGemma 2 requires recent Transformers and Sentence Transformers releases. To preserve another environment (especially one containing vLLM with an older Transformers requirement), use a separate virtual environment. This example reuses an existing working Eole/PyTorch installation and installs only the RAG dependencies:

python -m venv --system-site-packages /path/to/eole-rag-env
source /path/to/eole-rag-env/bin/activate
pip install -r recipes/rag/requirements.txt

export EOLE_MODEL_DIR=/path/to/models
export QWEN38_MODEL="$EOLE_MODEL_DIR/Qwen3.8-27B-INT4"
CUDA_VISIBLE_DEVICES=0 OMP_NUM_THREADS=8 \
EOLE_TORCH_COMPILE=1 EOLE_COMPILE_MODE=0 \
python -m eole.bin.main serve -c recipes/rag/serve.yaml \
--host 127.0.0.1 --port 5000

Run from the repository root. This does not rebuild the CUDA extension. For a fresh Eole installation, the same libraries are available through pip install 'eole[rag]'. The combined recipes/ui/serve-showcase.yaml also includes Knowledge.

Open http://127.0.0.1:5000, select Knowledge, and import observatory-guide.md. It is an explicitly fictional sample. Try: “When does the observatory close on Saturdays and how can I reserve a telescope?” The answer should mention 23:00 and emailing visits@cedar.example at least two days in advance, with supporting source references.

The first import downloads/caches the embedding model weights if absent. The first Qwen answer can spend minutes compiling; subsequent requests reuse compiled programs. OMP_NUM_THREADS=8 is a starting point for CPU embedding throughput; adjust for your machine.

Workflow​

  • Create/select a collection, then drop or select PDF, DOCX, Markdown or text files.
  • Ask a question. Retrieval selects up to five passages before generation.
  • Click a [1] reference to inspect its passage and PDF page number, or inspect the sources attached to an earlier answer. DOCX and text sources have passage numbers, since they do not have reliable fixed page boundaries.
  • Ask follow-ups in the same collection. The previous user question is included in the retrieval query; this initial version does not run a separate query-rewriting LLM.
  • Remove documents or delete collections when finished. New conversation clears questions and answers while retaining the indexed collection.
  • For scanned PDFs, use Documents (OCR), download the extracted Markdown, and import it here. This version indexes text, not page images, audio, or video.

Document limits: 4 MB/file and 10 documents/collection, with no page-count, extracted-character or chunk-count cap. Large indexes are inserted in batches of 256 chunks, with rollback on cancellation or failure. Four collections/session and 16 sessions/server bound the number of independent libraries. Encrypted PDFs must be unlocked first. Generation keeps only passages that fit the selected model's context budget and rejects requests if no passage fits.

Storage and privacy​

Collections, vectors and extracted text are temporary server-memory data. A random session token kept in this tab's sessionStorage separates collections from other sessions. There is no idle timeout: collections remain until explicitly deleted, the session is reset, or the server restarts. Resetting a session explicitly removes its previous collections. A server restart removes all collections. Answers live in the tab's memory and are cleared on reload. The model weights remain in the normal Hugging Face cache. PDF parsing uses a temporary file removed after loading. Chroma persistence and anonymized telemetry are disabled.

Session tokens provide collection isolation, not user authentication. Use an access-controlled reverse proxy if sharing the server. As with the other workspace views, active/recent request metrics are server-wide; document text and collection contents are not included in those metrics.

Configuration and measurements​

knowledge:
embedding_model: google/embeddinggemma-2 # also accepts its local model directory
embedding_cpu: false # initial UI toggle state; GPU is the default
chunk_tokens: 384
chunk_overlap: 48
retrieval_k: 5

The backend supplies distinct question/document embedding prompts and normalized 768-dimensional vectors. The configurable model location is intended for EmbeddingGemma 2-compatible checkpoints; it is not a generic embedding adapter. Generation uses the selected Eole chat model. A Knowledge model default can be set through workspace.models.knowledge.

Indexing time includes embedding-model initialization when needed. Retrieval time includes workspace queueing, query embedding and vector search. Decode tokens/second comes from Eole's inference worker; it excludes retrieval, prefill and compilation. Source references identify retrieved evidence, but do not independently verify the generated claims.

Tests without downloads run with:

python -m unittest eole.tests.test_ui_knowledge

PDF extraction tests run when the optional RAG packages and PyMuPDF are installed.

For an opt-in real embedding/Chroma test (loads or downloads model weights):

OMP_NUM_THREADS=8 EOLE_TEST_RAG_MODEL=google/embeddinggemma-2 \
python -m unittest eole.tests.test_knowledge_embedding

Set EOLE_TEST_RAG_CUDA=1 alongside EOLE_TEST_RAG_MODEL to verify GPU query embeddings and switching the existing index back to CPU.