作者以 Astro 建站实验「如何让大模型准确引用页面内容」,总结出结构化数据、语义清晰度、模块化等实操方法,并诚实区分已验证与待验证部分。
Search 和 LLM 检索奖励不同的东西。
搜索引擎对文档进行排名。它想给你十个链接让你自己决定。权威性、链接和新鲜度占主导地位,这就是为什么新域名处于劣势:它所缺乏的信号恰恰是最重要的信号。
语言模型回答问题,更像是在做提取。它需要一个能干净回答问题的段落,能原样引用而不破坏原意,并且能归属于它认识的实体。权威性仍然重要——但可提取性是一个真实的、独立的维度,而且是你在第一天就能完全控制的。
这就是那个赌注。不是结构打败权威,而是结构是新站点真正能竞争的部分。
采用 Astro 静态模式,部署到 Cloudflare Workers 静态资源。内容通过 Astro 的内容集合以 markdown 形式管理,带有类型化的 frontmatter schema。
126 个页面,全部在构建时预渲染。恰好一个动态端点(/api/geo,用于预选 Amazon 店铺)。其余一切都是 Cloudflare 边缘节点上的文件。
内容分为:
内容页面上的 JavaScript 总量:接近零。导航菜单、FAQ 手风琴和词汇表搜索全部基于 <details>/<summary> 构建,或降级为普通可见内容。这一点比听起来更重要——见"无聊的东西"部分。
这里没有新奇的东西。都是做得妥当而已,这就是整个重点。
一些爬虫会执行 JavaScript。许多不会,或者延迟到第二轮才执行,或者对其大量限流。静态构建完全回避了这个问题。到达的内容字节本身就包含内容。
如果这篇文章只让你记住一件事,就记这一件。它毫不光鲜,却压倒一切。
每篇 Learn 和 FAQ 页面都是一个单一问题。标题就是问题。H1 就是问题。H1 之后的第一段是一段 40-70 词的直接回答,独立存在,无需周围上下文。
---
question: "What is investing, actually?"
pillar: "investing"
answer: "Investing is buying a share of something productive — companies,
property, loans — in the hope it earns money over time. Unlike saving, the
value moves, and it can move down. You are being paid, on average and over
long periods, for accepting that uncertainty rather than for being clever."
description: "Investing means owning a share of something productive and
accepting that its value moves. The return is payment for uncertainty, not
for skill."
---
回答字段由内容 schema 强制要求,所以页面不可能不携带一个回答就发布。然后文章在其下深入展开。
自包含是这里的纪律所在。"如上所示,这意味着……"在脱离上下文时就毫无用处。每一个回答都必须能够在周围没有任何东西的情况下被引用而存活。
这是我看到做得最差的环节。大多数网站发出孤立的 JSON-LD 碎片——这里一个 Article,那里一个 Organization,它们之间毫无关系。
相反,每个页面发出一张 @graph,其中节点通过 @id 相互引用:
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Person",
"@id": "https://example.com/#author",
"name": "…",
"knowsAbout": ["personal finance", "saving", "investing", "debt"],
"sameAs": ["https://www.amazon.com/stores/author/…", "…"]
},
{
"@type": "WebSite",
"@id": "https://example.com/#website",
"publisher": { "@id": "https://example.com/#author" }
},
{
"@type": "Article",
"@id": "https://example.com/learn/x#article",
"author": { "@id": "https://example.com/#author" },
"abstract": "the same 40-70 word answer"
}
]
}
Person 和 WebSite 节点由一个组件在每个页面发出,所以实体事实是全站字节相同的。页面在此基础上添加自己的节点。不可能有一个页面描述的作者与另一个页面不同,因为描述只存在于一个地方。
sameAs 是整张图中价值最高的行。它告诉搜索引擎,一个平台上的_profile 和另一个平台上的_profile 是同一个实体,而不是三个巧合。
60 个词汇表页面最初只能从词汇表索引到达。对爬虫来说这读起来像是"边缘内容",对读者来说则意味着在他们需要定义的时刻从来不会遇到它。
所以有一个组件扫描页面渲染后的文本,并将真正出现在其中的词汇表术语做链接:
const hit = names.find((n) => {
const safe = n.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
return new RegExp(`\\b${safe}s?\\b`).test(haystack);
});
全词匹配,所以"share"不会在"shareholder"中触发。每页最多五条。
两个刻意为之的选择。没有向正文注入任何东西——自动的内联链接会产生尴尬的锚点和读起来过度优化的文本。取而代之的是页面底部的一个诚实的列表。数量上限从八条开始,我降到五条,因为一大块机器匹配的链接看起来像是机器做的,即使每一个匹配都合情合理。
一个 68 行的脚本,在部署时读取构建后的站点地图并向 Bing、Yandex 和 Seznam 发送 ping。验证是网站根目录下一个包含你密钥的静态文件。就这样——没有仪表板,没有注册。
Google 没有等效方案,但 Bing 的索引为 ChatGPT 和 Copilot 提供内容,这使其性价比极高,值得花二十分钟。
我发布它们是因为成本接近零,而不对称性很好。要适当持怀疑态度——我也是。
出现在可见 HTML 中的同一段 40-70 词回答也作为 abstract 进入 schema。
诚实评估:我没有证据表明任何模型专门读取 abstract。发布它的论据是边际成本只是一个组件里的一行,而该字段已经存在于可见文本中,所以没有伪装风险,也没有什么需要保持同步的。如果它什么都没做,那它也没花什么成本。
网站根目录的一个 markdown 文件,声明该实体的事实、每个部分的用途以及规范 URL。
诚实评估:这是一个提议的惯例,不是标准。我不知道有任何证据表明主要爬虫今天会消费它。它只是一个文件。真正的好处是,编写它迫使你在一个页面上陈述你的网站实际上声称是什么——这暴露了我自己文案中的两个不一致之处。
这一条是通常建议的刻意反转:
User-agent: *
Content-Signal: ai-train=yes, search=yes, ai-input=yes
Allow: /
加上对 GPTBot、ClaudeBot、PerplexityBot、CCBot、Google-Extended 等的明确 Allow 块。
大多数网站忙于屏蔽这些。对有流量需要保护的老牌出版商来说,屏蔽是一个合理的立场。对一个不知名的作者来说,不出现在 AI 回答中的风险远大于被包含在其中的风险。这个计算真的因人而异,我认为很多人在盲目复制默认设置而没有做这个算术。
如果你走这条路,有两件事值得知道:
边缘规则在 robots.txt 被获取之前就已执行。你的 CDN 的机器人保护设置可能悄悄覆盖你写的每一条 Allow 行。你的 repo 说一套,你的边缘做另一套,而你毫不知情。
一些 CDN 会替你管理 robots.txt。如果 # BEGIN Cloudflare Managed content 出现在服务文件中,那就不再是你的了。要对比的是服务的文件和你 repo 中的文件,而不是你以为你部署的。
两者都特定于 Workers 静态资源,且在文档中都不明显。
Worker 代码中的重定向永远不会对存在的文件触发。匹配静态资源的请求在边缘提供服务,根本不调用你的脚本。我在 Worker 中写了一个 www → apex 重定向,从我发布的那一刻起就是死代码——它只对无法解析到文件的 URL 运行,也就是说永远不会对任何真实页面运行。主机级重定向属于 Redirect Rule,它在管道中更早执行。
通配符路由会吞掉你的子域名。这一条花了我一整天。我把 *.example.com/* 放在了 Worker 上。后来我在 R2 中放了 60 个视频文件在 media.example.com 后面。每一个都返回 404。
存储桶没问题。文件没问题,正确的内容类型,正确的大小。自定义域名显示为 Active。问题是 Worker 路由优先于 R2 自定义域名,所以 Worker 在应答,找不到匹配的文件,然后服务网站自己的 404 页面。
线索是那个 404 是我自己的——我的样式、我的文案——出现在一个与网站毫无关系的 URL 上。如果你曾经在自己的错误页面出现在一个根本不应该服务 HTML 的子域名上,先检查你的 Worker 路由再去动别的。我花了数小时调试一个完全正常工作的服务。
如果你有一个新站点而没有权威,按顺序:
然后再考虑那些投机的东西。
第 1-5 项只是把基础工作做好。如果 LLM 提取论被夸大了,那些工作仍然会通过普通搜索获得回报。这是我即使前提错了也会捍卫这个方法的主要原因——下行情况是"你建了一个结构良好的网站"。
第二部分的东西是否能起到任何作用。问题优先结构是否比仅仅是一个好页面更能可衡量地提高引用率。llms.txt 一年后会是一个标准还是一个脚注。
有结果我会发出来。如果你正确地测量过其中任何一项,我真的很想听听——特别是如果你发现结构性的东西没有任何区别,确实是权威性一路到底。
网站是 edmundwarde.com,如果你想看实现的话。任意 Learn 页面查看源代码;图谱全在那里。