做 LLM 应用的人,大概都经历过这样一个阶段:给模型配上搜索引擎,却发现答案总是差一口气。第一反应往往是换引擎——商业 API 换一家,或者干脆自建一个聚合搜索,调完接口继续试,质量好像提升了一点,又好像没有本质变化。
直到我认真看了一项关于 LLM 联网搜索的基准测试,才意识到问题可能从一开始就找错了方向。这项测试的标题本身就非常直白:在 LLM 联网搜索中,更多次搜索,胜过更好的搜索引擎。换句话说,同样一个模型,对一个查询多搜几轮、多取几块信息,效果往往比把底层引擎从“一般”换成“更好”还要明显。
这个判断乍看反直觉,因为它挑战了“工具越强结果越强”的直觉。但放到 LLM 的工作方式里,它其实一点都不意外。这篇文章想把背后的机制、落地方法和适用边界一次讲清楚,也顺便聊聊为什么很多团队在这件事上花了冤枉钱。
1. 先理解:基准测试里比的不是“搜索质量”,而是“组合效果”
1.1 测试到底在控制什么变量
一项把搜索能力接入 LLM 的基准测试,测的往往不是“搜索引擎本身好不好”,而是“模型 + 搜索”这个组合最终能不能答对问题。所以设计上一般会尽量控制住模型、提示词、结果处理方式这些变量,只让两件事发生变化:
- 底层搜索引擎是谁,返回的结果质量如何;
- 模型在回答之前允许执行几次搜索,以及每轮搜索之间是否有信息补充。
当这两组对照同时存在时,标题给出的结论才有意义:搜索次数对最终答案的影响,大于搜索引擎本身的差异。
这里有一个容易误读的地方。不是说所有搜索引擎都一样,也不是说换引擎完全没用。而是说,在“模型 + 搜索”这个组合里,检索只是整个链路的一段。排序精度的差异,在经过“取回 -> 截断 -> 拼接 -> 生成”之后,会被明显稀释。而搜索次数直接影响的,是模型拿到的信息覆盖面。覆盖面才是决定答案能不能“拼出来”的关键,而不只是“搜得准不准”。
1.2 为什么“更好的引擎”没有带来碾压优势
搜索引擎是为人类设计的,不是为模型设计的。人的阅读习惯是看排名靠前的链接,点进页面自己判断;而 LLM 联网搜索通常只拿摘要片段,然后把多个片段拼合成答案。这意味着:
- 人类眼里“排在最前面很重要”,但模型拼答案时,更需要的是不同来源、不同角度、不同时间点的片段组合;
- 主流搜索引擎在处理常见问题时精度差异很小,真正的差距体现在长尾信息上;
- 长尾信息往往不在前三名里,如果只取 top-k 个摘要,再好的长尾内容也进不了上下文。
所以,把引擎从 A 换成 B,改善的往往是检索精度的“上半场”。而 LLM 回答问题更像是在打“下半场”:已经拿到一批材料之后,能不能找到缺口、补齐证据、完成推理。这个下半场,主要由搜索轮次和查询策略决定。
从工程经验看,这个判断对多数团队都是好消息。因为换引擎往往要改 API、改解析、改计费逻辑,成本不低;而增加搜索轮次,通常只是改一个循环参数和查询生成逻辑。同样是提升效果,后者的改动面小得多。
2. 单次搜索为什么总是不够:信息是拼出来的,不是搜出来的
2.1 一个查询,只有一种措辞,一次机会
搜索的起点是一个查询字符串。模型用“什么原因导致某问题发生”去搜,搜索引擎就会按这个措辞理解意图。但同一个问题,换一个角度提问,返回的结果可能完全不同。复杂问答很少只依赖一个页面就能完整回答,它往往需要:
- 不同来源的不同说法相互印证;
- 不同时间点的信息做时效对比;
- 不同子问题分别检索,再合并推理。
单次搜索,等于只给了模型一扇窗。窗口里有什么,答案就局限在什么范围里。这也解释了一个常见困惑:为什么模型明明能联网,遇到稍微复杂一点的问题,还是答得像在猜。不是模型不行,是它只被允许看了一页资料。
2.2 多轮搜索的本质:让模型像人一样去“查资料”
人在做一份调研时,不会只搜一次就下结论。第一轮搜索往往是建立底图;中间发现某个数字来源不可信,会再搜一条验证;某个专有名词不认识,会再补一次定义查询;写完初稿,还可能要回头确认最新数据。
模型的多次搜索,做的其实是同样的事。只不过它需要自己判断“我还缺什么”,然后生成下一轮查询。这恰恰是“搜索次数”能成为比“引擎质量”更稳定的预测因子的原因:只要模型具备基本的查询改写能力,多搜几轮就能稳定地扩大信息覆盖;而引擎升级带来的边际收益,会随着排序精度已经较高而迅速递减。
换句话说,更多搜索是在提升模型“看到更多世界”的概率,换引擎只是让模型“把同一扇窗户擦得更干净”。
2.3 多搜不是重复搜:查询多样性才是关键
这里要划一个重点。如果每一轮搜索都用同一个查询,只是把结果页数增加,那么多搜的优势会大打折扣。真正有效的“多搜”,是让每轮查询之间产生差异:
- 把原问题拆成子问题,例如“这个方案的适用场景”和“这个方案的局限”分开搜;
- 更换表述,从“如何做 A”换成“A 的常见坑”;
- 加限定条件,例如时间范围、站点来源、文件类型;
- 针对缺失信息做反问,上一轮没提到成本,下一轮就专门搜成本。
基准测试把“更多搜索”和“更好引擎”放在一起比较,本质上是在比较两种投资方向:投资在检索精度上,还是投资在探索广度上。至少在 LLM 问答这个场景里,后者的回报更明显。
注意:如果发现日志里每一轮查询几乎一样,那不是“多搜”,是“重复搜”。多轮搜索的收益来自查询多样性,而不是提交次数。
3. 真正值得优化的,是把“搜索次数”变成“搜索策略”
3.1 一个可复用的三层检索框架
把“多搜几次”工程化,不能只是简单地把搜索函数多调用几次。直接把一个查询循环提交 5 遍,浪费预算,效果还不如单次搜索。我自己在项目里一般会用一个三层框架:
第一层:基线检索。直接用原始问题去搜,取回 3 到 5 个权威结果,作为整轮回答的事实底座。
第二层:子问题补检。让模型先拆解问题,列出 2 到 4 个必须回答的子问题,逐个独立检索。这一层负责把覆盖面打开。
第三层:求证与补缺。把前两轮的结果合并,让模型判断:哪些关键信息缺失,哪些来源相互冲突。对缺失信息做定向补搜,对冲突信息增加一次“求证搜索”。
最后收口时,把三轮结果按来源权重和时效性合并去重,再交给生成环节。这个框架的价值,不是让模型每次都搜满 8 轮,而是让每一轮搜索都有明确动机。
| 搜索层 | 查询来源 | 主要作用 | 典型轮次 |
|---|---|---|---|
| 基线检索 | 原始问题 | 建立事实底座 | 1 |
| 子问题补检 | 模型拆解出的子问题 | 扩大信息覆盖面 | 2-4 |
| 求证与补缺 | 缺失信息 / 冲突信息 | 提升可信度 | 1-3 |
3.2 框架、平台和工具链能帮你做哪些事
现在很多 RAG 增强方案和 LLM 工具调用机制,已经在支持这种多轮搜索。至少有三种落地方式:
- 让模型自己调用搜索工具:通过 function calling / tool use,模型每一轮都能决定搜什么、什么时候停。这种方式最灵活,但对模型的自主性要求高。
- 用工作流平台编排:像 Dify 这类平台可以在节点里配置多次搜索、条件分支和结果合并,适合不想写太多代码的团队。
- 自己在应用层写循环:把“查询生成 -> 搜索 -> 结果合并 -> 判断是否继续”做成循环体。这种方式可定制性最高,也是下一节最小流程的基础。
选择哪种方式,取决于你的模型对工具调用的支持程度,以及你是否需要在中间环节插入人工判断。如果在某个 provider 上遇到工具调用 schema 被拒,报错信息里出现类似 provider rejected the request schema or tool payload 的内容,多半是模型版本不支持某个参数,或者返回格式不匹配。这属于工具链层的兼容问题,不一定要靠改搜索策略解决。
3.3 成本和质量不是对立的,是分级管理的
多搜几次确实会带来 API 成本和延迟上升。但如果因此放弃多轮搜索,等于把质量上限锁死在单次检索的覆盖面上。更务实的做法,是按问题复杂度分级:
- 简单事实问题:1 次搜索,直接回答;
- 常规问答:2 到 3 次搜索,基线加一次子问题补检;
- 调研型问题:4 到 6 次搜索,完整走三层框架;
- 争议性问题或深度报告:8 次以上,并且在求证环节多加权重。
判断一个查询属于哪一级,可以在前端用另一个轻量模型做路由,也可以用规则做关键词匹配。先分级,再分配搜索预算,成本就不会失控。
4. 落地一个“多搜几次”的最小流程
4.1 前置条件与最小实现
实现这个流程,需要四样东西:
- 一个支持工具调用或函数调用的 LLM;
- 一个搜索 API 或自建搜索引擎接口;
- 一个结果缓存,避免不同会话对同一查询重复计费;
- 一个能把多轮搜索结果合并去重的处理函数。
最小流程的代码结构大致长这样。注意这只是一个常见的实现骨架,具体函数名和参数要以你使用的 SDK 为准,不要直接照抄。
# 示例结构:多轮搜索的最小循环 def answer_with_multi_search(question, max_rounds=3): merged_results = {} query_list = [question] # 第一轮:原始问题 for round_idx in range(max_rounds): new_results = [] for query in query_list: hits = search_api(query, top_k=5) new_results.extend(hits) merge_dedup(merged_results, new_results) # 按 URL/标题去重 # 判断是否还需要下一轮 evidence = format_for_prompt(merged_results) need_more, next_queries = llm_decide(evidence, question) if not need_more: break query_list = next_queries # 通常是拆解后的子问题或补缺查询 # 收口:合并 -> 裁剪 -> 生成 context = truncate(format_for_prompt(merged_results), max_chars=8000) return llm_generate(question, context)这个结构有三个关键点。第一,每一轮的查询列表都必须来自上一轮的信息缺口,而不是把同一个查询重复提交。第二,结果合并一定要做去重和截断,不然第 5 轮之后,上下文里会出现大量重复段落。第三,循环必须设置最大轮次,防止模型在某个问题上无限搜索下去。
4.2 参数理解:先别急着把值拉满
几个容易踩坑的参数,逐个说一下:
- top_k:每一轮每个查询取几条结果。我一般取 3 到 5 条。取太多,摘要片段互相重复,还挤占上下文;取太少,覆盖面不够。
- 每轮总结果数:和 top_k 配合使用。理想状态是“每轮都有新信息”,而不是“每轮都堆满”。
- max_rounds:最大搜索轮次。默认给 3 轮,足够做基线加子问题加一次补缺。调研型任务再调高,但一般不建议超过 8。
- 上下文裁剪:合并后给生成模型的上下文长度。长上下文模型能装更多,但不要指望模型依赖几万字背景去回答一个 50 字的问题,注意力会被稀释。
- 缓存:用查询语句做 key,加时间戳失效。同一问题被反复问时,能省掉大量重复计费。
这里有一个通用经验:单次跑通,只能说明流程没有断;真正麻烦的是批量任务、异常重试和长期维护。所以不要一上来就把批量数拉满,先用一条样例确认输入、输出和日志都正常,再逐步加量。
4.3 从单条到批量的推进路径
建议按三步走:
- 单条样例验证:用 5 到 10 条不同难度的问题跑一遍,重点看查询是否多样化、结果是否去重、答案是否引用了新增信息。
- 小批量稳定性测试:跑 50 到 100 条,统计平均搜索轮次、平均耗时、缓存命中率、失败率。这一阶段最容易暴露 provider 的限流和超时问题。
- 批量与生产化:加日志、加失败重试、加熔断、加评估集。每次改动搜索策略后,都要用同一批评估题跑回归,不然你无法判断是策略变好了,还是运气变好了。
5. 多搜了但没变好?按这个顺序排查
5.1 先把现象分清楚
遇到“多搜了但效果没提升”时,先别急着改参数,按现象定位:
| 现象 | 优先排查方向 |
|---|---|
| 答案几乎没变化 | 查询是否在重复同一个角度;缓存是否命中了同一批结果 |
| 答案越来越乱、越来越糊 | 上下文塞入太多重复或无关片段;合并去重失效 |
| 搜索结果明明有,模型却说找不到 | 截断策略太激进,关键片段被切掉 |
| 调用报错,提示 provider rejected tool payload 之类 | 工具调用 schema 与模型版本不匹配 |
| 整体超时,或提示 request timed out | 搜索轮次串行太多,耗时叠加;需要并发和超时控制 |
5.2 推荐的排查链路
按下面的顺序查,不要跳步:
- 先看日志:把每一轮的查询、返回条数、摘要前 200 字都打出来。这一步能直接判断是不是“重复搜索”。
- 再看输入:多轮结果是否正确合并、去重、截断;时间戳和来源信息有没有保留;URL 是否完整。
- 再看环境:模型版本是否支持工具调用;provider 对搜索工具的 schema 要求是什么;API key 权限是否够用。
- 再看参数:top_k、每轮结果数、max_rounds 是否合理;缓存 key 是否把同一问题误判成不同问题。
- 最后回到策略:如果前四步都正常,那就是查询改写策略的问题。试着把问题拆得更细,或在补缺环节加入“明确指出缺失信息”的要求。
排查过程中,数据是唯一的裁判。你不需要靠感觉判断“多搜到底有没有用”,把一轮搜索和五轮搜索各跑 20 条评估题,对比答案正确率和引用一致性,结论会非常明显。
6. 这个结论不是万能药:边界和反例同样重要
6.1 什么时候多搜是浪费
并不是所有场景都适合多轮搜索。下面几种情况,“多搜”带来的收益很低,甚至可能变差:
- 简单实体查询:例如“某产品发布时间是哪一年”,一次搜索精确命中,多搜只是增加延迟和成本。
- 强实时低延迟场景:客服机器人需要在几百毫秒内回复,多轮搜索会让用户等待明显变长。
- 上下文非常有限的场景:如果生成阶段的上下文窗口只有 4K,塞下三轮搜索结果后,模型已经没有足够空间做推理。
在这些场景里,正确做法不是多搜,而是用路由把简单问题引到单次搜索,只让复杂问题走多轮流程。
6.2 多来源也会带来新风险
信息覆盖面扩大之后,新问题出现了:来源之间可能互相冲突。这时候模型需要判断谁更可信,而不是简单地把所有信息平均一下。我在实践里的做法是:
- 保留每个结果的来源、时间和类型,例如官网、第三方、论坛;
- 在提示词里要求模型优先采用官方或一手数据,并明确说明冲突点;
- 对关键数字做二次求证,未验证的数字在答案里标注不确定性。
换句话说,多轮搜索提升的是“资料收集能力”,但“资料判断能力”仍然要靠提示词、评估集和人工抽检来兜底。不要指望多搜几轮之后,模型就不会被错误网页带偏。
6.3 这个经验真正适合谁
适合的人群和场景:正在做 RAG 增强问答、Agent 搜索、研究型内容生成的团队;已经接入搜索 API 但对效果不满意的个人开发者;想在 LLM 应用里把检索、验证、生成串成一条可持续优化链路的架构师。
不太适合的场景:简单 FAQ、纯知识库内部检索、对成本极端敏感且问题普遍简单的应用,以及没有日志和评估体系的实验性项目。因为在后一类项目里,你根本看不出多搜到底有没有带来提升,所谓优化只是在碰运气。
最后的经验:先让模型学会“需要时才搜”
回到最初那个判断。很多团队纠结于“哪个搜索引擎更好”,其实是把问题想小了。对 LLM 应用来说,检索不是终点,它是推理的输入。同样一个模型,拥有 5 次有策略的搜索机会,通常比拥有 1 次更完美的搜索结果表现更好。这个结论的意义,不只是让你去调大 max_rounds,而是提醒你:真正值得投入的地方,是让模型学会判断“我还缺什么、下一步该搜什么”,然后把搜索从一次性功能,变成一种可持续优化的能力。
如果你现在正在做 LLM 联网搜索,我的建议是:先别急着换搜索引擎。把你现有的搜索 API 留用,先在同一个引擎上跑一组“1 次搜索 vs 3 次搜索 vs 5 次搜索”的对比评估。用 20 到 30 条真实问题,记录答案正确率和引用一致性。绝大多数情况下,你会亲眼看到,搜索次数的差异比引擎选择的差异更明显。等到多轮策略稳定了,再回去考虑是否值得为更好的引擎增加预算。