简单来说,“向量”Vector 是大模型(LLM)在搜索时使用的一种“技术手段”,通过向量比对,大模型能找出问题的相关答案,并且进行智能回答。

向量简介

Vector 是向量或矢量的意思,向量是数学里的概念,而矢量是物理里的概念,但二者描述的是同一件事。

定义:向量是用于表示具有大小和方向的量。

向量可以在不同的维度空间中定义,最常见的是二维和三维空间中的向量,但理论上也可以有更高维的向量。例如,在二维平面上的一个向量可以写作 (x,y),这里 x 和 y 分别表示该向量沿两个坐标轴方向上的分量;而在三维空间里,则会有一个额外的 z 坐标,即 (x,y,z)。

例如,有以下 4 种狗,我们要在大模型中如何表示它们呢:

我们就可以使用向量来表示,如下图所示:

向量关系图:

向量数据库

定义:向量数据库是一种专门用于存储、管理和检索向量数据(即高维数值数组)的数据库系统。其核心功能是通过高效的索引结构和相似性计算算法,支持大规模向量数据的快速查询与分析。

向量数据库以向量为基本存储单元,这些向量通常由文本、图像、音频等非结构化数据通过深度学习模型(如 Embedding 技术)转换而来,每个向量代表对象在多维空间中的特征。例如,一段文本可转化为 512 维的浮点数向量,用于表示其语义信息。

向量数据库维度越高,查询精准度也越高,查询效果也越好。

常用向量数据库

Java 领域常用的向量数据库有:

  • Redis Stack:原有 Redis 服务升级之后就可以用来存储向量数据。
  • Elastic Search
  • Milvus:一款开源的高性能向量数据库,专为存储、索引和检索大规模向量数据而设计。它可以实现万亿级向量的毫秒级相似性搜索。

向量数据去重

向量数据库去重通常是在添加时进行判断,它主要实现方式有以下几种:

  1. 基于向量相似度去重。
  2. 基于 Redis 唯一键去重。
  3. 使用 Redis SetNX 去重。
  4. 基于 Redis Set 数据结构去重。

具体实现如下。

1.基于向量相似度去重

原理:在插入前计算新向量与已有向量的余弦相似度,若超过阈值(如 0.95)则视为重复。

EmbeddingSearchRequest request = EmbeddingSearchRequest.builder()
.queryEmbedding(newEmbedding)
.maxResults(1)
.minScore(0.95) // 相似度阈值
.build();
List<EmbeddingMatch<TextSegment>> matches = embeddingStore.search(request);
if (matches.isEmpty()) {
embeddingStore.add(newEmbedding, textSegment);
}

优点:语义级去重,适合文本内容相似但表述不同的场景。

缺点:存在线程安全问题,多任务同时执行,可能导致插入重复数据。

2.基于 Redis 唯一键去重

原理:使用文本内容的哈希值(如 MD5)作为 Redis Key 的一部分,确保唯一性。

String textHash = DigestUtils.md5Hex(textSegment.text());
String redisKey = "embedding:" + textHash;
if (!redisTemplate.hasKey(redisKey)) {
embeddingStore.add(newEmbedding, textSegment);
redisTemplate.opsForValue().set(redisKey, "1");
}

优点:性能高,适合完全相同的文本内容。

缺点:存在线程安全问题,多任务同时执行,可能导致插入重复数据。

3.使用 Redis SetNX 去重

原理:使用 Redis 的 SETNX(set if not exists)命令,避免非原子性问题,它是先判断才插入,如果已经存在就不再插入了。

具体实现代码如下:

// 生成文本的唯一哈希(如 MD5)
String textHash = DigestUtils.md5Hex(textSegment.text());
String redisKey = "vector:" + textHash;
// 判断是否存在
Boolean isSet = redisTemplate.opsForValue()
.setIfAbsent(redisKey, "1");
if (Boolean.TRUE.equals(isSet)) {
// 键不存在,保存向量数据
embeddingStore.add(embedding, textSegment);
} else {
// 键已存在,跳过或报错
throw new RuntimeException("重复数据");
}

优点:性能高,不存在线程安全问题。

4.基于 Redis Set 数据结构去重

原理:Set 去重,将向量 ID 或文本哈希存入 Redis Set,插入前检查是否存在。

// 生成文本的唯一哈希(如 MD5)
String textHash = DigestUtils.md5Hex(textSegment.text());
if (redisTemplate.opsForSet().add("unique_embeddings", textHash) == 1) {
embeddingStore.add(newEmbedding, textSegment);
}

优点:简单高效,不存在线程安全问题。

缺点:需维护额外的 Set 数据结构。

小结

向量数据库去重一定是生产环境要做的事,它的解决方案也有很多,通常我们会选择一种高效、且没有线程安全的解决方案,例如 Redis SetNX 或 Set 数据结构来解决。

本文已收录到我的技术小站 www.javacn.site,其中包含的内容有:Spring AI、LangChain4j、MCP、Function Call、RAG、向量数据库、Prompt、多模态、向量数据库、嵌入模型等内容。

大模型向量数据库去重的N种实现方案!的更多相关文章

  1. Django 模型和数据库 总结

    模型和数据库 模型 首先我们在创建一个model的时候,这个类都是继承自 django.db.models.Model, 各种Model Field类型 AutoField,自动增长的IntegerF ...

  2. 【ASP.NET Core】EF Core 模型与数据库的创建

    大家好,欢迎收看由土星卫视直播的大型综艺节目——老周吹逼逼. 今天咱们吹一下 EF Core 有关的话题.先说说模型和数据库是怎么建起来的,说装逼一点,就是我们常说的 “code first”.就是你 ...

  3. PowerDesigner 学习:十大模型及五大分类

    个人认为PowerDesigner 最大的特点和优势就是1)提供了一整套的解决方案,面向了不同的人员提供不同的模型工具,比如有针对企业架构师的模型,有针对需求分析师的模型,有针对系统分析师和软件架构师 ...

  4. PowerDesigner 15学习笔记:十大模型及五大分类

    个人认为PowerDesigner 最大的特点和优势就是1)提供了一整套的解决方案,面向了不同的人员提供不同的模型工具,比如有针对企业架构师的模型,有针对需求分析师的模型,有针对系统分析师和软件架构师 ...

  5. MySQL数据库去重 SQL解决

    MySQL数据库去重的方法 ​ 数据库最近有很多重复的数据,数据量还有点大,本想着用代码解决,后来发现用SQL就能解决,这里记录一下 看这条SQL DELETE consum_record FROM ...

  6. 玩转Django2.0---Django笔记建站基础六(模型与数据库)

    第六章 模型与数据库 Django对各种数据库提供了很好的支持,包括:PostgreSQL.MySQL.SQLite和Oracle,而且为这些数据库提供了统一的调用API,这些API统称为ORM框架. ...

  7. Django中的模型(操作数据库)

    目录 Django配置连接数据库 在Django中操作数据库 原生SQL语句操作数据库 ORM模型操作数据库 增删改查 后台管理 使用后台管理数据库 模型是数据唯一而且准确的信息来源.它包含您正在储存 ...

  8. 图解大数据 | 海量数据库查询-Hive与HBase详解

    作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/84 本文地址:http://www.showmeai.tech/article-det ...

  9. 千亿参数开源大模型 BLOOM 背后的技术

    假设你现在有了数据,也搞到了预算,一切就绪,准备开始训练一个大模型,一显身手了,"一朝看尽长安花"似乎近在眼前 -- 且慢!训练可不仅仅像这两个字的发音那么简单,看看 BLOOM ...

  10. 两个文件去重的N种姿势

    最近利用shell帮公司优化挖掘关键词的流程,用shell替代了多个环节的操作,极大提高了工作效率. shell在文本处理上确有极大优势,比如多文本合并.去重等,但是最近遇到了一个难搞的问题,即两个大 ...

随机推荐

  1. Irwin-Hall 分布/CF1477F 题解

    Irwin-Hall 分布 对于 \(n\) 个均匀分布于 \([0,1]\) 的连续随机变量 \(X_1,X_2,\dots,X_n\),其和的随机变量 \(X\) 满足: \[P(X\le x)= ...

  2. 项目中途引入Mybatis-plus后报错,报错Caused by: java.lang.ClassNotFoundException: org.mybatis.logging.LoggerFactory

    一.报错原因 mybatis-plus和pagehelper jar包冲突,注释mybatis-spring和pagehelper插件即可 <!-- SpringBoot集成mybatis框架 ...

  3. 别再为文本提取抓狂!一站式文本提取神器Kreuzberg 助你解决PDF、图片、文档等多格式文件的文本提取难题

    大家好,我是六哥,相信很多朋友肯定都有过从各种文档里提取文本的经历,那过程可太让人头疼了!今天就给大家分享一款超实用的现代Python库--Kreuzberg,帮你轻松解决文本提取的难题. 一.Kre ...

  4. VSCode ESLint规则警告屏蔽方法

    举例:要屏蔽"Missing trailing comma"或"comma-dangle"警告,你可以使用ESLint的配置选项来设置规则.下面是一些方法,你可 ...

  5. git码云安装及使用菜鸟教程

    1.下载Windows本地码云 https://mirrors.huaweicloud.com/git-for-windows/(华为镜像下载),选择合适的版本下载,此处下载速度要快些 2.登录码云官 ...

  6. 【Matlab】cell 和cell array

    最近写matlab程序和处理数据,用到了cell 和struct ,简单记录一下. 从cell array 删除cell 用{}不能删除,要用(),赋予[]. >> s.a=1 s = 包 ...

  7. 修改npm下载地址为淘宝镜像

    修改 npm 下载地址 修改为国内淘宝镜像 # 修改为新淘宝镜像(推荐) npm config set registry https://registry.npmmirror.com/ # 旧 npm ...

  8. Error: Address already in use

    端口被某个进程占用 使用命令 lsof -i:端口号 然后看到进程号,直接杀掉进程就好 kill -9 进程号

  9. 使用Win32控制台实现socket通信

    本示例使用Win32控制台实现socket通信 ,可多个客户端同时连接服务器. 服务端代码: #include <iostream> #include <winsock2.h> ...

  10. Mavros & Mavlink

    博客地址:https://www.cnblogs.com/zylyehuo/ 参考 https://www.bilibili.com/video/BV1x841167uG?spm_id_from=33 ...