背景与问题
- rag可以解决大模型的知识局限性问题,那要怎么使用rag, 重点知识库的构建?
- 构建策略,文档分块有什么策略、有什么注意事项?
分块策略
- 按照字符数来分块
- 按固定字符数 结合overlapping window
- 按句子分块
- 递归方法 RecursiveCharacterTextSplitter
按固定字符数来分块
按固定字符数来分块,简单直接,但是会导致分块不完整,丢失上下文信息。
# 按固定字符数来分块
def split_by_fixed_char_count(text, char_count):
return [text[i: i + char_count] for i in range(0, len(text), char_count)]
document_text = """
自然语言处理(NLP),作为计算机科学、人工智能与语言学的交融之地,致力于赋予计算机解析和处理人类语言的能力。"
"在这个领域,机器学习发挥着至关重要的作用。利用多样的算法,机器得以分析、领会乃至创造我们所理解的语言。"
"从机器翻译到情感分析,从自动摘要到实体识别,NLP的应用已遍布各个领域。随着深度学习技术的飞速进步,"
"NLP的精确度与效能均实现了巨大飞跃。如今,部分尖端的NLP系统甚至能够处理复杂的语言理解任务,"
"如问答系统、语音识别和对话系统等。NLP的研究推进不仅优化了人机交流,也对提升机器的自主性和智能水平起到了关键作用。
"""
result = split_by_fixed_char_count(document_text, 100)
for i, chunk in enumerate(result):
print(f"块{i+1}:------------ 长度{len(chunk)}")
print(f"内容: {chunk} \n ")
# 块1:------------ 长度100
# 内容:
# 自然语言处理(NLP),作为计算机科学、人工智能与语言学的交融之地,致力于赋予计算机解析和处理人类语言的能力。"
# "在这个领域,机器学习发挥着至关重要的作用。利用多样的算法,机器得以
# 块2:------------ 长度100
# 内容: 分析、领会乃至创造我们所理解的语言。"
# "从机器翻译到情感分析,从自动摘要到实体识别,NLP的应用已遍布各个领域。随着深度学习技术的飞速进步,"
# "NLP的精确度与效能
# 块3:------------ 长度100
# 内容: 均实现了巨大飞跃。如今,部分尖端的NLP系统甚至能够处理复杂的语言理解任务,"
# "如问答系统、语音识别和对话系统等。NLP的研究推进不仅优化了人机交流,也对提升机器的自主性和智能水平起
# 块4:------------ 长度8
# 内容: 到了关键作用。
固定字符数 结合overlapping window
固定字符数 结合overlapping window 可以解决分块不完整的问题,但是会导致分块重复。重复的部分是为了保证保持上下文的完整性。
# chunk_size表示块的字符个数,stride为步长,滑动窗口的大小为chunk_size-stride
# overlapping window 重叠窗口
# 参数:原文,块的字符个数,步长
def sliding_window_chunks(text, count, stride):
# 列表推导式
return [text[i: i+count] for i in range(0, len(text), count - stride)]
document_text = ("自然语言处理(NLP),作为计算机科学、人工智能与语言学的交融之地,致力于赋予计算机解析和处理人类语言的能力。"
"在这个领域,机器学习发挥着至关重要的作用。利用多样的算法,机器得以分析、领会乃至创造我们所理解的语言。"
"从机器翻译到情感分析,从自动摘要到实体识别,NLP的应用已遍布各个领域。随着深度学习技术的飞速进步,"
"NLP的精确度与效能均实现了巨大飞跃。如今,部分尖端的NLP系统甚至能够处理复杂的语言理解任务,"
"如问答系统、语音识别和对话系统等。NLP的研究推进不仅优化了人机交流,也对提升机器的自主性和智能水平起到了关键作用。")
chunks = sliding_window_chunks(document_text, 100, 20)
for j, chunk in enumerate(chunks):
print(f"块 {j} ------------ 长度{len(chunk)}")
print(f"内容: {chunk} \n")
# 块 0 ------------ 长度100
# 内容: 自然语言处理(NLP),作为计算机科学、人工智能与语言学的交融之地,致力于赋予计算机解析和处理人类语言的能力。在这个领域,机器学习发挥着至关重要的作用。利用多样的算法,机器得以分析、领会乃至创造我们所
# 块 1 ------------ 长度100
# 内容: 的算法,机器得以分析、领会乃至创造我们所理解的语言。从机器翻译到情感分析,从自动摘要到实体识别,NLP的应用已遍布各个领域。随着深度学习技术的飞速进步,NLP的精确度与效能均实现了巨大飞跃。如今,部分
# 块 2 ------------ 长度100
# 内容: 精确度与效能均实现了巨大飞跃。如今,部分尖端的NLP系统甚至能够处理复杂的语言理解任务,如问答系统、语音识别和对话系统等。NLP的研究推进不仅优化了人机交流,也对提升机器的自主性和智能水平起到了关键作
# 块 3 ------------ 长度22
# 内容: 对提升机器的自主性和智能水平起到了关键作用。
按句子分块
按句子分块,简单直接,但是会导致分块不完整,丢失上下文信息,并且会切得比较零碎。
# 正则表达式
import re
text = ("自然语言处理(NLP),作为计算机科学、人工智能与语言学的交融之地,致力于赋予计算机解析和处理人类语言的能力。"
"在这个领域,机器学习发挥着至关重要的作用。利用多样的算法,机器得以分析、领会乃至创造我们所理解的语言。"
"从机器翻译到情感分析,从自动摘要到实体识别,NLP的应用已遍布各个领域。随着深度学习技术的飞速进步,"
"NLP的精确度与效能均实现了巨大飞跃!如今,部分尖端的NLP系统甚至能够处理复杂的语言理解任务,"
"如问答系统、语音识别和对话系统等。NLP的研究推进不仅优化了人机交流,也对提升机器的自主性和智能水平起到了关键作用。")
'''
re.split(r'[。?!]', text) 是使用正则表达式对字符串 text 进行分割的操作。
re.split(pattern, string):这是 Python 的 re 模块中的一个函数,用于根据正则表达式 pattern 将字符串 string 分割成多个部分。
r'[。?!]':这是一个正则表达式模式,用于匹配中文句子结束的标点符号。
re.split 函数会返回一个列表,其中包含分割后的子字符串和匹配到的标点符号
'''
sentences = re.split(r'[。?!]', text)
print(sentences)
print('-' * 100)
for j, chunk in enumerate(sentences):
print(f"块 {j} ------------ 长度{len(chunk)}")
print(f"内容: {chunk} \n")
递归方法 RecursiveCharacterTextSplitter
思想是根据一组规则顺序地将文本分割成多个块,直到每个块满足指定的条件。如果某个chunk_size过大,会继续使用下一个分割方式分割,直到每个块的字符数小于等于chunk_size。默认["\n\n", "\n", " ", ""],这种设置首先尝试保持段落、句子和单词的完整性。
chunk_size = 分割长度
chunk_overlap = 重叠长度
注意: 1.chunk_overlap 是在文本块尺寸大于chunk_size 时,为了确保相邻文本块之间有部分重叠才发挥作用的 2.若分隔符分割出的文本块尺寸已经小于chunk_size,RecursiveCharacterTextSplitter则认为没必要进行重叠处理,此时相邻文本块间没有重叠
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 目标文本
document_text = """
2023年国家林业重点展会新闻发布会
【国家林草局宣传中心副主任 王振】各位记者朋友,大家上午好。欢迎参加2023年国家林业重点展会新闻发布会。2023-09-08 10:00:10
【王振】近年来,我国林业产业蓬勃发展,油茶等木本油料、林下经济、竹藤花卉、生态旅游、林果等特色产业规模不断壮大,产业结构更加优化,林产品贸易逐年扩大,在助力脱贫攻坚和乡村振兴,促进生态文明建设、应对气候变化等方面发挥了重要作用。2023-09-08 10:00:29
【王振】国家林业重点展会是展示林业产业发展成效的重要平台和宣传推介林产品的重要窗口。今年11月,第16届中国义乌国际森林产品博览会和第3届中国新疆特色林果产品博览会将分别在浙江省义乌市和广东省广州市举办。今天,我们非常高兴地邀请到我局林业和草原改革发展司副司长苏祖云先生、新疆维吾尔自治区林业和草原局一级巡视员李江先生、浙江省义乌市人民政府副市长李睿先生,请他们为大家介绍林业产业高质量发展及两个展会筹备有关情况,并回答大家感兴趣的问题。首先,请苏司长介绍。2023-09-08 10:01:48
【国家林草局林业和草原改革发展司副司长 苏祖云】各位来宾、新闻界的各位朋友,上午好!在此,我代表国家林草局改革发展司诚挚欢迎出席本次发布会的各位来宾和新闻界的记者朋友们,并衷心感谢大家长期以来对林业产业的关注和支持!2023-09-08 10:02:10
【苏祖云】林业产业是绿色产业,是规模最大的绿色经济体,是绿水青山转化为金山银山的重要途径和载体,肩负着生态富民、绿色惠民的重大使命。国家林草局认真学习贯彻习近平生态文明思想,积极践行“两山”理论和新发展理念,推进林业产业高质量发展,林业产业总产值连续保持快速增长,年产值达到8.04万亿元,林产品进出口贸易额超过1800亿美元,其中木浆、原木、锯材进口和木制家具、人造板、地板出口均居世界首位,我国已成为世界林产品生产、贸易、消费第一大国。同时,不断推进木竹建材、生物质能源、林草碳汇等新兴产业,生态旅游、森林康养、木本粮油、林下经济、竹藤花卉等绿色富民产业快速发展,形成了经济林、木材加工及木竹制品制造、森林旅游康养、林下经济四个年产值超过万亿元的支柱产业,绿色生态产品供给能力持续增强。2023-09-08 10:05:43
"""
# 使用langchain提供的RecursiveCharacterTextSplitter 类来实现递归字符文本分割
splitter = RecursiveCharacterTextSplitter(
chunk_size=200, # 分割长度
chunk_overlap=40, # 重叠长度 /重叠窗口大小
separators=[
"\n\n",
"\n",
"。",
"!",
"?",
";",
" ",
""], # 分割符 在分割长度内依次使用段落、换行符、中文句号、中文问号、中文分号、空格、无内容来切分
)
chunks = splitter.split_text(document_text)
for i, chunk in enumerate(chunks):
print(f"块 {i + 1} -------------- 长度{len(chunk)}")
print(f"内容: {chunk} \n")
注意事项: 1、chunk_size 过小会导致信息丢失,过大会导致切割的文本块包含多重含义 这里设置100-200合适,而在生产中要根据具体场景、实践之下调整。 2、chunk_overlap 一般设置chunk_size的10-20%,这是为了保证相邻文本块之间有部分重叠,避免信息丢失。 3、以上案例分隔符以中文内容参考,依次使用段落、换行符、中文句号、中文问号、中文分号、空格、无内容来切分。 4、这种情况chunk_overlap只在相邻文本块尺寸大于chunk_size时才起作用(必要时才介入),若分隔符分割出的文本块尺寸已经小于chunk_size,RecursiveCharacterTextSplitter则认为没必要进行重叠处理,此时相邻文本块间没有重叠。