品牌方现在最焦虑的事情之一,是用户在AI搜索里根本搜不到自己。这不是危言耸听。身边越来越多的用户,已经习惯打开生成式引擎直接问“XX面膜敏感肌能用吗”“XX和YY哪个更适合油皮”,而回答这些问题的不是品牌官网,也不是电商详情页,而是大模型基于海量内容拼接出来的摘要。传统SEO那套“关键词排名+外链+TDK”的打法,在生成式引擎面前正在失效。我们做了一套GEO系统,本质上是把品牌方碎片化的内容整理成一张品牌知识图谱,再通过RAG链路把这张图“喂”给大模型,让它在回答问题时主动引用品牌方的事实信息。这篇文章把整个系统的技术架构和工程实践拆开讲一遍,包括为什么选“图谱+RAG”的组合、每个模块到底怎么落地、以及我们踩过的坑和总结的经验。
1. 先搞清楚GEO到底解决什么问题
1.1 传统SEO与GEO的差别
先别急着聊技术,得把GEO这套东西要解决的问题说清楚。我们说的GEO,全称是Generative Engine Optimization,也就是面向生成式引擎的优化。它不是传统SEO的升级版,而是另一套游戏规则。
传统SEO优化的对象是搜索引擎的结果页,品牌方想尽办法让自己的页面排到首页。考核指标是关键词排名、点击率、收录量、外链数。生成式引擎来了之后,用户根本不翻结果页,而是直接看AI生成的一段答案。这段答案从哪来?模型从训练知识、当前网页、知识库片段、以及其他内容源里综合出来的。品牌方要做的,不再是“让网页排名靠前”,而是“让AI在生成答案时把我们的信息当作事实来用”。
这两者有一个本质差别:传统SEO可以做“标题党”,可以堆关键词,因为用户点了标题之后,内容好不好是后话。GEO不一样,AI会真的读取内容并提炼事实,如果你的页面信息互相矛盾、没有结构化表达、缺乏可验证细节,AI就不太可能引用它。换句话说,传统SEO关心的是“被看到”,GEO关心的是“被引用”。
1.2 品牌知识图谱在整个链路里扮演的角色
那品牌知识图谱在这套系统里是什么位置?一句话:它是内容的“事实基准盘”。
一个品牌的内容散落在各处。官网产品页、公众号推文、电商详情、用户评论、客服FAQ,这些内容格式不同,发布时间不同,甚至口径都不同。直接把这些非结构化文本一股脑扔给大模型做RAG,会出现两个问题。第一,相互矛盾的文本会被同时召回来,模型不知道该信哪个。第二,长尾问题覆盖不足,很多用户问法在原文里找不到对应的段落,语义检索也不一定能补救。
知识图谱的作用,是把散乱内容里的关键实体和关系抽出来,形成一张结构化的网络。比如“产品A”“成分B”“适用肤质C”“认证资质D”“售后政策E”,以及它们之间的“包含”“适用于”“获得”“区别于”关系。有了这张网,系统在面对用户提问时,可以先走图谱,快速定位品牌相关的实体和关系,再用这些结构化信息去约束和指导检索与生成。
图谱负责“确定性知识”,RAG负责“开放性的长尾内容”。两者不是替代关系,是配合关系。图谱相当于公司的账本,RAG相当于资料室,大模型生成答案时既要有账本上的准确数字,又要有资料室里丰富的上下文。
2. 系统整体架构与分层设计
2.1 六层架构总览
这套GEO系统的整体架构,我们内部按六层来划分,每一层的职责相对独立,替换成本可控。
- 数据接入层:对接官网页面、公众号文章、电商评论、客服工单、离线文档等来源,负责增量采集和全量同步。
- 内容加工层:清洗HTML、去掉噪声信息(导航、广告、脚注),做文本分块、格式归一化、数据脱敏。
- 知识构建层:基于LLM做实体抽取、关系抽取、属性补全,形成三元组并写入图数据库;同时做冲突消解和人工审核。
- 检索召回层:向量检索、关键词检索、图谱查询扩展、混合融合、重排,最后形成候选片段集合。
- 生成服务层:负责构造Prompt、调用生成模型、输出带引用的答案,同时做安全过滤和兜底策略。
- 评估监测层:评测集评估、线上问答质量监控、数据新鲜度巡检、成本统计。
这个分层的核心思路是:数据、知识、检索、生成必须解耦。一开始最容易犯的错是,为了让demo跑通,把知识库和检索逻辑写在一个脚本里,后面加数据源或者换模型时,整个链路都得跟着动。分层之后,每一层只对上层提供接口,内部随便改。
2.2 为什么采用“知识图谱+向量库”双底座
架构层面很多人会问:既然已经有了向量库,为什么还要费劲去建知识图谱?直接把你所有内容切块向量化,用RAG不就行了吗?这确实是大多数团队最容易走通的路径,但我们在实际项目中发现了它的天花板。
纯向量库的问题有三个。一是多跳问题处理不好。用户问“A和B都含有C成分,那A适合敏感肌吗”,如果A的关键信息页没有直接写“敏感肌适用”,但图谱里有“A含C”“C被认证为低刺激”“C推荐敏感肌使用”这些关系,向量检索很难把这些跨来源线索串起来,图谱却可以用一条路径查询完成。二是口径不一致。向量检索会把矛盾内容同时召回,而图谱在构建时已经做了冲突消解,给的是统一的事实。三是运营成本。品牌方想调整某个产品参数,在向量库里得重新切块、重新索引;如果图谱里有这个属性,改一个节点值就行,下游自动生效。
当然,图谱也不是万能的。品牌用户的提问变化多端,很多是开放式描述,图谱没法覆盖所有表达方式。所以最终形态是双底座:图谱负责确定性的实体、属性和关系,向量库负责承接非结构化的语义内容;查询时先走图谱做实体链接和查询扩展,再进向量库做候选召回。
2.3 一个典型请求的处理时序
拿一个真实场景举例。用户问:“你们家那款修护面霜到底能不能给孕期用?”
系统收到问题后,流程大致是这样:
- Query理解模块先做实体识别,识别出“修护面霜”这个品类,可能对应图谱里的具体产品节点。
- 图谱查询返回该产品的成分表、功效宣称、适用人群、资质信息,以及相关的官方说明片段。
- 系统根据图谱返回的实体和属性,扩展生成若干个检索子查询,比如“修护面霜 孕期”“修护面霜 成分 安全性”等。
- 这些子查询同时进入向量库和关键词检索引擎,进行混合召回。
- 召回结果进入重排模型,去掉与问题无关的噪声片段,保留Top 5到Top 8个高相关片段。
- 生成服务层把这些图谱三元组和检索片段拼进Prompt,要求模型只基于这些上下文回答,并给每个关键事实标注引用编号。
- 输出答案,同时附上引用的文档列表,前端可以展示“信息来源”。
整个链路看起来不复杂,但每一层都有不少工程上的坑,下面挨个说。
3. 品牌知识图谱的构建细节
3.1 实体与关系的设计
图谱构建的第一步,是定义本体。我们服务的对象是品牌方,所以实体类型围绕“品牌”展开,而不是泛泛的通用知识图谱。
实体类型大概是这几类:品牌、产品线、单品、成分/原料、功能/功效、适用人群、资质/认证、服务政策、内容载体。关系类型也相对固定:产品线属于品牌,单品属于产品线,单品含有成分,成分带来功效,功效适用于人群,单品获得资质,品牌提供服务政策,内容载体承载某个单品的官方详情。
| 实体类型 | 举例 | 关键属性 |
|---|---|---|
| 品牌 | 某护肤品牌 | 品牌名、定位、官方渠道 |
| 产品线 | 某系列 | 系列名、上市时间、目标人群 |
| 单品 | 某款修护面霜 | 规格、价格、备案号、核心卖点 |
| 成分 | 某保湿因子 | 浓度、安全性、来源 |
| 资质/认证 | 某检测报告 | 认证机构、有效期、适用范围 |
关系表建立之后,抽取时就不需要让模型自由发挥,而是限定在预设的schema里,这也方便后续的查询和校验。
3.2 基于LLM的批量抽取流程
图谱的构建,我们用了“LLM抽取+人工抽检”的方式,而不是完全靠NLP正则。原因很简单:品牌内容的表达太活了,同一个成分,官方文案可能叫“专利成分X”,用户评论里叫“那个啥精华里的核心成分”,产品详情页又叫“X复合物”。规则是人写的,永远跟不上语言的多样性。
抽取流程是这样的:先把清洗后的文本按产品、场景切好,每段注入一个抽取Prompt,让LLM输出标准JSON。Prompt大概长这样:
你是一名品牌知识抽取助手。请从以下文本中抽取品牌相关信息,并输出JSON数组。每一条抽取结果必须包含:head(实体名称)、head_type(实体类型:产品/成分/功效/人群/资质等)、relation(关系类型:contains/claims/applies_to/certified_by等)、tail(实体名称)、tail_type(实体类型)、evidence(原文中的证据片段)。 只抽取文本中明确提到的信息,禁止推测。若无法抽取任何信息,返回空数组。 文本: {chunk_text}抽取结果会先进入一个校验环节,主要是做实体对齐。比如“修护面霜”“XX修护霜”“这款面霜”都指向同一实体,需要归一为统一的标准名。这一步我们用图谱里已有的实体别名表来辅助,LLM负责识别新的别名,人工确认后再加入表。
3.3 冲突消解与人工校准
这是整个知识图谱构建里最容易被低估的环节。多个来源的数据经常互相打架:官网标注的适用人群是“所有肤质”,电商详情页写的是“不推荐敏感肌急性期使用”;旧页面说产品含某成分,新版配方已经换掉了;客服FAQ里的售后周期和售后政策页对不上。
我们的处理策略是给每个三元组加“来源优先级”和“置信度”。官网和产品备案信息优先级最高,电商自营详情页次之,用户评论和第三方内容再次之。置信度则根据来源之间的吻合度来算:多个高优先级来源一致,置信度高;否则降低。
冲突消解之后,并不会把低置信度的三元组直接删掉,而是保留在知识库里,只是降低它在生成时的参考权重。这么做的好处是,万一用户问“我看某篇文章说这款产品含X”,系统仍能回答“那篇内容出现过该说法,但官网备案信息未标明”,既照顾了用户看到的第三方信息,又维护了官方口径。如果直接删除,系统就会失忆,面对这类问题答不上来。
4. RAG链路的工程实现
4.1 文档切分与向量化
RAG链路看起来是标准操作,但切分策略直接影响召回质量。我们试过按固定token切,比如512个字一刀切,结果很惨:一句话被劈成两半,段落含义断裂,召回片段经常是半截话。
后来改成按“标题层级+语义段落”切。清洗HTML时先保留页面里的h1、h2、h3层级,再把每个标题下的正文作为一个基础块;如果某个块太长,再按语义边界二次细切。每个块会附带元数据:来源URL、标题、产品、时间、权限级别。这些元数据后面要拼进Prompt,模型才知道这段话的来源和身份。
Embedding选型上,我们没有一开始就追求领域微调。通用中文Embedding模型在品牌内容上的表现已经够用,关键是切块干净、元数据完整。句向量和段落向量是分开的:短文本用句向量做轻量召回,长段落用段落向量做深度召回。
4.2 混合召回与重排
向量检索不是万能的,尤其是品牌名、产品名这类专有名词,语义向量反而容易被泛化。比如用户问“这个牌子孕妇能用吗”,向量检索可能召回一堆“孕期护肤”的泛内容,漏掉品牌特有的资质信息。所以我们的召回层是“向量+关键词+图谱”三路并行。
- 向量检索:用用户Query的Embedding,从向量库召回Top 50。
- 关键词检索:基于BM25,在同一个文档块集合上召回Top 30。
- 图谱扩展:先在知识图谱里找到匹配的实体,然后用实体的属性、关系、关联文档ID去查候选块。
三路结果用RRF(Reciprocal Rank Fusion)合并,各路的排位权重给到前几名比较大的分数。合并后取Top 50进入重排模型。重排用的是cross-encoder,把Query和候选片段拼在一起打分,比纯向量相似度更准,但计算量大,所以只对Top 50重排,取Top 8作为生成上下文。
4.3 上下文构造与生成约束
生成阶段是我们花时间最多的部分。模型不是万能的,给什么上下文就答什么,但上下文构造方式直接决定答案质量。
我们的Prompt结构大概是这样的:
你是一个品牌智能问答助手。请基于以下“已知信息”回答用户问题。你只能使用已知信息中给出的内容,禁止使用外部知识或自行推测。 【已知信息】 1. (来源:官网产品页){content块1} 2. (来源:备案信息){content块2} 3. (图谱事实)产品A包含成分B;成分B通过敏感性测试;适用人群:孕妇可用。 要求: - 回答中每个关键事实后面标注引用编号,例如[1]。 - 如果已知信息不足以回答,直接回复“根据现有信息无法确认”,不要编造。 - 回答结束后,输出一个JSON块,包含answer和citations两个字段。加图谱三元组作为已知信息,是给模型一个“结构化事实底座”。它不需要再靠向量片段去推断成分与产品的关系,直接就有明确的三元组可用,幻觉概率明显下降。
输出侧也做了约束和校验。模型生成的JSON块,我们用模式校验器检查是否字段完整、引用编号是否都在已知信息列表里。引用归属校验这步是重点:片段编号存在,不代表模型真的基于该片段作答。我们拿到生成的答案后,会把每个标引用的句子和对应片段做一次语义相似度比对,低于阈值的判定为“疑似幻觉引用”,整条答案降级或触发重新生成。
5. 工程实践中的关键经验与踩坑记录
5.1 数据质量决定效果上限
这句话我们踩了很深。最初我们花了大把时间调参数、调Prompt,但准确率一直上不去。后来排查发现,根源是知识库里有大量过期页面。官网某个旧产品已经停产半年,页面居然还在被采集;电商详情页里标注的价格和实际结算页差了几十块;客服FAQ里有一条“发货时效3天”,但活动期间实际是“预售7天内发货”。
数据层的解决方案是定时巡检加上数据版本管理。每个内容块记录采集时间和版本号,每次新增时比对新旧内容,出现变更就自动触发图谱属性和向量索引的更新。如果某个来源连续两次采集失败,系统会在知识库标记数据源异常,而不是静默保留旧数据。
5.2 幻觉比想象中难压
RAG已经给了上下文,模型还是可能脑补。尤其是在用户问“为什么”的时候,模型会倾向于补充“自己的理解”,而这些理解可能不在知识库里。我们试过在Prompt里反复强调“禁止推测”,效果有限。
真正有效的是生成后的校验机制。答案出来后,系统会做两道检查:第一道,提取答案中所有的陈述性断言,去和已知信息片段做匹配,匹配不上就拦下;第二道,对“敏感类问题”(比如孕妇可用、儿童可用、疾病相关),设置更严格的阈值,置信度不够直接拒绝回答,把问题转给人工客服。我们宁可让用户得到“无法确认”的答复,也不希望生成一段看起来合理但要承担风险的答案。
5.3 评估体系不能只靠感觉
做这类系统,如果只看几个Demo案例就宣布成功,后面会非常被动。我们花了两周建了一套评测基准,不是特别复杂,但非常管用。
评测集包含大约500个品牌相关问题,分成四类:参数查询类、场景推荐类、资质安全类、对比选择类。每类问题又分“能直接答”“需要图谱多跳”“需要长尾语义召回”三个难度级别。每个问题带着标准答案的要点和期望引用的来源类型。
评估分两个维度:答案准确性和引用相关性。准确性用LLM裁判模型打分,并且每个月抽样200条进行人工复核,防止LLM裁判自己跑偏。引用相关性是硬指标,逐条检查引用片段是否真的支持对应句子的断言。链路优化时,我们只看评测集上的分数变化,不看单条案例效果,这样能避免“改了一个问题,坏了十个问题”的情况。
5.4 性能与成本平衡
线上问答链路对延迟有要求。我们的目标是不超过2.5秒,实测下来,检索阶段大约80ms,重排大约200ms,生成阶段占大头,1.5到2秒。有一个比较关键的优化点:不要在生成时才做混合召回,而是在查询理解阶段先判断问题的类型。参数类问题优先走图谱路径,场景类问题优先走向量路径,混合路径只用于复杂长尾问题。这让平均生成上下文长度下降了四分之一左右,成本和延迟都有改善。
模型层面,我们做了分级调度:简单问题用轻量模型,复杂问题才上更强的模型。判断逻辑基于Query的意图分类结果和召回片段的置信度。这个策略比一味堆大模型更实用。
6. 落地效果与应用边界
6.1 我们观察到的实际效果
说一点不吹牛的效果。在内部评测集上,经过大约三轮迭代,长尾问题的答案覆盖率提升了四成左右。所谓覆盖率,是指“答案能够正确引用至少一个官方来源”的问题占比。参数查询类问题的准确率最高,因为图谱信息密度高、冲突少;场景推荐类次之,依赖向量召回和重排质量;资质安全类因为设置了高阈值,拒绝回答的比例偏高,但我们宁可保守。
线上体验上,品牌方内部的客服团队明显感受到了差别。原来的FAQ需要人工一条条检索,现在AI给出的答案基本能覆盖大部分常见问题,客服只需要在系统答不上来或者用户反复追问的时候介入。这个转变对团队的实际帮助比单纯追求“AI讲得全面”更明显。
6.2 适用场景与不适合的场景
这套系统适合什么场景?我们的判断是:品牌官网AI助手、客服知识库、电商详情页自动问答、参数字段化的内容中台。这些场景的共同点是,知识点相对固定,答案需要引用可靠来源,而且品牌方对回复口径有明确的掌控需求。
不适合的场景也很多。比如舆情监测,需要的是开放式的观点归纳,而不是给出确定答案,图谱这套体系帮不上忙;再比如强时效性的突发事件问答,内容源更新速度跟不上,反而容易出问题。对预算有限的品牌方来说,不用一开始就全量铺开,挑一两个核心产品线先做知识图谱,其余页面用纯RAG兜底,成本会低很多。
6.3 后续演进
后面我们打算做三件事:多模态知识接入,把产品图片、演示视频里的信息也抽进知识库;知识图谱自动更新,不依赖人工审核全部节点,只对高风险的属性变更做人工确认;以及接入更多生成式引擎的内容分发接口,让同一份图谱事实可以被不同的AI问答服务调用。
另外还有一个值得关注的方向,是把对话中的用户反馈回流到知识库。比如用户反复追问某一个问题,说明现有知识库没有覆盖到;解答后用户明确表示满意,可以把这个问答对沉淀成新的FAQ节点。这样图谱不是一次建好就停,而是会随着运营持续变厚。
如果让我给准备做类似系统的团队一句建议:别从“全自动AI知识库”这个宏大目标开始,先挑客服FAQ和产品参数这两块高确定性数据跑通链路,把评估口径定下来,再逐步扩大范围。这样你踩坑的时候,至少能分清到底是内容数据的问题,还是链路设计的问题。