Featured image of post 从关键词检索到 TopK:手写一个最小 RAG 检索器的技术演进路径

从关键词检索到 TopK:手写一个最小 RAG 检索器的技术演进路径

详解 RAG 检索阶段从基础字符串匹配到加权排序的实现演进

AI 应用开发 Day4:RAG 检索器的最小可行性实现

本文基于稀土掘金开发者社区的技术分享,系统梳理了 RAG(Retrieval-Augmented Generation)检索环节的最小可行实现路径。核心在于通过关键词加权与 TopK 排序,突破传统 contains() 纯字符串匹配的语义局限。

核心技术演进路径

RAG 流程包含 Retrieve(检索)、Augment(增强)、Generate(生成)三阶段。本文聚焦 Retrieve 环节的实现升级:

  • 起点:直接使用 Java 的 contains() 进行关键词匹配
  • 进阶:将知识库与检索逻辑解耦,支持多词典映射
  • 关键升级:引入 KeywordScore 加权机制,同义词/相关词多次命中则加分
  • 最终架构:遍历全库→计算相关度分数→降序排序→TopK 截取

关键认知转变:关键词命中不等于语义相似。例如问题"为什么这种内存数据库性能这么高"无法被 contains("Redis") 捕获,暴露出纯字符串匹配的本质缺陷。

从单知识召回到多知识 TopK

实现过程中需解决三个实际问题:

  1. 知识库结构化存储:使用 Map<String, List<String>> semanticMap 建立实体-语义词映射,如 Redis 对应 [“redis”, “缓存”, “内存数据库”, “高性能”, “key-value”]

  2. 多知识同时召回:问题如"Redis 和 MySQL 有什么区别"需同时命中两个实体,不能找到首个匹配即终止

  3. TopK 排序机制:引入常量 TOP_K = 3 控制返回数量,避免超量知识挤占 LLM Prompt 上下文

测试用例显示:问题"Redis和MySQL有什么区别?“中 MySQL 命中 [“mysql”, “sql”] 得分 2,Redis 命中 [“redis”] 得分 1,最终按分数降序返回。

检索器的架构设计

完整检索流程包含五个步骤:

  1. 用户输入问题后转小写处理(如 “Redis为什么这么快?” → “redis为什么这么快?")
  2. 遍历知识库中每条知识的语义词典,统计命中次数作为原始分数
  3. 封装为 KnowledgeScore DTO 携带知识文本与分数
  4. 按分数降序排序后截取 TopK 条目
  5. 提取知识文本拼接到 Prompt 的"已知知识"部分

值得注意的 Bug 反例:contains("sql") 会错误命中 “mysql”(因字符串包含关系),说明关键词方案存在虚假相关性风险。

落地建议

  • 适合立即实践:中小规模知识库(< 1000 条)、语义关系明确的垂直场景(如产品文档、FAQ 系统)
  • 建议再等等:需要处理多语言、同义词泛化、上下文长依赖的复杂场景,应引入 Embedding + 向量数据库方案

写在最后

当前关键词检索方案本质是"相关度计算"的简化版,其骨架结构(候选→打分→排序→截取)与后续向量检索完全一致。区别仅在于分数计算方式:从简单的字符串匹配计数,升级为语义向量的余弦相似度计算。这为深入学习 Embedding 技术提供了清晰的衔接入口。