AI大模型综合(四)langchain4j 解析PDF文档

目录

一、langchain4j如何解析PDF文档

二、向量数据库

三、构建PDF文件摘要总结功能


一、langchain4j如何解析PDF文档

1.1 添加依赖

复制代码
<!-- Source: https://mvnrepository.com/artifact/dev.langchain4j/langchain4j-document-parser-apache-pdfbox -->
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-document-parser-apache-pdfbox</artifactId>
    <version>1.10.0-beta18</version>
    <scope>compile</scope>
</dependency>

1.2、 写一段测试代码

java 复制代码
package com.ai.langgraph4j.codehelper2.pdfbox;

import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.DocumentParser;
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
import static org.bsc.langgraph4j.agentexecutor.AgentExecutor.log;

public class PDFBoxTest {
    public static void main(String[] args) throws Exception {
        String path = "/Users/apple/Documents/AI/langchain4jAIdemo/pdf/5.成绩登记表模板(系统中打印).pdf";
        DocumentParser parser = new ApachePdfBoxDocumentParser();
        Document document = FileSystemDocumentLoader.loadDocument(path, parser);
        log.info("textSegment:{}", document.toTextSegment());//返回textSegment,这个可以跟向量数据库结合在一起
        log.info("meta data:{}", document.metadata().toMap());
        log.info("text:{}", document.text());
    }
}

二、向量数据库

2.1 向量数据库

在传统数据库中,精确查询匹配,检索通常依赖于关键词、精确匹配或范围查询。

大模型场景中,在自然语言处理、图像识别等 AI 场景中,更需要的是语义相似度检索,即"查找与某个内容在语义上最接近的内容"。这正是向量数据库的核心用途。比如,基于相似度搜索(如余弦相似度),返回近似匹配结果(如"视觉相似的图片"),容忍容错。‌‌

2.2 什么是向量

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

例子: vector = [-0.049977552, -0.022875419, 0.028773291, -0.058595255, 0.009328811, 0.025546558, -0.022599563, 0.004922383, 0.031749923, -0.014742963, -0.0051747668, -0.0023935703, 0.01949408, 0.053132694, 0.07271755, -0.0037443836]

2.3 如何实现语义检索

在语义空间中,++相似的内容对应的向量距离会更近++,从而实现语义检索。此功能基于欧氏距离和余弦相似度等度量,在高维空间中查找与给定查询向量接近的向量。

2.4 核心功能

(1)向量存储 :支持大量高维向量的高效存储,通常采用列式存储或专用压缩格式以减少空间占用。

(2)相似性搜索 :通过近似最近邻(ANN, Approximate Nearest Neighbor)算法(如HNSW、IVF、FAISS等)快速检索与查询向量最相似的数据。

(3)索引优化:构建空间分区或图结构索引(如Hierarchical Navigable Small World, HNSW),平衡搜索速度与精度。

(4)元数据支持:可关联向量与文本、标签等元数据,支持混合查询(如"查找与向量A相似且标签为'猫'的图片")。

2.5 与传统数据库的区别

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

2.6 那些常用的向量数据库

  • 主流开源向量数据库(免费可自托管),这些适合技术团队自主部署,灵活控制数据:

‌Milvus‌:处理海量数据(如十亿级向量),支持图像、文本搜索,社区活跃。‌‌
‌Chroma‌:轻量级,适合快速开发原型(如聊天机器人),集成简单。‌‌‌‌
‌Qdrant‌:平衡搜索速度与精度,支持实时更新,适合推荐系统。‌‌‌‌
‌Weaviate‌:结合图数据库,擅长语义搜索(如问答系统),支持多模态数据。‌‌‌‌
‌Faiss‌:Meta 开发,适合学术研究,支持 GPU 加速但配置复杂。‌‌

  • 托管服务向量数据库(免运维)适合资源有限的团队,开箱即用:

‌Pinecone‌:最快响应(亚秒级),自动扩展,适合生产级 AI 应用。‌‌
‌Elasticsearch‌:同时支持全文和向量搜索,适合已有 Elastic 生态的企业。‌‌‌‌
‌SingleStore‌:唯一融合 SQL 和向量搜索,适合实时分析(如金融风控)。‌‌
‌MongoDB‌:文档数据库 + 向量搜索,适合混合数据场景。‌‌‌‌

2.7 向量嵌入(Embedding)

向量嵌入(Embedding)是将文本转换为数值向量的技术,是 RAG 和语义搜索的基础

文本到向量的转换

复制代码
示例1:
java 复制代码
InMemoryEmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();

        EmbeddingModel embeddingModel = new BgeSmallEnV15QuantizedEmbeddingModel();

        TextSegment segment1 = TextSegment.from("I like football.");
        //将单个文本转换为向量
        Embedding embedding1 = embeddingModel.embed(segment1).content();
        System.out.println("向量维度: " + embedding1.dimension());  //384
        System.out.println("向量值: " + Arrays.toString(embedding1.vector()));//向量值: [-7.621452E-5, -0.0026724, 0.0048467875, -0.066098645, 0.04864948, 0.00899909, 0.07489078, 0.019991739, 0.10673115, -0.036116153, -0.07130266, -0.07919503,...]
        //计算余弦相似度
        System.out.println("计算余弦相似度: " + CosineSimilarity.between(embedding1, embedding1));//0.9999999999999999
复制代码
示例2:https://github.com/langchain4j/langchain4j-examples/blob/main/other-examples/src/main/java/embedding/store/InMemoryEmbeddingStoreExample.java
java 复制代码
package com.ai.langgraph4j.codehelper2.pdfbox;

import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.onnx.bgesmallenv15q.BgeSmallEnV15QuantizedEmbeddingModel;
//import dev.langchain4j.model.embedding.onnx.allminilml6v2.AllMiniLmL6V2EmbeddingModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingMatch;
import dev.langchain4j.store.embedding.EmbeddingSearchRequest;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;

import java.util.List;

public class InMemoryEmbeddingStoreExample {
    public static void main(String[] args) {

        InMemoryEmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();

        EmbeddingModel embeddingModel = new BgeSmallEnV15QuantizedEmbeddingModel();

        TextSegment segment1 = TextSegment.from("I like football.");
        Embedding embedding1 = embeddingModel.embed(segment1).content();
        embeddingStore.add(embedding1, segment1);

        TextSegment segment2 = TextSegment.from("The weather is good today.");
        Embedding embedding2 = embeddingModel.embed(segment2).content();
        embeddingStore.add(embedding2, segment2);

        Embedding queryEmbedding = embeddingModel.embed("What is your favourite sport?").content();
        EmbeddingSearchRequest embeddingSearchRequest = EmbeddingSearchRequest.builder()
                .queryEmbedding(queryEmbedding)
                .maxResults(1)
                .build();
        List<EmbeddingMatch<TextSegment>> matches = embeddingStore.search(embeddingSearchRequest).matches();
        EmbeddingMatch<TextSegment> embeddingMatch = matches.get(0);

        System.out.println(embeddingMatch.score()); // 0.8235980955180371
        System.out.println(embeddingMatch.embedded().text()); // I like football.

        // In-memory embedding store can be serialized and deserialized to/from JSON
        // String serializedStore = embeddingStore.serializeToJson();
        // InMemoryEmbeddingStore<TextSegment> deserializedStore = InMemoryEmbeddingStore.fromJson(serializedStore);

        // In-memory embedding store can be serialized and deserialized to/from file
        // String filePath = "/home/me/embedding.store";
        // embeddingStore.serializeToFile(filePath);
        // InMemoryEmbeddingStore<TextSegment> deserializedStore = InMemoryEmbeddingStore.fromFile(filePath);
    }
}

2.8 Embedding 模型

方法1: 用于开发调试 BgeSmallEnV15QuantizedEmbeddingModel

注: 只需要添加依赖即可

java 复制代码
public static void main(String[] args) {
        // 1. 创建嵌入模型
        EmbeddingModel embeddingModel = new BgeSmallEnV15QuantizedEmbeddingModel();
//        EmbeddingModel embeddingModel = new BgeSmallZhEmbeddingModel();


        // 2. 创建内存向量数据库
        EmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();

        // 3. 准备批量文档片段
        List<TextSegment> segments = List.of(
                TextSegment.from("Java 是一种面向对象的编程语言"),
                TextSegment.from("Python 是一种简洁易学的编程语言"),
                TextSegment.from("JavaScript 主要用于 Web 开发"),
                TextSegment.from("机器学习是人工智能的一个分支")
        );

        // 4. 嵌入并存储文档片段
        for (TextSegment segment : segments) {
            Embedding embedding = embeddingModel.embed(segment).content();
            embeddingStore.add(embedding, segment);
        }

        // 5. 搜索
        String query = "什么编程语言适合 Web?";
        Embedding queryEmbedding = embeddingModel.embed(query).content();
        EmbeddingSearchRequest searchRequest = EmbeddingSearchRequest.builder().maxResults(1).minScore(Double.valueOf("0.5")).queryEmbedding(queryEmbedding).build();
        // 6. 输出结果
        EmbeddingSearchResult searchResult = embeddingStore.search(searchRequest);
        searchResult.matches().forEach(embedding -> {
            System.out.println(embedding.toString());
        });
        List<EmbeddingMatch<ImageCacher.Embedded>>matches = searchResult.matches();
        System.out.println("查询: " + query);
        System.out.println("\n最相关的文档:");
        for (EmbeddingMatch<ImageCacher.Embedded> match : matches) {
            //没有语句,是语句的向量
            System.out.printf("相似度: %.3f - %s\n", match.score(), match.embedding().toString());
            System.out.println( match.toString());// EmbeddingMatch { score = 0.907476111694336, embedded = TextSegment { text = "JavaScript 主要用于 Web 开发" metadata = {} }, embeddingId = 5215685a-5715-4634-9c44-72be8206e4a3, embedding = Embedding
//            String information = match.embedded().text();//报错,使用不了
//            System.out.println( information);

        }

        List<EmbeddingMatch<TextSegment>>matches2 = searchResult.matches();
        System.out.println("查询: " + query);
        System.out.println("\n最相关的文档:");
        for (EmbeddingMatch<TextSegment> match : matches2) {
            //没有语句,是语句的向量
            System.out.printf("相似度: %.3f - %s\n", match.score(), match.embedded().text());

        }
    }

控制台输出结果:

注:

// 嵌入单个文本

Embedding embedding = model.embed("Hello World").content();

// 批量嵌入

List<TextSegment> segments = List.of(

TextSegment.from("文本1"),

TextSegment.from("文本2"),

TextSegment.from("文本3")

);

List<Embedding> embeddings = model.embedAll(segments).content();

三、构建PDF文件摘要总结功能

注: 很多PDF大量应用的场景,比如 专业论文等场景都可以用到。

相关推荐
m5655bj2 小时前
使用 C# 对比两个 PDF 文档的差异
pdf·c#·visual studio
WXDcsdn2 小时前
Windows无法使用Microsoft to PDF输出PDF文件
windows·pdf·电脑·it运维
Yqlqlql4 小时前
基于 Python+PySide6 开发的本地复合文件工具:图片转 PDF+PDF 转 Word 双功能
pdf
softshow10265 小时前
html2canvas + jspdf实现页面导出成pdf
开发语言·javascript·pdf
木叶子---5 小时前
pdf生成排查记录与解决方案
java·pdf
M宝可梦6 小时前
I-JEPA CVPR2023 LeCun所说的world model和视频生成模型是一回事儿吗
人工智能·大语言模型·世界模型·lecun·jepa
开开心心_Every6 小时前
文件数量统计工具:支持多层文件夹数量统计
游戏·微信·pdf·excel·语音识别·swift·lisp
萧技电创EIIA8 小时前
node-red导出图表PDF
pdf
小程故事多_8020 小时前
攻克RAG系统最后一公里 图文混排PDF解析的挑战与实战方案
人工智能·架构·pdf·aigc