游乐游手机版
首页/AI热点日报/热点详情

企业AI知识库Word解析痛点 95%准确率100%开源

类型:热点整理2026-07-19
针对企业AI知识库建设中Word文档解析难题,基于ApacheTika和POI开源组件,提出创新解决方案。通过差异化处理策略与通用算法,精准还原复杂表格合并单元格,确保转换后HTML与源文件视觉结构高度一致,准确率95%,实现100%开源。

在大模型与RAG技术高速迭代的当下,企业AI知识库建设已成为落地AI的核心战场。而文件解析,则是所有参与其中的开发者都绕不开的“硬骨头”。

本文围绕开发TorchV AIS企业级AI知识库产品时遇到的Word解析难题展开,分享如何将Word文档(.doc.docx)高效、准确地转换为Web友好格式(Markdown/HTML)。依托Apache Tika和POI这两大开源组件,我们提出了一套创新的、具备行业领先水平的解决方案——通过一套完全基于表格结构、无需硬编码的通用算法,完美解决了复杂表格的解析问题,确保转换后的HTML与源文件在视觉和结构上高度一致。

一、前言

大模型与RAG(检索增强生成)技术加速发展,企业AI知识库建设已成为AI落地的关键领域。而文件解析是所有参与企业AI知识库开发的开发者都必须面对的难题。

本文将结合开发TorchV AIS企业级AI知识库产品过程中碰到的Word解析问题,分享如何将Word文档(.doc.docx)高效、准确地转换为Web友好格式(Markdown/HTML)的优化方案。结合当前的实际解决方案(基于Apache Tika/POI),详细阐述一种创新的、具备行业领先水平的方案。通过实现一套完全基于表格结构、无需硬编码的通用算法,完美解决了.doc.docx格式中的复杂表格解析问题,确保转换后的HTML与源文件在视觉和结构上高度一致。

二、Word文档解析:企业AI知识库的隐形瓶颈?

根据调研与实践经验:

1、两种文件格式,两种世界

  • .docx格式:基于Office Open XML (OOXML) 标准,本质上是一个ZIP压缩包,内部包含描述文档结构的XML文件。表格的合并信息(如gridSpanvMerge)在XML中有明确定义,解析相对规范
  • .doc格式:是微软私有的二进制格式,内部结构复杂、缺乏公开的完整文档。通过POI的HWPFDocument模块进行解析时,获取到的表格信息非常原始,几乎不直接提供合并单元格的完整信息

2、传统工具的局限

  • • 大多数转换工具在处理.doc格式时,无法准确还原rowspancolspan
  • • 它们通常会把合并单元格下的空单元格渲染成独立的,导致表格“散架”。
  • • 为了绕过难题,一些方案采取“扁平化”策略,即复制合并单元格的内容来填充所有被合并的单元格,但这破坏了表格的原始结构。

3、企业现状

  • • 90%的企业仍然有大量Word格式文档需要导入企业AI知识库,特别是金融、政府领域的客户对老旧的doc格式文件有强烈需求。
  • 传统解析方案的表格准确率普遍较低,尤其在处理合并单元格时。
  • 表格信息的丢失或错误直接导致企业AI知识库系统对业务关键信息的理解偏差,进而使大模型回答准确度大幅下降。
  • 现有开源工具要么功能简陋,要么商业化程度过高,开发者缺乏可控的解决方案。

三、企业AI知识库的诉求

对于企业AI知识库的服务商而言,Word文档解析是一个需要全面综合考量的问题。主要方向包括:

1、解析格式需同时支持doc和docx两种格式

现有的许多开源工具、商业产品在处理Word格式时,对doc格式的解析都感到棘手。这个上世纪微软遗留的产物让开发者恨得牙痒痒,不亚于十年前开发者解决IE6的各种兼容性问题。然而在客户中,特别是金融、政府领域的客户,依然存在大量老旧的doc格式文件,这些文件仍是企业的数字资产。在AI时代,它们都需要搭上这趟高速列车,将数据装载进入企业AI知识库,发挥知识的价值。

2、Word文档能够解析提取为Markdown格式,提取的元素包括:文档Header、表格、图片

企业AI知识库最关心的是“知识的结构化”。解析文档的目标不只是转换文本,更是为了“识别并提取有价值的知识结构”。因此:

  • • 文档头信息(如标题、章节、层级结构)需准确提取并转化为Markdown标题(###等);
  • • 段落、列表、加粗/斜体等格式也应保留,确保语义清晰、上下文连贯;
  • • 引用和脚注等内容建议标准化处理,以支持企业在QA和文档搜索场景中进行深度挖掘。

3、表格内容需用HTML呈现,解决合并单元格(rowspan/colspan)的问题

Markdown表格天生不支持合并单元格(rowspan/colspan),而这正是企业文档中极为常见的复杂表格结构(如绩效考核表、组织结构图、流程图表等):

  • • 采用HTML格式解析表格内容,能完整保留表格的合并信息;
  • • 这样在知识回显、检索结果展示以及大模型上下文学习时,能确保原貌还原;
  • • 可为后续编辑器的“所见即所得”功能打下良好基础。

TorchV AIS企业AI知识库提供了强大的富文本编辑器,对于Word中的格式内容,尤其是表格内容,需要解析成标准的HTML格式进行展现,以丰富企业知识的二次加工创作。


4、图片正确提取,并且图片与文档内容的上下位置正确

Word中的图文混排结构(例如图解流程、插图说明等)是许多专业知识文档的重要组成部分:

  • • 图片应以URL链接保留,确保知识库中可以复现图文内容;
  • • 同时还要保持图片在文档中的原始顺序和上下文位置,不能打乱段落与图片的对应关系;
  • • 若有Alt文本或说明文字,也需提取出来作为附加语义数据。
  • • 必要时可灵活利用外部工具(OCR/多模态等)对图片进行深度理解,以扩展当前图片的语义,提升问答精准度。

5、性能及成本考虑

不同企业对解析能力的投入存在差异,因此服务端需提供灵活选择:

  • • GPU/CPU双重选择,预算充足的企业可选用GPU模型版本驱动Word文档解析。
  • • 解析的性能效率,包括高效转换以及向量嵌入的转化。需综合考虑不同成本下的解析效果。

四、TorchV技术实现路径:“预处理+注入”策略

TorchV目前采用Ja va语言开发,在底层技术栈上,对于Word的解析,恰好有两个优秀的开源软件可以利用:

  • • Apache Tika:提供了多种文档解析的统一封装,开发者无需关心底层细节,只需统一调用即可。
  • • Apache POI:能够处理Office套件的文件解析,包括doc、docx格式。

虽然这两个组件在底层技术上已经做得很好,但对于上面第二点(企业AI知识库)的诉求,仍需要手工干预一下,才能解析得到想要的结果。

1、这两个工具在表格处理、图片提取方面,默认策略都不太能满足要求,因此需要做更深层次的定制改动。

2、依赖上述两个组件进行优化,它们在CPU环境下能够快速解析处理,所依赖的服务资源很少。

1. FileMagic:差异化处理策略

对于doc/docx格式,需要从底层做差异处理,两种格式采用完全不同的解析策略,针对不同格式采用不同的解析方案

// 检测文件格式
FileMagic fileMagic = FileMagicUtils.checkMagic(wordFile);
if (fileMagic == FileMagic.UNKNOWN) {
    String suffix = FileUtil.getSuffix(wordFile.getName());
    if (StrUtil.equalsIgnoreCase(suffix, "docx")) {
        fileMagic = FileMagic.OOXML;
    } else if (StrUtil.equalsIgnoreCase(suffix, "doc")) {
        fileMagic = FileMagic.OLE2;
    }
}

log.info("检测到文件格式: {}, 文件: {}", fileMagic, wordFile.getAbsolutePath());

// 根据文件格式选择不同的处理方式
switch (fileMagic) {
    case OOXML -> {
        // DOCX 格式 - 使用自定义表格解析器
        log.info("DOCX格式使用自定义表格解析器");
        transfer = processDocxWithHtmlTable(wordFile, target);
    }
    case OLE2 -> {
        // DOC 格式 - 使用新的HTML表格支持
        transfer = processDocWithHtmlTable(wordFile, target);
    }
    default -> {
        log.warn("不支持的文件格式: {}, 使用默认处理方式", fileMagic);
        // 回退到原始转换
        target = toMarkdown(wordFile, pictures);
        transfer = true;
    }
}

2. DOCX格式处理策略

核心思路:利用DOCX格式的标准化特性,采用“预处理+替换”模式

利用WordTableParser类,单独精准解析docx格式中的所有表格。然后在Tika处理完的Content内容上,做replace替换。

private static boolean processDocxWithHtmlTable(File docxFile, File target) {
    // 1. 预处理阶段:使用WordTableParser精准解析表格
    XWPFDocument document = new XWPFDocument(inputStream);
    WordTableParser wordTableParser = new WordTableParser();
    List customTablesHtmlList = wordTableParser.parseToHtmlList(document);
    
    // 2. 常规解析:使用Tika进行流式解析
    AutoDetectParser parser = new AutoDetectParser();
    parser.parse(parseStream, textHandler, metadata, parseContext);
    
    // 3. 智能替换:用精准的表格HTML替换Tika的粗糙输出
    String finalContent = replaceTablesWithCustomHtmlList(tikaContent, customTablesHtmlList);
}

由于docx格式相对标准,POI在底层为我们封装了非常强大的上层API供开发者调用,能够获取docx中的所有table元素对象,这使得处理表格合并时更加方便。

public class WordTableParser {
    
    private final CellMergeAnalyzer cellMergeAnalyzer;
    private final HtmlTableBuilder htmlTableBuilder;
    
    public WordTableParser() {
        this.cellMergeAnalyzer = new CellMergeAnalyzer();
        this.htmlTableBuilder = new HtmlTableBuilder();
    }
    
    public WordTableParser(CellMergeAnalyzer cellMergeAnalyzer, HtmlTableBuilder htmlTableBuilder) {
        this.cellMergeAnalyzer = cellMergeAnalyzer;
        this.htmlTableBuilder = htmlTableBuilder;
    }
   
   /**
     * 解析 Word 文档中的所有表格为 HTML
     */
    public String parseToHtml(XWPFDocument document) {
      // 拿到所有table
        List tables = document.getTables();
        log.info("开始解析Word表格,共 {} 个表格", tables.size());
        
        StringBuilder html = new StringBuilder();
        for (int i = 0; i < tables.size(); i++) {
            XWPFTable table = tables.get(i);
            log.info("解析第 {} 个表格,包含 {} 行", i + 1, table.getRows().size());
            
            html.append(parseTableToHtml(table));
            
            if (i < tables.size() - 1) {
                html.append("

\n"); } } return html.toString(); } // more.... }

在处理docx格式时,我们抽象了一个CellMergeAnalyzer来处理表格合并的情况。

3. DOC格式处理策略

核心思路:直接在解析过程中注入表格处理逻辑

扩展Tika下的Handler模块,单独处理doc格式的文件。

private static boolean processDocWithHtmlTable(File docFile, File target) {
    // 使用专门的DOC内容处理器
    DocMarkdownWithHtmlTableContentHandler handler = new DocMarkdownWithHtmlTableContentHandler();
    handler.setCurrentDocument(document);
    
    // 在解析过程中实时应用我们的表格算法
    DocXMarkdownWithHtmlTableContentHandler textHandler =
        new DocXMarkdownWithHtmlTableContentHandler(handler, metadata);
}

doc格式与docx天然不同,几乎可以算作一种新文件类型。对于表格的解析合并内容,差异明显,主要体现在提取的Table元素并不能很好地获取单元格合并信息,需要一套通用的合并单元格识别算法

DocumentTableParser中实现了完全基于表格结构特征的通用算法,不依赖任何具体内容:

1. 数据结构构建

// 构建表格数据矩阵
String[][] cellContents = new String[numRows][];
int[] rowCellCounts = new int[numRows];

2. 列合并检测算法

private static int detectColspanByStructure(int rowIndex, int cellIndex, 
        String[][] cellContents, int[] rowCellCounts, int maxCols) {
    
    int currentRowCells = rowCellCounts[rowIndex];
    
    // 如果当前行只有1个单元格,占满整行
    if (currentRowCells == 1) {
        return maxCols;
    }
    
    // 智能分配列数
    int a verageColspan = maxCols / currentRowCells;
    int remainingCols = maxCols % currentRowCells;
    
    // 最后一个单元格处理剩余空间
    if (cellIndex == currentRowCells - 1 && remainingCols > 0) {
        return a verageColspan + remainingCols;
    }
    
    return a verageColspan > 0 ? a verageColspan : 1;
}

3. 行合并检测算法

private static int detectRowspanByStructure(int rowIndex, int cellIndex, 
        String cellText, String[][] cellContents, int[] rowCellCounts) {
    
    // 检查向下相邻行的对应位置
    int rowspan = 1;
    for (int nextRow = rowIndex + 1; nextRow < cellContents.length; nextRow++) {
        String nextCellText = cellContents[nextRow][cellIndex];
        
        if (nextCellText.trim().isEmpty()) {
            // 进一步验证:检查该行是否有其他内容
            boolean hasContentInRow = false;
            for (int i = 0; i < rowCellCounts[nextRow]; i++) {
                if (!cellContents[nextRow][i].trim().isEmpty()) {
                    hasContentInRow = true;
                    break;
                }
            }
            
            if (hasContentInRow) {
                rowspan++;
            } else {
                break; // 整行为空,不是rowspan
            }
        } else {
            break; // 遇到非空单元格,rowspan结束
        }
    }
    
    return rowspan;
}

4. 智能跳过算法

private static boolean shouldSkipCellByStructure(int rowIndex, int cellIndex, 
        String cellText, String[][] cellContents, int[] rowCellCounts) {
    
    // 向上查找可能的rowspan源
    for (int prevRow = rowIndex - 1; prevRow >= 0; prevRow--) {
        if (cellIndex < rowCellCounts[prevRow]) {
            String prevCellText = cellContents[prevRow][cellIndex];
            
            if (!prevCellText.trim().isEmpty()) {
                // 重新计算该单元格的rowspan
                int calculatedRowspan = calculateRowspanFromPosition(
                    prevRow, cellIndex, cellContents, rowCellCounts);
                
                // 判断是否覆盖到当前行
                if (prevRow + calculatedRowspan > rowIndex) {
                    return true; // 跳过被占用的单元格
                }
            }
        }
    }
    
    return false;
}

五、解析效果验证

通过大语言模型创建了30种不同格式的复杂表格类型,包括上下单元格合并、跨页表格、左右单元格合并等多种复杂情况,验证了doc/docx两种格式。主要表现如下:

  • • ✅ 完美识别rowspancolspan合并单元格
  • • ✅ 准确保留所有表格内容,无丢失现象
  • • ✅ 正确处理跨页表格和复杂嵌套结构
  • • ✅ 支持任意语言和字符集的表格内容
  • • ✅ 在.doc和.docx格式上表现一致(目前doc格式无法提取markdown的header标题)
  • • ✅ 正确提取图片且图片位置正确

在31个复杂表格情况下,对于表格的合并情况:

  • • ✅ 数据无错误,表格内容完全正确的比例:30/31=96.8%
    包含数据完全正确的情况,目前出现6个表格数据无异常,但表格在纵向合并时的表现并不完全一致
  • • ✅ 数据解析异常,错误比率:1/31=3.23%
    在31个复杂表格数据中,出现了解析还原错误,表格数据错位,这种情况在做知识库场景下送给大模型时,会导致数据异常、产生回答幻觉
  • • ✅ 表格完全正确,colspan/rowspan完全无错误的情况:25/31=80.6%
    数据完全一致、表格结构完全一致,100%还原出来的比例。

1、简单的上下合并情况


2、跨页上下单元格合并的情况


3、上下左右单元格合并的情况


4、翻页单元格上下左右合并的情况



5、更复杂的纵向横向表格合并情况


六、100%开源

TorchV的企业级AI知识库系统,是在开源生态的基础上构建的。从创业初期开始,便充分受益于业界开源的各种大语言模型、Embedding模型、Reranker模型、开源组件/中间件等,这些技术的开放极大地推动了行业发展。我们深知开源的价值,也始终秉持开放、共享、共建的理念。

在构建产品的过程中,特别是在Word文档解析这一关键环节,团队进行了深入研究和持续优化,并在实践中取得了一些突破。尽管当前的解析组件仍存在一些待完善之处,或测试覆盖面上尚有不足,但我们通过开源的形式将其开放出来,希望借此与更多开发者携手,共同完善这一能力模块,推动行业工具链的进步。

诚挚欢迎社区开发者参与共建,一起打磨这项通用而关键的能力。

GitHub:https://github.com/torchv/torchv-unstructured

Gitee: https://gitee.com/torchv/torchv-unstructured

该仓库是一个Ja va项目,1.0.0版本已推送至Ma ven中央仓库,坐标地址:


    com.torchv.infra
    torchv-unstructured
    1.0.0

来源:https://www.53ai.com/news/OpenSourceLLM/2025072291428.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。