掘金 人工智能 09月18日
LangChain4j与向量数据库操作指南
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文详细介绍了LangChain4j框架下Embedding Model和Embedding Store的核心概念与工作原理,阐述了如何将文本、图像、视频转化为向量,并利用向量数据库进行高效存储和相似性检索。文章通过在Docker中安装Qdrant向量数据库,并结合Spring Boot集成,提供了从依赖配置、数据库连接到数据写入和查询的完整实操步骤,旨在帮助开发者快速掌握LangChain4j在向量化和检索增强生成(RAG)应用中的应用。

📚 **Embedding Model与向量化原理**:Embedding Model是将文本、图像或视频等信息转换为高维向量(浮点数数组)的机器学习模型。这些向量能捕捉数据的语义相似性,使得机器能够进行高效的比较、聚类和分类。例如,用数值表示水果的特征,比文字描述更易于比较。

🗄️ **向量数据库(VectorStore)的作用**:向量数据库专门用于存储和检索高维向量数据,其查询方式为相似性搜索而非精确匹配。当给定一个查询向量时,它能返回与之最相似的向量。这对于实现语义搜索、推荐系统以及检索增强生成(RAG)等应用至关重要,能够捕捉复杂的词汇关系,超越传统文本匹配。

🚀 **LangChain4j与Qdrant集成实操**:文章详细演示了如何使用LangChain4j与Qdrant向量数据库进行集成。通过在Spring Boot项目中添加相应依赖,配置Qdrant客户端和Embedding Store,并利用阿里云百炼的向量大模型(如OpenAI Embedding Model)进行文本向量化。实际操作包括创建数据库集合、向数据库写入向量化后的文本数据,以及通过查询向量进行相似性检索,展示了RAG应用的完整流程。

💡 **配置与部署要点**:文中强调了在Spring Boot应用中正确配置`application.yaml`以处理中文乱码问题(设置`server.servlet.encoding.charset=utf-8`)。同时,介绍了通过Docker容器部署Qdrant数据库,并提供了访问Qdrant Dashboard的URL,为本地开发和测试提供了便利。

12. LangChain4j + 向量数据库操作详细说明

@[toc]

LangChain4j 向量化 3 件套:

    Embedding Model模型简介:

docs.langchain4j.dev/tutorials/r…

嵌入(Embedding) 的工作原理是将文本,图像和视频转换为称为向量(Vectors) 的浮点数数组。

    Embedding Store存储简介

docs.langchain4j.dev/tutorials/r…

向量存储(VectorStore) 是一种用于存储和检索高维向量数据的数据库或存储解决方案。

在 VectorStrore 中,查询与传统关系数据库不同。它们执行相似性搜索,而不是精确匹配。

mysql   select * from book where id = 1
    EmbeddingSearchRequest查询

docs.langchain4j.dev/tutorials/r…

小总结:

嵌入模型是一种机器学习模型,旨在在连续的低维向量空间中表示数据(例如文本、图像或其他形式的信息)。

这些嵌入可以捕获数据之间的语义或上下文相似性,使机器能够更有效地执行比较、聚类或分类等任务。

假设你想描述不同的水果。你不用长篇大论,而是用数字来描述甜度、大小和颜色等特征。例如,苹果可能是[8,5,7],而香蕉是[9,7,4]。这些数字使比较或对相似的水果进行分组变得更容易。

向量数据库能做什么:

将文本,图像和视频转换为称为向量(Vectors) 的浮点数数组在 VectroStore 中,查询与传统关系数据库不同。它们执行相似性搜索,而不是精确匹配。当给定一个向量作为查询时,VectorStore 返回与查询向量“相似”的向量。

特点:

总结:

将文本映射到高维空间中的点,使语义相似的文本在这个空间中距离较近。

例如:“肯德基” 和 “麦当劳”的向量可能会比“肯德基”和“新疆大盘鸡”的向量更接近

LangChain4j 支持的向量数据库

docs.langchain4j.dev/integration…

docs.langchain4j.info/integration…

LangChain4j + 向量数据库实操——Qdrant

    创建对应项目的 module 模块内容:导入相关的 pom.xml 的依赖,这里我们采用流式输出的方式,导入 整合 Spring Boot ,langchain4j-open-ai-spring-boot-starter,langchain4j-spring-boot-starter ,同时我们加入我们的 qdrant 向量数据库 jak 依赖。这里我们不指定版本,而是通过继承的 pom.xml 当中获取。
        <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>            <version>1.2.0-beta8</version>        </dependency>        <!--lombok-->        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <optional>true</optional>        </dependency>

Docker 容器当中安装 Qdrant 向量数据库

关于 Qdarant 学习内容,参考如下官网:

Qdrant是一个高性能的向量数据库,用于存储嵌入并进行快速的向量搜索其它。

这里我们使用 Docker 安装 Qdrant 。

docker run -p 6333:6333 -p 6334:6334 qdrant/qdrant

打开浏览器访问:http://localhost:6333/

打开浏览器访问:http://localhost:6333/dashboard#/collections

可以打开上述两个页面就说明 Qdant 向量数据库安装成功了。

    设置 applcation.yaml / properties 配置文件,其中指明我们的输出响应的编码格式,因为如果不指定的话,存在返回的中文,就是乱码了。
server.port=9011spring.application.name=langchain4j-11chat-embedding# 设置响应的字符编码,避免流式返回输出乱码server.servlet.encoding.charset=utf-8server.servlet.encoding.enabled=trueserver.servlet.encoding.force=true# https://docs.langchain4j.dev/tutorials/spring-boot-integration#langchain4j.open-ai.chat-model.api-key=${aliQwen-api}#langchain4j.open-ai.chat-model.model-name=qwen-plus#langchain4j.open-ai.chat-model.base-url=https://dashscope.aliyuncs.com/compatible-mode/v1# 大模型调用不可以明文配置,你如何解决该问题# 1 yml:                ${aliQwen-api},从环境变量读取# 2 config配置类:      System.getenv("aliQwen-api")从环境变量读取

使用向量数据库实操

    选取我们合适的向量大模型,注意:向量数据库是一个将文本,图像和视频转换为称为向量(Vectors) 的浮点数数组在 VectroStore 中的数据库,而我们需要将我们的文本,图像,视频等信息转换为向量数据库可以存储是向量数据,就需要借助使用我们的向量大模型(也被称之为嵌入大模型),这里我们选择大阿里云百炼的向量大模型。

    编写大模型三件套(大模型 key,大模型 name,大模型 url) 三件套的大模型配置类。同时也需要配置,我们的向量数据库,让向量数据库和向量大模型(嵌入式大模型)绑定,进行写入到向量数据库当中

package com.rainbowsea.langchain4jchatembedding.config;import dev.langchain4j.data.segment.TextSegment;import dev.langchain4j.model.chat.ChatModel;import dev.langchain4j.model.embedding.EmbeddingModel;import dev.langchain4j.model.openai.OpenAiChatModel;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;/** */@Configurationpublic class LLMConfig{    @Bean    public EmbeddingModel embeddingModel()    {        return OpenAiEmbeddingModel.builder()                    .apiKey(System.getenv("aliQwen_api"))                    .modelName("text-embedding-v3")                    .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")                .build();    }    /**     * 创建Qdrant客户端     * @return     */    @Bean    public QdrantClient qdrantClient() {        QdrantGrpcClient.Builder grpcClientBuilder =                QdrantGrpcClient.newBuilder("127.0.0.1", 6334, false);        return new QdrantClient(grpcClientBuilder.build());    }    @Bean    public EmbeddingStore<TextSegment> embeddingStore() {        return QdrantEmbeddingStore.builder()                .host("127.0.0.1")                .port(6334)                .collectionName("test-qdrant")                .build();    }}
    编写对外访问的 ctroller ,注意:我们先将数据通过向量大模型将文本信息写入到向量数据库,在查询操作向量数据库当中的信息、

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;/** * @Description: 知识出处,https://docs.langchain4j.dev/tutorials/rag#embedding-store */@RestController@Slf4jpublic class EmbeddinglController{    @Resource    private EmbeddingModel embeddingModel;  // 文本向量化模型    @Resource    private QdrantClient qdrantClient;  // 向量数据库访问的连接客户端    @Resource    private EmbeddingStore<TextSegment> embeddingStore;  // 对向量数据库CRUD 的操作类    /**     * 文本向量化测试,看看形成向量后的文本,     * http://localhost:9011/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:9011/embedding/createCollection     */    @GetMapping(value = "/embedding/createCollection")    public void createCollection()    {        // 创建向量数据库实例和创建索引:test-qdrant        var vectorParams = Collections.VectorParams.newBuilder()                .setDistance(Collections.Distance.Cosine)                .setSize(1024)                .build();        qdrantClient.createCollectionAsync("test-qdrant", vectorParams);    }}

注意:我们需要先将(文本,图像,视频)数据通过向量大模型,转换为向量信息,才能写入到向量数据当中。

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;/** * @Description: 知识出处,https://docs.langchain4j.dev/tutorials/rag#embedding-store */@RestController@Slf4jpublic class EmbeddinglController{    @Resource    private EmbeddingModel embeddingModel;  // 文本向量化模型    @Resource    private QdrantClient qdrantClient;  // 向量数据库访问的连接客户端    @Resource    private EmbeddingStore<TextSegment> embeddingStore;  // 对向量数据库CRUD 的操作类    /**     * 新建向量数据库实例和创建索引:test-qdrant     * 类似mysql create database test-qdrant     * http://localhost:9011/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", "zzyy");        Embedding embedding1 = embeddingModel.embed(segment1).content();        // 向量大模型转换好的信息,写入到向量数据库当中        String result = embeddingStore.add(embedding1, segment1);        System.out.println(result);        return result;    }}

查询向量数据库的内容(比较相似度,不是精确查找)

注意:查询比较向量数据库当中的内容,也是要将我们查找的“关键词、内容”,通过向量大模型向量化,后进行去向量数据库查询比较相似度才行

同时注意:我们向量数据库查询到的数据
还是向量化的,
我们需要通过
:searchResutl.matches().get(0)
.embedded().text() 返回回来向量化之前的
样子。注意这里,get(0) 表示获取
第一个,下标为0的数据内容

package com.rainbowsea.langchain4jchatembedding.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;/** * @Description: 知识出处,https://docs.langchain4j.dev/tutorials/rag#embedding-store */@RestController@Slf4jpublic class EmbeddinglController{    @Resource    private EmbeddingModel embeddingModel;  // 文本向量化模型    @Resource    private QdrantClient qdrantClient;  // 向量数据库访问的连接客户端    @Resource    private EmbeddingStore<TextSegment> embeddingStore;  // 对向量数据库CRUD 的操作类      @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("zzyy2"))                .maxResults(1)                .build();        EmbeddingSearchResult<TextSegment> searchResult = embeddingStore.search(embeddingSearchRequest);        System.out.println(searchResult.matches().get(0).embedded().text());    }}

最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

LangChain4j 向量数据库 Embedding Model Qdrant Spring Boot RAG AI Vector Database Vectorization
相关文章