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

server/2025/3/29 5:03:37/

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.ppmy.cn/server/179146.html

相关文章

深入解析 Service Worker 在 Chrome 扩展中的应用

1. 什么是 Service Worker&#xff1f; Service Worker 是一种运行在后台的 JavaScript 线程&#xff0c;与网页主线程独立。它的主要作用是拦截网络请求、缓存资源、提供离线支持&#xff0c;并执行后台任务&#xff0c;如推送通知和后台同步。在 Chrome 扩展&#xff08;Ext…

leetcode-45.跳跃游戏II

题很简单&#xff0c;怎么少点写代码比较困难。 这题很明显贪心算法&#xff0c;每次跳跃我们都希望理论上能到达的地方更远。一开始站在初始点&#xff0c;那么可选范围就是0到nums[0]&#xff0c;在这里面找能跳得最远的点i&#xff0c;接下来遍历nums[0]1到 inums[i]&#x…

CityEngine:3D城市建模专家

今天为大家介绍的软件是CityEngine&#xff1a;3D城市建模专家, 这款建模软件也是ESRI的产品. 下面我们将从软件的主要功能、支持的系统、软件官网等方面对其进行简单的介绍。 CityEngine的官网网址为https://www.esri.com/zh-cn/arcgis/products/arcgis-cityengine/overview。…

Flink 自定义数据源:从理论到实践的全方位指南

目录 第一章:自定义数据源的基础概念 数据源是什么?它在 Flink 中扮演什么角色? Flink 的内置数据源:开箱即用的 “标配” 为什么需要自定义数据源?它的杀手锏在哪? 第二章:自定义数据源的实现之道 接口选择:从简单到高级,选对工具事半功倍 SourceFunction:入门…

当今前沿科技:改变世界的最新技术趋势

人工智能AI&#xff09;在医疗影像诊断中越来越重要。它帮助医生分析影像&#xff0c;提高了诊断的准确性和效率。传统的方法依赖于医生的经验&#xff0c;可能会出现误诊或漏诊。AI能快速处理大量影像数据&#xff0c;减少这些问题。 AI通过深度学习和图像识别技术&#xff0…

a-date-picker 格式化日期格式 YYYY-MM-DD HH:mm:ss

<template><a-range-pickerv-model:value"dateRange":show-time"{ format: HH:mm:ss, // 时间部分格式defaultValue: [moment(00:00:00, HH:mm:ss), moment(23:59:59, HH:mm:ss)] // 默认时间范围}"format"YYYY-MM-DD HH:mm:ss" // 整体…

[Android] NFC卡模拟 9.05 模拟NFC门禁卡 电梯卡等 手机代替卡片

[Android] NFC卡模拟 链接&#xff1a;https://pan.xunlei.com/s/VOM4VZZGlLh_SLa9m6Mwh4YBA1?pwdaeqp# 【应用名称】NFC卡模拟 【应用版本】9.05 【软件大小】2.7mb 【适用型号】安卓 【应用说明】功能强大且的NFC卡模拟器&#xff0c;可模拟各类门禁卡、电梯卡、部分公司&…

System.InvalidOperationException:对象当前正在其他地方使用

Form窗口当UI更新被多个地方的调用&#xff0c;并且存在冲突时&#xff0c;可能出现以上错误。 比如UI正在初始化&#xff0c;结果另外一个线程调用了更改界面的函数&#xff0c;则会出现上面的错误&#xff0c;因为这个错误是偶发的&#xff0c;所以暂无办法稳定复现。 解决…