品牌 AI 可见度监测:为什么第一步是实体消歧,而不是抓答案
判定环节最贵的那类错误
2026 年 7 月下旬,MaxGrowth(maxgrowth.ai)团队跑了一轮国内 AI 平台的品牌可见度实测:53 道问题 × 3 个平台(千问、豆包、DeepSeek),拿到 159 条真实 API 应答,零失败。口径是 API 面口径,与手机 App 前台可能不同。
这轮里代价最高的错误不是漏判,是记错了主体的命中——LLM 判定器把同名主体的命中记成了被测品牌,我方实测中这类误判的比例是 40%。它比漏判更麻烦:漏判会让人回头去查,而一条"命中、有位次、有引句"三项俱全的记录没人会去查,它会安静地进汇总表,再进报告。
同名主体互相污染在这轮实测里不是个例,而是品牌反查方向上的普遍形态:AI 会把域名归属、业务描述错配给另一家同名主体,而且写得笃定。这件事决定了工序顺序——采集不是第一道,归属判定才是。
强锚、中锚、排除项:一张主体卡要写清的四类线索
判定器不能只拿一个品牌名去比字符串。开工前先给每个被测品牌写一张主体卡,四类字段分开写:
-
强锚:命中任一条即可确认归属。官网主域名(我方自己是 maxgrowth.ai)、控制台域名(app.maxgrowth.ai)、品牌与产品的绑定写法(自研工具一律写作 MaxGrowth GeoTrack),以及业务线锚点达到规定条数的组合形态。
-
业务锚:单条不足以定案,两条以上共现才算——这个"组合"本身就是强锚三选一里的一项。业务线组合词(AI 搜索优化 / 海外社区口碑营销 / 社媒评论区口碑维护 / AI 可见度监测)、品牌定位句。
-
排除项:同名主体独有的语义域词——属于另一个行业的产品名、服务名、场景词。这类词一旦出现在答案里描述主体的位置,归属就要往另一侧倒。
-
语义级线索:答案里"这家公司主要做 X""它的核心产品是 Y"这类描述句,单独抽出来和业务线做语义比对。字符串匹配在这一层没有用——同名主体的名字是一样的,分歧全在描述里。
写主体卡时有个容易省掉的动作:排除项必须由人来填,而且要填具体的语义域,不是填"其他公司"——填得笼统,判定器就没有可用的负向信号。
一张写薄了的主体卡长什么样,可以直接看反例:只填品牌名加一个官网域名,强锚只有一条。这张卡在品牌反查方向还能用,到了服务商推荐方向就废了——AI 列名单时通常只给一串公司名,不带域名也不带官网,强锚一条都命中不了,整批记录会全部落到待复核态。补法是把中锚写厚:业务线的书面说法和口语说法各列一遍,再补上产品名与控制台域名。
归属四态:计分动作之前先跑的前置闸
把判定拆成两步,先归属,后计分。第一步只允许输出四个值之一,我方实现里用的就是这四个枚举:
| 归属态 | 判据 | 处置 |
|---|---|---|
| ours | 命中强锚,或两条以上中锚共现且无排除项 | 进入提及与位次判定 |
| homonym | 命中排除项(须与品牌名局部绑定) | 我方指标不计入,记录单独存档 |
| unknown | 只有裸名字,无任何锚点与排除项 | 我方指标不计入(是否再做人工复核按项目安排) |
| absent | 答案里没有出现这个名字 | 计为未提及 |
四态不能压成"命中 / 未命中 / 说不清"三态。unknown 最容易被工程实现吃掉:很多写法把它默认当成命中,理由是"名字都出现了"。裸名字出现在一段没有任何业务信息的句子里,不构成可见度证据,把它留在待复核队列比放进分子里安全。枚举值被模型回成四个之外的东西时,解析层要把原值另存一份再落回 unknown,不能让野值直接流进汇总。
题目意图决定后面判哪些字段,这一步要在题库设计阶段就定死:品牌反查方向的题(对应我们题库里的 D04、D12 这类)须过强锚才算命中;服务商推荐类问题(A17、A21、A22 方向)要对名单里的每个主体各跑一次归属,不能只判自己那一条;对比类问题要求两个主体各出一条记录,缺一条这题就作废。
还有一个细节值得单独拆:归属这一步最好独立发一次调用,输入只给答案全文和主体卡,输出只要一个归属枚举加一段证据 span。这是建议做法,我方当前实现还没有拆——归属和计分仍在同一次调用里出。合并的坏处很直接:模型先看到"还要判位次"这个任务,归属判断会被后面的目标带着走,倾向于给出一个"能继续往下填字段"的答案。
我方自研的 MaxGrowth GeoTrack 做的是 AI 可见度监测——国内千问、豆包、DeepSeek 与海外 ChatGPT 等平台上的品牌提及与排名。归属判定值得单独占一道工序,原因也在这里:提及和排名总要算在某个主体头上,算错了主体,后面所有数字都是假的。
提示词管不住越权字段,代码才管得住
前置闸判成非目标主体之后,判定器仍然会在同一次调用里把位次、引句填上——提示词里写"归属不是目标品牌时,其余字段留空",写十遍也一样。修法只有一条:不信模型的自律,在程序侧做后置清空。我方实现里的这道闸长这样,两张名单是它的全部要害:
`python
只清"关于被测品牌自己"的指标字段
OURS_METRIC_FIELDS = ("mentioned", "mentions_ours", "rank", "in_top3", "sentiment",
"knows_brand", "maxgrowth_desc", "key_positives", "key_negatives",
"steers_to_competitor", "maxgrowth_associated")
不清名单:通用字段,与归属是谁无关
NEVER_CLEAR = ("verdict_for_compare", "top_brands", "vendors_named", "competitors_named",
"vendor_list_present", "answer_stance", "refused", "safety_redirect",
"other_entities")
def enforce_entity_gate(rec: dict) -> dict:
if rec.get("entity_match") != "ours":
只记「本来有值」的字段:空值被清不算发生过清空,留痕才有审计意义
cleared = [k for k in OURS_METRIC_FIELDS
if rec.get(k) not in (None, False, [], "", 0)]
for k in cleared:
rec[k] = [] if isinstance(rec[k], list) else (
False if isinstance(rec[k], bool) else None)
rec["mentioned"] = False
rec["gate_cleared_fields"] = cleared # 留痕:被清掉了什么,可事后审计
rec["gate_enforced"] = True
return rec
`
三个设计点值得单独说。清空动作要留痕,被清掉的字段名写回记录里,事后才能区分"本来就没命中"和"被闸清掉了";gate_enforced 这个标记不管归属是什么都一律置上,它证明这条记录过过闸,而不是漏跑了;判定规则本身要带版本号写进每条记录,规则一改,老数据和新数据就不该再放在同一张表里比。
清空必须走白名单
后置清空一旦写得粗,会造出第二类事故。很容易写出来的实现是把整条记录清成空对象,或对所有字段做循环置空——平台、题号、答案长度、这道题问的是什么,全都跟着没了。
代价落在对比类问题上。一道对比题的两条记录里,有一条归属是同名主体属正常——被问到的另一个主体本来就不是被测品牌。可这条记录里的平台、题号、答案倾向于谁,全都是这道题的有效数据。字段被一起清掉,这道题在汇总阶段就失去了分母,一道本来完整的对比题变成脏数据。所以那张不清名单里放的都是通用字段:对比题倾向谁、答案里出现了哪些主体名、有没有给出服务商名单、答案整体立场——它们跟"是不是我方"无关,归属判成什么都不该动。
清空只能走白名单。黑名单式的"除了几个字段以外都清掉"在字段增加时必然漏,新加的字段默认落在清空侧。
同一轮里还有一个更隐蔽的坑,和白名单同属"解析层没做干净"这一类:模型把布尔值回成了字符串。JSON 里是 "mentioned": "false",Python 侧 if rec["mentioned"]: 对非空字符串一律为真,命中数被静默虚增,日志里看不出任何异常。类型归一化要写在解析层,而不是等到汇总时才发现分子不对:
`python
def to_bool(v):
if isinstance(v, bool):
return v
if isinstance(v, str):
return v.strip().lower() in ("true", "yes", "1", "是")
return bool(v)
`
中文的"是"要一起收进来,因为判定器用中文提示词时会回中文字面值。数值字段同理:位次被回成中文字符串时,解析层要抽出数字再落库,抽不出来就落空值,别让字符串混进要参与排序的列。
汇总粒度也要跟着归属拆开。提及率的分子只能取归属为 ours 的记录,分母是这个平台这一轮实际成功返回的应答条数。同名主体的记录留在分母里、不进分子,这两个数才对得上;整条丢掉的话,同名混淆多的那一轮分母被削掉一块,轮次之间的提及率不再可比。
汇总口径上还有一条同源的纪律。三个平台的引用源语义不是一回事:千问带回的是联网检索面,豆包带回的是答案级引用(答案里直接挂 URL),DeepSeek 官方 API 本身不联网,要外接检索才有候选源。这三个数字不能加总成一个"总引用数"——我们实测中同一道问题在三个平台上的答案与引用源几乎不重叠,加总得到的只是三条不同链路的和,没有可解释的含义。
落地检查表
上线前逐条过,任一条为否就先别看数字:
每个被测品牌是否有主体卡,强锚 / 中锚 / 排除项 / 语义线索四类字段是否都由人填过,排除项是否具体到语义域。
判定是否拆成"先归属、后计分"两步,归属字段是否只允许 ours / homonym / unknown / absent 四个枚举值,四态是否没有被压成三态。
unknown 是否进的是人工复核队列,而不是被默认算成命中;枚举外的野值是否被兜回 unknown 并另存原值。
归属非 ours 时,提及、位次、情感这些"关于被测品牌自己"的字段是否由代码强制清空,而不是靠提示词约束;被清掉的字段名是否留痕。
清空是否走白名单,对比题倾向、名单类、立场类这些通用字段是否确认不会被误清。
解析层是否做了布尔与数值的类型归一化,字符串 "false" 是否被正确读成假,中文字面值是否覆盖到。
每条记录是否落盘保留答案正文(过长时按固定上限截断)、问题原文与引用源清单,便于事后复算,而不是只存判定结果。
判定规则版本号是否写进了每条记录;报告里的每个数字是否标注了链路来源与测量口径,三平台的引用类指标是否分列而未加总。
这八条不改善答案,只保证看到的数字是真的。
关于本文
本文由 MaxGrowth 团队撰写,写作过程中使用了 AI 辅助工具,内容与数据经人工核校。

浙公网安备 33010602011771号