Leonid Chekin
KNOWLEDGE ASSISTANT · AI / RAG

How documents
become answers.

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.

Try the demo ↗Swagger / OpenAPI ↗Source code ↗
QUICK DEMO · 22 SECONDS

See the workflow.

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 ↗
01 / DATA FLOW

From file to answer.

  1. 01 · WEB CLIENTReact

    The demo works without signing in on a built-in sample; PDF, DOCX, and TXT uploads go to the signed-in account library.

  2. 02 · EXTRACTIONFastAPI + parsers

    Validates type and size, extracts text, and preserves page numbers. The temporary file is removed after processing.

  3. 03 · PASSAGESChunking + SQLite

    Normalizes text, creates 1,100-character chunks with 160-character overlap, and stores text with source metadata.

  4. 04 · RETRIEVALLexical search

    Compares question and passage terms, ranks matches with cosine similarity, and selects up to three sources.

  5. 05 · GENERATIONOpenRouter · free route

    The server sends the question and retrieved excerpts to the model. The API key stays in Render environment variables and never reaches the browser.

  6. 06 · RESULTAnswer + sources

    The UI displays the answer, cited passages, and recent questions; chat history is stored in SQLite.

Data boundary: the original uploaded file is not sent to OpenRouter. The provider receives the question and relevant extracted passages — up to about 6,000 context characters per request.
02 / DESIGN DECISIONS

What happens inside.

RETRIEVAL

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.

SOURCES

Answers you can verify

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.

SECRETS

The key stays server-side

React calls the app's own API. FastAPI reads OPENROUTER_API_KEY from the environment, never from the browser or public repository.

PROCESSING

Synchronous path for a small demo

Indexing runs during the upload request. This keeps the demo simple; large files and higher traffic need a task queue and resource limits.

03 / DEPLOYMENT PROFILES

Hosted demo and full Compose profile.

LayerPublic Render demoFull Compose profile
UI / APIReact · FastAPIReact · FastAPI
DataSQLite · container filesystemPostgreSQL · upload volume
Search / generationLexical search · OpenRouter Free routeQdrant vectors · Ollama embeddings and LLM
Background servicesRequests run in a single web serviceCompose includes Redis and a Celery worker; indexing can be moved into background tasks
PersistenceData may reset after a restart or idle periodLocal 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.

04 / KNOWN GAPS

Before using real customer data.

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.