在我们<u>上一篇文章</u>中,我们探讨了如何通过构建知识库,使得大模型能够从“无状态”变成“有状态”,从而增强其记忆和上下文感知的能力。知识库作为一种让大模型“拥有记忆”的方式,其形式多种多样,从传统的文件系统到数据库,再到如今被广泛使用的向量数据库。这些不同的知识载体并非都是同等适用的,尤其在语义检索的时代,向量数据库正逐渐成为行业的事实标准,成为大模型知识存储和检索的核心。
主要有以下这些问题:
toc
随着对知识库概念的进一步深入理解,我们也更加清晰地认识到:在整个AI系统中,Embedding、向量数据库与LLM(大语言模型)并非孤立存在,而是形成了一个完整的工作链路。正是这个链条,让AI能够更加智能、精确地理解问题、存储信息,并做出最为贴切的回应。而这一切的基础,正是通过向量数据库来打下的坚实基础。
接下来,我们将深入探讨向量数据库的核心概念,并结合实际案例演示,一起来更好地理解向量数据库在大模型中的实际应用。
在了解向量数据库之前,我们还是要明确一下到底什么是向量?
向量(Vector)在数学、物理、计算机科学等领域中有着广泛的应用。它是一个表示具有大小和方向的量,在机器学习和数据科学中,向量通常表示为一组数字(通常是浮点数),这些数字用于描述一个对象的特征或属性。
比如在 Milvus 这样的向量数据库中,向量常常用来表示数据(例如文本、图像、音频等)的特征,以便进行高效的相似度检索。
1、数学上的向量:
在数学中,向量是一个有大小和方向的量。通常在二维或三维空间中,向量可以表示为一个有序的数值序列:

向量的长度(或称为模)表示其大小,而方向表示其朝向。
2、向量在计算机科学中的应用:
1)特征表示: 在机器学习、深度学习、自然语言处理(NLP)等领域,向量通常用来表示数据的特征。例如:
2)高维空间: 向量不仅限于二维或三维空间,数据科学中的向量往往是高维的。每个维度表示某种特征。高维向量可以描述图像的颜色、形状、纹理等,或者文本的语法、语义等。
向量通常用一个有序的数字列表来表示。每个数字代表了某一维度的数值。在机器学习和数据科学中,我们经常处理高维向量(即向量的维度很高),这些高维向量可以表示非常复杂的数据。
例如:
(3, 4),其中 3 是 X 轴上的值,4 是 Y 轴上的值。(0.5, 1.2, -0.3, 0.7),这是一个 4 维向量。在自然语言处理中,单词、句子或段落常常被表示为向量,通过词嵌入模型(如 Word2Vec、BERT)将其转化为向量;在计算机视觉中,图像也可以通过卷积神经网络(CNN)提取出一个向量来表示图像的特征。
图像向量:
图像通常被转换成一个高维的向量。在计算机视觉中,深度学习模型(如 CNN)将图像通过网络进行处理,最后得到一个向量表示,向量的每个元素代表图像中的某种特征。这个向量可以用于图像的检索、分类、生成等任务。

文本向量:
文本数据(如单词、句子、文章)通过自然语言处理模型(如 Word2Vec、BERT 等)转换为向量表示。这些向量捕捉了文本的语义信息,使得相似语义的文本具有相似的向量表示。比如,“猫”与“狗”的词向量应该相近,“猫”与“计算机”的词向量应该相对远离。

音频向量:
音频文件也可以通过特征提取算法(如 MFCC)转换为向量。这个向量可以表示音频信号中的频率、音调等特征,用于语音识别、音频检索等任务。
向量有很多操作,以下是一些常见的操作:
1)向量加法:
向量加法是将两个向量的对应元素相加。例如:
向量 v1 = (1, 2) 和 v2 = (3, 4)
则 v1 + v2 = (1+3, 2+4) = (4, 6)。
2)向量点积(内积):
向量的点积是两个向量的对应元素相乘并求和。点积结果是一个标量(数字),常用于计算两个向量的相似度:
向量 v1 = (1, 2) 和 v2 = (3, 4)
则 v1 • v2 = 1*3 + 2*4 = 11。
3)向量的夹角:
向量之间的夹角可以通过点积来计算。若两个向量的夹角小,则它们更相似,通常在检索系统中用于衡量相似度。
4)向量的长度(模):
向量的长度表示该向量的大小,可以通过平方和开根号来计算:
向量 v = (x, y) 的长度为 √(x^2 + y^2)。
5)余弦相似度:
在高维空间中,余弦相似度是衡量两个向量相似度的常用指标。它通过计算两个向量的夹角余弦值来判断它们的相似性,值的范围从 -1 到 1,1 表示完全相同,-1 表示完全相反,0 表示没有相似度。公式:
cosine_similarity(v1, v2) = (v1 • v2) / (|v1| * |v2|)
其中 |v1| 和 |v2| 是向量的模。
明白了什么是向量,我们下一步就可以继续了解向量数据库的概念。
向量数据库是一种专门为高效存储、检索和管理高维向量数据(即向量嵌入)而设计的数据库系统。其核心价值并非简单的向量存储,而在于能够对海量向量执行高速近邻搜索(如相似度计算)等复杂运算,从而实现对非结构化数据(文本、图像、音频等)的语义级查询。
在人工智能技术栈中,向量数据库已成为关键组件,它为大型语言模型提供了持久的“记忆”与高效的检索能力,是实现检索增强生成、推荐系统、语义搜索等AI应用的基础设施。尽管常被称为“AI数据库”,但数据库技术正趋于融合,许多现代数据库已开始支持包括向量在内的多模型数据。
想象一下,你管理一个庞大的信息库:
传统数据库(如 MySQL)就像一个严谨的图书管理员,管理着一个结构清晰的档案室。
1)数据格式: 信息被整齐地记录在表格中,就像Excel一样。每一行是一条记录(如一个用户),每一列是一个属性(如姓名、年龄、ID)。数据是结构化的,格式固定。
2)工作方式: 当你提问时,你必须使用它能理解的精确语言(如SQL语句)。例如:“查找所有年龄大于30岁的用户”。
3)查询逻辑: 它根据你的指令,去表格里精确匹配符合条件的行。年龄“31”会被找到,但“三十多岁”或“中年”这种模糊概念它无法理解。它的核心是 “是与否”的精确过滤。
向量数据库则像一个理解含义的智能助手,管理着一个“思想空间”。
1)数据格式: 它不直接存储原始文本、图片或声音,而是先通过AI模型将这些内容转换成高维向量(即“语义指纹”)。这个向量是一长串数字(如768个浮点数),代表了该内容的核心含义和特征。一篇关于“苹果手机”的报道和一张“iPhone照片”的向量,在数学空间里会很接近。
2)工作方式: 当你提问(例如:“帮我找一些关于气候变化影响的科学文章”),它会先将你的问题也转换成向量。
3)查询逻辑: 然后,它在自己的“思想空间”里进行相似度搜索,找出那些向量最接近你问题向量的内容。它返回的不是精确匹配的关键词,而是含义最相关的结果。它的核心是 “像不像”的相似度计算。
通俗的来讲,我们可以把向量数据库想象成一个专门处理“思想指纹”的智能图书馆。普通数据库(比如Excel)存放的是规整的数字和文字,就像图书馆按书名或编号找书。而向量数据库存放的是一种“思想的指纹”——它用一串数字(向量)来代表一段文字、一张图片或一首歌的核心含义。当你提问时,它不会去机械地匹配关键词,而是去寻找和你的问题在“思想”上最相近的答案。
它最厉害的本事是“快”: 即使这个图书馆里有数十亿本“书”(向量),它也能在眨眼间找到和你想法最相似的几本。这正是当前AI应用(如智能聊天机器人、个性化推荐)急需的能力——让AI不仅能即时生成回答,还能瞬间从海量知识中精准找到最相关的内容来支撑它的回答,变得更渊博、更准确。
因此,向量数据库本质上就是 “为AI大脑配备的超高速记忆检索系统”。
对比维度 | 传统数据库 | 向量数据库 |
|---|---|---|
数据存储对象 | 结构化数据:数字、字符串、日期等,存放在行和列中。 | 非结构化数据的向量嵌入:文本、图像、音频、视频的“语义指纹”(高维数字数组)。 |
数据关系体现 | 显式关系:通过外键等明确建立表与表之间的联系。 | 隐式关系:通过向量在空间中的距离体现语义相似性。距离越近,含义越相似。 |
查询范式 | 精确查询:使用SQL进行条件匹配( | 相似性查询:进行“近似最近邻搜索”。找到与查询目标最相似的Top K个结果。答案是按相关性排序的、连续的。 |
核心索引技术 | B-树、哈希索引等,用于加速精确值查找。 | HNSW、IVF-PQ等近似最近邻索引,用于在高维空间中快速找到相似向量。 |
擅长解决的问题 | 事务处理、精准查询:电商订单、银行交易、用户信息管理等,需要绝对准确。 | 语义搜索、内容推荐、AI记忆:根据描述找图片、聊天机器人上下文检索、推荐相似产品等,需要理解意图和内容。 |
总而言之,传统数据库是“数据的仓库”,擅长处理“是什么”的问题;向量数据库是“意义的图谱”,擅长处理“像什么”的问题。 正是这种根本性的不同,使得向量数据库成为了处理现代海量非结构化数据、构建智能应用(如RAG)不可或缺的基础设施。
在AI大模型的应用架构中,向量数据库正从"辅助工具"演变为"核心记忆中枢",尤其在当前主流的RAG(检索增强生成) 技术栈中,它扮演着连接静态知识与动态对话的关键桥梁角色。
向量数据库在AI大模型中承担着三重核心角色:


简单来说,这个过程是这样的:当我们提问时,系统不会让AI直接凭空回答,而是会先将问题变成一段“数学指纹”(向量),并立即用这个指纹去专属资料库(向量数据库)里查找几份(TOP-K)最相关的原文资料;最后,AI会像一位严谨的发言人,严格基于刚刚查到的这几份资料来组织答案,从而确保回答的准确性和可靠性,有效避免“信口开河”。
RAG可以说在AI Agent生态中无处不在,主要有以下场景:
应用场景 | 传统LLM局限 | RAG + 向量数据库解决方案 |
|---|---|---|
智能客服 | 无法访问最新产品文档 | 检索最新FAQ、产品手册后生成回答 |
法律咨询 | 可能编造法律条文 | 精确检索相关法律法规后解释 |
学术研究 | 知识存在时间滞后 | 检索最新论文摘要后综述 |
医疗辅助 | 通用建议缺乏针对性 | 基于患者历史病历生成建议 |
企业知识库 | 不了解内部流程 | 检索公司内部文档后回答问题 |
向量数据库在AI大模型生态中的角色正在快速演进:

基础层:简单的向量存储与最近邻搜索
增强层:支持混合检索(向量+关键词+过滤)、重新排序
智能层:集成查询理解、多跳检索、自适应检索策略
4
生态层:与大模型框架(LangChain、LlamaIndex)深度集成
向量数据库已不仅仅是存储高维向量的"数据仓库",而是AI大模型的"外接大脑皮层"——它扩展了模型的记忆容量,增强了事实核查能力,并使其具备了领域专业知识。在RAG成为大模型应用标准架构的今天,向量数据库从可选组件转变为必选基础设施,成为平衡模型"创造力"与"准确性"的关键支点,支撑着更可信、更专业、更个性化的AI应用落地。
选择向量数据库,本质是平衡 控制力、成本、场景和复杂度。
1)数据是否必须留在自己的服务器上?
是 → 只能选 开源方案(如 Weaviate、Qdrant、Milvus)。
否 → 可以考虑 托管服务(如 Pinecone),以运维成本换取开发速度。
2)应用场景是什么?
边缘/IoT设备 → 唯一选择 ObjectBox(专为资源受限环境优化)。
快速原型验证 → 首选 Chroma 或 Pinecone(上手最快)。
大规模生产系统 → 进入主流开源方案角逐。
3)数据规模与性能要求如何?
极高吞吐、超大规模(>1亿向量) → Milvus 或 Vespa(分布式架构最成熟)。
高并发、低延迟 → Qdrant(Rust编写,性能出色)。
需要强混合搜索(向量+关键词) → Weaviate 或 Vespa(原生设计支持好)。
主流的向量数据库产品进行对比:
数据库 | 核心优势 | 最适合的场景 |
|---|---|---|
Milvus | 功能最全、生态最成熟的云原生开源方案,适合超大规模。 | 企业级AI平台、需要处理海量向量的复杂生产系统。 |
Weaviate | “数据库”思维,强在对象-向量联合存储、混合搜索和易用性。 | 需要结合结构化过滤的AI应用(如推荐系统、知识库)。 |
Qdrant | “搜索引擎”思维,Rust带来极致性能和资源效率,API简洁。 | 对延迟和资源消耗敏感的高性能搜索、实时推荐。 |
Pinecone | 完全托管、零运维,开发者体验最佳,开箱即用。 | 初创团队、需要快速验证业务假设、无专职运维。 |
Chroma | 轻量、简单,与AI开发栈(如LangChain)集成极深。 | AI应用原型开发、学习和轻量级项目。 |
1)筛除明显不匹配项
要边缘计算 → ObjectBox。
要完全免运维 → Pinecone。
要快速做Demo → Chroma。
2)在主流开源中聚焦
追求功能全面和社区规模 → 在 Milvus 和 Weaviate 中选。
追求极致性能和简洁性 → 重点评估 Qdrant。
3)用真实数据做概念验证
从2个最终候选开始,用自身业务数据的子集和典型查询请求进行测试。
关键指标:查询延迟(P99)、吞吐量、插入速度、内存/CPU占用。
不要只看公开报告,你的数据模式才是关键。
4)评估长期成本与锁定风险
开源方案:前期投入工程运维成本,但拥有控制权和退出自由。
托管方案:前期投入资金成本,换取速度,但需承担长期订阅费和供应商锁定。

一句话总结:初创验证用Pinecone/Chroma;重混合搜索选Weaviate;求极致性能看Qdrant;建大规模企业平台评Milvus;做边缘设备只有ObjectBox。最终务必用真实数据测试。
名称 | 是否开源 | 许可证 | 开发语言 | 简介 | 索引类型 | 是否支持ANN |
|---|---|---|---|---|---|---|
ObjectBox | 是 | Apache-2.0 | C++ (支持多语言API) | 适用于移动、IoT、嵌入式设备的边缘AI向量数据库 | HNSW | 是 |
Marqo AI | 是 | Apache-2.0 | Python | 基于张量的云原生商业开源搜索分析引擎 | HNSW | 未知 |
Weaviate | 是 | BSD | Assembly, C++, Go | 存储对象和向量的商业开源云原生向量数据库 | 支持CRUD的自定义HNSW PQ算法 | 是(支持CRUD的ANN算法) |
Chroma | 是 | Apache-2.0 | Python & TypeScript | 商业开源向量数据库 | 未明确 | 是 |
Qdrant | 是 | Apache-2.0 | Rust | 商业开源向量相似性搜索引擎和向量数据库 | HNSW (SQ & PQ) | 是 |
Milvus | 是 | Apache-2.0 | Go & Python | 云原生商业开源向量数据库 | ANNOY; HNSW; IVF_PQ; IVF_SQ等 | 是 |
Vespa | 是 | Apache-2.0 | Java & C++ | Yahoo!的商业开源向量数据库,支持向量搜索、词法搜索和结构化数据搜索 | 自定义HNSW(多向量混合HNSW-IF) | 是 |
Vald | 是 | Apache-2.0 | Go | 云原生开源分布式近似最近邻密集向量搜索引擎 | NGT | 是(NGT) |
Pinecone | 否 | 专有 | 未明确 | 完全托管的向量数据库,专注于语义搜索能力 | 专有 | 是(专有),加KNN(Faiss) |
在上文我们不断提到向量数据库在RAG中的重要性,那么下面我们就动手实现一个简单的RAG,来直观的感受向量数据库带来的作用。
为什么需要RAG?我们可以从“大模型幻觉”切入。
想象一下,你问一位天赋异禀但只接受过2023年初以前通用知识训练的“学者”一个问题。这位学者能结合已知模式,流畅、自信地生成一段回答。但问题在于:
1)他可能不知道你问题中涉及的、2023年后发生的具体新事件。
2)他可能不掌握你公司内部的私有数据或专业知识。
3)他有时会为了保持回答的“流畅合理”,而基于不完整的知识,编造听起来可信但实际错误的细节。
这就是当前大语言模型面临的核心困境:幻觉问题。
幻觉指模型生成看似合理但事实上不正确或无法验证的信息。

静态知识边界:大模型的训练数据是静态的、有截止日期的。它无法实时获知世界的新变化。
参数化知识的局限性:模型将海量知识压缩存储在神经网络的权重参数中。这个过程就像一场“有损压缩”,细节、精准数据(如具体数字、小众事实)容易丢失或模糊。
生成模式的固有倾向:模型的核心任务是“根据上文预测下一个最可能的词”。在缺乏明确依据时,为了延续合理的文本模式,它可能会“创作”内容,而非“引用”事实。
更大规模训练/微调:成本极高,无法解决知识实时性问题,且每次更新知识都需要重新训练或微调,不灵活。
提示工程:在提示词中要求模型“不要编造”,效果有限。这治标不治本,因为模型缺乏事实依据时,依然会陷入幻觉。
由于上述的原因,就催生了RAG的出现。
RAG的核心思想是不让模型仅依赖其内部压缩的、可能过时或不完整的记忆来作答,而是先为模型提供相关的、最新的、准确的事实依据,再让它基于这些依据来组织答案。
这就像让一位学者从“闭卷作文” 转变为“开卷考试”:

1)检索:当用户提问时,系统不会直接将问题丢给大模型。而是先将问题转换成向量,在向量数据库中搜索与之最相关的知识片段。这个知识库可以是你的产品文档、最新的市场报告、公司制度、法律条文等任何可靠、最新的数据源。
2)增强:将检索到的原文片段(作为事实依据)和用户的原始问题,一起组合成一个新的、增强版的提示词,发送给大模型。
3)生成:大模型基于收到的 “问题+权威依据” 来生成最终答案。它被明确要求:“请仅根据所提供的上下文信息来回答问题。”
解决知识过时问题:RAG的知识库可以随时更新。只需检索最新的文档即可,无需重新训练模型。
引入精准事实来源:模型不再依赖模糊的参数化记忆,而是基于检索到的、包含具体数字和细节的原文进行生成,极大减少了“捏造细节”的可能。
提供可验证性:系统可以保留检索到的原文出处。当答案存疑时,用户可以“溯源”,查看生成答案所依据的原始材料,建立了可信度。
降低专业领域错误:对于法律、医疗、金融等专业领域,通用大模型极易出错。RAG通过引入该领域的专业资料(如病历、法典、财报),将生成答案约束在专业框架内。

RAG通过在生成前引入一个可控制、可更新、可验证的“事实锚点”,巧妙地拆解了这个问题。它将大模型从“全知但不可靠的叙述者”,转变为“精准且富有文采的解说员”,使其答案既流畅,又可靠。这是当前在成本、效果和可行性上,平衡大模型能力与缺陷的最佳工程实践之一,也是其能在企业级场景落地的关键技术。
我们本着先了解再使用的原则先从概念入手,先带大家了解一下Milvus这个向量数据库产品,然后在使用Python代码结合Milvus实现RAG。
Milvus 是一款领先的云原生、开源向量数据库,专门为大规模AI 应用和向量相似性搜索而设计。它就像是 AI 时代的“数据搜索引擎”,能够高效存储和检索由文本、图像、音频、视频等非结构化数据转换而成的高维向量,帮助 AI 模型快速找到最相关的信息。
特性 | 说明 |
|---|---|
高性能检索 | 支持十亿级向量的毫秒级查询,满足实时 AI 应用需求 |
高可扩展性 | 云原生架构,支持水平扩展,轻松应对数据增长 |
丰富的索引 | 提供 10+ 种向量索引类型(HNSW、IVF、SCANN等),适配不同场景 |
多语言支持 | 提供 Python、Java、Go、Node.js 等主流语言 SDK |
支持动态数据 | 完整 CRUD 操作,支持实时插入、更新、删除 |
混合查询 | 支持向量 + 标量(结构化数据)的联合过滤查询 |
来自官网的核心架构图:

图片来自https://milvus.io/docs/zh/architecture_overview.md
简化版:

应用程序通过 Python 或 Java 等 SDK 发起一个查询时,请求首先经过访问层,在这里进行负载均衡、身份验证和初步的路由分配。随后,请求被递交给核心的协调层,这一层如同系统的大脑,其中的查询协调器负责分解和规划任务,数据管理和元数据管理组件则负责定位数据的位置与状态。
规划好的任务被下发给底层的工作节点:查询节点 负责核心的计算工作,执行高效的向量相似性搜索和标量条件过滤;而数据节点 则扮演存储库的角色,不仅安全地保存着海量的向量和标量数据,还管理着构建好的索引。最终,各节点的结果被协调层汇总,并沿原路径返回给应用程序,从而完成一次高效、可靠的向量检索。
Milvus的核心架构围绕集合(Collection)组织数据。
其中,每个集合包含多个实体(Entity),实体由字段(Field)构成,其中最关键的是向量(Vector)字段用于存储嵌入表示。
通过分区(Partition)实现数据逻辑划分,段(Segment)作为物理存储单元,系统采用相似性搜索(Similarity Search)基于度量方式(Metric)计算向量距离。
向量索引(Vector Index)加速检索过程,支持多种索引类型。
在集群部署中,数据节点(Data Node)负责存储,查询节点(Query Node)处理搜索,索引节点(Index Node)构建索引,代理(Proxy)协调客户端请求。
整个系统通过嵌入(Embedding)技术将原始数据转化为向量,并支持标量过滤(Scalar Filter)进行混合查询,实现高效的向量数据管理。

术语解释:
术语 | 说明 | 类比 |
|---|---|---|
Collection (集合) | 数据组织的最高层级,包含一组实体 | 数据库中的表 |
Entity (实体) | 集合中的一条记录,由多个字段组成 | 表中的一行 |
Field (字段) | 实体的属性,可以是向量或标量 | 表中的列 |
Vector (向量) | 高维数值数组,表示数据的特征 | 128/256/768维数组 |
Scalar (标量) | 传统数据类型(字符串、整数等) | 普通数据列 |
Partition (分区) | 集合的逻辑划分,便于数据管理 | 表的分区 |
Segment (段) | 物理存储单元,数据持久化的最小单位 | 数据文件块 |
维度 | Milvus | Pinecone | Weaviate |
|---|---|---|---|
开源协议 | Apache 2.0 | 商业闭源 | BSD 3 |
部署复杂度 | 中等 | 简单(托管) | 简单 |
最大规模 | 十亿+ 向量 | 百万+ 向量 | 亿级向量 |
混合查询 | ✅ 优秀 | ✅ 支持 | ✅ 优秀 |
成本模型 | 自托管成本低 | 按使用量付费 | 自托管/托管 |
首先我们先列举一下使用Milvus实现简单RAG的基本步骤:

然后下面我们来动手实现。
在上面的简单操作中我们就已经尝试了环境准备最重要的一步,就是先启动 Milvus 服务:
docker run -d --name milvus -p 19530:19530 milvusdb/milvus:v2.6.9然后对于我们的代码项目,最重要的两步就是安装Milvus客户端依赖和LLM API的调用,我们目前就选择DeepSeek作为我们的基础LLM能力。(具体调用DeepSeek API的代码我会统一上传到Github仓库中并分享给大家)
构建知识库主要有三步:
1)加载文档:读取并分割您的文本资料(PDF、TXT、网页等)
2)向量化处理:使用嵌入模型(如Sentence-BERT)将文本转为向量
3)存入Milvus:创建集合、定义字段,批量插入向量和原文
代码如下:
// 初始化知识库
func (r *RAGSystem) InitializeKnowledgeBase() error {
ctx := context.Background()
collectionName := r.config.CollectionName
// 检查集合是否存在
exists, err := r.milvusClient.HasCollection(ctx, collectionName)
if err != nil {
return err
}
// 如果集合已存在,先删除(为了演示)
if exists {
err = r.milvusClient.DropCollection(ctx, collectionName)
if err != nil {
return fmt.Errorf("删除集合失败: %w", err)
}
}
// 创建集合
err = r.milvusClient.CreateCollection(ctx, &entity.Schema{
CollectionName: collectionName,
Description: "RAG演示知识库",
Fields: []*entity.Field{
{
Name: "id",
DataType: entity.FieldTypeVarChar,
PrimaryKey: true,
AutoID: false,
TypeParams: map[string]string{
"max_length": "100",
},
},
{
Name: "title",
DataType: entity.FieldTypeVarChar,
TypeParams: map[string]string{
"max_length": "200",
},
},
{
Name: "content",
DataType: entity.FieldTypeVarChar,
TypeParams: map[string]string{
"max_length": "10000",
},
},
{
Name: "vector",
DataType: entity.FieldTypeFloatVector,
TypeParams: map[string]string{
"dim": "4", // 简化版,使用4维向量
},
},
},
EnableDynamicField: false,
}, 2) // 分片数为2
if err != nil {
return fmt.Errorf("创建集合失败: %w", err)
}
// 插入示例文档
err = r.insertSampleDocuments()
if err != nil {
return fmt.Errorf("插入文档失败: %w", err)
}
// 创建索引
index, err := entity.NewIndexHNSW(entity.L2, 8, 64)
if err != nil {
return fmt.Errorf("创建索引失败: %w", err)
}
err = r.milvusClient.CreateIndex(ctx, collectionName, "vector", index, false)
if err != nil {
return fmt.Errorf("创建向量索引失败: %w", err)
}
return nil
}
// 插入示例文档
func (r *RAGSystem) insertSampleDocuments() error {
ctx := context.Background()
// 示例文档数据(包含最新信息)
documents := []Document{
{
ID: "doc_001",
Title: "闫同学人物介绍",
Content: "闫同学,男,来自中国,26岁,天蝎座,是知名技术博主、摄影博主、技术爱好者,擅长写Go语言,喜欢打羽毛球。",
},
{
ID: "doc_002",
Title: "扯编程的淡公众号介绍",
Content: "扯编程的淡,科技领域知名微信公众号,由闫同学运营,内容多为技术博客,日常生活感想,截止2026年1月,已有粉丝2000+。",
},
}
// 为每个文档生成向量并插入
var ids []string
var titles []string
var contents []string
var vectors [][]float32
for _, doc := range documents {
// 生成简化向量(4维)
vector := r.generateSimpleVector(doc.Content)
ids = append(ids, doc.ID)
titles = append(titles, doc.Title)
contents = append(contents, doc.Content)
vectors = append(vectors, vector)
}
// 插入数据
idColumn := entity.NewColumnVarChar("id", ids)
titleColumn := entity.NewColumnVarChar("title", titles)
contentColumn := entity.NewColumnVarChar("content", contents)
vectorColumn := entity.NewColumnFloatVector("vector", 4, vectors)
_, err := r.milvusClient.Insert(ctx, r.config.CollectionName, "", idColumn, titleColumn, contentColumn, vectorColumn)
if err != nil {
return err
}
fmt.Printf("✅ 插入了 %d 个文档到知识库\n", len(documents))
return nil
}func (r *RAGSystem) SearchDocuments(query string, topK int) ([]SearchResult, error) {
ctx := context.Background()
collectionName := r.config.CollectionName
// 加载集合
err := r.milvusClient.LoadCollection(ctx, collectionName, false)
if err != nil {
return nil, fmt.Errorf("加载集合失败: %w", err)
}
// 生成查询向量
queryVector := r.generateSimpleVector(query)
// 搜索参数
sp, _ := entity.NewIndexHNSWSearchParam(32)
// 执行搜索 - 根据最新SDK修正
searchResults, err := r.milvusClient.Search(
ctx,
collectionName,
nil, // 分区列表
"", // 表达式
[]string{"title", "content"}, // 输出字段
[]entity.Vector{entity.FloatVector(queryVector)}, // 查询向量
"vector", // 向量字段名
entity.L2, // 距离度量
topK, // topK
sp, // 搜索参数
)
if err != nil {
return nil, fmt.Errorf("搜索失败: %w", err)
}
var results []SearchResult
// 检查是否有结果
if len(searchResults) == 0 {
return results, nil
}
// 获取第一个查询的结果(因为我们只查询了一个向量)
if len(searchResults) > 0 {
searchResult := searchResults[0]
// 获取ID列
idCol, ok := searchResult.IDs.(*entity.ColumnVarChar)
if !ok {
return results, fmt.Errorf("ID列类型错误")
}
// 获取分数列和字段
scores := searchResult.Scores
fields := searchResult.Fields
// 遍历所有结果
for i := 0; i < searchResult.ResultCount; i++ {
// 获取ID、分数
id := idCol.Data()[i]
score := float64(1.0 / (1.0 + scores[i]))
// 获取标题和内容
var title, content string
for _, field := range fields {
switch field.Name() {
case "title":
if col, ok := field.(*entity.ColumnVarChar); ok {
title = col.Data()[i]
}
case "content":
if col, ok := field.(*entity.ColumnVarChar); ok {
content = col.Data()[i]
}
}
}
// 添加到结果列表
results = append(results, SearchResult{
Title: title,
Content: content,
Score: float32(score),
})
// 调试输出
fmt.Printf("找到文档: ID=%s, Title=%s, Score=%.2f\n", id, title, score)
}
}
return results, nil
}func (r *RAGSystem) GetRAGAnswer(question string) (string, float64, []SearchResult, error) {
start := time.Now()
// 1. 检索相关文档
results, err := r.SearchDocuments(question, 3)
if err != nil {
return "", 0, nil, err
}
// 2. 构建上下文
var contextBuilder strings.Builder
contextBuilder.WriteString("以下是相关文档信息:\n\n")
for i, result := range results {
contextBuilder.WriteString(fmt.Sprintf("文档%d: %s\n", i+1, result.Title))
contextBuilder.WriteString(fmt.Sprintf("内容: %s\n\n", result.Content))
}
contextStr := contextBuilder.String()
// 3. 调用DeepSeek生成答案
ctx := context.Background()
resp, err := r.openAIClient.CreateChatCompletion(ctx, openai.ChatCompletionRequest{
Model: r.config.DeepSeekModel,
Messages: []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleSystem,
Content: "你是一个严谨的AI助手,必须严格基于提供的上下文信息回答问题。如果上下文信息不足,请如实告知。不要编造上下文之外的信息。",
},
{
Role: openai.ChatMessageRoleUser,
Content: fmt.Sprintf("上下文信息:\n%s\n\n问题:%s\n\n请基于上述上下文信息回答问题:", contextStr, question),
},
},
Temperature: 0.1,
MaxTokens: 500,
})
elapsed := time.Since(start).Seconds()
if err != nil {
return "", elapsed, results, err
}
if len(resp.Choices) == 0 {
return "", elapsed, results, fmt.Errorf("未收到回答")
}
return resp.Choices[0].Message.Content, elapsed, results, nil
}在这个案例中由于时间关系我们并没有涉及到交互界面,但是在正常情况下一个完整的项目需要有知识库的导入和导出等等。
我们之所以说RAG可以增强LLM回答的准确率,就是由于向量数据库可以将我们的外部数据进行存储,等到查询时在进行检索后返回,所以我们来对比下询问LLM一些特殊问题时候RAG带来的效果,我们先看数据流转图:

当我们输入问题后,系统并行执行两种处理方式。
1)纯DeepSeek路径直接调用API基于训练数据生成答案;
2)RAG路径则先将问题向量化,通过Milvus向量数据库检索相关文档,构建上下文后调用DeepSeek API生成增强答案并附带参考来源。
在用上面的知识库输入后我们可以提问两个问题:
"闫同学是谁?"
"介绍一下扯编程的淡公众号"然后我们执行RAG流程(执行之前要调通Milvus和LLM API):
问题1:"闫同学是谁?"
🔍 获取纯DeepSeek回答:
⏱️ 响应时间: 6.71秒
💬 回答: “闫同学”这个称呼比较常见,通常用于泛指一位姓“闫”的学生,没有特指某一位具体人物。如果您指的是某个特定领域的知名人物、网络热点事件中的人物,或者您身边的具体个人,请提供更多背景信息,以便我为您提供更准确的解答。
例如:
- 如果您指的是**学术或公众人物**(如科学家、作家等),可以补充其全名或领域。
- 如果您指的是**网络上的热点人物**(如社交媒体上的博主、新闻事件当事人等),可以描述相关事件。
- 如果您指的是**身边的同学或朋友**,建议直接联系对方或相关人士了解。
期待您的补充信息,我将尽力帮助您!
🔍 获取RAG增强回答:
找到文档: ID=doc_002, Title=扯编程的淡公众号介绍, Score=1.00
找到文档: ID=doc_001, Title=闫同学人物介绍, Score=1.00
⏱️ 响应时间: 6.04秒
💬 回答: 闫同学是来自中国的26岁男性,天蝎座,是一名知名技术博主和摄影博主,也是技术爱好者,擅长Go语言,喜欢打羽毛球。他运营着科技领域知名微信公众号“扯编程的淡”,该公众号内容以技术博客和日常生活感想为主,截至2026年1月已有2000多名粉丝。
📄 检索到的相关文档:
1. [相似度: 1.00] 扯编程的淡公众号介绍
内容: 扯编程的淡,科技领域知名微信公众号,由闫同学运营,内容多为技术博客�...
2. [相似度: 1.00] 闫同学人物介绍
📊 对比分析:
- 时间开销: RAG比纯DeepSeek慢 -0.67秒
- 信息质量: RAG基于 2 个相关文档生成问题2:"介绍一下扯编程的淡公众号"
🔍 获取纯DeepSeek回答:
⏱️ 响应时间: 14.38秒
💬 回答: “扯编程的淡”是一个以**幽默、轻松、生活化**的方式分享编程知识、技术观点和行业见闻的微信公众号。其内容风格独特,通常不局限于枯燥的技术教程,而是将编程与生活、职场、文化等结合,用通俗易懂的语言“扯淡”,让读者在轻松的氛围中获取信息或思考技术问题。
### 主要特点:
1. **幽默调侃的风格**
文章常以段子、吐槽或网络流行语开头,用轻松的语言讨论技术话题,比如用“程序员脱发”“996”等梗引发共鸣。
2. **贴近实际场景**
内容多围绕程序员日常(如面试、加班、技术选型)、行业热点(如AI发展、大厂动态)或学习心得,接地气且实用。
3. **非典型技术分享**
可能涉及技术冷知识、工具推荐、职业规划,甚至用编程思维解读生活问题(如“用算法找对象”“Debug人生”)。
4. **互动性强**
标题和内容常带有互动性,鼓励读者留言讨论,形成社区氛围。
### 适合人群:
- 编程初学者或学生,想以轻松方式入门技术。
- 在职程序员,希望缓解压力、寻找共鸣。
- 对科技文化感兴趣的非技术读者。
### 注意事项:
- 内容可能不够系统,适合碎片化阅读而非深度学习。
- 幽默风格可能掩盖技术深度,需结合其他资源补充学习。
若你对该公众号感兴趣,可以在微信搜索名称关注。类似风格的公众号还有“程序员小灰”“码农翻身”等,均以故事化、趣味化的方式讲解技术。
🔍 获取RAG增强回答:
找到文档: ID=doc_002, Title=扯编程的淡公众号介绍, Score=1.00
找到文档: ID=doc_001, Title=闫同学人物介绍, Score=1.00
⏱️ 响应时间: 5.03秒
💬 回答: 根据提供的上下文信息,“扯编程的淡”是一个科技领域的知名微信公众号,由闫同学运营。该公众号主要发布技术博客和日常生活感想。截至2026年1月,其粉丝数量已超过2000人。
📄 检索到的相关文档:
1. [相似度: 1.00] 扯编程的淡公众号介绍
内容: 扯编程的淡,科技领域知名微信公众号,由闫同学运营,内容多为技术博客�...
2. [相似度: 1.00] 闫同学人物介绍
📊 对比分析:
- 时间开销: RAG比纯DeepSeek慢 -9.35秒
- 信息质量: RAG基于 2 个相关文档生成从上面的测试结果我们不难看出,使用RAG能够很大程度上的提升我们LLM回答的准确性。但前提是需要使用向量数据库为基础构建一个合理的知识库。
代码地址:
从向量这一基础的数学概念,到它成为机器理解世界的“语义指纹”;从传统数据库对结构化数据的精确管理,到向量数据库对非结构化信息的语义化存储与检索——我们正见证着数据处理范式的一次根本性转移。
向量数据库并非仅仅是另一种存储工具。它通过将文本、图像等一切数据映射为高维空间中的点,并基于“距离”来衡量其语义相似性,从而解决了传统数据库无法应对的核心挑战:理解内容的意义。它因此成为AI大模型不可或缺的“长期记忆体”和“事实校验器”,通过RAG等技术,将大模型的强大生成能力与精准的外部知识结合,有效缓解了“幻觉”问题。
总而言之,向量数据库正在底层重塑我们组织、检索和利用知识的方式。它不仅是存储向量的容器,更是连接数据世界与智能世界的桥梁,是将海量非结构化数据转化为可用智能的核心基础设施。随着AI的持续演进,向量数据库作为其坚实的数据根基,必将扮演越来越重要的角色,驱动更准确、更可信、更智能的应用未来。
https://www.youtube.com/watch?v=uQcBwN1PEyI
https://projector.tensorflow.org/
https://zhuanlan.zhihu.com/p/265849139
https://lakefs.io/blog/best-vector-databases/
https://www.datacamp.com/blog/the-top-5-vector-databases
https://objectbox.io/vector-database/
https://aws.amazon.com/what-is/retrieval-augmented-generation/
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。