Dify智能体平台源码二次开发笔记(6) - 优化知识库pdf文档的识别

目录

前言

新增PdfNewExtractor类

替换ExtractProcessor类

最终结果


前言


dify的1.1.3版本知识库pdf解析实现使用pypdfium2提取文本,主要存在以下问题:
1. 文本提取能力有限,对表格和图片支持不足
2. 缺乏专门的中文处理优化
3. 没有文档结构分析
4. 缺少文档质量评估
建议优化方案:
1. 使用pdfplumber替代pypdfium2
2. 增加OCR支持
3. 优化中文处理逻辑
4. 添加文档结构分析
5. 实现智能表格识别
6. 增加缓存机制
7. 优化大文件处理

导入包pdfplumber和pytesseract

pip install pdfplumber
pip install pytesseract

新增PdfNewExtractor类


新增一个PdfNewExtractor处理类替代老的PdfExtractor

from collections.abc import Iterator
from typing import Optional, cast
import pdfplumber
import pytesseract
from PIL import Image
import iofrom core.rag.extractor.blob.blob import Blob
from core.rag.extractor.extractor_base import BaseExtractor
from core.rag.models.document import Document
from extensions.ext_storage import storageclass PdfNewExtractor(BaseExtractor):"""Enhanced PDF loader with improved text extraction, OCR support, and structure analysis.Args:file_path: Path to the PDF file to load.file_cache_key: Optional cache key for storing extracted text.enable_ocr: Whether to enable OCR for text extraction from images."""def __init__(self, file_path: str, file_cache_key: Optional[str] = None, enable_ocr: bool = False):"""Initialize with file path and optional settings."""self._file_path = file_pathself._file_cache_key = file_cache_keyself._enable_ocr = enable_ocrdef extract(self) -> list[Document]:"""Extract text from PDF with caching support."""plaintext_file_exists = Falseif self._file_cache_key:try:text = cast(bytes, storage.load(self._file_cache_key)).decode("utf-8")plaintext_file_exists = Truereturn [Document(page_content=text)]except FileNotFoundError:passdocuments = list(self.load())text_list = []for document in documents:text_list.append(document.page_content)text = "\n\n".join(text_list)# Save plaintext file for cachingif not plaintext_file_exists and self._file_cache_key:storage.save(self._file_cache_key, text.encode("utf-8"))return documentsdef load(self) -> Iterator[Document]:"""Lazy load PDF pages with enhanced text extraction."""blob = Blob.from_path(self._file_path)yield from self.parse(blob)def parse(self, blob: Blob) -> Iterator[Document]:"""Parse PDF with enhanced features including OCR and structure analysis."""with blob.as_bytes_io() as file_obj:with pdfplumber.open(file_obj) as pdf:for page_number, page in enumerate(pdf.pages):# Extract text with layout preservation and encoding detectioncontent = page.extract_text(layout=True)# Try to detect and fix encoding issuestry:# First try to decode as UTF-8content = content.encode('utf-8').decode('utf-8')except UnicodeError:try:# If UTF-8 fails, try GB18030 (common Chinese encoding)content = content.encode('utf-8').decode('gb18030', errors='ignore')except UnicodeError:# If all else fails, use a more lenient approachcontent = content.encode('utf-8', errors='ignore').decode('utf-8', errors='ignore')# Extract tables if presenttables = page.extract_tables()if tables:table_text = "\n\nTables:\n"for table in tables:# Convert table to text formattable_text += "\n" + "\n".join(["\t".join([str(cell) if cell else "" for cell in row]) for row in table])content += table_text# Perform OCR if enabled and text content is limited or contains potential encoding issuesif self._enable_ocr and (len(content.strip()) < 100 or any('\ufffd' in line for line in content.splitlines())):image = page.to_image()img_bytes = io.BytesIO()image.original.save(img_bytes, format='PNG')img_bytes.seek(0)pil_image = Image.open(img_bytes)# Use multiple language models and improve OCR accuracyocr_text = pytesseract.image_to_string(pil_image,lang='chi_sim+chi_tra+eng',  # Support both simplified and traditional Chineseconfig='--psm 3 --oem 3'  # Use more accurate OCR mode)if ocr_text.strip():# Clean and normalize OCR textocr_text = ocr_text.replace('\x0c', '').strip()content = f"{content}\n\nOCR Text:\n{ocr_text}"metadata = {"source": blob.source,"page": page_number,"has_tables": bool(tables)}yield Document(page_content=content, metadata=metadata)

替换ExtractProcessor类


在ExtractProcessor中把两处extractor = PdfExtractor(file_path),替换成extractor = PdfNewExtractor(file_path)。
分别在代码144行和148行

最终结果


经过测试,优化效果完美

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/901971.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

easyExcel单元格合并

环境 java 1.8 easyexcel 3.1.1 实现方式 自定义WriteHandler&#xff0c;实现AbstractMergeStrategy抽象类&#xff0c;实现merge 方法完成自定义的合并操作。 本测试代码&#xff0c;实现了eques方法&#xff0c;用于判断是否需要合并 核心代码 实现AbstractMergeStrate…

Jenkins 简易使用记录

一、Jenkins 核心功能与适用场景 核心功能&#xff1a; 持续集成&#xff08;CI&#xff09;&#xff1a;自动构建代码、运行单元测试。持续交付&#xff08;CD&#xff09;&#xff1a;自动化部署到测试/生产环境。任务调度&#xff1a;定时执行任务&#xff08;如备份、清理&…

【HFP】蓝牙HFP协议音频连接核心技术深度解析

目录 一、音频连接建立的总体要求 1.1 发起主体与时机 1.2 前提条件 1.3 同步连接的建立 1.4 通知机制 二、不同主体发起的音频连接建立流程 2.1 连接建立触发矩阵 2.2 AG 发起的音频连接建立 2.3 HF 发起的音频连接建立 三、编解码器连接建立流程 3.1 发起条件 3.…

【卡洛诗】成为平价市场中的标杆西餐厅

近年来&#xff0c;中国餐饮市场在消费分级趋势下面临结构性调整&#xff0c;消费者对“质价比”的追求催生了新赛道的崛起。在这一背景下&#xff0c;卡洛诗西餐凭借精准的定位与系统性创新&#xff0c;以“中式西餐”为核心理念&#xff0c;成功打破西餐高价壁垒&#xff0c;…

嵌入式设备网络的动态ID分配机制实现

文章目录 前言一、系统设计要点二、核心数据结构2.1 设备唯一标识(DeviceUID)2.2 节点信息(Node)2.3 节点管理器(NodeManager) 三、核心算法实现3.1 初始化与清理3.1.1 初始化节点管理器3.1.2 清理节点管理器 3.2 动态ID分配策略3.2.1 查找最小可用ID3.2.2 ID使用检查 3.3 心跳…

WebSocket 双向通信技术详解

引言 在现代Web应用中&#xff0c;实时通信已经成为不可或缺的一部分。想象一下聊天应用、在线游戏、股票交易平台或协作工具&#xff0c;这些应用都需要服务器能够即时将更新推送给客户端&#xff0c;而不仅仅是等待客户端请求。WebSocket技术应运而生&#xff0c;它提供了一…

kafka菜鸟教程

一、kafka原理 1、kafka是一个高性能的消息队列系统&#xff0c;能够处理大规模的数据流&#xff0c;并提供低延迟的数据传输&#xff0c;它能够以每秒数十万条消息的速度进行读写操作。 二、kafka优点 1、服务解耦 &#xff08;1&#xff09;提高系统的可维护性‌ 通过服务…

SQLMap工具使用

一、SQLMap介绍 SQLMap 是一款强大的开源自动化 SQL 注入工具&#xff0c;用于检测和利用 Web 应用程序中的 SQL 注入漏洞。其工作原理是SQLMap 通过向目标 URL 发送带有特殊构造的 SQL 语句的请求&#xff0c;观察目标应用程序的响应&#xff0c;来判断是否存在 SQL 注入漏洞…

virtualbox安装xp系统卡顿的解决

安装virtualbox的增强功能即可。 先去下载 — Oracle VirtualBox下载 VirtualBox Guest Additions iso镜像 然后在这里导入iso镜像 再按照这几步操作 virtualbox按键 强制关闭xp-cuckoo的虚拟机 VBoxManage controlvm "xp-cuckoo" poweroff

观察者 ➜ 事件总线:一路走来的碎碎念

写给未来的自己:每次手敲事件模型都要 Google,干脆把思路和踩坑一次性记清楚。文章很长,都是唠叨,目的是让自己看两眼就能把设计理由找回来。 目录 为什么我要折腾事件模型?V0 ─ 单一事件的观察者模式V1 ─ 多事件同步总线(类型拆分)V2 ─ 订阅者优先级(链式调用可控)…

windwos脚本 | 基于scrcpy,只投声音、只投画面

安装scrcpy&#xff0c;scrcpy自带adb 写脚本命名为 .bat 结尾 注意这里的set "PATHD:\tools\scrcpy-win64-v3.2;%PATH%" 替换成scrcpy的安装目录 echo off :: 设置UTF-8编码 chcp 65001 > nul :: 设置标题 title 手机投屏工具:: 添加 scrcpy 路径到 PATH set &q…

Android device PCO (protocol configuration options) intro

术语 英文缩写英文全称中文PCOprotocol configuration options协议配置选项RILradio interface layer 无线电接口层PCO介绍 PCO(Protocol Configuration Options) 是 3GPP 标准协议(TS 24.008)中定义的核心概念,用于在 LTE/5G 网络建立 PDN 连接时传递动态配置参数(如 D…

Spring Boot配置文件优先级全解析:如何优雅覆盖默认配置?

&#x1f4da; 一、为什么需要了解配置文件优先级&#xff1f; 想象一下&#xff0c;你正在玩一个游戏&#x1f3ae;&#xff0c;游戏里有默认设置&#xff0c;但你可以通过不同的方式修改这些设置&#xff1a; 游戏内置的默认设置&#xff08;就像Spring Boot的默认配置&…

汽车行驶工况特征参数:从“速度曲线”到“驾驶DNA”的硬核解码

作为新能源汽车行业的从业者&#xff0c;你是否曾困惑于这些问题&#xff1a; 为什么同一款电动车&#xff0c;不同用户的实际续航差异高达30%&#xff1f;如何精准量化驾驶行为对电池寿命的影响&#xff1f;车企标定的“NEDC续航”与真实路况差距的根源是什么&#xff1f; 这…

HTTP 2.0 协议特性详解

1. 使用二进制协议&#xff0c;简化传输的复杂性&#xff0c;提高了效率 2. 支持一个 TCP 链接发起多请求&#xff0c;移除 pipeline HTTP/2 移除了 HTTP/1.1中的管道化&#xff08;pipeline&#xff09;机制&#xff0c;转而采用多路复用&#xff08;Multiplexing&#xff0…

完美解决浏览器不能复制的问题(比如赛氪网的中题库练习题)

仅供复制题库题目进行打印学习使用&#xff01; 最近想把赛氪网题库中的题目打印出来做练习&#xff0c;发现题库中的题目不能复制&#xff0c;不能在试卷上勾画标记太难受了&#xff0c;而且不能留作材料以后复习&#xff0c;故出此策。 而且CtrlP打印出的pdf会缺少题目。(我…

std::set (C++)

std::set 1. 概述定义特点 2. 内部实现3. 性能特征4. 常用 API5. 使用示例6. 自定义比较器7. 注意事项与优化8. 使用建议 1. 概述 定义 template<class Key,class Compare std::less<Key>,class Allocator std::allocator<Key> > class std::set;特点 有…

SSM省市区三级联动和三表联查附带数据库

SSM省市区三级联动和三表联查 ------附带数据库码云地址&#xff1a;https://gitee.com/Mr_ZKC/NO1 数据库在项目中

曲棍球·棒球1号位

中国女子曲棍球队曾涌现过马弋博、李红侠等优秀选手&#xff0c;但“李红”这一名字可能为信息误差。以下为您系统介绍曲棍球&#xff0c;并结合棒球进行对比分析&#xff1a; 曲棍球&#xff08;Hockey&#xff09;核心特点 运动形式 分为草地曲棍球&#xff08;夏季奥运会项…

12芯束装光纤不同包层线颜色之间的排列顺序

为什么光纤线必须按照以下颜色顺序进行排序&#xff1f;这其实是为了防止光污染的问题&#xff0c;不同颜色在传递光时从包层表皮漏光传感到梳妆的其它纤芯上&#xff0c;会有光污染的问题&#xff0c;而为了减少并防止光污染的现象&#xff0c;所以在光通信之中&#xff0c;需…