53 道题问遍千问、豆包、DeepSeek:三家「联网」根本不是一回事

题目 53 道,平台 3 个,一次跑完拿到 159 条应答,零失败。测量时间 2026 年 7 月下旬,执行方是 MaxGrowth(maxgrowth.ai)团队。这批数据要回答的问题只有一个:三个国内 AI 平台在"联网"这件事上,返回给调用方的是不是同一种东西。

结论是:不是。三条链路的语义各不相同,把它们的引用源统计并进一张表相加,得到的数一定是错的。下面按设置、逐平台结果、再讨论的顺序写。

实验设置与判定口径

53 道题一次冻结,跑批期间不改动、不增删。题目按提问形态分层,包含服务商推荐类、品牌反查类、方法与选型类几种,目的是让每种形态各自有足够样本,而不是把所有提问写成同一个句式。冻结的理由是题面一改,前后两次的数据就不能放在一起看——AI 的回答本身就有波动,再叠加题面变化,任何差异都归不了因。

每道题在三个平台各发一次,一条应答落一行 JSONL。落盘的不是原始返回体,而是解析后的一组固定字段:平台、问题原文、题目类型与标签、题号、判定档位、几个评估开关位、判定规则的版本号,加上答案长度、答案正文(截断到 8000 字符)、200 字摘录、引用源数组、判定结果;这条跑挂了就改存一条错误信息。

有几样东西没有留档,写报告时得记住它们不存在:出口与传输方式、单次耗时、模型配置、超时值、重试次数。所以一条数据看着异常时,想回头查它是不是走了另一条出口、耗时是不是偏离同批,这批记录支持不了——把传输层元信息一并落盘是建议做法,当前实现还没做。

断点续跑的键是问题文本加平台名拼成的字符串,不是题号加平台;已经有判定结果、且没有错误的记录才跳过。写入方式是追加,同一个键跑过两次就会留下两行,没有后写覆盖先写的合并逻辑,统计前得自己去重。

口径必须先说清:这批数据是 API 面口径,与手机 App 前台可能不同。三条链路分别是——

  • 千问:DashScope 接口打开联网检索

  • 豆包:方舟 responses 接口挂 web_search 工具

  • DeepSeek:官方接口本身不联网,由外接的第三方检索拼装上下文后再问

判定分两步,顺序不能颠倒。第一步是实体消歧闸,输出四种状态之一:是我方、是同名主体、无法判断、答案里根本没出现。判成"是我方"要命中强锚,三种强锚任一命中即可:① 答案里出现我方域名;② 答案描述的业务方向命中我方业务锚两项以上的组合;③ 产品名以「MaxGrowth GeoTrack」这种绑定形态出现(我方做 AI 可见度监测的产品)。裸品牌词单独出现不算——既没有域名也没有业务描述时记为无法判断,不计入命中。反向也一样明确:答案里带上同名主体的特征描述,直接判同名主体,不计入我方任何指标。第二步才判提及与位次,而且只有第一步判成"是我方"才继续往下判。

顺序颠倒的后果很直接:先数品牌词、后做消歧,会把同名公司的曝光算到自己账上。品牌反查类问题上,AI 把域名归属和业务描述错配给另一家同名公司,在这批数据里是普遍现象,不是个别噪声。

千问返回体里多出来的那一层

打开联网检索之后,返回体里除正文之外多一段检索信息:search_info.search_results 是一个数组,每条带 site_name、title、url、index。拿到这层数据的第一反应容易是"这就是引用源",但它不是。

它是检索面——模型这一轮看过的候选页面集合。答案里哪一句来自哪一条候选,返回体没有给出对应关系。所以这条链路只能回答一类问题:"哪些站进了候选池";它回答不了"哪句话被哪一页支撑"。

我方实测中,这条链路检索面里出现频次靠前的域名包括知乎专栏、IT之家、博客园、搜狐、CSDN。这里只报频次靠前,没有算过占比;出现在 AI 答案中不代表我方对其服务的评价。

有一个常见误读要单独记一笔:把检索面的条数当引用次数统计,会得出"某站被引 N 次"的结论,而那 N 次里有一部分内容,一句话都没进答案。这个偏差事后修不了,只能一开始就把两层分开记账。

如果确实要句子级的出处,这条链路上只有两条路,而且都有额外成本。一是把检索面里的页面正文抓回来,用文本相似度把答案句子对回页面,误差自己承担,相似度阈值定多少全凭手感。二是改问法,直接要求模型在答案里标出处,但那样测到的已经不是它的默认行为。我方这批两条都不走,这条链路的数据只当候选面用,报告里也只写"进池",不写"被引用"。

豆包把 URL 挂在答案里

方舟这条链路给的是答案级引用:URL 出现在答案文本的位置上,能对到具体句子。返回结构上它落在 annotations 里,类型是 url_citation,逐条能解析出标题、URL 和站点。

这一层的分量比检索面重,原因不在数量而在性质。检索面里的页面是"模型看过",答案级引用是"模型采纳并且愿意署出处"。放到内容分发上看,前者只说明进了池子,后者说明进了答案。

我方实测中,这条链路的引用里出现频次靠前的包含 B2B 信息发布站、行业垂媒,以及火山引擎开发者社区这类开发者站点。同样只报频次靠前,不报占比。

记账上要区分两个数:一条应答里出现了几条引用,以及一个站点在 53 道题里被采纳过多少次。前者受答案长度影响很大,长答案天然挂得多,拿它做站点排序会把话多的题算重;后者才是对内容分发有用的量。另外空引用要单独留一类:模型判断这题不需要检索,和检索了但一条都没采纳,单看落盘的引用数组这两种情况长得一样,都是空数组,都不能当成解析失败丢掉,否则统计里会同时少掉"没检索"和"没采纳"两种真实状态。方舟的返回里其实带有检索调用记录和检索次数,拿这两样能把两种状态分开;我方这批只把引用数组落了盘,没存它们,所以事后分不了——把检索调用信息一起落盘是建议做法,当前实现还没做。

工程上这条链路有个硬要求:必须流式收流。非流式取回要长时间空等一个完整响应,连接容易在中途被掐;流式一直有字节在动,等到"响应已完成"这个事件再把完整响应整体解析出来——注意是整体解析,不是边收边把正文和引用分成两个缓冲区各自累加。

第三条链路:接口不检索时拿到的是候选

DeepSeek 官方接口本身不联网。要让它回答需要新鲜信息的题,只能自己在前面接一层检索,把结果拼进上下文。

这么做之后拿到的东西,严格说连"模型看过的完整候选"都不算——喂进去的那几条是我方检索器挑的,而系统提示写的是让模型基于这些检索结果、也可以结合自身常识回答。也就是说,它既不是平台自己的检索面,也不是一个封闭的证据集合:答案里的某句话来自喂进去的材料还是来自模型本身的知识,返回体里区分不了。所以这条链路的引用源统计,测量对象很大程度上是我方的检索策略,不是平台的偏好。

这批实测里,这条链路的候选中靠前的包括 IT之家、博客园、搜狐、腾讯新闻、知乎。这组数据只能自己跟自己比:换一个检索器、改一下往上下文里塞几条,名单就会变。把它拿去跟前两条链路做横向排名,在方法上不成立。

这条链路上有三样东西会直接改写结果:检索器本身、查询词怎么定、往上下文里塞几条。三者任何一个动了(建议固定下来并记版本),得到的候选名单就换了一份。我方当前的做法是:查询词不做改写,把原题原样发给第三方检索接口;取回条数在代码里是固定值。这三项都没有逐条写进记录——落盘的只有引用源数组。后果是,之后再跑一次,如果中间换过检索器或改过条数,单看结果文件连自己跟自己比都比不了:名单变了,分不清是 AI 变了还是自己的检索层变了。把这三项连同结果一起记下来是建议做法,当前实现还没做。

一张语义表,和它对内容分发的约束

| 链路 | 数据来自哪里 | 语义 | 能回答什么 | 回答不了什么 |

|---|---|---|---|---|

| 千问 | search_info.search_results | 联网检索候选面 | 哪些站进了候选池 | 哪句话由哪一页支撑 |

| 豆包 | annotations 里的 url_citation | 答案级引用 | 答案采纳了哪些出处 | 模型看过但没采纳的还有哪些 |

| 外接检索链路 | 自建检索层的返回 | 我方投喂的候选 | 我方检索策略的覆盖面 | 平台自身的站点偏好 |

三列的生成机制、分母和口径都不一样,任何"三平台合计被引 N 次"的说法,都是把三种东西加在了一起。

同题跨平台比对之后还有一条更硬的观察:同一道题在三个平台上,答案措辞和引用源几乎不相交。这批只做了逐题人工比对,没有算重叠率,所以只报"几乎不重叠"这个定性结论。对内容分发的含义是——把一份内容投一个站、期待三个平台同时收进去,在这批数据里找不到依据。

另外两条观察可以一起放进讨论。一是"服务商推荐"类问题上,三个平台给出的名单高度分裂,没有哪一家在三处都稳定出现。二是我方一篇新上线的文章在数日内进入了千问的检索面。这是单条观察,不能推广成"所有内容都能几天收录"。

落到具体动作上,这批数据支持三条:站点清单按链路分开维护,不做合并排序;一篇内容的分发目标按链路选站,而不是按"看起来权重高的站"选;任何跨平台汇总的数字在报告里必须拆列到链路,拆不开的就不写进报告。

下一轮跑批,我方会把这三列各自单独记账、各配一份站点清单,并把每条链路的取值一起记下来。把它们并成一列做加总,是这批数据里最先被否掉的做法。

关于本文

本文由 MaxGrowth 团队撰写,写作过程中使用了 AI 辅助工具,内容与数据经人工核校。

posted @ 2026-07-28 19:21  MaxGrowth  阅读(3)  评论(0)    收藏  举报