Retrieve first, generate second
Lexical retrieval narrows the context to relevant excerpts. The LLM receives only the question and those excerpts; its system prompt says to treat document content as untrusted and not follow instructions inside it.
The assistant extracts text, retrieves relevant passages, and sends only those passages with the question to a generative model. The answer includes source filenames, page numbers, and citations.
The video shows a question about the built-in sample and an answer with a source. The app also supports uploads after account creation; free demo data may reset when the service restarts.
Download the short video ↗The demo works without signing in on a built-in sample; PDF, DOCX, and TXT uploads go to the signed-in account library.
Validates type and size, extracts text, and preserves page numbers. The temporary file is removed after processing.
Normalizes text, creates 1,100-character chunks with 160-character overlap, and stores text with source metadata.
Compares question and passage terms, ranks matches with cosine similarity, and selects up to three sources.
The server sends the question and retrieved excerpts to the model. The API key stays in Render environment variables and never reaches the browser.
The UI displays the answer, cited passages, and recent questions; chat history is stored in SQLite.
Lexical retrieval narrows the context to relevant excerpts. The LLM receives only the question and those excerpts; its system prompt says to treat document content as untrusted and not follow instructions inside it.
Each API source includes a filename, page, excerpt, and relevance score. The model is asked to cite sources so readers can check claims against the document.
React calls the app's own API. FastAPI reads OPENROUTER_API_KEY from the environment, never from the browser or public repository.
Indexing runs during the upload request. This keeps the demo simple; large files and higher traffic need a task queue and resource limits.
| Layer | Public Render demo | Full Compose profile |
|---|---|---|
| UI / API | React · FastAPI | React · FastAPI |
| Data | SQLite · container filesystem | PostgreSQL · upload volume |
| Search / generation | Lexical search · OpenRouter Free route | Qdrant vectors · Ollama embeddings and LLM |
| Background services | Requests run in a single web service | Compose includes Redis and a Celery worker; indexing can be moved into background tasks |
| Persistence | Data may reset after a restart or idle period | Local Docker volumes preserve data across restarts |
The free profile lets visitors try the app without installation. The full profile is for exploring vector search and a local model; it is a development option, not a separate public production service.
Persistent database: the app supports PostgreSQL, but the current successful demo release uses ephemeral SQLite on Render.
Files and backups: source uploads are deleted after indexing; object storage and a tested database restore process are still needed.
Already implemented: accounts, per-account document and history isolation, and owner-only document deletion.
Next improvements: email verification, password recovery, queued indexing, and retrieval/citation quality evaluation.