搜索 K
主题
@vaultkit/vitepress-plugin-llms 是一个在 VitePress buildEnd 钩子里调用的 llms.txt / llms-full.txt 生成器,遵循 llmstxt.org 约定:前者是给 LLM 看的站点索引(标题 + 摘要 + 链接),后者是全文汇编,AI 助手一次抓取就能把整站内容装进上下文。
它与 @vaultkit/vitepress-plugin-feed 采用同构的职责切分:站点元数据与写盘由插件负责(缺省从 site 配置与 sitemap.hostname 推导,零重复配置),「条目从哪来、正文如何净化」完全委托宿主。这是零依赖的纯构建期包,本文所有产物示例都以代码围栏呈现。
越来越多的读者不再直接访问网页,而是让 AI 助手代为阅读与总结。HTML 对 LLM 并不友好:导航、侧栏、脚本占掉大量 token,正文反而被稀释。llmstxt.org 提出的约定很简单——在站点根部放一个 /llms.txt Markdown 文件,用固定结构告诉 LLM「这个站是什么、有哪些内容、去哪里读」:
- [标题](链接): 可选说明社区还衍生出 llms-full.txt——直接把全文内容平铺进一个文件,省去 LLM 逐链接抓取。本包两个产物一次生成。
对 Obsidian vault 这类内容源,还有一层隐私考量:md 源文件里可能有 ``、未发布草稿。直接读盘导出的社区插件会把这些原样泄漏。本包的做法是隐私策略前置——插件只写入宿主传进来的字段,正文净化在传入前完成,插件不碰源文件。
pnpm add -D @vaultkit/vitepress-plugin-llms使用 @vaultkit/vitepress-theme-vault 主题则开箱即带:features.llms 缺省为 true,主题复用与 RSS/页面一致的笔记口径(publish 门控、注释剥离、日期倒序),并把 wikilink 语法平文本化后再喂给本包。关闭方式:
export default defineConfigWithTheme({
extends: createVaultTheme({
site: { /* ... */ },
features: { llms: false },
}),
})import { generateLlms } from '@vaultkit/vitepress-plugin-llms'
import { defineConfig } from 'vitepress'
export default defineConfig({
sitemap: { hostname: 'https://example.com' }, // hostname 从这里自动读取
async buildEnd(config) {
await generateLlms(config, {
sectionHeading: '## 笔记',
items: notes.map(note => ({
title: note.title,
url: note.url,
description: note.excerpt,
date: note.date,
tags: note.tags,
body: note.sanitizedBody, // 宿主负责隐私净化
})),
})
},
})构建结束打印 [llms] llms.txt / llms-full.txt 已生成(N 条)。
| 导出 | 形态 | 说明 |
|---|---|---|
generateLlms | 异步函数(具名导出) | 生成入口,(config, options) => Promise<void> |
| 默认导出 | 同上 | import generateLlms from '...' 亦可 |
LlmsOptions | 类型 | 选项接口 |
LlmsItem | 类型 | 条目结构 |
LlmsSiteConfig | 类型 | SiteConfig 的结构化子集(只消费 outDir、site、userConfig.sitemap.hostname) |
LlmsItem[] | (() => LlmsItem[] | Promise<LlmsItem[]>)const notes = await loadNotes()
await generateFeed(config, { items: notes.map(toFeedItem) })
await generateLlms(config, { items: notes.map(toLlmsItem) })string,默认取 VitePress sitemap.hostname/ 自动剥离;索引行与全文头部的 URL 均由 hostname + item.url 拼出。两处都没配时直接抛错——llms.txt 的价值就在于可跟随的绝对链接。string,默认分别取 site.title、site.descriptionstring,默认 '## 内容'## 前缀的完整行)。llmstxt.org 用 H2 分节组织链接列表,博客站点常用 '## 笔记' / '## 文章',文档站可用 '## 指南'。boolean,默认 truefalse,只保留索引。string,默认 'llms.txt' / 'llms-full.txt'outDir。按 llmstxt.org 约定应放在站点根部,一般不需要改。| 字段 | 类型 | 必填 | 去向 |
|---|---|---|---|
title | string | 是 | 索引行链接文字;全文条目的 # 标题 |
url | string | 是 | 站内路径(如 '/my-post'),与 hostname 拼出条目链接 |
description | string | 否 | 索引行冒号后的一句话摘要(llmstxt.org 的 optional details 位) |
date | string | 否 | llms-full.txt 条目头部的 日期: 元数据行 |
tags | string[] | 否 | llms-full.txt 条目头部的 标签: 元数据行(顿号连接) |
body | string | 否 | llms-full.txt 的纯文本正文;缺省跳过正文段,宿主必须先完成隐私净化 |
description 只进索引、date / tags / body 只进全文——两个产物各取所需,条目结构一份即可。
# 数字花园
> 基于 Obsidian vault 的个人博客
## 笔记
- [llms:让站点对 AI 友好的 llms.txt](https://example.com/llms-txt): 介绍 llms.txt 生成插件
- [feed:给博客配上 RSS 与 JSON Feed](https://example.com/feed-rss-json-feed): 介绍 RSS 插件
- [Minimal Theme](https://example.com/minimal-theme)结构逐行对应 llmstxt.org 约定:H1 站点名 → 引用块摘要 → H2 分节 → - [标题](链接): 摘要 列表;无摘要的条目省略冒号后半段。
# llms:让站点对 AI 友好的 llms.txt
日期:2026-07-10
标签:VaultKit、AI
URL:https://example.com/llms-txt
llms.txt 是给 LLM 看的站点索引……(净化后的纯文本正文)
---
# feed:给博客配上 RSS 与 JSON Feed
日期:2026-07-09
标签:VaultKit、RSS
URL:https://example.com/feed-rss-json-feed
RSS 是博客与读者之间最长寿的契约……每个条目 = # 标题 + 日期/标签/URL 元数据行(缺失的行直接省略)+ 空行 + 正文,条目之间以 --- 分隔线隔开。没传 body 的条目只留头部——LLM 至少还能拿到元数据与 URL。
llms.txt 标准刻意选择 Markdown 而非 JSON/XML:LLM 本身就以 Markdown 为最舒适的输入格式,人类也能直接读。固定的「H1 + 引用块 + H2 链接列表」结构又保留了可编程解析的余地——既是给模型的散文,也是给解析器的 schema。本包的输出严格贴合这一结构,不添加私货。
「读 md 源文件直接导出」的方案,等于把发布管线里所有净化步骤(注释剥离、草稿门控、定时发布)全部旁路。本包反过来:body 传什么写什么,不传就不写。主题适配层的净化示例——把 Obsidian 语法平文本化:
function plainifyWikiSyntax(body: string): string {
return body
.replace(/!\[\[[^\]]*\]\]/g, '') // 媒体/嵌入剔除
.replace(/\[\[([^\]|]+)\|([^\]]+)\]\]/g, '$2') // 别名 wikilink → 别名
.replace(/\[\[([^\]|]+)\]\]/g, '$1') // wikilink → 纯文本
}两包的 options 形状、hostname 推导、items 委托、抛错语义完全一致——学会一个等于学会两个。区别只在产物:feed 面向订阅器(结构化时间线),llms 面向模型(结构化知识库)。
Q:构建报 [llms] 缺少 hostname 错? 与 feed 包同款约束:配 VitePress sitemap.hostname 或传 options.hostname,推荐前者一处配置全站共享。
Q:llms-full.txt 会泄漏我的私人注释吗? 只要你不把未净化的正文传进 body 就不会——插件本身从不读源文件。用主题则净化已内置(与页面渲染同一条 publish/剥离管线)。
Q:想只要索引、不要全文?full: false,llms-full.txt 不再生成,控制台日志也只报 llms.txt。
Q:如何验证 AI 真的在用? 观察访问日志中 /llms.txt 的抓取记录(GPTBot、ClaudeBot 等 UA)。如果反过来想屏蔽 AI 抓取,见同系列的 robots:一分钟配好 robots.txt。