政策快报平台上线初期,搜索功能很简单:用户输入关键词,系统在标题和正文里做关键词匹配。
效果很差。搜"补贴"出不来"专项资金",搜"专精特新"出不来"小巨人"。
用户的搜索词是口语化的,政策文件是书面化的。两者之间有一道鸿沟。
后来我们做了一系列改造,从关键词检索到语义检索,再到混合检索。今天复盘这个过程。
3个阶段
阶段一:关键词检索(Elasticsearch)
方案:用Elasticsearch做全文检索,对标题和正文建倒排索引。查询时按TF-IDF/BM25相关性排序。
问题:词不匹配就搜不到。
用户搜"补贴",政策里写的是"专项资金"------匹配不上,出不来结果。
用户搜"小巨人",政策里写的是"专精特新"------同样匹配不上。
这个阶段,搜索点击率只有30%左右。用户经常搜不到想要的东西,然后流失。
优化尝试:加同义词词典------"补贴"映射到"专项资金、补助、后补助、奖励","专精特新"映射到"小巨人、隐形冠军、单项冠军"。效果有限,同义词覆盖不全,新词、生僻词无法及时补充。
阶段二:语义检索(向量检索)
方案:引入向量检索。用Sentence-BERT将用户查询和政策文本分别编码为向量,计算余弦相似度,按相似度排序。
效果:语义匹配。搜"补贴"能出"专项资金",搜"小巨人"能出"专精特新"。
搜索点击率从30%涨到了50%左右。
新问题:向量检索吃资源。每次查询需要实时计算向量相似度,CPU消耗高;索引构建时间长,新政策入库后无法立即被搜到;语义检索有时过于"发散",搜"专精特新认定"会匹配到一些相关性不高的政策。
阶段三:混合检索(ES + 向量检索)
方案:BM25 + 向量检索,两种得分加权融合。精确匹配(发文字号、政策名称)走ES,语义匹配走向量检索,两者按权重合并排序。
效果:既保证了精确匹配(搜"国发〔2026〕1号"能精确命中),又保证了语义泛化(搜"补贴"能出"专项资金")。
搜索点击率从50%涨到了60%左右。
几个关键的技术决策
决策一:为什么不用单一向量检索?
向量检索擅长语义泛化,但不擅长精确匹配。用户搜"国发〔2026〕1号"这种精确的发文字号时,向量检索的泛化能力反而成了干扰。
混合检索取两者之长:精确匹配走ES,语义匹配走向量。
决策二:同义词词典还要不要?
要,但角色变了。
之前同义词词典是"主力",现在是"辅助"。向量检索能解决大部分语义泛化问题,同义词词典只作为"兜底",覆盖向量模型训练数据中没有覆盖到的特殊词汇(如最新政策术语)。
决策三:向量模型的选择
我们试用过OpenAI的embedding接口,准确率高但延迟大,每次查询都要调用外部API,响应时间不稳定。最终选择了开源的Sentence-BERT多语言模型,在政策领域数据上做了微调。
结尾
搜索的核心价值:让用户"能找到自己想找的东西"。关键词→语义→混合,每一次演进都在缩小用户表达和文件表达之间的差距。
政策快报平台的搜索系统还在持续优化,方向是让用户用最自然的方式表达需求,系统能理解并返回最匹配的政策。
技术选型有取舍,平衡了准确性、召回率、响应时间和成本。目前ES做精确匹配兜底,向量做语义泛化覆盖,两者结合覆盖了绝大多数搜索场景。