微信扫码
添加专属顾问
我要投稿
尽管大型模型在生成式问答领域已经取得了显著的成果,但因为大量数据是私有的,这些模型的训练和微调成本依旧高得惊人。因此,使用RAG(Retrieval-Augmented Generation)方法逐渐成为实现应用的一种关键途径。然而,对文档进行精确的chunk划分却是一项挑战。现实中,多数专业文档以PDF格式保存,若解析精度不高,将严重影响专业问答系统的性能。
可编辑PDF文档可以使用PDF解析工具进行解析,优劣势对比如下:
PDF解析后得到的文本数据丢失了段落信息,需要重新划分和重组段落。下面我们将探讨训练语义段落划分模型的策略,并介绍一款现成的开源分段模型工具。
经过pdf解析工具处理后,原始文档的段落信息会丢失,需要重新划分和重组段落。接下来将介绍一种语义分段模型的训练方法和一个开源分段模型。
语义分段训练策略的步骤流程如下:
from modelscope.outputs import OutputKeysfrom modelscope.pipelines import pipelinefrom modelscope.utils.constant import Tasksp = pipeline(task=Tasks.document_segmentation,model='damo/nlp_bert_document-segmentation_chinese-base')result = p(documents='移动端语音唤醒模型,检测关键词为“小云小云”。模型主体为4层FSMN结构,使用CTC训练准则,参数量750K,适用于移动端设备运行。模型输入为Fbank特征,输出为基于char建模的中文全集token预测,测试工具根据每一帧的预测数据进行后处理得到输入音频的实时检测结果。模型训练采用“basetrain + finetune”的模式,basetrain过程使用大量内部移动端数据,在此基础上,使用1万条设备端录制安静场景“小云小云”数据进行微调,得到最终面向业务的模型。后续用户可在basetrain模型基础上,使用其他关键词数据进行微调,得到新的语音唤醒模型,但暂时未开放模型finetune功能。')print(result[OutputKeys.TEXT])# 输出'''移动端语音唤醒模型,检测关键词为“小云小云”。模型主体为4层FSMN结构,使用CTC训练准则,参数量750K,适用于移动端设备运行。模型输入为Fbank特征,输出为基于char建模的中文全集token预测,测试工具根据每一帧的预测数据进行后处理得到输入音频的实时检测结果。模型训练采用“basetrain + finetune”的模式,basetrain过程使用大量内部移动端数据,在此基础上,使用1万条设备端录制安静场景“小云小云”数据进行微调,得到最终面向业务的模型。后续用户可在basetrain模型基础上,使用其他关键词数据进行微调,得到新的语音唤醒模型,但暂时未开放模型finetune功能。'''
以下是PaddleOCR的使用例子:
import cv2from paddleocr import PaddleOCRpaddleocr = PaddleOCR(lang='ch', show_log=False, enable_mkldnn=True) img = cv2.imread('1.jpg')result = paddleocr.ocr(img)for i in range(len(result[0])):print(result[0][i][1][0]) # 输出识别结果对版式分析的表格区域,用表格解析模型转换为特定格式,如:csv、html、markdown等。常见开源模型有ppstructure。
如下:
import osimport cv2from paddleocr import PPStructure,save_structure_restable_engine = PPStructure(layout=False, show_log=True) save_folder = './output'img_path = 'table.jpg'img = cv2.imread(img_path)result = table_engine(img)save_structure_res(result, save_folder, os.path.basename(img_path).split('.')[0])for line in result:line.pop('img')print(line)from PIL import Imagefrom pix2tex.cli import LatexOCRmodel = LatexOCR()img = Image.open('1.jpg')print(model(img))
xy-cut方法:通过边界框的位置信息重新排序文档内容,就像整理散落的拼图,恢复它们原本的图案。
import numpy as npdef xy_cut(bboxes, direction="x"):result = []K = len(bboxes)indexes = range(K)if len(bboxes) <= 0:return resultif direction == "x":sorted_ids = sorted(indexes, key=lambda k: (bboxes[k][0], bboxes[k][1]))sorted_boxes = sorted(bboxes, key=lambda x: (x[0], x[1]))next_dir = "y"else:sorted_ids = sorted(indexes, key=lambda k: (bboxes[k][1], bboxes[k][0]))sorted_boxes = sorted(bboxes, key=lambda x: (x[1], x[0]))next_dir = "x"curr = 0np_bboxes = np.array(sorted_boxes)for idx in range(len(sorted_boxes)):if direction == "x":if idx != K - 1 and sorted_boxes[idx][2] < sorted_boxes[idx + 1][0]:rel_res = xy_cut(sorted_boxes[curr:idx + 1], next_dir)result += [sorted_ids[i + curr] for i in rel_res]curr = idx + 1else:if idx != K - 1 and sorted_boxes[idx][3] < sorted_boxes[idx + 1][1]:rel_res = xy_cut(sorted_boxes[curr:idx + 1], next_dir)result += [sorted_ids[i + curr] for i in rel_res]curr = idx + 1result += sorted_ids[curr:idx + 1]return resultdef augment_xy_cut(bboxes,direction="x",lambda_x=0.5,lambda_y=0.5,theta=5,aug=False):if aug is True:for idx in range(len(bboxes)):vx = np.random.normal(loc=0, scale=1)vy = np.random.normal(loc=0, scale=1)if np.abs(vx) >= lambda_x:bboxes[idx][0] += round(theta * vx)bboxes[idx][2] += round(theta * vx)if np.abs(vy) >= lambda_y:bboxes[idx][1] += round(theta * vy)bboxes[idx][3] += round(theta * vy)bboxes[idx] = [max(0, i) for i in bboxes[idx]]res_idx = xy_cut(bboxes, direction=direction)res_bboxes = [bboxes[idx] for idx in res_idx]return res_idx, res_bboxesbboxes = [[58.54924774169922, 1379.6373291015625, 1112.8863525390625, 1640.0870361328125],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]res_idx, res_bboxes = augment_xy_cut(bboxes, direction="y")print(res_idx)new_boxs = []for i in res_idx:new_boxs.append(bboxes[i])print(new_boxs)
import torchfrom model import LayoutLMv3ForBboxClassificationfrom collections import defaultdictCLS_TOKEN_ID = 0UNK_TOKEN_ID = 3EOS_TOKEN_ID = 2def BboxesMasks(boxes):bbox = [[0, 0, 0, 0]] + boxes + [[0, 0, 0, 0]]input_ids = [CLS_TOKEN_ID] + [UNK_TOKEN_ID] * len(boxes) + [EOS_TOKEN_ID]attention_mask = [1] + [1] * len(boxes) + [1]return {"bbox": torch.tensor([bbox]),"attention_mask": torch.tensor([attention_mask]),"input_ids": torch.tensor([input_ids]),}def decode(logits, length):logits = logits[1: length + 1, :length]orders = logits.argsort(descending=False).tolist()ret = [o.pop() for o in orders]while True:order_to_idxes = defaultdict(list)for idx, order in enumerate(ret):order_to_idxes[order].append(idx)order_to_idxes = {k: v for k, v in order_to_idxes.items() if len(v) > 1}if not order_to_idxes:breakfor order, idxes in order_to_idxes.items():idxes_to_logit = {}for idx in idxes:idxes_to_logit[idx] = logits[idx, order]idxes_to_logit = sorted(idxes_to_logit.items(), key=lambda x: x[1], reverse=True)for idx, _ in idxes_to_logit[1:]:ret[idx] = orders[idx].pop()return retdef layoutreader(bboxes):inputs = BboxesMasks(bboxes)logits = model(**inputs).logits.cpu().squeeze(0)orders = decode(logits, len(bboxes))return ordersif __name__ == '__main__':bboxes = [[584, 0, 595, 1], [35, 120, 89, 133],[35, 140, 75, 152]]model_path = ""model = LayoutLMv3ForBboxClassification.from_pretrained()print(layoutreader(bboxes))# [1, 2, 0]
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2025-10-16
基于大模型的智能问答场景解决方案——RAG提升召回率的关键
2025-10-16
用合成数据评测 RAG 系统:一份可直接上手的 DeepEval 实操指南
2025-10-16
2025 年 RAG 最佳 Reranker 模型
2025-10-16
HiRAG问答流程深入分析
2025-10-13
LightRAG × Yuxi-Know——「知识检索 + 知识图谱」实践案例
2025-10-13
PG用户福音|一次性搞定RAG完整数据库套装
2025-10-12
任何格式RAG数据实现秒级转换!彻底解决RAG系统中最令人头疼的数据准备环节
2025-10-12
总结了 13 个 顶级 RAG 技术
2025-09-15
2025-09-02
2025-08-05
2025-08-18
2025-08-25
2025-08-25
2025-08-25
2025-09-03
2025-08-20
2025-09-08
2025-10-04
2025-09-30
2025-09-10
2025-09-10
2025-09-03
2025-08-28
2025-08-25
2025-08-20