链载Ai

标题: RAG 中的语义分块:实现更优的上下文检索 [打印本页]

作者: 链载Ai    时间: 1 小时前
标题: RAG 中的语义分块:实现更优的上下文检索

ingFang SC";font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">检索增强生成(RAG)技术异军突起,席卷了整个大语言模型领域。通过将大语言模型(LLMs)的强大能力与外部知识检索相结合,RAG使得模型能够生成准确且有依据的回复,即便在专业领域也不例外。在每一个表现卓越的RAG流程背后,都有一个默默发挥关键作用的 “英雄”:分块技术,尤其是语义分块。

ingFang SC";font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">RAG生态系统与分块的作用

ingFang SC";font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">RAG代表了人工智能系统获取和利用知识方式的重大变革。传统的大语言模型仅依赖于其预先训练的知识,这可能存在局限性或时效性问题。RAG通过在生成过程中从外部资源(如数据库、文档或互联网)检索相关信息,很好地解决了这一局限性。这些外部知识就像补充弹药,极大地扩展了模型的知识边界,使其能够应对各种复杂问题。

ingFang SC";font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">在RAG流程中,分块是至关重要的一环。分块指的是在对文档进行嵌入和索引之前,将其分割成较小单元的过程。这些分块在查询时被检索出来,并输入到大语言模型中用于生成回复。然而,分块并非简单的切割操作,其方式直接影响着RAG系统的性能。如果分块过大,它们可能无法适配模型的上下文窗口,导致信息丢失;而如果分块过小或分割不当,语义信息会被破坏,使模型难以理解和处理,进而影响最终回复的质量。

ingFang SC";font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">分块面临的挑战

ingFang SC";font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">以一段医学文章为例,假设内容如下:“蝙蝠侠主要在哥谭市活动,这是一个犯罪猖獗、腐败横行的大都市。他的宿敌小丑在混乱和不可预测中如鱼得水。尽管布鲁斯·韦恩资助了哥谭市的许多社会项目,但他仍在为自己作为亿万富翁和义警的双重身份而苦苦挣扎。” 如果使用简单的分块方法,可能会将其分割为:

ingFang SC";font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">此时,若用户提问:“是什么让蝙蝠侠的生活如此矛盾?” 检索器可能会随机获取到句子中间的某个分块,或者遗漏关于他双重身份的关键信息,进而导致给出的答案笼统或错误。这清晰地展现了不恰当分块带来的问题,突出了语义分块的重要性和必要性。

ingFang SC";font-size: medium;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">

ingFang SC";font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">语义分块详解

语义分块旨在以一种保留每个单元有意义、自包含上下文的方式分割文档。它尊重自然的边界,比如段落、句子或主题,确保每个分块都能独立回答相关的查询。实现语义分块通常涉及以下几个关键步骤:

  1. 句子边界检测
    准确识别句子的起止位置,这是保留语义完整性的基础。因为句子是表达完整思想的基本语言单位,正确划分句子边界有助于将相关信息归为一组。
  2. 主题建模或基于嵌入的分割
    主题建模可以分析文档内容,将具有相似主题的部分划分为一个分块。基于嵌入的分割则利用词或句子的嵌入向量,通过计算向量之间的相似度来确定分割点,在语义发生变化的地方进行分割,使每个分块内的语义更加连贯。
  3. 使用重叠窗口保留上下文
    为了避免在分割过程中丢失上下文信息,通常会采用重叠窗口的方法。即相邻分块之间有一定比例的重叠内容,这样可以确保在检索和处理分块时,前后信息能够相互关联,增强模型对上下文的理解。

分块策略对比

常见的分块策略有多种,从简单到语义化程度高依次介绍如下:

  1. 固定大小分块(简单方法)
    在Python的LangChain库中,可以使用CharacterTextSplitter进行固定大小分块。示例代码如下:
    from langchain.text_splitter import CharacterTextSplitter
    splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50)
    chunks = splitter.split_text(document)
    这种方法的优点是简单直接,易于实现。但它存在明显的缺陷,可能会在句子中间进行分割,破坏句子的完整性和上下文连贯性,影响语义的表达。
  2. 基于句子的分块
    借助NLTKTextSplitter可以实现基于句子的分块,示例代码为:
    from langchain.text_splitter import NLTKTextSplitter
    splitter = NLTKTextSplitter(chunk_size=3, chunk_overlap=1)
    chunks = splitter.split_text(document)
    该方法能够保留句子边界,一定程度上保证了语义的完整性。然而,它可能仍然会在分块过程中分割主题,导致一个主题被分散到多个分块中,不利于模型对完整主题的理解和处理。
  3. 递归分块
    RecursiveCharacterTextSplitter提供了递归分块的功能,代码如下:
    from langchain.text_splitter import RecursiveCharacterTextSplitter
    splitter = RecursiveCharacterTextSplitter(
    separators=["\n\n", "\n", ".", " ", ""],
    chunk_size=500,
    chunk_overlap=100
    )
    chunks = splitter.split_text(document)
    递归分块尝试在较大的边界(如段落、句子、单词)上进行分割,能够在分块长度和语义保持之间取得较好的平衡。不过,它可能仍然需要根据具体应用场景进行微调,以达到最佳效果。
  4. 基于嵌入的语义分块(高级方法)
    这种技术利用句子嵌入来在语义发生变化的地方分割文本。示例代码如下:
    fromsentence_transformersimportSentenceTransformer,utilimportnltkmodel=SentenceTransformer('all-MiniLM-L6-v2')sentences=nltk.sent_tokenize(document)embeddings=model.encode(sentences)similarities=[util.cos_sim(embeddings[i],embeddings[i+1])foriinrange(len(embeddings)-1)]chunks=[]chunk=[sentences[0]]fori,scoreinenumerate(similarities):ifscore<0.6:#可根据需要调整阈值chunks.append("".join(chunk))chunk=[]chunk.append(sentences[i+1])ifchunk:chunks.append("".join(chunk))

    基于嵌入的语义分块能够真正实现语义层面的分割,对于包含丰富主题的文档效果显著。但它的计算复杂度较高,处理速度相对较慢,实现过程也更为复杂。

评估分块质量

分块策略的优劣直接影响RAG系统下游的各个环节,因此评估分块质量至关重要。可以从以下几个方面进行评估:

  1. 指标





欢迎光临 链载Ai (https://www.lianzai.com/) Powered by Discuz! X3.5