Cognosa Query Sequence

One question from the browser to the answer, across the SPA, app, Postgres, the rt workers, Qdrant, and the LLM

The web request ends at step 3. Everything after that is asynchronous: the doc_tasks row in Postgres is the only channel between the app process and the rt process, and its status column is the state machine the browser polls. The vector store shown is Qdrant; ChromaDB and pgvector follow the same path.

React SPA QueryDocuments page app · FastAPI routers/doc_tasks.py PostgreSQL doc_tasks row rt · main loop main_iteration.py · qd_lib/ VDB worker vdb_lib · process Qdrant group VDB collection LLM worker llm_lib · thread LLM Ollama · cloud chat APIs submit + poll retrieval generation deliver POST /api/v1/doc_tasks (JWT) input_text, gvdbs_id, gllms_id, gc_id 1 INSERT doc_tasks: snapshot group_vdbs, group_llms rows → gvdbs_json, gllms_json 2 0 QD_INIT 201 → doc_task uuid 3 poll GET /doc_tasks/{uuid} on a timeout loop → status, status_text, pct, answer so far until status in FINISHED_LIST 4 SELECT … WHERE status IN (0, 3) ORDER BY doc_task_id LIMIT 1 FOR UPDATE SKIP LOCKED 5 qd_init: validate gvdbs_json (url, collection, emb model, retr filters) 6 1 QD_INIT_FETCHED Queue.put(VDBDocTaskQueueMsg) multiprocessing queue 7 2 QD_VDB_PENDING embed question: HuggingFaceEmbeddings (gvdbs_emb_model, preloaded) 8 as_retriever(search_type, k …) + payload filter from retr_filters 9 top-k chunks + metadata 10 UPDATE context_json (found docs, deduped), vdb_query_seconds 11 3 QD_VDB_FETCHED next poll picks status 3 → qd_vdb_fetched 12 4 QD_LLM_PENDING start LLMWorker(Thread)(doc_task_id) 13 read task, gllms_json, group_contexts template 14 prepare_context: "Document i: …" chain = {context, question} | prompt | ChatModel | StrOutputParser 15 chain.stream(question) ChatOpenAI · ChatAnthropic · ChatGoogleGenerativeAI 16 token chunks, streamed 17 write sent_to_llm; append answer per chunk 18 5 QD_LLM_WRITING final answer, llm_query_seconds 19 6 QD_LLM_FETCHED poll returns status 6: answer (markdown) + sources from context_json; stop polling 20 Errors: each stage writes its own negative status and a status_text: -1 QD_INIT_ERROR, -3 QD_VDB_ERROR, -6 QD_LLM_ERROR. The SPA stops polling on any of them. No-retrieval mode: a task with gvdbs_id = -1 skips steps 6 to 11; the main loop moves it from status 0 straight to 3 and it goes to the LLM with an empty context. Concurrency: FOR UPDATE SKIP LOCKED lets several rt instances share one doc_tasks table; VDB workers are RT_VDB_PROCESS_NUM processes; each task gets its own LLM thread.
Numbered arrows are messages in time order, top to bottom. Solid arrows are calls, dashed arrows are returns or polled reads. A black pill on the Postgres lane is the doc_tasks.status value written at that step. Shaded bands group the steps into the four phases.

Task status machine

StatusNameWritten byMeaning
0QD_INITappRow inserted; question and the group's VDB and LLM config snapshots stored
1QD_INIT_FETCHEDrt main loopPicked up; options validated
2QD_VDB_PENDINGrt main loopQueued to a VDB worker process
3QD_VDB_FETCHEDVDB workerRetrieved chunks saved in context_json
4QD_LLM_PENDINGrt main loopLLM thread started
5QD_LLM_WRITINGLLM workerStreaming; partial answer visible to the SPA
6QD_LLM_FETCHEDLLM workerComplete; answer and timings final
-1 / -3 / -6QD_INIT_ERROR / QD_VDB_ERROR / QD_LLM_ERRORstage that failedTerminal; status_text and exc_text carry the reason

What the browser sees

The QueryDocuments page submits once, then polls the task by uuid on a timeout loop. Each poll returns the status, a status text, a percent derived from status divided by six, the answer so far, and once complete the retrieved documents from context_json rendered as sources. Polling stops when the status is 6 or negative.

Retrieval parameters in play

The group's VDB row carries the embedding model name, the Qdrant collection, a retrieval parameter set, and optional retrieval filters. The parameter set selects the LangChain retriever mode, one of similarity, mmr, or similarity with a score threshold, with k, fetch_k, lambda_mult, and score_threshold. The filters become a Qdrant payload filter so the search is restricted to matching metadata before similarity is computed.