<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Karthick Builds]]></title><description><![CDATA[Karthick Builds]]></description><link>https://karthickbuilds.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Wed, 28 Oct 2026 06:41:12 GMT</lastBuildDate><atom:link href="https://karthickbuilds.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[I Built a RAG Application to Chat With Documents]]></title><description><![CDATA[Learn how a RAG application answers questions from documents using embeddings, vector databases, retrieval, and large language models.]]></description><link>https://karthickbuilds.hashnode.dev/i-built-a-rag-application-to-chat-with-documents</link><guid isPermaLink="true">https://karthickbuilds.hashnode.dev/i-built-a-rag-application-to-chat-with-documents</guid><category><![CDATA[RAG ]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[llm]]></category><category><![CDATA[Python]]></category><category><![CDATA[Machine Learning]]></category><dc:creator><![CDATA[karthick]]></dc:creator><pubDate>Sun, 18 Oct 2026 04:18:17 GMT</pubDate><content:encoded><![CDATA[<p>Have you ever opened a PDF, searched for a particular piece of information, and spent several minutes scrolling through pages to find it?</p>
<p>I wanted to explore how AI could make this process easier.</p>
<p>Instead of manually searching through documents, what if we could upload a file, ask a question in plain English, and get an answer based on its contents?</p>
<p>That idea introduced me to <strong>Retrieval-Augmented Generation (RAG)</strong>.</p>
<p>In this article, I'll walk through how I approached building a document question-answering application, the technologies involved, how the components work together, and the engineering challenges I needed to consider.</p>
<h2>The Problem I Wanted to Solve</h2>
<p>Imagine a company has hundreds or thousands of documents containing policies, reports, product manuals, and technical documentation.</p>
<p>An employee asks:</p>
<p><em>"What is the company's annual leave policy?"</em></p>
<p>A traditional file search may help locate a document, but the employee still needs to open it and find the relevant information.</p>
<p>A general-purpose LLM might explain annual leave, but it cannot automatically know the contents of private company documents it has never received.</p>
<p>I wanted to explore a system that could retrieve the relevant information from documents and use an LLM to generate a useful answer.</p>
<p>That is the problem RAG is designed to address.</p>
<h2>Understanding the Architecture Before Writing Code</h2>
<p>Before putting the components together, I broke the application into two workflows.</p>
<p><strong>1. Document processing</strong></p>
<p>Uploaded documents → Text extraction → Chunking → Embeddings → Vector database</p>
<p><strong>2. Question answering</strong></p>
<p>User question → Retrieval → Relevant document chunks → LLM → Generated answer</p>
<p>The first workflow prepares the documents for searching. The second uses those prepared documents to answer questions.</p>
<p>Understanding this separation is important because I don't want to process every document from scratch whenever someone asks a new question.</p>
<h2>Step 1: Processing the Documents</h2>
<p>The first challenge is getting useful text out of uploaded files.</p>
<p>A PDF may contain paragraphs, headings, tables, page numbers, or scanned images. The application needs to extract its text before it can search the content.</p>
<p>For a basic implementation, I would start with text-based PDFs and add OCR support for scanned documents later.</p>
<p>Once the text is extracted, the application can prepare it for retrieval.</p>
<h2>Step 2: Splitting the Text Into Chunks</h2>
<p>Why not store an entire document as one large piece of text?</p>
<p>Because retrieving a small, relevant passage is often more useful than retrieving a whole document.</p>
<p>For example, an employee handbook might contain separate sections for annual leave, sick leave, and remote work.</p>
<p>I would split the extracted text into smaller chunks, ideally preserving paragraph and section boundaries where possible.</p>
<p>Chunking requires some experimentation. If the chunks are too small, they may lose context. If they are too large, the retrieved content may include irrelevant information.</p>
<p>Overlapping chunks can also help preserve information across boundaries.</p>
<h2>Step 3: Generating Embeddings</h2>
<p>Next, the application needs a way to find information based on meaning rather than exact word matches.</p>
<p>This is where embeddings come in.</p>
<p>An embedding model converts a piece of text into a numerical vector.</p>
<p>Consider these two sentences:</p>
<ul>
<li><p>"Employees receive 20 days of annual leave."</p>
</li>
<li><p>"How many vacation days can staff take each year?"</p>
</li>
</ul>
<p>The wording differs, but the sentences express related ideas. An embedding-based search system can help identify that relationship.</p>
<p>I would generate embeddings for the document chunks and later generate an embedding for each user question using a compatible model.</p>
<h2>Step 4: Storing the Data in a Vector Database</h2>
<p>The application needs to store the embeddings so that relevant chunks can be retrieved efficiently.</p>
<p>For a prototype, ChromaDB is one option worth exploring. Other options include Qdrant and PostgreSQL with pgvector.</p>
<p>Alongside each embedding, I would store the corresponding text and metadata, such as:</p>
<ul>
<li><p>Document ID</p>
</li>
<li><p>File name</p>
</li>
<li><p>Page number</p>
</li>
<li><p>Chunk ID</p>
</li>
</ul>
<p>This information helps the application retrieve the original text and identify where an answer came from.</p>
<p>For a larger application, document ownership and access permissions would also need to be enforced during retrieval.</p>
<h2>Step 5: Retrieving Relevant Information</h2>
<p>Suppose a user asks:</p>
<p><em>"How many annual leave days do employees receive?"</em></p>
<p>The application converts the question into an embedding and searches the vector database for relevant chunks.</p>
<p>The retrieval system might return a passage stating that eligible employees receive 20 days of annual leave each year.</p>
<p>At this stage, the application has found potentially useful information. It has not generated the final answer yet.</p>
<p>Retrieval quality matters: if the relevant passage is missing from the retrieved results, the language model may not have enough evidence to answer correctly.</p>
<h2>Step 6: Connecting the Retrieved Context to an LLM</h2>
<p>Now comes the generation step.</p>
<p>The application combines the user's question with the retrieved text and passes both to an LLM.</p>
<p>A simplified prompt could look like this:</p>
<p><strong>Question:</strong></p>
<p>How many annual leave days do employees receive?</p>
<p><strong>Context:</strong></p>
<p>Eligible employees receive 20 days of annual leave each year.</p>
<p><strong>Instruction:</strong></p>
<p>Answer using the provided context. If the context does not contain enough information, say so rather than inventing an answer.</p>
<p>The model can then generate a natural-language response based on the supplied information.</p>
<p>The important point is that the application performs retrieval first and provides the resulting context to the LLM. The LLM does not automatically know the contents of the vector database.</p>
<h2>Step 7: Making the Application Useful</h2>
<p>Generating an answer is only part of the application.</p>
<p>I would also want to provide:</p>
<ul>
<li><p>A document upload interface</p>
</li>
<li><p>A chat interface for asking questions</p>
</li>
<li><p>Loading indicators while processing files</p>
</li>
<li><p>Source references for generated answers</p>
</li>
<li><p>Clear error messages for unsupported files</p>
</li>
<li><p>A way to update or delete uploaded documents</p>
</li>
</ul>
<p>For a production system, I would also need authentication, secure file storage, access controls, and reliable handling of document updates.</p>
<p>These features help turn a technical prototype into something people can actually use.</p>
<h2>The Challenges I Would Focus On</h2>
<p>Building a RAG system is not simply a matter of connecting a vector database to an LLM.</p>
<p>Some important challenges include:</p>
<p><strong>Retrieval accuracy:</strong> Does the system find the correct passage for a question?</p>
<p><strong>Chunking strategy:</strong> Does each chunk preserve enough information to be understood independently?</p>
<p><strong>Hallucinations:</strong> Does the model introduce claims that are not supported by the retrieved text?</p>
<p><strong>Document updates:</strong> What happens when a source file changes or gets deleted?</p>
<p><strong>Performance:</strong> How do retrieval time, embedding generation, and model response time change as the document collection grows?</p>
<p>These questions need to be investigated through actual testing rather than assumptions.</p>
<p>For example, I would prepare a set of questions with known answers, check which chunks are retrieved, and compare the generated responses with the original documents. That would help identify whether a problem comes from retrieval, document processing, or generation.</p>
<h2>What I Learned From Exploring RAG</h2>
<p>The most interesting idea behind RAG is that a language model does not have to contain all the information it needs inside its training data.</p>
<p>An application can retrieve external information when a question is asked and use that information as context.</p>
<p>This connects several areas of software engineering:</p>
<ul>
<li><p>Document processing</p>
</li>
<li><p>Embedding models</p>
</li>
<li><p>Vector search</p>
</li>
<li><p>Backend development</p>
</li>
<li><p>LLM integration</p>
</li>
<li><p>Data security</p>
</li>
<li><p>Testing and evaluation</p>
</li>
</ul>
<p>It also highlights an important lesson: a fluent answer does not necessarily mean the system retrieved the right evidence.</p>
<p>The quality of a RAG application depends on the complete pipeline, not just the language model.</p>
<h2>What's Next?</h2>
<p>I would like to explore how retrieval quality changes with different chunk sizes, how metadata filtering works across document collections, and how source citations can make answers easier to verify.</p>
<p>The next step is to test these ideas in a working application and document the results.</p>
<p>For me, the value of learning AI engineering is not just understanding what a technology does. It is understanding how its components work together, where they fail, and how to improve them.</p>
<p><strong>Thanks for reading!</strong> If you're exploring RAG or building document-based AI applications, I'd love to hear what you're learning and which challenges you've encountered.</p>
]]></content:encoded></item></channel></rss>