前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
返回 AI 情报前线
All News · 全部资讯8915
  • OpenCode永久提供DeepSeek V4.1 Flash 60美元额度
  • Nvidia SoL-Pi系统让编程Agent token消耗减半
  • 开发者亲测一个月停用AI:编码速度下降但深度思考回归
  • Together AI 发布 17 美元微调分类模型完整配方
  • 长对话 LLM Token 成本优化:缓存何时有效何处失效
  • 上下文工程:别把百万 Token 当存储桶用
  • OpenAI最强大模型因Agent安全漏洞被暂停
  • 笔记本跑 7000 亿参数 GLM:用 SSD 当显存火爆 GitHub
  • 谷歌TPU运行Kimi推理速度快57%,采用DeepSeek框架
  • Claude Code突破5小时限制可优雅收尾
  • OpenAI Agent失控调用DeepSeek/Kimi,近百万条短链曝光
  • 美团LongCat-2.5-Preview:1.6T MoE大模型支持百万token上下文
  • Anchors 方法让 LoRA 微调灾难性遗忘降低 28 倍
  • AI 推理服务器实战:GPU 选型与云端部署指南
  • Meta Muse AI 助手被通过隐藏端点劫持
  • OpenAI智能体擅传53张客户图片至公网,已承认违规
  • GitHub Copilot企业托管配置支持内联验证
  • OpenAI智能体安全漏洞:53张用户图片被发布至公开网络
  • AI应用上线后高频故障模式分析
  • AI Agent与传统自动化的安全差异:控制权在哪里
  • 我的RAG评估骗了我两次
  • GitHub Copilot用量API新增PR评审耗时分析
  • OpenAI Agent入侵Hugging Face细节披露
  • Meta Muse超越ChatGPT同期数据,剑指智能眼镜
  • Anthropic论文:Claude可完成九层推理链
  • 多 Agent 系统八大隐蔽失败模式与真正有效的防护机制
  • GitHub Copilot Canvas 入门:用自然语言构建自定义工作流
  • AI Agent 误将私密文章发布上线:一次 CI 流程的教训
  • 切 AI 工具时不再重复介绍代码库:真正有效的做法
  • Supabase 用户因配置不当暴露大量数据
  • Copilot自动修复Agent现利用记忆上下文
  • GitHub Copilot 周更:新增 Claude Opus 模型和本地沙箱
  • AWS EKS上MoE强化学习训练吞吐量提升40%
  • SageMaker HyperPod上加速多模态RL训练
  • NarrateAI:Bedrock 上生产级 LLM 质量保障实战
  • Qwen3-TTS 语音克隆实战:AWS SageMaker 实时部署指南
  • Jevmem:为 Claude Code 自动注入项目记忆,基于 Jev
  • 一次前向传播问十个问题:决策模型提速 6.7 倍
  • 边缘设备低延迟部署 LLM 的策略与最佳实践
  • AI Agent 情景记忆 vs 语义记忆的实际应用
  • Claude Opus 5.5 vs GPT-6 Sol:新一轮降价潮来了
  • TypeSafe AI Jev:不做生成、只做判断的极速模型
  • AI Agent 的失败根源不在推理,在于状态管理
  • Cloudflare Turnstile Spin:AI Agent自动修复网站安全配置
  • 微软 Copilot 超级应用:聊天、编程、Agent 三合一
  • Meta Muse为每位用户配备云端Ubuntu电脑
  • n8n推出新Agent类型:自然语言描述即可创建自动化代理
  • Microsoft 推出 Copilot 超级应用,整合聊天、编程和 Agent
  • OpenAI与Cursor对Agent协调器的设计分歧
  • Anthropic 联手 Google Cloud 在纽约办 Claude Code 实战工作坊
  • AI SRE智能处理值班警报:自动根因分析并提PR修复
  • 已加载 51 / 8915
8.0
热点
AI SCORE
编程提效2026-09-26 05:47

我的RAG评估骗了我两次

dev.to · AI#RAG#LLM#评估方法
Editor brief · 编辑速览

作者用700行TypeScript/SQLite-Vec/Voyage/Claude搭建RAG系统后,花一周做评估实验,发现三个负面结果,其中最valuable的是揭示自身评估方法有缺陷——chunk overlap设计反而引入假相关。

文章思维导图
Knowledge map
拖拽缩放
Full translation

完整中文译文

我的 RAG 评估一直在骗我,而且是两次!!

我搭了一套常见的东西:一个 CLI,摄入文档、嵌入向量、用引用回答问题。Bun、TypeScript、SQLite(用 sqlite-vec 做向量索引)、Voyage 做嵌入、Claude 做生成。大约 700 行代码。这套技术栈没什么特别的——周末工作量的东西,网上有五十个教程讲这个。

真正有意思的是接下来那一周——我想看看这东西到底效果如何。我跑了四个实验,三个阴性,最有价值的一个告诉我:我的测量方式本身就是坏的。

3,200 段维基百科 passage,按 500 词分块、重叠 50 词,用 voyage-3.5 嵌入到 1024 维,存放在 vec0 虚拟表里。查询时把问题嵌入、用 L2 距离取 top k,然后把相关块交给 Claude 并指示它引用或拒绝回答。

一次查询长这样——答案流式输出,然后打印来源,* 标记的是答案实际引用到的:

$ bun run index.ts query "What is the capital of Uruguay, and how many people live there?" -k 3

Montevideo is Uruguay's capital [1][3]. Its metropolitan area is home to 1.7 million of the country's 3.3 million people [1].

[1] data/rag-mini-wikipedia.jsonl#0 — distance 0.846 [2] data/rag-mini-wikipedia.jsonl#15 — distance 0.916

[3] data/rag-mini-wikipedia.jsonl#36 — distance 0.922

三个取回的块里用了两个;第三个取到了但没用到。打印出未使用的块,这件事比我预想的更重要—— retrieval 暴露出来的内容和答案实际依赖的内容之间的差距,是你不用跑任何评估就能看出 retrieval 质量的地方。

这个数据集自带 918 对问答,随语料一起提供,这才让任何测量成为可能。它没有标注哪段 passage 回答哪个问题,所以没有 gold label 可以对比。我的代理指标:一个 retrieval 算命中,只要答案字符串出现在某个取回的块里。

麻烦就从这个代理指标开始了。

发现 1:指标是错的,而且它反转了一个结论

我的第一版检查规范化后的答案是否作为子串出现。简单、直接、明显——但看了一段时间才发现它错在哪里。

下面这个问题被判定为未命中:

▎ Q: What countries border Liechtenstein? ▎ Expected: "Switzerland and Austria." ▎ Retrieved, rank 1: "...a tiny, doubly landlocked alpine country in Western Europe, bordered by Switzerland to its west and by Austria to its east."

检索是完美的。评分器说不,因为确切的短语"Switzerland and Austria"从未连续出现过。

我换成了 token 重叠——去掉停用词,如果 80% 的答案内容词出现在同一个块里,就算命中。测得的命中率在 k=3 时从 65% 移动到了 78%。我的系统一直比我想的好了 13 个点。

还有第二个同类 bug。语料写的是"around 60,000",答案写的是"60000"。去掉标点后前者变成了两个 token,永远无法匹配后者。在规范化之前先把数字组合连起来,又找回了一个点。

真正让人心痛的部分:在那个坏的指标下,命中率从 k=3 之后看起来是平的——k=3、5、10 时分别是 65%、66%、67%。我得出结论:取回超过 3 个块是浪费上下文,考虑降低默认值。而用修正后的指标,曲线一直在上升:79%、82%、83%。坏的指标不只报了一个错的数字,还把我指向了错误的决策。

发现 2:20 道题什么也测不出来

我一开始跑了 20 道题,因为对于一个副业项目来说那感觉是合理的评估集大小。

n=20 时我测到 50%(k=3)。n=100,同样的种子、同样的代码:65%。(两者都在上面的修复之前的原始子串指标下——这里的重点是差距,不是那个数字本身。)

这 15 个点的差距纯粹是采样噪声。20 道题时 95% 置信区间大约是 ±22 个点——宽到能吞掉任何你实际在测试的变化。n=100 时两个不同种子相差 1–5 个点,这才是可用的分辨率。

如果你的评估集小到一下午就能手写出来,那它也小到可以告诉你任何你想听的话。

发现 3:混合搜索,还没建好就被限定了

混合检索——把 BM25 关键词排名和向量排名合并——是标准的下一步,而且我有一个来自自己笔记的动机案例。问"关于 refinance 我需要知道什么",正确地暴露了一篇文档——里面"refinance"和"refi"这两个词出现次数恰好为零。关键词搜索会把它排在不知道哪里。

于是我在同样的块上加了 FTS5 索引,用 reciprocal rank fusion 融合两个排名。结果,n=100:

┌─────────┬─────┬─────┬─────┬──────┐
│         │ k=1 │ k=3 │ k=5 │ k=10 │
├─────────┼─────┼─────┼─────┼──────┤
│ vector  │ 69% │ 79% │ 82% │ 83%  │
├─────────┼─────┼─────┼─────┼──────┤
│ keyword │ 60% │ 71% │ 78% │ 82%  │
├─────────┼─────┼─────┼─────┼──────┤
│ hybrid  │ 67% │ 78% │ 82% │ 83%  │
└─────────┴─────┴─────┴─────┴──────┘

混合最多和向量持平,在低 k 时还输了。在动融合权重之前,我先测了原因——在 k=10 时每个检索器找到对方遗漏的东西的频率:

both retrievers found it 80
vector only 3
keyword only 2  <- everything fusion could rescue
neither 15

vector 单独 83% 完美,fusion 天花板 85%

总共两个点的提升空间。任何融合策略——RRF、加权、学习——在这里都不可能超过 85%,而且 RRF 把两个点花在了降级好的向量命中上。这不是调参问题,花一下午调参什么也发现不了。

为什么agree这么多?因为这是针对百科散文的自然语言问题,回答 passage 和问题共享含义和词汇。混合检索在查询带有精确 token——姓氏、错误码、零件号、函数名——而嵌入会模糊这些的时候才有用。这个语料几乎没有这种情况。

互补性测试花了十分钟,本来可以节省一天的工作。我应该在构建任何融合之前、在任何语料上先跑这个测试。

发现 4:更多上下文配更少块输给了更多块

评估暴露了一个具体的失败案例困扰着我:

▎ Q: Who graduated in ecclesiastical law at the early age of 20? ▎ Retrieved, rank 1: "He graduated in ecclesiastical law at the early age of 20 and began to practice."

检索又是完美的。块就是不包含自己的主语——"Amedeo Avogadro" 在两个块之前,而"He"没有指代身份。

教科书式的修复是上下文检索:在嵌入之前给每个块前面加上文档级上下文。我没法应用它。这个数据集中每个 passage 都是作为自己的单块文档摄入的,所以没有父文档可以继承上下文——那句话到的时候已经被切开了。在你预算花数千次 LLM 调用来生成不存在的上下文之前,值得先检查一下。

我能低成本测试的是:把每个检中的 hit 扩展到包含它两侧的块。零额外嵌入。它精确修复了目标案例——在 radius 0 时找不到答案;radius 1 时窗口读出来是"Amedeo Avogadro was born in Turin... He graduated in ecclesiastical law..."

按 k 来衡量,看起来是明显的胜利:k=1 提升 3 点,k=10 提升 2 点。

但按相等 k 来比较是在作弊,因为每个 hit 现在携带了最多 3 倍的文本。按实际消耗的上下文来匹配:

┌────────────┬────────────┬─────────────────────┐
│  context   │   plain    │      expanded       │
├────────────┼────────────┼─────────────────────┤
│  3 chunks  │  k=3 → 79% │  radius 1, k=1 → 72%│
├────────────┼────────────┼─────────────────────┤
│  5 chunks  │  k=5 → 82% │  radius 2, k=1 → 75%│
├────────────┼────────────┼─────────────────────┤
│ ~10 chunks │ k=10 → 83% │  radius 1, k=3 → 81%│
└────────────┴────────────┴─────────────────────┘

普通检索在每个预算下都赢了。十个独立的猜测覆盖的语料比三个用邻居填充的猜测更多。

任何在每个 hit 上增加文本的技术都必须按匹配的上下文来比较,而不是按匹配的 k。否则你测的是"更多上下文有帮助吗"——这个问题的答案是显而易见的(有帮助),但告诉不了你这个技术本身怎么样。

然后我读了那些未命中的

15 道题两个检索器都没找到。我全部读了,花了二十分钟——这本来应该是我最先做的事。

其中八道根本没有任何系统能回答:"页面上的第一个数字是什么?""页面上的最后一个词是什么?""他什么时候死的?"(没有指代对象)"近年来发生了什么?",一道需要跨两个事实做算术,一道答案是"It is arguable."

还有三道是评分器的人为因素——正确的块取到了,答案表述方式不同,或者刚好在我的 80% 阈值下面(71% 和 67%)。

剩下四道是真正的检索失败,100 道里。

所以原始基准是 83%。排除语料库中没有答案的问题后,更接近 93%。两个数字都是真的,它们之间的差距才是重点:基准里包含垃圾,而你还没检查过那些失败案例的数字就不是测量。

如果我一开始就告诉自己这些

在任何优化之前先读那些未命中的。我的每一个发现都来自读失败案例,而不是盯着 aggregate 数字变动。

在构建之前先界定改进空间。互补性检查花了十分钟,封堵了一天的工。

先怀疑指标。它错了两次,朝同一个方向错,还改了一个决策。

按成本匹配,而不是按你转的那个旋钮。固定的 k 不是固定的上下文。

n=20 是冒烟测试,不是评估。

四个实验里三个失败了。系统还在原地——纯向量搜索,k=5——我现在知道这是正确的配置,这比一个我无法解释的 2% 提升更有价值。

代码:github.com/JQ100/ask-my-notes。测试工具是 scripts/eval-retrieval.ts;--mode vector|keyword|hybrid 和 --expand N 可以复现上面每个表格。

Original source

本文由 AI 翻译整理自 dev.to · AI,原文版权归原作者所有。

阅读英文原文
上一篇
AI Agent与传统自动化的安全差异:控制权在哪里
下一篇
GitHub Copilot用量API新增PR评审耗时分析