检索——一次查询怎么找到那一页
如果你想知道,在你敲下 omem query "…" 和那串排好序的页面返回之间,中间到底发生了什么——以及为什么换到真实、杂乱、中英夹杂的办公数据上,搜索质量也照样靠得住——这一页讲清楚。
两个后端,一个接口
Section titled “两个后端,一个接口”omem query 跑在当前生效的那个索引后端上。命令本身从不变,变的是它背后那套运转的机制。
fts5(默认)——在 jieba 切出来的 token 上做 BM25 关键词搜索。一直在线、约 50ms、零配置。中文在这里是一等公民,不是顺带捎上的:要是不分词,FTS5 会把每个汉字当成一个 token,中英混排的文本搜起来精度基本归零。有了 jieba,中文跟英文才打成平手。qmd(可选插件)——多路检索:query expansion 加 BM25 加向量 embedding 加一个重排器,全在本地跑。当你要的是按意思来搜、还要跨语言,而不只是关键词对得上时,就该上它。
qmd 的多路召回是怎么回事
Section titled “qmd 的多路召回是怎么回事”qmd 能找到纯关键词搜索漏掉的页面,关键在于它不把宝押在一个信号上。它先把查询扩开,并排跑两条召回路——一条走关键词,一条走语义——再把两边的结果融到一块,最后重排。按 ▶ 让一次查询跑完这五步(或者点任意一步,挨个细看):
第一步,qmd 把你的问题"放宽"。
你打了三个词,但真正对的那个页面可能一个都没用到。所以 qmd 把你的 query 改写成几种说同一件事的相关表述——"Q3 budget review" 也能触及 "third-quarter financials" 和 "预算评审"。这样搜索找的是这个意思,而不仅仅是你打的那几个字。(更简单的默认索引 fts5 跳过这一步,只匹配你打出来的词。)
回报很实在:
- 跨语言搜索是真能用的。 一个英文查询,比如
"Q3 budget review",能把一页全用中文写的第三季度预算评审给捞出来——因为向量这条路匹配的是意思,不是 token。对那些天天泡在中英混排文档里的全球化团队来说,这就是搜索”能用”和”白搭”之间的差别。 - 专有名词的精度保住了。 关键词那条路照样能咬死确切的名字、代号、发票号——这些恰恰是单靠向量搜索时容易被”平均没了”的东西。
- 全程不出本地。 扩展、embedding、重排几个模型都在你机器上跑。除了摄入时那一道整理,检索这一路哪儿都不往外打电话。
质量是一道硬关,不是凭感觉
Section titled “质量是一道硬关,不是凭感觉”搜索质量是拿一个量得出来的标准卡死的,不是凭感觉拍脑袋。OMem 拿一组固定的 golden query(配着核对过的预期命中)做回归测试,打 precision@3 的分——一个 milestone 要是掉到阈值底下,就发不出去。两个后端都得过这一关:默认的关键词索引,和 qmd 那套多路栈,被同一把尺子量着。所以”搜索好用”是构建环节硬卡出来的结果,不是我们嘴上盼出来的。
分数是开头,不是结尾
Section titled “分数是开头,不是结尾”有一点值得你记着、带进怎么用这套东西里:不管哪个后端,它给你的那个分数,都只是把候选粗粗排个序,不是最终那句相关性的判决。它能找出看着相关的页面,但哪一页真答上了你的问题,它不知道。这个缺口,是 agent 来补的——它去读摘要、自己重排——而这正是 从 agent 查询 走过的那一步。
最后提一句跨后端的事:别拿 fts5 的 0.9 去比 qmd 的 0.9,两者算法不一样。只有同一次查询里的排名次序,才说明问题。