当前位置: 首页 > news >正文

[初阶--使用milvus向量数据库实现简单RAG]

什么是向量数据库

向量是数据在高维空间中的数学表示。在这个空间中,每个维度对应数据的一个特征,维度的数量从几百到几万不等,具体取决于所表示数据的复杂性。向量在该空间中的位置代表其特征。单词、短语或整篇文档,以及图像、音频和其他类型的数据,都可以被向量化
向量数据库(Vector database)、向量存储或向量搜索引擎是一种能够存储向量(固定长度的数值列表)及其他数据项的数据库。向量数据库通常实现一种或多种近似最近邻(Approximate Nearest Neighbor,ANN)算法,使用户可以使用查询向量搜索数据库,以检索最匹配的数据库记录(来自维基百科)

为什么选择milvus

官网
Milvus 是一款云原生向量数据库,它具备高可用、高性能、易拓展的特点,用于海量向量数据的实时召回。

Milvus 提供强大的数据建模功能,使您能够将非结构化或多模式数据组织成结构化的 Collections。它支持多种数据类型,适用于不同的属性模型,包括常见的数字和字符类型、各种向量类型、数组、集合和 JSON,为您节省了维护多个数据库系统的精力。
在这里插入图片描述

milvus单机部署

milvus官方文档

linux部署

curl -sfL https://raw.githubusercontent.com/milvus-io/milvus/master/scripts/standalone_embed.sh -o standalone_embed.shbash standalone_embed.sh start

windows部署

前提条件

安装 Docker Desktop。

安装 Windows Subsystem for Linux 2 (WSL 2)。

安装 Python 3.8+。

1.在管理员模式下右击并选择以管理员身份运行,打开 Docker Desktop。

2.下载安装脚本并将其保存为standalone.bat 。

Invoke-WebRequest https://raw.githubusercontent.com/milvus-io/milvus/refs/heads/master/scripts/standalone_embed.bat -OutFile standalone.bat

3.运行下载的脚本,将 Milvus 作为 Docker 容器启动。

standalone.bat start
Wait for Milvus starting...
Start successfully.
To change the default Milvus configuration, edit user.yaml and restart the service.

使用python连接milvus

安装pymilvus

pip install pymilvus

连接milvus

from pymilvus import MilvusClientclient = MilvusClient(uri="http://localhost:19530",token="root:Milvus"
)

milvus数据库操作

# 删除数据库
client.drop_database(db_name="teachRag"
)
# 创建数据库
client.create_database(db_name="teachRag"
)
# 使用数据库
client.use_database(db_name="teachRag"
)

milvus创建合集(Collection)

Collection可以理解为关系型数据库里面的表
Collection 是一个二维表,具有固定的列和变化的行。每列代表一个字段,每行代表一个实体。
在这里插入图片描述

client.create_collection(collection_name="teach",dimension=1024,
)

生成文本向量

RAG的构建流程如下:
在这里插入图片描述
这其中最重要的就是文本向量化的过程

async def get_embedding(text: str):completion = embedding_client.embeddings.create(model="text-embedding-v3",input=text,dimensions=1024,encoding_format="float")return completion.data[0].embedding

使用的模型是通义的text-embedding-v3,维度是1024
传入的参数是字符串类型的text

插入向量数据

插入数据预览

西游记现代文版 第一章第一回1 化猴出世有一首诗说:“当我们的世界还是一片混沌的时候,天地之间一片混乱,荒芜的世界中没有任何人的踪影。但是自从盘古开天辟地之后,世界的清气和浊气开始分离,变得容易分辨。世间万物逐渐出现,并且都本性善良淳朴。你如果想知道天地众生运行的规律,就不得不细细品味这部西游记。”世界的万事万物是如何运行的呢?如果我们把十二万九千六百年叫做一个“元”。把一个“元”按照十二地支分成十二份:“子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥”,那么每一份都足足有一万八百年。而且在同一天的不同时间段里,不同的事物也有各自运行的规律:在晚上二十三点到第二天凌晨一点的时候,天地之间的阳气开始上升,新的一天就开始了;等到了凌晨一点到三点的时候,公鸡就会鸣叫;在凌晨三点到五点的时候,天地仍然是一片黑暗;但是到了凌晨五点到七点的时候,太阳就出来了;在上午七点到九点,人们吃完了早餐;在上午九点到十一点,人们忙于工作;在上午十一点到下午一点的时候,太阳刚好运行到天空的正中间;到了下午一点到三点的时候,太阳就开始偏向西边;而到了下午三点到五点,天色渐渐变晚,等到了下午五点到七点的时候,太阳就落山了。下午七点到九点慢慢进入夜晚,到了九点至十一点,人们就开始休息。在一个“元”的第十一份时间即将结束的时候,天地之间就会变得昏昏蒙蒙,大多数生灵都会灭绝。再过五千四百年,整个世界会变得一片黑暗,所有的生命和事物都会消失,整个世界都会变成一片混沌。再过五千四百年,整个世界才会慢慢变得有序。随着时间的推移,才慢慢有了日月星辰,日月星辰也被叫做“四象”。再后来,世界慢慢演化出了水、火、山、石、土。水、火、山、石、土被称作“五形”。整个世界演化的过程中,清气上升,浊气下降,万事万物逐渐形成,人类和各种动植物也就慢慢诞生了。盘古开天辟地之后,三皇和五帝确定了人间的各种习俗和秩序。整个世界分为四个大洲,分别是东胜神洲、西牛贺洲、南赡部洲和北俱芦洲。东胜神州的海边有一个国家,叫作“傲来国”。傲来国附近的大海中有一座仙山,被叫作“花果山”。花果山是整个世界的祖脉,在这个世界刚刚形成的时候就已经存在于天地之间了。真是一座好山!有一首词赋对花果山作了描述:“势镇汪洋,威宁瑶海。势镇汪洋,潮涌银山鱼入穴;威宁瑶海,波翻雪浪蜃离渊。木火方隅高积上,东海之处耸崇巅。丹崖怪石,削壁奇峰。丹崖上,彩凤双鸣;削壁前,麒麟独卧。峰头时听锦鸡鸣,石窟每观龙出入。林中有寿鹿仙狐,树上有灵禽玄鹤。瑶草奇花不谢,青松翠柏长春。仙桃常结果,修竹每留云。一条涧壑藤萝密,四面原堤草色新。正是百川会处擎天柱,万劫无移大地根。”花果山的山顶有一块仙石,这块石头高三丈六尺五寸,周长二丈四尺。三丈六尺五寸高,刚好对应三百六十五天;周长二丈四尺,恰好呼应二十四节气。石头上面有九个窍和八个孔,按照九宫八卦布局。这块石头的四周没有任何树木遮阴,但是边上却有灵芝灵草相伴。原来是自从天地开辟以来,这块石头每天都吸收着日月精华,时间一长,就慢慢通灵了。石头里面孕育着一个生命。有一天,那块石头突然裂开,产出一个圆球状的石头。被风一吹,就变成了一个猴子,五官和四肢都齐全。这个石猴很快就学会了爬和走,后来石猴的两只眼睛突然射出两道刺目的金光,一直冲到了天上的凌霄宝殿上。玉皇大帝正和一群神仙们在一块议事,突然看见有两道金光闪现,于是玉皇大帝连忙命令千里眼和顺风耳两位天将打开南天门察看。两位天将出了南天门,把花果山的一切看得真真切切,听得明明白白。然后他们立刻回到凌霄宝殿向玉皇大帝汇报:“启禀玉帝,臣等奉命察看和监听了那两道金光的来源,发现金光来自于东胜神洲的傲来国,那傲来国的花果山上有一块天生地养的仙石,不久前产了一个石卵,那石卵被风一吹就变成了一只石猴。那两道金光就是从那只石猴的两只眼睛里射出来的。后来这只石猴喝了点水,金光就收敛了。玉皇大帝仁慈地说:“下界的这只石猴是天地的精华所孕育出来的,难怪出生的时候有这么大的动静。”那只石猴天生就有灵智,外表也和其它猿猴一般无二,平时在花果山上跳跃行走,饿了就吃花果山上的果实,渴了就喝山间的泉水,平时与其它猿猴相伴,白天在山间游乐,晚上在石崖的下面休息,非常逍遥自在。俗话说“山中无甲子,寒尽不知年”,山中的快活日子很容易让人忘记时间的流逝。

使用fastapi进行构建
这里我使用的文档是从我服务器拉下来的,所以是url
大家自己在插入的时候可以从本地加载

@app.get("/text_embedding")
async def text_embedding_and_store(file: str = Query(...)):try:if file.startswith("http://") or file.startswith("https://"):response = requests.get(file)response.raise_for_status()with tempfile.NamedTemporaryFile(delete=False, suffix=".txt") as temp_file:temp_file.write(response.content)temp_file_path = temp_file.nametry:loader = TextLoader(temp_file_path, encoding="utf-8")documents = loader.load()text_splitter = RecursiveCharacterTextSplitter(separators=["\n\n", "\n", ".", " "],chunk_size=100,chunk_overlap=50)split_docs = text_splitter.split_documents(documents)texts = [doc.page_content for doc in split_docs]data = []for i, text in enumerate(tqdm(texts, desc="Creating Embeddings")):embedding = await get_embedding(text)print(f"嵌入向量 {i}: {embedding[:10]}...")data.append({"id": i, "vector": embedding, "text": text})print(f"文本块 {i}: {text[:50]}...")milvus_client.insert(collection_name=collection_name, data=data)return {"message": "插入成功", "inserted_count": len(data)}finally:if os.path.exists(temp_file_path):os.unlink(temp_file_path)else:raise ValueError("文件必须是 HTTP/HTTPS URL")except requests.RequestException as e:raise HTTPException(status_code=400, detail=f"无法下载文件: {str(e)}")except ValueError as e:raise HTTPException(status_code=400, detail=str(e))except Exception as e:raise HTTPException(status_code=500, detail=f"处理文件时出错: {str(e)}")

访问接口测试

http://localhost:8000/text_embedding?file=http://<公网ip>:91/usr/local/nginx/files/teach/test.txt

测试结果:

{"message": "插入成功","inserted_count": 10
}

相似度搜索

@app.get("/query")
async def query(question: str = Query(...)):try:question_embedding = await get_embedding(question)search_res = milvus_client.search(collection_name=collection_name,data=[question_embedding],limit=3,search_params={"metric_type": "IP","params": {}},output_fields=["text"])# 转换为可序列化的格式serialized_results = [{"id": hit["id"],"distance": hit["distance"],"text": hit["entity"]["text"]}for hits in search_resfor hit in hits]print(f"序列化搜索结果: {serialized_results}")return {"results": serialized_results}except Exception as e:raise HTTPException(status_code=500, detail=f"搜索失败: {str(e)}")

测试接口

http://localhost:8000/query?question=什么东西突然裂开

测试结果

{"results": [{"id": 7,"distance": 0.5229408740997314,"text": "\n有一天,那块石头突然裂开,产出一个圆球状的石头。被风一吹,就变成了一个猴子,五官和四肢都齐全。这个石猴很快就学会了爬和走,后来石猴的两只眼睛突然射出两道刺目的金光,一直冲到了天上的凌霄宝殿上。玉皇大帝正和一群神仙们在一块议事,突然看见有两道金光闪现,于是玉皇大帝连忙命令千里眼和顺风耳两位天将打开南天门察看。"},{"id": 6,"distance": 0.4799390435218811,"text": "\n花果山的山顶有一块仙石,这块石头高三丈六尺五寸,周长二丈四尺。三丈六尺五寸高,刚好对应三百六十五天;周长二丈四尺,恰好呼应二十四节气。石头上面有九个窍和八个孔,按照九宫八卦布局。这块石头的四周没有任何树木遮阴,但是边上却有灵芝灵草相伴。原来是自从天地开辟以来,这块石头每天都吸收着日月精华,时间一长,就慢慢通灵了。石头里面孕育着一个生命。"},{"id": 3,"distance": 0.44567835330963135,"text": "\n在一个“元”的第十一份时间即将结束的时候,天地之间就会变得昏昏蒙蒙,大多数生灵都会灭绝。再过五千四百年,整个世界会变得一片黑暗,所有的生命和事物都会消失,整个世界都会变成一片混沌。再过五千四百年,整个世界才会慢慢变得有序。随着时间的推移,才慢慢有了日月星辰,日月星辰也被叫做“四象”。再后来,世界慢慢演化出了水、火、山、石、土。水、火、山、石、土被称作“五形”。整个世界演化的过程中,清气上升,浊气下降,万事万物逐渐形成,人类和各种动植物也就慢慢诞生了。"}]
}

可以看到查询的结果是非常精确的

相关文章:

  • 云曦25年春季期中考核复现
  • 滚珠导轨:重构精密仪器传动架构,开启微纳世界
  • MacBookPro上macOS安装第三方应用报错解决方案:遇到:“无法打开“XXX”,因为Apple无法检查其是否包含恶意软件 问题如何解决
  • python学习打卡day33
  • Mysql刷题之正则表达式专题
  • MA网络笔记
  • leetcode2261. 含最多 K 个可整除元素的子数组-medium
  • 关于Python编程语言的详细介绍,结合其核心特性、应用领域和发展现状,以结构化方式呈现:
  • 网络编程 之 从BIO到 NIO加多线程高性能网络编程实战
  • JMeter 教程:响应断言
  • 融合蛋白质语言模型和图像修复模型,麻省理工与哈佛联手提出PUPS ,实现单细胞级蛋白质定位
  • recurrent neural network(rnn)
  • 记录Pycharm断点调试的一个BUG
  • Java的列表、集合、数组的添加一个元素各自用的什么方法?
  • 蜂鸣器模块
  • 7.2.顺序查找
  • 【KWDB 2025 创作者计划】_KWDB时序数据库特性及跨模查询
  • 把银河装进镜头里!动态星轨素材使用实录
  • iisARR负均衡
  • indicator-sysmonitor 在Ubuntu 右上角实时显示CPU/MEM/NET的利用率
  • 网站注册系统用什么做/交换友情链接的意义是什么
  • 石景山广州网站建设/百度推广官网
  • 奉节做网站/最吸引人的营销广告文案
  • 找别人做网站的注意事项/企业品牌推广
  • 毕设做网站是不是太low/优化大师win7官方免费下载
  • 帮客户做网站平台犯法吗/百度云网盘网页版