随笔(四)

发布时间:2026/8/14 16:26:22
随笔(四) 前面已经设计完知识库附件的文档相关总体层面数据流以及具体的如何解析接下来就是讲解分块向量化知识图谱以及检索重排上下文压缩引用归因等等相关设计了也是个大工程不过前面难过的基本上都设计完了总算能够步入正文了还是很快乐的。chunk分块我们前面费了那么大劲增强mineru输出的json文件各种回填各种元数据补充为的是啥为的就是满足我们对于结构化分块的设计以及后续检索质量的需求。在这里先声明一下我的结构化分块每个chunk不多于1024 token父子分块下父块则采用滑动窗口分块1536t, overlap100t最后一个父块不少于1536token最多就是两倍后续下面我的子块检索拼接策略有应对子块固定窗口分块固定为 100 token最后一个子chunk不少于 100 token防止出现几token为一chunk的情况而由于我子块固定分块大小比较小也就100token所以最后一个子chunk顶天也就200token占用较小对于分块还有咱的大宝贝增强版的json我们基于文章结构进行结构化分块同时如果某一段某一章节太长了一锅炖不下那我们可以对其进行父子分块这个子块我们直接用固定窗口切分就行后续回答反正是将子块所在章节塞入上下文中。这个方法天然支持扁平文档和复杂结构文档的分块因为扁平文档各位也知道肯定是那种大长段然后标题没几个所以需要靠父子分块。当然我们这里面的父子分块设计肯定不可能是将子块所在章节完整塞入上下文的因为我们这里面有个前提某一章节段落太长了。这个很重要我们都那么长了结果我们还好家伙全部塞入上下文让llm回答这不就很超模吗对于其他正常规格的结构化chunk。所以在此刻的设计我们先基于我们自己的推理来合理的塞入上下文后续整个项目或者说这个rag链路跑起来了我们再去优化我们的分块策略。基于写作习惯这个检索到的子块附近肯定是核心相关区然后还有这个父块的开头结尾两个子chunk。所以大概检索到的子块附近5个子chunk加上开头结尾4个子chunk大概1000个token左右在llm的注意力窗口中得到关注的概率差不多当然像什么U型曲线高相关的放提示词首尾这些我们现在肯定不考虑上面那个设计各位神通广大的uu要是有能力可以完善其实还是有缺点的首先是首尾和锚定的子chunk之间的断裂还有既然总共最大也就1024chunk然后我们还要从中挑选1000token出来这不就全覆盖嘛然后还有可能出错还有各种特殊情况例如命中的子块是开头的那就是往后延申子块。所以我就不考虑了直接统一返回父块。上面的分块还是有缺点例如没有把表格图片意图等独立标榜出来如果固定窗口分块那岂不是 直接把表格图片意图这些都直接腰折噜那我们前面辛苦半天增强的json都没啥用了所以我们要对这些增强的block进行标记即原子性确保始终都是一个整体。同时我们需要把固定分块与递归字符分块结合起来尽可能地不要出现断裂一个句子说一半地情况下直接给我截断了。所以我们可以这样设计在1024token这个临界点处上下浮动几十token找断句的符号例如句号分号这些确保语义的完整。同时结构化分块作为我们的整体设计底层采用父子分块这个更好的为我们提供了章节细节同时父块划分采用固定划分我们还要设计好最后一个chunk怎么办如果只剩下几十token这个作为一个父chunk想想就牙疼碎的劈里啪啦的。所以我们采用了末尾合并的策略如果小于300token则合并大于300还可以接受因为我们划分子块还可以给我划分出来3个左右。ParseResult.blocks │ ▼ [1. 结构化解析与清洗] ├── 过滤噪音块 ├── 计算 section_path ├── 识别原子块chart/image/table 打标 _is_atomic └── 按 section_path 分组 → Section[]小节合并100t 向前合并 │ ▼ [2. 在section中父块构建] ├── 大原子块200t从 token 流中抽离标记为独立父块候选记录 original_idx ├── 剩余 token 流含小原子块做固定窗口切分 │ ├── 目标 1024t句子边界对齐 ±70t │ ├── 切点落在小原子块内 → 推到原子块边界 │ └── 无句子边界 → 硬切兜底 ├── 末尾合并最后一块 300t → 并入上一块 └── 将独立父块候选按 original_idx 插回父块序列 │ ▼ [3. 子块切分] ├── 原子块内容 → 整体作为一个 ChildChunk不拆句子 └── 普通文本 → 按句子拆分贪心组合 1-3 句 ≤200t分完块就可以将子块放到postgresql这个向量数据库中存储了我打算使用pgvector还有父块直接存关系数据库postgresql众所周知好叭其实是我目前只知道的两种向量存储方式一个是sidecar模式适合qdrant等专用的向量数据库将text这些原文都给我单独提出来存到关系数据库中后续通过chunk_id关联另一个是text等直接跟vector存储在一起在同一个表中由于postgresql关于向量数据库的设计我们这里直接将子chunk中的text跟vector存储到一起至于像前面提到的分类器中的样例库他们向量化的存储肯定要用到MRL剪切到256维度差不多这样子能够减轻存储压力和检索成本。图谱抽取由于金融的专业性等我们对于图谱提取肯定不能使用openie这种开放式的长尾提取我们采用结构化的提取强约束提取提前定义好相关的实体类型关系等我们不用一开始就追求实体库的完整性可以采用版本迭代的形式逐渐更新实体库。同时我们要考虑新文档的加入这个过程中会产生大量的实体关系边我们要做的就是实体对齐例如byd和比亚迪如果分成了两个实体那么我们的图谱会逻辑断裂。我去参考了最近新出的SAG以及之前的GraphRAG, KAG, LightRAG首先这些都是封闭好的框架而我们目前已经实现了解析分块向量化图谱提取实际上是在分块之后开始用父块提取实体。加上这些框架都比较重当然lightrag主要是没有单独的流程他是完整的rag流程。所以我们需要自研一个。目前的mvp不打算实现图谱这个被我取舍优化掉了懂得都懂嘻嘻。在我之前的打算中是在问题涉及多跳推理的时候使用图谱查询与其他两路混合查询可是多跳在我们的智能体场景下是可以被拆解成多步查询的虽然推理链长了点类似于IRCoT可是对于我们mvp来说这个是可以接受的我们如果选择了图谱我们要开始维护实体库关系库不断优化抽取提示词等多了个复杂的需要运维的还不如后续优化迭代版本的时候再去仔细加入。至于原来的稍微复杂的问题我打算在问题优化上下手采用hyde或者step-backmulti-query等同时考虑一下要不要用splade等当然肯定要剪枝。至此我们解析分块嵌入大致就设计完了接下来来设计检索重排等工具之后我们就要开始多智能体的编排设计了下一讲我们开始设计rag工具。