AI/ML · 2025
NexaQuery AI
A web Q&A agent for uploading a PDF and asking it questions through a conversational interface.
NexaQuery AI media, 2 items. Use the arrow keys to move.
Illustration. Not a screenshot of the app.
I built NexaQuery AI so I could drop a PDF on the page and ask it questions, instead of searching a folder for the paragraph I half remembered.
The problem
A long PDF is a bad search box. The answer is usually one section, and the section is not labeled with the words I would have typed. Opening the file, scrolling, and hoping is how a document wins. The person it frustrates is anyone who has the file and still cannot get a straight reply out of it.
A search over a folder of old uploads was not the point. I wanted a conversation about the document I had just dropped in, with the reply tied to that file and not to whatever else happened to be on the server. That was worth building because a chat that is not grounded in the PDF is just a chat.
How I built it
The screen is React 18 and Ant Design, and Axios carries the upload and the question. The page is a conversation, not a results page. You put the PDF in, then you talk to it.
The API is Node.js and Express. Multer takes the upload. pdf-parse reads the text out of the file. Those two steps exist because a model cannot answer from a PDF it has never opened, and the browser should not be the thing that splits the document.
OpenAI GPT-3.5 Turbo and LangChain 0.0.135 do the rest of the pipeline: load the text, split it, store it, retrieve the pieces that match the question, and write the answer. The store is a memory vector store, in process, so the lookup stays with that document rather than in a database of every PDF anyone has ever uploaded.
The memory store is the decision I keep coming back to. A shared index would have mixed one person’s file with another’s. Keeping the vectors in memory ties the reply to the document in front of you, and it means the retrieval does not need a second service just to answer one PDF.
Challenges and what I learned
The answer is only as good as the split and the retrieval. If the relevant sentence never makes it into the pieces LangChain pulls back, GPT-3.5 Turbo has nothing honest to say. That is why the pipeline is load, split, store, retrieve, then answer, in that order, and why the store stays in memory with the document instead of becoming a search box over a folder.

Let's talk ↗









