当前位置: 首页 > news >正文

让大模型拿到实时搜索结果:SERP API 的一个实现方案

做 LLM 应用绕不开的一个问题:模型的知识停在训练截止日期,问它「昨天发生了什么」它不会承认自己不知道,只会一本正经地编。

更糟的是,模型回答错的语气和回答对的语气完全一样,用户根本分不清。这种「看起来对但其实假」的回答,比「我不知道」危险得多。

要补这块能力,最常见的做法是给模型接一个工具,让它能去网上查。但「网上查」这件事,如果直接丢 HTML 给模型,基本是行不通的——模型要的是结构化字段,不是 div 和 class。HTML 里 70% 的内容是样式、脚本、广告位,模型拿到这种输入基本没法用,就算硬塞进去也只会让回答变得更混乱。

这就需要一个 SERP API:把 Google 搜索结果转成结构化 JSON,再喂给模型。整个链路里 API 这一层的职责是「把脏的 HTML 洗干净,把散的字段整理成结构」,让下游的 LLM 只需要关心「怎么用这些字段」。

下面把整个实现方案拆开讲,从协议选择、字段设计、错误处理到 LLM 侧的上下文压缩,一步步过一遍。

为什么用 API 而不是自爬

我自己一开始是写爬虫的,最早的方案是 Playwright + 简单调度。跑了两周之后翻车:

  • captcha 把 IP 拉黑,改 User-Agent 没用。
  • Google 改版一次,解析器全废,半夜挂掉没人发现。
  • 不同地区拿到的 SERP 不一样,有的数据是「简化版」。

第三个问题最阴——HTTP 200 + 看起来正常的 HTML,但实际上缺了 PAA、缺了 knowledge_graph、甚至缺了第一条 organic。数据混进 JSON 里给模型用,模型还以为这是真的。调了一周才发现是 IP 拿到的 SERP 不完整。

后来转向 SERP API。把抓取、解析、IP 调度这些脏活全交给上游,自己只关心「怎么把结果喂给模型」。这个分工很关键:调用方不应该去管 Google 改版的事,也不应该去管每个 IP 拿到的 SERP 是不是被降级了。这部分工作应该由专门的 API 服务来兜底。

接口长什么样

下面以 SerpBase 的接口为例。Base URLhttps://api.serpbase.dev,鉴权用X-API-Key头,请求体是 JSON。

最常用的搜索接口:

curl-XPOST https://api.serpbase.dev/google/search\-H"Content-Type: application/json"\-H"X-API-Key:$SERPBASE_API_KEY"\-d'{"q":"openai realtime api","hl":"en","gl":"us","device":"default"}'

/google/search一次消耗 1 credit。q是查询词,hl是语言,gl是国家,device默认自动路由,也可强制pcmobile

返回的 JSON 里主要带这些模块:

  • organic—— 自然结果
  • top_stories—— 顶部新闻
  • people_also_ask—— 相关问题
  • knowledge_graph—— 知识图谱
  • related_searches—— 相关搜索
  • ai_overview—— Google 给的 AI 摘要(如果有)

所有端点共用一个响应外壳:

{"status":0,"request_id":"0f3576b2-6e2e-4f1e-bb0e-8cb0d4a60195","elapsed_ms":1432,"credits_charged":1,"search_type":"search"}

status: 0成功。request_id全链路唯一,调试时直接给支持就行。elapsed_ms是网关观测到的延迟,可以用来判断是网关慢还是上游慢。credits_charged是实际扣的 credit,失败时一般是 0。

错误码:调用方最依赖的一层

我第一次接 SERP API 的时候只看 HTTP 状态码,第二天就翻车了——HTTP 200 但status: 1029(限流),我把空结果当成「搜索没结果」传给了模型。模型收到空上下文之后开始自由发挥,给了一个完全编造的回答。

后来设计成两套状态码:

  • HTTP 状态码:给运维和网关看,决定要不要告警、要不要切流量。
  • 业务状态码status:给调用方判断成功失败,决定要不要重试。

下面以 SerpBase 的错误码为例:

  • 1001UNAUTHORIZED —— API key 不对,重试也没用
  • 1004NOT_FOUND —— 资源不存在,重试也不会出现
  • 1029RATE_LIMITED —— 限流,先降并发再重试
  • 1500INTERNAL_ERROR —— 平台 bug,可重试但要带 trace id
  • 1502UPSTREAM_FAILED —— 上游失败,最适合重试
  • 1503SERVICE_UNAVAILABLE —— 服务暂不可用,重试
  • 1504UPSTREAM_TIMEOUT —— 上游超时,重试

HTTP 200 +status: 1029是合法的。调用方只看status字段,错误时附带的request_id用来查日志。客户端大致这样:

importos,time,requests API="https://api.serpbase.dev"KEY=os.environ["SERPBASE_API_KEY"]RETRYABLE={1029,1502,1503,1504}defsearch(q:str,retries:int=3):foriinrange(retries):r=requests.post(f"{API}/google/search",headers={"X-API-Key":KEY,"Content-Type":"application/json"},json={"q":q,"hl":"en","gl":"us"},timeout=15,)data=r.json()st=data.get("status")ifst==0:returndataifst==1001:raiseRuntimeError(f"unauthorized:{data}")ifstinRETRYABLE:time.sleep(2**i);continueraiseRuntimeError(f"status{st}:{data}")raiseRuntimeError("retries exhausted")

几个细节:超时 15 秒(Google P50 大概 1.4s,冷启动会到几秒);退避用 2 的幂;retries卡在 3 以内,再多也救不回来。

喂给 LLM 之前的压缩

拿到 JSON 之后,下一步是塞给模型。但完整 JSON 拼起来其实不小:

  • organic默认会带 10 条,每条还可能嵌套sitelinks
  • people_also_ask会有 4-8 条。
  • knowledge_graph加上图片、属性、相关实体,能堆几千 token。

贪多全塞,Agent 走 5 轮对话就爆上下文。我自己的压缩规则:

  1. organic截前 5 条,只留titlelinksnippet
  2. PAA 截前 4 条,每条只留questionanswer
  3. knowledge_graphdescription和关键属性,图片不传。

然后塞进 system prompt:

Use the following search results to answer the user's question. If the answer is not in the results, say you don't know — do not make things up. {json.dumps(compressed, ensure_ascii=False, indent=2)}

还有一个容易踩的坑:Google 的snippet里经常出现「根据 X 资料整理」「点击查看更多」这种没信息量的句子,模型会原样复述。塞进 prompt 之前先过滤掉空白 snippet、重复标题、太短的描述。

按问题类型选择性注入更省 token。问「什么是 X」就只塞knowledge_graph,问「X 怎么用」就只塞organic+people_also_ask,问「X 最新动态」就只塞top_stories+ai_overview。具体怎么判断,可以在 system prompt 里给模型一个明确的分类指令,让它在调用工具前先输出意图标签,比写一堆 if-else 干净。

压缩之后再加一道:把每条结果的link也单独提出来塞进 prompt 末尾的「来源」列表里。模型回答时直接把链接带上,用户能看到「这个结论来自某某网站」,比一个不带链接的干答案可信度高一个量级。这对 Agent 类应用尤其重要——用户没办法判断模型说的是不是真的,但能看到来源就有办法自己核验。

高级模式:MCP

如果想做得更彻底,可以让 Agent 通过 MCP 服务直接调用搜索接口。MCP 是给 AI 客户端用的标准协议,把搜索作为一个工具注册给模型,模型自己决定什么时候调、调什么 query。

下面以 SerpBase 的 MCP Server 为例,Claude / Cursor / Codex 这类客户端配一行 JSON 就能用:

{"mcpServers":{"serpbase":{"command":"python","args":["-m","serpbase_mcp"],"env":{"SERPBASE_API_KEY":"your_api_key"}}}}

我自己在 Claude Code 里接过一次,比手写 tool schema 干净不少。模型自己知道该调几次、调完就停,不再需要提前在代码里写一长串「先调搜索、再判断要不要再调一次」的逻辑。这种「模型自治」的调用方式在多轮对话里特别省心——上一轮调过搜索的 query 下一轮不需要再调,模型自己会判断。

不过 MCP 也有代价:每次会话都要起一个 MCP server 进程,模型对每个工具的调用都要过一遍 schema 校验。如果只是简单的「给 Agent 加一个搜索能力」,手写 tool schema 反而更轻量;如果是多工具、多 step 的复杂工作流,MCP 省的工程量就值回来了。具体怎么选,看自己的场景。

Maps 场景的两段式调用

如果工作流里需要本地搜索,/google/maps/search/google/maps/detail(各 2 credit)组合起来用很顺手:先用maps/search拿到一堆 place,再拿feature_idmaps/detail拉详情。

latlng必须一起传,zoom范围 1-21,不传时默认 14。详情里能拿到电话、官网、营业时间、相册、评分。

注意feature_id0x...:0x...这种格式,从maps/search返回里的data_idcid长得也像 id,但都不能直接当feature_id用——这是当时调试时卡了我半小时的地方。

一些收尾的坑

  • hl/gl要传对。中文用zh-CN / cn,英文用en / us,混了 SERP 完全不一样。
  • page是 1-based,不是 0-based。
  • 高频调用要自己做缓存。Google 同一个 query 在几分钟内的结果变化不大,能省掉很多重复请求。
  • request_id一定要打到日志里statuselapsed_mscredits_charged一起打,出问题回查时一查一串。
  • 失败时不一定是 0 credit1502 / 1503 / 1504失败时一般是 0,但1029不一定。

整个方案跑下来,模型侧的「实时性」问题就解决了。SerpBase 的完整接口文档在 serpbase.dev/docs。

http://www.cnnetsun.cn/news/3111643.html

相关文章:

  • 智能动效检查:AI 可以看节奏,但标准要由人定义
  • 投机解码技术解析:如何用DSpark实现大模型推理85%加速
  • ASP.NET 8 Cookie身份验证实现与安全实践
  • MetaTube插件:Jellyfin/Emby媒体库的终极元数据自动刮削解决方案
  • 学习型查询优化器:特征漂移比模型精度更麻烦
  • 2026手机抠图工具实操指南:人像物品背景去除,安卓苹果免费软件整理
  • GraphQL 成本控制:灵活查询也要有防火墙
  • MySQL 慢查询根治指南:从 EXPLAIN 看懂到索引覆盖率优化的完整链路
  • AI 后端队列背压:请求堆住时,系统要会说不
  • Node.js企业级部署手册:Windows与Linux生产环境实战指南
  • CSS 滚动驱动动效:让页面跟着内容节奏移动
  • 从零到一:STM32嵌入式温度控制系统实战指南 [特殊字符]
  • STM32F429ZI与MC6470 IMU的运动控制实现
  • 架构师转 CEO:别把公司当成一个大系统重构
  • 通达信缠论可视化插件:5分钟实现专业级K线分析
  • Uniapp+Vite H5真机调试HTTPS穿透方案实战
  • ClickHouse 分区设计:分区不是越细越好
  • 生产故障复盘的系统化框架:从根因追溯到改进闭环的方法论
  • CTFshow弱口令爆破
  • 魔兽世界宏工具GSE:智能技能循环与游戏自动化解决方案
  • Spring Boot整合MongoDB实战:从CRUD到聚合查询
  • PUBPEER上微纳光子学相关的质疑-1
  • 【2026实测有效】 如何永久禁止Win11自动升级?6大方法关闭Windows11更新最安全简单操作方法
  • 电容式触控感应原理,Q-Touch:针对不同的覆盖层厚度或 PCB 布局微调灵敏度 ,快速构建项目
  • TDD在Unity3D游戏项目开发中的实践0x00
  • ChatIG架构揭秘:高效推理网关背后的技术原理
  • Win7系统上安装Python教程:轻松上手3.8.6版本
  • 企业仓储数字化如何落地?不同规模仓库WMS仓储系统举例
  • ModSecurity CRS实战:解决误报、性能瓶颈与规则更新的完整指南
  • 专科生必学:8款AI工具提升学习效率