RAG 数据源全景解析指南:从 .txt 到知识图谱的 7 大阵营 47 种格式


那个......RAG 处理 PDF 和 Excel 具体是怎么弄的呀?

听到面试官这个问题时,你的大脑是不是瞬间死机,然后开始疯狂输出:「呃......就是......解析......然后......切片?」

停停停!隔着屏幕我都替你抠出三室一厅了。

别担心,救星来了。今天这篇博客,就是专门为你量身定制的「反懵圈指南」。咱们不背死板的八股文,直接把各种文档格式的解析套路摸得透透的------从 .txt 的编码鬼故事,到扫描件 PDF 的 OCR 流水线,从嵌套 JSON 怎么拍扁,到视频怎么抽出关键帧。保证你看完之后,不仅能把面试官问服,还能让他忍不住点头说------

「这小伙子/小姑娘有点东西!」


目录

  • [〇、为什么数据解析才是 RAG 的「水下冰山」](#〇、为什么数据解析才是 RAG 的「水下冰山」)
  • 一、基础文本与文档
    • [1.1 纯文本 (.txt)](#1.1 纯文本 (.txt))
    • [1.2 Word 文档 (.docx)](#1.2 Word 文档 (.docx))
    • [1.3 PowerPoint (.pptx)](#1.3 PowerPoint (.pptx))
    • [1.4 Excel / CSV (.xlsx .csv)](#1.4 Excel / CSV (.xlsx .csv))
    • [1.5 PDF(三种类型,三种策略)](#1.5 PDF(三种类型,三种策略))
    • [1.6 Markdown (.md)](#1.6 Markdown (.md))
    • [1.7 邮件 (.eml)](#1.7 邮件 (.eml))
    • [1.8 EPUB (.epub)](#1.8 EPUB (.epub))
  • [二、多媒体数据(多模态 RAG)](#二、多媒体数据(多模态 RAG))
    • [2.1 图像:三重提取](#2.1 图像:三重提取)
    • [2.2 音频:STT 语音识别](#2.2 音频:STT 语音识别)
    • [2.3 视频:关键帧 + 语音轨](#2.3 视频:关键帧 + 语音轨)
  • 三、结构化数据(数据库)
    • [3.1 关系型数据库:Text2SQL](#3.1 关系型数据库:Text2SQL)
    • [3.2 知识图谱:GraphRAG](#3.2 知识图谱:GraphRAG)
  • 四、半结构化数据
    • [4.1 JSON:嵌套结构的扁平化](#4.1 JSON:嵌套结构的扁平化)
    • [4.2 日志:去噪 + 聚合](#4.2 日志:去噪 + 聚合)
  • 五、实时动态数据
  • 六、企业私有数据
  • 七、公开权威数据
  • 八、一表总结

阅读导航

复制代码
                              ┌──────────────────────────────┐
                              │  ① 基础文本与文档              │
                              │  .txt .docx .pptx .xlsx .pdf  │
                              │  .md  .epub .eml              │
                              └──────────────────────────────┘
                                              │
  ┌──────────────────────────────┐   ┌────────┴─────────┐   ┌──────────────────────────────┐
  │  ② 多媒体(多模态 RAG)       │   │                   │   │  ③ 结构化数据                 │
  │  .jpg .mp3 .mp4             │   │   RAG 数据源全景   │   │  MySQL · 知识图谱            │
  └──────────────────────────────┘   └────────┬─────────┘   └──────────────────────────────┘
                                              │
  ┌──────────────────────────────┐   ┌────────┴─────────┐   ┌──────────────────────────────┐
  │  ④ 半结构化数据               │   │                   │   │  ⑤ 实时动态数据               │
  │  JSON .xml 日志              │   │  ⑥ 企业私有数据    │   │  天气/股票/新闻 API           │
  └──────────────────────────────┘   │  Confluence Notion │   └──────────────────────────────┘
                                     │  ⑦ 公开权威数据    │
                                     │  Wikipedia arXiv   │
                                     └───────────────────┘

〇、为什么数据解析才是 RAG 的「水下冰山」

大多数 RAG 教程教你:装一个 PDF loader → 调 text_splitter → 调 embedding → 调 LLM,完事。

生产环境中的真实情况是:

客户丢过来 500 页扫描件 + 嵌套 8 层合并单元格的 Excel + 一段没有字幕的会议录音,

你的 pipeline 在第一步就「哑火」了。

数据解析占 55%,而「Prompt 与生成」只占 10%。这就是冰山------海面上是优雅的向量检索,海面下是编码检测、版面分析、OCR 纠错、表格语义化、语音转文字......


一、基础文本与文档

核心要点 :基础文档占了 RAG 数据源的 60% 以上。记住三条铁律------① 永远先做编码检测(chardet);② .docx/.pptx 本质是 ZIP 包,解压后按 XML 解析;③ PDF 有三种人格(原生/扫描/混合),先判断类型再选方案。
这是 RAG 的「主食」。看似简单,每种格式都有自己的暗坑。


1.1 纯文本 (.txt)

.txt 解析的核心问题只有一个:编码。中文环境尤其严重------同一个文件可能是 UTF-8、GBK、GB2312、Big5。

python 复制代码
import chardet

with open("unknown.txt", "rb") as f:
    raw = f.read()

result = chardet.detect(raw)
text = raw.decode(result["encoding"] or "utf-8", errors="replace")

# 清洗控制字符、统一换行符
import re
text = re.sub(r"[\x00-\x08\x0b\x0c\x0e-\x1f]", "", text)
text = text.replace("\r\n", "\n").replace("\r", "\n")
常见坑 表现 解决
编码检测失败 中文变 "é��误" chardet.detect_all() 候选逐个试
BOM 头残留 开头有  text.lstrip("")
超大文件 OOM 流式读取 f.read(65536) 循环

1.2 Word 文档 (.docx)

.docx 本质上是一个 ZIP 压缩包,内部是一组 XML 文件:

python 复制代码
from docx import Document

doc = Document("report.docx")

for para in doc.paragraphs:
    if para.text.strip():
        level = 0
        if para.style.name.startswith("Heading"):
            level = int(para.style.name.replace("Heading ", ""))
        # level=1 是 H1,level=2 是 H2,0 是正文
        # 切片时以 H2 为边界,H1 作为文档标题元数据
.docx vs .doc 新格式 (.docx) 旧格式 (.doc)
内部结构 ZIP + XML OLE 二进制
推荐工具 python-docx antiword / libreoffice 转换
建议 直接解析 先转 .docx 再解析

1.3 PowerPoint (.pptx)

PPT 的文本不是线性的------它散布在文本框、表格和备注中,有绝对坐标

关键洞察 :PPT 的演讲者备注往往是正文的精华浓缩,对 RAG 的价值远超幻灯片上的要点文字。解析时务必带上。

python 复制代码
from pptx import Presentation

prs = Presentation("slides.pptx")
for i, slide in enumerate(prs.slides, 1):
    # 收集文本框,按 top 坐标(y)排序
    shapes = [(s.top, s.text_frame.text)
              for s in slide.shapes if s.has_text_frame]
    shapes.sort(key=lambda x: x[0])

    title = shapes[0][1] if shapes else ""
    body = "\n".join(t for _, t in shapes[1:] if t.strip())

    notes = ""
    if slide.has_notes_slide:
        notes = slide.notes_slide.notes_text_frame.text

1.4 Excel / CSV (.xlsx .csv)

表格绝对不能当纯文本切片。一张表被切成碎片后,语义全部丢失。

python 复制代码
import pandas as pd

df = pd.read_excel("data.xlsx")

# 策略 A:Markdown 化
md = df.to_markdown(index=False)

# 策略 B:行级展开
for _, row in df.iterrows():
    parts = [f"{col}是{row[col]}" for col in df.columns]
    sentence = ",".join(parts)  # "姓名是张三,部门是技术,工资是15000"
解法
合并单元格 df.fillna(method='ffill') 向下填充
CSV 分隔符不一定是逗号 csv.Sniffer().sniff(sample) 自动检测
数字丢失前导零 读入时指定 dtype=str

1.5 PDF(三种类型,三种策略)

PDF 是 RAG 数据解析的「终极 Boss」。它有三种截然不同的人格:

三种解析引擎对比

引擎 原生 PDF 扫描 PDF 表格提取 中文 OCR
PyMuPDF (fitz) ★★★★★ ★★★☆ ★★★★
pdfplumber ★★★★ ★★★★★ ★★★☆
PaddleOCR ★★★★★ ★★★★★
Tesseract ★★★☆ ★★☆
LlamaParse ★★★★ ★★★☆ ★★★★ ★★★☆

原生 PDF 代码

python 复制代码
import fitz

doc = fitz.open("native.pdf")
blocks = []

for page in doc:
    text_dict = page.get_text("dict")
    for block in text_dict["blocks"]:
        if block["type"] == 0:  # 文本块
            text = "".join(s["text"] for line in block["lines"]
                                    for s in line["spans"])
            if text.strip():
                blocks.append({
                    "page": page.number + 1,
                    "text": text.strip(),
                    "y": block["bbox"][1]  # 垂直位置,用于排序
                })

# 按页面+垂直位置排序 → 阅读顺序
blocks.sort(key=lambda b: (b["page"], b["y"]))

扫描件 PDF 代码

python 复制代码
from pdf2image import convert_from_path
from paddleocr import PaddleOCR

images = convert_from_path("scanned.pdf", dpi=300)
ocr = PaddleOCR(use_angle_cls=True, lang="ch", show_log=False)

full_text = []
for i, img in enumerate(images, 1):
    result = ocr.ocr(f"/tmp/page_{i}.png", cls=True)
    if result and result[0]:
        page_text = "\n".join(line[1][0] for line in result[0])
        full_text.append(f"--- Page {i} ---\n{page_text}")

1.6 Markdown (.md)

Markdown 是对 RAG 最友好的格式------标题天然就是切片边界,代码块有语言标注,链接有 URL 上下文。

复制代码
切片策略:
  # H1 → 文档级元数据(不参与切片,作为 document title)
  ## H2 → 切片边界(每个 H2 区块独立成一个 chunk)
  ### H3 → 作为 H2 chunk 的子结构保留
  ```代码块 → 保留语言标注(如 "python"),内容不参与切片分割
python 复制代码
import re

with open("doc.md") as f:
    content = f.read()

# 按 ## 二级标题切分
sections = re.split(r"\n(?=## )", content)
for sec in sections:
    m = re.match(r"^#{1,6}\s+(.+)", sec)
    title = m.group(1) if m else ""
    body = sec[m.end():].strip() if m else sec.strip()
    # 每个 (title, body) 是一个 chunk

1.7 邮件 (.eml)

邮件的独特价值:元数据极其丰富------发件人、收件人、时间、主题、正文、附件------且在企业知识库中,大量隐性知识只存在于邮件中。

python 复制代码
import email
from email import policy
from bs4 import BeautifulSoup

with open("message.eml", "rb") as f:
    msg = email.message_from_binary_file(f, policy=policy.default)

# 元数据:检索时可作为过滤条件
meta = {k: msg[k] for k in ["From", "To", "Subject", "Date"]}

# 正文:优先 text/plain,降级 text/html
body = ""
for part in msg.walk():
    if part.get_content_type() == "text/plain":
        body = part.get_content(); break
    elif part.get_content_type() == "text/html" and not body:
        body = BeautifulSoup(part.get_content(), "lxml").get_text()

1.8 EPUB (.epub)

EPUB 也是 ZIP 包,内部是 XHTML 章节。用 ebooklib 按章节提取即可。

python 复制代码
from ebooklib import epub
from bs4 import BeautifulSoup

book = epub.read_epub("book.epub")
for item in book.get_items():
    if item.get_type() == 9:  # ITEM_DOCUMENT
        text = BeautifulSoup(item.get_content(), "lxml").get_text()

二、多媒体数据(多模态 RAG)

核心要点:多模态 RAG 的统一范式是「先转文字,再进 RAG」。图像用 OCR+视觉描述+EXIF 三重提取,音频用 Whisper STT,视频是两者的组合,关键是按时间轴对齐。
核心范式:先转为文本,再进入 RAG 流水线。


2.1 图像:三重提取

一张图片可以提取三种互补文本,拼接后形成完整语义:

提取层 工具 输出示例
① OCR 文字 PaddleOCR "欢迎光临 · 营业时间 9:00-22:00"
② 视觉描述 GPT-4V / Qwen-VL "一张街边店铺的照片,玻璃门上贴着营业时间告示......"
③ EXIF 元数据 Pillow "拍摄时间: 2026-07-01, GPS: 39.9N 116.4E"

三者拼接 → 一个包含「画面里有什么 + 画面上写了什么 + 何时何地」的完整 chunk。

python 复制代码
from paddleocr import PaddleOCR
from PIL import Image
import base64

ocr = PaddleOCR(use_angle_cls=True, lang="ch", show_log=False)
result = ocr.ocr("photo.jpg", cls=True)
ocr_text = "\n".join(line[1][0] for line in result[0]) if result[0] else ""

# 视觉描述 → 调用多模态 LLM API
img_b64 = base64.b64encode(open("photo.jpg", "rb").read()).decode()
description = call_vision_llm(img_b64)  # 返回自然语言描述

# EXIF
exif = Image.open("photo.jpg")._getexif() or {}

2.2 音频:STT 语音识别

python 复制代码
import whisper

model = whisper.load_model("medium")  # 中文用 medium,英文可用 small
result = model.transcribe("audio.wav", language="zh", task="transcribe")

# 每段带时间戳
for seg in result["segments"]:
    print(f"[{seg['start']:.1f}s - {seg['end']:.1f}s] {seg['text']}")

2.3 视频:关键帧 + 语音轨

视频 = 图像序列 + 音频轨。解析策略是双通道并行,时间轴对齐

python 复制代码
import cv2, subprocess

# 提取音频
subprocess.run(["ffmpeg", "-i", "video.mp4", "-vn", "-ar", "16000",
                "-ac", "1", "audio.wav", "-y"], capture_output=True)
audio_text = transcribe("audio.wav")  # 复用 2.2 的 STT

# 关键帧:每 5 秒取一帧
cap = cv2.VideoCapture("video.mp4")
fps = cap.get(cv2.CAP_PROP_FPS)
for t in range(0, int(cap.get(cv2.CAP_PROP_FRAME_COUNT)), int(fps * 5)):
    cap.set(cv2.CAP_PROP_POS_FRAMES, t)
    _, frame = cap.read()
    cv2.imwrite(f"/tmp/frame_{t/fps:.1f}s.jpg", frame)

三、结构化数据(数据库)

核心要点:结构化数据不要 dump 成文本。关系型数据库走 Text2SQL------把 Schema 注入 Prompt,让 LLM 写 SQL 实时查。知识图谱走 GraphRAG------实体关系 + 向量语义混合检索。

3.1 关系型数据库:Text2SQL

对于 MySQL / PostgreSQL,不要把数据 dump 成文本。用 Text2SQL 让 LLM 生成查询语句实时检索:

python 复制代码
from sqlalchemy import create_engine, inspect, text

def get_schema(engine):
    """提取所有表的列信息作为 LLM 上下文"""
    insp = inspect(engine)
    return "\n".join(
        f"TABLE {t}:\n  " + "\n  ".join(
            f"{c['name']} ({c['type']})" for c in insp.get_columns(t)
        )
        for t in insp.get_table_names()
    )

# Prompt = Schema + 用户问题 → LLM → SQL → execute → 结果

3.2 知识图谱:GraphRAG

传统 RAG 找「相似文本」,GraphRAG 还能找「实体关系」:

GraphRAG 三阶段:离线构建 (文本 → 实体抽取 → 图谱入库)→ 在线检索 (向量 + 图谱混合查询)→ 生成(双源上下文注入 LLM)。


四、半结构化数据

核心要点:JSON 的核心问题是深层嵌套------LLM 读嵌套 JSON 会「迷失」。解决方法是扁平化:对象列表转 Markdown 表格。日志的核心问题是噪声太大------先过滤 DEBUG/INFO 级别,再聚合相同错误。

4.1 JSON:嵌套结构的扁平化

JSON 有深层嵌套。直接当纯文本给 LLM → 嵌套深了 LLM 会「迷失」。正确做法是扁平化

复制代码
原始 JSON:                        扁平化后:
{                                 | company | name | dept | salary |
  "company": "Apple",             |---------|------|------|--------|
  "employees": [                  | Apple   | 张三  | 技术  | 15000  |
    {"name":"张三","dept":"技术"},  | Apple   | 李四  | 销售  | 12000  |
    {"name":"李四","dept":"销售"}   |
  ]                               LLM 对表格的理解准确度 >> 嵌套 JSON
}
python 复制代码
def flatten_json(data, max_depth=3):
    if isinstance(data, list) and data and isinstance(data[0], dict):
        # 对象列表 → Markdown 表格
        keys = list(data[0].keys())[:10]
        lines = ["| " + " | ".join(keys) + " |",
                 "| " + " | ".join(["---"] * len(keys)) + " |"]
        for item in data[:100]:
            lines.append("| " + " | ".join(str(item.get(k,""))[:50] for k in keys) + " |")
        return "\n".join(lines)
    return str(data)

4.2 日志:去噪 + 聚合

日志的核心问题不是解析,是噪声太大。Info 级别的常规日志没有检索价值,需要过滤:

复制代码
原始日志 (10 万行) → 正则提取级别 → 过滤 DEBUG/INFO
→ 保留 WARN/ERROR + 异常堆栈 → 相同错误聚合计数
→ "Connection timeout (×42)"  → 干净的 chunks

五、实时动态数据

核心要点:时效性数据不要提前索引。用 Agent 的 Function Calling 机制在查询时实时拉取------这是「RAG + Agent」融合架构的典型场景。

对于天气、股票、新闻等时效性数据,不提前索引,查询时实时拉取。这是 Agent 的 Function Calling 机制,不是传统 RAG 的向量检索。


六、企业私有数据

核心要点:企业 RAG 和公网 RAG 最大的区别是权限。Confluence/Notion 解析时要保留页面→用户组的权限映射,检索时做权限过滤。业务系统数据走 Text2SQL,不要全量 dump。

平台 特有挑战 策略
Confluence / Notion 层级结构 + 富文本 + 权限 API 递归拉取 → 保留空间/页面层级元数据 → 权限映射到 RAG 过滤
飞书 / 钉钉文档 国内 API 限频 增量同步 + Webhook 监听变更 → 只处理 diff
CRM / ERP 结构化 + 自然语言混查 静态知识(手册)→ 向量检索;动态数据(客户列表)→ Text2SQL

关键点:企业数据的 RAG 必须带权限过滤------CEO 能搜到的内容,实习生不应该搜到。这是企业 RAG 和公网 RAG 最大的区别。


七、公开权威数据

核心要点:公开数据优先用预清洗数据集(HuggingFace / arXiv API),不要自己爬。学术和法律法规要按章节/条款号切片,保留元数据用于引用溯源。

  • 维基百科 :直接用 HuggingFace 预清洗数据集 wikimedia/wikipedia,不要自己爬
  • arXiv :API 免费、返回结构化元数据(标题/作者/摘要/分类)。保留元数据用于引用溯源
  • 政府/法律数据 :格式高度规范但冗长。建议按法条编号切片,不要按字数硬切

八、一表总结

数据源 核心工具 核心挑战 RAG 策略 难度
.txt chardet 编码鬼故事 直接切片
.docx python-docx 表格+图片混杂 结构感知切片 ★★
.pptx python-pptx 文本框阅读顺序 按幻灯片切片 ★★
.xlsx pandas 合并单元格 Markdown 化 / Text2SQL ★★
原生 PDF PyMuPDF 版面分析 坐标排序+按章节切片 ★★★
扫描 PDF PaddleOCR OCR 识别率 OCR→纠错→切片 ★★★★
.md 标准库 几乎没有 按标题层级切片
.epub ebooklib XHTML 清洗 按章节切片 ★★
.eml email 模块 附件递归 元数据+正文 ★★
图片 PaddleOCR+GPT-4V 三合一融合 多模态向量 ★★★★
音频 Whisper 多人说话人分离 STT→分段 ★★★
视频 cv2+Whisper 帧去重+时间轴对齐 双通道并行 ★★★★★
数据库 SQLAlchemy Schema 注入设计 Text2SQL ★★★
知识图谱 Neo4j 实体消歧 GraphRAG ★★★★★
JSON json 模块 深层嵌套 扁平化→表格 ★★
日志 正则+聚合 噪声 过滤+聚合 ★★
实时 API requests 时效性 Agent Function Call ★★★
Confluence REST API 权限映射 层级感知+权限过滤 ★★★★
Wikipedia datasets 更新频率 预训练数据集
arXiv arxiv API 公式/图表 元数据增强 ★★★

One more thing :一个好的 RAG 系统,70% 的代码在数据管道上,20% 在检索策略上,只有 10% 在 Prompt 上。但大多数教程把比例反过来教。如果你在面试中能把上面这个表的内容讲出来------面试官会知道你在生产环境做过 RAG,而不只是跑过 demo。


写在最后

如果这篇博客帮你搞清楚了 RAG 数据解析的全貌,不妨:

  • 👍 点赞------让更多人看到这份「反懵圈指南」
  • ⭐ 收藏------面试前翻出来看一遍,底气至少 +50%
  • 💬 评论区聊聊------你遇到过最头疼的格式是什么?扫描件 PDF 还是嵌套 8 层的 JSON?我赌扫描件 PDF 赢

关注我,持续输出「能直接写到简历上」的 AI 实战内容。


编程星辰海· 2026-07 · MIT License

相关推荐
chanalbert4 小时前
Agent 工程化指南(二):记忆与规划 — 让 Agent “记得住“且“做得对“
agent·memory·rag·mcp
ahauedu2 天前
多租户 RAG 知识库系统基于Spring Boot 4.0.5+Spring AI 2.0.0 + Milvus
spring·rag·springai2.0
染指11102 天前
50.llama_index-文档分割器(文本)
llama·rag·llamaindex
前端Baymax3 天前
Agent工具调用中无限重试死循环的根因与修复
ai·agent·rag
接着奏乐接着舞。4 天前
【2026年7月最新】69道RAG面试题
前端·人工智能·后端·aigc·embedding·rag
大鹅同志4 天前
Agent Runtime Evaluation Platform — AI Agent 运行时全维度质量评估平台
ai·langchain·agent·rag·langgraph·vibecoding·llm-as-judge
荣--4 天前
业务智能体实战笔记:分层消除不确定性(一)|总纲:把不确定性从 LLM 侧转移到工程侧
prompt·rag·ai agent·spring ai·业务智能体
阿拉斯攀登5 天前
Prompt 工程与答案生成优化
prompt·agent·memory·知识库·向量数据库·rag
阿拉斯攀登5 天前
企业知识库实战:从 0 到 1 落地全记录
agent·ai编程·loop·rag