为 Hugo 添加 LLMS 的支持
首先表明观点:
需要特定格式来消费信息的人工智能不是人工智能。
人工智能不需要它自己的格式来理解我的网站,如果它不能理解 HTML,那么它就不是人工智能。
好,如果还是不死心,要给小笨蛋ai做在线知识库,那就开始今天的正片内容:
添加 LLM 友好的 Hugo 内容。
现在的 LLMs.txt 标准尚未被广泛采用,但是 Hugo 开发者说了,如果未来 LLMS 获得更多关注,Hugo 将会原生支持 LLMS嵌入式模板。
目前只能通过手动去创建 LLMS 模板。
创建 LLMS
这里利用 robots.txt 作为代码入口,正好可以放入llms-txt链接,
(不用robots改成其他入口文件,比如 home.html 布局文件也是可以的)
启用 robots.txt
hugo.yaml
1enableRobotsTXT: true
用于动态生成,和链接一个名为 llms.txt
的文件。
layouts/robots.txt
1User-agent: *
2
3{{/* LLMS */}}
4{{- $llms := resources.Get "llms.txt" -}}
5{{- if $llms -}}
6 {{- $llms := $llms | resources.ExecuteAsTemplate "llms.txt" . -}}
7 llms-txt: {{ $llms.Permalink }}
8{{- end }}
最后创建编写 llms.txt 的布局格式
assets\llms.txt
1{{ with .Site.Title -}}
2 # {{ . }}
3{{- end }}
4
5{{ with .Site.Params.Description -}}
6> {{ . }}
7{{- end }}
8
9{{ range (where (sort ((.Site.GetPage "/").Pages) "Weight" "asc" "Date" "desc" "Lastmod" "desc") "Params.sitemap_exclude" "ne" true) -}}
10 - [{{ .Title }}]({{ .Permalink }}): {{ .Description }}
11{{ end -}}
12
13{{/* Sections */}}
14{{ range (where (sort ((.Site.GetPage "/").Sections) "Weight" "asc" "Date" "desc" "Lastmod" "desc") "Params.sitemap_exclude" "ne" true) -}}
15{{ with .Title -}}
16 ## {{ . }}
17{{- end }}
18
19{{ with .Description -}}
20 > {{ . }}
21{{- end }}
22
23{{ range (where (sort .Pages "Weight" "asc" "Date" "desc" "Lastmod" "desc") "Params.sitemap_exclude" "ne" true) -}}
24 {{ if .Title -}}
25 - [{{ .Title }}]({{ .Permalink }}){{ with .Description }}: {{ . }}{{ end }}
26 {{- end }}
27{{ end -}}
28
29{{/* Sub-Sections */}}
30{{ range (where (sort .Sections "Weight" "asc" "Date" "desc" "Lastmod" "desc") "Params.sitemap_exclude" "ne" true) -}}
31{{ with .Title -}}
32 ### {{ . }}
33{{- end }}
34
35{{ with .Description -}}
36 > {{ . }}
37{{- end }}
38
39{{ range (where (sort .Pages "Weight" "asc" "Date" "desc" "Lastmod" "desc") "Params.sitemap_exclude" "ne" true) -}}
40 {{ if .Title -}}
41 - [{{ .Title }}]({{ .Permalink }}){{ with .Description }}: {{ . }}{{ end }}
42 {{- end }}
43{{ end }}
44{{ end -}}
45
46{{ end -}}
此时,运行 hugo server ,已经能正常编译出llms.txt文件了
如果不需要在 robots.txt 里显示 llms-txt 的链接,可以把 llms-txt: {{ $llmsTXT.Permalink }}
这行删除
与 curcor 对比,基本一样
参考自:https://discourse.gohugo.io/t/support-for-llms-txt-standard-for-ai-crawlers/53782/3
创建 LLMS-FULL
llms-full 支持度非常低,甚至连 llms 的官网也不支持
https://llmstxt.org/llms-full.txt,可以看到返回404
当然,想要支持很简单,与上面llms无异
robots.txt 底下追加代码
layouts\robots.txt
1{{/* LLMS-FULL */}}
2{{- $llmsfull := resources.Get "llms-full.txt" -}}
3{{- if $llmsfull -}}
4 {{- $llmsfull := $llmsfull | resources.ExecuteAsTemplate "llms-full.txt" . -}}
5 llms-full-txt: {{ $llmsfull.Permalink }}
6{{- end }}
编写 llms-full.txt 的布局格式
assets\llms-full.txt
1{{- range .Site.RegularPages -}}
2# {{ .Title }}
3Source: {{ .Permalink }}
4{{ .RawContent }}
5
6{{ end -}}
最终效果可以和 cursor 对比
添加 MD 文件以进行 LLM 友好的站点使用
这个有点麻烦,需要创建自定义输出格式
在 hugo.yaml 文件中追加单页的markdown输出格式,
用 outputFormats.baseName 设置文件名前缀,符合llms 官网所要求的 index.html -> index.html.md 。
用 outputs.page 设置多输出一个 markdown 文件
hugo.yaml
1outputFormats:
2 MARKDOWN:
3 mediaType: "text/markdown"
4 isPlainText: true
5 baseName: "index.html"
6
7outputs:
8 page: ["HTML", "MARKDOWN"]
创建 single.markdown ,用于表示单页文章的 markdown 布局
如果你想为单一类型文章和页面创建 .md,比如blog,可以把文件放在 layouts\blog\single.markdown (不过hugo控制台可能会报警告,因为无法限制单一分区下输出文件,会提示其他页面找不到markdown布局文件,不影响使用)
layouts\single.markdown
1# {{ .Title }}
2{{ .RawContent }}
最后运行就可以看到输出结果了
在llms.txt链接md格式文件
此时你会发现,有 llms.txt 文件,也有 MD 友好文件,但是 llms 指向的连接确是普通页面的 html。
我们需要修改llms.txt,把 {{ .Permalink }}
改写成 {{ (.OutputFormats.Get "MARKDOWN").Permalink }}
,来指向之前 outputFormats 设置的md格式
这里只修改分区下的链接做演示
assets\llms.go.txt
1{{ with .Site.Title -}}
2 # {{ . }}
3{{- end }}
4
5{{ with .Site.Params.Description -}}
6> {{ . }}
7{{- end }}
8
9{{ range (where (sort ((.Site.GetPage "/").Pages) "Weight" "asc" "Date" "desc" "Lastmod" "desc") "Params.sitemap_exclude" "ne" true) -}}
10 - [{{ .Title }}]({{ .Permalink }}): {{ .Description }}
11{{ end -}}
12
13{{/* Sections */}}
14{{ range (where (sort ((.Site.GetPage "/").Sections) "Weight" "asc" "Date" "desc" "Lastmod" "desc") "Params.sitemap_exclude" "ne" true) -}}
15{{ with .Title -}}
16 ## {{ . }}
17{{- end }}
18
19{{ with .Description -}}
20 > {{ . }}
21{{- end }}
22
23{{ range (where (sort .Pages "Weight" "asc" "Date" "desc" "Lastmod" "desc") "Params.sitemap_exclude" "ne" true) -}}
24 {{ if .Title -}}
25 - [{{ .Title }}]({{ (.OutputFormats.Get "MARKDOWN").Permalink }}){{ with .Description }}: {{ . }}{{ end }}
26 {{- end }}
27{{ end -}}
28
29{{/* Sub-Sections */}}
30{{ range (where (sort .Sections "Weight" "asc" "Date" "desc" "Lastmod" "desc") "Params.sitemap_exclude" "ne" true) -}}
31{{ with .Title -}}
32 ### {{ . }}
33{{- end }}
34
35{{ with .Description -}}
36 > {{ . }}
37{{- end }}
38
39{{ range (where (sort .Pages "Weight" "asc" "Date" "desc" "Lastmod" "desc") "Params.sitemap_exclude" "ne" true) -}}
40 {{ if .Title -}}
41 - [{{ .Title }}]({{ .Permalink }}){{ with .Description }}: {{ . }}{{ end }}
42 {{- end }}
43{{ end }}
44{{ end -}}
45
46{{ end -}}
最后看看效果