先区分问题的检索语义
“检索”不是单一操作。一个系统可能同时面对精确筛选、关键词匹配、短语定位、概念近似、跨文档聚合和时间序列计算。单一向量接口无法在这些目标上同时保持精确性、可解释性和稳定性。
| 问题类型 | 主要机制 | 结果含义 |
|---|---|---|
| 某日期范围内的记录 | 字段过滤、SQL | 满足条件的完整集合 |
| 某个名称或术语出现在哪里 | 全文索引、短语查询 | 包含词项的文档排序 |
| 与某概念含义接近的段落 | 向量嵌入、相似度 | 语义空间中的近邻 |
| 某期间的总额或分类占比 | 结构化数据、确定性聚合 | 可复算的数值 |
| 关键词与概念召回并重 | 多路召回、排名融合 | 合并后的候选证据 |
结构化查询负责精确事实
关系表、CSV 和带类型字段的记录适合等值条件、范围条件、分组、排序与聚合。日期、币种、金额、状态和分类都具有明确的数据类型与运算规则。此类问题的正确性来自 schema、约束和确定性计算,而不是文本相似度。
向量检索会返回“看起来相近”的记录,但不能保证覆盖某个期间的全部行,也不能保持小数精度、会计恒等式或去重规则。因此,数值报表通常由结构化数据生成;文本检索只承担解释材料与上下文的发现。
倒排索引与全文检索
普通文档可以看作“文档到词项”的映射。倒排索引反转该关系,为每个词项保存出现过的文档或位置列表,列表通常称为 postings。查询一个词时,系统直接读取对应 postings,不需要逐个扫描全部文档。
位置数据支持短语和邻近查询;字段索引支持标题、正文或标签的不同权重。英文常按单词边界切分。中文没有天然空格边界,常见实现包括词典分词、统计分词和字符 n-gram。字符二元组、三元组会增加索引体积,但能稳定处理新词、简称和混合语言文本。
“全文索引”描述可搜索全文的整体能力;“倒排索引”描述实现该能力的核心数据结构。两者经常同时出现,但概念层级不同。
BM25 如何排序关键词结果
BM25 是基于词项统计的相关性函数。核心因素包括查询词在文档中的频率、词在整个语料中的稀有程度,以及文档长度相对平均长度的偏差。一个常见表达为:
IDF(t)提高稀有词的权重,降低到处出现的词的区分度。f(t,D)表示词频;饱和项使重复十次不会简单等于重复一次的十倍。|D|/avgdl提供长度归一化,减少长文仅因词更多而占优的倾向。k₁与b控制词频饱和和长度校正的强度。
BM25 对专有名词、错误码、产品名和原文措辞具有直接解释性。局限来自词汇不匹配:两个段落表达同一概念但没有共享词项时,BM25 可能无法建立联系。
向量嵌入与语义相似
嵌入模型把文本映射到固定维度的数值向量。训练目标使语义相关文本在向量空间中更接近。检索阶段通常计算余弦相似度、点积或欧氏距离。
精确向量扫描会比较查询向量与全部候选,结果确定但计算量随向量数线性增长。HNSW、IVF 等近似最近邻结构以额外内存、构建成本和召回损失换取更低延迟。数据量较小时,精确扫描的运维复杂度通常更低;规模和延迟要求提高后,近似索引的收益才会显现。
向量相似不代表事实相同。模型可能混淆否定、数字、时间、主体或因果方向;长文本截断和分块边界也会改变向量。因此,向量结果适合扩大召回范围,完整原文仍然承担证据确认。
混合检索与 RRF
关键词评分和向量相似度处在不同量纲,直接相加会引入不稳定的缩放问题。Reciprocal Rank Fusion(RRF)只使用每个通道的名次:
每个召回通道分别产生排序列表。某个文档在多个列表中都靠前时,融合得分随之提高。常数 k 降低头部名次差异的敏感度。RRF 不需要把 BM25 分数与余弦分数校准到同一区间,适合组合异构检索器。
混合检索仍然受各通道候选集限制。若结构化必读材料不进入任一候选集,融合算法不会自动补回。因此,强制证据清单、元数据过滤和多路召回属于不同层次的控制。
SQLite 作为单机检索层
SQLite 是进程内数据库,没有独立服务器进程。FTS5 提供全文索引、短语查询、高亮、snippet 与 bm25()。文档元数据、分块、构建版本和向量 BLOB 可以保存在同一数据库文件中,事务与原子文件替换为索引发布提供清晰边界。
| 表或索引 | 职责 |
|---|---|
documents | 源标识、标题、日期、领域和内容哈希 |
chunks | 稳定分块、heading、顺序和原文片段 |
FTS5 | 词项 postings 与 BM25 排序 |
embeddings | 模型标识、维度和 float32 向量 |
metadata | schema 版本、源指纹和构建计数 |
SQLite 的优势是部署简单、备份直观、SQL 过滤方便和本地事务完整。限制包括单写入者协调、大规模向量扫描成本,以及默认数据库文件不自带加密。文件权限、磁盘加密、备份位置和进程权限仍然属于系统安全设计。
权威数据与隐私边界
派生索引与权威数据分离可以降低损坏面。索引进程只读取源文件;数据库、模型、临时文件、锁和日志位于独立缓存层。索引删除后可由源数据重建,任何检索结果都不反向覆盖原文。
“本地数据库”本身不等于隐私安全。嵌入模型可能在首次使用时联网下载公开权重;完成缓存后,本地推理不需要把文本发送到外部 API。临时文件、崩溃转储、命令历史、云同步目录和备份同样可能扩大数据边界。安全属性来自完整的数据流与运行环境,而不是文件扩展名。
索引构建与更新生命周期
- 读取白名单配置,解析并规范化源路径。
- 计算源文件集合与内容哈希,形成构建前指纹。
- 按标题、段落和长度分块,并保留源路径、日期、heading 与 chunk 哈希。
- 在缓存目录的新临时数据库中构建 FTS5 与向量;内容未变的 chunk 可复用旧向量。
- 再次计算源指纹。构建期间有变化时,临时结果被放弃。
- 执行数据库完整性检查、文件同步与原子替换,上一版数据库直到替换时仍可查询。
稳定 chunk ID 使增量复用成为可能。模型名称、维度、分块配置或 tokenizer 变化会改变索引语义,构建元数据用于识别这种不兼容。单一构建锁避免两个写入者同时发布不同版本。
评测与常见失败模式
检索评测需要带相关性标注的查询集合。Recall@k 衡量相关项是否进入前 k 名;MRR 关注第一个相关项的位置;nDCG 适合存在多级相关性的排序。答案准确性、引用完整性和推理可靠性属于检索之后的独立评测层。
| 失败模式 | 可观测现象 | 对应控制 |
|---|---|---|
| 中文分词不匹配 | 短词、新词或混合语言漏召回 | n-gram、领域词典、查询分析 |
| 分块过大 | 向量主题混杂,片段难定位 | 按 heading 与段落切分 |
| 分块过小 | 上下文断裂,否定与主体丢失 | 重叠窗口、父文档回读 |
| 向量误相似 | 措辞接近但事实不同 | BM25 交叉、元数据过滤、原文确认 |
| 索引陈旧 | 源已更新而结果仍指向旧片段 | 源指纹、构建版本、freshness 检查 |
| 以 top-k 代表全集 | 聚合遗漏、错误的“没有记录”结论 | 结构化查询、完整枚举、必读清单 |
其他存储与检索方案
| 方案 | 主要特征 | 典型适用条件 |
|---|---|---|
| SQLite + FTS5 + 向量 BLOB | 单文件、进程内、可精确扫描 | 单机、低运维、数据量与并发有限 |
| sqlite-vec | SQLite 向量扩展,SQL 内执行向量查询 | 需要保留单文件形态并增加向量 SQL 能力 |
| PostgreSQL + pgvector | 事务数据库、丰富过滤、HNSW/IVFFlat | 已有 PostgreSQL、并发写入与服务化查询 |
| Qdrant | 专用向量服务、过滤与分布式接口 | 高并发 API、独立服务生命周期 |
| LanceDB | 面向列式数据与多模态检索的嵌入式方案 | 较大分析数据集、对象存储或多模态工作负载 |
选择条件包括数据规模、写入并发、延迟目标、过滤复杂度、备份方式、加密要求和运维能力。向量数据库解决的是向量存储与近邻查询,不会替代源数据治理、结构化计算、证据引用或隐私控制。
来源与说明
- SQLite FTS5 Extension:FTS5 查询、tokenizer、排序与
bm25()。 - SQLite Is Serverless:进程内、无独立数据库服务器的架构。
- The Probabilistic Relevance Framework: BM25 and Beyond:BM25 的概率相关性框架。
- Reciprocal Rank Fusion Outperforms Condorcet and Individual Rank Learning Methods:RRF 排名融合。
- Efficient and Robust Approximate Nearest Neighbor Search Using Hierarchical Navigable Small World Graphs:HNSW。
- Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks:检索增强生成的经典架构。
- FastEmbed、sqlite-vec、pgvector、Qdrant、LanceDB:本地嵌入与向量存储实现资料。