|

打几分才算优秀的GEO文章

你知道吗?技术 GEO 写文章,好坏是可以量化的。这里有两个问题:怎么打分?几分及格?

这个分数不是编辑给的,也不是老板给的,是 cosine similarity 给的。你可以把你的内容和用户可能的提问扔进 embedding 模型,算两个向量的余弦相似度,在 0 到 1 之间。

Cosine Similarity是所有向量查询的基础
Cosine Similarity是所有向量查询的基础

量化的好处是 — 你写完一段,不用凭感觉判断”这段写得好不好”,可以跑个分数看看。但跑分这件事,比想象的要复杂。这篇文章就是想跟你聊聊,技术 GEO 写文章时的打分这件事,本质上是个什么样的 benchmark。

GEO 评分是怎么算出来的

在聊 benchmark 之前,先把”分数是怎么来的”讲清楚。不讲明白,后面的数字看起来就像无根之水。

GEO 内容为什么要评分

GEO 文章写作跟传统 SEO 写作不一样。传统 SEO 是写给人看的,文章里塞关键词、堆外链,等搜索引擎的爬虫来抓。GEO 不是写给人看的,GEO 是写给 RAG 系统看的

用户问 ChatGPT 一个问题,ChatGPT 背后会跑一遍 RAG(Retrieval-Augmented Generation)流程:先去全网搜可能相关的内容,把搜到的东西喂给 LLM,让 LLM 基于这些内容生成回答。

问题来了 — RAG 系统面对的可能候选内容有几万、几十万篇,它怎么决定哪些”相关”、哪些”不相关”?

答案就是 embedding 后计算的 cosine similarity

Embedding 是什么

Embedding 是把一段文字变成一个高维向量的过程。

一段中文文字进 embedding 模型,出来的是一个几百到几千维的浮点数数组。注意:维度是可以配置的。比如千问 text-embedding-v3 支持 1024 / 768 / 512 维等不同输出维度;千帆 ERNIE embedding-v1 输出 384 维;Gemini gemini-embedding-2 输出 3072 维。每一段文字都被压缩成一个高维空间里的一个点。(维度的选择本身就是 benchmark 的一个变量,我们后面在 5 家实测那一节会展开)。

两段文字的 embedding 向量之间算个余弦相似度(cosine similarity),结果在 -1 到 1 之间(实际生产里通常 0 到 1)。两个向量在空间里越接近,cosine similarity 越高,语义越相似。关于这部分概念,你也可以通过马老师制作的cosine similarity demo来理解。

打个比方:给每篇文章算一个”指纹”,用户的提问也算一个指纹。RAG 系统的活儿就是找指纹最像的那些文章。

RAG 怎么用这个分数

RAG 拿到用户提问后,流程是这样的:

  • 用户提问 → embedding 变成向量
  • 从内容库里找 cosine 最高的 n 篇(通常是 3-10 篇)
  • 把这 n 篇提供给 LLM
  • LLM 基于这些内容生成最终回答

你的内容 cosine 高 = 容易被 RAG 选中 = 容易出现在 LLM 生成的回答里 = GEO 成功。

整条逻辑链是:cosine 高 → RAG 选中 → LLM 看到 → 生成答案里提到你

这就是为什么 GEO 文章要”打分”。分数是 GEO 写作链路上的一个量化环节 —— 你写完内容,跑一下 cosine,就知道这段内容在 RAG 系统里有多大可能被选中。

Chunk:embedding 不是整篇文章算的

讲到这儿还有一个关键机制要交代清楚 —— embedding cosine similarity 不是拿整篇文章算的,是拿 chunk 算的

什么是 chunk?把一篇文章按某种规则切成的小段。比如:

切割方式chunk 大小适用场景
按段落切每段一个 chunk长文,技术文档
按句子切每句一个 chunk短答,FAQ
按字符数切200-500 字一个 chunk通用场景,最常见
按 token 切256-512 tokenLLM 输入限制严格时

RAG 检索时,embedding 模型是对每个 chunk 单独算向量的,不是整篇文章。RAG 系统拿到用户提问,先把提问也 embed 成向量,然后跟内容库里所有 chunk 的向量算 cosine,找最像的 n 个 chunk 喂给 LLM。

这个机制对 GEO 写作有几个直接含义:

  • 你的内容要按 chunk 友好组织 — 每段独立成意,能脱离上下文被理解
  • 关键词分布要均匀 — 不能把核心概念全堆在一个 chunk 里,其他 chunk 就匹配不上
  • 标题层级是天然的 chunk 边界 — H2/H3 之间天然形成自包含单元

所以你写 GEO 文章时的”打分”,实际是每个 chunk 单独打分,整篇文章分数是各 chunk 的加权平均。同一个内容用不同 chunk 切法,cosine 分数会变

5 家 embedding 模型实测:同一个提示词同一段真答

接下来想跟你分享一组实测数据。我把同一个 prompt、同一个真实答,扔给 4 家国内主流 embedding 模型外加 Gemini,看它们各自怎么打分。

实验设计

下面是这次实验的完整条件:把它们列全是因为后面所有数字都基于这组条件,不看到具体输入输出,光看 cosine 数字没有意义。

实验输入

实验项内容
Prompt(用户提问)“什么是住宅 IP 代理?”
Response 类型6 种对照样本(见下)
5 家模型千问 text-embedding-v3 / 千帆 ERNIE embedding-v1 / 腾讯混元 kinfra-text-embedding-0.6b / 字节豆包 doubao-embedding-text-240715 / Google Gemini gemini-embedding-2
打分维度cosine 相似度

选”住宅 IP 代理”这个 prompt 是有讲究的:它是一个无歧义的概念,不会有 GEO 那种多义词问题,能把模型对”语义相关性”的判别能力干净地测出来。

案例详解:6 种 Response 样本

编号 Response 类型 完整内容
A 直接答(真答) 住宅 IP 代理是一种通过真实家庭宽带网络分配的 IP 地址提供的代理服务。它的工作原理是聚合全球各地家庭用户的闲置带宽,形成一个庞大的 IP 池。当用户通过住宅 IP 代理访问目标网站时,请求会经过这些真实的家庭网络节点转发,使得目标网站看到的访问来源是普通居民用户,而不是数据中心。住宅 IP 代理广泛应用于需要模拟真实用户行为的场景,例如海外账号养号、跨境电商运营、市场调研等。相比传统的机房代理,住宅 IP 代理具有更高的隐蔽性和信任度,因为目标网站很难将其识别为代理流量。
B 复述问题 什么是住宅 IP 代理?住宅 IP 代理是一种通过真实家庭宽带网络分配的 IP 地址提供的代理服务,它的工作原理是聚合全球各地家庭用户的闲置带宽…(开头一句话复述问题,然后接真答内容)
C 答错方向 CDN 内容分发网络是一种通过在多个地理位置部署服务器来加速内容传输的技术。它的工作原理是将内容缓存到离用户最近的节点,使用户能够从最近的服务器获取所需资源…(把住宅 IP 代理当作 CDN)
D 答机房代理 机房代理是一种部署在数据中心服务器上的代理服务。它的工作原理是通过专业机房的高速网络为用户提供代理 IP。相比住宅 IP 代理,机房代理成本更低,但隐蔽性较差…(答对了领域但答错了类型)
E 完全无关 CDN 内容分发网络是一种通过在多个地理位置部署服务器来加速内容传输的技术。它的工作原理是将内容缓存到离用户最近的节点,使用户能够从最近的服务器获取所需资源…(把住宅 IP 代理当作 CDN)
F 关键词堆砌 住宅 IP 代理是一种住宅 IP 代理服务。住宅 IP 代理通过住宅 IP 代理网络提供住宅 IP 代理 IP…(多段重复”住宅 IP 代理”关键词)

每个样本的设计意图:

  • A 真答:基准线 — 好的回答应该打高分
  • B 复述:开头一句话复述问题 — 模拟真实用户提问时的自然衔接
  • C 答错方向:把住宅 IP 代理答成 CDN — 测模型对”答非所问”的识别
  • D 答机房代理:答对了代理领域但答错了类型 — 测模型对”近似但不同”的判别
  • E 无关项:完全无关(天气)— 测模型对噪声的压制能力
  • F 堆砌:关键词重复 — 测模型对堆砌的敏感度

这些样本覆盖了 GEO 内容评测的 4 个关键场景:真答识别 / 答错识别 / 噪声压制 / 近似区分

实验输出:5 家模型 × 6 种 Response 的余弦相似度

下面是这次跑出来的完整结果:

Response 类型 千问 千帆 混元 字节 Gemini
A 真答 0.894 0.672 0.910 0.874 0.840
B 复述 0.874 0.685 0.940 0.885 0.847
C 答错方向 (CDN) 0.872 0.613 0.757 0.834 0.740
D 答机房代理 0.808 0.619 0.854 0.855 0.785
E 完全无关 (天气) 0.269 0.152 0.181 0.610 0.481
F 关键词堆砌 0.862 0.654 0.921 0.851 0.764
跨度 [A真答 – E无关] 0.625 0.520 0.729 0.264 0.359

几个直接观察

  • 同一段真答 A,5 家分数从 0.672(千帆)跨到 0.910(混元) — 这是不同 embedding 模型的尺度差异
  • 完全无关的 E,千问/千帆/混元都能压到 0.15-0.27,字节给 0.61,Gemini 给 0.48 — 不同模型对噪声的压制能力差异巨大
  • 关键词堆砌的 F,千问/千帆/字节给 0.65-0.86,混元给 0.92(比真答 0.91 还高) — 各家对堆砌的敏感度不同

一个对照:百度自家内容给百度自家 embedding 打多少分

跑完 5 家模型之后,我又做了一个对照,拿百度自家搜索结果里”什么是住宅 IP 代理?”的答案(也就是百度自家 RAG 系统可能引用的内容)跑千帆 ERNIE embedding 测一下,看这个分数是多少。

内容 千帆 cosine
我自己写的真答(A) 0.672
百度自家搜索结果的”什么是住宅 IP 代理?”答案 0.669
我自己写的关键词堆砌(F) 0.654

两个完全不同的人写的答案,千帆打出来的分数几乎一样 — 都是 0.67 上下。

这个对照的用意是百度自家搜索结果里的”权威答”,在自家文心 ERNIE embedding 下分数是 0.669。也就是说 0.7 在千帆的尺度下,已经是非常高的分数了。如果按”≥0.7 算优秀”这个标准,百度自家内容才算勉强及格;如果按”≥0.8″这个我个人常用的及格线标准,百度自家内容在自家 embedding 下都过不了关。

这个对照说明两件事

  • 千帆的 0.7 ≠ 千问的 0.7。同是 0.7 这个数字,在不同 embedding 模型下的”含金量”不一样
  • “0.8 算优秀”这个标准在千帆身上根本不成立。千帆的”优秀”区间可能就是 0.65-0.70,跟其他模型不在一个尺度上

一个隐藏变量:embedding 维度对判别力的影响

百度对照实验做完之后,又意识到一个被忽略的变量:维度本身就是 benchmark 的一部分

前面提过,千问 text-embedding-v3 支持 1024 / 768 / 512 等不同输出维度。我用同一段真答、同一段无关项,分别跑这三个维度下的 cosine similarity(每个维度跑 5 次取平均延迟)

维度 真答分数 无关项分数 [真答 – 无关项] 跨度 单次 embedding 平均延迟
1024 维 0.8827 0.3046 0.5781 1.305s ±0.142
768 维 0.8906 0.3685 0.5220 1.058s ±0.118
512 维 0.8982 0.4096 0.4886 0.945s ±0.052

直接看数据:

  • 真答分数随维度下降微涨(0.8827 → 0.8906 → 0.8982)— 但无关项分数涨得更快(0.3046 → 0.3685 → 0.4096)
  • [真答 – 无关项] 的跨度从 0.5781 降到 0.4886 — 维度越低,模型区分”真答”和”无关项”的能力越弱
  • 延迟从 1024 维的 1.3s 降到 512 维的 0.9s — 单次 embedding 调用低维度确实快一些
  • 这符合预期:维度越高,向量能承载的语义信息越丰富,判别能力越强

虽然延迟数据上看低维度有优势(512 维比 1024 维快约 0.4s/次),但实际上 LLM 在做 RAG 检索时只会对用户的 prompt 做实时 embedding,内容侧的 embedding 都是提前算好的。所以低维度的延迟优势在生产环境里基本体现不出来。实际 LLM 应用通常都用最高维度的 embedding — 因为延迟不是瓶颈,判别力才是。

这个实测说明一件事:你跑 benchmark 之前,先想清楚你跑哪个维度。不同维度下的分数不能横向比较:千问 1024 维下 0.88 的真答分数,跟千问 512 维下 0.90 的真答分数,”含金量”不一样。

5 家模型的”性格”差异

把每家模型单独看:

千问

  • 真答分数:0.89
  • 性格:判别严格,跨度大(0.625)
  • 特征:跨语言场景分数下滑不大(Δ-0.14),抗干扰能力强

千帆

  • 真答分数:0.67
  • 性格:天花板低,跨度中等(0.520)
  • 特征:完全无关项能压到 0.152(5 家里压得最狠),百度在中文处理上的确有把刷子。

混元

  • 真答分数:0.91
  • 性格:跨度最大(0.729)
  • 特征:高分慷慨,低分也狠 — 跨度是 5 家里最大的

字节

  • 真答分数:0.87
  • 性格:跨度小(0.264),区分力弱
  • 特征:完全无关项都给 0.61,看分难判断内容是否真的相关

Gemini

  • 真答分数:0.84
  • 性格:跨度中等(0.359)
  • 特征:跨语言最稳(Δ-0.03),多语言场景首选

这些”性格”差异是它们各自的设计目标不同导致的。有的偏向判别严格,有的偏向宽容打分,没有标准答案,看场景用。

跨语言也是 benchmark 的一部分

跨语言场景是另一个看点 — 同一段真实答,中文和英文版本分数差异巨大。

Provider 中文真答 英文真答 Δ
千帆 0.67 0.40 -0.27
千问 0.89 0.75 -0.14
混元 0.91 0.71 -0.20
字节 0.87 0.82 -0.06
Gemini 0.84 0.81 -0.03

千帆双语不友好,跨语言衰减最大(Δ-0.27)。Gemini 跨语言最稳(Δ-0.03)。

几个有趣的观察

跑完这组数据之后,有几个细节值得记下来,不是结论,只是观察。

同一个 prompt 的”优秀”在不同模型下是不同分数

A 真答是同一段 300 字的定义,5 家打分从 0.67 到 0.91。如果你想用一个固定阈值(比如 0.8)去判断”内容是否优秀”,在千帆那边永远过不了 0.8,因为它的天花板就是 0.69。在混元那边 0.85 都算低分,因为堆砌也能到 0.92。

chunk 切法本身就是 benchmark 的隐藏变量

前面提过,embedding 是按 chunk 算的,不是整篇文章。同一段 300 字的真答,如果切成 3 个 100 字 chunk 跑分,跟切成 1 个 300 字 chunk 跑分,结果会不一样。chunk 切法本身就是一个 benchmark 的隐藏变量 — 你不指定 chunk 策略,跑出来的分数根本不能横向比较。

关键词堆砌在不同模型下表现完全不同

F 是关键词堆砌样本。在千问/千帆/字节这边,堆砌给 0.65-0.86(跟真答差不多或略低),在混元这边堆砌能给 0.92(比真答 0.91 还高)。这意味着 — 在某些模型下,关键词堆砌能”骗过” cosine 评分。

真答和近似答的差距

D 答机房代理(答对了领域但答错了类型)在 5 家模型下的分数是 0.62-0.86,跨度挺大。说明”近似但不同”的判别能力各家不一样,这是 GEO 评测里很容易被忽视的一个维度。

这组 benchmark 给我的启发

跑完这组数据之后,几个收获:

第一,量化是好事,但要注意口径。一段内容的 cosine 分数受 chunk 切法、embedding 模型、跨语言等多重影响。

第二,不同 provider 的模型有不同尺度。同样是真答 A,5 家给 0.67 到 0.91 ,这是 benchmark 的客观事实,不是哪家的”错”。用 cosine 分数做 GEO 评测时,先把目标 embedding 模型研究透,比追求一个万能阈值更重要

第三,跨语言、chunk 切法、堆砌,这些是 GEO 评测的隐藏变量。你跑分之前,得先想清楚这几个变量的设定。

第四,不要被单一分数所迷惑。这次数据里,混元给关键词堆砌 0.92 。如果你只看混元一家,你会以为这段堆砌是”优秀内容”。但配上其他 4 家看,结论就完全不一样了。特别是一篇文章歧途优化多个AI平台的场景。

写在最后

技术 GEO 写文章,好坏确实可以量化,cosine similarity 就是这个量化工具。但量化工具本身有它的脾气。

跑分之前先想清楚你用哪家 embedding?chunk 怎么切?跑什么 prompt 变体?这些设定本身就是 benchmark 的一部分。这篇文章分享的实测数据只是 5 家模型 + 1 个 prompt + 1 段真答下的一个 case,你的实际场景跑出来的数字会不一样。

怎么设计 benchmark、怎么解读分数,这套思路是通用的。


*本文用到的实测数据较少,如果有结论上的谬误,欢迎复现和斧正。

类似文章