一句话结论:自建 GEO 监测最危险的地方不是搭不通,是搭通了、跑得很顺、数字却在回答另一个问题。国内主流大模型的开发者接口,联网检索默认都不是开启状态,而且每一家的开关名字、挂载位置都不一样——不显式打开它,你跑出来的「提及率」测的是模型训练语料里有没有你,不是用户在 AI 搜索里会不会看到你。更糟的是,这类参数在 OpenAI 兼容封装里会被静默丢弃:请求返回 200,答案照常生成,只是没联网。下面按数据流水线的顺序,把五个让数字失真的工程点逐个拆开,每个都给出可核的官方口径和自检方法。
先划清和另一篇的界:自己写脚本监测 AI 提及,还是买工具? 回答的是商业决策层的问题——这笔账划不划算,读者是市场负责人。本篇是工程实现层——你已经决定自己干了,真动手会在哪一步拿到错数字,读者是技术负责人。两篇不重复:那篇的结论是「贵在人天」,本篇的结论是「错在口径」,而口径错了,人天再多也补不回来。
一、先承认:API 方案有几个真优点,别打稻草人
中文侧那批自建教程(火山引擎、CSDN 的实战附代码稿)说对了很多事,这些优点是真的:
- 批量与调度自由。几百条问题、几个引擎、想什么时候跑就什么时候跑,不受工具的配额与界面限制。
- 便宜。纯 token 成本确实低到可以忽略——量级见上面那篇的成本表,本文不重复算账。
- 数据在自己手里。原始答案能直接进你自己的数仓和 BI,和站内数据、投放数据 join 起来做归因。
- 接入门槛确实低。DeepSeek、通义、混元、Kimi 都提供 OpenAI 兼容接口,换个
base_url和api_key就能跑通第一版。
所以问题从来不是「能不能搭」。问题是搭出来的那条曲线,在你不知道的情况下已经在测别的东西了。
二、错点 1(最致命):联网检索默认是关的,而且每家开关都不一样
为什么这一条决定其余全部
GEO 监测想测的是生成式检索的结果:用户问一句话,引擎现场去检索、召回、总结,然后决定提不提你。这里面「现场检索」才是你能优化的部分——你上周发的一篇行业稿、更新的一版产品页,能影响的只有它。
而模型不联网时给出的答案,来自训练语料压进参数里的静态记忆。这份记忆几个月才随模型版本变一次,你做的任何内容动作,在下一次预训练之前都不会反映到里面。
所以:不开联网跑出来的提及率,是一个你几乎无法通过 GEO 工作改变的数字。 它不是没有意义(它反映品牌的历史沉淀),但它绝对不是你汇报「这个月 GEO 做得怎么样」时该用的那个数。
五家引擎的联网开关对照(截至 2026-09-09 官方文档口径)
这张表是本文最该被抄走的一张。注意第三列——没有任何两家是一样的:
| 引擎 | 联网检索怎么开 | 默认行为 | 官方文档 |
|---|---|---|---|
| 豆包(火山方舟) | 联网能力以**「联网内容插件」形式挂在应用(Bot)**上,调用走 Bot API,不是直接打模型的 chat/completions | 直接调模型端点 = 不联网 | 联网内容插件功能说明、应用(Bot)API |
| DeepSeek | 标准 OpenAI 兼容 chat/completions 没有内置检索工具,文档里的工具类型是 function,检索需要你自己实现并执行 | 不联网 | DeepSeek API 文档 |
| Kimi(Moonshot) | 声明内置工具 type: "builtin_function" + function.name: "$web_search",模型只生成检索参数,检索由 Kimi 侧执行 | 不声明则不联网;触发检索另行计费 | 使用 Kimi API 的联网搜索功能 |
| 通义千问(阿里云百炼) | 传 enable_search: true;它不是标准 OpenAI 参数,Python SDK 必须走 extra_body;开启后由模型自行判断是否需要检索 | 不传 = 不联网;传了也未必每次都检索 | 大模型如何联网搜索 |
| 文心 / 百度(千帆) | 请求体里传 web_search 对象(enable / enable_citation / enable_trace / search_mode / search_number 等);另有独立端点 /v2/ai_search/chat/completions | 不传 = 不联网 | 千帆·联网搜索、调用百度 AI 搜索 |
⚠️ 接口参数与模型支持范围变动频繁(例如百度侧的 web_search 目前标注为 ERNIE 5.0 / X 系列支持),上线前请以各平台官网当日文档为准。
那个最隐蔽的失效点:统一封装会把开关吃掉
自建方案第二天一定会做的事,是写一个统一的 client 把几个引擎包起来:
# 看起来很干净,但它对国产引擎是危险的
resp = client.chat.completions.create(
model=m, messages=msgs, temperature=0
)
阿里云百炼文档已经把话说明白了:enable_search 不是标准 OpenAI 参数,Python SDK 下必须通过 extra_body 传递(Node.js SDK 则作为顶层参数)。同理,火山方舟的联网能力压根不在模型端点上,百度的 web_search 是一个自定义对象,Kimi 的是一个非标准的 builtin_function 工具类型。
这四种东西,没有一种能穿过一个「只认标准字段」的统一封装。 而它失败的方式是最坏的那种:
- 不抛异常
- HTTP 200
- 答案正常生成,读起来完全合理
- 只是没有联网
于是你的管线看起来健康得不得了,仪表盘每天更新,数字全是另一件事的数字。
自检方法(30 秒):拿一条只有最近才有答案的问题去问——比如你上个月刚发布的产品名、或者某个上周才出现的行业事件。如果模型答不上来或明显在编,这一路就没联网。用「今天是几号」这类问题是测不出来的,很多模型会用系统提示里的日期糊弄过去。
三、错点 2:引用字段五家五个样,「引用数」在归一化之前不可比
联网开通之后,第二个坑立刻到:每家返回引用的方式都不一样。
- 百度千帆要你额外打开
enable_citation(还有enable_trace)才给引用与过程信息; - Kimi 的检索由服务端执行,你拿到的是模型消化过后的结果,不是一份原始 SERP;
- 通义要在
search_options里配置才拿得到检索来源信息; - 火山方舟走 Bot API 时,引用的呈现方式和直接调模型完全不是一回事。
后果有三个,每一个都直接扭曲指标:
- 「引用数」不是同一个物理量。 有的返回的是「检索召回的条数」,有的是「最终答案里真正被采纳的条数」,还有的两者混在一起。把它们塞进同一列做跨引擎柱状图,图是好看的,含义是错的。
- 有的面给不了精确 URL。 这直接决定你能不能做信源归因——拿不到 URL,你就只能按站名做模糊匹配,而中文站名重名严重。
- 检索条数上限是你自己设的。 百度的
search_number/reference_number这类参数,你填多少,「引用数」就大概是多少。也就是说这个指标里有一部分是你自己的配置,不是引擎的行为。跨引擎比较时如果两边配置不同,比出来的差异是你造的。
工程上的处理办法:在存储层就把「引擎原始字段」和「归一化后的指标」分成两组字段,永不覆盖原始值;跨引擎的图表只画归一化后的、并在图注里写清归一化规则。指标分子分母怎么定义,见GEO 术语表和提问集设计。
四、错点 3:你测的是「开发者面」,用户在另一个面
这是自建方案整体性的局限,不是某一行代码的问题。
我们对豆包做过逐面对比实测:同一批问题,火山方舟 API 面的引用常在 4–8 条,手机 App 面常到 12–20 篇以上,而且两者引用的具体站点集合本身就不重合——不是「App 比 API 多几条」,是两套来源(完整方法与数据见实测:豆包的 API、网页、App 引用不是同一套)。
更结构性的问题是:中国市场里最大的那几个面,根本没有开发者接口。
| 用户实际在用的面 | 有没有对应的开发者 API | 自建 API 方案能覆盖吗 |
|---|---|---|
| 豆包 App | 无(火山方舟提供的是 Doubao 系列模型 API) | ❌ 留白 |
| 腾讯元宝 App | 无(腾讯云提供的是混元大模型 API,是模型服务,不是元宝那一面) | ❌ 留白 |
| 夸克 AI 搜索 | 无公开消费级面接口 | ❌ 留白 |
| 小红书「点点」 | 无 | ❌ 留白 |
| DeepSeek App / 网页 | 消费级侧有「联网搜索」,但那是产品功能,不等同于标准 API 端点行为 | ⚠️ 只能近似 |
| 百度 AI 搜索 | 千帆有 ai_search 端点,口径与 C 端界面未必一致 | ⚠️ 只能近似 |
这一列 ❌ 就是纯 API 自建在中国市场的天花板。 海外工具在中国的盲区也正是这一层(见海外 AI 可见度工具在中国的盲区)——区别只在于,你自己搭的话,这个盲区是你自己造成的,而且你知道它在那儿。
⚠️ 说明:要采 App 面,需要真机或云手机、账号与网络出口的隔离、以及长期的维护投入。本文不讨论任何绕过平台风控、伪装身份或规避反爬的具体做法——这里只陈述「存在这类工程量」这个事实,它是自建成本里最被低估的一项。
诚实的做法:如果你决定只做 API 面,就在报告的每一页标注「口径:开发者 API 面」。这不丢人,混着报才丢人。采购与验收侧怎么把「取数面」写死,见GEO 监测怎么写进采购需求书。
五、错点 4:采样次数和分母写在脚本里,而不是写在 schema 里
这一条 build-vs-buy 那篇从成本角度讲过(单次采样不是数据、模型每次生成都有随机性),这里只补工程实现上的那半句:
采样次数、会话状态、分母定义,必须是数据里的字段,不能是代码里的常数。
区别在哪:如果「每条问题跑 3 次」只是脚本里的一个 for i in range(3),那么半年后有人把它改成 5 次,你的历史曲线会在那一天出现一个无法解释的台阶,而且没有任何记录说明发生了什么。反过来,如果每条记录里都带着 sample_index、sample_total、session_isolated、prompt_set_version,那么口径变更是可查询、可回溯、可以在图上标注的。
最小字段建议:
| 字段 | 为什么必须存 |
|---|---|
prompt_set_version | 提问集一改,前后两期就不可比——这是最常见的「假趋势」来源 |
sample_index / sample_total | 采样次数变了要能查出来;聚合口径也依赖它 |
session_isolated | 是否新开会话/是否带历史上下文,直接影响答案 |
web_search_enabled | 见错点 1,这是全篇最需要留痕的一个布尔值 |
model_id(含版本号,不要用别名) | 别名会在你不知道的时候指向新模型 |
最后一条值得单独说:不要用 deepseek-chat 这类别名做长期监测的记录字段。别名是会被重新指向的——DeepSeek 官方就退役过别名,而别名一变,你的历史数据在没有任何代码改动的情况下就换了被测对象。存带日期或版本号的具体模型 ID。
至于「多少次才算数」「分母怎么定」,见提问集怎么设计;跑出来的数字算高算低,见提及率 18% 算高还是低。
六、错点 5:只存结果、不存原文——引擎一改版,整段历史作废
这是最工程化、也是我见过被跳过得最多的一条。
绝大多数自建方案的存储长这样:(问题, 引擎, 日期, 是否提及, 引用数)。干净、省空间、直接能画图。
然后引擎改版了。 曲线上出现一个台阶,你需要回答一个问题:是引擎的行为变了,还是我的解析逻辑对新格式失效了?
只存结果的话,这个问题无法回答。你没有原文可以重新解析,没有当时的请求参数可以复现,唯一的选择是把改版之前的数据全部作废、重新攒基线。而基线是要用月计的。
最小可回溯记录(在结构化结果之外额外存的):
- 完整原始答案文本(不是截断的、不是解析后的)
- 完整原始返回体(含引用/检索字段的原样 JSON)
- 请求参数快照:模型 ID、是否开联网、检索条数上限、temperature、工具声明
- 时间戳与采样序号
- 解析器版本号——这样「解析逻辑变了」和「引擎变了」才能被分开
第 5 条尤其容易漏。存了原文却没存解析器版本,你仍然分不清那个台阶是谁造成的,只是至少还能重跑。
成本对比很直白:原始答案按每条几 KB 算,一个中等规模的采集盘子一年也就几个 GB 的存储;不存的代价是引擎每改一次版,你的历史数据就归零一次。而 2026 年上半年,主流引擎的改版频率是以月计的。
七、搭完之后先跑这七条自检
按顺序过一遍,任何一条不通过,你的数字都还不能拿去汇报:
- 联网真的开了吗? 用一条「只有最近才有答案」的问题验(别用「今天几号」)。逐个引擎单独验,别假设统一封装生效了。
- 联网开关有没有被封装吃掉? 打印一次实际发出去的请求体,肉眼确认参数在里面。
- 引用字段归一化规则写下来了吗? 每个引擎的「引用数」到底是召回数还是采纳数,写进文档,不要留在某个人脑子里。
- 检索条数上限跨引擎一致吗? 不一致就不要画跨引擎对比图,或者在图注里标清楚。
- 模型 ID 存的是具体版本还是别名? 别名一律换成带版本/日期的具体 ID。
- 原始答案落库了吗? 抽一条三个月前的记录,看能不能重新解析出结果。不能,就是没落。
- 报告上标了取数面吗? 「口径:开发者 API 面」这行字必须在每一页上。
这七条里有五条是一次性的(做完就不用再做),但它们决定了后面所有数字的效力。先过这七条,再讨论提及率是多少。
八、那到底什么时候自建就够了
诚实的分界线,和写不写得动代码基本无关:
够用——三条同时成立:
- 你要的是一次性摸底,不需要跨周比较;
- 你接受口径是「开发者 API 面」,并在报告里标清楚;
- 你盯的引擎恰好有稳定的开发者接口。
这时候写脚本完全合理,一两天出结果,比走采购流程快得多。想先手动跑一轮更省事的,见怎么免费自查品牌在 AI 里有没有被提到。
不够用——只要出现下面任何一条:
- 你要回答「这个月比上个月好了没」(→ 口径漂移是你的主要敌人,不是 token 费);
- 你要覆盖 App 面(→ 这不是 API 能解决的问题);
- 你要跨引擎横比(→ 归一化本身就是一个持续维护的项目)。
这三条的共同点,和 build-vs-buy 那篇的结论是同一个:成本从「写代码」变成了「维护口径」。 该测哪几个引擎、别为「覆盖 12 个模型」多付钱,见该测哪几个 AI 引擎才够;国内跨引擎的整体方法论见国内 AI 搜索可见度监测指南。
常见问题(FAQ)
用 API 自己搭 GEO 监测,跑出来的提及率代表什么? 没显式开联网的话,代表「模型训练语料里有没有你」,不是「用户在 AI 搜索里会不会看到你」。前者你几乎无法通过内容工作改变,后者才是 GEO 要优化的对象。国内主流引擎的开发者接口,联网默认都不是开启状态。
为什么用 OpenAI 兼容 SDK 统一封装,联网就悄悄失效了?
开联网的参数在每家都是非标准参数(阿里云文档明写 enable_search 须走 extra_body),统一封装只认标准字段,会把它们序列化时丢掉。失败方式是最坏的那种:不报错、200、答案正常,只是没联网。
国内哪些 AI 引擎面根本没有开发者 API? 消费级 App 那一面基本都没有。腾讯云提供的是混元大模型 API,不等于元宝 App 那一面;豆包 App、夸克、小红书「点点」同理。纯 API 方案覆盖的是开发者面,而多数真实用户在 App 面。
同一个引擎,API 拿到的引用和用户看到的差多少? 我们对豆包的逐面实测:API 面引用常 4–8 条,手机 App 面常 12–20 篇以上,且站点集合不重合。只用 API 取数会系统性低估引用规模,也会误导信源优化的方向。
自建管线里最容易被跳过、事后最贵的是哪一步? 把请求参数快照和原始答案全文一起落库。只存结构化结果的话,引擎改版后你无法区分「引擎变了」和「解析器坏了」,历史数据只能整段作废。存储成本是几个 GB,不存的代价是几个月的基线。
什么情况下自建是够用的? 一次性摸底、接受「开发者 API 面」口径并标注、目标引擎有稳定接口——三条同时成立就够用。要跨周比较、要 App 面、要跨引擎横比,成本就从写代码变成维护口径了。
本文涉及的接口行为、参数名与默认值,均为各平台官方文档截至 2026 年 9 月 9 日 的公开表述,已逐条附链接。云厂商接口参数、模型支持范围与计费规则变动频繁,上线前请以官网当日文档为准。文中「豆包 API 面 4–8 条 / App 面 12–20 篇以上」为本站实测区间,方法见对应实测文;其余未标注为实测的内容均为方法论描述,不含未经核实的数字。
信息来源:火山方舟·联网内容插件功能说明、火山方舟·应用(Bot)API、火山方舟·对话(Chat)API、DeepSeek API 文档、Kimi API·联网搜索功能、阿里云百炼·大模型如何联网搜索、百度千帆·联网搜索、百度千帆·调用百度 AI 搜索、腾讯混元大模型、火山引擎开发者社区的自建监测通稿。
上面这七条自检,闻响 GeoEcho 是当成产品底线在做的:分引擎面标清口径(API / 网页 / App 真实档)、固定采样次数、原始答案与请求参数全量留档、跨改版保持可比。国内(豆包 / DeepSeek / Kimi / 通义 / 元宝 / 百度 AI)与海外(ChatGPT / Perplexity / Gemini)一起测。输入域名,先免费跑一次,看看你现在的底盘——就算最后你决定自己搭,这一次也能当成你的对照组。
常见问题
用 API 自己搭 GEO 监测,跑出来的提及率代表什么?
如果你没有显式打开联网检索,它代表的是「这个模型的训练语料里有没有你」,不是「用户在 AI 搜索里会不会看到你」。这两件事的差别是根本性的:前者是模型参数里的静态记忆,几个月才随版本变一次;后者是每次提问现场检索出来的,你上周发的一篇稿子就可能改变它。而国内主流大模型的开发者接口,联网检索默认都不是开启状态——火山方舟要把插件挂在「应用(Bot)」上走 Bot API,通义要传 enable_search,百度千帆要传 web_search 对象,Kimi 要声明 $web_search 内置工具。不做这一步,你搭的是一套「模型记忆监测」,不是 GEO 监测。
为什么用 OpenAI 兼容 SDK 统一封装几个国产引擎,联网就悄悄失效了?
因为开启联网的参数在每一家都是非标准参数,而 OpenAI 兼容层只认标准字段。阿里云百炼文档明确写了:enable_search 不是标准 OpenAI 参数,用 Python SDK 时必须通过 extra_body 传递。你若图省事写一个统一的 client.chat.completions.create(...) 包装所有引擎,这类参数会在序列化时被丢掉——而且不报错,请求照样 200 返回,答案照样生成,只是没有联网。这是自建方案里最隐蔽的一个失效点:管线跑得很健康,数字全是另一件事的数字。
国内哪些 AI 引擎面根本没有开发者 API?
消费级 App 那一面基本都没有。腾讯云对外提供的是混元大模型 API,那是模型服务,和用户打开腾讯元宝 App 看到的答案不是同一套;豆包 App、夸克 AI 搜索、小红书「点点」同理。也就是说,纯 API 自建方案在中国市场覆盖到的是「开发者面」,而绝大多数真实用户在 App 面。要采 App 面,需要的是真机或云手机、账号与网络出口隔离、以及持续的维护投入,这已经不是写脚本的活了。
同一个引擎,API 拿到的引用和用户看到的引用差多少?
我们对豆包做过逐面对比:同一批问题,火山方舟 API 面的引用常在 4–8 条,手机 App 面常到 12–20 篇以上,而且两者引用的具体站点集合本身就不重合——不是「App 比 API 多几条」,是两套来源。所以只用 API 取数会系统性低估引用规模,也会让你把优化重点押在错误的信源上。分面口径见我们那篇实测。
自建管线里,最容易被跳过、但事后最贵的是哪一步?
把每次采集的「请求参数快照」和「原始答案全文」一起落库。绝大多数自建方案只存了解析后的结构化结果(提到没提到、引用几条),没存当时用的模型 ID、是否开启联网、检索条数上限、采样序号、时间戳与完整原文。后果是引擎一改版,你无法判断曲线上的台阶是引擎变了还是自己的解析逻辑变了,历史数据只能整段作废。存原文的成本是几毛钱的存储,不存的代价是几个月的基线。
什么情况下自建 API 监测是够用的?
三个条件同时成立时够用:①你只需要一次性摸底,不需要跨周比较;②你接受口径是「开发者面」,并在报告里标清楚;③你盯的引擎恰好有稳定的开发者接口。这时候写脚本完全合理,一两天就能出结果。反过来,只要你要的是「这个月比上个月好了没」,成本就从写代码变成了维护采集口径——那才是自建与买工具的真正分界线,这笔账我们单独算过一篇。