「Java AI实战」LangChain4J - 向量数据库接入与语义检索

系列文章目录

第一章 「Java AI实战」LangChain4J接入Xinference本地大模型
第二章 「Java AI实战」LangChain4J - ChatAPI 及常用配置



前言

相比 Python 社区的 LangChain,LangChain4J 为 Java 提供了相似的链式语言模型编排能力,兼顾工程化可维护性与复杂场景的灵活性。而在众多场景中,向量数据库(如 FAISS、Milvus、Qdrant)扮演了大模型“记忆体”的角色,尤其适用于构建基于语义理解的问答系统(RAG)、文档检索、智能客服等系统。


一、什么是向量数据库?

1.1. 向量数据库的原理简述

在传统数据库中,检索通常依赖于关键词、精确匹配或范围查询。而在自然语言处理、图像识别等 AI 场景中,我们更需要的是语义相似度检索,即“查找与某个内容在语义上最接近的内容”。这正是向量数据库的核心用途。

✅ 什么是向量?

向量是通过深度学习模型(如 BERT、OpenAI Embedding、CLIP 等)对文本、图片、音频等内容提取出的稠密特征表示。

它通常表现为一个高维浮点数组,例如:

[0.12, -0.08, 0.33, ..., 0.91] // 维度可以是 384、768、1536 等

在语义空间中,相似的内容对应的向量距离会更近,从而实现语义检索。

✅ 向量数据库的核心功能

  • 向量存储:存储大量高维向量及其关联元数据(如文档ID、标题、标签等)。

  • 相似度搜索:基于欧几里得距离、余弦相似度等方式,快速查找最相近的Top-K向量。

  • 近似最近邻(ANN)算法:为提升性能,向量数据库使用 ANN 算法(如 HNSW、IVF)在亿级数据中实现毫秒级搜索。

  • 条件过滤:支持结合结构化字段(如类别、时间)进行筛选+向量检索。

✅ 与传统数据库的区别

功能点传统数据库向量数据库
检索方式精确匹配 / 范围查询语义相似度(向量Top-K)
数据结构行/列、主键索引高维向量 + 元数据结构
查询能力SQL 查询向量相似度 + 条件过滤
典型应用场景电商、金融系统搜索推荐、AI检索、RAG场景

1.2. 主流向量数据库介绍

名称特点
FaissFacebook 出品,C++/Python,高性能本地引擎
Milvus专业向量数据库,支持多种索引算法,企业级
Weaviate云原生,支持 GraphQL 查询和语义增强
Pinecone商业化云向量服务,易用性高
QdrantRust 编写,支持嵌入过滤,支持 Docker 快速部署
Chroma适合轻量级 RAG 本地场景,支持 LangChain

1.3. 向量数据库在语义搜索中的价值

向量数据库是语义搜索的核心基础设施,在传统关键词检索中,系统只能根据字面匹配进行查找,难以理解用户的真实意图。

而向量数据库通过将文本等非结构化内容映射为高维语义向量,使得系统能够基于语义相似度进行“意图层”的检索。

这意味着,即使用户输入的查询词与数据库中的文档没有明显的词面重合,系统依然可以通过语义向量的接近程度,返回语义相关度最高的内容。这种能力广泛应用于:

  • 问答系统(RAG):基于语义检索找到相关知识片段,提供更可靠的上下文补全。

  • 智能搜索框:实现更“懂你”的搜索体验。

  • 推荐系统:用向量衡量兴趣相似度,实现个性化推荐。

  • 企业知识库检索:提升非结构化文档的可用性和搜索效率。

二、Xinference注册向量模型

在这里插入图片描述

三、接入Qdrant并实现语义问答

3.1. 项目依赖配置

   <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>
        <!--sensitive-word-->
        <dependency>
            <groupId>com.github.houbb</groupId>
            <artifactId>sensitive-word</artifactId>
            <version>0.21.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

3.2. Qdrant数据库安装

可以基于docker进行安装:

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

3.3. 注册向量模型和向量数据库

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(proxyBeanMethods = false)
public class EmbeddingModelConfig {
    @Bean
    public EmbeddingModel embeddingModel() {
        return OpenAiEmbeddingModel.builder()
                .apiKey("1")
                .modelName("bge-large-zh-v1.5")
                .baseUrl("http://192.168.1.13:9997/v1")
                .build();
    }

    @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();
    }
}

此处注册的模型是直接对接Xinference的向量模型,api_key可以任意填写。指定模型名称和baseUrl即可。

3.4. 问答式语义检索API

import dev.langchain4j.data.segment.TextSegment;
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 dev.langchain4j.model.embedding.EmbeddingModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import dev.langchain4j.data.embedding.Embedding;

import static dev.langchain4j.store.embedding.filter.MetadataFilterBuilder.metadataKey;
@RestController
@Slf4j
public class EmbeddingController {
    @Resource
    private EmbeddingModel embeddingModel;
    @Resource
    private QdrantClient qdrantClient;
    @Resource
    private EmbeddingStore<TextSegment> embeddingStore;

    /**
     * 文本向量化测试,看看形成向量后的文本
     * 
     */
    @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
     */
    @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", "zxl");
        segment1.metadata().put("price", "50");
        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("zxl"))
                .maxResults(1)
                .build();

        EmbeddingSearchResult<TextSegment> searchResult = embeddingStore.search(embeddingSearchRequest);

        System.out.println(searchResult.matches().get(0).embedded().text());
    }
}


四、总结

LangChain4J为Java开发者打开了大模型生态的一扇窗,特别是在语义搜索与RAG问答场景中,通过接入向量数据库如FAISS或Milvus,可以高效实现文档理解与语义检索功能。本文不仅解析了LangChain4J在向量数据库接入中的架构设计,也通过完整代码案例展示了其在Java后端中的落地方式。未来,随着本地模型与嵌入技术的发展,Java + LangChain4J + 向量数据库将成为企业级AI服务的强有力支撑。

### 使用 LangChain4j 调用多模态大模型实现音频处理 #### 音频数据预处理 为了有效利用多模态大模型处理音频,首先需要对音频文件进行必要的预处理操作。LangChain 提供了丰富的工具集用于准备不同类型的输入数据[^1]。对于音频而言,通常涉及的操作包括但不限于: - 将原始音频转换成适合模型接收的形式; - 对音频信号执行特征提取,比如梅尔频率倒谱系数(MFCCs)或其他表示方法。 ```java // 假设有一个名为AudioPreprocessor的类负责音频预处理工作 AudioPreprocessor preprocessor = new AudioPreprocessor(); File audioFile = new File("path/to/audio/file.wav"); float[] processedData = preprocessor.process(audioFile); ``` #### 模型加载配置 接着,在准备好待分析的数据之后,下一步就是初始化并设置好要使用的多模态大模型实例。通过 LangChain 的插件机制可以轻松集成外部提供的高质量语音识别或情感检测等特定功能的大规模预训练模型。 ```java import com.langchain.model.MultiModalModel; MultiModalModel model = MultiModalModel.load("audio-processing-model-name", "model-version"); model.configure(new HashMap<String, Object>() {{ put("device", "cuda"); // 或者 "cpu" }}); ``` #### 执行推理过程 完成上述准备工作后就可以调用 `predict` 方法来进行实际预测任务了。这里假设我们已经得到了经过适当变换后的音频特征向量作为输入给定至模型中去获取相应的输出结果。 ```java Map<String, Float[]> predictionResult = model.predict(processedData); for (String key : predictionResult.keySet()) { System.out.println(key + ": " + Arrays.toString(predictionResult.get(key))); } ``` 以上展示了基于 Java 平台下的 LangChain 库如何简单快捷地接入强大的多模态能力来解决具体的业务需求——即针对音频内容的理解解析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值