<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>RAG on kenji.blog</title><link>http://kenji.blog/en/categories/rag/</link><description>Recent content in RAG on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 13:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/en/categories/rag/index.xml" rel="self" type="application/rss+xml"/><item><title>[RAG Implementation Guide] How to Load Your Own Documents into Local AI</title><link>http://kenji.blog/en/p/rag-local-ai-implementation-guide/</link><pubDate>Fri, 11 Sep 2026 13:00:00 +0900</pubDate><guid>http://kenji.blog/en/p/rag-local-ai-implementation-guide/</guid><description>&lt;img src="http://kenji.blog/p/rag-local-ai-implementation-guide/img/eyecatch.jpg" alt="Featured image of post [RAG Implementation Guide] How to Load Your Own Documents into Local AI" />&lt;h1 id="introduction">Introduction
&lt;/h1>&lt;p>In recent years, the evolution of Large Language Models (LLMs) has been remarkable, and many AIs, led by ChatGPT and Claude, have permeated our daily lives and business operations. However, general LLMs have a distinct weakness. That is, they only know &amp;ldquo;public information at the time of their training&amp;rdquo;. Naturally, they cannot answer questions about &amp;ldquo;private documents&amp;rdquo; such as internal company regulations, personal notes, and unpublished project materials. Forcing them to answer increases the risk of generating plausible lies (hallucinations) that differ from the facts.&lt;/p>
&lt;p>Therefore, the technological architecture known as &lt;strong>RAG (Retrieval-Augmented Generation)&lt;/strong> is currently spreading explosively worldwide. By using RAG, it becomes possible to dynamically provide unique knowledge to the LLM from an external database and have it generate accurate and well-founded answers based on it.&lt;/p>
&lt;p>Furthermore, when handling enterprise domains or personal confidential information, sending data to cloud-based APIs like OpenAI is often unacceptable under security policies. What is required there is the construction of &amp;ldquo;Local RAG&amp;rdquo; combined with &lt;strong>Local AI&lt;/strong> (an LLM that operates entirely on your own PC or on-premise server).&lt;/p>
&lt;p>In this article, we will thoroughly explain everything from the fundamental theory of RAG, specific implementation methods of Local RAG using Python, mathematical background (how vector search works), to advanced techniques for running the system in production.&lt;/p>
&lt;hr>
&lt;h1 id="1-overall-architecture-of-rag">1. Overall Architecture of RAG
&lt;/h1>&lt;p>RAG is not a single AI model, but a system architecture where multiple components work together. It broadly consists of two phases: the &amp;ldquo;Ingestion (Data Loading) Phase&amp;rdquo; and the &amp;ldquo;Retrieval &amp;amp; Generation Phase&amp;rdquo;.&lt;/p>
&lt;p>The Mermaid diagram below shows the overall picture of a RAG system.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "Ingestion Phase (Preparation)"
Doc["Custom Documents (PDF, TXT, etc.)"] --> Loader["Document Loader"]
Loader --> Splitter["Text Splitting (Chunking)"]
Splitter --> EmbedModel1["Embedding Model"]
EmbedModel1 --> VectorDB["Vector Database"]
end
subgraph "Inference Phase (User Query)"
User["User Question (Query)"] --> EmbedModel2["Embedding Model"]
EmbedModel2 --> QueryVector["Query Vector"]
QueryVector --> Search["Similarity Search (Vector Search)"]
VectorDB --> Search
Search --> Context["Relevant Chunk Extraction (Context)"]
User --> PromptBuilder["Prompt Builder"]
Context --> PromptBuilder
PromptBuilder --> LocalLLM["Local LLM"]
LocalLLM --> Answer["Final Answer Generation"]
end&lt;/div>
&lt;h2 id="ingestion-phase-preparation">Ingestion Phase (Preparation)
&lt;/h2>&lt;ol>
&lt;li>&lt;strong>Document Loading&lt;/strong>: Loads unstructured data such as PDFs, Word documents, and text files.&lt;/li>
&lt;li>&lt;strong>Chunking (Text Splitting)&lt;/strong>: Splits long texts into meaningful chunks to fit within the LLM&amp;rsquo;s input limit (context window) and to improve search accuracy.&lt;/li>
&lt;li>&lt;strong>Embedding (Vectorization)&lt;/strong>: Inputs the split chunks into an Embedding Model and converts them into an array of numerical values (vectors) with hundreds to thousands of dimensions.&lt;/li>
&lt;li>&lt;strong>Saving to Database&lt;/strong>: Saves the converted vectors and their associated original text data into a Vector Database (Vector DB).&lt;/li>
&lt;/ol>
&lt;h2 id="inference-phase-runtime">Inference Phase (Runtime)
&lt;/h2>&lt;ol>
&lt;li>&lt;strong>Query Vectorization&lt;/strong>: Vectorizes the user&amp;rsquo;s question text using the same embedding model used in the preparation phase.&lt;/li>
&lt;li>&lt;strong>Similarity Search&lt;/strong>: Performs a similarity calculation between the query vector and the document vectors in the database, and retrieves the top few semantic (highly relevant) text chunks.&lt;/li>
&lt;li>&lt;strong>Prompt Building&lt;/strong>: Combines the retrieved relevant text as &amp;ldquo;context (background knowledge)&amp;rdquo; with the user&amp;rsquo;s question text to create an input prompt for the LLM.&lt;/li>
&lt;li>&lt;strong>Answer Generation&lt;/strong>: The LLM, receiving the augmented prompt, generates an answer based on the provided context information.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h1 id="2-deep-understanding-of-vector-search-and-embeddings">2. Deep Understanding of Vector Search and Embeddings
&lt;/h1>&lt;p>At the core of RAG is &amp;ldquo;Vector Search (Semantic Search)&amp;rdquo;. While traditional keyword search (like BM25) is based on exact word matching and frequency, vector search is based on &amp;ldquo;semantic similarity&amp;rdquo;. For example, even if the words are different, like &amp;ldquo;dog&amp;rdquo; and &amp;ldquo;puppy&amp;rdquo;, or &amp;ldquo;PC&amp;rdquo; and &amp;ldquo;computer&amp;rdquo;, they will be hit in the search if their meanings are close.&lt;/p>
&lt;h2 id="what-is-an-embedding-model">What is an Embedding Model?
&lt;/h2>&lt;p>An embedding model is a neural network that takes natural language text as input and outputs a fixed-length dense vector. Common models (e.g., &lt;code>text-embedding-3-small&lt;/code> or the open-source &lt;code>multilingual-e5-large&lt;/code>) map text into a vector of real numbers with 384 or 1024 dimensions.&lt;/p>
&lt;p>In this multi-dimensional space (latent space), the model is trained so that sentences with similar meanings are closer in distance in the coordinate space.&lt;/p>
&lt;h2 id="mathematical-background-of-similarity-calculation-cosine-similarity">Mathematical Background of Similarity Calculation: Cosine Similarity
&lt;/h2>&lt;p>When a vector database searches for relevant documents, the most commonly used distance metric is &lt;strong>Cosine Similarity&lt;/strong>. Unlike Euclidean distance (absolute spatial distance), cosine similarity focuses on the &amp;ldquo;angle between two vectors&amp;rdquo;. Since it is less affected by the length of the sentence (the norm of the vector), it is highly suitable for calculating text similarity.&lt;/p>
&lt;p>Expressed mathematically, the cosine similarity between vectors $\mathbf{A}$ and $\mathbf{B}$ is as follows:&lt;/p>
$$ \text{Cosine Similarity}(\mathbf{A}, \mathbf{B}) = \cos(\theta) = \frac{\mathbf{A} \cdot \mathbf{B}}{\|\mathbf{A}\| \|\mathbf{B}\|} = \frac{\sum_{i=1}^{n} A_i B_i}{\sqrt{\sum_{i=1}^{n} A_i^2} \sqrt{\sum_{i=1}^{n} B_i^2}} $$
&lt;ul>
&lt;li>$\mathbf{A} \cdot \mathbf{B}$ represents the Dot Product.&lt;/li>
&lt;li>$\|\mathbf{A}\|$ represents the L2 norm (length) of vector $\mathbf{A}$.&lt;/li>
&lt;li>$n$ is the number of dimensions of the vector.&lt;/li>
&lt;/ul>
&lt;p>Cosine similarity takes a value from -1 to 1.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Close to 1&lt;/strong>: The directions of the two vectors are almost the same (meanings are very similar).&lt;/li>
&lt;li>&lt;strong>Close to 0&lt;/strong>: The two vectors are orthogonal (unrelated).&lt;/li>
&lt;li>&lt;strong>Close to -1&lt;/strong>: The two vectors are in opposite directions (meanings are opposite).&lt;/li>
&lt;/ul>
&lt;p>Recent Vector DBs (Chroma, FAISS, Qdrant, etc.) employ an Approximate Nearest Neighbor (ANN) algorithm called HNSW (Hierarchical Navigable Small World), optimizing them to search for documents with high cosine similarity in milliseconds even from millions of vector data.&lt;/p>
&lt;hr>
&lt;h1 id="3-technology-stack-for-building-local-rag">3. Technology Stack for Building Local RAG
&lt;/h1>&lt;p>To build a fully local RAG that does not rely on the cloud, we leverage the open-source ecosystem. The recommended technology stack is introduced below.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Large Language Model (LLM)&lt;/strong>
&lt;ul>
&lt;li>Tools: &lt;code>Ollama&lt;/code> or &lt;code>Llama.cpp&lt;/code>&lt;/li>
&lt;li>Models: Lightweight, high-performance open models like &lt;code>Llama-3-8B-Instruct&lt;/code>, &lt;code>Gemma-2-9B-It&lt;/code>, &lt;code>Qwen2-7B-Instruct&lt;/code>. For Japanese tasks, Japanese-tuned models like &lt;code>Llama-3-ELYZA-JP-8B&lt;/code> are suitable.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Embedding Model (Embedding)&lt;/strong>
&lt;ul>
&lt;li>Models: &lt;code>intfloat/multilingual-e5-large&lt;/code> or &lt;code>BAAI/bge-m3&lt;/code>. When running locally, it is common to download them from Hugging Face and run them with Sentence-Transformers.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Vector Database (Vector DB)&lt;/strong>
&lt;ul>
&lt;li>&lt;code>ChromaDB&lt;/code>: Python-based and extremely easy to set up. Ideal for local development.&lt;/li>
&lt;li>&lt;code>FAISS&lt;/code>: A fast vector search library developed by Meta.&lt;/li>
&lt;li>&lt;code>Qdrant&lt;/code> / &lt;code>Milvus&lt;/code>: For larger scale and production environments.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Orchestration Framework&lt;/strong>
&lt;ul>
&lt;li>&lt;code>LangChain&lt;/code>: The de facto standard for chaining components together.&lt;/li>
&lt;li>&lt;code>LlamaIndex&lt;/code>: A data connection framework specifically specialized for RAG.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>This time, we will implement it using the easiest combination to introduce: &lt;strong>LangChain + ChromaDB + Ollama + HuggingFaceEmbeddings&lt;/strong>.&lt;/p>
&lt;hr>
&lt;h1 id="4-implementation-tutorial-building-a-full-local-rag-with-python">4. Implementation Tutorial: Building a Full Local RAG with Python
&lt;/h1>&lt;p>From here, we will build a local RAG while actually writing Python code. Please install Ollama on your PC in advance and have it running in the background. Also, pull a model on Ollama (e.g., &lt;code>ollama run llama3&lt;/code>).&lt;/p>
&lt;h2 id="step-1-installing-required-libraries">Step 1: Installing Required Libraries
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">pip install langchain langchain-community langchain-huggingface
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pip install chromadb sentence-transformers pypdf
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="step-2-complete-implementation-code">Step 2: Complete Implementation Code
&lt;/h2>&lt;p>Below is the complete Python script to load a PDF file, vectorize it, and have the local LLM answer questions.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;span class="lnt">80
&lt;/span>&lt;span class="lnt">81
&lt;/span>&lt;span class="lnt">82
&lt;/span>&lt;span class="lnt">83
&lt;/span>&lt;span class="lnt">84
&lt;/span>&lt;span class="lnt">85
&lt;/span>&lt;span class="lnt">86
&lt;/span>&lt;span class="lnt">87
&lt;/span>&lt;span class="lnt">88
&lt;/span>&lt;span class="lnt">89
&lt;/span>&lt;span class="lnt">90
&lt;/span>&lt;span class="lnt">91
&lt;/span>&lt;span class="lnt">92
&lt;/span>&lt;span class="lnt">93
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_community.document_loaders&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">PyPDFLoader&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_text_splitters&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">RecursiveCharacterTextSplitter&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_huggingface&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">HuggingFaceEmbeddings&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_community.vectorstores&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Chroma&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_community.llms&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Ollama&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_core.prompts&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">PromptTemplate&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain.chains&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">RetrievalQA&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. Document Loading&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Loading document...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Specify the path of the PDF you want to load&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">file_path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;sample_company_policy.pdf&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">loader&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PyPDFLoader&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">file_path&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">documents&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">loader&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. Chunking (Text Splitting)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Split into appropriate sizes without breaking the meaning of the sentences&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">text_splitter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">RecursiveCharacterTextSplitter&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">chunk_size&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">500&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># Maximum number of characters per chunk&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">chunk_overlap&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">50&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># Overlap characters between previous and next chunks (prevents context disconnection)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">separators&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;。&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;、&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34; &amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">chunks&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">text_splitter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split_documents&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">documents&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Split into &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">chunks&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> chunks.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 3. Initialization of Embedding Model (Local HuggingFace Model)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Using a multilingual model with strong Japanese support&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Loading embedding model...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">HuggingFaceEmbeddings&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;intfloat/multilingual-e5-large&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model_kwargs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;device&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;cpu&amp;#39;&lt;/span>&lt;span class="p">}&lt;/span> &lt;span class="c1"># &amp;#39;cuda&amp;#39; or &amp;#39;mps&amp;#39; if you have a GPU&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 4. Building Vector Database (Chroma)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Building vector database...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">persist_directory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;./chroma_db&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">vectorstore&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Chroma&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_documents&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">documents&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">chunks&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embedding&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">embeddings&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">persist_directory&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">persist_directory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Creating a Retriever. Configured to get the top 3 relevant documents&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">retriever&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vectorstore&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">as_retriever&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">search_kwargs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;k&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 5. Initialization of Local LLM (Ollama)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Connecting to Local LLM...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Make sure to get the model in advance with &amp;#39;ollama pull llama3&amp;#39; etc.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Ollama&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;llama3&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 6. Definition of Prompt Template&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt_template&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;You are an excellent assistant familiar with company regulations and internal information.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">Please answer the user&amp;#39;s question in detail based ONLY on the following context (background information).
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">If you cannot find the answer from the context, please do not guess and honestly answer &amp;#34;I don&amp;#39;t know from the provided information.&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">[Context]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{context}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">[Question]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&lt;/span>&lt;span class="si">{question}&lt;/span>&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">[Answer]:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">PROMPT&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PromptTemplate&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">template&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">prompt_template&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">input_variables&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;context&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;question&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 7. Building RAG Chain&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qa_chain&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">RetrievalQA&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_chain_type&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llm&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">llm&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">chain_type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;stuff&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">retriever&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">retriever&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">return_source_documents&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># Set whether to return source documents&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">chain_type_kwargs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;prompt&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">PROMPT&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 8. Executing a Question&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;Please tell me about the conditions for transportation expenses payment regarding remote work.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">Question: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">qa_chain&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;query&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">query&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;[Answer]&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;result&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">---&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;[Reference Sources]&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">doc&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;source_documents&amp;#39;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;- Page &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">doc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">metadata&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;page&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Unknown&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">doc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">page_content&lt;/span>&lt;span class="p">[:&lt;/span>&lt;span class="mi">50&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">main&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="explanation-of-key-code-points">Explanation of Key Code Points
&lt;/h2>&lt;ol>
&lt;li>&lt;strong>RecursiveCharacterTextSplitter&lt;/strong>:
This is the most recommended splitter for dividing natural language. It attempts to split in the order of paragraphs (&lt;code>\n\n&lt;/code>), lines (&lt;code>\n&lt;/code>), and periods (&lt;code>。&lt;/code>), keeping semantic blocks together as much as possible while fitting within the specified &lt;code>chunk_size&lt;/code>. By setting &lt;code>chunk_overlap&lt;/code>, you prevent context boundaries from being cut off and information from being lost.&lt;/li>
&lt;li>&lt;strong>HuggingFaceEmbeddings&lt;/strong>:
&lt;code>intfloat/multilingual-e5-large&lt;/code> is a very powerful open-source embedding model that supports multiple languages. You can vectorize text locally on your memory offline without using a cloud API (like OpenAI&amp;rsquo;s &lt;code>text-embedding-ada-002&lt;/code>).&lt;/li>
&lt;li>&lt;strong>ChromaDB&lt;/strong>:
Since it runs in-memory or on local storage (SQLite-based), there is no need to spin up a complex database server. By specifying &lt;code>persist_directory&lt;/code>, you can skip the vectorization process on subsequent runs and load the DB from disk.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h1 id="5-advanced-rag-techniques">5. Advanced RAG Techniques
&lt;/h1>&lt;p>The basic RAG system (Naive RAG) built in the above tutorial works, but if high answer accuracy is required in a production environment, the introduction of advanced techniques like the following becomes necessary.&lt;/p>
&lt;h2 id="51-hybrid-search">5.1 Hybrid Search
&lt;/h2>&lt;p>While vector search is good at capturing &amp;ldquo;meaning&amp;rdquo;, it can be poor at strict keyword searches like &amp;ldquo;specific proper nouns&amp;rdquo;, &amp;ldquo;product model numbers&amp;rdquo;, and &amp;ldquo;employee IDs&amp;rdquo;.
Therefore, by running &lt;strong>semantic search&lt;/strong> via vector search and &lt;strong>keyword search&lt;/strong> using algorithms like BM25 in parallel, and integrating both results by scoring them (using techniques like Reciprocal Rank Fusion; RRF), you can drastically reduce search misses.&lt;/p>
&lt;h2 id="52-re-ranking">5.2 Re-ranking
&lt;/h2>&lt;p>Vector search is fast, but it does not necessarily evaluate the exact contextual relevance of the context. A general pipeline for improving search accuracy is as follows:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>First-stage Retrieval&lt;/strong>: Retrieve a broad and shallow range of relevant chunks (about 20-30) from the Vector DB.&lt;/li>
&lt;li>&lt;strong>Re-ranking&lt;/strong>: Use another heavier machine learning model called a Cross-Encoder (e.g., &lt;code>bge-reranker&lt;/code>) to input pairs of the user&amp;rsquo;s query and the retrieved chunks, and recalculate their semantic relevance scores.&lt;/li>
&lt;li>&lt;strong>Selection&lt;/strong>: Pass only the top 3-5 with the highest scores as the final context to the LLM prompt.&lt;/li>
&lt;/ol>
&lt;p>This technique prevents irrelevant noise information from being passed to the LLM, significantly increasing the precision of the answers.&lt;/p>
&lt;div class="mermaid">graph LR
Query["Query"] --> VSearch["Vector Search (Top 20)"]
VSearch --> Reranker["Re-ranker Model (Cross-Encoder)"]
Query --> Reranker
Reranker --> TopK["High Precision Top 3"]
TopK --> LLM["LLM Generation"]&lt;/div>
&lt;h2 id="53-semantic-chunking-and-parent-document-retrieval">5.3 Semantic Chunking and Parent Document Retrieval
&lt;/h2>&lt;p>Instead of mechanically splitting text by a fixed number of characters, there is a technique called &amp;ldquo;Semantic Chunking&amp;rdquo; that uses AI to detect shifts in meaning and splits the text accordingly.
Also, in the &amp;ldquo;Parent Document Retriever&amp;rdquo; technique, you vectorize in very small units (like sentences) for high-precision search, but when passing it to the LLM, you provide the &amp;ldquo;original large paragraph (parent document)&amp;rdquo; containing that sentence, thus providing sufficient context to the LLM.&lt;/p>
&lt;hr>
&lt;h1 id="6-challenges-and-countermeasures-when-operating-local-rag">6. Challenges and Countermeasures when Operating Local RAG
&lt;/h1>&lt;p>There are unique hurdles when building and operating RAG in a local environment.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>VRAM (Video Memory) Exhaustion&lt;/strong>:
To run a Local LLM at a practical speed (dozens of tokens per second), you need to load the model into the GPU&amp;rsquo;s VRAM. Running an 8B class model in fp16 (16-bit floating point) requires about 16GB of VRAM, but by using &lt;strong>Quantization&lt;/strong> technologies (compressing to 4-bit or 8-bit, such as GGUF or AWQ formats), it is possible to run it fast enough even with 8GB of VRAM (like a standard gaming PC). Llama.cpp and Ollama support these quantization formats by default.&lt;/li>
&lt;li>&lt;strong>Context Window Limits&lt;/strong>:
If the amount of retrieved context is too large, it may exceed the LLM&amp;rsquo;s input limit (token limit), or the model might forget the middle part of the information (Lost in the middle phenomenon). Adjusting the number of chunks to extract and carefully selecting them through the aforementioned re-ranking techniques are essential.&lt;/li>
&lt;li>&lt;strong>Data Freshness Management&lt;/strong>:
When a source document is updated, the corresponding document&amp;rsquo;s vector in the vector database also needs to be updated or deleted (CRUD operations). Since ChromaDB supports updates based on document IDs, it is practical to manage file hash values and set up a batch process to sync only the differences.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h1 id="conclusion">Conclusion
&lt;/h1>&lt;p>RAG (Retrieval-Augmented Generation) is a powerful paradigm that evolves AI from a general-purpose assistant into your &amp;ldquo;exclusive expert&amp;rdquo; or an &amp;ldquo;expert specialized in internal business&amp;rdquo;.&lt;/p>
&lt;p>We found that even with highly confidential requirements where cloud services cannot be used, a complete &amp;ldquo;Local RAG&amp;rdquo; environment can be relatively easily built by combining the open-source ecosystem such as Ollama, LangChain, and ChromaDB.&lt;/p>
&lt;p>Based on the advanced approaches such as mathematical understanding of vector space, text splitting, and re-ranking explained in this article, please try developing an original AI system using your own data. The speed of evolution in local AI is astounding, and the system you build today can instantly update its performance tomorrow simply by swapping in a smarter lightweight model that appears.&lt;/p>
&lt;hr>
&lt;p>&lt;em>This blog will continue to publish deep-dive articles on AI technology and RAG. If you have any questions or feedback, please share them in the comments section.&lt;/em>&lt;/p></description></item></channel></rss>