相关文章推荐 新
约 1144 字
概述
在文章 / 文档页底部展示相关内容,帮助读者继续阅读,同时增强站内链接。
推荐结果在 构建期 计算完成并写入页面数据,客户端只负责渲染。
默认关闭
relatedPosts 默认关闭,需要显式开启(relatedPosts: true 即可使用默认配置)。
快速开始
开启功能
在主题配置中开启,
true表示使用全部默认值:.vuepress/config.tsimport { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ relatedPosts: true, }), })按需调整
传入对象可以覆盖任意默认值:
.vuepress/config.tsexport default defineUserConfig({ theme: plumeTheme({ relatedPosts: { limit: 4, minScore: 0.12, diversity: 0.3, }, }), })运行并查看
只对某个集合开启
集合级配置优先于主题级配置,未设置的集合不会受到影响:
.vuepress/config.ts
export default defineUserConfig({
theme: plumeTheme({
collections: [
{
type: 'post',
dir: 'blog',
title: '博客',
relatedPosts: { limit: 6 },
},
],
}),
})相似度信号
对每个集合内的页面,提取以下信号并加权:
| 信号 | 来源 | 默认权重 |
|---|---|---|
| 标签 | frontmatter.tags | 3 |
| 分类 | 自动分类结果 | 2 |
| 标题 | 页面标题 | 2 |
| 标题结构 | 正文中的 ## ~ ###### | 1.5 |
| 正文 | Markdown 正文(默认取前 2000 字符) | 1 |
信号被转换为带字段前缀的词项(例如标签 vue 记为 #g:vue),再以 TF-IDF + 余弦相似度 计算两两相关度。
- 同集合、同语言:默认只在当前集合、当前语言内推荐,博客与文档、中文站与英文站互不影响
- 候选裁剪:先建立倒排索引,只对存在共享词项的页面打分,复杂度接近线性
- 高频词抑制:正文中出现在 30% 以上文档中的词会被忽略(仅在文档数 ≥ 10 时生效), 标签、分类、标题不受影响
- 多样性:取 Top-N 前用 MMR(最大边际相关性)在更宽的候选池里重新挑选, 避免 N 条推荐都是同一系列的相邻文章
- 多语言分词:中文使用
Intl.Segmenter(可切换为 2-gram),日文、韩文自动使用 对应语言的分词器;拉丁(含变音符号)、西里尔、希腊文字按词切分 - 确定性:相同分数按创建时间、路径排序,同一份源码重复构建结果一致
为什么不使用向量检索
文档站的规模通常在数百到数千篇之间,TF-IDF 在可解释性、构建耗时、产物体积上 都更有优势,也不需要在构建时调用任何外部服务。
配置
完整的配置项说明见 主题配置 - relatedPosts。
| 配置 | 类型 | 默认值 | 说明 |
|---|---|---|---|
limit | number | 4 | 推荐条数,取值 1–12 |
minScore | number | 0.12 | 相似度阈值,低于该值不展示 |
diversity | number | 0.3 | 结果多样性,0 关闭 |
recency | number | 0 | 时间衰减半衰期(年),0 不考虑新旧 |
scope | 'collection' | 'locale' | 'collection' | 候选范围 |
weights | object | 见上文 | 各信号权重 |
showExcerpt | boolean | false | 是否展示摘要 |
contentLimit | number | 2000 | 参与计算的正文长度 |
cjk | 'segmenter' | 'bigram' | 'segmenter' | 中文分词策略 |
exclude | string[] | [] | 排除的路径,支持 glob |
debug | boolean | false | 输出评分明细 |
常用组合
- 更聚焦:降低
diversity(如0.1)或提高minScore - 更发散:提高
diversity(如0.5)或降低minScore - 优先新文章:设置
recency(如0.5,即半衰期半年) - 跨集合推荐:设置
scope: 'locale'
手动指定
单篇文章可以用 frontmatter 完全接管推荐结果:
blog/hello.md
---
relatedPosts:
- /blog/vue3-reactivity/
- /blog/vue3-computed/
---或者关闭当前页的推荐:
blog/hello.md
---
relatedPosts: false
---手动列表在 构建期 解析:链接指向的页面不存在时会在构建日志中给出警告, 不会生成失效链接。
调优
打开调试日志
.vuepress/config.tsexport default defineUserConfig({ theme: plumeTheme({ relatedPosts: { debug: true }, }), })观察分数分布
构建时会输出每篇页面的 Top-N 分数:
[related-posts] /blog/vue3-reactivity/ 0.482 /blog/vue3-ref/ 0.311 /blog/vue3-computed/按目标调整
现象 调整方式 大部分页面没有推荐 降低 minScore(如0.08)或提高weights.content推荐内容明显无关 提高 minScore(如0.2)、提高weights.tags、降低weights.content推荐高度重复 提高 diversity旧文章长期占位 设置 recency
注意事项
- 加密页面与草稿页面不会作为推荐结果出现
- 只处理真实 Markdown 内容页:
article: false、home/friends等布局页面、 主题生成的虚拟列表页(标签页、归档页等)均不参与推荐 frontmatter.relatedPosts只在功能已开启的集合内生效
