30天从零开始学AI应用开发(Day 18):文档切分与检索优化:RAG 效果好坏的分水岭

这是系列的第 18 篇。整个系列写给零基础、想入行 AI 的朋友,每天一篇,30 天后你会做出 3 个能写进简历的项目。

这篇解决什么问题

昨天你的最小 RAG 跑起来了,但有人反馈:简单问题答得挺准,问复杂一点的就答非所问了。

这是个好现象,说明你已经越过了"能不能跑"的阶段,进入"效果好不好"的阶段。今天这篇就是分水岭。RAG 项目做得好不好,八成取决于一个不起眼的环节:文档怎么切。

很多人做完 demo 就停在这里,因为不知道问题出在哪。今天把切分的门道讲清楚。

一、为什么切分这么重要

先回到原理。RAG 的流程是:提问 → 找出最相关的几个片段 → 交给 AI 回答。

注意这里的关键词是"片段"。AI 最终看到的不是你整份文档,而是检索出来的那几段。所以片段切得对不对,直接决定 AI 看到的内容对不对。

切得太碎会怎样?比如一句话被切成两半,"差旅费报销需要提交申请单"和"出差结束后五个工作日内提交发票"。如果提问命中前半句,AI 只看到半条信息,回答就会残缺。

切得太大又会怎样?一段里混了报销、请假、考勤三件事。检索命中了这一段,AI 就要从一堆无关内容里找答案,容易被干扰,还浪费 token。

所以好的切分标准只有一句话:一个片段只讲一件事。

二、三个实用的切分原则

原则一:优先按语义边界切,别机械按字数切。

文档本身就有天然的边界:段落、标题、列表项。按这些边界切,切出来的片段是完整的。硬按 500 字一刀切,很容易把一段完整的话劈开。

原则二:设置重叠区。

相邻片段之间留一点重复内容。比如第 1 段是 1 到 500 字,第 2 段就从 450 字开始,重叠 50 字。这样即使关键信息正好落在边界上,也不会被劈掉。这个参数通常叫 chunk_overlap。

原则三:给每个片段贴上"身份证"。

片段入库时顺便记下它来自哪个文件、第几页、哪个标题。检索出来的时候,你就知道答案的出处了:

python 复制代码
{
    "text": "差旅费报销流程:先提交申请单......",
    "source": "员工手册.pdf",
    "page": 12,
    "section": "第五章 费用管理"
}

这个元数据很有用,一是能在回答里标注来源(用户会更信任),二是能做过滤(比如只在某一类文档里搜)。

三、动手改一版切分代码

先看最朴素的写法,按固定长度切:

python 复制代码
def split_naive(text, size=500):
    """最朴素的切法:每 500 字一刀(有缺陷,不推荐)"""
    return [text[i:i + size] for i in range(0, len(text), size)]

问题很明显:不问语义,硬切。改进版加上重叠:

python 复制代码
def split_with_overlap(text, size=500, overlap=50):
    """加重叠的切法,避免边界信息被劈开"""
    chunks = []
    start = 0
    while start < len(text):
        end = start + size
        chunks.append(text[start:end])
        start = end - overlap          # 关键:下一次从重叠处开始
    return chunks

再进一步,优先在段落边界切。这里可以直接用 LangChain 提供的成熟工具,不用自己造轮子:

python 复制代码
from langchain_text_splitters import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,           # 每段目标长度
    chunk_overlap=50,         # 重叠字数
    separators=["\n\n", "\n", "。", "!", "?", " ", ""]   # 优先在这些位置切
)

chunks = splitter.split_text(长文本)
print(f"切成了 {len(chunks)} 段")

separators 这个列表是精髓,它会从上到下依次尝试:先按空行切(段与段),切完发现某段还是太长,再按换行切,还长就按句号切,最后才按字切。这样切出来的片段尽量保持语义完整。

装包命令是 pip install langchain-text-splitters,用清华源更快。

四、比切分更狠的三招:检索优化

切分是基础,想再往上提一档,还有三个技巧值得知道。

第一招:多召回几条再筛。不要只取 3 条,取 10 条,然后让 AI 或者用算法再筛一遍。多给一点余地,命中率会明显提升。

第二招:改写问题再检索。用户的提问往往很口语,比如"那个报销的事咋弄"。可以让 AI 先把问题改写成规范的检索语句,再去查:

python 复制代码
def rewrite_question(question):
    prompt = f"""把下面的问题改写成适合检索的规范表述,
只输出改写结果,不要解释:
{question}"""
    # ......调用 API 返回改写后的问题......
    return rewritten

改写完再检索,命中率经常有肉眼可见的提升。

第三招:混合检索。向量检索擅长"意思相近",但对专有名词不敏感。比如搜"泰坦尼克号",向量检索可能返回一堆"船难""沉船"的内容,而关键词检索能精准锁定这个词。把两种检索的结果合并,效果比单独用一种好很多。

这三招你了解就行,做项目时用上前两招,已经比多数入门项目讲究了。

五、怎么判断自己的切分合不合格

给你一个自测方法:随便抽三个片段读一遍。

  • 每段是不是在讲一件完整的事?
  • 把这段单独拿给一个不了解背景的人看,他能不能看懂?
  • 有没有哪个片段是半句话开头、半句话结尾?

三个问题都是"是",切分就算过关了。这个自测很快,但极其有效,比调参数管用。

常见报错排查

报错一:langchain 装不上或导入报错。

版本问题居多。教程里的导入路径会随版本变化,如果 from langchain.text_splitter import ... 报错,换成 from langchain_text_splitters import ... 试试,这是新版路径。

报错二:chunk_size 设多少合适?

没有标准答案,500 到 1000 是常见区间。判断标准是内容密度:技术文档、规范类文字密集,可以小一点;散文、说明性内容可以大一点。用你自己的资料试两三个值,对比检索效果,比问别人更靠谱。

报错三:切出来的片段里有一堆空白或乱码。

PDF 转文本时常见,页眉页脚、页码混进来了。入库前做一遍清洗,去掉空行和重复的页眉,效果立竿见影。

报错四:中文按默认分隔符切效果差。

有些默认配置对中文不友好(英文按空格分词,中文没有空格)。检查 separators 里有没有中文标点,像"。""?""!"这些一定要加进去。

今天的作业

拿你昨天的资料,用两种参数各跑一遍(比如 chunk_size 设 300 和 800),问同一个问题,对比检索出来的片段有什么不同。把观察结果贴到评论区。

这个对比做过一次,你对切分的理解就超过大部分只跑过 demo 的人了。

明天预告

Day 19:《项目二完结:RAG 知识库问答系统,把自己攒的资料变成私人顾问》。明天是项目二的大结局,我们会把前面四天学的东西组装成一个完整系统:能导入文档、能问答、能标出来源、资料里没有就老实说不知道。这是你简历上第二个项目,含金量比第一个高。


*系列目录:30天从零开始学AI应用 开发

相关推荐
张彦峰ZYF4 小时前
越过边界之前:Reward Seeker 实验如何改写智能体安全的时间逻辑
人工智能·ai agent·anthropic·智能体安全·reward seeker·“控制评价过程”泛化跨领域策略·envbom
拓恒技术5 小时前
无人机巡检AI算法的工程化落地:从需求到交付的5个核心环节
人工智能·算法·无人机
罗西的思考7 小时前
AI 时代的 “房谋杜断”:如何培养能力、品味与判断力
人工智能·算法·机器学习
字节跳动视频云技术团队7 小时前
720P 直升 8K,解密 2026 抖音美好奇妙夜巨幕超分黑科技
人工智能·音视频开发
打工仔折腾 AI8 小时前
在 Ubuntu ARM64 部署 Q1 V3.0 MuJoCo 模型:加载、单步推理与执行器响应解析
linux·运维·人工智能·python·深度学习·ubuntu·性能优化
特别关注外国供应商8 小时前
Qualys TotalAI:AI 安全治理的四大支柱
ai·大模型安全·ai数据安全·qualys·ai安全治理·ai saas 治理·ai代码安全
逐米时代8 小时前
从试点验证到协同深化:制造业AI转型三年路线图设计方法
人工智能
GlobalInfo8 小时前
全球及中国风电叶片检测机器人行业研究报告(2026版):市场现状、行业前景与占有率分析
运维·网络·人工智能·机器人
stormzhangV9 小时前
AI 越强,失业越严重
人工智能·aigc
夏文强9 小时前
Rerank 与混合检索:怎么让 RAG 从「能用」变成「好用」
人工智能·大模型·向量数据库·rag·检索增强生成