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

LangChain4J-(8)-向量化

一、什么是向量

向量是一种有大小和方向的数学对象。它可以表示为从一个点到另一个点的有向线段。例如,二维空间中的向量可以表示为 (x,y),表示从原点 (0,0) 到点 (x,y) 的有向线段。

从数学的角度看,向量是一个“有方向和大小的东西”,可以用数字坐标来描述。在计算机世界中,我们可以把向量简单地理解为一组“有意义的数字”,用来表示事物的特征。

例如我们描述一只猫的可以描述为有胡须、有毛、会喵喵叫,这些信息转换成向量就可以用一堆数字来表述[有胡须:0.981,有毛:0.193,会喵喵叫:0.453],每个数字都代表一个特征,这样猫的特性就被向量化了,就能被计算机检索出来。

文本向量就是将文本转成一组N维的浮点数,即文本向量又叫Embeddings,向量之间可以计算距离,距离的远近对应语义相似度的大小。

PS:文本向量是怎么计算得到的,这不是本文能讲解明白的,不是笔者不想写,是想要把这个话题拿来写着实是有点难度。

二、向量间的相似度计算

向量的相似性通常通过计算向量之间的距离来比较。 距离越小,相似性越高。常用的算法比如余弦距离和欧式距离来判断向量距离。

假设我们有两个文本的向量:

文本1:“我感冒了” → 向量为 [0.82, 0.61, 0.97]

文本2:“我流感了” → 向量为 [0.90, 0.73, 0.98]

通过余弦相似度公式计算余弦相似性,结果越接近1,说明两个文本的语义高度相似。

欧氏距离:越小越相似。

余弦距离:越大越相似,余弦值越大夹角越小,距离越近。

三、向量数据库

Embedding Modle(嵌入模型)负责计算向量,向量数据库负责存储和比较向量。向量数据库是专门为向量检索设计的中间件!

读到这里大家可能会觉着向量数据真厉害,简直可以秒杀传统的关系型数据库,在这里告诉大家:

  • 向量数据库的意义是快速的检索;

  • 向量数据库本身不生成向量,向量是由 Embedding 模型产生的;

  • 向量数据库与传统的关系型数据库是互补的,不是替代关系,在实际应用中根据实际需求经常同时使用。

大家不要盲目迷信学习大模型我们带来的新的技术视野。

下面为大家列举几个常见的向量数据库,这些向量数据库的特点大家可自行总结:

  1. Chroma

  2. Deep Lake (Activeloop)

  3. Elasticsearch & OpenSearch(没想到吧,Elasticsearch也支持向量检索)

  4. Faiss (Facebook AI Similarity Search)

  5. LanceDB

  6. Milvus

  7. Pinecone

  8. PgVector (PostgreSQL 扩展)

  9. Qdrant

  10. ScaNN (Scalable Nearest Neighbors)

四、langchain4j的向量化三件套

在 LangChain4j 中,EmbeddingModelEmbeddingStore 和 EmbeddingSearchRequest 是向量化流程中的核心组件,分别共同完成文本的向量转换、存储和检索功能。以下是对这三个组件的详细说明及使用示例:

1. EmbeddingModel(嵌入模型)

  • 作用:将文本(字符串)转换为数值向量(Embedding),是向量化的核心。

  • 特性:支持本地模型(如 BERT 系列)和远程 API(如 OpenAI、Anthropic 等)。

  • 常见实现OpenAiEmbeddingModelLlamaCppEmbeddingModelSentenceTransformersEmbeddingModel 等。

示例代码

// 使用 OpenAI 的嵌入模型
EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder().apiKey("your-openai-api-key").modelName("text-embedding-3-small") // 模型名称.timeout(Duration.ofSeconds(60)) // 超时设置.build();// 将文本转换为向量
String text = "LangChain4j 是一个用于构建 LLM 应用的 Java 框架";
Embedding embedding = embeddingModel.embed(text).content();System.out.println("向量维度: " + embedding.vector().size());
System.out.println("向量前 5 个值: " + embedding.vector().subList(0, 5));

2. EmbeddingStore(向量存储)

  • 作用:存储向量(Embedding)及其关联的元数据(如原始文本、ID 等),并支持向量相似度搜索。

  • 特性:底层通常对接向量数据库(如 Chroma、Milvus、Weaviate 等)。

  • 核心功能add(添加向量)、search(搜索相似向量)、delete(删除向量)等。

示例代码--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

// 创建 Chroma 向量存储(需先启动 Chroma 服务)
EmbeddingStore<TextSegment> embeddingStore = ChromaEmbeddingStore.builder().baseUrl("http://localhost:8000") // Chroma 服务地址.collectionName("my-collection") // 集合名称.embeddingModel(embeddingModel) // 关联嵌入模型.build();// 准备文本片段(带元数据)
TextSegment segment1 = TextSegment.from("LangChain4j 支持多种嵌入模型", Metadata.of("source", "doc1.txt", "page", "5"));
TextSegment segment2 = TextSegment.from("向量存储用于高效检索相似文本", Metadata.of("source", "doc2.txt", "page", "10"));// 将文本片段转换为向量并存储
embeddingStore.add(segment1, segment2);

3. EmbeddingSearchRequest(向量搜索请求)

  • 作用:定义向量搜索的参数(如查询向量、返回数量、过滤条件等),作为 EmbeddingStore.search 方法的输入。

  • 核心参数

    • queryEmbedding:查询文本的向量。

    • maxResults:返回的最大相似结果数。

    • metadataFilter:基于元数据的过滤条件(可选)。

示例代码

// 生成查询文本的向量
String query = "LangChain4j 如何存储向量?";
Embedding queryEmbedding = embeddingModel.embed(query).content();// 构建搜索请求
EmbeddingSearchRequest request = EmbeddingSearchRequest.builder().queryEmbedding(queryEmbedding).maxResults(2) // 返回 top 2 相似结果.metadataFilter(MetadataFilter.builder().addCondition("source", MetadataConditionOperator.EQUALS, "doc2.txt") // 过滤来源.build()).build();// 执行搜索
List<EmbeddingMatch<TextSegment>> matches = embeddingStore.search(request);// 输出结果
for (EmbeddingMatch<TextSegment> match : matches) {System.out.println("相似度: " + match.score());System.out.println("文本: " + match.embedded().text());System.out.println("元数据: " + match.embedded().metadata());
}

4、三者协同流程

  1. 文本向量化:通过 EmbeddingModel 将原始文本转换为向量。

  2. 向量存储:通过 EmbeddingStore 存储向量及元数据。

  3. 向量检索:构建 EmbeddingSearchRequest,基于查询向量在 EmbeddingStore 中搜索相似结果。

这个流程是构建基于向量的语义搜索、问答系统等 LLM 应用的基础。

五、撸代码

Step1

再开始撸代码前请先安装Qdrant向量数据库,使用http://localhost:6333/dashboard#/welcome验证是否安装成功。安装过程本文不做讲解:)

Step2

本章的pom中来了新伙伴

  <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j</artifactId></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-open-ai</artifactId></dependency><!--qdrant--><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-qdrant</artifactId></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

Step3

新建LLMConfig

package com.xxx.demo.config;import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.qdrant.QdrantEmbeddingStore;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class LLMConfig {@Beanpublic EmbeddingModel embeddingModel(){return OpenAiEmbeddingModel.builder().apiKey(System.getenv("aliqwen-apikey")).modelName("text-embedding-v3").baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1").build();}/*** 创建Qdrant客户端* @return*/@Beanpublic QdrantClient qdrantClient() {QdrantGrpcClient.Builder grpcClientBuilder =QdrantGrpcClient.newBuilder("127.0.0.1", 6334, false);return new QdrantClient(grpcClientBuilder.build());}@Beanpublic EmbeddingStore<TextSegment> embeddingStore() {return QdrantEmbeddingStore.builder().host("127.0.0.1").port(6334).collectionName("test-qdrant").build();}
}

Step4

创建一个controller,笔者自己用AI模仿《静夜思》写一首《明月夜》

package com.xxx.demo.controller;import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.store.embedding.EmbeddingSearchRequest;
import dev.langchain4j.store.embedding.EmbeddingSearchResult;
import dev.langchain4j.store.embedding.EmbeddingStore;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.grpc.Collections;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import static dev.langchain4j.store.embedding.filter.MetadataFilterBuilder.metadataKey;@RestController
@Slf4j
public class EmbeddinglController {@Resourceprivate EmbeddingModel embeddingModel;@Resourceprivate QdrantClient qdrantClient;@Resourceprivate EmbeddingStore<TextSegment> embeddingStore;/*** 文本向量化测试,看看形成向量后的文本* http://localhost:9012/embedding/embed* @return*/@GetMapping(value = "/embedding/embed")public String embed(){String prompt = """明月夜明月照庭阶,清辉满客怀。举头望银汉,归思自难排。""";Response<Embedding> embeddingResponse = embeddingModel.embed(prompt);System.out.println(embeddingResponse);return embeddingResponse.content().toString();}/*** 新建向量数据库实例和创建索引:test-qdrant* 类似mysql create database test-qdrant* http://localhost:9012/embedding/createCollection*/@GetMapping(value = "/embedding/createCollection")public void createCollection(){var vectorParams = Collections.VectorParams.newBuilder().setDistance(Collections.Distance.Cosine).setSize(1024).build();qdrantClient.createCollectionAsync("test-qdrant", vectorParams);}/*往向量数据库新增文本记录*/@GetMapping(value = "/embedding/add")public String add(){String prompt = """明月夜明月照庭阶,清辉满客怀。举头望银汉,归思自难排。""";TextSegment segment1 = TextSegment.from(prompt);segment1.metadata().put("author", "BBK");Embedding embedding1 = embeddingModel.embed(segment1).content();String result = embeddingStore.add(embedding1, segment1);System.out.println(result);return result;}@GetMapping(value = "/embedding/query1")public void query1(){Embedding queryEmbedding = embeddingModel.embed("明月夜说的是什么").content();EmbeddingSearchRequest embeddingSearchRequest = EmbeddingSearchRequest.builder().queryEmbedding(queryEmbedding).maxResults(1).build();EmbeddingSearchResult<TextSegment> searchResult = embeddingStore.search(embeddingSearchRequest);System.out.println(searchResult.matches().get(0).embedded().text());}@GetMapping(value = "/embedding/query2")public void query2(){Embedding queryEmbedding = embeddingModel.embed("明月夜").content();EmbeddingSearchRequest embeddingSearchRequest = EmbeddingSearchRequest.builder().queryEmbedding(queryEmbedding).filter(metadataKey("author").isEqualTo("BBK")).maxResults(1).build();EmbeddingSearchResult<TextSegment> searchResult = embeddingStore.search(embeddingSearchRequest);System.out.println(searchResult.matches().get(0).embedded().text());}
}

Step5

查看向量化之后结果

查看向量数据库的存储结果

Step6

查看大模型从向量数据库中获取的结果

http://www.dtcms.com/a/399202.html

相关文章:

  • 湖州做网站优化wordpress门户网站模板下载
  • 客户管理软件 crm肇庆seo按天收费
  • 修改centos7镜像仓库
  • 生成式人工智能在汽车软件开发中的应用
  • todesk远程到被控Mac后能看到画面,鼠标键盘操作无反应
  • HOW - 前端团队手动上报规范(Sentry)
  • 开源 java android app 开发(十五)自定义绘图控件--仪表盘
  • 深圳防疫最新政策公告百度推广怎么优化排名
  • React学习第一天
  • 内蒙古网站建设网络推广的目标
  • 秋招防作弊指南:AI面试智能监考全解析
  • 来宾住房和建设局网站ppt 模板免费下载
  • 最新2025版本!Bandicam8.2.2.2531,最佳电脑录屏,无限制,支持4K画质,新人UP主游戏录屏录课必备工具
  • app制作公司哪个好厦门seo外包平台
  • 浅谈Node.js以及对fs模块的理解及常用方法
  • AIGC中的图像生成Stable Diffusion,MidJourney需要的算力配置要求是什么?
  • 建设资格执业注册中心网站扬中话
  • 兰州网站建设小程序html访问人数统计代码
  • vscode ssh连接远程服务器一直显示正在打开远程Initializing VS Code Server(已解决)
  • 网站初期建设的成本来源关键词快速排名软件价格
  • Nature论文深度剖析:DeepSeek R1 MoE架构的工程化实践与代码级优化
  • 【GD32】串口
  • 双活、异地多活架构怎么设计才不翻车?
  • 怎么创建一个网站卖东西isp网站接入做哪些业务
  • 佛山市多语言营销型网站建站制作网站的最新软件
  • UniApp 技术架构深度解析
  • 北京网站seowyhseo滨海做网站的公司
  • 基于 DMS 进行 DDL 同步的测试与分析
  • 网站 分辨率射阳做企业网站哪家好
  • Qt入门学习记录