Please enable Javascript to view the contents

llms.txt:让 AI 读懂你的网站

 ·  ☕ 12 分钟

1. llms.txt 是什么

llms.txt 是一个约定:在网站根目录放一个 Markdown 文件,用自然语言告诉大模型和 AI Agent——这个网站是什么、哪些内容值得读、每一篇讲了什么。

它由 Jeremy Howard(Answer.AI)在 2024 年 9 月提出,规范全文只有一个页面。

简单说,robots.txt 管的是「你能不能抓」,llms.txt 管的是「抓完怎么理解」——前者是许可,后者是导读。

一个最小可用的 llms.txt 长这样:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 陈少文的网站

> 关于 AI、云原生与基础设施工程的个人技术博客,700+ 篇实践笔记。

站点以中文为主,包含 Kubernetes、Ceph、RDMA、GPU 运维、
AI Agent 等方向的实操记录,每篇都有可复现的命令与结论。

## 核心内容

- [Ceph 架构与运维](https://www.chenshaowen.com/blog/container-deploy-ceph-architecture-operations-and-testing.html):集群架构、日常巡检、监控与升级
- [RDMA 运维](https://www.chenshaowen.com/blog/rdma-ops.html):RoCE、Soft RoCE、InfiniBand 的配置与测试

## Optional

- [关于我](https://www.chenshaowen.com/about.html):联系方式与咨询方式

注意整份文件就是给人看也给模型读的普通 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. 文件格式

规范给的结构非常克制:按固定顺序排列的几个部分,其中只有一个是必需的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 站点名

> 一句话摘要,说明这个站点是什么

补充说明段落,可以写定位、语言、内容范围、更新频率等

## 分组标题

- [链接标题](https://example.com/page):这条链接讲了什么

## Optional

- [次要链接](https://example.com/other):模型可自行决定是否读取

各部分的作用和约束:

部分是否必需说明
BOM可选规范允许文件以字节序标记开头,面向程序的解析器会顺手跳过
H1 标题必需站点或项目名,整个文件唯一必需的字段
引用块 >可选一句话摘要,模型最可能直接引用的一段
正文段落可选补充细节,写定位、范围、语言、更新习惯
H2 分组 + 列表可选文件清单,必须是 Markdown 链接格式- [名称](URL):说明
## Optional可选约定的次要分组,放锦上添花的内容

几条硬性要求:

  • 放在站点根目录或任意子路径,路径就是 /llms.txt/docs/llms.txt。文件只覆盖它所在路径下的 URL,同时存在多份时,客户端取最具体的那一份
  • 必须是 Markdown,纯文本输出,Content-Type 用 text/plaintext/markdown
  • 列表项没有链接就不是链接,规范要求用标准 Markdown 超链接语法,不要写裸 URL
  • 除 H1 外所有部分都是可选的,但只有 H1 的 llms.txt 基本没有价值

3.1 Markdown 版本:.md 后缀

规范在索引文件之外,还提了一件事:给页面本身配一份干净的 Markdown 源文,让模型少做一轮 HTML 抽取正文。

下面的示例都用本博客举例,但本站尚未实现这一能力,示例是假设实现之后的样子。

原提案对 URL 给了两种写法,都算合规:

  • 追加:page.htmlpage.html.md
  • 替换扩展名:page.htmlpage.md

没有文件名的路径则用 index.html.mdindex.md。原提案自己用的是追加写法——by_example.htmlby_example.html.md——实战里也更推荐它:静态托管上 page.md 有可能和真实路由撞车,追加后缀则不会。

1
2
curl -s https://www.chenshaowen.com/blog/rdma-ops.html      # 默认:HTML
curl -s https://www.chenshaowen.com/blog/rdma-ops.html.md   # 追加 .md:Markdown

后者返回的就是文章原文,没有模板噪声:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
---
title: RDMA 运维
tags:
  - RDMA
  - RoCE
  - InfiniBand
  - 网络
  - 运维
  - 高性能计算
enableToc: true
layout: post
url: blog/rdma-ops.html
updated: 2026-08-22 00:00:00
date: 2026-08-22 00:00:00
---

## 1. RoCE

### 1.1 连接要求

RDMA 要求端到端同一类网络,比如同一个 B 段网。
...

对比一下同一段内容在 HTML 里的样子——模型得先自己判断哪一块才是正文:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<body>
  <nav class="navbar">...</nav>
  <aside class="sidebar">...</aside>
  <main>
    <article>
      <h2>1. RoCE</h2>
      <h3>1.1 连接要求</h3>
      <p>RDMA 要求端到端同一类网络……</p>
    </article>
  </main>
  <div class="adsense">...</div>
  <script>
    ...
  </script>
</body>

3.2 怎么让模型找到这份 Markdown

多出一份文件,模型怎么知道它存在?规范的答案是用标准的 link 关系声明,两种写法等价:

1
2
<link rel="alternate" type="text/markdown" href="/blog/rdma-ops.html.md">
<link rel="describedby" href="/llms.txt">

或者放在 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)。规范没有提这种方式,是工程实践里常见的另一种选择。

1
2
3
4
5
6
7
8
# 默认:拿 HTML
curl -s https://www.chenshaowen.com/blog/rdma-ops.html | head -2
# <!DOCTYPE html>

# 声明偏好:同一个 URL,拿 Markdown
curl -s -H 'Accept: text/markdown' \
     https://www.chenshaowen.com/blog/rdma-ops.html | head -2
# ---

按 HTTP 语义,Accept 表达的是偏好而非命令,所以更常见的写法是带权重:

Accept: text/markdown, text/html;q=0.9

意思是「优先 Markdown,HTML 也能接受」。服务端无法满足时应当回退到 HTML,而不是返回 406——否则普通浏览器也会拿不到页面。

服务端的判断逻辑大致是这样:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
map $http_accept $prefer_markdown {
    default            0;
    "~*text/markdown"  1;
}

location /blog/ {
    if ($prefer_markdown) {
        rewrite ^(/blog/.+)\.html$ $1.md last;
    }
}

这段配置只做了字符串匹配,没有解析 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 个真正值得作为入口的页面,按主题分组。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
## 存储

- [Ceph 架构与运维](https://www.chenshaowen.com/blog/container-deploy-ceph-architecture-operations-and-testing.html):集群架构、日常巡检、池与 OSD 管理、监控与升级
- [MinIO 多节点多盘部署与运维](https://www.chenshaowen.com/blog/minio-multi-node-multi-disk-deployment-and-maintenance.html):部署、桶与用户管理、备份,以及节点重启、单盘更换、节点重建
- [JuiceFS 性能测试](https://www.chenshaowen.com/blog/performance-testing-and-comparison-of-juicefs-ce-ee-and-dragonfly.html):本地盘、社区版、企业版与 Dragonfly 集成的 dd / benchmark / fio 实测对比

## AI 基础设施

- [常用 GPU 运维及故障处理](https://www.chenshaowen.com/blog/common-gpu-operation-and-fault-handling.html):XID 错误码、掉卡、ECC、显存泄漏等故障的处理笔记,持续更新
- [RDMA 运维](https://www.chenshaowen.com/blog/rdma-ops.html):RoCE、Soft RoCE、InfiniBand 三种模式的连接要求、装机和点对点测试

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 摘要要写清「是什么」,不是「很好」

摘要那一段最容易被写成宣传语。「专注于分享高质量技术内容」这种句子对模型没有信息量。

有用的摘要包含三个要素:领域内容形态规模或边界

1
2
> 关于 AI、云原生与基础设施工程的个人技术博客,700+ 篇实践笔记,
> 以中文为主,每篇都有可复现的命令与结论。

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 放次要内容。除了根目录,也可以放在任意子路径,只覆盖该路径下的页面。
  • 配套:给页面配一份 .md Markdown 版本,再用 Link 响应头里的 rel="alternate" 声明出来,是比 llms.txt 更本质的一步。
  • 怎么写:策展而非罗列,10~30 个精选入口,每条描述写清价值而不是复述标题。
  • 怎么落地:静态站把文件放进站点根目录即可,无需任何服务端改动;需要覆盖更多页面时,可用构建工具生成初稿再人工删减。
  • 如何看待:没有厂商背书、爬虫请求量低,但成本极低、副作用小。先保证正文能被抓取,再顺手加这一个文件。

花半小时写一份,至少能换来一个清晰的站点自述——这件事本身就有价值。

7. 参考链接


微信公众号
作者
微信公众号