给AI Agent接入联网搜索:一个可落地的检索流水线

简介: 为AI Agent添加联网搜索,远不止调用API:需构建完整检索链路——精准判断搜索必要性、多轮查询改写、结果标准化去重、权威来源排序、正文精读与引用校验,才能确保答案既实时又可靠。(239字)

给Agent增加联网搜索并不难。定义一个搜索工具,把用户问题传进去,再把结果交给大模型,十几行代码就能跑起来。

真正麻烦的是上线以后。

同一个问题有时能找到准确答案,有时全是重复转载;搜到了正确页面,返回的摘要却不包含关键内容;模型明明带了引用,链接里的原文却无法支持它的结论。请求量上来以后,还会遇到超时、限流和网页读取失败。

这些问题通常不是换一个更大的模型就能解决,而是搜索链路本身没有设计完整。

一条完整的联网检索链路

比较实用的处理流程是:

用户问题
  ↓
判断是否需要联网
  ↓
查询改写与拆分
  ↓
并发搜索
  ↓
结果标准化、去重
  ↓
相关性与来源排序
  ↓
读取少量候选网页
  ↓
正文切分与压缩
  ↓
生成带引用答案
  ↓
引用一致性检查

搜索API只是其中一环。最终效果取决于整条链路,而不是接口一次返回多少条结果。

先判断这个问题是否需要搜索

并非所有问题都需要联网。

代码解释、固定知识和已经存在于内部知识库中的内容,可以直接回答。涉及新闻、政策、价格、版本、公司信息和实时状态的问题,则应该强制搜索。

可以先做一个简单分类:

def search_policy(question: str) -> str:
    realtime_words = [
        "今天", "目前", "最新", "现在",
        "价格", "版本", "政策", "公告",
        "是否上线", "什么时候发布"
    ]

    if any(word in question for word in realtime_words):
        return "required"

    return "model_decide"

生产环境可以用一个小模型判断,但最好保留强制规则。否则模型可能认为自己知道答案,直接使用已经过期的内部知识。

不要直接拿用户原话搜索

用户问题和搜索引擎需要的查询往往不是一回事。

例如:

为什么我的流式接口经常过一会儿自己断掉?

这个问题至少包含几个可能方向:

SSE连接超时原因
反向代理SSE超时配置
流式API idle timeout
Nginx proxy_read_timeout SSE

如果只搜索用户原话,结果可能非常分散。比较稳妥的做法是让模型生成两到四个查询,分别覆盖现象、技术术语和可能原因。

async def rewrite_queries(question: str) -> list[str]:
    prompt = f"""
    将下面的问题改写为最多4个适合搜索引擎的查询。
    查询之间要有不同侧重点,不要生成同义句。

    用户问题:
    {question}
    """

    return await small_model.generate_json(prompt)

查询数量也不是越多越好。简单事实问题通常一个查询就够;只有调研、比较和故障排查类问题,才有必要并行搜索多个方向。

搜索结果必须先标准化和去重

不同搜索源返回的字段不完全一样。有的提供标题和摘要,有的返回正文片段,还有的额外提供发布时间、站点名称或相关性得分。

进入后续流程前,最好统一成内部结构:

from dataclasses import dataclass

@dataclass
class SearchResult:
    title: str
    url: str
    snippet: str
    source: str
    published_at: str | None = None
    score: float | None = None

去重时不能只比较完整URL。同一篇文章可能带有不同的跟踪参数,也可能被多个页面转载。

至少需要处理:

  • 删除utm_*等跟踪参数;
    -统一HTTP与HTTPS形式;
  • 识别相同域名下的重复路径;
  • 比较标题相似度;
  • 比较摘要或正文指纹;
  • 合并同一事件的重复新闻。

如果不做去重,模型可能看到五条结果,以为得到了多个来源的交叉验证,实际上五条都来自同一篇稿件。

不要读取所有网页

搜索结果里的摘要通常不足以回答复杂问题,但也没必要读取每一个页面。

更合理的流程是:

  1. 搜索阶段先获取10条左右结果;
  2. 根据标题、摘要、时间和来源完成第一次排序;
  3. 只读取排名靠前的3—5个页面;
  4. 对正文再次排序;
  5. 最终向模型提供2—4个真正有用的来源。

简化后的代码大致如下:

async def retrieve(question: str):
    queries = await rewrite_queries(question)

    result_groups = await parallel_search(
        queries=queries,
        top_k=10
    )

    merged = normalize_and_merge(result_groups)
    unique = deduplicate(merged)
    candidates = rank_search_results(question, unique)

    pages = await read_pages(
        candidates[:5],
        timeout=12
    )

    passages = split_and_rerank(
        question=question,
        pages=pages,
        top_k=8
    )

    return passages

读取网页时要设置单独超时。一两个页面解析失败,不应该拖死整个Agent任务。

时间和来源需要显式控制

新闻、版本、价格、政策等问题应设置时间范围,不能完全依赖搜索引擎自行判断。

高风险问题还需要限制来源。例如:

  • 法规优先政府和监管机构网站;
  • 医疗优先卫生机构、医院及专业组织;
  • 软件问题优先官方文档和代码仓库;
  • 公司公告优先交易所及企业官网;
  • 学术问题优先论文原文和权威数据库。

可以给不同来源配置基础权重:

SOURCE_WEIGHT = {
   
    "official": 1.0,
    "academic": 0.9,
    "professional_media": 0.75,
    "community": 0.55,
    "unknown": 0.3,
}

权重不能代替相关性。一个权威但答非所问的页面,不应该排在真正解决问题的技术文章前面。

引用链接不等于答案可靠

很多系统做到“答案后面有链接”就结束了,但真正需要检查的是:

引用页面里的内容,是否真的支持答案中的说法?

一种可操作的方式,是把生成答案拆成若干事实陈述,再逐条寻找支持证据:

陈述:某功能从3.2版本开始支持。
证据:官方更新日志明确写明3.2版本新增该功能。
结论:支持。

陈述:该接口平均延迟低于500ms。
证据:引用页面只写了“低延迟”,没有提供测试数据。
结论:不支持,应删除具体数值。

对于找不到直接证据的内容,可以删除、降低语气强度,或者明确标注为推断。

这一步会增加一次模型调用,但对调研、报告和高风险问答很有价值。

必须处理超时、限流和空结果

联网服务不可避免会失败,Agent不能把搜索失败理解为“网上没有信息”。

建议区分以下情况:

class SearchError(Exception):
    pass

class RateLimited(SearchError):
    pass

class SearchTimeout(SearchError):
    pass

class EmptyResult(SearchError):
    pass

对应策略也应不同:

  • 限流:指数退避后重试;
  • 超时:缩短查询或切换备用搜索源;
  • 空结果:改写查询后再搜索;
  • 网页读取失败:保留搜索摘要,继续处理其他页面;
  • 全部失败:明确告诉用户当前无法完成联网验证。

如果业务对可用性要求较高,最好准备两个搜索源,但不建议每次同时调用。正常情况下使用主搜索源,失败或结果质量不足时再触发备用源。

怎么判断搜索链路有没有变好

只统计请求成功率不够。搜索接口正常返回,不代表Agent找到了正确答案。

可以重点记录下面这些指标:

指标 说明
Top 5相关率 前5条结果中真正相关的比例
新鲜信息命中率 时间敏感问题是否找到最新资料
权威来源占比 候选结果中可信来源的比例
重复结果率 多条结果是否实际来自同一内容
正文读取成功率 候选页面能否提取有效正文
引用支持率 引用内容是否能支持对应结论
P50/P95耗时 常规请求与慢请求的实际表现
单任务成本 搜索、读取、重排和模型调用总成本
任务完成率 最终是否正确回答了用户问题

测试问题最好来自真实业务,而不是只用“今天天气怎么样”之类容易搜索的问题。

一套基础测试集可以包含新闻、技术文档、政策、产品信息、故障排查、学术资料和长尾问题。每个问题重复运行几次,才能看出结果波动。

结语

联网搜索不是给模型加一个工具按钮,而是一条完整的信息处理链路。

查询改写决定搜什么,去重和排序决定看什么,网页读取决定能拿到多少证据,引用校验决定最后的答案能不能相信。

接口接通只是开始。真正影响Agent体验的,通常是这些看起来不起眼的工程细节。

相关文章
|
24天前
|
人工智能 JSON API
全网刷屏的 Jev 模型正式开放!一手实战测评 + 保姆级教程
全网爆火的 Jev 模型是什么?有什么用?怎么使用?怎么接入 AI 编程工具?效果真的好么?傻子可懂的 Jev 保姆级实战教程 + 项目实战测评来啦
9478 31
|
1天前
|
云安全 人工智能 运维
当攻击全面Agent化,你的安全防御能否跟上AI Speed?
多起客户侧AK泄露事件应急的真实观察
1155 0
|
10天前
|
存储 人工智能 并行计算
大模型本地部署终端选型方法论:以 Qwen3.8-27B 为例的四档分层完整流程
本文提出一套大模型本地部署终端选型方法论:定约束、定档位、定框架、定参数四步决策法,配合入门、主力、质量、无损四档分层模型。以 Qwen3.8-27B 实测数据为例,逐环节解读显存、带宽、存储、散热、系统、预算等要素,给出面向不同预算的优选方案、决策自查清单与市场观察框架。文末前瞻 AI 笔记本的 CPU+GPU 与统一内存两条路线,论证四步决策法在新品类上的延续性。
|
9天前
|
人工智能 JSON 自然语言处理
2026 年 Jev 决策模型深度拆解:原理解读、实战测评与保姆级落地教程
有一款特殊AI模型在开发者圈子刷屏,它摒弃传统大模型擅长的对话聊天能力,专注做高速结构化决策,它就是TypeSafe AI推出的Jev模型。该模型由ChatGPT共同发明人Diogo Almeida主导研发,定位为**System One Model(系统一模型)**,对标人类大脑快速直觉判断的思维模式,在响应延迟、调用成本、结构化输出稳定性上相比传统生成式大模型有着巨大差异。本文会完整拆解Jev底层原理、三大核心原语能力、适用业务场景,同时提供可直接运行的curl、Python代码示例,并且结合多组实测数据,客观分析模型优势与能力边界,帮助普通开发者和AI应用从业者快速上手落地。
716 1
|
5天前
|
人工智能 JSON 自然语言处理
2026 年 Jev 决策模型全解析:核心原理拆解,性能实战测评与落地部署教程
有一款特殊AI模型在开发者圈子刷屏,它摒弃传统大模型擅长的对话聊天能力,专注做高速结构化决策,它就是TypeSafe AI推出的Jev模型。该模型由ChatGPT共同发明人Diogo Almeida主导研发,定位为System One Model(系统一模型),对标人类大脑快速直觉判断的思维模式,在响应延迟、调用成本、结构化输出稳定性上相比传统生成式大模型有着巨大差异。本文会完整拆解Jev底层原理、三大核心原语能力、适用业务场景,同时提供可直接运行的curl、Python代码示例,并且结合多组实测数据,客观分析模型优势与能力边界,帮助普通开发者和AI应用从业者快速上手落地。
467 0
|
22天前
|
人工智能 测试技术 API
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
Jev是TypeSafe AI推出的“系统一模型”,不生成文本,专做毫秒级结构化决策:Choice(多选)、Score(打分)、Noul(是非概率)。响应快193倍、成本低444倍,适合工单路由、内容审核、测试定级等高频判断场景。
2547 4
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
|
4天前
|
存储 缓存 测试技术
QWT 3D 模块重构记:旧渲染管线改进介绍及实时瀑布图示例
QWT 3D模块完成重大重构:解耦窗口与图形(Plot+Item),摒弃OpenGL 1.x固定管线,迁至Core Profile着色器渲染;支持多图元同场景叠加,并以实时3D瀑布图验证——滑动窗口、固定色域、64帧×256点达61fps。兼容Qt 5.12+/6,LGPL协议。
177 120
|
16天前
|
Windows
【保姆级】.NET Framework 3.5离线安装教程(2026最新实测)
.NET Framework 3.5是微软经典运行库,专为兼容老软件、老游戏设计。Win7自带,Win10/11需手动启用(在线或离线安装)。它与4.x系列并存不冲突,缺它会导致“找不到组件”报错。本文详解两种安装方式及常见问题解决,小白也能轻松上手。(239字)
2080 0

热门文章

最新文章