资讯动态

RAG项目实战:PDF解析三层架构,从物理提取到语义切块全指南

发布时间:2026/9/20 13:07:16 来源:尧图企业网站定制
做RAG项目做久了你会发现真正卡住系统的往往不是模型选型也不是向量数据库调参而是最不起眼的文档解析。尤其是PDF几乎每个企业知识库项目里都有大量PDF文档而PDF这种格式本身就是为“打印”设计的不是为“提取”设计的。这篇文章我结合最近一个企业知识库RAG项目的落地经验讲讲我是怎么把PDF解析拆成三层来做的以及在每个环节踩过的坑和验证过的做法。无论你是刚接触RAG的初学者还是已经被PDF解析折磨过的老手这套思路应该都能帮你少走不少弯路。我讲的“三层”指的是把PDF从原始文件变成可检索、可回答的向量内容时需要依次跨越的三道关卡物理文本提取层、版面结构还原层、语义切块与检索增强层。很多RAG项目效果差问题不是出在Embedding模型上而是前面两层就没做好内容进向量库之前就已经变形了。这篇文章会把这每一层做什么、怎么选工具、怎么调参数、怎么验证效果全部讲透。1. 为什么PDF解析要拆成“三层”来做1.1 RAG系统的第一公里不是向量库是解析大多数RAG教程上来就教你用LangChain的PDFLoader加载文档然后直接切块、embedding、入库。我在真实项目里试过这种默认流程用户问“上季度营收是哪个部门贡献的”系统答非所问甚至引用了一段完全不相关的售后服务条款。排查到最后根因就是PDF解析阶段出了问题原始PDF里的表格结构被拍平成纯文本数字和列名完全错位检索时自然只能摸到错误的碎片。这里我特别想强调一个观点RAG的上限由检索决定检索的上限由文档解析决定。Embedding模型再强喂进去的是一堆语义错乱、结构残缺的文本召回质量也救不回来。所以我把PDF解析当成RAG链路里独立的一等公民来对待而不是简单调一个默认Loader就完事。在做技术选型时我给自己定的标准是每一层都要能看到中间产物能单独验证结果能按需替换工具。1.2 我理解中的“三层”到底拆什么这三层是我在实际项目中逐渐沉淀出来的划分方式分别对应PDF文档从物理存储到语义理解的三次提升。第一层是物理文本提取层解决“把字符拿出来”的问题。PDF里的文字可能以文本对象形式存在也可能只是一张扫描图片这一层用PyMuPDF、pdfplumber或OCR工具把这些内容变成最原始的文本字符串。这一步做得干不干净直接决定后面所有环节的食物质量。第二层是版面结构还原层解决“把结构找回来”的问题。PDF本身没有任何语义标签标题、正文、表格、页眉页脚在源码里都是同样的矩形框和字符流。这一层要做的是判断“这段文字属于标题还是正文”“这组字符构成一个表格还是普通段落”用规则、坐标信息或者版面分析模型把物理文本重新组织成有结构的文档块。第三层是语义切块与检索增强层解决“让知识块能被检索到”的问题。拿到结构化的文档块之后不能按固定字数机械切分而要根据标题层级、表格语义边界、段落完整性来切块再给每个块注入标题路径、页码、文档类型等元数据最后才做向量化和入库。这三层是典型的前一层输出是后一层输入的流水线关系。前期哪怕只多花一小时在第二层的结构还原上后期检索效果都能呈现出数量级的差别。1.3 这套方案适合谁、能解决什么问题这套三层方案特别适合下面这些场景企业知识库里的产品手册、技术规范、合同文档、政策文件需要精确回答数字、日期、责任条款等结构化信息的问答系统还有那些“看起来是PDF实际上是图文混排”的复杂文档。它解决的问题也很聚焦一是解决表格解析乱掉的问题二是解决标题层级丢失导致检索无边界的问题三是解决扫描版PDF无法检索的问题。如果你手头只需要解析几个干净的纯文字PDF用这套流程反而会觉得有点重可以只取第一层。2. 工具选型与总体方案设计2.1 先别急着上模型理清PDF的三种类型PDF解析工具选型之前第一件事不是安装库而是把待处理的PDF分成三种类型不同类型的应对方案完全不一样。我这里直接用最简单粗暴的分类方式大家在项目里可以照着判断。第一种是文本型PDF。用命令pdftoteepdf或者PyMuPDF打开后能直接用page.get_text()抽出来一堆字符这种PDF本质上是把文字排版结果输出成固定版式字符对象和坐标都存在文件里。项目里遇到的产品说明书、系统导出的报表大部分属于这一类。第二种是扫描型PDF。整个页面其实就是一张或几张图片没有文本对象。典型特征是鼠标框选文字时选不中或者用文本提取接口只能返回空内容。第三种是混合型PDF。一部分页面是文字层一部分是扫描图片甚至有些页面文字层和图片层叠加在一起。这时候如果只跑文字提取会丢一半内容只跑OCR又会把文字层也重复识别一遍。我在项目里专门写了一个检测脚本先快速判断PDF属于哪一类再决定走文本提取流程还是OCR流程。这一步看起来不复杂但能在后续避免大量无效调用。2.2 每个工具背后的取舍逻辑我在整个流程里主要用到四个工具组这里讲一下我为什么选它们。PyMuPDF也就是fitz用做第一层的主力提取工具。它的优势是解析速度极快对几十上百页的文档能在毫秒级内完成文本提取同时能拿到精确的字符坐标、字体信息、颜色信息。RAG场景下我们后面要按坐标做版面还原所以这个坐标信息几乎是必须的。缺点是它对部分复杂表格的语义还原不关心只负责把字符输出给你。pdfplumber用做表格和精细坐标提取。它的extract_table()在规则表格场景下非常好用能按线框把单元格行列关系还原出来。代价是速度慢比PyMuPDF慢一个数量级。所以我的策略是先用PyMuPDF做全量粗提取只有遇到疑似表格区域才调用pdfplumber细采而不是全文档无脑跑pdfplumber。PaddleOCR用做扫描版的OCR识别。选择它的核心原因是中文识别效果好、支持版面分析模型并且可以通过PP-Structure直接输出标题、表格、段落的分层结果。对包含大量中文扫描件的项目这一套比Tesseract要准得多。不过PaddleOCR的环境依赖稍重部署时会多花一些时间。LangChain的文档加载器与文本切分器用做第三层的基础设施。虽然它可以一键加载PDF但我在关键项目里不会让它跳过前两层直接进切分。我会把前两层产出的结构化结果用文档对象承接再交给LangChain做后续切分与向量化这样既能复用生态又不牺牲底层可控性。2.3 三层架构的整体链路整个链路我画成下面这样的流程来理解不用代码先看逻辑PDF文件输入 - 类型检测文本型/扫描型/混合型 - 第1层物理文本提取PyMuPDF提取字符和坐标 / PaddleOCR兜底 - 第2层版面结构还原规则判断标题层级 pdfplumber抽表格 - 第3层语义切块与元数据注入 - Embedding - 向量库每一层产出独立的结果文件方便单独调试。我会在后面的章节把每一层的关键代码和参数放出来并解释为什么这样配置。3. 第一层实战物理文本提取3.1 从PyMuPDF开始快速拿到干净文本第一层最核心目标是用最少的代价拿到完整的字符流和坐标信息。我用PyMuPDF写了一个提取函数下面直接贴核心逻辑。import fitz # PyMuPDF def extract_text_and_blocks(pdf_path): doc fitz.open(pdf_path) page_data [] for page_idx, page in enumerate(doc): # 提取按块组织的内容每个block自带bbox坐标、类型等 blocks page.get_text(dict, flagsfitz.TEXTFLAGS_TEXT)[blocks] page_text [] for block in blocks: if block[type] ! 0: # type 1是图片块留到后面单独处理 continue lines [] for line in block[lines]: text .join(span[text] for span in line[spans]).strip() if text: lines.append({ text: text, bbox: line[bbox], font: line[spans][0][font] if line[spans] else }) if lines: page_text.append({ block_bbox: block[bbox], lines: lines }) page_data.append({ page_idx: page_idx 1, blocks: page_text }) return page_data这里有两个关键点需要解释。第一我特意用了get_text(dict)而不是get_text(text)因为dict模式返回的数据结构里带bbox坐标和字体名这是第二层版面还原的核心素材。第二flagsfitz.TEXTFLAGS_TEXT是只提取文本字幕后忽略图片块避免把图片的字节信息混入文本流。这段代码跑完你会得到一个按页、按块、按行组织的结构化文本对象每一行都带着坐标。建议在这个阶段把中间结果保存成JSON文件后面做版面还原时能反复查阅不用每次重新解析。3.2 遇到扫描件怎么办OCR兜底如果检测到PDF是扫描型也就是页面没有任何文本对象就必须上OCR。我用PaddleOCR做这件事原因是它对中文扫描件识别效果最稳而且能输出每个识别文本行的坐标框。from paddleocr import PaddleOCR import numpy as np import fitz ocr PaddleOCR(use_angle_clsTrue, langch, show_logFalse) def ocr_pdf_page(pdf_path, page_idx, zoom2.0): doc fitz.open(pdf_path) page doc[page_idx] # 渲染成高分辨率图像 mat fitz.Matrix(zoom, zoom) pix page.get_pixmap(matrixmat) img np.frombuffer(pix.samples, dtypenp.uint8).reshape(pix.height, pix.width, pix.n) result ocr.ocr(img, clsTrue) lines [] for res in result[0]: box res[0] # 四点坐标 text res[1][0] # 把缩放后的坐标还原到PDF原始坐标 orig_box [[x / zoom, y / zoom] for x, y in box] lines.append({text: text, bbox: orig_box}) return lines这里我踩过的坑是渲染分辨率。一开始用默认zoom1.0小字号文字识别错字率很高尤其是中文字体里的“日”和“曰”、“处”和“外”。调到zoom2.0也就是两倍分辨率后识别准确率提升非常明显。但分辨率也不是越高越好再往上提升有限且耗时翻倍。实际项目里zoom2.0到3.0之间是性价比最高的区间。OCR结果的坐标还原也要特别注意。渲染出来的图片坐标是经过缩放的必须除以缩放倍数才能映射回PDF页面的坐标空间。这个细节如果漏了第二层的版面结构还原拿到的坐标全部对不上后面整个流程都会乱掉。3.3 文本提取的边界与陷阱第一层看似简单但有一些很隐蔽的坑。我整理了几个高频问题给大家提个醒。文本断行错乱。PDF文本对象在换行时经常被拆成多个块特别是多栏排版文档两栏内容会交错出现。解决办法是拿到所有block后按y坐标排序再按x坐标判断是否属于同一栏而不是直接按文档顺序拼接。页眉页脚混入正文。这个话题我在第二层会说但第一层提取时就要有意识保留坐标才能在后面对页眉页脚进行过滤。千万别在第一步就把坐标丢掉只存字符串那是给自己后面挖坑。部分字体导致乱码。某些PDF用了自定义编码的子集字体PyMuPDF提取出来可能是一堆奇怪字符。这时候可以尝试用get_text(rawdict)对比或者用OCR替代这一页文本。我在项目里遇到过一种设计软件导出的PDF所有文本都用Type3字体PyMuPDF提取出来完全是空白最后就是靠OCR兜底。4. 第二层实战版面与结构还原4.1 标题层级是怎么被丢掉的做RAG问答时一个非常常见的失败模式是用户问“你们产品的保修政策是什么”系统回答了“保修期外维修费用由用户承担”却忽略了前面还有一句“保修期内免费维修”。原因就在于切块时把“保修政策”这个标题和正文块拆散了检索时只命中了含“维修费用”的正文块。这个问题在默认PDF解析流程里几乎必然出现因为LangChain的默认PDFLoader只做物理文本提取完全没有标题层级的概念。我在第二层做的核心工作之一就是从物理文本块里重建标题层级。具体做法是用三组特征组合判断字体特征标题通常比正文字号大、字重更高我按字体名里是否含Bold、Medium等关键词判断位置特征标题在页面上的位置相对独立行尾通常没有句号编号特征很多文档标题自带“1.”“1.1”“第一章”等模式import re def infer_heading_level(line): text line[text].strip() font line.get(font, ) size line.get(size, 0) # 判断是否带编号 level_match re.match(r^(\d(\.\d){0,3})[\s、. ], text) if not level_match: # 没有编号大概率是普通正文或章名这里先用字体判断 if Bold in font or bold in font or Medium in font: return 2 return None num_part level_match.group(1) level num_part.count(.) 1 return level这里我补充说明一下这段代码是简化版真实项目里要结合字号阈值和页面上下文。一个可靠的改进是统计该文档正文字号的中位数凡是比中位数大一定比例的行都优先怀疑是标题。这样即使字体名不可靠也能靠字号聚类抓住绝大多数标题。很多传统PDF解析方案在这一步用规则引擎但真实文档太复杂规则永远有漏网之鱼。我的建议是规则先做识别出八成以上的标题剩下的用版面分析模型比如PP-Structure里的版面模型做二次兜底后面我会讲到。4.2 表格识别pdfplumber与表格结构化表格是RAG文档解析里最让人头疼的部分也是用户最能直接感知解析质量差异的部分。表格一旦被拍平成文本行与列的对应关系就散了“销售额”和“180万元”可以被横跨好几行分到不同块里检索时完全对不上。我用的方式是分三层来处理表格。第一层用简单的线条检测判断页面是否存在表格区域。第二层用pdfplumber的extract_table()做精准抽取。第三层把表格转成结构化的Markdown表格或JSON再作为独立文档块送入后续切分。import pdfplumber def extract_tables_pdfplumber(pdf_path, page_num): tables_data [] with pdfplumber.open(pdf_path) as pdf: page pdf.pages[page_num] tables page.extract_tables() for table in tables: # 转成带表头的dict方便后续转Markdown或JSON if not table: continue header [cell.replace(\n, ) if cell else for cell in table[0]] rows [] for row in table[1:]: clean_row [cell.replace(\n, ) if cell else for cell in row] rows.append(clean_row) tables_data.append({header: header, rows: rows}) return tables_data注意pdfplumber的extract_table()对有线表格有边框线的表格效果很好但遇到无线表格或无边框三线表它经常会把两列识别成一列或者完全识别不出来。对于这种表格我建议直接改用OCR的表格识别能力比如PaddleOCR的表格结构化模型它基于深度模型识别单元格位置而不是依赖线框。这也是我在大型项目里的推荐方案优先用pdfplumber跑规则识别不好再上模型。表格解析完我会把它表示成Markdown表格再入库。原因是LLM和Embedding模型都对Markdown结构有较好的理解能力检索时能把“表头单元格”的语义关联起来。另外我还给表格块加了“_typetable”的元数据方便后续检索时做类型过滤。4.3 布局模型兜底当规则失效时规则策略处理标准文档够用但企业知识库里总有些“不按常理出牌”的文档比如双栏混排、图文混排、文本框随意摆放的营销册子。这时候就需要走布局模型。我在实际项目里用的主要是PaddleOCR的PP-StructureV2。它可以输出版面元素类型包括标题、文本、表格、图片、公式等并能把表格结构也还原出来。用法上它对整页图片输入输出结构化结果from paddleocr import PPStructure engine PPStructure(show_logFalse, langzh) result engine.predict(img_path) # result中的每个元素都是这样的结构 # {type: title, bbox: [...], res: {text: 第二部分 产品特色}} # {type: table, bbox: [...], res: {html: table.../table}}布局模型兜底的关键价值是在规则完全失效时还能拿到一个不丢内容的底线。不过它也不是万能的推理耗时明显比规则高一个页面的处理经常需要两三秒。所以我的策略是先跑规则处理如果页面里检测到的block数量过少、或者block坐标大量重叠、或者文本提取结果为空再触发布局模型。另外我还踩过一个坑PP-Structure的表格结果默认输出HTML字符串我一开始直接把它当文本切块结果向量化时一大段HTML标签污染了语义。后来改成从HTML里解析出纯文本表格结构再统一转成Markdown效果就好多了。5. 第三层实战语义切块与检索增强5.1 按结构切块而非按字符数切块传统RAG教程里最常见的切块方式是固定窗口比如chunk_size500, chunk_overlap50。这种方式的优点是简单、通用但对结构复杂的文档来说效果很差。比如一个产品手册的“技术参数”表格有60行按500字切块容易被拦腰切断前半截还是参数表后半截已经跑到下一个标题了。我采用的方式是以第二层产出的结构块为基本单元再结合标题层级做边界修正。简单说就是标题和它对应的内容块尽量放在同一个chunk里表格本身作为独立chunk如果一个表格太大再按行分组切。def semantic_chunking(structured_doc, headingNone): chunks [] current_title_path heading if heading else [] for block in structured_doc[structure_blocks]: if block[type] title: current_title_path update_title_path(current_title_path, block[text], block[level]) continue chunk_text f{ .join(current_title_path)}\n{block[text]} chunks.append({ text: chunk_text, title_path: .join(current_title_path), page: structured_doc[page_idx], type: block[type] }) return chunks这里关键的设计是title_path。我把标题路径作为上下文信息拼在每个chunk的开头这样即使正文块单独被检索到模型也能知道它属于哪一章哪一节。比如一个块是“1800元”在这时它的完整文本变成了“产品报价 保修政策 延长保修服务价格\n1800元”语义边界就清晰多了。5.2 元数据注入与父子分块光切块还不够我给每个块补了丰富的元数据。元数据的作用有两个一是检索时可以做前置过滤比如用户限定“只看2024年的文档”就不必让向量检索在全库里找二是可以把这些字段作为大模型回答时的辅助上下文提升可信度。我常用的元数据字段包括source_file、page_num、title_path、block_type、last_modified。其中title_path是最关键的它让检索结果能自动带上章节归属。另外一个非常推荐的做法是父子分块。具体来说检索用小的子块以提升召回率但提交给大模型时把子块所在的父块整体带上这样上下文更完整。我一般把子块控制在150到300字左右用于检索父块就是一整个章节或一整个表格。这相当于多花一点存储成本换回答质量的明显提升。在实现上我用LangChain的ParentDocumentRetriever做过一版后来因为要定制元数据过滤逻辑改成了自己维护一个chunk_id到parent_chunk_id的映射表。两种方案都能跑关键是理解思想而不是依赖某个具体类。5.3 向量化与检索验证切块完成后向量化就是很工程化的一步。我用的Embedding模型是bge-large-zh-v1.5在中文场景下效果不错而且是开源模型可以私有化部署。向量维度1024配合pgvector或Milvus都能跑。但有一个非常容易踩的坑Embedding之前一定要做清洗。我在3.3节提到的页眉页脚、页签、页码如果在切块前没清理干净后面的chunk里就会混入大量类似“某某公司内部资料”“第3页”这样的垃圾文本。这些文本在高维空间里分布极不均匀会严重干扰检索排序。向量化之后不能只看“看起来差不多”我用一个标准的评测集来做检索验证。具体方法是从文档集中挑出20到30个有明确答案的问题把正确答案所在的chunk标记为ground truth然后测召回率Recall5。比如我手头一个合同问答项目最初Recall5只有0.4后来通过修表格解析、加title_path上下文、清洗页眉页脚一路提升到0.83。没有这个评测集你根本不知道改进是正向还是负向。6. 完整流程整合一个可跑通的PDF解析Pipeline6.1 关键代码链路上面讲了很多模块整合成一个可执行pipeline才是关键。我在这里给一个完整度较高的伪代码级实现大家可以直接照着改。def process_pdf_to_chunks(pdf_path): # Step 1: 类型检测 doc_type detect_pdf_type(pdf_path) # Step 2: 第一层物理提取 if doc_type in (text, mixed): text_blocks extract_text_and_blocks(pdf_path) else: text_blocks ocr_all_pages(pdf_path) # Step 3: 第二层结构还原 structured_doc structure_recover(text_blocks) # Step 4: 表格独立抽取与替换 tables extract_all_tables(pdf_path) structured_doc merge_tables_into_doc(structured_doc, tables) # Step 5: 页眉页脚过滤 cleaned_doc filter_running_headers(structured_doc) # Step 6: 第三层语义切块 chunks semantic_chunking(cleaned_doc) # Step 7: 向量化 embeddings embed_chunks(chunks) return chunks, embeddings这段代码里我特别提一下merge_tables_into_doc这一步。我的做法是先用PyMuPDF提取文本块标记出疑似表格区域比如发现有大量短行长且带竖线字符的块再用pdfplumber在原PDF对应页面重新抽取完整表格然后用表格结果替换掉文本块中的表格区域。这样既保证了文本提取速度又保证了表格结构不丢失。6.2 参数配置经验整个pipeline里有几组参数需要根据文档类型反复调我分享一些经验值。字号阈值。判断标题时先统计整篇文档正文最多的字号作为baseline_size凡是字号大于等于baseline_size * 1.2的且非正文样式的行可判定为小标题大于等于baseline_size * 1.5的判定为大标题。这个比例是我在多个行业文档上测试下来的折中值你们可以微调。chunk size。我用的不是固定chunk而是按结构单元走。如果真要给一个经验值绝大多数企业文档用300到500字之间的chunk比较合适。太短会丢失上下文太长则语义混杂。设置chunk_overlap时我建议在结构边界处重叠而不是机械地按字符数重叠。OCR阈值。什么时候触发OCR我的判断标准是页面字符数低于50个且页面面积大于A5或者文本块坐标大量重叠时走OCR兜底。同时OCR渲染分辨率用zoom2.0这个在3.2节解释过。6.3 效果评估与调优一个pipeline做出来必须能量化它到底好不好。我每次调完参数都会跑同一套评测集对比这个习惯帮我省了大量走弯路的时间。我重点看三个指标解析覆盖率成功的页面数除以总页面数。理想是0.98以上低于0.9说明有大量页面解析失败。结构还原准确率抽20页人工判断标题层级是否准确、表格是否完整。理想是0.9以上。检索Recall5理想是0.8以上低于0.5说明前期解析或切块有严重问题。调优顺序也很讲究先用视觉检查前三页的JSON中间产物确定文本和结构没有大问题再跑评测集看检索指标最后才去调Embedding模型参数。千万别一上来就换模型那样根本分不清问题是出在解析层还是向量化层。7. 常见问题与排查技巧7.1 问题速查表我在多个RAG项目里遇到过下面这些典型问题整理成速查表方便大家直接对照排查。现象可能原因排查方法解决方案文本提取出来是乱码自定义字体子集/Type3字体对比get_text(rawdict)该页改用OCR表格数据错位严重pdfplumber没识别出线框打印表格区域坐标目视检查换PP-Structure表格模型标题层级全丢失只做了文本提取没做结构还原检查JSON里是否有font/size补齐第二层chunk里全是页眉页脚没做运行头过滤查看chunk前50字增加filter_running_headers检索命中了无关段落title_path缺失导致上下文错乱查看chunk文本注入章节路径OCR识别错字率高渲染分辨率太低缩小字号区域检查结果调高zoom到2.0及以上7.2 几个我踩过的坑第一个坑是对表格做过早的文本化。刚做RAG解析的时候我用PyMuPDF抽取了一个带长表格的PDF然后直接按段落文本切块结果用户问“各分店的销售额是多少”时系统把店铺名和销售额拆到了两个chunk里怎么调Embedding都不行。后来改成表格独立解析并保持行列结构问题才彻底消失。第二个坑是忽略页码和章节的连续性。一份多页PDF的章节可能连续跨十几页但默认加载器会把每一页单独变成Document。这样用户问“这份报告的结构是什么”时检索到的chunk只包含某一页的内容回答自然不完整。我的解决办法是切块阶段合并跨页的同一章节内容让chunk在语义上完整而不是在物理页边界上切割。第三个坑是相信默认参数。很多库都有默认值但默认值是给“平均情况”用的企业文档没有平均情况。比如PaddleOCR默认会启用方向分类但纯扫描的文档可以关掉pdfplumber默认表格提取设置对某些文档漏检需要手动传vertical_strategylines或text。所有默认值都应该理解后再覆盖这是工程老手的习惯。第四个坑是没有做去重。同一份PDF被多次上传到知识库或者多个文档之间有大段重复内容在向量检索里会导致一个query返回好几条相似的重复片段挤掉了真正有价值的内容。我在pipeline里加了基于SimHash的文本去重效果很好。尤其在合同文档场景大量格式模板重复去重后检索结果质量明显提升。8. 结尾的一点个人体会做PDF三层解析这套流程我最大的体会是文档解析没有银弹规则、模型、参数组合需要根据你手上真实文档来定。别指望有一个万能库能开箱即用解决所有PDF问题也别一听说模型能做版面分析就放弃所有规则。实际工程里规则负责速度和稳定模型负责兜底和泛化两者配合才能达到理想效果。最后再分享一个小技巧每次解析完一批文档我都会把中间产物JSON格式的文本块、结构块、chunk随机抽几份人工检查。这个动作看着笨但能发现很多自动化指标发现不了的问题比如某个PDF的一页被OCR反向识别、某个编号标题被规则误判成正文。文档解析这种东西数据质量永远是第一位的而这个质量只能靠你对细节的关注来保证。希望这套三层实战经验能帮你把RAG项目的第一公里跑扎实。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价