基于Langchain.js将PDF转为Markdown以提升Embeddings质量
Node.js下PDF转Markdown工具推荐及RAG优化建议
一、PDF转Markdown的Node.js工具方案
1. pdf2md
专门针对PDF转Markdown的工具,能自动识别标题层级(依据字体大小、加粗属性),提取表格并转为标准Markdown格式,对常规排版的PDF适配性较好。
安装命令:npm install pdf2md
简单使用示例:
const pdf2md = require('pdf2md'); async function convertPdf() { const mdContent = await pdf2md.convert('input.pdf'); // 手动过滤页眉页脚:根据实际特征匹配重复文本 const lines = mdContent.split('\n'); const filteredLines = lines.filter(line => { // 示例:过滤含固定页码、文档名的页眉页脚内容 return !line.match(/^第\d+页$/) && !line.includes('XX项目文档'); }); const finalMd = filteredLines.join('\n'); console.log(finalMd); } convertPdf();
缺点:对多列排版、不规则表格的支持有限,需自行补充页眉页脚的过滤逻辑。
2. unstructured-node
Unstructured的Node.js版本,主打结构化文档提取,能精准识别标题、正文、表格、图片等元素,输出结构化数据后可自行转换为标准Markdown。
安装命令:npm install @unstructured.io/unstructured
使用示例(提取结构化内容后转Markdown):
const { partition } = require('@unstructured.io/unstructured'); async function processPdf() { const elements = await partition({ filePath: 'input.pdf', strategy: 'hi_res', // 高分辨率模式适配复杂PDF }); let mdContent = ''; for (const elem of elements) { switch (elem.type) { case 'Title': // 根据字体大小判断标题层级,示例用一级标题 mdContent += `# ${elem.text}\n\n`; break; case 'NarrativeText': mdContent += `${elem.text}\n\n`; break; case 'Table': mdContent += generateMarkdownTable(elem.metadata.table) + '\n\n'; break; case 'Image': // 用Base64嵌入图片,或替换为占位符 mdContent += `\n\n`; break; } } // 可选:通过元素位置过滤页眉页脚(比如剔除顶部10%、底部10%区域的元素) console.log(mdContent); } function generateMarkdownTable(tableData) { let table = '| ' + tableData[0].join(' | ') + ' |\n'; table += '| ' + tableData[0].map(() => '---').join(' | ') + ' |\n'; for (let i = 1; i < tableData.length; i++) { table += '| ' + tableData[i].join(' | ') + ' |\n'; } return table; } processPdf();
优势:对复杂PDF的结构识别更准确,能直接区分标题、正文等元素,图片和表格的提取可靠性更高。
3. 组合方案(pdf-parse + 自定义逻辑)
如果需要极致灵活的控制,可采用pdf-parse提取原始文本与结构信息,自行编写处理逻辑:
- 用
pdf-parse获取每页的文本、字体大小、位置坐标 - 根据字体大小+位置判断标题(比如字体≥16号且位于页面顶部的为一级标题)
- 搭配
pdf-table-extractor提取表格,转换为Markdown格式 - 通过检测每页重复的顶部/底部文本过滤页眉页脚
二、RAG项目优化建议
文档预处理精细化
- 转Markdown后,按标题层级做语义分块,比如将每个二级标题下的完整内容作为一个块,避免拆分完整语义单元
- 对长文档做递归分块,确保每个块的长度适配嵌入模型的上下文窗口
嵌入与检索优化
- 选择支持结构化理解的嵌入模型,优先适配Markdown格式的模型,提升标题、表格等元素的嵌入准确性
- 采用混合检索:结合向量检索与关键词检索(比如用Elasticsearch同时做向量和全文检索),提升召回率
- 加入Rerank步骤:用Cross-Encoder对检索结果重新排序,确保最相关的内容排在前列
元数据增强
- 把PDF的元数据(文档类型、章节、页码)、Markdown的标题层级作为块的元数据,检索时可通过元数据过滤(比如仅检索某一章节的内容)
缓存与效率优化
- 对已处理的PDF转Markdown结果、嵌入向量做缓存,避免重复处理,提升系统响应速度
- 批量处理PDF文档,减少单次请求的资源消耗
LLM生成优化
- 在提示词中明确说明Markdown格式的结构,引导LLM更好地利用标题、表格等信息生成回答
- 若检索到的内容过长,先做摘要处理再喂给LLM,减少冗余信息
内容的提问来源于stack exchange,提问作者Uiyoung Kim
相关产品推荐
相关产品推荐

