☰
从搜索框到Agent:Chatbot联网搜索的演进与技术实践
2026/10/8 10:59:07 网站建设 项目流程

先问一个问题:你上一次真正在 Chatbot 的联网搜索里找到“答案的质感”,是什么时候?我记忆里的分水岭是 2023 年前后——那时候整个圈子都在吵同一个话题:Chatbot 到底该不该联网。支持的人说,不联网你就是个会背课本的复读机;反对的人说,联网之后幻觉更难管,引用来源满天飞。这两种观点都没有错,但两年过去,讨论的语境早就换了。现在的问题是:不是“要不要联网”,而是“怎么让 Agent 在联网时聪明地活着”。

这个变化背后是一条清晰的技术演进路线——从“搜索框”到“Agent”。如果你用过早期版本的 ChatGPT 联网插件,或者研究过各类 Web Search API 接入,你会发现它们大多还停留在“搜索框时代”:用户问一句,系统把这句话转成关键词丢给搜索引擎,搜索引擎返回十条结果,模型基于这十条结果再写一段回答。本质上是一条线性流水线。而 Agent 时代的联网搜索,是把搜索变成模型自主决策的“感知器官”,让模型自己判断什么时候搜、搜什么、怎么用搜到的内容。这篇文章就围绕这条演进线,把历史逻辑、技术实现、框架选型、安全边界和踩坑经验一次讲清楚。无论你是想给自己的聊天机器人接入联网能力,还是正在从 RAG 往 Agent 方向过渡,这篇文章都值得认真读一遍。

1. 搜索框时代的 Chatbot:先搞清楚我们在告别什么

1.1 从 RAG 到“关键词复制粘贴”的产品原型

我最早接触联网搜索类产品,还是在做知识库问答的时候。当时的方案特别朴素:用户问一个问题,程序拿 LLM 或者规则从问题里抽取关键词,调用搜索 API,取回 Top 10 结果,把这些网页摘要一股脑塞进 prompt,再让模型生成答案。这套流程在后来被叫成 RAG(检索增强生成),到今天还有大量生产环境在跑,本身并不丢人。

但它本质上有一个无法回避的局限:它是单程的。用户输入一次、检索一次、生成一次,流程就结束了。模型没有第二次机会去确认“我搜到的内容对不对”,也没有能力发现“搜索结果已经过期”。举一个很典型的场景:用户问“帮我查一下某公司最近三个月发布的 AI 产品”,搜索框模式会把“某公司 AI 产品、最近三个月”一起发给搜索引擎。搜索引擎对“最近三个月”这个时间限定处理得很弱,它更擅长匹配“AI 产品发布”这个主题,于是返回的第一页可能有一半是三年前的旧闻。模型拿到这些内容后,并不会因为“时间对不上”就拒绝回答,它会硬着头皮把旧闻组织成一份看起来没什么毛病的答案。这个问题在当时几乎无解,因为整套架构里根本没有“验证”这个环节。

刚接触这类项目的人,往往会掉进另一个坑:习惯性把搜索 API 的返回结果全量塞进上下文。搜索 API 一页返回二三十条,每条摘要加上标题、链接、发布时间又有两三百字,一次搜索就能吃掉六七千 token。如果问题稍微复杂一点,需要两次搜索,上下文就快爆了。这也是搜索框时代产品体验普遍不好的直接原因——不是模型不够聪明,而是喂给模型的“原材料”质量太差、缺少结构。

1.2 搜索框模式的四个硬伤,也是 Agent 的出发点

我后来复盘过很多“搜索框模式”的产品,发现它们主要死在四个地方。这四个硬伤,其实正是 Agent 架构要解决的问题。

第一个是缺乏任务拆解。用户的问题常常不是一个搜索能覆盖的。比如“对比一下 A 和 B 两款开源框架的社区活跃度”,理想做法是先分别搜索 A 的社区情况,再搜索 B 的社区情况,甚至还要搜一下技术论坛里对两者的讨论。搜索框模式只会执行一次关键词检索,它没有“计划”的概念。

第二个是缺乏主动追问。真人搜索时,遇到模糊需求会先问你“预算多少”“在哪个城市”“芯片平台是什么”。基于流水线的 Chatbot 不会问,它默认它猜中了你的意图,然后把猜测结果作为事实输出。这是大量“答非所问”的根源。

第三个是缺乏结果判断。搜索引返回的内容本来就包含广告、软文、过时内容、错误信息,搜索框模式把这些一视同仁地交给生成模型。生成模型没有“这个网站可信度不高”的概念,它只知道把上下文里的内容整合起来。

第四个是不能自我修正。搜索框模式下,如果第一次搜到的结果不理想,整个回答就已经注定了。Agent 则可以在生成过程中发现“信息不足”,主动发起第二轮搜索,甚至第三轮。这种“发现问题再解决”的能力,是体验质感最大的来源。

这四个问题放在一起,本质上是同一个缺陷:搜索在架构中的角色太被动。搜索框时代的搜索是“被调用的工具”,Agent 时代的搜索是“感知外界环境的器官”。从被动到主动,从一次到多次,从线性到循环,这才是真正意义上的演进。

2. Agent 重新定义了联网搜索在系统中的位置

2.1 Agent 不是一个会聊天的程序,而是一个会做决策的程序

聊到 Agent,很多人第一反应是“Agent 是不是就是更聪明的 Chatbot”。我建议换个思路理解:Chatbot 解决的是“如何回答好一个问题”,Agent 解决的是“如何完成一个目标”。前者的核心动作是生成,后者的核心动作是决策。这个区别非常重要,因为它决定了系统的架构形态。

Agent 的工作方式可以缩成一个循环:目标-行动-观察-再行动。模型拿到用户目标后,不急着生成最终答案,而是先想“要完成这个目标,我需要哪些信息”。缺信息就触发一个行动,比如调用搜索工具、打开网页、执行一段代码。然后观察行动的结果,判断信息是否足够。不够就继续行动,够了才进入最后一步——生成答案。

生活化的类比是:你在手机上找中介租房子。传统 Chatbot 像自动答复机,你输入“找一套近地铁的两居室”,它马上吐给你十个房源链接。Agent 更像一个真实的中介——它先问你的预算、通勤上限、是否接受合租,然后自己去房源平台搜一轮,点开几套户型的详情页,比对价格和照片,最后给你推荐两套并解释理由。整个过程里,“搜索”只是其中一个动作,而不是全部。

我在实际操作中的体会是,很多人做 Agent 项目最大的障碍不是模型能力不够,而是思维没切换过来。他们还是把 Agent 当成“带工具的 Chatbot”,想问一句答一句。结果模型偶尔调用一次工具,感觉就像“多点了一个搜索按钮”,完全没有体现出 Agent 的价值。真正的 Agent,应该在一次任务里自己决定搜索三次、读五个网页、再横向对比,最后给结论。

2.2 搜索不起“返回结果集”的作用了,它开始提供“环境反馈”

当搜索被放进 Agent 循环之后,你会发现搜索 API 的评价标准完全变了。搜索框时代,我们关心的是“返回结果准不准、全不全”。Agent 时代,我们要关心的是“返回结果能不能被模型稳定地理解和利用”。

这也是为什么现在很多面向大模型应用的搜索开放平台,首页都在强调“web search(联网搜索)能力”的接口规范。它们追求的早就不只是“搜索工程师看得懂”,而是“模型调用起来顺手”。具体来说,至少包含几件事:返回结果是结构化 JSON,字段之间没有歧义;摘要部分做了截断和去重,避免内容重叠消耗 token;自带引用索引,方便 Agent 在回答时标注来源;支持时间过滤和地域过滤,方便 Agent 做更精细的信息筛选。

我以前把 Google Search API、Bing Web Search API 都接进过 Agent 项目,最后都会遇到同一个问题:这些通用搜索引擎的接口,字段设计面向的是“人看搜索结果页”的场景,而不是“模型读取环境信息”的场景。通用搜索返回的很多字段,比如广告位标识、复杂的分页结构,对模型来说是噪音。后来换了面向 LLM 优化的搜索 API,比如 Tavily、博查、Brave Search 的 AI 接口,明显能感觉到模型做决策的准确率上升了。它们会把“干净的网页正文摘要”“发布时间”“来源域名”这些最核心的信号优先暴露给模型,减少模型自己在噪音里找重点的负担。

连本地模型工具 LM Studio 这种主打“本地部署”的产品,现在也加了“对话开启联网搜索”的开关。但这个开关对应的还只是搜索框模式:开启后模型在回答前先去搜索引擎拿一批结果,再生成。真正值得关注的,是更高层的 Agent 平台开始把“web search”做成一个标准 skill,让模型在推理循环中可以随时调用。同样是联网,搜索框模式是“查完一次再回答”,Agent 模式是“边查边想,不够再查”,两者在体验上根本不是一个量级的东西。

3. 从零搭一个会联网搜索的 Agent:选型与实现

3.1 搜索 API 怎么选:免费额度、结构化程度、时间过滤是关键

到这一步,我们开始聊实操。首先解决第一个问题:Agent 用的搜索 API 到底选哪个。

选型标准有三个优先级。第一是接口返回结构是否干净,是否直接面向 LLM 设计。第二是是否支持时间过滤,因为 Agent 的很多查询天然带“最新”“最近”这类时间意图。第三才是价格和免费额度。

如果把免费的选项列一下,市面上有几类可以参考:

API免费额度面向 Agent 的程度备注
Bing Web Search API有试用额度,按量计费中等通用搜索引擎接口,字段多,需自行清洗
Brave Search API提供免费额度中等偏高隐私导向,接口干净,部分功能收费
Tavily Search API提供免费额度极高专门为 LLM/Agent 设计,支持自定义搜索深度
博查(Bocha)API有免费额度高国内可用,面向 AI 场景做了优化
SerpAPI有试用额度中等主打聚合搜索引擎结果,字段丰富但偏重

如果你只是自己做一个实验项目,我建议优先挑面向 Agent 的,别在这事上省。面向喷模型设计的搜索 API,返回结果本身就带摘要、来源、发布时间这些关键字段,省掉你自己做后处理的一大段代码。等到项目规模上来了,需要更细粒度的语种过滤、站内搜索、去重规则时,再考虑在网关层做多路搜索的聚合。

另外一个容易忽略的点是:搜索 API 的返回结果要不要缓存。Agent 在一次对话中可能会反复搜索相似的关键词,如果不做缓存,同一份搜索结果可能被搜三次,费用和延迟都是三倍。我在项目里会用一个简单的 Redis 缓存,key 是规范化后的查询词加上时间窗口,TTL 设 30 分钟,效果非常明显。这是低成本高收益的优化。

3.2 用 Function Calling 让模型获得“自动搜索”的能力

选好搜索 API 之后,下一步是打通模型调用工具的链路。现在主流的大模型都支持 Function Calling 或 Tool Use,简单说就是:模型在生成回复时,可以输出一个“我想调用某个函数”的结构化指令,而不是直接输出文本。程序拿到这个指令后执行对应的函数,再把函数结果作为新的上下文消息返回给模型,模型继续决策。

下面这段代码是我常用的一种极简实现,核心是一个 while 循环:

import json from openai import OpenAI client = OpenAI() tools = [ { "type": "function", "function": { "name": "web_search", "description": "在互联网上搜索最新信息,返回结构化摘要和来源", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "用于搜索的关键词,尽量具体并带上时间限定" } }, "required": ["query"] } } } ] def web_search(query: str): # 替换成你选用的搜索 API 客户端 results = search_client.search(query) return results messages = [{ "role": "user", "content": "帮我查一下某热门开源 Agent 框架最近一个月发布的更新" }] # Agent 的核心:循环直到模型不再请求调用工具 for step in range(5): response = client.chat.completions.create( model="gpt-4o", messages=messages, tools=tools, tool_choice="auto", ) msg = response.choices[0].message messages.append(msg) if not msg.tool_calls: print(msg.content) break for call in msg.tool_calls: args = json.loads(call.function.arguments) result = web_search(args["query"]) messages.append({ "role": "tool", "tool_call_id": call.id, "content": json.dumps(result, ensure_ascii=False) })

如果只挑一段最值得反复看的代码,就是那个for step in range(5)循环。这是 Agent 与搜索框模式的架构分界线。搜索框模式是“问一句、搜一次、结束”,这里则给模型留出了最多五轮“思考-行动-观察”的机会。模型可以第一轮先搜框架的名字,发现信息不够,第二轮再搜具体的发布仓库,第三轮甚至在总结时觉得数据存疑,再补一次搜索。这些能力完全来自循环结构本身,不需要额外写任何逻辑。

新手最容易被忽略的细节有两个。第一个是把tool_choice设置为"auto",让它由模型自己判断是否调用工具。万一你不小心设成了某固定工具,模型会在不需要搜索的时候也必须搜索,结果就是每一个回答都带着一堆无用的搜索过程。第二个是要注意循环次数的上限。没有上限,模型可能在复杂任务里无限搜索下去,token 和费用都受不了。我在生产环境里通常设 5 到 8 步,超过上限就直接让模型基于现有信息回答,并在答复里注明“信息可能不完整”。

3.3 搜索行为调优:不止是让模型“会搜”,还要让它“会停”

打通调用链路只完成了一半工作。更花时间的,是让模型知道什么时候需要搜索、搜完怎么用结果。这部分主要靠 system prompt 和工具 description 一起约束。

我给很多 Agent 项目写过搜索相关的系统提示词,沉淀下来三条核心规则。第一条:不要对常识类问题搜索。模型自己确定知道答案的问题,直接回答,搜索反而引入噪音。第二条:搜索结果与生成答案之间要有“引用对齐”。要求模型在输出时标注“根据哪些来源得出这个结论”,没有来源支撑的内容不写。第三条:如果搜索结果与已有知识冲突,以搜索结果为准,但要显式说明“这个信息来自最新搜索”。这三条规则看起来简单,实际对模型行为的影响非常大。

还有一个很实用的经验:把搜索工具的 description 写细一点,尤其是“关键词怎么写更好”。我通常会在 description 里提醒模型“query 中应该包含实体全名、年代或时间范围、目标领域等限定信息,减少歧义”。原因是模型直接拿用户原话当搜索词的行为非常普遍。比如用户问“帮我看看最近有什么 Agent 开发框架更新”,模型如果直接搜“Agent 开发框架更新”,搜索引擎返回的内容会非常泛。反过来,把 query 改造成“Agent 框架 github release 2025”会精准很多。这一步不依赖任何高级技术,就是靠工具描述和提示词约束,但改进效果立竿见影。

另外,我个人强烈建议保存一份“搜索调用日志”。每一次模型触发搜索时,把 query、返回结果的关键字段、模型后续是否采用了这条结果,都记录到日志里。跑几天之后,你能很清楚看到模型的搜索行为有哪些问题——是搜得太频繁,还是搜出来的东西根本没用上。这类日志就是 Agent 调优最可靠的依据,比任何抽象的“幻觉评估”都实在。

4. 框架选型与多 Agent 架构:搜索成为信息基础设施

4.1 LangChain、Dify、CrewAI,还是自研?

到了 Agent 项目有一定复杂度之后,不可避免要面对一个问题:到底用什么框架来编排整个 Agent 逻辑。市面上的选项非常多,而且热词榜上常年挂着 LangChain、Dify、CrewAI 这些名字,新手很容易选择困难。

我先说一个容易被忽略的事实:如果你已经像我上面那样用原生 Function Calling 写出了循环,你其实已经是一个 Agent 的最小形态了。框架解决的主要是三个问题:第一,多个工具的生命周期管理;第二,提示词、记忆、会话状态的统一封装;第三,多 Agent 协作时的握手协议。理解了这三点,选型就好办了。

LangChain 是老牌框架,生态最全,什么模块都有。它的优势是组件化程度高,做复杂编排时几乎都能找到现成的模块。缺点是抽象层级多,出现问题时排查链路长。如果你熟悉源码,用起来很顺手;如果只是当黑盒用,会有一种“它老是替我做了我不想要的决定”的无力感。适合团队里有对 LangChain 源码比较熟的工程师。

Dify 是另一类思路,主打可视化工作流编排。你可以用拖拽的方式把“意图识别-搜索-生成”串成一条流水线,还能一键把多 Agent 节点接起来。我非常推荐产品团队早期验证方案时用 Dify,因为它把大量工程细节,比如会话记忆、知识库检索、工具接入,都封装好了,你只需要关注业务流程。代价是深度定制时灵活的余地小,推理路径一旦要做得非常细,可视化节点反而会使操作变得繁琐。

CrewAI 主打的是“角色化多 Agent 协作”。你可以定义研究员 Agent、写作 Agent、审核 Agent,让它们像团队一样分工。如果你的场景天然适合多个角色分工,比如“先搜索整理资料,再由另一个 Agent 负责生成报告”,CrewAI 的上手成本比 LangChain 低很多。

我的个人建议:小项目或者首次尝试,直接用原生 Function Calling,最多配合 LangChain 的基础组件;如果目标是做产品原型、给客户演示,Dify 能帮你省下铺天盖地的工程时间;如果要做多角色协作、且团队成员都有一定工程能力,CrewAI 会让我觉得轻便。自研框架适合对推理路径、记忆结构、安全审计有极端要求的团队,比如要给客户私有化部署,或者模型链路里嵌了太多内部服务,这时候自己封装反而比学别人的抽象更快。

4.2 多 Agent 协作时,搜索服务怎么升级成“基础设施”

单 Agent 项目里,搜索只是一个工具。但在多 Agent 协作状态下,搜索的定位会发生一次质变——它变成多个 Agent 共享的公共服务。

想象这样的场景:你有一个“研究员 Agent”负责搜集信息,一个“分析 Agent”负责做横向比较,一个“写作 Agent”负责出报告。如果每个 Agent 都各自接一个搜索 API 自己搜,会出现三个问题。第一是重复搜索,同一个问题被不同 Agent 各搜一遍,费用和时间都浪费。第二是结论不统一,两个 Agent 搜到的信息源不同,产出之间可能互相冲突。第三是行为不可控,你不知道到底哪一个 Agent 在什么时刻执行了搜索,审计变得困难。

所以我会建议把搜索能力抽成一个独立的“搜索服务层”,对外只暴露一个接口:输入查询词,输出标准化结果。所有 Agent 要搜索都走这同一个服务。服务层内部统一做缓存、限流、结果清洗、敏感内容过滤。这样一来,不管下游有多少个 Agent,搜索行为都是统一策略,费用也能通过缓存被明显压缩。

还有一个值得实践的小设计:在搜索服务层加一个“查询词改写”模块。不同 Agent 对同一个主题的描述方式可能不一样,研究员可能说“某个框架的内存管理机制”,写作 Agent 可能说“这个框架的 memory 模块设计”。如果这两个查询都直接发给搜索 API,返回结果可能完全不同。在服务层里做一次规范化改写,把它们映射到同一组核心实体上,搜索缓存命中率能大幅度提高。多 Agent 协作项目里,这种底层服务的收益通常比调提示词更快。

4.3 关于“Agent Skills”:搜索作为可复用能力的封装

现在主流的 Agent 框架里,越来越多提到“skills”这个概念。本质上是把一类能力封装成可以被 Agent 自主调用的模块。搜索就是最适合先做成 skill 的能力之一。

以 Claude 生态里常见的 agent skills 为例,把“web search”封装成独立的 skill 之后,它包含的不只是一个 API 函数,而是还带了一份使用说明。说明里写清楚:什么场景触发搜索、查询词如何构造、结果如何筛选、如果结果不可信怎么办。Agent 在运行时会读这些说明,决定要不要调用、怎么调用。

这个思路很适合借鉴到自己的项目里。不要只给模型一堆裸函数,要给它“带说明书的能力包”。我自己的经验是,把搜索的使用策略写进 skill 描述之后,模型的搜索行为规范程度一下子高了很多,尤其在“什么时候不该搜索”这件事上明显更克制了。这比在超长 system prompt 里用规则约束要可靠得多,因为 skill 描述是在模型决定调用那一刻才被读取,注意力更集中,不容易被前面大段的系统指令稀释。

5. 安全边界与可靠性:让 Agent 的“手”不伸过长

5.1 Agent 联网,四条安全底线缺一不可

Agent 有了联网能力,意味着模型可以把外部世界的内容拉进来,也可以把内部信息带出去。搜索框时代,用户点一下“联网搜索”按钮,至少这个动作是显式的。Agent 时代,模型也许在用户毫不知情的情况下搜了三次、访问了五个网站。这就带来了新的安全要求。

我的底线是四条。第一条,工具权限白名单化。Agent 能调用的工具必须显式登记,没有在白名单里的服务一律拒绝。搜索 API、网页访问、代码执行,每一项都要单独授权,绝不能默认放开“所有工具都能用”。第二条,数据外发最小化。搜索请求只能携带必要的查询词,不能顺手把用户的隐私信息、企业内部数据、当前会话里的其他内容都拼进 query 发出去。很多搜索 API 默认会记录请求日志,这一点尤其要小心。第三条,输出合规检查。Agent 生成的内容在展示给用户之前,至少过一道关键词过滤和格式校验。第四条,过程可审计。每一次工具调用的时间、参数、结果摘要都需要被记录,出问题时有据可查。

这里特别想提醒一件事:搜索 API 的请求日志问题。很多人选型时只看返回结果质量,忽略数据合规。如果你的 Agent 面向企业客户,涉及内部敏感信息,搜索引擎服务商的日志留存政策就是一道硬门槛。要么选支持私有化部署或者明确承诺不记录请求内容的服务,要么在接入层做查询词脱敏,避免把完整的敏感上下文直接送进 search query。

5.2 Agent Harness 与沙箱:把 Agent 关进能放心的笼子

现在 Agent 工程里,Harness 和沙箱这两个词出现的频率越来越高了。很多人分不清两者的区别。我的理解是:沙箱解决的是“Agent 运行环境隔离”问题,Harness 解决的是“Agent 行动过程控制”问题。一个管环境,一个管行为。

沙箱主要落在代码执行类 Agent 上。如果 Agent 不仅要联网搜索,还要执行 Python 脚本、操作文件,那就必须在一个隔离环境里跑。以前很多项目图省事,直接在宿主机上执行 Agent 生成的代码,一旦代码里出现rm -rf或者访问系统关键文件的命令,后果是灾难级的。Docker 容器、微 VM、云沙箱服务,都是可选的方案。负责的态度是默认 Agent 不可信,所有执行都被限制在无写权限的文件系统和受限网络策略中。

Harness 则更像一套“管理笼统”。它给 Agent 的行动套上明确的规则框架:允许调用哪些工具、每一步是否允许修改记忆、任务执行到什么条件必须终止、出现异常时是否有人工介入通道。早期 Agent 项目里,我们最怕模型陷入某种搜索死循环——查一个词,返回结果不够,又查另一个词,结果还不对,于是一只搜下去,token 费用飙升。Harness 会限定最大工具调用次数,一旦超过边界就直接终止任务,哪怕信息不完整也只能基于已有信息回答。这个机制听起来简单,但能救项目于水火。

Claude 官方也强调过 harness 的“幂等性”设计:Agent 重复执行同一个动作,不应该产生额外的副作用。比如 Agent 连续两次搜索同样的 query,第一次返回的结果被缓存了,第二次直接命中缓存,而不是重新消耗一次 API 配额。再比如 Agent 写文件,如果内容完全相同,第二次应该直接跳过。这背后是工程上的细节,但正是这些细节决定了一个 Agent 在生产环境中能不能稳定跑下去。

5.3 搜索结果的信任分级

最后聊一个很多人忽略的可靠性问题:搜索结果到底该被信任到什么程度。

我的习惯是给搜索结果按来源打一个信任标签。官方文档、技术论文、知名技术社区作者发布的博客,信任等级高;论坛匿名内容、SEO 软文、营销页面,信任等级低。具体做法不复杂,在搜索 API 返回结构化数据之后,加一层规则,把域名和页面类型映射成预设的信任分。后续 Agent 生成回答时,再根据这条信任分决定“能不能直接引用”还是“只能作为参考”。

这套看起来粗暴的规则,在实际项目里比什么高级的“可信度评估模型”都管用。原因是搜索返回结果中真正造成问题的,是大量的 SEO 拼凑内容和营销软文,它们的特征非常明显——域名很新、内容结构雷同、发布时间频繁更新。用规则就能挡住一大部分。模型自己判断可信度则不可靠,因为 LLM 的本能是把上下文里所有内容都当成事实一样对待。加上信任分级之后,模型抓取重点的行为明显会收敛很多。

6. 常见问题排查实录:我踩过的坑,希望你别再踩

6.1 “模型就是不调用搜索工具”,先检查这四件事

接完了搜索 API,写好了 tools,结果运行起来模型死活不调工具,直接硬答。这个问题我见过太多次了,每一次排查路径几乎都一样。拿一份排查清单,按顺序查,基本能解决问题。

现象排查点解决方案
模型完全不调用工具tool_choice没设置或设置不准确确认设置为"auto",并完成一次带简单工具请求的测试
工具方法名错误或签名不匹配工具名称、参数 schema 与真实函数不一致把 tools 里的 function name 和实际执行代码逐一对照
模型觉得不需要搜索system prompt 里没有给出搜索的条件说明明确提示“涉及事实、时效、外部数据时优先搜索”
返回内容有工具调用但被截断max_tokens 设置太小,截断了 tool_call 输出调大 max_tokens,或改用带 buffer 的截断判断

第一类问题最隐蔽的就是tool_choice。看起来只是一个枚举值,实际影响很大。有人说:我明明给了模型 tools,它为什么不搜?我打开代码一看,他把tool_choice写成了"none"。这等价于告诉模型“工具给你看,但你不许用”。所以我建议你写代码时把tool_choice参数单独一行,注释写清楚,防止误改。

另外,如果模型偶尔调用工具,但调用的频率和你的预期差很远,先别急着调提示词,看一眼 message 历史。有时候是上下文里的信息已经足够详细了,模型基于已有信息判断不需要搜索。这时候的问题不是“模型不会搜”,而是“模型太自信”。可以考虑在 system prompt 里加入类似“当上下文信息可能过期或不完整时,必须通过搜索核实”的行为规范。

6.2 搜索结果太旧、太泛、上下文爆掉:三个高频问题的实操解法

搜索 API 返回结果和用户意图不匹配,大概会有三种表现。第一种是结果太旧,用户要最新动态,返回的是一年前的新闻。第二种是结果太泛,用户想知道某个具体的配置参数,返回的是框架介绍首页。第三种是结果太多,一个查询返回几十条摘要,直接把上下文塞满了。

结果太旧,解决办法是设置搜索 API 的时间过滤参数。Bing、Brave、Tavily 这类接口基本都支持,在 tools 的参数 schema 里加一个freshness或者time_range字段就行。但要记得把可选参数也描述清楚,否则模型经常不填。结果太泛,通常是 query 构造得不够具体。前面已经说过,可以在工具描述里教模型把 query 写得更精确,还可以在后续生成时强制模型“必须引用具体数值或版本号,避免泛泛而谈”。上下文爆掉,更直接的方法是把搜索结果先做一次摘要压缩,再塞给模型。搜索 API 返回 20 条摘要,长度可能超过 8000 token;但 Agent 真正需要的可能只有 5 条有效信息。可以在搜索服务层加一个“精选”环节,用一个小模型或者规则把结果压到 3000 token 以内,再喂给主模型。

这里还有一个我试过很有用的技巧:给搜索结果的摘要里加上“发布时间”和“来源域名”,并要求模型在生成时优先参考发布时间较新的内容。很多选择困难其实就是信息排序问题,把这些信号显式放进上下文里,模型做决策的准确率会上一个台阶。

6.3 幻觉与错误引用:让模型“不知道就承认不知道”

联网搜索并不能消除幻觉,这一点要认清。模型在生成时仍然有可能编造搜索结果里没有的内容,尤其是在它“觉得”自己知道答案的时候。应对手段不是说服模型“别撒谎”,而是用机制逼它只能引用真实存在的内容。

最有效的做法是引用编号约束。在把搜索结果注入上下文时,给每一条结果编号,并在 system prompt 里写入强约束:“回答中必须使用 [1] [2] 这样的编号标注来源,没有来源支撑的信息不得输出。”再加上一条:“如果搜索结果不足以回答问题,直接说明信息不足,不要猜测。”这两条规则组合使用,对压制幻觉的效果非常明显。

我还遇到过一个典型案例:Agent 在回答某公司的财报数据时,引用了另一家同名公司的数据。排查了好久,最后发现是搜索 API 返回的结果里,两家公司的名称相似度太高,模型没有能力区分实体。解决方案是在搜索之前加了一次实体消歧——让模型先判断用户问的是哪家公司,再把完整名称、行业、地区等信息一并写进 query。加了这个前置步骤之后,类似的错引问题基本绝迹。这个经验也说明,Agent 的很多问题不是在生成环节解决的,而是在搜索环节就埋下了隐患,前面的链路做得越干净,后面的幻觉越少。

最后再分享一点实际感受

我一路从“把网页摘要拼进提示词”的搜索框模式,做到现在这种带推理循环的 Agent 编排,最深的体会其实是:联网搜索从来不是一个功能,它是让模型第一次拥有“环境感知”的起点。搜索框时代,搜索是挂在系统里的一根拐杖,模型拄着它走两步,但方向还是人定的。Agent 时代,搜索变成了系统的眼睛,模型自己决定往哪看、看多久、看完怎么走。技术形态在变,但底层的产品判断没有变——用户要的不是“能搜”的聊天机器人,而是“知道该搜什么、搜完能给结论”的助手。如果你现在正处在“模型已经会搜,但结果仍然不聪明”的瓶颈期,我建议你先别急着换更大的模型,回头检查一下搜索结果的输入结构和推理循环的判断条件,往往比升级模型更有效。这条路很长,但越往后走,你会越觉得值得。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询