Demo · 7 September 2026
TenderLens
HTML is split into chunks and indexed through a queue. Search runs in pgvector; answers link to the retrieved chunks. The demo has four test documents. Embeddings and the LLM are mocked; the external crawler is disabled.
01 / The task
Document search with FastAPI and pgvector
Search over a fixed document set. Answers need links to the source chunks. If there are no relevant matches, the response says so.
Use case: Searching and reading a document collection.
Work done
- Document normalization, event-based indexing and chunk storage.
- Search and answer API with source links. A separate response for empty context.
- Test corpus, deterministic AI mocks and per-session limits.
Screenshots
Screens, forms, errorsScreenshots, diagrams and source evidence retain their original language; captions and descriptions are translated.
02 / Technology
Stack
FastAPI / Pydantic
HTTP contracts, validation and search responses.
NATS JetStream
Event delivery to the indexer and replay.
PostgreSQL / pgvector
Documents, attachments, chunks and cosine search.
SQLAlchemy / Python
Normalization, extraction, chunking and content_hash verification.
03 / Decisions
How the project works
- Seed sends a real TenderChangedV1 event through NATS; the indexer extracts HTML and creates chunks.
- PostgreSQL VECTOR(1024) performs cosine search. FakeAIProvider creates embeddings using the hashing trick.
- Event replay uses content_hash: an unchanged document does not duplicate chunks.
- Answers use an explicitly labeled template based on retrieved passages; the external crawler and Ollama are disabled.
04 / Verification
Demo workflows
- Find a document about servers or an Angular portal.
- Ask a question and open the answer's sources.
- Enter a query outside the corpus and check the missing-context response.
- Replay indexing events: the four documents and 16 chunks should remain without duplication.
Check results
- 12 meaningful screenshots of the actual interface retained.
- Each screenshot includes its date, scenario and code revision.
- Peak container RAM in the short test: 127.04 MiB. Shared services are counted separately; the shop includes its own database.
- 6 scenario repetitions measured; median 997.0 ms, maximum 2738 ms. Timing includes the browser and HTTPS; methodology and limitations are included.
- Four ready documents, 16 chunks. Replaying four NATS events created no duplicates.
Limitations
- Four synthetic documents and 16 chunks form a demonstration corpus, not a database of real procurement records.
- Cosine scores and template answers are not an evaluation of a production model's quality.
- Up to 30 requests per minute per session and 1,000 active demo keys. User queries are not stored.
- Worker health confirms the connection at startup; a separate stalled-computation detector is not implemented.
Technical notes
Modules, API, data model, setup and check results.
Documentation →Materials ↓