Building a Retrieval-Augmented AI Research Assistant
Using embeddings, semantic search, and generative AI to unlock organizational knowledge
Introduction
Organizations often have valuable knowledge trapped inside reports, papers, and documents. The challenge is not creating more information, but rather the challenge is making existing information accessible.
This project demonstrates how Retrieval-Augmented Generation (RAG) can connect large language models with an organization’s existing knowledge base.
For this case study, I used the articles published on the LS3P website. LS3P has published a lot of great research, but that information is scattered across numerous PDFs, and it is difficult to know what is even available. For example, LS3P has published work on AI, but to find it, you need to click into DESIGN TECHNOLOGY and scroll down to the relevant publication. It is unlikely that a client, even one hungry for information about AI and architecture, would ever stumble onto that paper.
The goal of this project was to make all of LS3P’s published material easy to search and query in plain language. To do this, I built a Retrieval-Augmented Generation (RAG) pipeline: I collected LS3P’s published research, made it searchable using OCR, chunking, and embeddings, and connected it to GPT so that users can ask questions in natural language and receive answers grounded in the actual documents, rather than in the model’s general knowledge.
Try the Demonstration
You can interact with the prototype here:
This prototype was independently developed as a demonstration using publicly available LS3P research materials. It is not affiliated with or endorsed by LS3P.
What is RAG?
Retrieval-Augmented Generation combines two ideas:
- Retrieve relevant information from a document collection.
- Use a language model to generate an answer based on that information.
Instead of asking an AI model to answer from general knowledge, the model is given relevant excerpts from the organization’s own documents.
Building the Knowledge Base
The process involved several steps:
- Collecting research documents
- Extracting text
- Chunking
- Embeddings
- Performing semantic search
- Generating answers with GPT
Collecting Research Documents
The first step was to create a single corpus of LS3P’s published material. Since I am not affiliated with LS3P, I had to download each PDF onto my local machine. This would be much easier if you have direct access to the original files and/or where they are stored online. After aggregating all the documents, I ran into my first hurdle.
Extracting Text
Imagine a PDF. Do you picture a simple white paper laid out in plain paragraphs with a boring title like “A Comprehensive Study of Architecture: Principles, Design Evolution, and Sustainability”? Or do you picture something more like a brochure, designed to be folded, with color, pictures, and different fonts? Both are PDFs (after all, a PDF is just a file format that describes how a document is packaged and displayed, not how that document is designed). However, some PDFs store text as actual characters, while others (especially scanned documents or image-heavy exports) store pages as images. In those cases, the computer sees mostly pixels rather than text. As a result, searching for a word like “sustainability” may fail even though the word is clearly visible on the page. This was the problem I encountered with the PDFs I downloaded.
To solve this, I first needed to apply OCR (Optical Character Recognition) to the PDFs. OCR recognizes text within images and converts it into machine-readable text, making the documents searchable and allowing the text to be extracted. I will not go into detail on the specific code and software used here, but you can certainly get away with many other combinations of tools and software! After this step, I had the entire research library stored as text on my machine. Only then was the project ready for chunking and embedding.
Chunking
The next step is chunking. Large language models do not read an entire library at once. Instead, they process information in smaller pieces called chunks. Think of chunking like cutting a book into individual note cards: each card contains enough context to stand on its own, but is small enough for the model to process efficiently. Otherwise, the model would have to read every page of every document for every question. This process would be far too slow and would quickly exceed its context window (the maximum amount of information a language model can consider at one time).
One key detail is that chunk boundaries are often determined by size constraints rather than the document’s natural structure. While many chunking methods try to preserve paragraphs or sentences when possible, they ultimately aim for chunks of a target size (typically measured in tokens or characters). If a chunk is too small, important context can be split across multiple chunks. If it is too large, the model wastes valuable context on unrelated information. This balance matters because, from this point forward, the chunk becomes the primary unit used for retrieval, rather than the full publication.
Imagine the following document:
“Cats need regular exercise. Play helps keep them healthy. Dogs require daily walks. Walking improves canine fitness.”
Ideally, these would be chunked as:
Chunk 1: “Cats need regular exercise. Play helps keep them healthy.”
Chunk 2: “Dogs require daily walks. Walking improves canine fitness.”
Now, if a user asks a question about dogs, the system does not need to retrieve unrelated information about cats. This is a simple example, but it highlights the importance of chunking at scale. In the LS3P research library, only 3 of the 110 documents focus on AI. Imagine the wasted processing power and tokens if every document were passed to the model with every question.
Embeddings
This is perhaps the most difficult concept in the process. Embedding is simply turning chunks into numbers based on meaning. What is meaning? It isn’t entirely clear, but imagine the following:
Teal: (0, 184, 169)
Those numbers likely mean nothing to you, unless you work in a print shop. But you know what teal is! A computer is the opposite. The concept of teal means nothing to a server running Red Hat Enterprise Linux (RHEL) 9.5 on an Intel Xeon Gold 6430 (32-core, 64-thread) processor, but a computer can easily generate that color by reading the RGB code: 0/255 Red, 184/255 Green, 169/255 Blue.
Embeddings work similarly, but imagine that instead of RGB we have an embedding vector I just made up. I call it CDHSC: Cat, Dog, Happy, Sad, Crying.
“We are getting a dog! I can’t stop crying!”: (0, 255, 203, 0, 160)
“We aren’t getting a dog! I can’t stop crying!”: (0, 255, 0, 203, 160)
Notice that the tone of these two sentences is completely different, even though the words barely change. Embedding is how a computer turns text into meaning. Now, this is where it gets more complex, because I have simplified the example far beyond what actually happens in practice. Real embedding vectors are significantly longer than five numbers, and each digit does not actually refer to a specific characteristic of the chunk. In this project, I used an embedding model where each chunk’s vector has a length of 1536 and values ranging from [-1 to 1]- and, to emphasize, no specific digit of the vector refers to any specific word or meaning.
If this is confusing, do not worry. Just know the following: embedding turns human-readable sentences into computer-readable numbers. The “why” is explained next.
Performing Semantic Search
Traditional search systems look for exact matches between words. For example, if you search for “sustainable materials,” a traditional search engine looks for documents that contain those exact words. This works well when you know the specific language used in a document, but it struggles when the same idea is described differently. What if the research instead refers to “regenerative resources”? The connection would be lost.
Enter semantic search. Instead of searching for matching words, it searches for matching meaning. Because each chunk has been converted into an embedding, the system can compare the numerical relationship between the user’s question and the stored chunks. The closer two vectors are in this “mathematical space,” the more similar their meanings are considered to be.
Imagine asking the system: “What strategies can architects use to reduce a building’s environmental impact?” A traditional keyword search might only find documents containing phrases like “environmental impact” or “sustainable design.” A semantic search system can also find relevant sections discussing “energy-efficient buildings,” “passive design principles,” or “low-carbon construction methods,” because the underlying concepts are similar. This similarity is captured in the embeddings.
In this project, the user’s question is converted into its own embedding and compared against the embeddings of every chunk in the research library. The system then identifies the chunks with the closest semantic relationships and retrieves only those sections. Instead of sending all 110 documents to the language model, it provides only the most relevant information needed to answer the question.
So now, when a user asks a question, only the most relevant chunks are retrieved from the research library. This is the “Retrieval-Augmented” part of RAG. The language model is no longer answering based only on its original training: it is augmented with specific information retrieved from the documents.
Generating Answers With GPT
The final step in the process is generation. After the system has retrieved the most relevant chunks from the research library, those pieces of information are provided to the language model along with the user’s question. The model now has both the ability to understand the question and access to the specific documents needed to answer it.
This is where GPT enters the process. GPT (Generative Pre-trained Transformer) is not searching through the entire research library or deciding which documents to retrieve. Instead, GPT takes the retrieved information, interprets it, and generates a response using the context it has been given.
Think of it like an open-book exam. The retrieval system is the person who finds the right pages in the textbook, while GPT is the student who reads those pages and writes the answer. Without retrieval, the student would have to rely only on what they remember. Without generation, the retrieved information would just be a collection of disconnected passages.
In this project, the retrieved chunks were passed into GPT as additional context alongside the user’s question. GPT then synthesized the information, connected ideas across different sources, and produced a response. Because the answer is grounded in the retrieved research library, the system can respond with information specific to the organization’s documents, rather than relying only on general knowledge from its original training.
This completes the RAG pipeline: documents are converted into searchable information through OCR, chunking, and embeddings; relevant information is retrieved through semantic search; and GPT generates a natural-language answer using that retrieved context.
Technology Stack I Used
- Python
- R
- Shiny
- OpenAI API (for embedding and GPT)
- shinyapps.io (for application hosting)
Conclusion
This is one application of RAG, but this same architecture can support many other use cases:
- An architecture firm could build an assistant that answers questions using past project documents, design standards, and internal guidelines.
- An engineering company could search thousands of technical reports and specifications to find relevant solutions from previous work.
- A university could create a research assistant that helps students and faculty navigate papers, publications, and institutional resources.
- A company could use RAG to help employees find answers from internal policies, training materials, and procedures.
- A customer support team could build a tool that retrieves information from product manuals, troubleshooting guides, and previous support documentation before generating a response.
The core idea remains the same: instead of replacing existing knowledge, RAG creates a way to make that knowledge easier to find, understand, and use. The applications are almost limitless.