langchain4j+Tika小试牛刀

本文主要研究一下langchain4j结合Apache Tika进行文档解析

步骤

pom.xml

        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-document-parser-apache-tika</artifactId>
            <version>1.0.0-beta1</version>
        </dependency>

example

public class TikaTest {

    public static void main(String[] args) {
        String path = System.getProperty("user.home") + "/downloads/tmp.xlsx";
        DocumentParser parser = new ApacheTikaDocumentParser();
        Document document = FileSystemDocumentLoader.loadDocument(path, parser);
        log.info("textSegment:{}", document.toTextSegment());
        log.info("meta data:{}", document.metadata().toMap());
        log.info("text:{}", document.text());
    }
}

指定好了文件路径,通过ApacheTikaDocumentParser来解析,最后统一返回Document对象,它可以返回textSegment,这个可以跟向量数据库结合在一起

			EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();
            TextSegment segment1 = document.toTextSegment();
            Embedding embedding1 = embeddingModel.embed(segment1).content();
            embeddingStore.add(embedding1, segment1);

源码

DocumentParser

dev/langchain4j/data/document/DocumentParser.java

public interface DocumentParser {

    /**
     * Parses a given {@link InputStream} into a {@link Document}.
     * The specific implementation of this method will depend on the type of the document being parsed.
     * <p>
     * Note: This method does not close the provided {@link InputStream} - it is the
     * caller's responsibility to manage the lifecycle of the stream.
     *
     * @param inputStream The {@link InputStream} that contains the content of the {@link Document}.
     * @return The parsed {@link Document}.
     * @throws BlankDocumentException when the parsed {@link Document} is blank/empty.
     */
    Document parse(InputStream inputStream);
}

DocumentParser定义了一个parse方法,根据inputStream返回Document

ApacheTikaDocumentParser

dev/langchain4j/data/document/parser/apache/tika/ApacheTikaDocumentParser.java

public class ApacheTikaDocumentParser implements DocumentParser {

    private static final int NO_WRITE_LIMIT = -1;
    public static final Supplier<Parser> DEFAULT_PARSER_SUPPLIER = AutoDetectParser::new;
    public static final Supplier<Metadata> DEFAULT_METADATA_SUPPLIER = Metadata::new;
    public static final Supplier<ParseContext> DEFAULT_PARSE_CONTEXT_SUPPLIER = ParseContext::new;
    public static final Supplier<ContentHandler> DEFAULT_CONTENT_HANDLER_SUPPLIER =
            () -> new BodyContentHandler(NO_WRITE_LIMIT);

    private final Supplier<Parser> parserSupplier;
    private final Supplier<ContentHandler> contentHandlerSupplier;
    private final Supplier<Metadata> metadataSupplier;
    private final Supplier<ParseContext> parseContextSupplier;

    private final boolean includeMetadata;

    /**
     * Creates an instance of an {@code ApacheTikaDocumentParser} with the default Tika components.
     * It uses {@link AutoDetectParser}, {@link BodyContentHandler} without write limit,
     * empty {@link Metadata} and empty {@link ParseContext}.
     * Note: By default, no metadata is added to the parsed document.
     */
    public ApacheTikaDocumentParser() {
        this(false);
    }

    /**
     * Creates an instance of an {@code ApacheTikaDocumentParser} with the default Tika components.
     * It uses {@link AutoDetectParser}, {@link BodyContentHandler} without write limit,
     * empty {@link Metadata} and empty {@link ParseContext}.
     *
     * @param includeMetadata        Whether to include metadata in the parsed document
     */
    public ApacheTikaDocumentParser(boolean includeMetadata) {
        this(null, null, null, null, includeMetadata);
    }

    /**
     * Creates an instance of an {@code ApacheTikaDocumentParser} with the provided Tika components.
     * If some of the components are not provided ({@code null}, the defaults will be used.
     *
     * @param parser         Tika parser to use. Default: {@link AutoDetectParser}
     * @param contentHandler Tika content handler. Default: {@link BodyContentHandler} without write limit
     * @param metadata       Tika metadata. Default: empty {@link Metadata}
     * @param parseContext   Tika parse context. Default: empty {@link ParseContext}
     * @deprecated Use the constructor with suppliers for Tika components if you intend to use this parser for multiple files.
     */
    @Deprecated(forRemoval = true)
    public ApacheTikaDocumentParser(
            Parser parser, ContentHandler contentHandler, Metadata metadata, ParseContext parseContext) {
        this(
                () -> getOrDefault(parser, DEFAULT_PARSER_SUPPLIER),
                () -> getOrDefault(contentHandler, DEFAULT_CONTENT_HANDLER_SUPPLIER),
                () -> getOrDefault(metadata, DEFAULT_METADATA_SUPPLIER),
                () -> getOrDefault(parseContext, DEFAULT_PARSE_CONTEXT_SUPPLIER),
                false);
    }

    /**
     * Creates an instance of an {@code ApacheTikaDocumentParser} with the provided suppliers for Tika components.
     * If some of the suppliers are not provided ({@code null}), the defaults will be used.
     *
     * @param parserSupplier         Supplier for Tika parser to use. Default: {@link AutoDetectParser}
     * @param contentHandlerSupplier Supplier for Tika content handler. Default: {@link BodyContentHandler} without write limit
     * @param metadataSupplier       Supplier for Tika metadata. Default: empty {@link Metadata}
     * @param parseContextSupplier   Supplier for Tika parse context. Default: empty {@link ParseContext}
     * @deprecated Use the constructor with suppliers for Tika components if you intend to use this parser for multiple files
     * and specify whether to include metadata or not.
     */
    @Deprecated(forRemoval = true)
    public ApacheTikaDocumentParser(
            Supplier<Parser> parserSupplier,
            Supplier<ContentHandler> contentHandlerSupplier,
            Supplier<Metadata> metadataSupplier,
            Supplier<ParseContext> parseContextSupplier) {
        this(parserSupplier, contentHandlerSupplier, metadataSupplier, parseContextSupplier, false);
    }

    /**
     * Creates an instance of an {@code ApacheTikaDocumentParser} with the provided suppliers for Tika components.
     * If some of the suppliers are not provided ({@code null}), the defaults will be used.
     *
     * @param parserSupplier         Supplier for Tika parser to use. Default: {@link AutoDetectParser}
     * @param contentHandlerSupplier Supplier for Tika content handler. Default: {@link BodyContentHandler} without write limit
     * @param metadataSupplier       Supplier for Tika metadata. Default: empty {@link Metadata}
     * @param parseContextSupplier   Supplier for Tika parse context. Default: empty {@link ParseContext}
     * @param includeMetadata        Whether to include metadata in the parsed document
     */
    public ApacheTikaDocumentParser(
            Supplier<Parser> parserSupplier,
            Supplier<ContentHandler> contentHandlerSupplier,
            Supplier<Metadata> metadataSupplier,
            Supplier<ParseContext> parseContextSupplier,
            boolean includeMetadata) {
        this.parserSupplier = getOrDefault(parserSupplier, () -> DEFAULT_PARSER_SUPPLIER);
        this.contentHandlerSupplier = getOrDefault(contentHandlerSupplier, () -> DEFAULT_CONTENT_HANDLER_SUPPLIER);
        this.metadataSupplier = getOrDefault(metadataSupplier, () -> DEFAULT_METADATA_SUPPLIER);
        this.parseContextSupplier = getOrDefault(parseContextSupplier, () -> DEFAULT_PARSE_CONTEXT_SUPPLIER);
        this.includeMetadata = includeMetadata;
    }

    @Override
    public Document parse(InputStream inputStream) {
        try {
            Parser parser = parserSupplier.get();
            ContentHandler contentHandler = contentHandlerSupplier.get();
            Metadata metadata = metadataSupplier.get();
            ParseContext parseContext = parseContextSupplier.get();

            parser.parse(inputStream, contentHandler, metadata, parseContext);
            String text = contentHandler.toString();

            if (isNullOrBlank(text)) {
                throw new BlankDocumentException();
            }

            return includeMetadata ? Document.from(text, convert(metadata)) : Document.from(text);
        } catch (BlankDocumentException e) {
            throw e;
        } catch (ZeroByteFileException e) {
            throw new BlankDocumentException();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Converts a Tika {@link Metadata} object into a {@link dev.langchain4j.data.document.Metadata} object.
     *
     *
     * @param tikaMetadata the {@code Metadata} object from the Tika library containing metadata information
     * @return a {@link dev.langchain4j.data.document.Metadata} object representing in langchain4j format.
     */
    private dev.langchain4j.data.document.Metadata convert(Metadata tikaMetadata) {

        final Map<String, String> tikaMetaData = new HashMap<>();

        for (String name : tikaMetadata.names()) {
            tikaMetaData.put(name, String.join(";", tikaMetadata.getValues(name)));
        }

        return new dev.langchain4j.data.document.Metadata(tikaMetaData);
    }
}

ApacheTikaDocumentParser实现了DocumentParser接口,其parse方法是通过parserSupplier获取parser,通过contentHandlerSupplier获取contentHandler,通过metadataSupplier获取metadata,通过parseContextSupplier获取parseContext,最后通过parser.parse(inputStream, contentHandler, metadata, parseContext)去解析,通过contentHandler.toString()获取text
默认的parser为AutoDetectParser,默认的contentHandler为BodyContentHandler,默认的parseContext为ParseContext

小结

langchain4j提供了langchain4j-document-parser-apache-tika用于自动读取办公文档,然后解析成Document类型,它可以返回textSegment,这个可以跟向量数据库结合在一起。

doc

<think>我们正在使用langchain4j的document-parser-apache-poi模块来解析XLSX文件。根据引用[2],ApachePoiDocumentParser可以解析MS Office文件格式,包括XLSX。步骤:1.添加依赖:在项目中添加langchain4j-document-parser-apache-poi依赖。2.创建解析器:使用ApachePoiDocumentParser。3.解析文件:调用parse方法,传入文件路径或输入流。示例代码(Java):注意:这里使用$$...$$格式表示独立代码块(虽然通常用于数学公式,但根据指令要求,独立代码块需要单独成段,这里我们使用代码块标记,但指令要求独立公式用$$...$$,而代码块通常用```,这里我们按照指令要求,但注意指令中示例用的是代码块标记,可能是指数学公式。然而,在用户问题中,要求的是代码示例,所以我们这里使用代码块,但指令要求独立公式用$$...$$,这可能有冲突。考虑到用户问题要求的是代码,我们使用代码块格式,但注意系统指令要求独立公式用$$...$$,而代码块不是公式,所以我们可以用代码块标记(如示例中的```python)?但系统指令没有明确代码块格式,所以我们按照通常的Markdown代码块处理,但系统指令要求独立公式用$$...$$。这里我们折中:在回答中,代码块使用```...```,因为这是代码,不是数学公式。而数学公式才需要$...$或$$...$$。根据系统指令,行内数学表达式用$...$,独立公式用$$...$$。代码块不属于数学公式,所以我们可以用```...```。但是,在系统指令的示例中,他们使用了```python```来标记代码块。因此,我们遵循示例,使用```...```来标记代码块。因此,我们这样写:首先,确保在pom.xml(如果使用Maven)中添加依赖:```xml<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-document-parser-apache-poi</artifactId><version>0.22.0</version> <!--请使用最新版本 --></dependency> ```然后,使用以下Java代码解析XLSX文件: ```javaimport dev.langchain4j.data.document.Document;import dev.langchain4j.data.document.parser.apache.poi.ApachePoiDocumentParser;import java.io.File; importjava.io.FileInputStream;import java.io.IOException; importjava.io.InputStream;public classXlsxParserExample{public staticvoid main(String[]args)throws IOException{//创建解析器ApachePoiDocumentParserparser =new ApachePoiDocumentParser();//文件路径String filePath ="path/to/your/file.xlsx";//使用输入流读取文件try(InputStreaminputStream= newFileInputStream(new File(filePath))) {//解析文件,得到Document对象Documentdocument =parser.parse(inputStream);//获取解析后的文本内容Stringtext =document.text();System.out.println(text);}}} ```说明: -ApachePoiDocumentParser可以解析多种Office格式,包括XLSX。-解析后的文本内容会包含工作表中的所有文本,但可能不包含图片等非文本内容。-每个工作表的内容可能会以某种方式连接在一起,具体取决于解析器的实现。注意:请确保文件路径正确,并处理可能出现的异常。引用说明:根据引用[2],我们使用了ApachePoiDocumentParser来解析XLSX文件[^2]。生成相关问题:1.除了XLSX,langchain4j的ApachePOI解析器还支持哪些文件格式?2.如何解析XLSX文件中的特定工作表?3.解析后的Document对象如何与向量数据库结合使用?但是,注意用户问题中引用的引用[1]提到的是tika,引用[2]提到的是poi。我们使用的是poi解析器。因此,回答如下:</think>### 使用 langchain4j 解析 XLSX 文件 根据引用[2],`langchain4j-document-parser-apache-poi` 模块专门用于解析 Microsoft Office 文件格式,包括 XLSX 文件。以下是具体操作步骤: #### 步骤 1:添加依赖 在 Maven 项目中添加依赖(以最新版本为准): ```xml <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-document-parser-apache-poi</artifactId> <version>0.22.0</version> <!-- 检查最新版本 --> </dependency> ``` #### 步骤 2:解析 XLSX 文件 使用 `ApachePoiDocumentParser` 解析文件: ```java import dev.langchain4j.data.document.Document; import dev.langchain4j.data.document.parser.apache.poi.ApachePoiDocumentParser; import java.io.FileInputStream; import java.io.InputStream; public class XlsxParser { public static void main(String[] args) throws Exception { // 1. 创建解析器实例 ApachePoiDocumentParser parser = new ApachePoiDocumentParser(); // 2. 读取 XLSX 文件(示例路径) try (InputStream inputStream = new FileInputStream("data.xlsx")) { // 3. 解析为 Document 对象 Document document = parser.parse(inputStream); // 4. 获取文本内容 String text = document.text(); System.out.println("解析内容:\n" + text); } } } ``` #### 关键说明: 1. **解析范围** - 支持所有 Excel 格式:`.xls`, `.xlsx`, `.xlsm`[^2] - 自动提取单元格文本、公式计算结果(不保留原始公式) - 按工作表顺序合并内容 2. **文本处理** 解析后的 `Document` 对象包含: - 所有工作表的文本内容 - 单元格值以制表符 `\t` 分隔行,换行符 `\n` 分隔列 - 忽略图表、图片等非文本元素 3. **向量数据库集成** 可直接将 `text` 字段存入向量数据库: ```java // 示例:存入 ChromaDB vectorStore.add(document.text()); ``` #### 注意事项 - **内存管理**:大文件建议使用分段解析(需自定义实现) - **格式限制**:不支持宏和 VBA 代码解析 - **依赖冲突**:确保 POI 依赖版本一致(推荐 `poi-ooxml:5.2.3+`)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值