实习七月复盘
文件处理阶段
- 使用libreoffice将doc,docx文件处理成pdf文件,方便后续使用mineru进行提取
- 完成mineru的docker本地部署;搭建fastapi服务,与项目容器构建自定义网络,方便后续服务调用;使用locust完成对mineru的并发性能测试,和吞吐量测试
- 对mineru提取的html格式的表格进行预处理工作,将其转化成md格式,方便后续分块,节省tokens
部分技术细节
mineru提取效果说明
可以完整提取表格与图片,将图片以相对链接形式储存在images文件夹下;可以完成pdf与扫描件的提取,可以实现对图片中文字的识别;输出符合人类阅读顺序的文本,适用于单栏、多栏及复杂排版;删除页眉、页脚、脚注、页码等元素,确保语义连贯
目前问题:仍无法实现对多级标题的识别
mineru的fastapi启动指令
1 | MINERU_MODEL_SOURCE=local CUDA_VISIBLE_DEVICES=1,2,3 mineru-api --host 0.0.0.0 --port 30000 --dp-size 3 --enable-torch-compile |
MinerU支持通过sglang的多GPU并行模式来提升推理速度。
- 如果您有超过多张显卡,可以使用sglang的多卡并行模式来增加吞吐量:
--dp-size 2- 同时您可以启用
torch.compile来将推理速度加速约15%:--enable-torch-compile
注意设置环境变量
MINERU_MODEL_SOURCE=local CUDA_VISIBLE_DEVICES=1,2,3保证模型本地加载与调用指定gpu
mineru容器启动指令
1 | docker run -d --name mineru-server --gpus all --shm-size 32g -p 30000:30000 --ipc=host -v /aisys/:/aisys/ --network network_test mineru-sglang:latest tail -f /dev/null |
mineru三种后端模式测试
pipeline (默认后端) ,vlm-sglang-engine,vlm-sglang-client
项目中使用的是vlm-sglang-engine,原因如下,pipeline应用场景更多是仅能cpu推理,解析速度大大落后与vlm模式,而我们gpu资源充足,自然不考虑;vlm-sglang-client应用场景更多是有SGLang服务器,这样客户端既可以不用安装sglang,同样不符合我们的条件
mineru并发与吞吐量测试
测试场景:10页的pdf,50用户并发
工具:locust
测试结果
对于推理模型的吞吐量,在3个gpu开启数据并行的情况下,平均每秒单个gpu处理tokens为1500左右
gpu状态如上:显存几乎打满 85–87 %,GPU 利用率 59–63 %,功耗 170–188 W / 350 W
压测结果如下,选取部分指标
| 指标 | 数值 | 通俗解释 |
|---|---|---|
| 平均响应时间 | 241 秒 ≈ 4 分钟 | 上传一个 PDF → 拿到解析结果,平均要等 4 分钟。 |
| 中位数 | 215 秒 ≈ 3.6 分钟 | 一半请求在 3.6 分钟内完成。 |
| 95% 用户 | 361 秒 ≈ 6 分钟 | 最慢的 5% 要等 6 分钟以上。 |
| 吞吐量 | 0.18 req/s | 这台 MinerU 每分钟只能处理约11 个 PDF。 |
分块阶段
当前主流的分块方式共五种:固定长度分块,语义分块,递归分块,文档结构分块,llm分块。
最后项目我选择了递归分块,原因如下:
- mineru无法正确提取md文档结构,因此我舍弃了文档结构分块
- 测试了agentic chunk(其主要思想是,先进行初步分段,按照长度或递归,然后让大模型生成这一段的概要,将段与段合并生成块),但是测试下来,我们这个一个文档的内容同质化很严重,基本上都分到一块里了,我猜测语义分块也是这种效果,因此舍弃
- 我们的文档中存在大量表格,我在预处理阶段增加了对表格的首尾标记,使用递归分块可以更好的保留这些结构
检索阶段
基于langchain_elasticsearch完成了向量搜索,bm25,混合检索,模糊检索的检索函数的编写。
结果如下:
- 混合检索elasticsearch需要付费使用
- bm25的多字段搜索有三种模式且字段的权重可以调整,后续评估时调整进行测试
- 检索的效果需要后续进行rag评估时判定
elasticsearch相关
完成对项目es模块的熟悉阅读;实现对elasticsearch的连接与字段的构建与存入。
关于字段的存储,我选取了report_name,report_url,page_content
相关细节
阅读elasticsearch代码相关记录:
- embedding_model.select_embeddings_model:根据指定的模型名称加载
- make_es_vector_store:
- docs_url = pd.read_excel(‘docs_new.xlsx’),从excel加载url并进行数据处理,保存筛选后的ur
- 完成文件加载测试:xizhang/retrival/docfile_test/test.py;
- 初始化es,使用elastic_search.load_es_index加载存储索引
- 完成测试elasticsearch连接与索引构建(索引名zxj_test):/aisys/repo_dev/xizhang/retrival/elasticsearch_test/test_es_connect.py,/aisys/repo_dev/xizhang/retrival/elasticsearch_test/test_add_es.py
- 顺序批量处理文件:共16000多份,每十份为一批进行处理,使用download_pdf.py进行文件下载,使用,使用vector_base.rewrite_file对文件进行处理,这里可以修改代码,增加对mineru处理pdf的markdown文件的处理,返回Document对象列表;
- elastic_search
重写了检索策略的函数,包括BM25,KNN,混合搜索
elastic_retriever创建Elasticsearch检索器:根据搜索类型选择对应的查询函数,创建Elasticsearch检索器ElasticsearchRetriever.from_es_params
retrievers
- 定义函数select_retriever,根据指定的名称选择并返回相应的检索器,目前只有bm25
文档结构
1 | doc = Document( |
rag评估
待补充
后续优化思考
- 重排序部分我没有做过,不知道怎么做,也不知道效果会怎样(我感觉在我们这个场景应该提升有限,听你说也是这样)
- 如何存入数据库的部分,可能也是优化的点,比如可以尝试agentic rag这种,在存入数据库前再进行一步处理
- 还有一个点我比较好奇,我们项目在召回后是如何处理的,就是上下文拼接吗