2026/1/27 23:13:18
网站建设
项目流程
网站数据怎么更新,网站数据怎么更新,二维码生成器免费版,网站外链建设方法本文详细介绍了文本分块的原理、方法和实现技巧#xff0c;是提升大模型RAG效果的关键技术。文章探讨了分块大小对检索精度的影响#xff0c;并系统讲解了多种分块方法#xff08;如字符分块、递归分块、语义分块等#xff09;及其适用场景#xff0c;同时提供了高级索引技…本文详细介绍了文本分块的原理、方法和实现技巧是提升大模型RAG效果的关键技术。文章探讨了分块大小对检索精度的影响并系统讲解了多种分块方法如字符分块、递归分块、语义分块等及其适用场景同时提供了高级索引技巧如滑动窗口、父子文本块等。通过合理选择分块策略可显著提高文档检索精度和生成质量是构建高效大模型应用的重要基础。文本分块的原理和重要性• 将长文本分解成适当大小的片段以便于嵌入、索引和存储并提高检索的精确度。• 文本分块Text Chunking是 RAG检索增强生成、文档问答、向量检索等场景的核心预处理步骤本质是将长文本拆分为大小合适、语义完整的片段核心目的是解决「长文本与模型 / 检索系统能力不匹配」的问题同时提升检索精度、生成质量和系统效率。1.1 如何确定大模型所能接受的最长上下文查官方文档获取模型的 理论上下文长度Token 数用 Token 计数器生成测试文本调用模型接口找到 实际可用上限排除 API / 显存限制from transformers import AutoTokenizer# 加载模型对应的 Tokenizer如 Llama 3tokenizer AutoTokenizer.from_pretrained(meta-llama/Meta-Llama-3-8B-Instruct)model_max_length tokenizer.model_max_length # 读取 Tokenizer 标注的最大长度理论值print(f模型理论最大 Token 数{model_max_length})# 生成测试文本逐步增加长度test_text 测试文本 * 1000# 可调整倍数直到 Token 数接近理论值tokens tokenizer.encode(test_text, return_tensorspt)print(f测试文本 Token 数{tokens.shape[1]})# 调用模型此处仅演示 Token 计数实际需加载模型# from transformers import AutoModelForCausalLM# model AutoModelForCausalLM.from_pretrained(meta-llama/Meta-Llama-3-8B-Instruct)# try:# output model.generate(tokens, max_new_tokens100)# print(未超出上下文长度)# except Exception as e:# print(f超出上下文长度报错{e})预留输出 Token 空间输入长度 实际上限 - 预期输出长度确保使用时不超限。1.2 分块大小对检索精度的影响 – 理解嵌入过程在这里插入图片描述文本嵌入的核心是用向量捕捉文本的整体语义。图中展示了「短文本」和「长文本」都通过 Mean Pooling对所有 Token 级向量求平均 生成最终嵌入• 分块过小时每个块的语义单元不完整如把一个完整的论点拆成两段Token 级向量的聚合结果会丢失关键语义信息。例如若将 “黑神话悟空的剧情设定很有深度” 拆成 “黑神话悟空的剧情” 和 “设定很有深度” 两个块各自的嵌入向量会因语义残缺导致检索时无法准确匹配 “剧情深度” 相关的查询。• 分块过大时块内包含多个无关语义如一篇文档同时讲 “游戏玩法” 和 “角色设定”Token 级向量的平均结果会成为 “混合语义”与查询的相似度被稀释。例如查询 “黑神话悟空的玩法” 时包含 “玩法 角色” 的大块嵌入可能因角色信息的干扰比仅包含 “玩法” 的小块嵌入匹配度更低。最优分块大小需在「语义完整性」和「噪声干扰」之间找到平衡• 对于短文本 / 语义密集型内容如单段论点、表格数据分块可略小确保语义单元完整• 对于长文本 / 多主题内容如多章节文档、包含冗余说明的报告分块需适中既保证每个块聚焦单一主题又避免语义残缺。可以基于ChunkViz 对文本分块进行可视化ChunkViz 是一款专注于文本分块策略的可视化工具核心用于帮助用户直观理解和对比不同文本分块方法的效果从而优化大语言模型LLM应用中的文本处理流程。它的核心功能和价值可总结为以下几点多策略可视化支持多种文本分块策略如字符分割器、递归字符分割器等通过不同颜色标记分块边界直观展示分块结果自定义参数调整可自定义分块大小、重叠程度等参数快速验证不同配置对分块效果的影响生态兼容与 LangChain、LlamaIndex 等主流 LLM 开发框架深度集成支持直接导入这些框架的分块策略进行对比开源易用以开源项目形式提供部署和使用门槛低适合开发者在构建 RAG检索增强生成系统、文档问答等场景中调试分块逻辑。简单来说ChunkViz 是文本分块的 “可视化调试器”能让开发者快速找到最适合业务场景的分块策略避免因分块不合理导致的检索精度下降或模型理解偏差。文本分块的方法和实现2.1 CharacterTextSplitter在这里插入图片描述from langchain_community.document_loaders import TextLoaderfrom langchain_text_splitters import CharacterTextSplitterloader TextLoader(90-文档-Data/山西文旅/云冈石窟.txt)documents loader.load()# 设置分块器指定块的大小为50个字符无重叠text_splitter CharacterTextSplitter( chunk_size100, # 每个文本块的大小为50个字符 chunk_overlap10, # 文本块之间没有重叠部分)chunks text_splitter.split_documents(documents)print(\n 文档分块结果 )for i, chunk inenumerate(chunks, 1): print(f\n--- 第 {i} 个文档块 ---) print(f内容: {chunk.page_content}) print(f元数据: {chunk.metadata}) print(- * 50) 核心参数详解之前提到的关键配置这里结合代码落地 chunk_size100每个分块的最大字符数注意是 “字符” 不是 “Token”中文、英文、标点都算 1 个字符比如 “云冈石窟位于山西大同” 是 12 个字符 若文本片段超过 100 字符会被截断若未超过则保留完整片段 chunk_overlap10相邻两个分块的重叠部分字符数不是 “无重叠”代码注释有误chunk\_overlap0 才是无重叠 作用避免因硬截断丢失上下文如第 1 块结尾是 “云冈石窟的佛像”第 2 块开头重叠 10 字符确保语义连贯  ### 2.2 RecursiveCharacterTextSplitter 递归分块  在这里插入图片描述 先搞懂递归分块的核心原理为什么叫 “递归” RecursiveCharacterTextSplitter的核心是“按优先级分割符递归尝试优先保持语义完整实在不行再硬截断”流程像 “剥洋葱” 一样层层递进 1递归分块的 4 步逻辑以代码中的 separators [\n\n, ., , ] 为例 1. 1. 第一步按最高优先级分割符拆分先用第一个分割符 \n\n双换行通常是段落分隔把整个文档拆成多个大段落。此时检查每个段落的字符数 * • 若段落 ≤ chunk\_size100 字符直接作为一个分块 * • 若段落 chunk\_size进入下一步对这个 “超长段落” 递归拆分。 1. 2. 第二步按次高优先级分割符拆分对超长段落用第二个分割符 .句号句子结束拆分得到多个句子。再检查每个句子的字符数 * • 若句子 ≤ chunk\_size合并相邻句子直到接近 chunk\_size作为分块 * • 若句子 chunk\_size进入下一步继续递归拆分。 1. 3. 第三步按更低优先级分割符拆分对超长句子用第三个分割符 逗号分句拆分得到多个分句。重复检查字符数 * • 若分句 ≤ chunk\_size合并相邻分句作为分块 * • 若分句 chunk\_size进入最后一步。 1. 4. 第四步终极方案硬截断用最后一个分割符 空格单词 / 词组分隔拆分若仍超长如连续无空格的长文本则直接按 chunk\_size 硬截断这是最后的妥协尽量避免破坏语义。 核心优势 优先按「段落→句子→分句→单词」的逻辑拆分最大程度保持语义完整不会轻易在句子中间截断 递归机制适配各种文本结构如长段落、短句子、无标点文本通用性比普通 CharacterTextSplitter 强得多。 plaintext from langchain_community.document_loaders import TextLoaderfrom langchain_text_splitters import RecursiveCharacterTextSplitterloader TextLoader(90-文档-Data/山西文旅/云冈石窟.txt)documents loader.load()# 定义分割符列表按优先级依次使用separators [\n\n, ., , ] # . 是句号 是逗号 是空格# 创建递归分块器并传入分割符列表text_splitter RecursiveCharacterTextSplitter( chunk_size100, chunk_overlap10, separatorsseparators)chunks text_splitter.split_documents(documents)print(\n 文档分块结果 )for i, chunk in enumerate(chunks, 1): print(f\n--- 第 {i} 个文档块 ---) print(f内容: {chunk.page_content}) print(f元数据: {chunk.metadata}) print(- * 50)2.3 代码分块• 普通递归分块from langchain_text_splitters import RecursiveCharacterTextSplitter# 示例代码GAME_CODE class CombatSystem: def __init__(self): self.health 100 self.stamina 100 self.state IDLE self.attack_patterns { NORMAL: 10, SPECIAL: 30, ULTIMATE: 50 } def update(self, delta_time): self._update_stats(delta_time) self._handle_combat() def _update_stats(self, delta_time): self.stamina min(100, self.stamina 5 * delta_time) def _handle_combat(self): if self.state ATTACKING: self._execute_attack() def _execute_attack(self): if self.stamina self.attack_patterns[SPECIAL]: damage 50 self.stamina - self.attack_patterns[SPECIAL] return damage return self.attack_patterns[NORMAL]class InventorySystem: def __init__(self): self.items {} self.capacity 20 self.gold 0 def add_item(self, item_id, quantity): if len(self.items) self.capacity: if item_id in self.items: self.items[item_id] quantity else: self.items[item_id] quantity def remove_item(self, item_id, quantity): if item_id in self.items: self.items[item_id] - quantity if self.items[item_id] 0: del self.items[item_id] def get_item_count(self, item_id): return self.items.get(item_id, 0)class QuestSystem: def __init__(self): self.active_quests {} self.completed_quests set() self.quest_log [] def add_quest(self, quest_id, quest_data): if quest_id not in self.active_quests: self.active_quests[quest_id] quest_data self.quest_log.append(fStarted quest: {quest_data[name]}) def complete_quest(self, quest_id): if quest_id in self.active_quests: self.completed_quests.add(quest_id) del self.active_quests[quest_id] def get_active_quests(self): return list(self.active_quests.keys())# 创建文本分割器text_splitter RecursiveCharacterTextSplitter( chunk_size1000, # 每个块的大小 chunk_overlap00, # 相邻块之间的重叠大小 # separators[\n\n, \n, , ] # 分割符列表)# 执行分块text_chunks text_splitter.create_documents([GAME_CODE])# 打印分块结果print(\n 代码分块结果 )for i, chunk inenumerate(text_chunks, 1): print(f\n--- 第 {i} 个代码块 ---) print(f内容:\n{chunk.page_content}) print(f元数据: {chunk.metadata}) print(- * 50)用通用递归分块器靠默认分割符和字符长度限制实现代码的 “无断裂拆分”分块结果与 3 个游戏系统类一一对应每个块都能独立运行 / 理解适配后续代码检索、问答等场景可以启用 Python 专属分割符能应对更复杂的代码结构如超长函数、无空行类如下• 按照编程语言来进行划分from langchain_text_splitters import RecursiveCharacterTextSplitterfrom langchain_text_splitters import Languageseparators RecursiveCharacterTextSplitter.get_separators_for_language(Language.JS)print(separators)from langchain_text_splitters import ( Language, RecursiveCharacterTextSplitter,)GAME_CODE class CombatSystem: def __init__(self): self.health 100 self.stamina 100 self.state IDLE self.attack_patterns { NORMAL: 10, SPECIAL: 30, ULTIMATE: 50 } def update(self, delta_time): self._update_stats(delta_time) self._handle_combat() def _update_stats(self, delta_time): self.stamina min(100, self.stamina 5 * delta_time) def _handle_combat(self): if self.state ATTACKING: self._execute_attack() def _execute_attack(self): if self.stamina self.attack_patterns[SPECIAL]: damage 50 self.stamina - self.attack_patterns[SPECIAL] return damage return self.attack_patterns[NORMAL]class InventorySystem: def __init__(self): self.items {} self.capacity 20 self.gold 0 def add_item(self, item_id, quantity): if len(self.items) self.capacity: if item_id in self.items: self.items[item_id] quantity else: self.items[item_id] quantity def remove_item(self, item_id, quantity): if item_id in self.items: self.items[item_id] - quantity if self.items[item_id] 0: del self.items[item_id] def get_item_count(self, item_id): return self.items.get(item_id, 0)class QuestSystem: def __init__(self): self.active_quests {} self.completed_quests set() self.quest_log [] def add_quest(self, quest_id, quest_data): if quest_id not in self.active_quests: self.active_quests[quest_id] quest_data self.quest_log.append(fStarted quest: {quest_data[name]}) def complete_quest(self, quest_id): if quest_id in self.active_quests: self.completed_quests.add(quest_id) del self.active_quests[quest_id] def get_active_quests(self): return list(self.active_quests.keys())python_splitter RecursiveCharacterTextSplitter.from_language( languageLanguage.PYTHON, # 指定编程语言为Python chunk_size1000, chunk_overlap0)python_docs python_splitter.create_documents([GAME_CODE])print(\n 代码分块结果 )for i, chunk inenumerate(python_docs, 1): print(f\n--- 第 {i} 个代码块 ---) print(f内容:\n{chunk.page_content}) print(f元数据: {chunk.metadata}) print(- * 50)from_language()方法会自动加载 Python 语言的「语法分割符」预设的无需手动定义比如•高优先级“\n\n”代码空行、“}”类 / 函数结束符、“;”语句结束符、“\n”换行•低优先级 “空格、”硬截断尽量不用分块逻辑按 Python 语法规则递归拆分优先保证「类、函数、代码块的语法完整性」比如不会把一个 class 拆成两半不会在函数中间截断。2.4 语义分块from llama_index.core import SimpleDirectoryReaderfrom llama_index.core.node_parser import ( SentenceSplitter, SemanticSplitterNodeParser,)from llama_index.embeddings.openai import OpenAIEmbedding # from llama_index.embeddings.huggingface import HuggingFaceEmbedding # embed_model HuggingFaceEmbedding(model_nameBAAI/bge-small-zh)documents SimpleDirectoryReader(input_files[../90-文档-Data/黑悟空/黑悟空wiki.txt]).load_data()# 创建语义分块器splitter SemanticSplitterNodeParser( buffer_size3, # 缓冲区大小 breakpoint_percentile_threshold90, # 断点百分位阈值 embed_modelOpenAIEmbedding() # 使用的嵌入模型)# 创建基础句子分块器作为对照base_splitter SentenceSplitter( # chunk_size512)buffer_size默认值为1这个参数控制评估语义相似度时将多少个句子组合在一起当设置为1时每个句子会被单独考虑当设置大于1时会将多个句子组合在一起进行评估例如如果设置为3就会将每3个句子作为一个组来评估语义相似度breakpoint_percentile_threshold默认值为95这个参数控制何时在句子组之间创建分割点,它表示余弦不相似度的百分位数阈值,当句子组之间的不相似度超过这个阈值时就会创建一个新的节点数值越小生成的节点就越多因为更容易达到分割阈值数值越大生成的节点就越少因为需要更大的不相似度才会分割这两个参数共同影响文本的分割效果buffer_size 决定了评估语义相似度的粒度breakpoint_percentile_threshold 决定了分割的严格程度例如如果 buffer_size2 且 breakpoint_percentile_threshold90每2个句子会被组合在一起,当组合之间的不相似度超过90%时就会分割,这会产生相对较多的节点如果 buffer_size3 且 breakpoint_percentile_threshold98每3个句子会被组合在一起,需要更大的不相似度才会分割,这会产生相对较少的节点# 使用语义分块器对文档进行分块semantic_nodes splitter.get_nodes_from_documents(documents)print(\n 语义分块结果 )print(f语义分块器生成的块数{len(semantic_nodes)})for i, node inenumerate(semantic_nodes, 1): print(f\n--- 第 {i} 个语义块 ---) print(f内容:\n{node.text}) print(- * 50)# 使用基础句子分块器对文档进行分块base_nodes base_splitter.get_nodes_from_documents(documents)print(\n 基础句子分块结果 )print(f基础句子分块器生成的块数{len(base_nodes)})for i, node inenumerate(base_nodes, 1): print(f\n--- 第 {i} 个句子块 ---) print(f内容:\n{node.text}) print(- * 50)2.5 Unstructured 工具2.5.1 分块策略的原理基于文档结构的智能拆分Unstructured 的分块不是简单的“字符截断”而是先识别文档的语义结构标题、段落、表格等再按策略聚合或拆分确保分块“语义完整、主题聚焦”。图中 4 种分块策略的核心逻辑如下分块策略原理核心适用场景Basic按“预设字符大小”聚合文本元素表格作为独立分块若元素超长对元素二次拆分通用文档需平衡分块大小与语义By Title检测到新标题时立即关闭当前分块并开启新块确保“标题下属内容”语义完整章节化文档论文、报告、手册By Page强制按 PDF 页码拆分每页内容作为独立分块需保留“页面边界”的场景合同、法律文书By Similarity用嵌入模型计算文本元素的语义相似度将主题相似的元素聚合成块跨位置的主题聚合如多处讨论同一概念的文档| 参数名 | 作用 | 示例值 ||-----------------------|----------------------------------------------------------------------|-----------------|| chunking_strategy | 指定分块策略basic/by_title/by_page/by_similarity| by_title || max_characters | 分块的最大字符数Basic 策略的硬限制| 500 || new_after_n_chars | 分块的“软限制”超过该字符数则停止聚合新元素| 400 || embed_model | By Similarity 策略的嵌入模型如 OpenAI、HuggingFace 模型| OpenAIEmbedding() || breakpoint_threshold | By Similarity 策略的相似度阈值值越高分块越少| 0.7 |#### 2.5.2 案例实例1. Basic 策略按字符大小分块表格独立pythonfrom unstructured.partition.pdf import partition_pdf# 读取PDF并按Basic策略分块elements partition_pdf( filename黑悟空wiki.pdf, chunking_strategybasic, # 启用Basic分块 max_characters500, # 每个分块最多500字符 new_after_n_chars400 # 软限制400字符)# 打印分块结果for i, el in enumerate(elements, 1): print(f--- 第 {i} 个分块 ---) print(f类型: {el.category}) print(f内容: {el.text[:100]}...\n)By Title 策略按标题拆分确保章节完整from unstructured.partition.pdf import partition_pdffrom unstructured.chunking.title import chunk_by_title# 先分区识别文档元素elements partition_pdf(filename黑悟空wiki.pdf, strategyhi_res)# 按标题分块chunks chunk_by_title( elements, combine_text_under_n_chars200, # 合并短文本 multipage_sectionsTrue # 跨页章节合并)# 打印分块结果for i, chunk inenumerate(chunks, 1): print(f--- 第 {i} 个分块标题驱动---) print(f内容: {chunk.text[:100]}...\n)By Page 策略按页码强制拆分from unstructured.partition.pdf import partition_pdf# 按页码分块每页一个分块elements partition_pdf( filename黑悟空wiki.pdf, chunking_strategyby_page)# 打印分块结果按页码区分for el in elements: print(f--- 第 {el.metadata.page_number} 页分块 ---) print(f内容: {el.text[:100]}...\n)By Similarity 策略语义相似性聚合from unstructured.partition.pdf import partition_pdffrom unstructured.chunking.similarity import chunk_by_similarityfrom unstructured.embeddings.openai import OpenAIEmbedding# 先分区elements partition_pdf(filename黑悟空wiki.pdf)# 按语义相似性分块chunks chunk_by_similarity( elements, embed_modelOpenAIEmbedding(), # 用OpenAI嵌入模型计算相似度 breakpoint_threshold0.7 # 相似度阈值值越高分块越少)# 打印分块结果for i, chunk inenumerate(chunks, 1): print(f--- 第 {i} 个语义分块 ---) print(f内容: {chunk.text[:100]}...\n)Unstructured 支持“Partition 时直接 Chunk”和“先 Partition 再 Chunk”两种流程区别如下流程类型说明适用场景Partition 时直接 Chunk分区和分块一步完成如示例 1、3代码更简洁快速验证分块效果场景简单先 Partition 再 Chunk先识别文档元素标题、段落、表格再针对性分块如示例 2、4需精细化控制分块逻辑场景复杂Unstructured 的分块能力核心是**“先理解文档结构再智能拆分”**——通过 4 种分块策略Basic、By Title、By Page、By Similarity适配不同类型的 PDF 文档。代码实现上只需通过partition_pdf函数或专用分块函数chunk_by_title等结合参数配置即可完成分块。选择策略时可参考• 通用文档 → Basic• 章节化文档 → By Title• 需保留页码 → By Page• 跨位置主题聚合 → By Similarity。这种“结构感知”的分块方式能大幅提升后续 RAG 检索或大模型问答的精准度是处理非结构化 PDF 文档的高效工具。与分块相关的高级索引技巧3.1 带滑动窗口的句子切分Sliding Windows在这里插入图片描述3.2 分块时混合生成父子文本块Parent-Child Docs在这里插入图片描述3.3 分块时为文本块创建元数据在这里插入图片描述3.4 在分块时形成有级别的索引Summary→Details 在这里插入图片描述3.5 文档转换为嵌入对象最后我在一线科技企业深耕十二载见证过太多因技术卡位而跃迁的案例。那些率先拥抱 AI 的同事早已在效率与薪资上形成代际优势我意识到有很多经验和知识值得分享给大家也可以通过我们的能力和经验解答大家在大模型的学习中的很多困惑。我整理出这套 AI 大模型突围资料包✅AI大模型学习路线图✅Agent行业报告✅100集大模型视频教程✅大模型书籍PDF✅DeepSeek教程✅AI产品经理入门资料完整的大模型学习和面试资料已经上传带到CSDN的官方了有需要的朋友可以扫描下方二维码免费领取【保证100%免费】为什么说现在普通人就业/升职加薪的首选是AI大模型人工智能技术的爆发式增长正以不可逆转之势重塑就业市场版图。从DeepSeek等国产大模型引发的科技圈热议到全国两会关于AI产业发展的政策聚焦再到招聘会上排起的长队AI的热度已从技术领域渗透到就业市场的每一个角落。智联招聘的最新数据给出了最直观的印证2025年2月AI领域求职人数同比增幅突破200%远超其他行业平均水平整个人工智能行业的求职增速达到33.4%位居各行业榜首其中人工智能工程师岗位的求职热度更是飙升69.6%。AI产业的快速扩张也让人才供需矛盾愈发突出。麦肯锡报告明确预测到2030年中国AI专业人才需求将达600万人人才缺口可能高达400万人这一缺口不仅存在于核心技术领域更蔓延至产业应用的各个环节。资料包有什么①从入门到精通的全套视频教程⑤⑥包含提示词工程、RAG、Agent等技术点② AI大模型学习路线图还有视频解说全过程AI大模型学习路线③学习电子书籍和技术文档市面上的大模型书籍确实太多了这些是我精选出来的④各大厂大模型面试题目详解⑤ 这些资料真的有用吗?这份资料由我和鲁为民博士共同整理鲁为民博士先后获得了北京清华大学学士和美国加州理工学院博士学位在包括IEEE Transactions等学术期刊和诸多国际会议上发表了超过50篇学术论文、取得了多项美国和中国发明专利同时还斩获了吴文俊人工智能科学技术奖。目前我正在和鲁博士共同进行人工智能的研究。所有的视频教程由智泊AI老师录制且资料与智泊AI共享相互补充。这份学习大礼包应该算是现在最全面的大模型学习资料了。资料内容涵盖了从入门到进阶的各类视频教程和实战项目无论你是小白还是有些技术基础的这份资料都绝对能帮助你提升薪资待遇转行大模型岗位。智泊AI始终秉持着“让每个人平等享受到优质教育资源”的育人理念通过动态追踪大模型开发、数据标注伦理等前沿技术趋势构建起前沿课程智能实训精准就业的高效培养体系。课堂上不光教理论还带着学员做了十多个真实项目。学员要亲自上手搞数据清洗、模型调优这些硬核操作把课本知识变成真本事如果说你是以下人群中的其中一类都可以来智泊AI学习人工智能找到高薪工作一次小小的“投资”换来的是终身受益应届毕业生无工作经验但想要系统学习AI大模型技术期待通过实战项目掌握核心技术。零基础转型非技术背景但关注AI应用场景计划通过低代码工具实现“AI行业”跨界。业务赋能 突破瓶颈传统开发者Java/前端等学习Transformer架构与LangChain框架向AI全栈工程师转型。获取方式有需要的小伙伴可以保存图片到wx扫描二v码免费领取【保证100%免费】**