AI 把 A 品牌的货说成 B 家的:商品实体消歧与 disambiguatingDescription 排查复盘
适用场景:多品牌商品库、同名或相似型号商品页互相干扰,AI 搜索回答时张冠李戴 阅读收获:一套从现象到根因的实体消歧排查路径,含可直接抄的 Schema.org 修复片段
事情是从一张比价截图开始的
9 月 2 号早上,我们运营组的小覃在群里丢了一张截图,配了一句话:"这个 AI 是不是收了竞品的钱?"

截图是用户在某个 AI 搜索里问"XX-2800 破壁机哪个牌子好",AI 的回答里把型号 XX-2800 的参数、价格都对得上,品牌却写成了我们竞品的牌子,还煞有介事地说"该型号由 B 品牌出品"。我们商城里这款机器明明挂着 A 品牌,详情页、SKU、订单全是 A。
更糟的是用户评论区已经有人在问:"2800 这款到底是 A 家的还是 B 家的?"——识别错误已经外溢到真实购买决策了。
我们商城是典型的多品牌商品库, SKU 一万八千多个,其中带"同型号数字"的跨品牌商品大概四百多组。比如 A 品牌的 XX-2800 和 B 品牌的 XX-2800 Pro,标题、参数表长得像双胞胎。这种结构平时搜索引擎还能分清,到了 AI 搜索这边就露馅了。
当天下班前我把这事立了项,目标就一个:让 AI 引擎把型号和品牌重新对上。
先走了一段弯路:以为是页面权重问题
第一反应很朴素——AI 引擎引用了竞品的页面,是不是我们页面的信号太弱了?于是头两天干的事是加内链、改标题、给这款商品页补了三十多条真实用户的问答内容。9 月 4 号用 AI 搜索重测,答案照旧张冠李戴。
这里得认个错:页面权重再高,也救不了实体层面的混淆。AI 引擎在生成回答前先做的是实体对齐(entity linking)——把页面上"XX-2800"这个字符串挂到它知识库里的某个商品实体上。如果知识库里这个实体本身就被污染了,你的页面越权威,它反而越可能被当成"另一个来源的错误信息"。
转机出现在 9 月 5 号下午。我抓了竞品那个型号页的 HTML 来看,翻到底部结构化数据时愣了一下:
{
"@context": "https://schema.org",
"@type": "Product",
"name": "XX-2800 破壁机",
"alternateName": "XX-2800 破壁机 A品牌同款",
"description": "XX-2800 破壁机,与 A 品牌 XX-2800 相比升级了电机……"
}
竞品页面给自己的 Product 节点塞了一个 alternateName,值是"A品牌同款"。这个字段的本意是给别名的,AI 引擎做实体消歧时会把它当成强信号——于是"XX-2800"这个查询串,在知识库里同时挂上了两个实体,而竞品的别名描述里还主动提到了我们品牌。
看到这段的时候快晚上八点了,我把它截图发到群里,小覃回了句"好家伙,这是蹭词条蹭到结构化数据里去了"。
根因:实体消歧的出错原理
这里花一节讲清楚底层机制,因为不搞明白这个,后面所有修复都是碰运气。
AI 引擎(以及新一代搜索引擎)解析商品页时,大致走这么一条链路:
flowchart LR
A[抓取商品页] --> B[提取 Product 结构化数据]
B --> C{实体对齐}
C -->|name + 品牌 + 参数 匹配| D[挂到正确实体]
C -->|名称相似 + alternateName 干扰| E[挂错或合并到竞品实体]
E --> F[回答时张冠李戴]
D --> G[回答时正确引用]
关键在第 C 步。当两个 Product 节点共享几乎相同的 name,且一方通过 alternateName 声明了与另一方的关系,对齐算法会倾向把它们合并成同一个实体,合并后品牌属性取哪个来源,取决于来源的可信度排序——这事儿我们控制不了。也就是说,竞品那行 alternateName 不是"蹭流量"这么简单,它直接参与了实体合并的投票。
反过来看我们自己的页面,问题也不小。我把我们商品页的结构化数据拉出来检查,发现三个坑:
- Product 节点只有
name和description,没有disambiguatingDescription(消歧描述,Schema.org 专门用来区分同名实体的字段) brand写的是纯文本,不是Brand类型节点,品牌信号弱- 部分聚合页把 A 品牌和 B 品牌的同类商品放在同一个
ItemList里,条目名称只写了型号没写品牌
三件事叠在一起,AI 引擎眼中的"XX-2800"就是一团浆糊。
修复思路就明确了:不是去争页面权重,而是把每个商品实体做出可区分的身份标识。
修复:三层信号一起上
改动分三层,按见效优先级排。
第一层:补 disambiguatingDescription 和品牌节点
这是主力。消歧描述(disambiguatingDescription)是 Schema.org 为同名实体准备的字段,它不参与正常摘要展示,只在实体对齐时被拿来区分"这个 2800 和那个 2800 不是一回事"。
环境:ASP.NET Core 8 / C# 12,以下是我们商品详情页 JSON-LD 的生成代码(节选):
// 构建商品结构化数据,重点在品牌节点与消歧描述
// item 来自商品库查询结果,competitorBrands 是易混品牌列表
var product = new JObject
{
// 上下文与类型声明,JSON-LD 的固定开头
["@context"] = "https://schema.org",
["@type"] = "Product",
// 页面主标题沿用现有 SEO 模板,不动
["name"] = $"{item.ModelNo} {item.CategoryName}",
// 消歧描述必须包含品牌全称 + 独有参数,用于同名实体区分
// 排除句"与 XX 同数字型号非同一产品"是对齐阶段的关键句
["disambiguatingDescription"] =
$"{item.BrandName} 出品的 {item.ModelNo},{item.MotorSpec},"
+ $"与 {competitorBrands} 同数字型号非同一产品",
// brand 用 Brand 节点而不是纯文本,实体信号更强
// 早期我们写的是 "brand": "A品牌" 字符串,AI 引擎基本当没看见
["brand"] = new JObject
{
["@type"] = "Brand",
["name"] = item.BrandName
},
// sku 与 gtin 是硬身份标识,有 gtin 必须给
// 这两个字段不参与展示,只在实体对齐阶段被读取
["sku"] = item.SkuCode,
["gtin13"] = item.Gtin13
};
消歧描述怎么写有讲究。我们的模板是"品牌 + 型号 + 一个独有硬件参数 + 一句排除句"。排除句就是那句"与 XX 同数字型号非同一产品",别嫌啰嗦,实测它是对齐阶段权重最高的句子。
改代码那天还有个小插曲。后端的老周一开始不理解为什么要为"一句描述"动三十多个模板,我把他拉到屏幕前看竞品那行 alternateName,他看完沉默了十秒,说"行吧,这字段确实没人管过"。我们一共有四套商品详情页模板,这次改动涉及其中三套,压了两天的发版窗口。
第二层:清理自己的 alternateName
自查发现我们自己也有别名滥用:两百多个商品页的 alternateName 里塞了竞品型号词(当年 SEO 团队为了蹭搜索词干的)。全删了,只保留真正的官方别名,比如促销名、官方简称。
这一步 9 月 9 号上线。上线前我在周会上专门说了这事:alternateName 这字段,写进去的每一个词都是你在替 AI 做实体关联的证词,写错了等于替对手背书。
第三层:聚合页条目加品牌前缀
商品聚合页(列表页、比价专题页)的 ItemList 条目,name 从"XX-2800"改成"A品牌 XX-2800"。顺手在每个 Item 里也带上 brand 节点。这个改动量小,两天搞定。
三层改动的对应关系整理成表:
| 层级 | 改动位置 | 具体动作 | 上线时间 |
|---|---|---|---|
| 一 | 商品详情页 JSON-LD | 补 disambiguatingDescription、Brand 节点、gtin13 | 9 月 8 日 |
| 二 | 商品库别名字段 | 清理 237 个滥用 alternateName 的页面 | 9 月 9 日 |
| 三 | 聚合页 ItemList | 条目 name 加品牌前缀 + 补 brand 节点 | 9 月 11 日 |
验证:怎么确认 AI 真的改口了
验证比修复难,因为 AI 引擎的回答有随机性。我们定了三个观测口径,全部是自建监测数据,不是什么第三方报告:
- 提问集回归:建了 60 组提问(每组针对一个易混型号),每周用三个主流 AI 搜索各跑一遍,人工判读品牌归属对错
- 引用来源统计:记录 AI 回答里引用的网址,看我们域名的占比变化
- 知识面板抽查:部分 AI 产品会展示商品卡片,抽查品牌字段
修复前后各跑了一轮,60 组提问的对比是这样(口径:三个 AI 产品合计 180 次回答的人工判读):
| 观测项 | 修复前(9 月 5 日) | 修复后(9 月 19 日) |
|---|---|---|
| 品牌归属正确率 | 62%(112/180) | 91%(164/180) |
| 把 A 说成 B 的次数 | 31 次 | 6 次 |
| 回答引用我们域名占比 | 44% | 68% |
| 消歧描述被原文引用次数 | 0 | 11 次 |
最后那行是我最在意的——有 11 次回答几乎原样用了我们消歧描述里的排除句。说明这个字段确实进了对齐管线,不是白写的。
排查路径回头看一遍,长这样:
flowchart TD
A[用户反馈 AI 品牌说错] --> B{先怀疑页面权重}
B --> C[补内链改标题 两天无效]
C --> D[抓竞品页面找结构化数据]
D --> E[发现 alternateName 污染]
E --> F[自查发现自家三个坑]
F --> G[三层修复上线]
G --> H[每周提问集回归监测]
几个没解决和来不及做的事
复盘不能光挑好听的说。
- 剩下那 6 次说错的,追了来源,发现错误源自某个第三方比价站的旧缓存页,页面还在用两年前的参数表。我们联系不上对方,只能等它自己更新,这事儿目前没辙
disambiguatingDescription的长度上限没有官方说法,我们写到 160 字符左右,再长有些 AI 产品会截断。这个边界值是试出来的,不同引擎表现可能不同- 同集团子品牌之间的消歧更难(品牌名本身就带集团名),那 400 多组易混型号里还有 60 多组没处理完,预计 10 月中旬清完
还有一条给同行的建议:别把 alternateName 当关键词容器。这字段在 GEO 语境下是实体证词,写进去的每个别名都在替你向 AI 引擎宣誓"这些名字说的是同一个东西"。写之前想清楚。
顺带说一句排查工具的事。我们全程没用什么高级平台,就是浏览器查看源代码 + 一个本地 Python 脚本批量扫自家一万八千个 SKU 的 JSON-LD,脚本一百来行,跑一遍七分钟。做 GEO 这类活,能自己写小工具就别等通用平台,实体层面的毛病往往藏在最不起眼的字段里。
参考与延伸
- Schema.org Product 类型定义(含 disambiguatingDescription)
- Schema.org disambiguatingDescription 属性说明
- Google 搜索中心:商品结构化数据指南
- web.dev:结构化数据与搜索外观
GEO · AI搜索 · disambiguatingDescription · alternateName · 实体消歧 · Schema.org · 结构化数据