RAG 每日一技(三):不止文本,代码和Markdown如何优雅地分块?

前情回顾

上一篇文章 中,我们掌握了强大的递归字符分块法,它能智能地按段落和句子来分割通用文本,效果拔群。对于大多数文章、文档类的处理,它已经足够优秀。

但现实世界是复杂的。作为开发者,我们经常需要让AI理解的,不仅仅是纯文本,还有:

  • 我们自己写的项目代码
  • 我们整理的技术笔记(Markdown格式)

如果继续用之前的方法来处理这些带有鲜明结构化特征的内容,会发生什么?

想象一下,一个完整的Python函数被从中间拦腰截断,或者一个Markdown的二级标题和它的内容被分到两个不同的块里。这无疑是一场灾难,会严重误导后续的检索和生成。

所以,今天我们的任务就是:为特定格式的内容,找到专属的、更优雅的分块方法。

针对特定语言的分割器 (Language-Specific Splitters)

幸运的是,像 LangChain 这样的框架已经为我们考虑到了这一点。它内置了针对多种主流编程语言的分割器。

其核心思想是:不再基于通用的标点符号,而是基于编程语言本身的语法结构(如类、函数、导入语句等)来进行分割。

我们以 Python 为例,直接上代码。

python 复制代码
# 导入针对Python的递归字符分块器
from langchain.text_splitter import (
    RecursiveCharacterTextSplitter,
    Language,
)

# 一段Python代码示例
python_code = """
import os
import sys

class MyClass:
    def __init__(self, name):
        self.name = name

    def say_hello(self):
        print(f"Hello, {self.name}!")

def my_function(x, y):
    return x + y

if __name__ == "__main__":
    instance = MyClass("World")
    instance.say_hello()
    result = my_function(5, 3)
    print(f"Result is {result}")
"""

# 使用 RecursiveCharacterTextSplitter.from_language() 方法
# 传入语言枚举值 Language.PYTHON
python_splitter = RecursiveCharacterTextSplitter.from_language(
    language=Language.PYTHON, chunk_size=150, chunk_overlap=0
)

# 进行分块
chunks = python_splitter.split_text(python_code)

# 我们来看看分块结果
for i, chunk in enumerate(chunks):
    print(f"--- Chunk {i+1} ---")
    print(chunk)
    print(f"(长度: {len(chunk)})\n")

输出结果:

python 复制代码
--- Chunk 1 ---
import os
import sys
(长度: 19)

--- Chunk 2 ---
class MyClass:
    def __init__(self, name):
        self.name = name

    def say_hello(self):
        print(f"Hello, {self.name}!")
(长度: 129)

--- Chunk 3 ---
def my_function(x, y):
    return x + y
(长度: 38)

--- Chunk 4 ---
if __name__ == "__main__":
    instance = MyClass("World")
    instance.say_hello()
    result = my_function(5, 3)
    print(f"Result is {result}")
(长度: 141)

效果分析

太漂亮了!看看这个分割结果:

  • 导入语句(import) 被单独分为一块。
  • 整个 MyClass,包含它的构造函数和方法,被完整地保留在了一个块里。
  • 独立的 my_function 函数 也自成一块。
  • 主执行模块 if __name__ == "__main__" 的内容也被聚合在一起。

这种基于语法的分割,完美地保留了代码的逻辑单元。当用户提问"MyClass类有什么功能?"时,检索系统能精准地定位到Chunk 2,为大模型提供最相关的、最完整的上下文。

除了Python,LangChain 还支持 CPP, GO, JAVA, JS, PHP, PROTO, RUBY, RST, SCALA, SWIFT, MARKDOWN, LATEX, HTML 等多种语言和格式。你只需要在 language 参数中传入对应的枚举值即可,非常方便。

Markdown文件的分割

Markdown是我们写技术文档和笔记的利器。它的标题层级(#, ##, ###)天然就是内容的逻辑分割线。

RecursiveCharacterTextSplitter 在处理 Language.MARKDOWN 时,会智能地将这些标题符号作为高优先级的分割符。

python 复制代码
# Markdown文本示例
markdown_text = """
# RAG系统概述

RAG(Retrieval-Augmented Generation)是一种强大的AI框架。

## 核心组件

RAG系统主要包含两个核心组件:

1.  **检索器 (Retriever)**:负责从知识库中快速找到相关文档。
2.  **生成器 (Generator)**:基于检索到的信息生成答案。

### 检索器的技术细节

检索器通常使用向量数据库实现...
"""

# 使用针对Markdown的分割器
markdown_splitter = RecursiveCharacterTextSplitter.from_language(
    language=Language.MARKDOWN, chunk_size=100, chunk_overlap=0
)

chunks = markdown_splitter.split_text(markdown_text)

for i, chunk in enumerate(chunks):
    print(f"--- Chunk {i+1} ---")
    print(chunk)
    print(f"(长度: {len(chunk)})\n")

输出结果:

markdown 复制代码
--- Chunk 1 ---
# RAG系统概述

RAG(Retrieval-Augmented Generation)是一种强大的AI框架。
(长度: 57)

--- Chunk 2 ---
## 核心组件

RAG系统主要包含两个核心组件:

1.  **检索器 (Retriever)**:负责从知识库中快速找到相关文档。
2.  **生成器 (Generator)**:基于检索到的信息生成答案。
(长度: 99)

--- Chunk 3 ---
### 检索器的技术细节

检索器通常使用向量数据库实现...
(长度: 34)

可以看到,分割完全按照 h1, h2, h3 的标题层级进行,保持了文档的章节结构,非常符合预期。

总结与预告

今日小结:

  • 处理代码、Markdown等结构化文本时,不要使用通用的文本分割器。
  • 应该使用针对特定语言的分割器 (Language-Specific Splitters),它能基于语法和标记(如函数、类、Markdown标题)进行更智能、更符合逻辑的分割。
  • LangChain 中,通过 RecursiveCharacterTextSplitter.from_language() 方法可以轻松实现这一点。

到目前为止,我们已经掌握了如何将各种类型的文档"优雅地"切分成高质量的文本块 (Chunks)。

我们的"原材料"准备好了。下一步,就是要将这些文本块转化成机器能够理解和比较的数学形式------向量 (Vectors)

这个过程,就是 Embedding。选择什么样的Embedding模型,将直接决定你的RAG系统能否"读懂"文本的深层含义。

明天预告:RAG 每日一技(四):不止是切分,如何让机器读懂文本的"灵魂"------初探Embedding

准备好进入向量的世界了吗?明天我们不见不散!

相关推荐
程序员cxuan1 小时前
速度太快了!本地可以跑 DeepSeek-V4-Flash 了
人工智能·后端·程序员
阿祖zu2 小时前
芝士就是力量!开源私有化部署与 GitHub 双向同步的个人知识笔记 App
前端·后端·ios
不才不才不不才2 小时前
Spring 源码系列(16): doDispatch 全流程——一次请求的主干链路
java·后端·spring
IT_陈寒2 小时前
SpringBoot自动配置失效?这个隐藏配置坑了我一整晚
前端·人工智能·后端
搜狐技术产品小编20233 小时前
告别“黑盒”与误判:如何用“多智能体对抗辩论”重构内容安全审核系统
后端·多agent
DantyWei3 小时前
controller注册及调用时机
后端
edwarddamon3 小时前
Spring Cloud 配置热更新与 Bean 代理机制梳理
java·后端
码事漫谈4 小时前
我用 Seed Evolving 做了个 AI 小说写作工具
后端
Raas1004 小时前
MAIGateway,魔芋企业级AI网关的FinAPI成本竞争力设计
java·后端·网关·api网关·魔芋ai·finapi·mai gateway
计算机魔术师5 小时前
传统基础架构 - 微服务
大数据·后端·微服务·架构·开发工具·编程语言