es向量搜索

**多数场景下,用“ES + 向量”会更稳**,尤其是同义改写、语序变化这类纯语义相似;但标题很短(≤8字)时,**仅向量容易误杀**,要搭配 BM25 一起用。最简单、效果好的做法是:**在你现有 ES 上加一个向量字段做 Hybrid(BM25+向量)**。 # 什么时候向量更好 * 同义/改写多:如“Kafka 广播机制原理?” vs “Kafka 主题广播怎么实现?” * 关键词差别大:同义换词、概念近义 * 你只看标题,不用标签/正文 # 什么时候别只用向量 * 标题很短(≤8字):语义不稳定,向量容易把不同题拉近 * 需要解释性强的匹配权重:BM25 分词+短语更可控 # 最小改造(基于 ES 的 Hybrid) 保留你现在的 `title` 字段,**只新增一个向量字段**,离线/入库时把标题做同一套预处理后生成 embedding 存进去。 ## 索引(ES 8.x 原生 HNSW,最小可用) ```json PUT question_idx { "mappings": { "properties": { "title": { "type": "text", "analyzer": "ik_smart" }, "title_vec": { "type": "dense_vector", "dims": 768, // 用你的向量维度 "index": true, "similarity": "cosine", "index_options": { "type": "hnsw", "m": 16, "ef_construction": 256 } } } } } ``` > 注:ES 7.10/7.15 没原生 ANN,只能 `script_score` 点积(慢)。若你有 ES 8 集群,直接上面这个。 ## 查询(Hybrid:BM25 召回 + 向量重排,保持简单) 1. 先做一次普通 BM25,拿 Top200 候选: ```json POST question_idx/_search { "size": 200, "_source": ["title"], "query": { "multi_match": { "query": "<raw_title>", "fields": ["title"] } } } ``` 2. 同时做一次向量 KNN(Top200): ```json POST question_idx/_search { "size": 200, "knn": { "field": "title_vec", "query_vector": [ /* 你的标题向量 */ ], "k": 200, "num_candidates": 1000 }, "_source": ["title"] } ``` 3. 在应用侧**合并去重**两路候选后打分融合(超简版): ``` final_score = 0.6 * cosine_sim + 0.4 * bm25_norm ``` * `cosine_sim`:ES knn 的 `_score` 本身就是相似度(取值看实现,通常可直接用/做Min-Max归一化) * `bm25_norm`:把 BM25 分数做 Min-Max 到 [0,1] ## 判重阈值(只标题) * 若标题长度 > 8 字: * `cosine_sim ≥ 0.88` → 直接判重 * `0.82 ≤ cosine_sim < 0.88` 且 BM25 Top1 → 判重 * 若标题长度 ≤ 8 字(短标题更严): * `cosine_sim ≥ 0.92` 且同时 BM25 Top3 → 判重 * 否则不判重(可把 Top5 返回人工二审) > 以上是保守默认值,跑你们历史样本100~200条后再微调一次就稳定了。 # 生成向量的注意点 * **线上查询与入库向量必须同一模型、同一预处理**(统一大小写、全半角、去括号尾注等) * 中文短文本用**中文专用 embedding**效果更好(维度 512/768/1024 均可,保持一致即可) * 入库时就写入 `title_vec`,避免查询时现算 # 如果你只想要“最简单可用”的版本 * 把上面的第 2 步(KNN)+ 第 3 步(融合)拿掉,先只用 BM25;不够再加 KNN * 或者只做 **KNN 一条查询**,判重阈值用 `cosine_sim ≥ 0.88/0.92(短标题)`,这是最少改造 # 小结 * **是的,向量会更好**(对语义改写鲁棒),但要与 BM25 互补,尤其短标题。 * 不需要上新向量库;**ES 8 自带 HNSW 就够**。 * 从“BM25 → Hybrid(再加一个向量字段)”的增量改造成本很低,先上再调阈值即可。 需要的话我可以: * 给你一段 Java/Python 的“标题→向量”小工具(同一清洗规则) * 帮你把现有索引脚本改成“BM25-only”与“Hybrid”两套可切换的版本(包含阈值配置)