当前位置: 首页 > news >正文

【大模型算法工程】大模型应用工具化、忠诚度以及知识库场景下PDF双栏解析问题的讨论

1. 大模型时代应用工具化以及无忠诚度现象讨论

        接触大模型久了,也慢慢探到一些大模型能力表现非常自然和突出的场景,比如AI搜索(依赖大模型的理解总结能力)、AI对话(即chat,依赖大模型的生成能力)、AI工具使用(即智能体,依赖大模型的规划能力),应该说目前主流应用就是围绕这三个点进行的,没有例外。比如近期推出的夸克超级框、manus智能体工具、ima知识库都是如此。

        另外,对于AI应用,当下用户其实完全没有忠诚度可言,这一特点是与之前移动应用时代app存在天壤之别。移动应用时代,更多是场景的扩展,将原来PC场景衍生到APP场景,用户忠诚的依然是平台资源本身。但到了AI应用时代,只要是哪一个产品使用更快更好更人性化,用户就会果断切换到新的产品。例如deepseek横空出世,包括腾讯、阿里云、字节在内的大厂,直接集成到自家云产品,用户也果断从之前的kimi、豆包、智谱清言,切换到各种deepseek chat工具。还有最近身边朋友看论文用夸克,但我推荐了另一款AI阅读助手后,他发现AI阅读助手表现更好,直接就放弃了夸克,改用我推荐的产品。这种现象和AI应用工具化有关,不需要依赖什么其他的资源,工具本身就是产品,随时可以切换,哪种效率提升更快就用哪一种。

        所以说,要想从众多的模型、应用中凸显出来,必然需要不断追求对于场景最优的模型,用户体验越好的产品。这就绕不开产品匠心逻辑。反正当下既要速度也需要沉下心打磨出更好的产品。

        说起产品打磨,回到知识库RAG场景,要想RAG能够又好又快又准确返回结果,一开始的文档解析工作就非常值得好好做。最近用了deepseek、智谱清言的工具,发现文档解析能力还有很多提升空间,只支持部分文档的解析,这或许是大模型公司更关注基础模型能力,只要有一个产品就行,但我觉得to C的产品还是有必要投入打磨。

2. 知识库生态建设之双栏PDF解析

       对于文档解析,其中一个非常有意思的场景是对PDF双栏文档的解析,如果是按正常的解析工具以行为单位解析,会导致解析后的排版非常糟糕,比如夸克的解析,就不是很好。反而通义的工具表现很不错。

 双栏解析的目标:

  • 正确识别左右两栏
  • 先处理左栏内容,再处理右栏内容
  • 每栏内部按照从上到下的顺序排列

这里给一个简单的双栏解析思路:

  • 利用CV工具将 pdf 每一页转换为图片
  • 利用目标检测模型识别每一页中的元素并标注类型,即版面分析(例如yolo)
  • 利用 OCR 来提取每一个元素中文字块信息(例如paddle系列)
  • 利用表格抽取模型识别跨页表格(可以自己训)
  • 完成版面分析,读取版面分析的JSON结果(包括每一模块的坐标信息)
  • 对每一模块元素进行排序,排序逻辑如下:
    • 计算每个元素在页面左右两侧的覆盖比例
    • 根据覆盖比例确定元素属于左栏还是右栏
    • 对于跨栏元素特殊处理
    • 按照"先左栏后右栏,同栏内从上到下"的顺序输出

实施方案:

  • 区分单栏和双栏:

    • 计算所有文本块中心点的横坐标极差。
    • 设定一个阈值(可以调整),如果极差小于阈值,则判定为单栏,否则为双栏。
  • 单栏排序:

    • 直接按中心点纵坐标(top)升序 排序。
  • 双栏排序:

    • 计算页面中线(即所有文本块中心点的平均横坐标)。
    • 文本块分类:
      • 左栏:文本块的 右边界 < 中线
      • 右栏:文本块的 左边界 > 中线
      • 通栏:文本块的 左边界 < 中线 且 右边界 > 中线
    • 排序顺序:
      • 先对 左栏按 top 升序 排序。
      • 再对 右栏按 top 升序 排序。
      • 处理 通栏:
        • 通栏上方 的 右栏拼接到左栏后。
        • 通栏 内容放在其下方。
        • 通栏下方 的 右栏拼接到左栏后。

其中:

  • 页面宽度估计:

    • 如果没有提供 page_width,则从元素坐标中推断最大右边界作为页面宽度,可用于适配不同页面宽度的文档。
  • 中线计算:

    • 采用 page_width / 2 计算页面的中线坐标,然后通过文本块覆盖比例(左/右)来判断其归属。
  • 更精准的左右栏判定:

    • 计算文本块的左侧部分宽度和右侧部分宽度,再计算左右覆盖比例。
    • 如果 90%以上的内容位于左侧,则归入左栏;如果 90%以上内容在右侧,则归入右栏。
    • 这种方式比简单的 “右边界 < 另一文本块的左边界” 方法更加准确,能够适应不同尺寸的文本块,尤其是跨栏情况。
  • 排序逻辑:

    • 左栏文本块按照纵坐标排序,确保从上到下排列。
    • 右栏文本块也按照纵坐标排序。
    • 最终合并:左栏 → 右栏,保证自然的阅读顺序。

代码示例:

def sort_text_blocks(res):"""对文本块进行排序,支持单栏、双栏、通栏布局:param res: 文本块列表,每个文本块包含 'page_idx' 和 'extra_data'(包含 'position' 坐标):return: 经过排序的文本块列表"""# 按页码排序res.sort(key=lambda x: get_page_idx_value(x["page_idx"]))sorted_res = []pages = {}# 按页分组for block in res:page_idx = get_page_idx_value(block["page_idx"])pages.setdefault(page_idx, []).append(block)# 处理每一页for page_idx, blocks in pages.items():if not blocks:continuemax_page_width = extract_max_page_width(blocks)page_center_x = max_page_width / 2left_column, right_column, full_column = [], [], []for block in blocks:position = block["extra_data"]["position"]if isinstance(position, list) and len(position) > 0 and isinstance(position[0], list):x1, x2, y1, y2 = position[min(1, len(position) - 1)]else:x1, x2, y1, y2 = positionblock_width = x2 - x1left_part = max(0, min(x2, page_center_x) - x1)right_part = max(0, x2 - max(x1, page_center_x))left_ratio = left_part / block_width if block_width > 0 else 0right_ratio = right_part / block_width if block_width > 0 else 0if left_ratio >= 0.9:left_column.append(block)elif right_ratio >= 0.9:right_column.append(block)else:full_column.append(block)# 按从上到下排序key_func = lambda b: get_position_value(b["extra_data"]["position"], 2)left_column.sort(key=key_func)right_column.sort(key=key_func)full_column.sort(key=key_func)if full_column:min_full_top = get_position_value(full_column[0]["extra_data"]["position"], 2)max_full_bottom = get_position_value(full_column[-1]["extra_data"]["position"], 3)sorted_blocks = ([b for b in left_column if get_position_value(b["extra_data"]["position"], 3) < min_full_top] +[b for b in right_column if get_position_value(b["extra_data"]["position"], 3) < min_full_top] +full_column +[b for b in left_column if get_position_value(b["extra_data"]["position"], 2) > max_full_bottom] +[b for b in right_column if get_position_value(b["extra_data"]["position"], 2) > max_full_bottom])else:sorted_blocks = left_column + right_columnsorted_res.extend(sorted_blocks)return sorted_res

3. 参考材料

【1】LLM常见问题(基于 AI 的 pdf 解析)

【2】双栏学术论文转换为单栏Markdown


http://www.mrgr.cn/news/95409.html

相关文章:

  • c#难点整理2
  • AI-Talk开发板之更换串口引脚
  • 汇川EASY系列之以太网通讯(MODBUS_TCP做主站)
  • 3.21-1自动化框架
  • 网络爬虫【爬虫库request】
  • Cesium 自定义路径导航材质
  • 【算法】DFS、BFS、floodfill、记忆化搜索、BFS拓扑排序
  • qt实现一个简单http服务器和客户端
  • Maven 简介及其核心概念
  • Java 大视界 -- Java 大数据在智能医疗远程会诊与专家协作中的技术支持(146)
  • 【多线程】线程安全集合类,ConcurrentHashMap实现原理
  • STM32 - 在机器人领域,LL库相比HAL优势明显
  • 区块链交易
  • MFC中CString类型是如何怎么转std::string的
  • 1.8 函数的连续性和间断点
  • 基于 FPGA的HLS技术与应用
  • 可发1区的超级创新思路:基于注意力机制的DSD-CNN时间序列预测模型(功率预测、交通流量预测、故障检测)
  • VLAN综合实验报告
  • Mybatis—01
  • C 语 言 --- 操 作 符 2