news 2026/5/16 2:50:21

从零搭建 RAG 系统:Milvus 向量数据库 + 大模型完整实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零搭建 RAG 系统:Milvus 向量数据库 + 大模型完整实战指南

从零搭建 RAG 系统:Milvus 向量数据库 + 大模型完整实战指南

本文融合了 RAG 核心概念、技术选型决策树、Milvus 实践和完整代码,帮你系统掌握检索增强生成技术。

目录

  1. 什么是 RAG?为什么要用 RAG?
  2. RAG 系统核心架构
  3. 向量数据库:Milvus 入门与实战
  4. Embedding:文本向量化详解
  5. 文档切片:容易被忽视的关键步骤
  6. 检索方法全解析与选型指南
  7. 索引与度量类型:性能与精度的权衡
  8. Rerank:什么时候值得用?
  9. 完整代码实践:一个可运行的 RAG 系统
  10. 综合决策树:如何为你的场景选择最佳配置
  11. 总结与进阶方向

1. 什么是 RAG?为什么要用 RAG?

RAG(Retrieval-Augmented Generation,检索增强生成)是一种结合信息检索文本生成的 AI 技术框架。它的名字拆解如下:

  • 检索(Retrieval):从外部知识源(向量数据库、搜索引擎等)中查找与问题相关的信息。
  • 增强(Augmented):将检索到的信息拼接到 LLM 的输入中,丰富上下文。
  • 生成(Generation):LLM 基于增强后的提示词生成最终答案。

为什么叫“增强”而不是“加”?

“增强”一词强调检索结果融入生成过程,成为生成决策的依据,而不是两个独立的步骤。类比:开卷考试时允许查阅资料(检索),然后结合自己的理解写出答案(生成)→ “查阅资料增强了你的答题能力”。

为什么需要 RAG?

尽管大语言模型(如 GPT-4、Qwen)表现惊艳,但它们在落地中存在硬伤:

问题说明RAG 如何解决
幻觉模型会编造不存在的事实强制基于检索到的真实文档回答
知识时效训练数据截止后的事件一无所知检索最新文档库,实时更新
私有数据无法访问企业内部文档将私有文档向量化后检索
成本高微调大模型成本高昂无需微调,只更新知识库即可

2. RAG 系统核心架构

┌─────────────────────────────────────────────────────────────┐ │ 用户提问 │ └─────────────────────────────┬───────────────────────────────┘ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 1. 查询向量化(Embedding) │ │ "什么是机器学习?" → [0.12, -0.45, 0.78, ...] │ └─────────────────────────────┬───────────────────────────────┘ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 2. 向量检索(Vector Search) │ │ 在 Milvus 中查找最相似的 Top‑K 文档片段 │ └─────────────────────────────┬───────────────────────────────┘ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 3. (可选)重排序(Rerank) │ │ 用 Cross‑Encoder 对结果精排,提升准确率 │ └─────────────────────────────┬───────────────────────────────┘ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 4. 构建提示词(Prompt) │ │ “请根据以下信息回答:\n[文档1]\n[文档2]\n问题:...” │ └─────────────────────────────┬───────────────────────────────┘ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 5. LLM 生成答案 │ │ 输出基于事实的准确回答 │ └─────────────────────────────────────────────────────────────┘

3. 向量数据库:Milvus 入门与实战

3.1 什么是向量数据库?

传统数据库按精确值查找(如WHERE name = '张三'),而向量数据库按相似度查找。它存储 Embedding 向量,并通过索引加速相似度计算。

Milvus是开源的向量数据库标杆,支持亿级向量毫秒级检索。

3.2 安装与连接

# 推荐使用 Docker 部署(完整功能)dockerrun-d--namemilvus_standalone-p19530:19530 milvusdb/milvus:v2.5.0# 或使用 Milvus Lite(仅限 Linux/Mac)pipinstallmilvus-lite

连接代码:

frompymilvusimportMilvusClient client=MilvusClient(uri="http://localhost:19530")print(client.get_server_version())# 输出如 "2.5.0"

3.3 创建集合(Collection)

client.create_collection(collection_name="knowledge_base",dimension=768,# 向量维度,需与 Embedding 模型匹配auto_id=True,# 主键自动生成metric_type="COSINE"# 相似度度量)

3.4 插入与检索

# 插入data=[{"content":"机器学习是人工智能的核心技术。","vector":[0.1,-0.2,...]}]client.insert("knowledge_base",data)# 检索results=client.search(collection_name="knowledge_base",data=[query_vector],limit=5,output_fields=["content"])

4. Embedding:文本向量化详解

4.1 什么是 Embedding?

Embedding 将文本映射到高维向量空间,语义相近的文本在空间中距离也近。

“苹果” → [0.8, -0.2, 0.5, ...] “香蕉” → [0.7, -0.1, 0.6, ...] ← 距离近 “手机” → [-0.5, 0.8, -0.3, ...] ← 距离远

4.2 常用 Embedding 模型对比

模型维度语言特点
bge-large-zh-v1.51024中文效果最佳,需本地部署
bge-base-zh-v1.5768中文平衡方案
bge-small-zh-v1.5512中文轻量快速
text-embedding-v4(阿里云)1024中英文API 调用,无需部署
text-embedding-3-small(OpenAI)1536多语言效果好,有费用

4.3 Embedding 模型选型决策树

数据可以上传云端吗? ├─ 不能 → 使用本地模型 │ ├─ 有 GPU/大内存(>2GB)→ bge-large-zh-v1.5 │ ├─ 资源受限 → bge-small-zh-v1.5 │ └─ 平衡 → bge-base-zh-v1.5 │ └─ 可以 → 年调用量 > 50 万次? ├─ 是 → 本地部署(长期更省钱) └─ 否 → 云端 API(阿里云或 OpenAI)

⚠️铁律:文档向量化和查询向量化必须使用同一个Embedding 模型。


5. 文档切片:容易被忽视的关键步骤

5.1 切片方法对比

方法原理优点缺点推荐场景
固定字符数每 N 字符一刀切简单快速可能切断句子快速原型
滑动窗口固定大小 + 重叠保留上下文连续性数据冗余通用首选
按段落/句子利用自然分隔语义完整依赖文档格式结构良好文档
AI 语义切片LLM 识别主题边界质量最高成本高、慢高质量 RAG

5.2 滑动窗口切片代码

defsliding_window_chunking(text,chunk_size=500,overlap=50):step=chunk_size-overlap chunks=[]start=0whilestart<len(text):end=min(start+chunk_size,len(text))chunks.append(text[start:end])start+=stepifend==len(text):breakreturnchunks

5.3 参数建议

  • chunk_size:300~500 字符(中文)或 200~300 单词(英文)
  • overlap:50~100 字符(10%~20% 重叠)
  • 原因:过小丢失语义,过大引入噪声;重叠防止边界信息丢失。

6. 检索方法全解析与选型指南

6.1 方法对比

方法原理优势劣势
标量查询精确字段筛选精确、快速无法处理文本语义
向量检索语义相似度理解同义词、跨语言对专有名词不敏感
BM25(关键字)词频+逆文档频率精确匹配专有名词无法理解语义
混合检索向量 + BM25 + RRF 融合综合两者优势实现稍复杂

6.2 什么时候用哪种?

问题中包含明显的专有名词/型号/代码? ├─ 是 → 必须加入 BM25 关键字检索 └─ 否 → 向量检索即可 是否需要高召回率(企业搜索、法律文档)? ├─ 是 → 混合检索(向量+BM25+RRF) └─ 否 → 单一向量检索够用

6.3 混合检索的 RRF 融合算法

向量得分和 BM25 得分尺度不同,不能直接加权平均。RRF(倒数排名融合)是标准方案:

defrrf_fusion(vector_results,keyword_results,k=60):scores={}forrank,(doc_id,_)inenumerate(vector_results):scores[doc_id]=scores.get(doc_id,0)+1/(k+rank+1)forrank,(doc_id,_)inenumerate(keyword_results):scores[doc_id]=scores.get(doc_id,0)+1/(k+rank+1)returnsorted(scores.items(),key=lambdax:x[1],reverse=True)

7. 索引与度量类型:性能与精度的权衡

7.1 索引类型选择

索引数据量检索精度速度内存适用场景
FLAT< 1 万100%测试、小规模
IVF_FLAT1 万 ~ 100 万95~98%通用生产
HNSW任意98~99%最快高精度、高内存
IVF_PQ> 100 万90~95%很快超大规模

决策树

  • 数据量 < 1 万 → FLAT
  • 1 万 ~ 100 万 → IVF_FLAT(推荐)
  • 100 万 → 内存足用 HNSW,内存紧用 IVF_PQ

7.2 度量类型

类型公式判断标准适用场景
COSINE`A·B / (A
L2欧氏距离越小越相似向量未归一化
IP内积越大越相似归一化后与 COSINE 等价

✅ 90% 的语义检索场景用COSINE。BGE、OpenAI、阿里云输出均已归一化。


8. Rerank:什么时候值得用?

8.1 两阶段检索架构

用户查询 → [第一阶段] 召回 50~100 条候选(快)→ [第二阶段] Rerank 精排 Top‑5(准)→ LLM 生成

8.2 启用条件

条件建议
召回数量 > 30 条✅ 值得用
对精度要求极高(医疗、法律)✅ 必须用
实时性要求极高(< 100ms)❌ 跳过
知识库 < 5000 条❌ 直接检索已足够

8.3 模型选择

fromFlagEmbeddingimportFlagReranker# 中文场景reranker=FlagReranker('BAAI/bge-reranker-large')# 效果最好,需 GPU# 轻量级reranker=FlagReranker('BAAI/bge-reranker-base')

9. 完整代码实践:一个可运行的 RAG 系统

importosfrompymilvusimportMilvusClientfromsentence_transformersimportSentenceTransformerimportjiebafromrank_bm25importBM25OkapiclassSimpleRAG:def__init__(self,milvus_uri="http://localhost:19530",collection_name="rag_demo"):self.client=MilvusClient(uri=milvus_uri)self.collection_name=collection_name self.embed_model=SentenceTransformer('BAAI/bge-small-zh-v1.5')self.dim=512self.bm25=Noneself.raw_docs=[]ifnotself.client.has_collection(collection_name):self.client.create_collection(collection_name=collection_name,dimension=self.dim,auto_id=True,metric_type="COSINE")def_chunk_text(self,text,chunk_size=300,overlap=50):step=chunk_size-overlap chunks=[]start=0whilestart<len(text):end=min(start+chunk_size,len(text))chunk=text[start:end].strip()ifchunk:chunks.append(chunk)start+=stepifend==len(text):breakreturnchunksdefadd_documents(self,texts):all_chunks=[]fortextintexts:chunks=self._chunk_text(text)all_chunks.extend(chunks)vectors=self.embed_model.encode(all_chunks)data=[{"content":chunk,"vector":vec.tolist()}forchunk,vecinzip(all_chunks,vectors)]self.client.insert(self.collection_name,data)# 构建 BM25 索引(用于混合检索)self.raw_docs=all_chunks tokenized_docs=[list(jieba.cut(doc))fordocinall_chunks]self.bm25=BM25Okapi(tokenized_docs)print(f"已添加{len(all_chunks)}个文档片段")defsearch(self,query,top_k=5,use_hybrid=True):query_vec=self.embed_model.encode(query).tolist()# 向量检索vector_results=self.client.search(collection_name=self.collection_name,data=[query_vec],limit=top_k*2,output_fields=["content"])[0]ifnotuse_hybridorself.bm25isNone:return[hit["entity"]["content"]forhitinvector_results[:top_k]]# BM25 检索tokenized_query=list(jieba.cut(query))bm25_scores=self.bm25.get_scores(tokenized_query)bm25_ranked=sorted(enumerate(bm25_scores),key=lambdax:x[1],reverse=True)[:top_k*2]# RRF 融合k=60rrf_scores={}forrank,(doc_idx,_)inenumerate(vector_results):rrf_scores[doc_idx]=rrf_scores.get(doc_idx,0)+1/(k+rank+1)forrank,(doc_idx,_)inenumerate(bm25_ranked):rrf_scores[doc_idx]=rrf_scores.get(doc_idx,0)+1/(k+rank+1)sorted_docs=sorted(rrf_scores.items(),key=lambdax:x[1],reverse=True)[:top_k]return[self.raw_docs[idx]foridx,_insorted_docs]# 使用示例rag=SimpleRAG()rag.add_documents(["机器学习是人工智能的核心技术。深度学习是机器学习的子集。"])results=rag.search("什么是机器学习?",use_hybrid=True)fordocinresults:print(doc)

10. 综合决策树:如何为你的场景选择最佳配置

开始 │ ├─ 1. 数据是否敏感? │ ├─ 是 → 本地 Embedding(BGE 系列) │ └─ 否 → 调用量 >50 万/年? → 是:本地 / 否:API │ ├─ 2. 文档结构是否清晰? │ ├─ 是 → 按段落切片 │ └─ 否 → 滑动窗口(size=500, overlap=50) │ ├─ 3. 查询是否包含专有名词? │ ├─ 是 → 混合检索(向量 + BM25 + RRF) │ └─ 否 → 纯向量检索 │ ├─ 4. 数据量级? │ ├─ <1 万 → FLAT 索引 │ ├─ 1~100 万 → IVF_FLAT │ └─ >100 万 → HNSW(内存足)或 IVF_PQ(内存紧) │ └─ 5. 精度要求是否极高? ├─ 是 → 启用 Rerank(召回 50→精排 5) └─ 否 → 跳过 Rerank

不同场景的推荐配置

场景文档量敏感实时推荐配置
企业内部知识库10 万本地 BGE-large + 滑动窗口 + IVF_FLAT + 混合检索 + Rerank
电商商品搜索100 万API + 固定切片 + HNSW + 混合检索
个人学习助手1000本地 bge-small + 滑动窗口 + FLAT + 向量检索
医疗/法律问答5 万本地 BGE-large + AI 语义切片 + IVF_FLAT + 混合检索 +必须 Rerank
实时客服机器人2 万极高API + 段落切片 + IVF_FLAT + 向量检索

11. 总结与进阶方向

核心要点

  • RAG = 检索 + 增强 + 生成,核心是用外部知识增强 LLM 的生成能力。
  • Milvus是向量数据库的首选,支持高效相似度搜索。
  • Embedding模型必须统一,维度要匹配;选型取决于隐私、成本、效果。
  • 切片策略显著影响检索质量,滑动窗口(500/50)是通用推荐。
  • 检索方法从标量→向量→混合→Rerank,逐级提升精度但增加成本。
  • 索引与度量:默认 IVF_FLAT + COSINE,大数据量用 HNSW/PQ。
  • 终极建议:从最简单配置开始,按效果迭代优化。

进阶方向

  1. 知识图谱增强 RAG:结合实体链接,提升复杂问题理解。
  2. Agentic RAG:让 LLM 自主决定检索时机、重写查询、多跳检索。
  3. 评估体系:使用 RAGAS、ARES 等框架评估检索和生成质量。
  4. 缓存策略:对高频查询缓存检索结果,降低延迟和成本。

如果本文对你有帮助,欢迎点赞、收藏、评论。更多 Milvus 实战项目可参考 Milvus Bootcamp。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/16 2:33:49

多模型聚合平台助力Matlab开发者,一站式解决模型选型与调用难题

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 多模型聚合平台助力Matlab开发者&#xff0c;一站式解决模型选型与调用难题 对于使用Matlab进行算法验证或原型开发的工程师和研究…

作者头像 李华
网站建设 2026/5/16 2:31:02

深入解析WuKongIM:Go语言高性能即时通讯内核的设计与实战

1. 项目概述&#xff1a;一个为现代应用而生的即时通讯内核如果你正在开发一个需要实时消息功能的项目&#xff0c;无论是企业内部协同工具、在线客服系统、社交应用&#xff0c;还是物联网设备指令下发平台&#xff0c;你大概率会面临一个核心抉择&#xff1a;是选择成熟的第三…

作者头像 李华
网站建设 2026/5/16 2:30:11

轻量级AI框架解析:从核心原理到边缘部署实战

1. 项目概述&#xff1a;从“jentic/jentic-mini”看轻量级AI应用框架的崛起最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“jentic/jentic-mini”。光看这个名字&#xff0c;你可能会有点摸不着头脑&#xff0c;这到底是啥&#xff1f;是某个新的编程语言&#xff1f;还…

作者头像 李华
网站建设 2026/5/16 2:28:07

iOS蓝牙BLE开发实战:从Core Bluetooth到Arduino双向通信

1. 项目概述与核心思路最近在做一个智能家居的小项目&#xff0c;需要让iPhone和几个传感器节点通过蓝牙通信。虽然网上资料不少&#xff0c;但要么是过于简单的“Hello World”&#xff0c;要么就是官方文档那种读起来像天书的抽象描述。折腾了好几天&#xff0c;总算把Core B…

作者头像 李华
网站建设 2026/5/16 2:21:49

开源HR智能体openhr-agent:本地部署、模块化设计与核心应用场景解析

1. 项目概述&#xff1a;一个开源的HR智能体最近在GitHub上看到一个挺有意思的项目&#xff0c;叫openhr-agent。光看名字&#xff0c;你可能会觉得这又是一个“AI要取代HR”的噱头工具。但实际深入了解一下&#xff0c;我发现它的定位和设计思路&#xff0c;比想象中要务实和清…

作者头像 李华