在构建企业级 RAG(检索增强生成)系统时,纯文本处理已无法满足复杂场景需求。文档中的图表、截图以及用户直接上传的图片提问,成为了提升智能问答体验的关键。本文将基于 Spring AI Alibaba,结合阿里云 DashScope(通义千问系列) 模型及 OCR 技术,深入探讨如何处理文档切片中的图片,并重点解决“如何智能判断图片类型”这一工程难题。
一、 技术栈与环境准备
本方案核心依赖 Spring AI Alibaba,它是 Spring AI 的扩展实现,专门对接阿里云 DashScope 平台。
核心框架:Spring AI Alibaba
大语言模型 (LLM):
qwen-plus或qwen-turbo(用于最终答案生成)多模态模型 (LMM):
qwen-vl-max(用于图片理解、视觉特征提取、复杂图表分析、图片分类)OCR 引擎:
Tess4J(本地轻量级)或 阿里云 OCR API(高精度云端)Embedding 模型:
text-embedding-v2或text-embedding-v3(用于文本向量化)
二、 核心痛点:文档中的图片怎么处理?
在文档解析阶段,图片是“沉默”的数据。我们需要将其转化为机器可理解的格式。以下是三种主流处理方案,其中方案 2 引入了 OCR 技术。
方案 1:占位符说明法(轻量级)
原理:在切片时,不解析图片内容,仅保留位置标记。
实现逻辑:
if (element.isImage()) {
chunk.append("[图片占位符: 位于第" + pageNum + "页]");
}优点:处理速度极快,零额外成本。
缺点:模型无法获取图片任何信息,回答涉及图片的问题时会失效。
适用场景:图片仅为装饰,或业务对图片内容无检索需求。
方案 2:OCR + 多模态混合处理法(高精度·推荐)
这是目前工程落地中性价比最高的方案,结合了 OCR 的文字提取能力 和 VLM 的语义理解能力。
1. 为什么需要 OCR?
高精度文字提取:对于包含大量文字的截图、扫描件,OCR(如 Tesseract 或阿里云 OCR)的字符识别准确率远高于通用 VLM,且成本更低。
结构化数据保留:专用 OCR 接口(如表格 OCR)能更好地保留行列结构。
2. 为什么需要 VLM (Qwen-VL)?
语义补充:OCR 只能提取文字,无法理解图表趋势、流程图逻辑或自然图像内容。VLM 可以生成“这张图展示了销售额逐月上升的趋势”这样的描述。
3. Spring AI Alibaba + OCR 实现思路
步骤 A:图片分类与路由(关键步骤,详见第三部分)
首先判断图片类型:是“纯文本/文档型”还是“图表/自然图像型”。
步骤 B:分支处理
分支 1:纯文本/文档型图片 -> 使用 OCR
// 示例:使用 Tess4J 进行本地 OCR
import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.Tesseract;
public String ocrText(byte[] imageData) {
ITesseract instance = new Tesseract();
instance.setDatapath("src/main/resources/tessdata");
instance.setLanguage("chi_sim");
try {
// 将 byte[] 转为 File 或 BufferedImage 后调用
return instance.doOCR(new File("temp_image.png"));
} catch (Exception e) {
throw new RuntimeException("OCR failed", e);
}
}或者使用阿里云 OCR SDK 获得更高精度。
分支 2:图表/复杂图片 -> 使用 Qwen-VL
@Autowired
private ChatClient chatClient; // 配置为 qwen-vl-max
public String describeImage(byte[] imageData) {
Prompt prompt = new Prompt(
List.of(
new UserMessage(
List.of(
new Media(MediaType.IMAGE_JPEG, imageData),
new TextMessage("请详细描述这张图片的内容。如果是图表,请总结数据趋势;如果是流程图,请解释逻辑关系。")
)
)
)
);
return chatClient.call(prompt).getResult().getOutput().getContent();
}步骤 C:合并索引
将 OCR 提取的原文与 VLM 生成的描述拼接,作为该 Chunk 的最终文本内容,存入向量数据库。
Chunk Content = [OCR原文: ...] \n [视觉描述: ...]
优点:兼顾了文字的高精度提取和图像的语义理解,检索命中率最高。
缺点:链路稍长,需要维护 OCR 服务或调用 API。
方案 3:原生多模态向量检索法(前沿·双路召回)
原理:使用支持多模态的 Embedding 模型,直接将图片转化为向量。
注意:目前 Spring AI Alibaba 主要封装了文本 Embedding,若需此方案,可能需要直接调用 DashScope 的多模态 Embedding API。
优点:保留视觉特征,支持“以图搜图”。
缺点:技术复杂度高,需特定向量数据库支持。
三、 难点突破:如何智能判断图片类型?
在实施“方案 2”时,最大的工程挑战是如何自动区分“普通文本/文档图片”(适合 OCR)和“图表/自然图像”(适合 VLM)。你提到的两个方案各有优劣,以下是详细分析与推荐实现:
方案 1:基于规则与传统 CV 的代码分析(低成本·快速过滤)
原理:利用图像处理算法统计图片的特征,通过阈值判断类型。
具体实现逻辑:
文字密度检测:
使用 OpenCV 进行二值化处理。
计算黑色像素(文字)占总像素的比例。如果比例极高且分布均匀,可能是纯文本截图。
使用连通域分析,如果检测到大量细小的、排列整齐的矩形框,大概率是文字。
色彩与线条检测:
图表特征:检测是否有明显的直线(坐标轴)、曲线、柱状矩形块。可以使用霍夫变换(Hough Transform)检测直线。
自然图像特征:计算色彩熵或边缘复杂度。自然图像通常色彩丰富、边缘不规则;而文档/图表通常色彩单一、边缘硬朗。
元数据辅助:
如果文档来源是 PDF,检查图片对象的元数据。有些 PDF生成工具会将图表标记为矢量图形,而将截图标记为位图。
代码示例思路(伪代码):
public ImageType classifyImage(BufferedImage img) {
// 1. 转灰度并二值化
Mat gray = convertToGray(img);
Mat binary = threshold(gray);
// 2. 计算文字密度
double textDensity = calculateBlackPixelRatio(binary);
// 3. 检测直线(图表特征)
int lineCount = detectLines(binary);
if (textDensity > 0.3 && lineCount < 5) {
return ImageType.TEXT_DOCUMENT; // 适合 OCR
} else if (lineCount > 10 || hasBars(binary)) {
return ImageType.CHART; // 适合 VLM
} else {
return ImageType.NATURAL; // 适合 VLM
}
}优点:速度极快(毫秒级),无需调用大模型,零 Token 成本。
缺点:规则难以覆盖所有情况,容易误判(例如:密集的代码截图可能被误判为图表;简单的饼图可能因线条少被误判为文本)。
方案 2:让 AI 调用工具自动分析(高精度·推荐)
原理:利用多模态大模型(如 Qwen-VL)强大的视觉理解能力,直接让模型对图片进行分类。
具体实现逻辑:
构建分类 Prompt:
不要直接让模型描述图片,而是先让它做一个“选择题”。调用 Qwen-VL-Max:
public ImageType aiClassifyImage(byte[] imageData) {
String prompt = "请判断这张图片的类型,并从以下选项中选择唯一的一个:\n" +
"A. 纯文本/文档截图(如书籍页面、合同、PPT文字页、代码截图)\n" +
"B. 数据图表(如折线图、柱状图、饼图、散点图)\n" +
"C. 流程图/架构图(包含方框、箭头、逻辑连接)\n" +
"D. 自然图像/界面截图(如风景照、人物照、软件UI界面)\n" +
"只输出选项字母(A/B/C/D),不要输出其他内容。";
Prompt classificationPrompt = new Prompt(
List.of(
new UserMessage(
List.of(
new Media(MediaType.IMAGE_JPEG, imageData),
new TextMessage(prompt)
)
)
)
);
String result = chatClient.prompt(classificationPrompt).call().content();
if (result.contains("A")) return ImageType.TEXT_DOCUMENT;
if (result.contains("B")) return ImageType.CHART;
if (result.contains("C")) return ImageType.FLOWCHART;
return ImageType.NATURAL;
}路由执行:
如果返回 A:调用 OCR 接口。
如果返回 B/C/D:调用 VLM 描述 接口。
优点:准确率极高,能理解复杂的语义场景(如“带有少量文字注释的复杂架构图”会被正确归类为流程图而非纯文本)。
缺点:每次分类都需要调用一次 VLM,增加了预处理的时间和 Token 成本。
💡 最佳实践:混合分层路由策略
为了平衡成本与精度,建议采用分层过滤策略:
第一层:快速规则过滤(代码分析)
使用 OpenCV 快速计算图片的长宽比、色彩饱和度、文字密度。
明确案例直接分流:
如果是纯色背景且文字密度 > 80% -> 直接判定为 TEXT_DOCUMENT(走 OCR)。
如果是高分辨率且色彩丰富、无明显文字区域 -> 直接判定为 NATURAL(走 VLM)。
模糊案例进入第二层。
第二层:AI 精准分类(Qwen-VL)
对于规则无法确定的“模糊地带”(如:带有图表的 PPT 页面、复杂的混合排版文档),调用 Qwen-VL 进行最终分类。
这样可以大幅减少 VLM 的调用次数(可能只需处理 20%-30% 的图片),从而控制成本。
四、 用户“图片提问”的检索策略
当用户上传一张图片(如报错截图、商品图)进行提问时,如何检索知识库?
策略:图转文检索(兼容 OCR 结果)
用户上传图片 -> 执行上述混合分层路由判断类型。
若是文档/文字截图:调用 OCR 提取文字作为查询词。
若是图表/自然图:调用 Qwen-VL 生成描述文本。
文本 Embedding -> 将提取的文字或描述通过
text-embedding-v2转化为查询向量。向量检索 -> 在向量数据库中搜索相似切片(这些切片在入库时也已通过方案 2 处理为“OCR原文+视觉描述”)。
最终生成 -> 将检索到的上下文 + 用户原始图片 + 问题,发送给
qwen-plus生成答案。
优势:链路清晰,复用性强,无需维护两套向量索引,且能充分利用 OCR 的高精度文字匹配能力。
五、 方案对比总结
六、 Java 中 OCR 技术栈简析
在实施“方案 2”时,你需要选择合适的 Java OCR 工具:
Tess4J (Tesseract):
特点:开源免费,离线运行。
适用:预算有限、对隐私要求高、图片质量较好的场景。
阿里云/百度 OCR SDK:
特点:高精度,支持表格、身份证等专用场景。
适用:企业生产环境,对准确率要求极高,接受云端 API 调用。
Spring AI Alibaba + Qwen-VL:
特点:不仅能识字,还能懂图。
适用:复杂图表分析、非结构化图片理解、图片分类路由。
七、 结语
在 Spring AI Alibaba 的生态下,“OCR 提取文字 + Qwen-VL 理解语义” 的混合策略是构建高质量 RAG 系统的黄金组合。而通过“规则初筛 + AI 精判”的分层路由机制,我们可以巧妙地解决图片类型判断难题,在控制成本的同时最大化识别精度。
对于开发者而言,建议优先落地 方案 2(OCR + VLM 混合法),并逐步引入智能路由机制。这样既保留了 Spring Boot 开发的便捷性,又充分发挥了通义千问在多模态领域的优势,打造出真正“看得懂、查得准”的智能知识库。
评论区