Ingest: load PDF -> split into chunks -> embed each -> upsert row + vector into chunks table. Retrieval: embed the user question -> ANN top-K -> fetch full text rows. Generation: assemble prompt(question, top-K chunks) -> LLM -> answer. Errors must bubble up at every stage so you can replay any step from logs.
ingest_pdf: file path -> page iterator -> splitter -> embed -> batch upsert to pgvector.
query: question -> embed -> ANN top-K -> Pydantic list of RetrievedChunk.
prompt: chat template(question, chunks) -> ChatGroq -> answer.
PDF -> splitter -> embed -> pgvector upsert
Question -> embed -> ANN top-K -> LLM -> answer
(errors at any step replay via per-row logs)
RAG is three components glued by typed interfaces; one missing interface will silently break the chain.