← Projects
05 / 05

Deployed AI product · 2026

Professional interview assistant

A generative AI assistant designed as a public service rather than an isolated demo: controlled retrieval, NDJSON streaming, sessions, queueing, usage limits and privacy sanitisation in one conversational experience.

1. Project summary

I built a conversational web application that lets recruiters and other interested visitors ask questions about professional information in natural language. The assistant combines a chat interface with a backend that looks for evidence in a curated set of documents and project records before generating each response. Its main contribution is to turn a structured professional profile into an interactive experience, with adjustable answers and controls that limit information exposure.

2. Problem and objectives

A CV presents information in a fixed format, requiring readers to locate the experience relevant to each question themselves. This project aims to make profile exploration more contextual, preserve continuity between questions, and let visitors start, stop or reset a conversation. It also addresses engineering goals: limiting the sources consulted, managing load and errors, and protecting credentials.

3. Solution and architecture

Visitors enter a question and choose a level of detail. The service validates the request, assigns a session and applies usage limits. Before answering, the model must select sources through restricted tools to read catalogued documents or search project records. The backend runs those queries, returns the evidence to the model and streams the answer to the browser as NDJSON events. Completed conversations are kept in memory to provide context for the next question.

Professional assistant architectureFastAPI validates the question and coordinates the OpenAI model with a document catalogue and project index. The answer returns through NDJSON streaming; only completed conversations are retained in memory.InteractionGeneration and sourcesquestion and detailNDJSONplan / evidencesources / answerhistoryVisitorWeb interfaceFastAPI serviceOpenAI model APICatalogue and MarkdowndocumentsStructuredproject indexIn-memory sessioncompleted answers

4. Development and technical decisions

The backend uses Python, FastAPI and Uvicorn. Its OpenAI integration uses the Responses API and function tools with closed schemas. Source selection is mandatory: if the model does not propose valid queries, planning fails. This separates the decision about what to consult from reading the sources, which is carried out by local functions.

Information is stored in Markdown documents described by a YAML catalog and a structured project index. Source resolution restricts reads to the permitted collection. The project search normalises terms and diacritics, counts matches in prioritised fields and applies editorial rules for specific topics. This is a deterministic lexical strategy, not vector search. For long documents, the system splits content by headings and selects sections matching the question up to a context limit.

The model is configurable, with gpt-5.5 set as the code default. Responses offer three levels of detail and are streamed. If a response is incomplete, the backend can request a continuation. A sanitizer retains a margin between chunks to detect sensitive patterns that span their boundaries.

The client uses HTML, CSS and JavaScript without a framework; it handles streaming, cancellation, conversation reset and visual preference. An HttpOnly cookie identifies the session; history remains in process memory and is size-limited. The service validates requests, limits usage and concurrency, orders the queue and applies security headers. The provider key remains on the backend. PostHog is optional and requires configuration and consent, with automatic capture and session recording disabled.

The Docker image uses a lightweight Python base and a non-privileged user. No controlled comparisons between models, providers or alternative strategies are documented.

5. Challenges and solutions

One challenge is retrieving useful evidence without sending all documentation to the model. The catalog guides source selection, the index returns compact project records, and long documents are reduced to matching sections. Restricted path resolution and the permitted public fields limit access and the information returned.

Streaming raises continuity and privacy challenges: errors can occur after part of an answer has been shown, or sensitive data can be split across chunks. The client preserves partial answers; the backend stores only completed answers in the conversation history and buffers text before emitting it. The queue and request limits manage capacity when relying on an external API.

6. Evaluation and results

The repository includes unit tests for the catalog, search, sessions, queue, headers, streaming, errors and sanitization, as well as simulated regressions for incomplete responses.

The project offers three response levels and configures two simultaneous generations with up to twenty additional requests in a FIFO queue; these are capacity settings, not load-test results. There is no documented user evaluation, labelled question set, quality comparison, under-load latency, or precision or retrieval metrics. Perceived quality and real-world performance remain to be measured.

7. Current state and future improvements

The implementation brings together the interface, service, structured sources, OpenAI-connected generation, streaming and a container. The documentation and project index record a public deployment on DigitalOcean App Platform; current availability has not been verified. Sessions and concurrency are local to one instance; scaling to multiple replicas requires shared state. Cost and latency also depend on the external provider.

As a next step, I propose measuring retrieval and answer quality with representative questions and reviewing latency under load. Session state could also be externalised for scaling, and semantic retrieval evaluated if tests show the limits of lexical search. These are future work, not implemented features.