你的公司服务器上有 500GB 的文档。
你被要求接入一个像 ChatGPT 一样的人工智能助手,用来回答关于这些文档的问题。
你心想,天啊,这要怎么完成?
根据你的经验,典型的聊天应用最多只能接受十几个文件。
因此,你必须使用一种不同的方法,让 AI 能够搜索、阅读并理解全部文件。
但该怎么做呢?
传统方法的局限性
也许你认为可以创建一个聪明的算法来搜索文档的标题和内容,并按相关性排序。
但你很快意识到,这意味着每次用户搜索时,都需要搜索全部 500GB 的文档。
这是一种非常低效的方式。
于是,你可能尝试另一种方法,通过预处理工作,提前将所有文档总结成可搜索的块。
但你也意识到,在这种情况下,结果可能不会很准确。
融合两种思路
让我们尝试一种不同的方法。
为什么不把这两种想法结合起来,取其精华呢?
从大语言模型(LLM)开始,我们知道其接收输入的核心思想是词嵌入(word embedding)。
这意味着人类语言被转换成数值表示,因为计算机不能用词语思考,只能用数字。
那么,有没有可能我们不用搜索全部 500GB 的文档,而是通过保留这些词语的语义(即意义),将文档存储为向量嵌入,并把这些向量存入数据库中呢?
如果我们能做到这一点,也许我们可以通过将上下文分割成向量数据库中的块(chunks)来更快地检索它们。
这样,AI 助手就能将它们放入其上下文窗口并生成输出。
这种方法被称为 RAG,即检索增强生成(Retrieval Augmented Generation)。
RAG 的工作原理
假设公司使用 AI 助手的一个用例是提问,比如:“你能告诉我去年与 CodeCloud 的服务协议吗?”
为了理解 RAG 的工作原理,我们需要将其分解为三个步骤:检索、增强和生成。
graph TD;
A[用户提问] --> B{词嵌入};
B --> C[向量数据库];
C -- 语义搜索 --> D[检索相关文档块];
A --> E{增强};
D --> E;
E --> F[大语言模型 (LLM)];
F -- 生成 --> G[最终答案];
第一步:检索 (Retrieval)
就像我们将文档转换为向量嵌入并存入数据库一样,我们对问题“你能告诉我去年与 CodeCloud 的服务协议吗?”也执行完全相同的步骤。
一旦问题的词嵌入生成,这个嵌入会与文档的嵌入进行比较。
这种搜索类型称为语义搜索。
它不是通过静态关键词来查找相关内容,而是利用查询的意义和上下文来匹配现有文档。
第二-步:增强 (Augmentation)
RAG 中的增强指的是在运行时将检索到的数据注入到提示(prompt)中的过程。
你可能会想,这有什么特别的?
通常,AI 助手依赖于它们在预训练期间学到的知识,这些是静态知识,很快就会过时。
而我们的目标是让 AI 助手依赖向量数据库中最新的信息。
因此,在运行时,我们需要能够为 AI 助手提供有助于回答上述问题的重要细节。
在 RAG 的情况下,语义搜索结果会附加到提示中,这实质上是作为一种增强知识。
这样,对于你的公司来说,AI 助手被赋予了关于公司文档的细节,这些文档是真实的、最新的私有数据集。
所有这一切都可以在无需微调 AI 模型或修改大语言模型的情况下发生。
第三步:生成 (Generation)
这是 RAG 的最后一步。
在这一步,AI 助手根据从向量数据库中检索到的语义相关数据生成响应。
对于最初的提示:“你能告诉我去年与 CodeCloud 的服务协议吗?”
AI 助手现在将通过使用与 CodeCloud 服务协议相关的文档来展示其对公司知识库的理解。
由于最初的提示指定了“去年”的标准,生成步骤将利用其自身的推理能力来处理提供的数据,以获得问题的最佳答案。
[!TIP] RAG 是一个非常强大的系统,可以即时提升其训练数据之外的知识深度。 但就像任何其他系统一样,学习如何校准是一项需要后天学习的技能,以获得更好的结果。
RAG 系统的校准
例如,在将数据存入向量数据库之前,知道如何分块(chunking)是一个关键决策,它将决定 RAG 的效能。
为了建立一个 RAG 系统,你必须采用不同的策略,例如:
- 分块策略:确定每个块的大小和重叠部分。
- 嵌入策略:决定使用哪个嵌入模型来将你的文档转换为向量嵌入。
- 检索策略:控制词语相似度的阈值,以及你可能想在数据集中添加的额外过滤器。
建立一个 RAG 系统会因系统而异,因为它在很大程度上取决于你试图存储的数据集。
例如,法律文件与客户支持记录文档相比,需要不同的分块策略。
这是因为法律文件通常有需要保留的长而结构化的段落。
而对话记录则可以采用句子级别的分块,并有高重叠以保留上下文。
RAG 的实践应用
现在我们已经涵盖了 RAG 的概念元素,让我们看看它在实践中是什么样子的。
为了更好地理解这一点,我们可以看一个专门关于如何使用 RAG 的实验。
真实世界任务:将 500GB 公司文档转化为即时答案
当我打开这个实验时,我直接进入了一个真实世界的任务。
500GB 的公司文档需要通过一个 RAG 系统转化为即时、准确的答案。
1. 建立开发环境
我创建了一个 Python 虚拟环境,激活它,安装了 uv,然后引入了 chromadb、sentence-transformers、openai 和 flask。
python -m venv .venv
source .venv/bin/activate
uv pip install chromadb sentence-transformers openai flask
一个标记为“就绪”的小提示确认我已设置好。
测试检查 venv 是否存在,uv 是否可用,以及所有四个包是否都已干净地安装。
2. 审查 TechCorp 的文档库
我浏览了模拟的 Markdown 文档库,包括员工手册、产品规格、会议记录和常见问题解答。
techcorp_docs/
├── employee_handbook.md
├── product_specs/
│ ├── product_a.md
│ └── product_b.md
├── meeting_notes/
│ └── q1_2026_planning.md
└── faq.md
关键是要将这些文档视为一个真实的企业语料库,并使它们可以通过意义而不仅仅是关键词来搜索。
3. 初始化向量数据库
我在本地使用持久化客户端启动了 ChromaDB,并创建了一个名为 techcorp_docs 的集合。
import chromadb
# 初始化持久化客户端
client = chromadb.PersistentClient(path="/path/to/db")
# 创建集合
collection = client.create_collection(name="techcorp_docs")
测试验证了 chroma_db 目录是否存在,并且初始化脚本也存在。
这是我们 AI 大脑的存储。
4. 学习分块策略
我写了一个小脚本,将文本分块,大小为 500,重叠为 100。
这保留了跨边界的上下文,并提高了检索质量。
它打印出分块统计信息,并写入一个包含分块计数的验证文件。
测试检查脚本是否存在,并且输出文件是否有效。分块对于准确性至关重要。
5. 理解嵌入
我从 sentence-transformers 加载了 all-MiniLM-L6-v2 模型,编码了几个短句,并计算了相似度。
测试检查结果文件是否存在,并包含相似度值。
这里的核心思想是,问题和文档都变成了向量。
所以我们可以衡量意义,而不仅仅是词语。
因此,“允许带狗”(dogs allowed)和“允许带宠物”(pets permitted)有很高的相似度。
然而,“远程工作”(remote work)则没有相似度。
6. 喂养 AI 大脑
这是所有部分结合在一起的地方。
我遍历 TechCorp 的文档,分块大小为 500,步幅为 400,用 all-MiniLM-L6-v2 嵌入每个块,并将向量和元数据存储到 techcorp_docs 集合中。
它记录每个文件的进度并写入一个摘要。
测试确认了摄取脚本的存在,完成文件已创建,并且格式有效。
这是我们的知识摄取管道。
7. 激活语义搜索
我构建了一个小型的搜索引擎脚本,加载集合,嵌入三个 CEO 风格的查询,并按语义相似度获取最高结果。
它将结果写入文件,并打印结构化输出。
测试确保脚本存在,结果文件存在,并且所有三个查询都已运行。
自己探索这个问题,阅读结果,看看基于意义的搜索效果如何。
8. 启动一个简单的 Web 界面
我启动了一个 Flask 应用,端口为 5000,然后运行一个标记。
我们被要求像 CEO 一样测试。
我打开应用并尝试提问,比如“宠物政策是什么?”
我观察了 RAG 的流程:检索、增强、生成,并附带来源。
然后我将测试标记为已测试。
这就是演示价值的闪光点:答案基于我们的私有文档。
总结与关键点
通过检索、增强和生成的结合,我们准备好了一个可以提问的用户界面。
我们拥有了一个端到端的 RAG 系统,它快速、有根据且可扩展。
在此过程中,我特别注意了以下几点:
- 模型:
all-MiniLM-L6-v2,它紧凑而有效。 - 分块: 测试时大小为 500,重叠为 100;摄取时步幅为 400。两者都保留了上下文以获得更好的召回率。
- 存储: Chroma 持久化客户端,文档集合为
techcorp_docs。 - Web: 简单的 Flask 应用,端口为 5000,用于快速评估。
- 安全: 相似度阈值排除了低质量的匹配,减少了幻觉。
在结束之前,自己探索这些问题,并注意检索质量和答案的帮助性如何随着微调而变化。
就是这样。我们从零开始,建立了一个由真实测试、清晰结构和演示界面支持的工作中的 RAG 系统。
去亲手试试吧。