新闻详情

新闻详情

首页 / 资讯中心 / 详情

RAG 检索很准,答案还是烂?把检索块和上下文块拆开

发布时间:2026/9/28 20:10:30来源:尧图网络
RAG 检索很准,答案还是烂?把检索块和上下文块拆开
RAG 检索很准答案还是烂把检索块和上下文块拆开最近几篇在写 RAG上一篇写了分块策略怎么选但那篇有个默认假设——检索用什么块就返回什么块。这篇把这个假设拆掉检索命中了相关内容LLM 的回答却单薄、答不出前因后果多数时候不是检索的锅是你把检索用的块和给模型的块当成了同一个。一、问题场景知识库按小块切好问“关羽为何千里走单骑”检索精准命中“辞别曹操、单人匹马出发”那一小块——只有结果没有前因模型拿着这一小段去回答只能复述结果答不出“为何”小块检索精准但回答需要完整上下文。这两个要求天然冲突块小了检索准但上下文断块大了上下文全但检索稀释。解法是把两层拆开子块只参与检索短、聚焦命中后沿映射返回父块完整上下文给模型。关键字段不是向量是 parent_id 映射——映射不稳就会出现“命中 A 返回 B”的事故。二、完整代码单文件直接跑# parent_child.py — 父子分块小块检索大块回答 # 依赖无纯标准库 import re def split_long(text, max_size): 按句拆保留标点塞不下的单句硬切兜底 chunks, buf [], for s in re.split(r(?[。]), text): if not s: continue if len(buf) len(s) max_size: buf s else: if buf: chunks.append(buf) while len(s) max_size: chunks.append(s[:max_size]) s s[max_size:] buf s if buf: chunks.append(buf) return chunks def build_chunks(text, child_size120, parent_size400): 父块段落聚合到 parent_size子块父块内按句细切。 返回 children {child_id: (text, parent_id)} 和 parents {parent_id: text} parents, children {}, {} pid, buf 0, def flush(): nonlocal pid, buf if not buf: return parents[pid] buf # 父块回答用信息完整 for c in split_long(buf, child_size): children[len(children)] (c, pid) # 子块检索用短而聚焦 pid 1 buf for para in text.split(\n\n): para para.strip() if not para: continue if buf and len(buf) len(para) 2 parent_size: flush() # 父块满了先落盘再开新块 buf f{buf}\n\n{para} if buf else para flush() return children, parents def retrieve(query, children, parents, k2): 玩具检索重叠字符打分。换向量库只改这个函数。返回父块 hits sorted(children.values(), keylambda cp: -sum(w in cp[0] for w in query))[:k] out, seen [], set() for _, pid in hits: if pid not in seen: # 同父块去重 seen.add(pid) out.append(parents[pid]) return out三、事故自检命中 A 返回 B父子分块最容易出的严重事故映射错位后检索命中了 A返回的却是 B——检索照常出结果答案答非所问不报错。自检把这条事故直接写成断言if __name__ __main__: text \n\n.join( f段落{i}讲的是主题{i}。 细节内容。 * 8 for i in range(30) ) children, parents build_chunks(text) # 1) 映射完整每个子块都能回到父块且父块包含该子块 for txt, pid in children.values(): assert txt in parents[pid], f命中 A 返回 B父块不含子块 {txt[:10]}… # 2) 父块拼回还原原文无丢字 assert .join(parents[i] for i in sorted(parents)).replace(\n\n, ) \ text.replace(\n\n, ), 父块丢字 # 3) 检索返回的父块必须包含命中内容 hits retrieve(主题7 的细节, children, parents, k2) assert hits and 主题7 in hits[0], 最相关命中没排到第一 print(f{len(children)} 子块 / {len(parents)} 父块 self-check ok)三条断言各管一类事故映射完整命中 A 返回 B、父块无丢字、检索命中真的排第一。分块参数怎么改这三条都得过。四、三个踩坑映射在运行时重算parent_id 入库时定死就别动检索服务里重算段落边界比如调了分块参数映射全错——命中 A 返回 B 就是这么来的。子块和父块同一次切、同一份映射入库父块不设上限父块无限聚合token 直接爆炸。本例 parent_size 兜底实际按模型上下文预算倒推换了检索就把映射也重写了玩具重叠检索换成向量库时只改 retrieve 一个函数children/parents 两层结构不动——映射层和检索层分开才好单测五、什么时候不用父子分块FAQ、知识卡片这类条目式内容条目本身就是天然父块一条问答就是完整上下文直接整条入库更省事。父子分块解决的是正文文档的检索精度与上下文完整的矛盾——条目式内容套上去是白加一层间接。总结铁律压成三句检索层和上下文层分开子块管准父块管全parent_id 入库时定死运行时只读不改三条断言映射完整 / 无丢字 / 命中排第一是父子分块的硬标准
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

SQE金舟军供应商质量管理培训 2026/9/28 20:52:00

SQE金舟军供应商质量管理培训

SQE供应商质量管理培训公开课课程 课程大纲 一.培训目的:通过本课程的学习,使学员能掌握供应商质量管理的工具,在互利的供方关系下,对供应商进行 有效管理,确保供应商提供产品的质量、成本和交期。 二.培训课程对象:供方质量工程师、供应商开…

阅读更多 →
4.3d10 2026/9/28 20:52:00

4.3d10

题目 设a>0,α,βa>0,\alpha,\betaa>0,α,β为任意两个实数,则有aα⋅aβaαβa^\alpha\cdot a^\betaa^{\alpha\beta}aα⋅aβaαβ 证明 不妨设a>1a>1a>1,根据实指数乘幂的定义知 aαsup{ar∣r≤α,r为有理数}aβsup{ar∣r≤β,r为有…

阅读更多 →
基于微信小程序的成人夜校预约管理系统设计与实现 2026/9/28 20:52:00

基于微信小程序的成人夜校预约管理系统设计与实现

摘 要 在终身学习理念普及与成人继续教育快速发展的背景下,成人夜校学员数量不断增加,课程安排与预约管理任务日益繁重。传统人工登记、线下办理的模式效率低下,易出现信息错乱、预约冲突等问题,难以满足现代化管理需求。为此&am…

阅读更多 →
超参数的调节方法——随机搜索 2026/9/28 20:52:00

超参数的调节方法——随机搜索

训练神经网络之前,我们需要先确定一些设置,例如学习率、批量大小、隐藏层神经元数量。这些设置叫作超参数。(“超参数”可以理解为训练开始前由人设定的选项;它和神经网络在训练中学到的权重不是一回事。) 问题是&…

阅读更多 →
Python 在定义函数时,究竟定义的是什么? 2026/9/28 20:52:00

Python 在定义函数时,究竟定义的是什么?

学习 Python 函数时,经常会听到一句话:Python 遇到函数时,只会定义,不会执行。其实所谓的“定义函数”,可以简单理解成:给一套操作取一个名字,让 Python 先看并记录这些操作,但暂时不…

阅读更多 →
linkedin-skills安全实践:如何防御“读后发布“AI代理的提示注入攻击(完整指南) 2026/9/28 20:51:53

linkedin-skills安全实践:如何防御“读后发布“AI代理的提示注入攻击(完整指南)

linkedin-skills安全实践:如何防御"读后发布"AI代理的提示注入攻击(完整指南) 【免费下载链接】linkedin-skills Claude skills for LinkedIn. 11 Claude Code and Codex skills that write human-sounding LinkedIn posts, craft …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉