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

Milvus 到 TiDB 向量迁移实践

作者: caiyfc 原文来源: https://tidb.net/blog/e0035e5e

一、背景

我最近在研究使用向量数据库搭建RAG应用,并且已经使用 Milvus、Llama 3、Ollama、LangChain 搭建完成。最近通过活动获取了 TiDB Cloud Serverless 使用配额,于是打算把 Milvus 已完成的向量数据给迁移到 TiDB Cloud Serverless 中。

经过查阅相关资料,我发现向量数据迁移的工具还不支持从 Milvus 迁移到 TiDB。那就无法迁移了吗?不,虽然现有的工具不能迁移,但是我可以手动迁移。于是就有了这篇文章。

TiDB Cloud Serverless 活动地址: 【TiDB 社区福利】贡献开源代码的开发者看过来!最高可获得超 14,000 元的 TiDB Cloud Serverless 云资源额度

搭建RAG应用方法: 手把手系列 | 使用Milvus、Llama 3、Ollama、LangChain本地设置RAG应用

二、迁移方案

要做数据迁移,首先需要确定迁移方案。最简单的迁移就两个步骤:数据从源库导出、数据导入到目标库,这样就完成了数据迁移。

但是这次就不同了。RAG应用使用了 LangChain,根据调研,LangChain 在 Milvus 和在 TiDB 中创建的结构是不同的。

在 Milvus 中的 collection 名称是:LangChainCollection,结构是: image-20241016162111628

但是在 TiDB 中的table 名称是:langchain_vector,结构是:

image-20241016162229794

在 LangChain 的文档中也有说明: image-20241016162326669

那么这次数据迁移就需要多增加两个步骤了:数据整理、表结构调整。而这两个又是异构数据库,所以导出的数据格式选择较为通用的csv。

整体方案如下:

image-20241016163112988

三、Milvus 数据导出

根据 Milvus 的官方文档,没找到能直接把数据导出成 csv 文件的工具,但是我可以用 python 的 SDK 来把数据读取出来,然后存成 csv 文件。

import csv
from pymilvus import connections, Collection
​
# 连接到 Milvus
connections.connect("default", host="10.3.xx.xx", port="19530")
​
# 获取 Collection
collection = Collection("LangChainCollection")
​# 分页查询所有数据
limit = 1000
offset = 0
all_results = []
​
while True:# 传递 expr 参数,使用一个简单的条件查询所有数据results = collection.query(expr="", output_fields=["pk", "source", "page", "text", "vector"], limit=limit, offset=offset)if not results:breakall_results.extend(results)offset += limit
​
# 打开 CSV 文件,准备写入数据
with open("milvus_data.csv", "w", newline="", encoding='utf-8') as csvfile:# 定义 CSV 列名fieldnames = ["pk", "source", "page", "text", "vector"]writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
​# 写入表头writer.writeheader()
​# 写入每一条记录for result in all_results:# 解析 JSON 数据,提取字段vector_str = ','.join(map(str, result.get("vector", [])))  # 将向量数组转换为字符串writer.writerow({"pk": result.get("pk"),          # 获取主键"source": result.get("source"),  # 获取源文件"page": result.get("page"),      # 获取页码"text": result.get("text"),      # 获取文本"vector": vector_str             # 写入向量数据})
​
print(f"Total records written to CSV: {len(all_results)}")

导出的 csv 文件数据的格式为:

image-20241016165426794

四、数据整理、表结构整理

我用少量测试数据转换成向量,使用 LangChain 加载到 TiDB Cloud 中了。这样就得到了 TiDB Cloud 中的数据结构及数据格式了。

表结构为:

CREATE TABLE `langchain_vector` (
`id` varchar(36) NOT NULL,
`embedding` vector(768) NOT NULL COMMENT 'hnsw(distance=cosine)',
`document` text DEFAULT NULL,
`meta` json DEFAULT NULL,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin

可以在 TiDB Cloud 中直接创建该表。

导出成 csv 的数据格式为(省略部分内容):

"id","embedding","document","meta","create_time","update_time"
"00a2ad02-eff5-4649-947f-820db0d24afa","[-0.08534411,0.048610855,0.018906716,0.023978366,***********-0.023846595,0.06352842,0.07482053]","— 22 —   (七)移交利用共用部位、共用设施设备经营的相关资料、\n物业服务费用和公共水电分摊费用交纳记录等资料;   (八)法律、法规员会和物业服务企业。","{\"page\": 21, \"source\": \"./湖北省物业服务和管理条例.pdf\"}","2024-10-15 08:18:16","2024-10-15 08:18:16"
​

已知 Milvus 导出的 csv 的数文件,根据对应关系,其实就是embedding 对应 vector,document 对应 text,meta 对应 page加source。这样逻辑就清晰了。根据对应关系编写数据整理的脚本:

import pandas as pd
import json
from uuid import uuid4
from datetime import datetime
​
# 读取CSV文件
input_csv = 'milvus_data.csv'  # 替换为你的CSV文件名
df = pd.read_csv(input_csv)
​
# 创建新的DataFrame
output_data = []
​
for _, row in df.iterrows():# 提取需要的字段id_value = str(uuid4())  # 生成唯一IDembedding = f"[{','.join(row['vector'].split(','))}]"  # 将vector转换为嵌入格式document = row['text']# 生成meta信息meta_dict = {"page": row['page'], "source": row['source']}meta = json.dumps(meta_dict, ensure_ascii=False)  # 首先生成正常的JSON# meta = meta.replace('"', '\\"')  # 转义双引号
​create_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")update_time = create_time  # 更新时同样的时间
​# 添加到输出数据output_data.append({"id": id_value,"embedding": embedding,"document": document,"meta": meta,"create_time": create_time,"update_time": update_time})
​
# 转换为DataFrame
output_df = pd.DataFrame(output_data)
​
# 保存为CSV文件
output_csv = 'output.csv'  # 输出文件名
output_df.to_csv(output_csv, index=False, quoting=1)  # quoting=1用于确保字符串加引号
​
print(f"转换完成,已保存为 {output_csv}")
​

数据整理完成后,就可以导入数据到 TiDB Cloud 中了。

五、导入数据到 TiDB Cloud

TiDB Cloud 提供三种导入方式:

image-20241016171123690

本次使用本地上传的方式。

小于 50MiB 的 csv文件可以使用第一种上传本地文件的方式,如果文件大于 50 MiB,可以使用脚本将文件拆分为多个较小的文件再上传:

image.png

上传文件后,选择已经创建好的库和表,点击 define table

image-20241016171658449

调整好对应关系,点击 start import 即可

image-20241016171812870

更多的导入方式可以查看文档: Migration and Import Overview

六、验证结果

数据成功导入之后,就需要开始验证数据了。于是我修改了 RAG应用的代码,分别从 Milvus 和 TiDB 中读取向量数据,使用同一个问题,来让大模型返回答案,查看答案是否类似。

from langchain_community.llms import Ollama
from langchain.callbacks.manager import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
from langchain import hub
from langchain.chains import RetrievalQA
from langchain.vectorstores.milvus import Milvus
from langchain_community.embeddings.jina import JinaEmbeddings
from langchain_community.vectorstores import TiDBVectorStore
import os
​
llm = Ollama(
model="llama3",
callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]
),
stop=["<|eot_id|>"],
)
​
​
embeddings = JinaEmbeddings(jina_api_key="xxxx", model_name="jina-embeddings-v2-base-zh")
​
vector_store_milvus = Milvus(embedding_function=embeddings,connection_args={"uri": "http://10.3.xx.xx:19530"},
)
​
​
TIDB_CONN_STR="mysql+pymysql://xxxx.root:password@host:4000/test?ssl_ca=/Downloads/isrgrootx1.pem&ssl_verify_cert=true&ssl_verify_identity=true"
vector_store_tidb = TiDBVectorStore(connection_string=TIDB_CONN_STR,embedding_function=embeddings,table_name="langchain_vector",
)
​
​
os.environ["LANGCHAIN_API_KEY"] = "xxxx"
query = input("\nQuery: ")
prompt = hub.pull("rlm/rag-prompt")   
​
qa_chain = RetrievalQA.from_chain_type(llm, retriever=vector_store_milvus.as_retriever(), chain_type_kwargs={"prompt": prompt}
)
print("milvus")
result = qa_chain({"query": query})
​
print("\n--------------------------------------")
print("tidb")
qa_chain = RetrievalQA.from_chain_type(llm, retriever=vector_store_tidb.as_retriever(), chain_type_kwargs={"prompt": prompt}
)
result = qa_chain({"query": query})

其中 TiDB 的连接串可以直接从 TiDB Cloud 中获取:

image-20241017100552250

向 RAG 应用提问之后,查看回答,发现 Milvus 和 TiDB 的回答基本一致,说明向量迁移是成功的。还可以更进一步,比对数据条数,如果一致,那么迁移应该已经成功,没有丢失数据。

RAG 应用的执行结果如下图:

image-20241016172840498

七、总结

不同数据库之间的数据迁移,本质上是将数据转换为所有数据库都能识别的通用格式,向量数据也不例外。本次迁移与传统的关系型数据库迁移有所不同,尽管 RAG 应用使用了 LangChain,但 LangChain 针对不同的数据库,创建的表结构和数据格式是不同的,因此需要对数据和表结构进行额外的整理,才能顺利将数据迁移至目标数据库。值得庆幸的是,TiDB Cloud 提供了多种便捷的数据导入方式,使迁移过程相对简单。

相关文章:

Milvus 到 TiDB 向量迁移实践

作者&#xff1a; caiyfc 原文来源&#xff1a; https://tidb.net/blog/e0035e5e 一、背景 我最近在研究使用向量数据库搭建RAG应用&#xff0c;并且已经使用 Milvus、Llama 3、Ollama、LangChain 搭建完成。最近通过活动获取了 TiDB Cloud Serverless 使用配额&#xff…...

springboot集成jsoup解析xml文件

springboot集成jsoup解析xml文件 1、引入依赖2、xml转成需要的map结构3、测试数据 1、引入依赖 <dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.16.2</version></dependency>2、xml转成需…...

基于Springboot相亲网站系统的设计与实现

基于 Springboot相亲网站系统的设计与实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;idea 源码获取&#xff1a;https…...

解决提示”warning C317 attempt to redefine macro ‘XX‘“问题

今天来分享一个之前在开发时候遇到的一个告警&#xff0c;是一个关于不正当使用宏定义产生的告警。 先看告警提示&#xff1a;warning C317: attempt to redefine macro ‘WIFI_UART_SEND_BUF’&#xff1b; 意思是该宏定义存在重新定义&#xff1b; 而为什么编译器会这样提示…...

3D图片动画效果组件封装

1.效果 3D图片动画效果 2.组件部分 import "./index.less"/*** 3D图片动画效果* pictures: 图片数组[封面,英雄,标题]*/ export const Picture3D (props: any) > {console.log("3D图片动画效果", props)return <divclassNamepicture3DonClick{prop…...

高级优化算法之 fminunc函数 实践

说明 在本专栏机器学习_墨#≯的博客-CSDN博客前面几篇文章中&#xff0c;大多采用梯度下降法来求解。其实还有很多的高级优化算法可以用来求解回归和分类问题&#xff0c;本文就是在吴恩达机器学习视频课程[1]的启示下&#xff0c;想要简单尝试一下Matlab自带的无约束多变量函数…...

1.5 ROS架构

到目前为止&#xff0c;我们已经安装了ROS&#xff0c;运行了ROS中内置的小乌龟案例&#xff0c;并且也编写了ROS小程序&#xff0c;对ROS也有了一个大概的认知&#xff0c;当然这个认知可能还是比较模糊并不清晰的&#xff0c;接下来&#xff0c;我们要从宏观上来介绍一下ROS的…...

Redis Search系列 - 第四讲 支持中文

目录 一、支持中文二、自定义中文词典2.1 Redis Search设置FRISOINI参数2.2 friso.ini文件相关配置1&#xff09;自定义friso UTF-8字典2&#xff09;修改friso.ini配置文件 三、实测中文分词效果 一、支持中文 Redis Stack 从版本 0.99.0 开始支持中文文档的添加和分词。中文…...

架构师备考-架构图设计案列

本文中所涉及的架构图主要参考软考-架构设计师历年Web 架构设计案例真题&#xff0c;在其基础上进行补充说明。 历年软考架构师案例题-Web架构设计考点 2014 MVC 架构2015、2016 J2EE 架构2017 经典网络架构2018 SOA 架构2019 分布式架构2020 SSM 架构2021 云平台架构2022 物…...

专业级Facebook直播工具推荐:提升你的直播体验

随着社交媒体的迅速发展&#xff0c;直播已成为现代内容传播的重要方式。Facebook作为全球最大的社交平台之一&#xff0c;为用户和企业提供了丰富的直播功能&#xff0c;吸引了众多观众和参与者。在这个竞争激烈的环境中&#xff0c;如何打造高质量的直播内容显得尤为重要。本…...

【NodeJS】NodeJS+mongoDB在线版开发简单RestfulAPI (三):Cors的设置及.env文件的设置

本项目旨在学习如何快速使用 nodejs 开发后端api&#xff0c;并为以后开展其他项目的开启提供简易的后端模版。&#xff08;非后端工程师&#xff09; 由于文档是代码写完之后&#xff0c;为了记录项目中需要注意的技术点&#xff0c;因此文档的叙述方式并非开发顺序&#xff0…...

[python flask 数据库ORM操作]

一、链接数据库 我们选择的框架是flask-sqlAlchemy 这个框架是对pymysql的封装。 连接数据库 #导入包 from flask_sqlalchemy import SQLAlchemy #创建flask app对象 app Flask(__name__) #设置配置信息 HOSTNAME "localhost" PORT 3306; USERNAME "root&…...

【JavaScript】如何优雅的编码if判断中的一个变量多个或条件

前言 你是否写过这样代码: ...if (status 1 || status 4 || status 6)...代码场景是这样的&#xff0c;记录有多个状态&#xff0c;当状态等于1,4,6时要做相同的逻辑。今天我们就分享一下如何简化写法&#xff0c;让代码更好看&#xff0c;更优雅。 使用 switch 语句 ...…...

SaaS云诊所系统源码,基于云计算技术的SAAS模式诊所管理系统,适用于诊所、门诊、卫生服务站、卫生站

SaaS云诊所管理系统源码&#xff0c;门诊管理系统源码&#xff0c;诊所药店云平台源码 云诊所管理系统是基于云计算的SAAS模式诊所管理系统&#xff0c;全面适用于诊所、门诊、卫生服务站、卫生站、卫生所、中医馆、药店、私人个体诊所、中小型门诊、乡村卫生室、医务室以及社…...

字节,AI产品经理面试,拿下offer!

如果大家最近打算找ai产品经理这方面的工作&#xff0c;可以对照着脑图准备起来啦。 这篇文章给大家讲解两道高频问题&#xff1a; 1&#xff09;AI产品经理和传统产品经理有什么区别 2&#xff09;AI 产品经理的工作职责和能力要求是什么&#xff1f; 这两个问题看似简单&a…...

Postgresql pgsql 插件之postgis 安装配置

相关链接&#xff1a; pgsql编译安装 一、说明 postgis是pgsql最强大的几个插件之一&#xff0c;可以用于地理信息系统&#xff08;gis&#xff09;的搭建 二、插件安装启动 由于我的pgsql是编译安装的&#xff0c;所以插件也是编译安装&#xff0c;更加灵活。 1.进入到源…...

单片机STC8H8K64U开发板_RA6809开发板 驱动彩屏显示

单片机STC8H8K64U开发板&#xff0c;型号RT8H8K001 预留Type C接口&#xff0c;可供电SWD下载&#xff1a; RA6809开发板&#xff0c;型号RT6809CNN01 预留Type C接口供电&#xff0c;预留MCU接口、电容触摸屏接口、液晶屏接口&#xff1a; 双臂合一&#xff0c;驱动和控…...

Redis底层和缓存雪崩,击穿,穿透

一、Redis的数据结构 1.动态字符串 我们知道Redis中保存的Key是字符串&#xff0c;value往往hi字符串或者字符串的集合。可见字符串是Redis中最常用的一种数据结构。不过&#xff0c;Redis 没有直接使用c语言的字符串&#xff0c;因为c语言字符串存在许多问题&#xff1a; …...

[Java基础] 集合框架

往期回顾 [Java基础] 基本数据类型 [Java基础] 运算符 [Java基础] 流程控制 [Java基础] 面向对象编程 [Java基础] 集合框架 [Java基础] 输入输出流 [Java基础] 异常处理机制 [Java基础] Lambda 表达式 目录 List 接口 数据结构 最佳实践 实战代码 Set 接口 数据…...

机器学习基础:算法如何让 AI 自我学习

大家好&#xff0c;我是Shelly&#xff0c;一个专注于输出AI工具和科技前沿内容的AI应用教练&#xff0c;体验过300款以上的AI应用工具。关注科技及大模型领域对社会的影响10年。关注我一起驾驭AI工具&#xff0c;拥抱AI时代的到来。 AI工具集1&#xff1a;大厂AI工具【共23款…...

25届字节跳动 抖音NLP算法工程师 面经

目录 一面/技术面 2024/08/30二面/技术面 2024/09/13 一面/技术面 2024/08/30 深挖实习&#xff08;最近的一段实习&#xff09;深挖论文&#xff08;让我共享屏幕&#xff0c;然后对着自己的论文讲&#xff09;论文做了多久完成的&#xff1f;主要都做了哪些工作&#xff1f;…...

转行网络工程师以后的就业前景如何?

就业前景如何本质上取决于你在这行业的发展状况&#xff0c;而发展状况又主要由你的技术水平和与人交流的能力所决定。 如果你的技术能力仅限于"安服仔"、"脚本小子"等入门级水平&#xff0c;那你的职业发展可能会像浮萍一样漂泊不定。但如果你能轻松编写…...

docker 和 containerd 关系

containerd 是一个开源的容器运行时&#xff0c;它是用来管理容器生命周期的守护进程。containerd 支持 Docker 和其他容器格式&#xff0c;并且是许多现代容器编排系统&#xff08;如 Kubernetes&#xff09;的基础组件之一。 containerd 提供了一个命令行工具 ctr&#xff0…...

算法-二叉树的最大路径和

为了找到二叉树的最大路径和&#xff0c;我们需要考虑所有可能的路径&#xff0c;包括不经过根节点的路径&#xff0c;所以其实如果你从整体上来一条路径一条路径的遍历&#xff0c;太复杂&#xff0c;我们可以换个思路&#xff0c;从每个节点出发&#xff0c;就把那个节点当成…...

解决url含%导致404错误

String imageUrl;// 使用WebClient下载图片WebClient webClient WebClientUtil.getWebClient();Mono<ByteArrayOutputStream> byteArrayOutputStreamMono webClient.get().uri(imageUrl).retrieve().bodyToFlux(DataBuffer.class) // 获取图片内容的DataBuffer流.reduc…...

[Linux Codec驱动]音频路由概念

1. 音频路由的基本概念 源&#xff08;Source&#xff09;&#xff1a;音频信号的发出方&#xff0c;通常是一个音频输入设备&#xff0c;如麦克风、音频播放设备等。接收端&#xff08;Sink&#xff09;&#xff1a;音频信号的接收方&#xff0c;通常是音频输出设备&#xff…...

母线槽温度监测的哪个部位?安科瑞母线槽测温解决方案-安科瑞黄安南

安科瑞生产厂家&#xff1a;黄安南 壹捌柒/陆壹伍/零陆贰叁柒 母线槽简单来说充当着电缆的角色只不过它是大电流的输送设备&#xff0c;一般是铜排或者绿排做导体&#xff0c;用非烯性绝缘材料做支撑&#xff0c;搭配金属外壳。相对于电缆来说母线槽的载流能力强、电能损耗低、…...

《深度学习》—— 模型的部署

文章目录 一、部署方式二、部署步骤三、注意事项 深度学习中模型的部署是将训练好的模型应用到实际场景中的过程&#xff0c;以下是对深度学习模型部署的详细解析&#xff1a; 一、部署方式 嵌入式设备部署&#xff1a;将深度学习模型部署到嵌入式设备中&#xff0c;如智能手机…...

多IP访问浏览器

添加多个ip地址 nmcli connection modify ens160 ipv4.method manual ipv4.addresses 192.168.61.100/24 ipv4.addresses 192.168.61.200/24 ipv4.addresses 192.168.61.128 ipv4.gateway 192.168.61.2 ipv4.dns 114.114.114.114...

1024程序员节福利放送 | AI 照片修复魔法,一键重拾旧时记忆

程序员充电礼包 今天是 1024 程序员节&#xff0c;小贝特意为大家准备了重磅福利&#xff01;新用户使用邀请码「1024」注册 http://OpenBayes.com&#xff0c;即可获得 20 小时单卡 A6000 的免费使用时长&#xff0c;价值 80 元&#xff0c;资源 1 个月有效。仅限今日&#xf…...