Zvec全文检索(FTS)完全指南:BM25、jieba中文分词与N-gram分词器
【免费下载链接】zvecA lightweight, lightning-fast, in-process vector database项目地址: https://gitcode.com/GitHub_Trending/zve/zvec
Zvec 是一款轻量、极速的进程内向量数据库,除了向量相似度检索,它还内置了原生的**全文检索(Full-Text Search, FTS)**能力:基于BM25算法的相关性打分、jieba 中文分词、N-gram 分词器以及一套 Lucene 风格的查询语法,让"关键词精确搜索"和"语义向量搜索"能在同一个引擎里共存、混合查询。这篇指南将带你从零理解 Zvec 全文检索的每个核心部件,新手也能快速上手。
一、什么是 Zvec 全文检索(FTS)?
传统向量检索擅长"意思相近"的召回,但面对精确关键词(型号、订单号、报错代码、人名等)往往力不从心。Zvec 的 FTS 正是为此设计:
- 关键词检索:支持自然语言或结构化表达式搜索字符串字段;
- BM25 相关性排序:命中的文档按经典 IR(信息检索)打分排序,而不仅是"命中/未命中";
- 多分词器可插拔:
standard(默认)、jieba(中文)、ngram(短文本/代码/短语)、whitespace四种内置分词器; - 与向量检索混合:同一次查询中可以融合 FTS、向量语义与标量过滤。
核心实现集中在src/db/index/column/fts_column/目录,按职责清晰分层:
fts_column/ ├── bm25_scorer.h / .cc # BM25 打分与 WAND 优化 ├── tokenizer/ # 分词器与过滤器 │ ├── jieba_tokenizer.h # 中文分词 │ ├── ngram_tokenizer.h # N-gram 分词 │ ├── standard_tokenizer.h # 标准分词 │ └── tokenizer_factory.cc # 分词器工厂 ├── iterator/ # 倒排迭代器(AND/OR/短语) └── posting/ # 位压缩倒排表 + SIMD 加速二、BM25 相关性打分:结果为什么这样排序?
BM25(Best Matching 25)是信息检索领域的经典打分函数,Zvec 在 bm25_scorer.h 中完整实现了标准公式:
核心思想:一个词在某篇文档里出现得越多(词频 tf),且在整个语料中越罕见(逆文档频率 IDF),这篇文档的相关性就越高;同时用文档长度归一化避免长文档"占便宜"。
Zvec 的关键工程细节:
| 设计点 | 说明 |
|---|---|
| 经典默认参数 | k1 = 1.2(词频饱和)、b = 0.75(长度归一化),符合 IR 通用最佳实践 |
| 分段统计 | BM25 统计量(文档总数、总词数、平均文档长度)按 segment 独立维护,读写线程安全 |
| WAND 剪枝 | 用词的最大词频预计算分数上界,TopK 检索时提前跳过不可能进入前列的文档,显著减少无效打分 |
| 增量统计 | 写入时实时更新统计量,保证搜索立刻使用最新语料状态 |
💡新手理解:你不需要手动调参——默认参数已经过基准调优,绝大多数场景开箱即用。
三、分词器怎么选?jieba、N-gram 与 standard
分词器决定了"什么算一个词",直接决定检索质量。Zvec 在 tokenizer_factory.cc 中提供四种分词器:
1️⃣standard(默认)——通用英文/混合文本
按 Unicode 边界切分单词,适合英文为主的场景。可以叠加 token 过滤器(在FtsIndexParam的filters中配置):
lowercase:统一小写;ascii_folding:去掉重音字符(café → cafe);stemmer:基于 Snowball 的词干还原(running → run)。
2️⃣jieba—— 中文分词的可靠选择
中文没有天然空格分词,standard分词器会把整句当一个词。jieba 分词器(jieba_tokenizer.h)内置了 cppjieba 引擎:
- 默认使用CutForSearch(搜索引擎模式),产出更细粒度的词——既切出"中华人民共和国",也切出"中华""人民",保证索引与查询两侧都能命中;
- 四种切分模式可配:
search(默认)、mix、full、hmm; - 支持用户自定义词典(
user_dict_path)注入领域术语,支持指定词典目录(jieba_dict_dir); - 初始化后线程安全,可并发调用 tokenize。
"全文检索" --jieba--> [ 全文, 检索, 全文检索 ]3️⃣ngram—— 短语、代码与短文本的利器
N-gram 分词器(ngram_tokenizer.h)把文本切成连续字符的 n 元组(默认 2-gram),是 Zvec v0.7.0 新增的能力,特别适合:
- 短语与子串匹配:"vector" 能匹配 "vectorize"、"vector_db";
- 代码检索:函数名、路径等没有空格边界的标识符;
- 短文本:标题、标签、命令。
配置项:ngram_min/ngram_max(默认均为 2,差值不超过 1)、token_chars(可选限定参与切分的字符类别,如letter、digit)。
4️⃣whitespace—— 按空格切分
最简单直接:以空白为界,不改变词形。适合内容本身已有明确分隔符的场景。
选型口诀🧭
中文文档 →
jieba;英文/通用 →standard(+filters);代码/短语/子串匹配 →ngram;日志、键值类 →whitespace
四、快速上手:定义 FTS 索引与发起查询
第 1 步:为字段声明 FTS 索引
在 Python SDK 中,给字段挂上FtsIndexParam即可(类型定义见python/zvec/model/param/):
from zvec.model.schema import FieldSchema from zvec.model.param import FtsIndexParam # 中文字段用 jieba 分词 content = FieldSchema( name="content", data_type=zvec.DataType.STRING, index_param=FtsIndexParam(tokenizer_name="jieba"), ) # 代码/短文本字段用 ngram,extra_params 传 JSON 配置 code = FieldSchema( name="code", data_type=zvec.DataType.STRING, index_param=FtsIndexParam( tokenizer_name="ngram", extra_params='{"ngram_min": 2, "ngram_max": 3}', ), )字段 Schema 的类型定义在 field_schema.py。
第 2 步:用 FTS 查询
查询参数Fts支持两种互斥输入(定义见 query.py):
①match_string(宽松匹配)——分词后"任一词命中即返回",适合普通搜索框:
from zvec.model.param import Fts, Query query = Query(field_name="content", fts=Fts(match_string="向量数据库 性能")) results = collection.query(query, topk=10)②query_string(结构化表达式)——Lucene 风格,支持完整布尔逻辑:
| 语法 | 含义 | 示例 |
|---|---|---|
+词 | 必须包含 | +BM25 +分词 |
-词 | 必须排除 | +python -爬虫 |
"短语" | 精确短语(保持词序相邻) | "全文检索" |
and / or / not | 显式布尔组合 | 召回 and not 排序 |
query = Query( field_name="content", fts=Fts(query_string='+向量 -向量库 "BM25 分词"'), )查询表达式由内置解析器编译(语法文件见
src/db/index/column/fts_column/FtsLexer.g4与FtsParser.g4),支持 AND、OR 与短语迭代的执行计划,性能远优于应用层字符串过滤。
五、Zvec FTS 的性能黑科技(新手也值得知道)
- 位压缩倒排表:posting list 采用 bit-packing 压缩存储,并提供 SSE4.1 / AVX2 SIMD 加速实现(
fts_column/posting/),内存与 CPU 双友好; - WAND 剪枝:如前所述,TopK 检索只计算"有希望"的文档分数;
- RocksDB 承载:倒排索引落在 RocksDB 之上(
fts_rocksdb_reducer.cc),多 segment 合并时统计量正确重算,保证 BM25 打分在数据合并后依然准确; - 进程内零部署:所有检索发生在你的进程里,没有网络往返,延迟毫秒级。
对应的质量保障也值得放心:单元测试覆盖倒排表、索引器、多 segment 召回(tests/db/sqlengine/fts_recall_test.cc)以及 Python 层的查询校验(python/tests/test_fts_query.py)。
六、混合检索:让 FTS 与向量各展所长
Zvec 的核心卖点是混合检索——FTS 负责"精确词命中",向量负责"语义相似",两者可同场协作:
- 单次查询融合:FTS 召回 + 向量召回 + 标量过滤在查询计划层融合排序;
- 稀疏向量路线:SDK 提供 BM25EmbeddingFunction,把文本编码为 BM25 稀疏向量,与稠密向量做加权混合检索;
- 重排(Rerank):粗召回后接 reranker 精排(
src/db/reranker/reranker.cc),进一步提升头部结果质量。
实践建议:
- 关键词强约束(型号、ID、报错文本)→ 字段挂 FTS 索引,用
query_string精确控制; - 语义泛化问题("怎么提升检索效果")→ 向量索引;
- 两者都重要 → 混合查询,让引擎替你融合。
七、核心路径速查表 📌
| 模块 | 路径 |
|---|---|
| BM25 打分器 | src/db/index/column/fts_column/bm25_scorer.h |
| jieba 中文分词 | src/db/index/column/fts_column/tokenizer/jieba_tokenizer.h |
| N-gram 分词器 | src/db/index/column/fts_column/tokenizer/ngram_tokenizer.h |
| 分词器工厂 | src/db/index/column/fts_column/tokenizer/tokenizer_factory.cc |
| FTS 查询语法 | src/db/index/column/fts_column/FtsParser.g4 |
| Python 索引参数 | python/zvec/model/param/ |
| Python FTS 查询 | python/zvec/model/param/query.py |
| BM25 稀疏嵌入 | python/zvec/extension/bm25_embedding_function.py |
八、总结
- Zvec 的 FTS 把BM25 相关性打分、可插拔分词器与布尔查询语法装进了一个进程内数据库,无需独立搜索引擎;
- 中文场景首选jieba 分词(搜索引擎切分模式 + 用户词典),代码/短语场景选N-gram,英文场景用standard + 过滤器;
match_string做宽松召回,query_string做精确控制,再与向量检索混合,即可获得又准又全的搜索体验。
现在,打开 Python SDK,给你的下一个文本字段挂上FtsIndexParam吧——全文检索,一分钟就位 ✅
【免费下载链接】zvecA lightweight, lightning-fast, in-process vector database项目地址: https://gitcode.com/GitHub_Trending/zve/zvec
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考