有人给自己的笔记搭了一个检索增强生成工具,没用 LangChain,也没用 LlamaIndex,每个环节都手写。然后他问了一个笔记里明确有答案的问题,工具回了一句:我在你的笔记里找不到这个问题的答案。
答案就在那儿,他甚至能指出是哪一行。问题出在检索环节,而且不止一处。
第一处:段落从词中间被切开
他问的是"为什么输入和输出 token 定价不同"。笔记里写着:输出 token 比输入 token 贵约 8 倍,每百万 token 分别是 2.50 美元 和 0.30 美元。
检索交给模型的片段却是从词中间开始的——开头两个字符被切掉,前半句留在了上一块里。他按 500 字符 硬切,切口正好落在词中间,一句话被劈成两半,哪一半都不完整,也就匹配不上任何东西。
他以为好片段排在后面,把 top-k 提到 10,结果它根本没出现——没有任何一块包含那句完整的话。
整个过程没有任何报错。没有异常,没有警告。事实就在笔记里,取不出来,工具看起来却一切正常。
修法是别把块大小当成硬边界,往回扫,找一个合适的切点:段落分隔、句末标点、任意空白,依次尝试。他在写这段逻辑时还发现了一个死循环风险——给一段 2000 字符、完全没有空白的字符串,循环就停不下来。
第二处:同一个毛病,方向反过来
那就把块调大。他试了 900 字符,心想上下文多点总没坏处。
另一个问题坏了。笔记里用四个编号步骤回答了"怎么保证 API key 安全",一共八行,标题几乎就是这个问题本身。可在 900 字符的块里,这八行被无关内容淹没,向量变成了一堆材料的平均值,匹配不上了。
350 字符 能用,是因为他的笔记本来就是短小节、标题密集,350 字符差不多正好一节。这是他那批文档的性质,不是放之四海皆准的常数。
关键不在那个数字。块数量这类统计量根本告诉不了你这件事,只有真实问题能。
那个假设:一个阈值能识别答不出的问题
早期他做过一个测试:同一主题的三句话互相比对,得分 0.617;三句不相关的话,得分 0.031。二十倍的差距,看起来只要设个下限,低于就拒答,答不出的问题就解决了。
真用起来不是这样。他问"街角小店周日几点关门",笔记里没有任何关于商店或营业时间的内容。最佳匹配得分 0.3386——它匹配上了一块含"Sun Oct 4"的内容,因为 Sunday 和 Sun 确实相关。
而他最弱的一个真正有用的答案,得分 0.3655。两者只差 0.027。
他差点把下限设在 0.35。后来他把这个值在四个真实问题上扫了一遍:0.35 时,那个坏问题被压住,但两个真问题掉到只剩两段;0.40 时,它们什么都返回不了。
分数在不同问题之间根本没有校准。措辞贴近笔记的问题,什么都能得高分;换个说法的问题,什么都得低分,哪怕它的最佳命中是对的。绝对阈值比较的是从来不在同一把尺子上的数字。
真正管用的是提示词——给模型留一条体面的退路:如果这些段落里没有答案,就直说,比如"我在你的笔记里找不到这个问题的答案",不要猜,不要用通用知识补。
只告诉模型"根据上下文回答",哪怕塞给它无关段落,它也会编出点什么,因为拒答从来不是它手里的选项。明确给了许可,拒答才成为合规的回答。
他的相关性下限,最终是关着上线的。
三条结论
- 块数量统计不是质量指标。他花了一天比较块数量和平均长度,选出的值在第二个真实问题面前就失效了。
- 要针对的是静默失败。这里每个真问题都不报错——被切断的句子、被稀释的小节、匹配错模型后一本正经的胡说。
- 测最弱的情况,不是最强的。他的阈值看起来安全,直到把它扫过那些不是自己精心挑选的问题。
代码和这些决定背后的每一次测量,包括一开始做错的部分,都在 github.com/Iddrisusalima/ask-my-docs。他最后留了一个问题:如果你也搭过类似的东西,答不出的问题你是怎么处理的?提示词那招有效,但他总觉得检索层面还漏了一个信号。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.