知识切分与维护相关知识介绍

知识的切分与维护(RAG 核心实践)

在 RAG(检索增强生成)系统中,知识的切分与维护直接决定了系统的检索质量和回答准确性。本章节详细介绍这两个核心环节的最佳实践。


一、知识切分(Chunking)

1.1 什么是知识切分?

将原始文档(PDF、Word、Markdown、HTML、数据库记录等)切割成适合检索和 LLM 处理的文本块(Chunks)

markdown 复制代码
原始文档 (10,000 字)
       ↓ 切分
┌──────┬──────┬──────┬──────┬──────┐
│块1   │块2   │块3   │块4   │块5   │
│500字 │500字 │500字 │500字 │500字 │
└──────┴──────┴──────┴──────┴──────┘

1.2 为什么需要切分?

原因 说明
模型上下文限制 LLM 的上下文窗口有限(如 4K、8K、128K token)
检索精准度 小块更容易找到精准相关内容;大块会混入噪声
成本控制 向量化(Embedding)按 token 计费,小块成本可控
相关性计算 小块与问题的语义相似度计算更准确

1.3 切分策略详解

策略一:固定大小切分(Fixed-size Chunking)
python 复制代码
from langchain.text_splitter import CharacterTextSplitter

splitter = CharacterTextSplitter(
    chunk_size=500,      # 每块 500 字符
    chunk_overlap=50,    # 重叠 50 字符
    separator=" "        # 按空格切分
)
chunks = splitter.split_text(document)
优点 缺点
实现简单,速度快 可能切在句子中间,破坏语义
块大小可控 忽略文档结构
策略二:递归切分(Recursive Character Splitting)

最常用的通用策略,按优先级使用分隔符递归切分:

python 复制代码
from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50,
    separators=["\n\n", "\n", "。", ",", " ", ""]  # 优先级从高到低
)
# 优先按段落切 → 按句子切 → 按逗号切 → 按空格切 → 按字符切

切分过程:

swift 复制代码
原始文本
   ↓ 尝试用 "\n\n" 切分
如果块仍大于 500 → 用 "\n" 切分
   ↓
如果块仍大于 500 → 用 "。" 切分
   ↓
如果块仍大于 500 → 用 "," 切分
   ↓
如果块仍大于 500 → 按字符硬切
策略三:语义切分(Semantic Chunking)

使用 NLP 技术识别语义边界。

python 复制代码
from langchain_experimental.text_splitter import SemanticChunker
from langchain_openai.embeddings import OpenAIEmbeddings

splitter = SemanticChunker(
    embeddings=OpenAIEmbeddings(),
    breakpoint_threshold_type="percentile",  # 语义相似度骤降处切分
    breakpoint_threshold_amount=95
)
chunks = splitter.split_text(document)

原理:

  1. 计算相邻句子的语义相似度
  2. 相似度骤降的地方 → 语义边界 → 在此切分
优点 缺点
保留完整语义单元 计算开销大
块大小不均匀 需要 Embedding 模型
策略四:文档结构切分(Document Structure Chunking)

按 Markdown/HTML 的标题层级切分。

python 复制代码
from langchain.text_splitter import MarkdownHeaderTextSplitter

headers_to_split_on = [
    ("#", "Header1"),
    ("##", "Header2"),
    ("###", "Header3"),
]
splitter = MarkdownHeaderTextSplitter(headers_to_split_on)
chunks = splitter.split_text(markdown_document)

# 每个块会保留其所属的标题层级信息
# 块.metadata = {"Header1": "引言", "Header2": "背景"}

适用场景: 技术文档、维基百科、结构化手册

策略五:递归摘要切分(Proposition Chunking)

将文本分解为原子命题(每个命题是一个独立的最小信息单元)。

arduino 复制代码
原文:"OpenAI 于 2015 年由 Sam Altman 和 Elon Musk 等人创立。"
       ↓ 分解
命题1:"OpenAI 成立于 2015 年。"
命题2:"OpenAI 的联合创始人包括 Sam Altman。"
命题3:"OpenAI 的联合创始人包括 Elon Musk。"
优点 缺点
信息粒度最细 需要 LLM 辅助,成本高
跨块重组能力强 可能丢失上下文关联

1.4 重叠(Overlap)的作用

diff 复制代码
块1: [==========]
块2:    [==========]
块3:       [==========]
      ↑ 重叠区域

为什么需要重叠:

  • 避免关键信息被切在边界上导致丢失
  • 保持跨块的上下文连贯性(如段落间的过渡句)

经验值:

块大小 推荐重叠
128 token 16-32 token
256 token 32-64 token
512 token 64-128 token
1024 token 128-256 token

1.5 块大小选择指南

场景 推荐块大小 原因
问答(Q&A) 200-500 字符 答案通常简短
摘要生成 500-1000 字符 需要足够上下文
代码生成 500-1000 token 函数通常在这个长度
长文档分析 1000-2000 字符 需要完整段落
表格数据 按行切分 保留行完整性

经验法则: 不确定时,从 512 token(约 400 中文字符) 开始实验。


二、知识维护(Knowledge Maintenance)

2.1 什么是知识维护?

对已切分和索引的知识库进行更新、删除、版本控制、质量保证等一系列管理活动。

2.2 知识生命周期

markdown 复制代码
┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
│   采集   │ → │   清洗   │ → │   切分   │ → │   索引   │ → │   检索   │
└──────────┘    └──────────┘    └──────────┘    └──────────┘    └──────────┘
     ↑              ↑              ↑              ↑              ↑
     └──────────────┴──────────────┴──────────────┴──────────────┘
                            持续维护

2.3 核心维护操作

操作一:增量更新

新文档加入时,不重建整个索引。

python 复制代码
# 伪代码
def add_document(doc):
    chunks = split(doc)
    embeddings = embed(chunks)
    vector_db.insert(embeddings, metadata={
        "doc_id": doc.id,
        "timestamp": now(),
        "version": doc.version
    })

挑战: 旧文档删除/更新时,需要同步处理。

操作二:删除与替换
python 复制代码
# 方案1:逻辑删除(标记为无效)
vector_db.update(doc_id, {"is_deleted": True})
# 检索时过滤 is_deleted=False

# 方案2:物理删除(直接移除)
vector_db.delete(doc_id)

# 方案3:版本控制(保留历史)
vector_db.insert(new_version, metadata={"version": 2, "supersedes": old_id})
操作三:一致性维护

当源文档更新时,确保向量库同步。

策略 做法 适用场景
全量重建 每天/每周重新构建整个向量库 数据量小,变化频率低
增量更新 只处理变化的文档 数据量大,实时性要求高
双写 源文档更新时同步更新向量 要求强一致性
事件驱动 监听文档变更事件触发更新 复杂系统

2.4 质量保证机制

健康检查指标
指标 定义 告警阈值
覆盖度 可回答的问题比例 < 80%
新鲜度 知识库中最新文档的时间 > 30 天无更新
冗余度 相似度过高的文档对比例 > 20%
孤儿块 无法归属到任何文档的块 > 5%
脏数据率 格式错误/乱码的比例 > 1%
自动化监控流程
python 复制代码
# 伪代码:定期健康检查
def health_check():
    # 1. 抽样检查:随机选 100 个问题,看检索结果质量
    sample_questions = get_sample_questions()
    recall_score = evaluate_recall(sample_questions)
    
    # 2. 重复检测:找出相似度 > 0.95 的文档对
    duplicates = find_near_duplicates(threshold=0.95)
    
    # 3. 时效性检查:最后更新时间
    last_update = get_last_update_time()
    
    # 4. 生成报告
    report = {
        "recall": recall_score,
        "duplicate_count": len(duplicates),
        "days_since_update": (now() - last_update).days
    }
    
    if report["recall"] < 0.7:
        alert("检索召回率过低,需要优化切分策略或 Embedding 模型")

2.5 版本管理与回滚

yaml 复制代码
# 知识库版本记录
versions:
  - version: "v3.2"
    timestamp: "2026-05-18"
    changes: "新增产品文档 50 篇,更新 API 文档"
    recall_score: 0.85
    
  - version: "v3.1"
    timestamp: "2026-05-10"
    changes: "修复切分边界问题"
    recall_score: 0.82
    
  - version: "v3.0"
    timestamp: "2026-05-01"
    changes: "切换到语义切分策略"
    recall_score: 0.79

# 回滚命令
rollback --to v3.1

三、切分与维护的最佳实践

3.1 针对不同文档类型的策略

文档类型 推荐切分策略 维护重点
技术文档 按标题层级切分(MarkdownHeaderTextSplitter) 保持 API 版本同步
财报/年报 固定大小 + 大块(1000-2000 字符) 定期更新(季度/年度)
对话/聊天记录 按会话边界切分 隐私清理
代码库 按函数/类切分(Language-specific splitter) 与 Git 版本同步
法律合同 按条款切分 + 保留章节号 追踪修订历史
论文/学术 按章节切分(摘要、引言、结论加强权重) 引用关系维护

3.2 元数据设计

每个块应携带足够元数据,便于过滤和溯源。

json 复制代码
{
  "chunk_id": "doc_123_chunk_5",
  "doc_id": "doc_123",
  "doc_title": "2025年技术年报",
  "doc_type": "annual_report",
  "section": "3.2 研发投入",
  "page": 23,
  "timestamp": "2026-01-15",
  "version": 2,
  "author": "tech_team",
  "tags": ["finance", "R&D", "2025"],
  "embedding_model": "text-embedding-3-small"
}

3.3 索引策略

python 复制代码
# 混合索引:向量索引 + 关键词索引
class HybridIndex:
    def __init__(self):
        self.vector_index = VectorIndex()   # 语义检索
        self.keyword_index = InvertedIndex() # 关键词检索(BM25)
    
    def search(self, query):
        # 并行检索两种索引
        semantic_results = self.vector_index.search(query, top_k=10)
        keyword_results = self.keyword_index.search(query, top_k=10)
        
        # 融合排序(RRF:Reciprocal Rank Fusion)
        return fusion_rerank(semantic_results, keyword_results)

3.4 维护自动化流程

yaml 复制代码
# CI/CD Pipeline for Knowledge Base
name: Knowledge Base Maintenance

on:
  push:
    paths:
      - 'docs/**'
      - 'knowledge/**'

jobs:
  update-knowledge-base:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout documents
        uses: actions/checkout@v3
      
      - name: Detect changed documents
        run: python scripts/detect_changes.py
      
      - name: Re-chunk changed documents
        run: python scripts/chunking.py --files $(cat changed_files.txt)
      
      - name: Update vector database
        run: python scripts/update_index.py --mode incremental
      
      - name: Run health checks
        run: python scripts/health_check.py
      
      - name: Notify on failure
        if: failure()
        run: slack notification "知识库更新失败"

四、常见问题与解决方案

问题 可能原因 解决方案
检索不到相关块 块太小,切碎了关键信息 增大块大小或增加重叠
检索结果包含噪声 块太大,混入无关内容 减小块大小
答案不连贯 相关信息分散在不同块 增加重叠或使用多跳检索
更新后旧答案仍出现 旧向量未被删除 使用版本标记 + 过滤
相似文档回答矛盾 知识库中存在冲突信息 增加时效性权重 + 人工复核
检索速度慢 向量数据库未优化 建立索引、使用 ANN 而非 exact search

五、总结

erlang 复制代码
┌─────────────────────────────────────────────────────────────────┐
│                    知识切分与维护核心要点                         │
├─────────────────────────────────────────────────────────────────┤
│ 切分策略:                                                        │
│   • 通用首选:递归切分(RecursiveCharacterTextSplitter)          │
│   • 结构化文档:按标题层级切分                                     │
│   • 追求精度:语义切分                                            │
│   • 块大小:512 token 起步,按场景调整                            │
│   • 重叠:块大小的 10-20%                                        │
├─────────────────────────────────────────────────────────────────┤
│ 维护策略:                                                        │
│   • 增量更新而非全量重建                                          │
│   • 元数据设计要包含版本、时间戳、来源                              │
│   • 定期健康检查(召回率、冗余度、新鲜度)                          │
│   • 版本管理支持回滚                                              │
│   • 自动化 CI/CD 流程维护                                         │
└─────────────────────────────────────────────────────────────────┘

一句话总结:

好的切分让检索更精准,好的维护让知识库长治久安。两者共同决定了 RAG 系统的上限。


文档版本:v1.0

最后更新:2026-05-18

相关推荐
卷帘依旧2 小时前
RAG 的设计问题与局限性分析
面试
小为资料库3 小时前
2026年5月16日教资面试真题汇总(中小幼各科全)
面试·职场和发展
卷帘依旧3 小时前
模式驱动开发(SSD)
面试
星辰_mya3 小时前
彩云之上——[特殊字符]的架构师
java·后端·微服务·面试·架构
BING_Algorithm4 小时前
深入理解JVM垃圾回收
jvm·后端·面试
Larry_Yanan4 小时前
QML面试常见问题(一)QML中组件呈现方式的方法有哪些
开发语言·c++·qt·ui·面试
knight_9___4 小时前
大模型project面试7
人工智能·python·算法·面试·大模型·agent
humcomm6 小时前
2026年 Java 面试新特点
java·开发语言·面试
AI人工智能+电脑小能手7 小时前
【大白话说Java面试题 第56题】【JVM篇】第16题:JVM有哪些垃圾收集器?
java·开发语言·jvm·面试