从玩具到生产:基于 ChromaDB 打造工程级 RAG 系统

私有数据 ,是大模型企业应用的痛点,毕竟大模型是基于在互联网上公开数据训练的。重新把这部分资料加进去,再训练一下模型?也不是不行,但是有点没有性价比,这时候就引出了大模型落地应用的核心技术-> RAG (Retrieval-Augmented Generation,检索增强生成)

1. RAG(检索增强生成)

1.1 什么是RAG?

考试的时候,如果考到不会的知识,不知道各位友人们会不会头疼,如果这时候,允许我们翻书,现去书里找,我们也很有可能找得到对应的答案,哪怕我们可能完全没学过。这就是RAG 的大致思路:不让模型凭空回忆,而是先给它找资料。

RAG,检索增强生成,字面上讲,就是 拿到考题->然后去翻书,通过目录之类的索引,快速翻到(检索 )相关的内容->再根据这些内容(增强 了的内容),回答出问题(生成回答)。

对比简单地把东西一股脑全部跟大模型说一遍,我们能清楚得发现,我们只用了检索到的那一部分内容,并没有让整本书大模型的脑子将占用, 这就是RAG的效率体现。

1.2 RAG的步骤

RAG技术的思路很简单,但是实现并非只是一个单一的技术能实现的,它有一套流水线(流水线) 。 把这头"大象"放进冰箱,总共需要两步:准备好数据让模型拿到数据

第一个阶段:数据准备(Indexing) -> 把书装进书包

在大模型能够翻书 之前,咱们得先把我们想给它看的 整理好,放进书包里。

  1. 加载 (Load):咱们的资料可能是各种各样的格式,一般大模型是不认识这么些格式的,所以我们就需要把 PDF、Word、网页等各种格式的文件读进来,统一提取出纯文本。

  2. 切分 (Chunking) :大模型一次吃不下整本书,就和我们一眼看不完整本《三国演义》一样,它有上下文长度限制 。我们需要把长文本切成一个个小的片段 (Chunks),比如每 500 个字切一段。

  3. 向量化 (Embedding)这是最关键的一步!

    • 计算机无法直接比较"苹果"和"iphone"是不是相关的。
    • 我们需要用一个专门的模型(Embedding Model),把每一段文字变成一串数字向量 (比如 [0.1, -0.5, 0.8, ...]),是不是有点耳熟,对这和大模型训练的Embedding是一个思路,但是我们一般会使用特制 的嵌入模型来做这个专业的事情。
    • 在这个数学空间里,语义相近的词,距离就越近, 这样我们就能知道,这本书中的所有向量,哪些是和我们的问题相关的了。
  4. 存储 (Storage) :把这些向量和对应的文字,存入向量数据库 (Vector DB) 中。

第二个阶段:应用数据给大模型生成(Retrieval & Generation)-> 开卷答题

拿到书了之后,我们想要翻书 ,就得找到和问题有关系 的内容,然后再将这些内容和我们自己的常识结合起来,对提出的问题进行答题。

  1. 问题向量化(Embedding):要想知道用户的提问(例如"火星基地吃什么?")和内容的相关性,我们就需要像对准备的数据一样,用同一个 Embedding 模型将问题变成向量。

  2. 检索 (Retrieval) :拿着这个"问题向量",去向量数据库里搜, 去找到关系性高的内容。

    • 系统会计算:"哪个文档片段的向量,和问题向量的距离最近?"
    • 找出最相似的前 3-5 个片段 (Top-k)。
  3. 增强 (Augmentation) :把这 3-5 个片段拼在一起,和用户的问题组合成一个超级长的 Prompt。

    • Prompt 模板示例: 你是一个助手。请根据以下参考资料回答问题。

      参考资料:[片段1]... [片段2]...

      用户问题:火星基地吃什么?

  4. 生成 (Generation) :把这个 Prompt 喂给大模型(LLM)。大模型阅读资料,总结并生成最终答案。

2. RAG技术选型

好了,理论我们已经懂了,现在我们撸起袖子,准备来实操一下子吧。我们打算从零开始 快速搭建一个工程级 的RAG系统: 私有API助手, 在我直接告诉各位友人们我们要用到的工具前,我觉得也有必要大概让各位友人们知道还有哪些别的选择,我们为什么选择了这几个。

2.1 框架: LlamaIndex vs. LangChain

  • LangChain:万能胶水,适合做复杂的 Agent(智能体),但写 RAG 代码比较啰嗦,抽象层级太碎,我们后面写智能体的时候(如果有精力做智能体的教程的话)再来使用它。

  • LlamaIndex数据专家。专门为 RAG 也就是"索引和检索"而生。接口极度简洁,且对数据清洗(Ingestion)的处理更专业。

  • 结论 :我们做RAG,直接先上LlamaIndex , 快速地实现效果。

2.2 嵌入模型 (Embedding):BGE vs. OpenAI

  • OpenAI (text-embedding-3):效果好,但要钱,且数据要传给 OpenAI(隐私风险)。

  • BAAI/bge-small-zh-v1.5国货之光。中文效果霸榜,体积极小(几百 MB),完全可以在 Kaggle 本地跑。

  • 结论 :为了免费和隐私,首选 BGE-Small

  • PS : 如果是英文资料的话,建议换成 BAAI/bge-small-en-v1.5 或者 OpenAI 的 text-embedding-3-small

2.3 向量数据库:Chroma vs. Milvus vs. Pinecone

  • Pinecone:纯云端 SaaS,不可本地部署,对 Kaggle 不友好。

  • Milvus:性能强悍,适合十亿级数据,需要 Docker 部署,适合数据量大的时候使用,但是对于咱们的这个项目来说,太重了。

  • ChromaDB轻量级王者。可以像 SQLite 一样以"本地文件"形式存在,也可以部署成服务器。

  • 结论 :中小型项目,首选 ChromaDB

3. 上手实操

项目背景:假设我们是一家名叫 "DeepStar" 的初创公司,我们有一套内部绝密的 API 文档,新来的实习生总是问重复的问题。我们要用 RAG 让他自己查。

3.1 环境配置 (Kaggle)

启动 Kaggle Notebook,确保 Internet: OnAccelerator: GPU T4 x2

复制代码
# 1. 更新transformers及其相关库
!pip install -U transformers peft accelerate bitsandbytes sentence-transformers

# 2. 安装 LlamaIndex 核心及相关插件
!pip install llama-index-core llama-index-llms-huggingface llama-index-embeddings-huggingface

# 3. 安装 ChromaDB 向量库支持
!pip install llama-index-vector-stores-chroma chromadb

下载依赖库可能会需要一点时间,之后我看看能不能在kaggle上用uv去做包管理。

3.2 造数据:模拟企业内部文档

我们创建两份文档:一份是核心接口定义,一份是错误码说明。

复制代码
import os

data_path = "/kaggle/working/data"
# 创建数据目录
os.makedirs(data_path, exist_ok=True)

# 文档 1: 核心 API 定义
api_doc = """
[机密] DeepStar 核心交易接口 v2.0
1. 创建订单 API: POST /api/v2/order/create
   - 必填参数: 'user_id' (String), 'amount' (Decimal), 'token' (X-Auth-Token)
   - 特殊逻辑: 如果 amount > 10000, 必须额外传递 'audit_code' (审计码)。
   - 频率限制: 单用户每秒最多 5 次调用。
2. 查询余额 API: GET /api/v2/balance
   - 缓存策略: 默认缓存 5 秒。传递 'no-cache=true' 可强制刷新。
"""

# 文档 2: 错误码字典
error_doc = """
[机密] DeepStar 全局错误码字典
- E1001: 签名验证失败。请检查 X-Auth-Token 是否过期。
- E2009: 余额不足。注意:冻结金额不计入可用余额。
- E5003: 审计风控拦截。大额交易未通过自动审计,请联系人工客服。
"""

with open(f"{/data_path}/api_specs.txt", "w") as f:
    f.write(api_doc)
with open(f"/{data_path}/error_codes.txt", "w") as f:
    f.write(error_doc)

print("[Success] 企业文档库已就绪!")

3.3 初始化大脑与眼睛 (Settings)

提前根据自己的情况来配置待会儿用的词嵌入模型推理模型

复制代码
embedding_model ="BAAI/bge-small-zh-v1.5"
llm = "Qwen/Qwen2.5-7B-Instruct"
# 在本地服务器,可以用modelscope下载下来, 把路径配置在这儿

利用 Settings 全局配置,将默认的 OpenAI 替换为本地模型。

复制代码
import torch
from llama_index.core import Settings
from llama_index.llms.huggingface import HuggingFaceLLM
from llama_index.embeddings.huggingface import HuggingFaceEmbedding

# 1. 设置 Embedding (眼睛)
# 使用 BGE-Small,显存占用极低,检索中文效果极佳
print("正在加载 Embedding 模型...")

Settings.embed_model = HuggingFaceEmbedding(
    model_name=embedding_model
)

# 2. 设置 LLM (大脑)
# 使用 Qwen2.5-7B-Instruct
print("正在加载 LLM 模型...")
Settings.llm = HuggingFaceLLM(
    model_name=llm,
    tokenizer_name=llm,
    context_window=30000,
    max_new_tokens=512,
    generate_kwargs={"temperature": 0.1, "do_sample": True}, # 技术文档要求严谨,温度调低
    device_map="auto",
    model_kwargs={"dtype": torch.float16, "trust_remote_code": True}
)
print("[Success] 模型加载完毕!")
相关推荐
Dxy12393102162 小时前
如何使用 ECharts 绘制 K 线图
开发语言·javascript
Frank_refuel2 小时前
QT->信号与槽详解下补充(概述、使用、自定义、连接方式、其他说明)
开发语言·qt
happymaker06262 小时前
VueCli标准化工程中的组件通信操作
开发语言·前端·javascript
ySq0REx012 小时前
.NET 10 & C# 14 New Features 新增功能介绍-.NET CLI工具改进
开发语言·c#·.net
Howrun7772 小时前
C++ 项目测试全指南:从 0 基础到落地实操
开发语言·c++·log4j
小灰灰搞电子2 小时前
Qt UI 线程详解-阻塞与解决方案
开发语言·qt·ui
追光的蜗牛丿2 小时前
C++传递参数时什么情况下传递引用
开发语言·javascript·c++
Pocker_Spades_A2 小时前
Python快速入门专业版(五十六)——爬虫会话管理:Cookie与Session原理及实战(保持登录状态)
开发语言·爬虫·python
MwEUwQ3Gx2 小时前
深入理解 Java Deque 的设计哲学
java·开发语言·python