ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

RAG数据导入实战:组件化实现多源文档解析与清洗

RAG数据导入实战:组件化实现多源文档解析与清洗 之前我们完成了 RAG 系列的前三篇分别聊了环境准备、组件化思想以及用 Cursor 快速搭建检索链路。这一篇重点解决一个非常现实的问题数据导入技术。很多人做 RAG 时第一步就卡住了。原因很简单大模型本身不关心你的数据是 PDF、Word、数据库还是网页它只认文本。而 RAG 要回答好问题必须让模型“读”到最新、最准确的私有数据。如果导入环节做得粗糙后面检索结果必然不理想。这篇文章会围绕“组件化”的思路把数据导入拆成若干独立模块结合实际代码说明每一类数据源该怎么处理。同时我们也会演示如何借助 Cursor 快速编写、调试这些导入组件。1. 数据导入为什么是 RAG 的核心环节1.1 数据导入在 RAG 中的位置先回顾一下一个典型的 RAG 流程原始数据 - 解析与清洗 - 切分Chunking - 向量化Embedding - 存入向量库 - 检索召回 - 大模型生成很多人会重点关注向量化和大模型生成却忽略了最前面的“原始数据 - 解析与清洗”。但实际上这一环节直接决定了后续切分和向量化的质量。如果导入的数据是脏的包含大量无关噪声那么切分得到的 Chunk 可能语义不完整Embedding 向量质量下降检索召回准确率降低最终大模型生成的答案出现幻觉或答非所问。所以数据导入不是简单“读文件、塞进向量库”它是一整套围绕数据适配、清洗、格式化的工程体系。1.2 为什么用“组件化”来处理数据导入在之前的组件篇中我们强调过RAG 系统应该具备良好的扩展性。数据导入也一样。一个真实项目的导入需求往往是多样的内部知识库可能是 Word 文档和 PDF 混合业务数据可能在 MySQL、PostgreSQL 等关系型数据库中部分内容来自公司内部 Wiki 或 Confluence还有可能是网页、Markdown、纯文本日志。如果每种数据源都单独写一套杂乱代码后期维护会非常痛苦。组件化要解决的就是让每种数据源变成独立、可复用的导入器Loader统一出口为规范文本后续的切分和向量化完全不用关心数据从哪来。1.3 数据导入与 RAG 效果的量化关系虽然很难给“数据导入质量”定一个绝对分数但从经验来看以下现象通常意味着导入环节有问题检索结果中频繁出现与问题无关的碎片文本答案引用内容不完整缺少上下文对表格数据处理错误导致数字或关系混乱扫描版 PDF 导入后全是乱码或空文本。这些问题如果不在导入阶段解决越往后越难补救。一句话RAG 的效果上限取决于导入数据的质量。2. 数据导入的整体架构设计在动手写代码之前我们先明确数据导入组件的整体架构。2.1 从数据源到标准文档模型市面上常见的 RAG 框架比如 LangChain、LlamaIndex底层都定义了一个统一文档模型通常包含以下字段字段含义示例page_content 或 text文档正文“这是一段技术文档内容……”metadata元信息文件名、页数、来源链接、更新时间等我们的导入组件最终目标就是把任意数据源转换成标准文档列表并携带尽可能完整的元数据。这样设计的好处是下游的切分器、Embedding 模型和向量库都可以基于统一的接口工作不需要关心上游数据是什么格式。2.2 数据导入组件的分层将数据导入拆成三个层次第一层数据接入层Connector负责连接各类数据源读取原始字节或记录。例如读取本地文件连接数据库执行 SQL调用远程 API 获取网页内容连接对象存储拉取文件。第二层解析与清洗层Parser Cleaner负责将原始内容转换为纯文本并去除噪声。例如PDF 文本提取HTML 标签去除特殊字符规范编码问题修复重复内容去重。第三层文档化层Document Builder负责将清洗后的文本包装成统一的标准文档对象同时写入必要的元数据。例如doc Document( page_contentclean_text, metadata{source: mysql, table: user_manual, id: 1001} )这三层职责清晰每一层都可以独立替换和扩展正好符合组件化的理念。2.3 组件接口设计在代码层面我们可以给导入器定义一个统一接口from abc import ABC, abstractmethod from typing import List, Dict, Any class BaseLoader(ABC): 所有数据导入组件的统一基类 abstractmethod def load(self, source: Any, **kwargs) - List[Dict[str, Any]]: 加载并转换数据为统一文档列表 返回格式 [ { text: 文档正文内容, metadata: {key: value} } ] pass后续每一种数据导入器只需要继承BaseLoader并实现load方法即可。3. 环境准备与依赖说明3.1 基础环境本文示例使用 Python 3.10 环境操作系统为 Windows / macOS / Linux 均可。需要安装以下 Python 包pip install pypdf python-docx beautifulsoup4 requests pymysql pandas各包用途说明包名用途pypdf解析 PDF 文本python-docx解析 Word 文档beautifulsoup4解析 HTML/XMLrequests发送 HTTP 请求抓取网页pymysql连接 MySQL 数据库pandas处理表格数据如果你使用的是 LangChain可以安装它的文档加载器扩展pip install langchain langchain-community不过本文为了讲清原理会尽量不依赖框架先用原生代码实现再说明如何与 LangChain 或自有框架集成。3.2 演示项目结构我们采用模块化工程结构rag_data_import/ ├── main.py # 入口演示 ├── loaders/ │ ├── __init__.py │ ├── base.py # 统一基类 │ ├── text_loader.py # 纯文本导入 │ ├── pdf_loader.py # PDF 导入 │ ├── docx_loader.py # Word 导入 │ ├── database_loader.py # 数据库导入 │ └── web_loader.py # 网页导入 ├── cleaners/ │ ├── __init__.py │ └── text_cleaner.py # 文本清洗工具 └── requirements.txt这样的项目结构后续新增一种数据源时只需要在loaders目录下增加一个文件并实现BaseLoader接口即可。4. 核心代码实现六类数据导入组件下面我们逐个实现数据导入组件。为了便于理解每个组件会先说明适用场景再给出核心代码最后补充关键参数和注意事项。4.1 纯文本与 Markdown 文件导入这是最简单的一种数据源但也是基础中的基础。很多内部知识库的底层源文件就是 Markdown 或 txt。# 文件路径loaders/text_loader.py import os from typing import List, Dict, Any from .base import BaseLoader class TextLoader(BaseLoader): 纯文本与 Markdown 文件导入器 支持编码检测避免中文乱码 def __init__(self, encoding: str utf-8): self.encoding encoding def load(self, source: str, **kwargs) - List[Dict[str, Any]]: if not os.path.exists(source): raise FileNotFoundError(f文件不存在: {source}) with open(source, r, encodingself.encoding) as f: text f.read() return [ { text: text, metadata: { source: source, file_name: os.path.basename(source), file_type: text, file_size: os.path.getsize(source) } } ]代码说明source参数传入文件路径通过encoding参数指定编码默认 utf-8对于中文环境通常够用返回列表即使单个文件也保持列表结构方便下游统一迭代。实战中如果遇到 GBK 编码的文件可以在实例化时指定loader TextLoader(encodinggbk) docs loader.load(./knowledge/readme.md)4.2 PDF 文档导入PDF 是 RAG 项目中最常见也最“坑”的数据源。因为 PDF 分为文本型 PDF 和扫描型 PDF图片前一种可以直接提取文字后一种需要 OCR 识别。我们这里先处理文本型 PDF。# 文件路径loaders/pdf_loader.py import os from typing import List, Dict, Any from pypdf import PdfReader from .base import BaseLoader class PdfLoader(BaseLoader): PDF 文件导入器 支持按页拆分保留页码元数据 def __init__(self, split_by_page: bool True): self.split_by_page split_by_page def load(self, source: str, **kwargs) - List[Dict[str, Any]]: if not os.path.exists(source): raise FileNotFoundError(f文件不存在: {source}) reader PdfReader(source) docs [] for page_num, page in enumerate(reader.pages, start1): text page.extract_text() or text text.strip() if not text: continue if self.split_by_page: docs.append( { text: text, metadata: { source: source, file_name: os.path.basename(source), file_type: pdf, page: page_num, total_pages: len(reader.pages) } } ) else: # 不按页拆分时只保留一个文档但页数信息记录在 metadata 中 # 这里简化处理用 last doc 的方式累积 # 为了保持逻辑清晰我们在非按页模式下直接拼接 pass if not self.split_by_page: full_text \n.join(doc[text] for doc in docs) return [ { text: full_text, metadata: { source: source, file_name: os.path.basename(source), file_type: pdf, total_pages: len(reader.pages) } } ] return docs实际使用中推荐split_by_pageTrue因为按页拆分能天然保留父文档的页码信息后续做引用溯源时很有用。4.3 Word 文档导入Word 文档在企业管理场景中非常常见。python-docx可以方便地提取段落和表格内容。# 文件路径loaders/docx_loader.py import os from typing import List, Dict, Any from docx import Document from .base import BaseLoader class DocxLoader(BaseLoader): Word 文档导入器 同时提取段落与表格内容 def load(self, source: str, **kwargs) - List[Dict[str, Any]]: if not os.path.exists(source): raise FileNotFoundError(f文件不存在: {source}) doc Document(source) parts [] # 提取段落 for para in doc.paragraphs: text para.text.strip() if text: parts.append(text) # 提取表格内容转为文本行方便 RAG 识别 for table in doc.tables: for row in table.rows: cells [cell.text.strip() for cell in row.cells] row_text | .join(cells) parts.append(row_text) full_text \n.join(parts) return [ { text: full_text, metadata: { source: source, file_name: os.path.basename(source), file_type: docx, paragraph_count: len(doc.paragraphs), table_count: len(doc.tables) } } ]这里需要注意Word 文档中的表格内容如果直接丢弃可能导致关键数据缺失。因此上面的实现把表格按行拼接成文本并用分隔符分隔各列。如果文档中有图片且图片里包含关键文字那么仅靠python-docx无法提取需要接入 OCR 组件这属于进阶内容后续可以单独展开。4.4 关系型数据库导入数据库导入是“加工成模型能读懂的数据”的关键环节。核心思路是将数据库中的结构化记录序列化为自然语言文本。比如MySQL 中有一张product表idnamepricedescription1无线鼠标99.00支持蓝牙和 2.4G 双模连接我们需要转换成类似产品名称无线鼠标价格99.00元描述支持蓝牙和 2.4G 双模连接。这样的文本放入 RAG模型才能自然理解并用于回答。# 文件路径loaders/database_loader.py import pandas as pd from typing import List, Dict, Any, Optional from .base import BaseLoader class DatabaseLoader(BaseLoader): 关系型数据库导入器 通过 SQL 查询将数据行转换为文本 def __init__( self, connection_config: Dict[str, str], sql: str, text_template: Optional[str] None ): :param connection_config: 数据库连接配置 :param sql: 查询语句 :param text_template: 文本模板使用 {column_name} 占位符 self.connection_config connection_config self.sql sql self.text_template text_template def load(self, source: Any None, **kwargs) - List[Dict[str, Any]]: # 这里以 MySQL 为例实际项目请按照你的数据库类型调整驱动 import pymysql conn pymysql.connect(**self.connection_config) try: df pd.read_sql(self.sql, conn) finally: conn.close() docs [] for _, row in df.iterrows(): if self.text_template: # 使用模板生成文本 text self.text_template.format(**row.to_dict()) else: # 默认将每行拼接为 列名值 的形式 parts [f{col}{val} for col, val in row.items()] text .join(parts) docs.append( { text: text, metadata: { source: mysql, db_table: self.sql.strip().split( )[-1] if self.sql else unknown, row_id: str(row.get(id, )) } } ) return docs使用示例config { host: localhost, user: root, password: 123456, database: business, charset: utf8mb4 } template 产品名称{name}价格{price}元描述{description} loader DatabaseLoader( connection_configconfig, sqlSELECT id, name, price, description FROM product LIMIT 1000, text_templatetemplate ) docs loader.load()这里有几个工程上的关键点查询建议使用LIMIT分批加载避免一次导入全表导致内存爆炸text_template是推荐方式它可以让数据更贴近自然语言表达不要把数据库连接配置硬编码在代码中建议通过环境变量或配置中心管理。4.5 网页数据导入网页数据导入通常分为两种静态网页直接请求 HTML 并解析动态渲染网页需要模拟浏览器执行 JavaScript。我们先处理静态网页场景用requests拉取 HTML然后用BeautifulSoup去除标签。# 文件路径loaders/web_loader.py import requests from typing import List, Dict, Any from bs4 import BeautifulSoup from .base import BaseLoader class WebLoader(BaseLoader): 静态网页导入器 抓取网页并提取正文文本 def __init__(self, headers: Dict[str, str] None, timeout: int 10): self.headers headers or { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } self.timeout timeout def load(self, source: str, **kwargs) - List[Dict[str, Any]]: :param source: 网页 URL resp requests.get(source, headersself.headers, timeoutself.timeout) resp.raise_for_status() # 根据响应头判断编码 if resp.encoding is None or resp.encoding ISO-8859-1: resp.encoding resp.apparent_encoding soup BeautifulSoup(resp.text, html.parser) # 去掉 script 和 style 标签 for tag in soup([script, style, nav, footer, aside]): tag.decompose() # 提取正文文本 text soup.get_text(separator\n, stripTrue) return [ { text: text, metadata: { source: source, file_type: html, title: soup.title.string.strip() if soup.title else , fetched_at: resp.headers.get(date, ) } } ]注意事项同一网页内容可能随访问时间变化建议在 metadata 中记录抓取时间网站有反爬机制时需要适当设置请求头、限速、重试策略涉及商业网站、版权内容时请务必遵守目标网站的抓取规范和服务条款仅抓取你有权使用的内容。4.6 HTML / XML 批量文件导入除了在线网页项目中还经常遇到本地批量 HTML 文件。可以基于上面的 WebLoader 思路改造为本地文件遍历模式。这里不再重复核心提取逻辑但可以给出一个批量遍历的示例框架# 文件路径loaders/html_folder_loader.py import os from typing import List, Dict, Any from .base import BaseLoader from .web_loader import WebLoader class HtmlFolderLoader(BaseLoader): 本地 HTML 文件夹批量导入器 def __init__(self, folder_path: str, glob_pattern: str *.html): self.folder_path folder_path self.glob_pattern glob_pattern self._single_loader WebLoader() def load(self, source: str None, **kwargs) - List[Dict[str, Any]]: import glob pattern os.path.join(self.folder_path, **, self.glob_pattern) files glob.glob(pattern, recursiveTrue) all_docs [] for file_path in files: with open(file_path, r, encodingutf-8) as f: html_content f.read() from bs4 import BeautifulSoup soup BeautifulSoup(html_content, html.parser) for tag in soup([script, style, nav, footer, aside]): tag.decompose() text soup.get_text(separator\n, stripTrue) all_docs.append( { text: text, metadata: { source: file_path, file_name: os.path.basename(file_path), file_type: html } } ) return all_docs4.7 统一入口 main.py为了让多个导入器协作我们可以写一个统一入口按需选择加载器。# 文件路径main.py from loaders.text_loader import TextLoader from loaders.pdf_loader import PdfLoader from loaders.docx_loader import DocxLoader from loaders.database_loader import DatabaseLoader from loaders.web_loader import WebLoader def main(): # 示例导入一份 Markdown 文档 text_loader TextLoader() docs text_loader.load(./knowledge/intro.md) print(f文本加载完成共 {len(docs)} 个文档块) print(docs[0][metadata]) # 示例导入 PDF pdf_loader PdfLoader(split_by_pageTrue) pdf_docs pdf_loader.load(./knowledge/manual.pdf) print(fPDF 加载完成共 {len(pdf_docs)} 页) if pdf_docs: print(pdf_docs[0][text][:100]) # 示例导入数据库 config { host: localhost, user: root, password: password, database: business, charset: utf8mb4 } db_loader DatabaseLoader( connection_configconfig, sqlSELECT id, name, price, description FROM product LIMIT 100, text_template产品名称{name}价格{price}元描述{description} ) db_docs db_loader.load() print(f数据库加载完成共 {len(db_docs)} 条记录) if __name__ __main__: main()5. 数据清洗与预处理组件数据导入并不只是“读取 转换”。真实数据里往往存在大量噪声因此必须有一个清洗层对文本做统一处理。5.1 常见数据噪声类型噪声类型示例多余空白和换行连续多个空格、\r\n 混合HTML 标签残留div、p等特殊控制字符\x00、\x1f 等重复内容片断页眉、页脚、免责声明乱码编码识别错误导致的中文乱码超长无分隔内容一行内堆砌大量无意义字符5.2 基础清洗工具实现# 文件路径cleaners/text_cleaner.py import re class TextCleaner: 文本清洗工具类 staticmethod def clean_text(text: str) - str: # 1. 去除 HTML 标签 text re.sub(r[^], , text) # 2. 统一换行符 text text.replace(\r\n, \n).replace(\r, \n) # 3. 去除控制字符 text .join(ch for ch in text if ord(ch) 32 or ch in \n\t) # 4. 压缩连续空白行 text re.sub(r\n{3,}, \n\n, text) # 5. 去除首尾空白 text text.strip() return text staticmethod def deduplicate(docs: list) - list: 去除重复文档保留元数据最完整的那个 seen set() result [] for doc in docs: text_hash hash(doc[text]) if text_hash not in seen: seen.add(text_hash) result.append(doc) return result在接入实际项目时可以把TextCleaner插入到每个 Loader 的返回之前形成“读取 - 清洗 - 文档化”的流水线。5.3 表格数据转为文本的两种方式表格数据是 RAG 的难点之一。如果直接把 Markdown 表格原样塞给模型效果通常不好。建议转换为自然语言描述。方式一逐行转句子张三 25岁 北京 - 姓名张三年龄25岁城市北京方式二按业务场景自定义模板产品无线鼠标价格99元库存300件支持双模连接。哪种方式更好取决于下游模型的理解能力。通常模板方式更可控也更容易让模型“读懂”。6. 用 Cursor 快速编写和调试数据导入组件6.1 为什么用 Cursor 提升导入组件开发效率Cursor 是一个 AI 辅助编程工具支持在一个熟悉的 IDE 界面中通过对话方式生成代码、解释报错、重构代码。对于数据导入这类“模式固定但细节多”的组件开发Cursor 能帮我们快速生成某类数据源的加载器模板根据报错自动修复解析问题补全 metadata 字段提高数据可追溯性自动编写单元测试和边界检查。6.2 在 Cursor 中生成 PDF 加载器的 Prompts 示例假设我们已经在 Cursor 中打开了项目目录可以通过对话输入以下指令请帮我写一个 PDF 加载器要求 1. 使用 pypdf 库 2. 支持按页拆分文本 3. 返回统一的文档格式text metadata 4. metadata 中包含 source、file_name、page、total_pages 5. 处理空页和没有文字提取成功的页面 6. 添加基本的异常处理。Cursor 会在对话框里生成代码同时会建议你放置到哪个文件。你只需要点击应用再根据实际项目调整细节即可。6.3 利用 Cursor 排查导入问题数据导入最常见的报错有两类编码错误UnicodeDecodeError文件路径错误FileNotFoundError可以用 Cursor 直接选中报错信息点击“Ask AI”让它分析原因。例如下面的报错UnicodeDecodeError: gbk codec cant decode byte 0xad in position 20: illegal multibyte sequenceCursor 通常会给出类似回复打开文件时未指定 utf-8 编码或者文件本身是 GBK 编码。解决方案是统一指定编码或使用编码检测库chardet。这个流程能大大缩短排错时间但同时你也要有基本判断能力AI 给出的方案如果涉及下载新依赖要评估是否必要。6.4 给 Cursor 装“RAG 项目上下文”如果想提高 Cursor 生成代码的针对性可以在项目根目录创建一个CLAUDE.md或AGENTS.md文件描述项目的目录结构、代码规范和数据流。这样 Cursor 在回答时会优先参考项目上下文。例如# 项目说明 这是一个 RAG 数据导入项目。 目录结构 - loaders/ 存放各类数据导入器 - cleaners/ 存放文本清洗工具 所有加载器必须实现 BaseLoader 接口返回格式为 List[Dict[text, metadata]]。有了这个文件Cursor 生成的代码会更贴合项目风格减少人工修改量。7. 常见问题与排查思路数据导入环节的坑很多下面梳理几个高频问题。问题现象常见原因解决思路PDF 提取出来是空文本扫描版 PDF没有文本层接入 OCR 组件如 PaddleOCR、Tesseract中文乱码文件编码与读取编码不一致使用 utf-8 或自动检测编码Word 表格内容丢失仅遍历 paragraphs 没有遍历 tables同时提取表格内容并转为文本数据库导入过慢全表扫描数据量大分页查询、增量导入、并行处理网页抓取返回 403网站有反爬策略设置合理的请求头、Cookie控制频率导入后切分结果语义断裂原始文本段落结构被破坏保留段落分隔符切分时按段落优先HTML 文本中包含大量导航和页脚没有过滤无用标签清洗时去掉 nav、footer、script、style下面针对两个典型场景再展开说明。7.1 扫描版 PDF 如何处理如果确认 PDF 是扫描版pypdf.extract_text()基本无能为力。这时候有两个方向使用 OCR 工具如 PaddleOCR、Tesseract识别图片文字使用支持 OCR 的文档解析服务或商用方案。OCR 方案会增加计算成本和识别误差因此在正式环境要对识别结果做人工抽检。7.2 数据库增量导入怎么做如果业务库数据量很大每次全量导入会很慢而且可能影响线上数据库性能。建议方案在表中预留updated_at字段记录上次导入的最大id或时间戳每次只导入增量部分删除或更新已变化的文档保证向量库数据一致性。这个思路属于“增量同步”的范畴在真实项目中几乎是刚需后续可以在“索引更新策略”中单独讨论。8. 最佳实践与工程建议8.1 元数据是 RAG 精准检索的“隐藏钥匙”很多初学 RAG 的人只关心 “text” 内容忽略 metadata。但在实际检索中metadata 的价值非常大可以用来过滤检索范围比如只搜索某个产品的文档可以在展示答案时显示信息来源增强可信度可以为权限控制提供基础比如某些文档只允许特定人群检索。所以在设计 Loader 时尽量把来源、文件名、页数、更新时间、业务主键 ID 都写入 metadata。8.2 导入与切分的配合导入组件不必把切分也做了但要为切分保留“结构信号”。有几种做法保留段落空行切分器按空行切分为标题行增加标记例如前面加#对长文档利用 metadata 中的页码信息辅助切分。这样下游的切分组件才能做到“尽量保持语义完整”而不是机械地按固定字符数硬切。8.3 避免 SQL 注入和数据库安全问题如果数据库导入器支持动态传入 SQL需要格外注意安全边界。建议SQL 语句尽量由配置中心或白名单管理不允许用户随意输入数据库账号使用最小权限只授予 SELECT 权限生产环境禁止使用 root 账号连接业务库。涉及删除、更新操作时必须经过审批和备份流程不要在生产环境直接执行高危语句。8.4 幂等性与可重跑数据导入任务应该设计成可重复执行的。也就是说针对同一份数据多次运行导入结果应当一致不会产生重复脏数据。实现幂等性的常用方式在导入记录表中保存文档指纹hash或使用向量库的 upsert 能力通过文档 ID 覆盖更新或在导入前先删除同源数据。8.5 性能优化批量与并发如果一次性导入大量文件单线程逐个读取会非常慢。可以考虑使用concurrent.futures做多线程并发读取限制并发数避免打满数据库连接或引发文件句柄耗尽对数据库导入使用分批 分页查询对超大文件采取分片读取避免一次性加载到内存。示例并发读取多个文件from concurrent.futures import ThreadPoolExecutor, as_completed from loaders.pdf_loader import PdfLoader pdf_files [a.pdf, b.pdf, c.pdf] loader PdfLoader() def load_one(file_path): return loader.load(file_path) with ThreadPoolExecutor(max_workers4) as executor: futures [executor.submit(load_one, f) for f in pdf_files] for future in as_completed(futures): docs future.result() print(f完成加载共 {len(docs)} 个文档块)注意并发读取只适合 I/O 密集型任务如果解析过程本身很耗 CPU需要评估是否使用多进程。9. 总结与下一步学习方向这篇文章围绕 RAG 数据导入技术从组件化架构出发实现了几类常见数据源的导入器包括纯文本、PDF、Word、关系型数据库、网页和本地 HTML 文件夹并补充了文本清洗、元数据设计、并发性能优化以及 Cursor 辅助开发的实践思路。数据导入作为 RAG 系统中容易被低估的一环直接决定了后续切分、向量化和检索的天花板。一个稳定、可扩展的导入层能让你在数据源不断增加时依然保持清晰的工程结构。下一步你可以继续学习文本切分策略比如固定大小切分、递归字符切分、基于段落结构切分向量化与 Embedding 模型的选择向量数据库的索引设计与检索评测RAG 测评指标增量更新与数据一致性保障。如果你正在使用 Cursor 搭建 RAG 项目建议先把数据导入组件跑通再逐步叠加检索和大模型生成环节。每一步都跑稳了整个系统才不会在关键时刻掉链子。希望这篇内容能帮你少踩一些导入环节的坑有疑问也欢迎在评论区交流。
返回列表