RAG(三)检索(1)关键词检索(BM25)
关键词检索BM251、apiapi接口BM25Okapi调参BM25 最核心的参数是这几个参数含义影响k1控制词频饱和程度越大词频重复出现的影响越明显b控制文档长度惩罚越大长文档惩罚越明显discount_overlaps是否忽略重叠 token处理同义词、叠加 token 时很有用k1默认值通常是 1.2控制“同一个词重复出现多次”时的加分程度k1 越大重复词的影响越强k1 越小重复词的边际收益越快饱和b默认值通常是 0.75控制文档长度归一化b 0 时基本不做长度惩罚b 1 时长度惩罚更强一般来说标题、名字、短字段b 可以适当大一点长文档b 不要过大否则容易过度惩罚discount_overlaps这个参数在 Lucene / Elasticsearch 里比较常见。如果文本分析器产生了重叠 token比如同义词扩展、叠加 token是否把这些 token 算进文档长度就由它控制。demoimport jieba from rank_bm25 import BM25Okapi corpus [ 苹果有什么营养, 苹果手机电池怎么保养, 水果营养成分表 ] tokenized_corpus [jieba.lcut(doc) for doc in corpus] bm25 BM25Okapi(tokenized_corpus) query 苹果的营养价值 tokenized_query jieba.lcut(query) top_docs bm25.get_top_n(tokenized_query, corpus, n2) print(top_docs)[苹果手机电池怎么保养, 苹果有什么营养]2、倒排索引存储在哪里可以是Elasticsearch / OpenSearch / Lucene 这类系统使用步骤1、切片BM25 不要求你必须切片但实际项目里通常会切因为整篇文档太长检索粒度太粗章节/段落更容易命中返回上下文更精准{doc_id: info.md,chunk_id: info.md_0001,section_title: 登录流程,content: 用户输入账号密码后进行验证码校验。}2、写入索引字段作用doc_id原始文档标识chunk_id片段标识file_name文件名section_title章节标题content要检索的正文tags可选标签path文件路径或来源路径其中最关键的是 content因为 BM25 主要就是对这个文本字段做词项匹配和打分。可以分成 3 类来看数据存什么存在哪原文info.md 的正文、标题、元数据_source、stored fields、业务库、文件系统倒排索引分词后的 term、doc id、词频、位置、归一化信息Lucene 的索引文件里BM25 参数k1、b、discount_overlaps索引配置 / similarity 配置Elasticsearch 官方文档说明了text / keyword 字段支持 similarity默认就是 BM25。倒排索引里会保存文档编号、词频、位置等信息BM25 依赖这些信息来打分。Lucene 的 codec 体系则负责把 postings lists、norms、stored fields 等索引数据编码到磁盘文件中。而 Elasticsearch 的索引数据则写在节点的 path.data 目录里。3、检索对 query 做同样的分词处理去倒排索引里找包含这些词的 chunk读取词频、文档长度、词稀有度等统计信息按 BM25 公式算分排序返回 TopK再从 _source 或 stored fields 中把 chunk 原文取出来