1. llms.txt 是什么
llms.txt 是一个约定:在网站根目录放一个 Markdown 文件,用自然语言告诉大模型和 AI Agent——这个网站是什么、哪些内容值得读、每一篇讲了什么。
它由 Jeremy Howard(Answer.AI)在 2024 年 9 月提出,规范全文只有一个页面。
简单说,robots.txt 管的是「你能不能抓」,llms.txt 管的是「抓完怎么理解」——前者是许可,后者是导读。
一个最小可用的 llms.txt 长这样:
| |
注意整份文件就是给人看也给模型读的普通 Markdown:没有 XML、没有 JSON Schema、没有配置文件。这个约定的全部复杂度,就是「把话说清楚」。
2. 为什么需要它
2.1 HTML 页面本身对模型不友好
把一个页面喂给模型,真正有用的正文只占其中一小部分,其余是导航栏、侧边栏、广告位、cookie 提示、内联脚本和样式。模型要先做一轮「抽取正文」,这个过程既消耗 token,也容易抽错。
更麻烦的是入口问题。站点有几百篇文章时,模型没有什么好办法知道「哪几篇是核心、哪几篇已经过时」。它只能靠 sitemap 遍历、靠搜索命中、靠猜 URL 规律。
llms.txt 的思路是:与其让模型自己猜,不如主动告诉它。
2.2 有/无 llms.txt 对比
假设用户问 AI:「Ceph 出问题怎么排查?」
没有 llms.txt:
抓首页 → 只列出最新 5 篇,要翻 140+ 页才能看全
→ 改抓 sitemap.xml → 上千条 URL,多半是标签页和分页,无从下手
→ 按关键词命中 3 篇 → 逐页抓 HTML、抽正文、去模板噪声
→ 其中 1 篇是几年前的旧文,命令已失效
→ 给出答案(token 大量花在模板和旧文上)
有 llms.txt:
请求 /llms.txt → 一次拿到站点定位 + 核心文章清单 + 每篇一句话摘要
→ 直接选中「Ceph 架构与运维」
→ 抓正文 → 给出答案
| 维度 | 没有 llms.txt | 有 llms.txt |
|---|---|---|
| 站点定位 | 靠模型从首页猜 | 一句话摘要直接给出 |
| 内容发现 | sitemap 全文遍历 | 策展过的核心入口清单 |
| 筛选成本 | 逐页抓取才知道讲什么 | 每条链接带描述,抓之前就能筛 |
| 时效判断 | 无法判断新旧 | 可在描述里标注版本与时间 |
| 上下文 | 大量 token 消耗在模板上 | 前几次调用就能命中正确页面 |
| 更新维护 | 无 | 新增文章时顺手加一行 |
2.3 它和 SEO 不是一回事
值得先说清楚:llms.txt 不提升搜索排名,Google 明确表示不用它做排名信号。
它服务的是另一条链路——AI 搜索、AI 浏览器、编程 Agent 在回答问题时如何取用你的内容。这个环节通常叫 GEO(Generative Engine Optimization)。做 SEO 是把页面喂给爬虫,做 GEO 是把理解喂给模型。
2.4 顺带一提:站点自述
llms.txt 还有一层容易被忽略的价值:它是一份写给机器看的站点自述,却也适合人读。新访客、搜索引擎之外的分发渠道、以及你自己在做内容盘点时,都能拿它当导览页——这也决定了它该怎么写,见第 4 节。
3. 文件格式
规范给的结构非常克制:按固定顺序排列的几个部分,其中只有一个是必需的。
| |
各部分的作用和约束:
| 部分 | 是否必需 | 说明 |
|---|---|---|
| BOM | 可选 | 规范允许文件以字节序标记开头,面向程序的解析器会顺手跳过 |
| H1 标题 | 必需 | 站点或项目名,整个文件唯一必需的字段 |
引用块 > | 可选 | 一句话摘要,模型最可能直接引用的一段 |
| 正文段落 | 可选 | 补充细节,写定位、范围、语言、更新习惯 |
| H2 分组 + 列表 | 可选 | 文件清单,必须是 Markdown 链接格式,- [名称](URL):说明 |
## Optional | 可选 | 约定的次要分组,放锦上添花的内容 |
几条硬性要求:
- 放在站点根目录或任意子路径,路径就是
/llms.txt或/docs/llms.txt。文件只覆盖它所在路径下的 URL,同时存在多份时,客户端取最具体的那一份 - 必须是 Markdown,纯文本输出,Content-Type 用
text/plain或text/markdown - 列表项没有链接就不是链接,规范要求用标准 Markdown 超链接语法,不要写裸 URL
- 除 H1 外所有部分都是可选的,但只有 H1 的 llms.txt 基本没有价值
3.1 Markdown 版本:.md 后缀
规范在索引文件之外,还提了一件事:给页面本身配一份干净的 Markdown 源文,让模型少做一轮 HTML 抽取正文。
下面的示例都用本博客举例,但本站尚未实现这一能力,示例是假设实现之后的样子。
原提案对 URL 给了两种写法,都算合规:
- 追加:
page.html→page.html.md - 替换扩展名:
page.html→page.md
没有文件名的路径则用 index.html.md 或 index.md。原提案自己用的是追加写法——by_example.html 配 by_example.html.md——实战里也更推荐它:静态托管上 page.md 有可能和真实路由撞车,追加后缀则不会。
| |
后者返回的就是文章原文,没有模板噪声:
| |
对比一下同一段内容在 HTML 里的样子——模型得先自己判断哪一块才是正文:
| |
3.2 怎么让模型找到这份 Markdown
多出一份文件,模型怎么知道它存在?规范的答案是用标准的 link 关系声明,两种写法等价:
| |
或者放在 HTTP 响应头里,效果一样:
Link: </blog/rdma-ops.html.md>; rel="alternate"; type="text/markdown",
</llms.txt>; rel="describedby"
rel="alternate" type="text/markdown" 指向这一页的 Markdown 版本,rel="describedby" 指向覆盖它的 llms.txt。规范推荐请求头形式,理由是它同样适用于非 HTML 资源,而且能在 Web 服务器或 CDN 配置里统一加,不用改任何一个页面。
3.3 另一种做法:请求头内容协商
还有一种不改 URL 的做法,靠 Accept 请求头区分返回格式,在 HTTP 里叫内容协商(content negotiation)。规范没有提这种方式,是工程实践里常见的另一种选择。
| |
按 HTTP 语义,Accept 表达的是偏好而非命令,所以更常见的写法是带权重:
Accept: text/markdown, text/html;q=0.9
意思是「优先 Markdown,HTML 也能接受」。服务端无法满足时应当回退到 HTML,而不是返回 406——否则普通浏览器也会拿不到页面。
服务端的判断逻辑大致是这样:
| |
这段配置只做了字符串匹配,没有解析 q 权重,实际实现要更细致一些。
3.4 社区惯例:llms-full.txt
实践中还流行一个伴生文件 /llms-full.txt,把清单里所有页面的正文全文内联进去。需要说明的是:它不在规范里,是社区约定,由各文档平台和工具自行支持。
分工是这样:
llms.txt是索引,小而精,用来选页面llms-full.txt是全集,大而全,一次请求拿到全部内容
对文档站、API 文档这类内容总量可控的站点,llms-full.txt 的价值更大——模型一次请求就拿全,省掉多轮抓取。对内容持续增长的博客,它的体积会失控,索引模式更合适。
3.5 落地成本
给页面配 Markdown 版本这件事,比 llms.txt 更本质——llms.txt 解决「选哪篇」,它解决「读得干净」。但成本也更高:
| 方案 | 成本 |
|---|---|
.md 后缀 | 资源翻倍:每个页面多产出一份文件,并维护 URL 映射 |
| Link 响应头 | 低:不改页面,在服务器或 CDN 配置里加一行;纯静态托管做不了,得加一层 CDN |
| 内容协商 | 要解析 Accept、处理权重、决定回退策略,缓存策略也更复杂 |
llms-full.txt | 需要构建流程把全文汇总成单文件,内容一多体积就失控 |
内容协商那一项最容易踩坑的是缓存:如果响应还存在 CDN,第一个请求缓存了 HTML,后续带 Accept: text/markdown 的请求也会拿到 HTML,而发起方往往察觉不到。缓存 key 必须带上 Accept 才安全。
正因如此,不少 CDN 厂商开始把这层转换做成边缘能力,站点的改造成本从「改服务端」降到「开一个开关」。这类能力还在演进,具体支持情况以各厂商文档为准。
4. 内容怎么写
格式五分钟就能学会,难点在内容。写 llms.txt 时最容易犯的错,是把它写成 sitemap 的 Markdown 版。
4.1 策展,不要罗列
如果站点有 700 篇文章,全部列进去等于没列——模型仍然要读完 700 行才能决策,而且分不清主次。
好的 llms.txt 是一次编辑行为:挑出 10~30 个真正值得作为入口的页面,按主题分组。
| |
4.2 每个描述都要回答「读了能得到什么」
描述不是标题的复述,而是筛选依据。对比一下:
| 写法 | 例子 | 效果 |
|---|---|---|
| 复述标题 | [RDMA 运维](https://www.chenshaowen.com/blog/rdma-ops.html):RDMA 运维 | 信息量为零,无法筛选 |
| 写清价值 | [RDMA 运维](https://www.chenshaowen.com/blog/rdma-ops.html):RoCE、Soft RoCE、InfiniBand 的配置与测试 | 模型能判断是否与问题相关 |
4.3 摘要要写清「是什么」,不是「很好」
摘要那一段最容易被写成宣传语。「专注于分享高质量技术内容」这种句子对模型没有信息量。
有用的摘要包含三个要素:领域、内容形态、规模或边界。
| |
4.4 Optional 只放次要内容
## Optional 是规范里唯一带约定含义的分组,用来放锦上添花的内容——关于页、更新日志、友链、法律声明。早期版本的提案给过它机械语义(上下文紧张时整段跳过),新版已经去掉了这层规定,但把次要内容单独归置仍然是有用的惯例。
反过来说,把核心内容放进 Optional,等于告诉模型「这些可以先不看」。
5. 现状与争议
写到这里必须说清楚一件事:llms.txt 目前没有强制力,也没有被主流厂商承诺支持。
几点观察:
- 没有厂商背书。OpenAI、Google、Anthropic 等都没有承诺「会读取 llms.txt」。它不是 robots.txt 那种被广泛遵守的约定——robots.txt 从 1994 年沿用至今,有合规压力和明确的爬虫行为规范,llms.txt 一样都没有。
- 公开的爬虫日志分析普遍显示,AI 爬虫对
/llms.txt的请求量很低,主要流量仍然集中在页面和小部分 feed 上。 - 但它并非无用。成本是一个静态文件和半小时的整理,副作用接近于零。这是它最实际的用途——给人看的站点导览和内容盘点。
所以合理的定位是:一个便宜的赌注,不是 SEO 银弹。
如果你的目标只是「让 AI 更容易取用我的内容」,按投入产出比排序,真正该先做的其实是这几件:
| 优先级 | 事项 | 说明 |
|---|---|---|
| 高 | 正文服务端渲染 | 全 JS 渲染的页面,爬虫几乎取不到内容 |
| 高 | 干净的 URL 与语义化 HTML | <article> / <h1> 比一堆 <div> 有用 |
| 高 | 保留 sitemap 与 RSS | 这两个才是被真正消费的发现渠道 |
| 中 | robots.txt 不误伤 AI 爬虫 | 很多站点在防采集时顺手把 AI 爬虫也封了 |
| 中 | 页面自带结构化数据 | 作者、发布时间、摘要,便于抽取 |
| 低 | llms.txt | 成本低、上限不高、值得顺手做 |
换句话说:llms.txt 是锦上添花的那一层。如果正文本身抓不到,写再好的 llms.txt 也没用。
6. 小结
llms.txt 要做的事很简单:在站点根目录放一份 Markdown,用自然语言写清这个站点是什么、哪些内容值得读。
具体来说:
- 格式:H1 标题唯一必需,加引用块摘要、正文说明、按主题分组的 Markdown 链接列表,
## Optional放次要内容。除了根目录,也可以放在任意子路径,只覆盖该路径下的页面。 - 配套:给页面配一份
.mdMarkdown 版本,再用Link响应头里的rel="alternate"声明出来,是比 llms.txt 更本质的一步。 - 怎么写:策展而非罗列,10~30 个精选入口,每条描述写清价值而不是复述标题。
- 怎么落地:静态站把文件放进站点根目录即可,无需任何服务端改动;需要覆盖更多页面时,可用构建工具生成初稿再人工删减。
- 如何看待:没有厂商背书、爬虫请求量低,但成本极低、副作用小。先保证正文能被抓取,再顺手加这一个文件。
花半小时写一份,至少能换来一个清晰的站点自述——这件事本身就有价值。
