<?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/zh-cn/tags/rag/</link><description>Recent content in RAG on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 13:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/zh-cn/tags/rag/index.xml" rel="self" type="application/rss+xml"/><item><title>【RAG入门指南】如何让本地AI读取你的专属文档</title><link>http://kenji.blog/zh-cn/p/rag-local-ai-implementation-guide/</link><pubDate>Fri, 11 Sep 2026 13:00:00 +0900</pubDate><guid>http://kenji.blog/zh-cn/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入门指南】如何让本地AI读取你的专属文档" />&lt;h1 id="前言">前言
&lt;/h1>&lt;p>近年来，大型语言模型（LLM）的进化引人瞩目，以ChatGPT和Claude等为首的众多AI已经渗透到我们的生活和工作中。然而，通用的LLM存在一个明显的弱点。那就是它们只知道“训练时的公开信息”。对于公司内部规定、个人笔记、未公开的项目资料等“私密文档”相关的问题，它们理所当然地无法回答。如果强行让它们回答，产生听起来很有道理但与事实不符的谎言（幻觉/Hallucination）的风险就会增加。&lt;/p>
&lt;p>因此，目前在全世界爆发性普及的是**RAG（Retrieval-Augmented Generation：检索增强生成）**这一技术架构。通过使用RAG，可以动态地从外部数据库向LLM提供专有知识，并让其基于这些知识生成准确且有根据的回答。&lt;/p>
&lt;p>此外，在处理企业领域或个人机密信息时，将数据发送到OpenAI等基于云的API在安全策略上往往是不被允许的。因此，我们需要构建结合了&lt;strong>本地AI&lt;/strong>（在自己的PC或本地服务器上完全运行的LLM）的“本地RAG”。&lt;/p>
&lt;p>本文将从RAG的基础理论开始，彻底解说使用Python构建本地RAG的具体实现方法、数学背景（向量检索的原理），以及使系统在生产环境中运行的高级技巧。&lt;/p>
&lt;hr>
&lt;h1 id="1-rag的整体架构">1. RAG的整体架构
&lt;/h1>&lt;p>RAG不是单一的AI模型，而是一个由多个组件协同工作的系统架构。它大致分为“摄取（数据导入）阶段”和“检索与生成（Retrieval &amp;amp; Generation）阶段”两部分。&lt;/p>
&lt;p>以下Mermaid图展示了RAG系统的全貌。&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "摄取阶段 (事前准备)"
Doc["专属文档 (PDF, TXT, etc.)"] --> Loader["文档加载器"]
Loader --> Splitter["文本分割 (分块/Chunking)"]
Splitter --> EmbedModel1["嵌入模型 (Embedding)"]
EmbedModel1 --> VectorDB["向量数据库"]
end
subgraph "推理阶段 (用户查询时)"
User["来自用户的提问 (查询/Query)"] --> EmbedModel2["嵌入模型 (Embedding)"]
EmbedModel2 --> QueryVector["查询向量"]
QueryVector --> Search["相似度检索 (向量检索)"]
VectorDB --> Search
Search --> Context["相关分块提取 (上下文/Context)"]
User --> PromptBuilder["构建提示词"]
Context --> PromptBuilder
PromptBuilder --> LocalLLM["本地LLM"]
LocalLLM --> Answer["生成最终回答"]
end&lt;/div>
&lt;h2 id="摄取阶段事前准备">摄取阶段（事前准备）
&lt;/h2>&lt;ol>
&lt;li>&lt;strong>加载文档&lt;/strong>：读取PDF、Word、文本文件等非结构化数据。&lt;/li>
&lt;li>&lt;strong>分块（文本分割）&lt;/strong>：为了适应LLM的输入限制（上下文窗口），并提高检索精度，将长文章分割成有意义的块（Chunk）。&lt;/li>
&lt;li>&lt;strong>嵌入（向量化）&lt;/strong>：将分割好的块输入到嵌入模型（Embedding Model）中，并将其转换为数百到数千维的数值数组（向量）。&lt;/li>
&lt;li>&lt;strong>保存到数据库&lt;/strong>：将转换后的向量与原始文本数据关联，并保存到向量数据库（Vector DB）中。&lt;/li>
&lt;/ol>
&lt;h2 id="推理阶段运行时">推理阶段（运行时）
&lt;/h2>&lt;ol>
&lt;li>&lt;strong>查询的向量化&lt;/strong>：使用与事前准备相同的嵌入模型，将用户的提问文本向量化。&lt;/li>
&lt;li>&lt;strong>相似度检索&lt;/strong>：在查询向量和数据库中的文档向量之间进行相似度计算，获取几条语义上最接近（相关性最高）的文本块。&lt;/li>
&lt;li>&lt;strong>构建提示词&lt;/strong>：将获取的相关文本作为“上下文（背景知识）”与用户的提问文本结合，创建输入给LLM的提示词（Prompt）。&lt;/li>
&lt;li>&lt;strong>生成回答&lt;/strong>：接收到增强提示词的LLM，基于附加的上下文信息生成回答。&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h1 id="2-深入理解向量检索与嵌入embeddings">2. 深入理解向量检索与嵌入（Embeddings）
&lt;/h1>&lt;p>构成RAG核心的是“向量检索（语义检索）”。与传统的基于单词完全匹配或频率的关键字检索（如BM25）不同，向量检索基于“语义的相似性”。例如，“狗”和“小狗”、“PC”和“电脑”，即使是不同的单词，只要意思相近就会被检索到。&lt;/p>
&lt;h2 id="什么是嵌入模型embedding-model">什么是嵌入模型（Embedding Model）？
&lt;/h2>&lt;p>嵌入模型是一种神经网络，它接收自然语言文本作为输入，并输出固定长度的稠密向量（Dense Vector）。一般的模型（例如 &lt;code>text-embedding-3-small&lt;/code> 或开源的 &lt;code>multilingual-e5-large&lt;/code>）会将文本映射为384维或1024维的实数向量。&lt;/p>
&lt;p>在这个多维空间（潜在空间）中，模型被训练为：意思越相似的文章，在坐标空间上的距离越近。&lt;/p>
&lt;h2 id="相似度计算的数学背景余弦相似度">相似度计算的数学背景：余弦相似度
&lt;/h2>&lt;p>当向量数据库检索相关文档时，最常用的距离指标是&lt;strong>余弦相似度（Cosine Similarity）&lt;/strong>。与欧几里得距离（空间上的绝对距离）不同，余弦相似度关注“两个向量之间的夹角”。因为它不容易受文章长度（向量的范数）影响，所以非常适合计算文本的相似度。&lt;/p>
&lt;p>用数学公式表示，向量 $\mathbf{A}$ 和 $\mathbf{B}$ 的余弦相似度如下所示：&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}$ 表示内积（Dot Product）。&lt;/li>
&lt;li>$\|\mathbf{A}\|$ 表示向量 $\mathbf{A}$ 的L2范数（长度）。&lt;/li>
&lt;li>$n$ 是向量的维数。&lt;/li>
&lt;/ul>
&lt;p>余弦相似度的取值范围是 -1 到 1。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>接近 1&lt;/strong>：两个向量的方向几乎相同（意思非常相似）&lt;/li>
&lt;li>&lt;strong>接近 0&lt;/strong>：两个向量正交（无关）&lt;/li>
&lt;li>&lt;strong>接近 -1&lt;/strong>：两个向量方向完全相反（意思相反）&lt;/li>
&lt;/ul>
&lt;p>最近的向量数据库（Chroma, FAISS, Qdrant等）采用了被称为HNSW（Hierarchical Navigable Small World）的近似最近邻搜索（ANN）算法，经过优化，即使在数百万条向量数据中，也能在毫秒级内检索出余弦相似度高的文档。&lt;/p>
&lt;hr>
&lt;h1 id="3-构建本地rag的技术栈">3. 构建本地RAG的技术栈
&lt;/h1>&lt;p>为了构建完全不依赖云端的本地RAG，我们将利用开源生态系统。以下是推荐的技术栈。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>语言模型 (LLM)&lt;/strong>
&lt;ul>
&lt;li>工具：&lt;code>Ollama&lt;/code> 或 &lt;code>Llama.cpp&lt;/code>&lt;/li>
&lt;li>模型：&lt;code>Llama-3-8B-Instruct&lt;/code>、&lt;code>Gemma-2-9B-It&lt;/code>、&lt;code>Qwen2-7B-Instruct&lt;/code> 等轻量且高性能的开源模型。对于日语任务，经过日语微调的 &lt;code>Llama-3-ELYZA-JP-8B&lt;/code> 等较为合适。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>嵌入模型 (Embedding)&lt;/strong>
&lt;ul>
&lt;li>模型：&lt;code>intfloat/multilingual-e5-large&lt;/code> 或 &lt;code>BAAI/bge-m3&lt;/code>。在本地运行时，通常从Hugging Face下载并使用Sentence-Transformers来执行。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>向量数据库 (Vector DB)&lt;/strong>
&lt;ul>
&lt;li>&lt;code>ChromaDB&lt;/code>：基于Python，设置极其简单。非常适合本地开发。&lt;/li>
&lt;li>&lt;code>FAISS&lt;/code>：Meta开发的高速向量检索库。&lt;/li>
&lt;li>&lt;code>Qdrant&lt;/code> / &lt;code>Milvus&lt;/code>：规模更大，面向生产环境。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>编排框架&lt;/strong>
&lt;ul>
&lt;li>&lt;code>LangChain&lt;/code>：用于连接（Chain）各组件的事实标准。&lt;/li>
&lt;li>&lt;code>LlamaIndex&lt;/code>：特别专注于RAG的数据连接框架。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>这次我们将使用最容易导入的 &lt;strong>LangChain + ChromaDB + Ollama + HuggingFaceEmbeddings&lt;/strong> 组合来进行实现。&lt;/p>
&lt;hr>
&lt;h1 id="4-实现教程使用python构建完整的本地rag">4. 实现教程：使用Python构建完整的本地RAG
&lt;/h1>&lt;p>接下来，我们将实际编写Python代码来构建本地RAG。请预先在PC上安装Ollama并在后台启动它。另外，在Ollama上拉取模型（例如：&lt;code>ollama run llama3&lt;/code>）。&lt;/p>
&lt;h2 id="step-1-安装必要的库">Step 1: 安装必要的库
&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-实现代码全貌">Step 2: 实现代码全貌
&lt;/h2>&lt;p>以下是一个完整的Python脚本，用于读取PDF文件，将其向量化，并让本地LLM进行问答。&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. 加载文档&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;正在加载文档...&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"># 指定要读取的PDF的路径&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. 文本分块（Text Splitting）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 在不破坏文章含义的前提下，分割成适当的大小&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"># 每个分块的最大字符数&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"># 前后分块的重叠字符数（防止上下文断裂）&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;已分割成 &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"> 个块。&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. 初始化嵌入模型 (Local HuggingFace Model)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 使用支持多语言的强大模型&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;正在加载嵌入模型...&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"># 如果有GPU，使用 &amp;#39;cuda&amp;#39; 或 &amp;#39;mps&amp;#39;&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. 构建向量数据库 (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;正在构建向量数据库...&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"># 创建检索器（Retriever）。设置为获取排名前3的相关文档&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. 初始化本地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;正在连接本地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"># 必须事先通过 &amp;#39;ollama pull llama3&amp;#39; 等命令获取模型&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. 定义提示词模板&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;你是一位熟悉公司规定和内部信息的优秀助手。
&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">如果你在上下文中找不到答案，请不要随意猜测，而是诚实地回答“根据提供的信息无法得知”。
&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">【上下文】
&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">【问题】
&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">【回答】:
&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. 构建RAG链&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"># 设置是否返回信息源&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. 执行提问&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;请告诉我关于远程办公的交通费报销条件。&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">问题: &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;【回答】&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;【参考的信息源】&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;- 第 &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;未知&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="代码要点解说">代码要点解说
&lt;/h2>&lt;ol>
&lt;li>&lt;strong>RecursiveCharacterTextSplitter&lt;/strong>:
这是在自然语言分割中最被推荐的分割器。它会尝试按照段落(&lt;code>\n\n&lt;/code>)、行(&lt;code>\n&lt;/code>)、句号(&lt;code>。&lt;/code>)的顺序进行分割，在尽可能保持语义完整性的同时，使其适应指定的 &lt;code>chunk_size&lt;/code>。通过设置 &lt;code>chunk_overlap&lt;/code>，可以防止由于上下文边界被切断而导致的信息丢失。&lt;/li>
&lt;li>&lt;strong>HuggingFaceEmbeddings&lt;/strong>:
&lt;code>intfloat/multilingual-e5-large&lt;/code> 是一款非常强大的支持多语言的开源嵌入模型。你可以不使用云端API（如OpenAI的 &lt;code>text-embedding-ada-002&lt;/code> 等），在本地内存中离线地将文本向量化。&lt;/li>
&lt;li>&lt;strong>ChromaDB&lt;/strong>:
因为它在内存中或作为本地存储（基于SQLite）运行，所以不需要建立复杂的数据库服务器。通过指定 &lt;code>persist_directory&lt;/code>，可以在重新运行时跳过向量化过程，直接从磁盘读取数据库。&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h1 id="5-高级rag技术advanced-rag-techniques">5. 高级RAG技术（Advanced RAG Techniques）
&lt;/h1>&lt;p>虽然使用上述教程构建的基础RAG系统（Naive RAG）也能运行，但在生产环境中如果要求很高的回答精度，就需要引入以下高级技术。&lt;/p>
&lt;h2 id="51-混合检索-hybrid-search">5.1 混合检索 (Hybrid Search)
&lt;/h2>&lt;p>向量检索擅长捕捉“语义”，但有时不擅长精确的关键字检索，比如“特定的专有名词”、“产品型号”、“员工ID”等。
因此，将基于向量检索的&lt;strong>语义检索&lt;/strong>和基于BM25算法等的&lt;strong>关键字检索&lt;/strong>并行执行，然后对两者的结果进行打分并合并（使用倒数排名融合；RRF等方法），可以大幅减少检索遗漏。&lt;/p>
&lt;h2 id="52-重排-re-ranking">5.2 重排 (Re-ranking)
&lt;/h2>&lt;p>向量检索速度很快，但它并不一定能准确评估上下文的语义契合度。为了提高检索精度，一般的管道流程如下：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>初次检索 (First-stage Retrieval)&lt;/strong>: 从向量数据库中，广泛而浅层地获取约20~30个相关分块。&lt;/li>
&lt;li>&lt;strong>重新评估 (Re-ranking)&lt;/strong>: 使用被称为Cross-Encoder的另一种参数量更大的机器学习模型（例如：&lt;code>bge-reranker&lt;/code> 等），输入用户查询和获取到的分块的配对，重新计算语义契合度分数。&lt;/li>
&lt;li>&lt;strong>筛选&lt;/strong>: 仅挑选出分数最高的3~5个作为最终的上下文，传递给LLM的提示词中。&lt;/li>
&lt;/ol>
&lt;p>通过这种方法，可以防止无关的噪声信息传递给LLM，从而大幅提高回答的精度（Precision）。&lt;/p>
&lt;div class="mermaid">graph LR
Query["查询"] --> VSearch["向量检索 (前20名)"]
VSearch --> Reranker["重排模型 (Cross-Encoder)"]
Query --> Reranker
Reranker --> TopK["高精度的前3名"]
TopK --> LLM["LLM生成"]&lt;/div>
&lt;h2 id="53-语义分块与父文档检索">5.3 语义分块与父文档检索
&lt;/h2>&lt;p>有一种名为“Semantic Chunking”的方法，它不是按照固定字符数机械地分割文本，而是使用AI检测文章语义的转折点来进行分割。
此外，“Parent Document Retriever（父文档检索）”这种方法，在检索时以非常小的单位（如句子等）进行向量化以实现高精度的检索，而在传递给LLM时，则传递包含该句子的“原始大段落（父文档）”，从而为LLM提供充足的上下文（Context）。&lt;/p>
&lt;hr>
&lt;h1 id="6-本地rag运行时的挑战与对策">6. 本地RAG运行时的挑战与对策
&lt;/h1>&lt;p>在本地环境中构建和运行RAG时，存在一些特有的障碍。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>VRAM（显存）枯竭&lt;/strong>:
为了让本地LLM以实用的速度（每秒数十个Token）运行，必须将模型加载到GPU的VRAM中。以fp16（16位浮点数）运行8B级别的模型大约需要16GB的VRAM。但是，通过使用**量化（Quantization）**技术（如GGUF、AWQ格式等，将其压缩为4bit或8bit的技术），即使是8GB的VRAM（如一般的游戏PC等）也能足够高速地运行。Llama.cpp和Ollama原生支持这些量化格式。&lt;/li>
&lt;li>&lt;strong>上下文窗口的限制&lt;/strong>:
如果检索获取到的上下文数量过多，可能会超出LLM的输入上限（Token限制），或者导致模型忘记中间部分的信息（Lost in the middle现象）。调整提取的分块数量，以及通过上述重排技术进行严格筛选是不可或缺的。&lt;/li>
&lt;li>&lt;strong>数据的时效性管理&lt;/strong>:
当源文档被更新时，向量数据库中对应文档的向量也必须进行更新或删除（CRUD操作）。因为ChromaDB支持基于文档ID的更新，所以通过管理文件的哈希值，并编写仅同步差异的批处理程序是非常实用的做法。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h1 id="总结">总结
&lt;/h1>&lt;p>RAG（检索增强生成）是一种强大的范式，它将AI从通用的助手进化为“你的专属专家”或“专注于公司内部业务的专家”。&lt;/p>
&lt;p>我们了解到，即使在无法使用云服务、保密性要求极高的情况下，通过组合Ollama、LangChain、ChromaDB等开源生态系统，也能相对容易地构建出完全的“本地RAG”环境。&lt;/p>
&lt;p>基于本文解说的向量空间的数学原理，以及文本分块、重排等高级方法，请务必尝试使用您自己的数据来开发原创的AI系统。本地AI的进化速度非常惊人，今天构建的系统，明天只需替换为更聪明的轻量级模型，就能在瞬间完成性能的升级。&lt;/p>
&lt;hr>
&lt;p>&lt;em>本博客今后将继续发布关于AI技术和RAG的深度文章。如果您有任何问题或反馈，请务必在评论区留言。&lt;/em>&lt;/p></description></item></channel></rss>