1. 从“搜得到”到“搜得懂”:AI站内搜索到底在解决什么问题
先抛个问题:你的网站上线了搜索功能,日志里检索点击率却一路走低,用户搜“怎么退款”翻了三页都没找到售后入口,搜“会员多少钱”蹦出来的全是无关的商品介绍——这个场景熟悉吗?
传统站内搜索的核心逻辑是关键词匹配,你输入什么词,系统就拿着这个词去倒排索引里找包含它的文档。这种方案在内容量小、query意图单一的阶段没什么问题,但内容一旦多起来,词表不匹配、口语化表达、同义词替换、长尾需求这些问题立马暴露。用户想要的是“答案”,搜索引擎给的却是“包含关键词的页面列表”,中间的语义鸿沟靠用户自己脑补,体验自然崩。
通智云智能搜索这个项目,本质上是把大模型的能力引入站内检索链路,从“关键词命中”升级为“语义理解+知识召回+生成式回答”。它不是简单地拿一个Embedding模型做向量检索,而是以一个完整的RAG(检索增强生成)架构为底座,把Query理解、混合召回、重排、答案生成、引用溯源串成一条完整的流水线。它能解决的核心问题有三个:一是用户用自然语言提问也能精准找到内容;二是跨词表、跨表述的语义匹配不再依赖人工维护同义词库;三是搜索结果从“链接列表”变成“可读的答案”,配合引用标注,用户可以快速确认信息是否可靠。
这套方案适合谁?如果你的站点是电商、文档中心、知识库、在线教育平台、SaaS帮助中心这类重内容检索的场景,搜索体验直接影响业务转化或用户留存,那这套思路就有很强的参考价值。这篇文章会把我在实践中踩过的坑、调参经验、评测方法完整拆开讲,从架构选型到线上效果一把梭,你能直接照着落地。
2. 内容整体设计与思路拆解:为什么不能只做向量检索
2.1 混合召回架构:关键词匹配没有过时
很多团队一听说AI搜索,第一反应是把沉寂已久的Elasticsearch扔掉,上马一套纯向量数据库。这是一个非常危险的极端。
纯向量检索的问题在于:向量模型对专有名词、SKU编号、型号参数这类“精确信号”非常不敏感。比如用户搜“RTX 4090 24G”,在向量空间里它的邻居可能是“显卡”“GPU”“NVIDIA产品”,但如果索引里存在一条完全匹配“RTX 4090 24G”的商品参数页,关键词检索可以用BM25算法靠词频和逆文档频率把它顶到最前面,而向量检索反而可能因为语义宽泛而埋没它。
所以通智云的整体思路是“混合召回、两层融合”。第一层同时跑两条路:一条是用Elasticsearch或OpenSearch做BM25关键词召回,一条是用向量索引做语义召回,两条路各取Top N。第二层把两路结果送入重排模型(RRF合并或cross-encoder精排),再做最终排序输出。混合架构的收益是明确的:既有精确匹配的确定性,又有语义扩展的覆盖面,两者叠加才能应对真实用户那千奇百怪的query。
2.2 为什么选RAG而不是直接微调大模型
团队内部讨论时有过一个方案:把文档喂给模型做微调,让模型直接“背下来”,用户提问时直接生成答案。这个方案被否掉了,原因有三条,而且每条都是硬伤。
第一,站内内容更新频繁。电商的商品上下架、知识库的文档修订、帮助中心的版本更新,都是日级甚至小时级的变化。微调一次的成本从几小时到几十个小时不等,更新频率根本跟不上业务。RAG的思路是“检索时拿最新的索引内容作为上下文喂给模型”,文档更新只涉及增量索引,模型本身不用动。第二,微调会产生幻觉固化。模型会把训练材料里的错误信息或过期信息当作事实记忆下来,而且你很难定位它记错在哪。RAG模式下,模型生成的每个句子都可以对应到具体的检索片段,错误可以溯源到源文档。第三,RAG的冷启动成本低得多。一套RAG服务可以先接上现有ES索引跑起来,效果逐步优化;微调则要标注数据、训练试点、反复评测,周期长到业务方等不起。
2.3 核心流程总览:一条完整的搜索流水线
通智云的搜索链路可以拆成六个核心环节,每个环节都有独立的任务边界:
- Query预处理:对用户输入做拼写纠错、分词、口语化转书面化、意图分类。比如“你们这怎么退”会被改写为更规范的“退款流程”检索条件。
- 查询改写与扩展:基于大模型对原始query做同义改写、拆解多意图。比如“苹果手机和华为哪个拍照好”可以拆出“苹果手机 拍照评测”“华为 拍照评测”两个子查询。
- 混合召回:BM25精准匹配 + 向量语义召回,双通道取回候选文档集合。
- 重排精排:对候选文档基于相关性做精细化打分,把真正对应当前问题的内容提到最前面。
- 答案生成:把重排后的Top K文档片段拼装成上下文,交给大模型生成回答,要求每个关键句都标注引用来源。
- 兜底策略:无召回或低置信度时,触发“无答案引导”,给出推荐问题、热门内容或转人工入口。
这个链路不是拍脑袋定出来的。每个环节都在解决一个真实存在的失败模式:用户query太口语化导致召回失败、同词不同义导致排序错误、长文档切分不当导致上下文丢失、模型幻觉导致答案不可信。串起来之后,搜索体验的稳定性才有保障。
3. 核心细节解析与实操要点:数据接入与技术选型
3.1 文档解析与切分策略:最容易被低估的环节
做AI搜索第一个真正的坑在数据接入,而不是模型。站内内容往往是PDF、Word、HTML、Markdown混杂,表格、图片、代码块、页脚导航到处都是。你要是直接拿爬虫抓下来的网页文本去切块,切出来的片段里大概率塞满导航链接和版权声明,检索质量惨不忍睹。
我的建议是至少做三层处理。第一层是格式归一化,PDF和Word优先用成熟的解析服务转成结构化Markdown,而不是用简单的文本抽取库,否则表格会被打乱成一段乱序文本,之后不论检索还是问答都会出问题。第二层是正文提取,HTML页面要去掉导航、侧栏、页脚、广告等无关区块,保留真正的正文内容。第三层是切分策略,这里需要结合内容结构来切,不要无脑按固定字符数硬切。操作上可以按“标题层级优先”原则:先按文档结构拆成章节,再对超长章节做滑动窗口切分,同时保留片段之间的重叠上下文。文本片段过长,模型理解会稀释关键信息,过短又会丢失上下文关联,经验值在300到500字左右比较稳妥,具体可以根据业务内容适当调整。
3.2 Embedding模型与向量索引选型
Embedding模型是语义召回的核心组件。选型时不要盲目追新,先在公开评测集上横向对比,更要在你自己的业务语料上做小规模测试。原则很简单:领域术语多的业务,优先选在相似领域语料上有优势的模型;需要多语言搜索的站点,必须验证模型对每种语言的效果,很多模型中文表现优秀但英文泛化平平,反之亦然。
向量索引方面,开源方案里Milvus、Qdrant、Elasticsearch自带的向量插件都是可选方向。存量ES集群可以直接启用向量字段,减少一套新组件。数据量在百万级以内,HNSW索引足够;再往上要考虑量化压缩和分片策略。维度选择也要注意,常见是768或1024维,过高的维度在百万级数据下会显著放大内存占用,需要权衡。
3.3 重排模型:向量召回之后的守门员
混合召回通常能拉回几十条候选,但最终展示给用户或者喂给大模型的只有五到十条。从几十条到十条这步,是重排模型的活。
向量检索算的是“句子对”的语义相似度,速度快但精度不够。重排阶段我推荐用cross-encoder架构,它会把query和文档拼接成一句话再一起过Transformer,交互式建模相关性的精度比双塔式Embedding高一个档次。缺点是速度慢,所以一般只对召回阶段筛出的候选集做重排,控制在一百条以内,线上延迟才扛得住。
重排模型怎么来?两条路:一是用开源的通用排序模型直接跑,简单但效果上限中等;二是用你站内的搜索点击日志构造训练样本,比如“曝光未点击”作为负样本,“曝光且深度点击”作为正样本,微调一版领域排序模型,效果提升往往很明显。
3.4 大模型生成环节的要点
答案生成环节,大模型的核心工作不是“知道答案”,而是“读懂检索到的片段并用通顺的语言组织出来”。因此Prompt工程和参数控制直接决定答案质量。
Prompt里必须明确约束三件事:一是只基于提供的上下文片段回答,禁止编造上下文不存在的信息;二是每个关键事实引用对应的片段编号,规范格式类似[来源1][来源2];三是当上下文不足以回答问题时要直接承认不知道,而不是强行凑答案。温度参数建议调低,0.1到0.3之间,线性一致性比文采重要。同时把这个环节拆成“独立服务”,因为生成耗时远高于检索耗时,两者在日志里必须分开监控,才能定位延迟瓶颈。
提示:尽量选择支持流式输出的模型接口,先让用户看到部分答案在生成,整体感知延迟能大幅下降。我在联调时发现,流式输出下的用户满意度比完整等待高出很多,这是体验优化的一个隐藏杠杆。
4. 实操过程与核心环节实现:从索引构建到上线
4.1 环境准备和组件清单
先列一份我在实操中用的最小组件清单,方便你照着搭:
| 组件 | 用途 | 可选方案 |
|---|---|---|
| 文档解析服务 | PDF/Word转结构化文本 | 自建解析管道或商用解析API |
| Elasticsearch | 全文检索与向量存储 | OpenSearch、Milvus + ES组合 |
| Embedding服务 | 文本转向量 | 自部署开源Embedding模型或调用API |
| 重排服务 | 候选精排 | cross-encoder模型或Rerank API |
| 大模型服务 | 答案生成与Query改写 | 开源模型自部署或商业API |
| 编排层 | 串联整条搜索流水线 | FastAPI自建网关 |
上面这些组件在百万级文档规模下,两到四台16核64G左右的服务器可以跑起来。规模再小一些的话,ES和向量库可以共用实例,成本进一步压缩。
4.2 索引构建的完整流程
索引构建是搜索质量的根基。很多人上来就调模型,结果索引里全是垃圾片段,怎么调都没用。我建议按这个顺序走:
- 第一步:整理全量文档,清洗格式,做坏页过滤。
- 第二步:按文档结构切分,输出带元数据的片段。元数据至少包括doc_id、标题路径、章节层级、原文链接、更新时间。
- 第三步:对每个片段生成向量,连同原始文本一起写入索引。注意向量字段和文本字段要同时保留,做Evaluate时才能对比不同召回路径的效果。
- 第四步:增量通道接上,文档更新或删除时同步变更索引。删除操作很容易遗漏,建议在更新时按doc_id先删后写。
- 第五步:索引质量抽检。随机抽几百条片段人工看一遍,重点检查切分是否破坏了表格、代码块或专有名词。
这一步里最经典的坑是:切分代码更新后存量索引没有重建,老片段依然带着旧格式问题参与召回,而新数据看起来是好的,导致问题排查非常迷惑。只要是改变了切分逻辑,务必做一次全量重建。
4.3 双路召回的Pipeline实现
流水线部分我给你一个简化但可直接套用的Python示例,帮你建立代码层面的骨架认识:
def search(query, top_k=10, user_id=None): # 1. Query预处理与改写 normalized_query = query_normalize(query) rewritten_queries = llm_rewrite(normalized_query) # 返回多个改写候选 # 2. 双路召回 bm25_hits = es_search(normalized_query, size=50) vector_hits = vector_search(embed(normalized_query), size=50) # 3. 融合与去重 merged = merge_results(bm25_hits, vector_hits, method="rrf") # 4. 精排 reranked = rerank(normalized_query, merged[:100])[:top_k] # 5. 生成回答(这里单独调生成服务) answer = generate_answer(normalized_query, reranked) # 6. 记录日志 log_search(query, normalized_query, reranked, answer, user_id) return format_response(answer, reranked)实际生产里编排层要做的事远不止这些,还有缓存策略、超时控制、降级开关和监控埋点。尤其是超时控制,大模型接口偶尔会卡到几十秒,网关层必须给整条链路设好超时和降级路径,宁可回到纯关键词搜索,也不能让用户一直转圈。
4.4 混合排序的核心逻辑:RRF合并与策略调优
两路召回结果怎么合并,直接影响最终排序。我建议从RRF(Reciprocal Rank Fusion)开始,它是一种实现简单、效果稳的融合算法。它的核心思想是:对同一个文档,看看它在各个召回列表里的名次,取名次的倒数然后求和,名次越靠前贡献越大。这样做的好处是不用纠结两路打分尺度不一致的问题,BM25是几十分,向量相似度是零点几,直接相加毫无意义,但名次是可比的。
在RRF基础上,还可以根据业务场景叠加一些自定义加权。比如电商搜索里,销量高、库存足的商品可以小幅上提;知识库场景里,官方文档的权重可以高于社区内容。这些规则要在重排之前先做,不要与模型分数混在一起。生产环境里我习惯把RRF参数k调成60,融合效果比较平稳。
4.5 检索与问答的效果评测
上线前不做评测直接发布,是我见过最多团队犯的错误。AI搜索的评测不能只看“有没有召回”,要分层看。我设计了一套三层的评测指标,你可以参考:
第一层是检索质量,用召回率、准确率、MRR等指标,离线评测集上用标准标注过的query-文档对计算。第二层是回答质量,核心是人工打分,从“回答正确性”“信息完整性”“有无幻觉”“引用正确性”四个角度打分,每个维度四分档。第三层是业务指标,线上AB测试看用户搜索成功率、点击率、转化率、搜索后跳出率。
其中回答质量这一层最容易被忽视,但它恰恰是用户能直接感受到的部分。建议每周固定抽一批真实query做人工评测,形成趋势记录。模型升级、索引调整之后,拿同一批query回归一遍,避免“按下葫芦浮起瓢”。
5. 常见问题与排查技巧实录:从Case出发的排障手册
5.1 用户搜不到,但内容明明存在
这是AI搜索上线后最多的一类问题,背后往往有三个方向的原因。第一个是切分问题,目标内容被切坏在片段边界上,比如表格被拦腰截断,关键数字分家了,向量和关键词都匹配不到完整语义。排查方法是直接检索目标片段,定位它在索引里的存储形态。第二个是Query改写过度,原始query被改写模型改得面目全非,比如用户问“怎么开发票”,被改写成“如何开具发票的流程步骤文档”,反而丢失了原词。第三个是索引更新延迟,用户搜的是刚发布的内容,但增量管道还没跑完。排查这类问题,关键词是“对比双路结果”:把经过程序处理的query和原始query分别跑一遍检索,就能迅速判断问题是出在改写环节还是检索环节。
5.2 答案看似合理,但关键数据是错的
这是RAG系统里最危险的失败模式,因为答案像模像样,用户很容易直接采信。我遇到过一个典型case:用户问某商品保修期,模型生成的回答结构工整、语气肯定,引用的来源也是对的文章,但年份引文对不上,整段保修政策是拼接了前后两个版本的内容,出了幻觉。
针对这类问题,解药有两个。一是设计强制引用机制,在Prompt里要求模型对每个数字、日期、专有名词都必须标注对应的来源片段编号,输出格式里做结构化校验,若存在缺引用的句子直接拦截。二是对数字类事实做逻辑校验,如果回答中出现了具体的参数值,可以用正则从引用片段里抽取核对一遍,不一致就触发旁路再检索或者返回“信息不足”。这个环节不能只靠模型自觉。
5.3 效果波动:今天好明天差
很多团队上线后会发现,昨天同一个query效果还不错,今天突然变差了。排查方向先看数据侧:增量管道有没有混入脏数据、Index是否被错误重建、文档更新是否删掉了原本正确的版本。再看模型侧:Embedding模型或大模型服务是否被平台悄悄更新过版本,很多API服务的模型版本是按时间变的,版本差异会直接导致Embedding分布漂移。遇到这种情况,稳定做法是“固定模型版本”并定期做回归评测。
5.4 常见问题速查表
| 现象 | 可能原因 | 排查手段 |
|---|---|---|
| query有结果但点击率极低 | 重排质量差,相关文档排太靠后 | 看第一页排序,人工核对相关性 |
| 答案流畅但数据不对 | 模型幻觉,引用不严谨 | 校验引用编号与答案一致性 |
| 特定文档永远搜不到 | 切分破坏内容或增量同步遗漏 | 按doc_id查索引,抽看片段 |
| 搜索延迟突然变高 | 向量召回或重排环节慢查询 | 链路各环节耗时监控,定位瓶颈 |
| 新发布内容搜不到 | 增量管道延迟或失败 | 查同步任务日志,验证消息队列消费情况 |
| 同义改写后反而更差 | 改写模型过度改写 | 对比原始query与改写后召回结果 |
注意:搜索系统的线上问题基本都吃“日志记录不全”的亏。从第一天起就要给链路里每个环节都埋好日志,记录耗时和输出摘要。等到出了问题再补日志,就像事故后补现场监控,什么都晚了。
5.5 兜底体验:没有答案时的最佳路径
AI搜索再怎么优化,也必然存在模型覆盖不到的长尾问题。这时候兜底策略就成了体验的保底。我的建议是做三级兜底:第一级是“相关推荐”,拆解用户query中的核心词,召回站内的热门内容或常见问题。第二级是“引导改进”,提示用户换一种说法,或者通过一个追问澄清模糊意图。第三级是“人工承接”,提供在线客服入口或留言表单,让失去自助能力的用户最小成本转人工。
三级兜底的价值在于:即使AI没答上来,用户仍然感觉这个系统是“有反应”的。从日志看,设计过兜底策略的站点,搜索失败后的跳出率明显低于直接展示空结果的方案。
6. 一个比较务实的体会
踩过这么多坑之后,我最大的感受是:AI站内搜索的工程挑战远大于模型挑战。Embedding模型、大模型、向量库这些组件都是现成的,真正的差距在于数据管道的干净程度、评测体系的完善程度、线上观测的精细程度。很多团队把预算花在调模型上,索引里的片段却是一团乱麻,最后上线效果自然打折扣。建议你动手时先花一半精力把数据接入和评测这套地基打扎实,模型反而是后面水到渠成的事。
最后分享一个小技巧:在混合召回阶段,一定要把BM25和向量的结果分开存日志。遇到线上case去定位,一眼就能看出是精确匹配没出结果,还是语义召回没兜住,排查速度会快很多。这个习惯帮我省了无数个小时,推荐你从一开始就养成。