内容关联生成系统为您的文章提供两种类型的关系:
┌───────────────┐
│ TF-IDF (Python) │ ← 高质量语义匹配
└──────┬────────┘
│ 失败/超时
┌──────▼────────┐
│ TagMatcher TS │ ← 降级到标签匹配
└───────────────┘
优势:
packages/linker/src/calculator/prev-next.tsnext = 更新的文章,prev = 更旧的文章packages/linker/src/matchers/tag-matcher.ts|A ∩ B| / sqrt(|A| × |B|)packages/linker/scripts/calculate_tfidf.pymax_features=5000 防止内存溢出packages/linker/src/bridge/python-bridge.tspackages/linker/src/orchestrator.ts运行以下命令时自动生成关系:
# 扫描并生成索引
npx tsx scripts/scan.ts --dir content/posts
# 重建索引(包含草稿)
npx tsx scripts/scan.ts --dir content/posts --include-drafts
生成的 content-index.json 包含:
{
"posts": {
"post-id": {
"id": "post-id",
"title": "文章标题",
"date": "2026-04-02T00:00:00Z",
"tags": ["标签1", "标签2"],
"contentHash": "abc123...",
"filepath": "/path/to/post.md",
"draft": false,
"prev": "older-post-id",
"next": "newer-post-id",
"related": [
{"id": "related-1", "title": "相关文章", "score": 0.8234}
]
}
}
}
要使用高质量的 TF-IDF 语义匹配:
pnpm python:install
这将安装:
jieba>=0.42.1 - 中文分词scikit-learn>=1.3.0 - TF-IDF 向量化numpy>=1.24.0 - 数值计算注意: 如果未安装 Python 依赖,系统会自动降级到基于标签的匹配。
设置 PYTHON 环境变量以使用特定的 Python 二进制文件:
export PYTHON=/usr/bin/python3
npx tsx scripts/scan.ts --dir content/posts
Python 桥接器默认缓存 TF-IDF 结果 1 小时。可以在 packages/linker/src/bridge/python-bridge.ts 中修改:
const bridge = new PythonBridge(
'packages/linker/scripts/calculate_tfidf.py',
30000, // timeout: 30 秒
3600000 // cacheTTL: 1 小时
)
| 操作 | 100 篇文章 | 500 篇文章 | 1000 篇文章 |
|---|---|---|---|
| TagMatcher | ~20ms | ~100ms | ~400ms |
| TF-IDF(首次运行) | ~5s | ~15s | ~30s |
| TF-IDF(缓存命中) | ~5ms | ~5ms | ~5ms |
症状: 日志显示 [LinkOrchestrator] Falling back to TagMatcher
可能原因:
解决方案: 系统会自动降级到基于标签的匹配。要修复:
# 安装 Python 依赖
pnpm python:install
# 或者继续使用 TagMatcher(效果也不错)
症状: 文章没有 prev/next/related 字段
可能原因:
解决方案:
# 扫描时包含草稿
npx tsx scripts/scan.ts --dir content/posts --include-drafts
症状: prev 指向更新的文章,next 指向更旧的文章
这是正确的行为:
next = 更新的文章(在排序数组中靠近索引 0)prev = 更旧的文章(在排序数组中靠近末尾)import { LinkOrchestrator } from '@content-hub/linker'
import { Post } from '@content-hub/core'
const orchestrator = new LinkOrchestrator()
const relationships = await orchestrator.generateRelationships(posts)
// 访问时间关系
const prevNext = relationships.prevNext.get('post-id')
console.log(prevNext?.prev) // 更旧的文章 ID
console.log(prevNext?.next) // 更新的文章 ID
// 访问语义关系
const related = relationships.related.get('post-id')
console.log(related) // 相关文章数组及分数
import { TagMatcher } from '@content-hub/linker'
import { calculatePrevNext } from '@content-hub/linker'
// 仅使用标签匹配
const tagMatcher = new TagMatcher()
const related = tagMatcher.findRelatedPosts(posts, currentPost, 3)
// 仅使用时间关系
const prevNext = calculatePrevNext(posts)
M1.2 之后的计划改进:
# 1. 查看已生成的关系
cat content-index.json | grep -B 2 -A 8 '"prev":'
cat content-index.json | grep -B 2 -A 8 '"related":'
# 应该看到:
# - prev/next 字段(基于日期)
# - related 数组(基于标签匹配或 TF-IDF)
# 1. 安装 Python 依赖
pnpm python:install
# 2. 重新生成索引
npx tsx scripts/scan.ts --dir content/posts --include-drafts
# 3. 检查日志,应该看到:
# [LinkOrchestrator] Python TF-IDF succeeded
# 4. 验证关系质量
cat content-index.json | jq '.posts["test-post-2"]'
# 1. 临时破坏 Python 环境
mv packages/linker/requirements.txt packages/linker/requirements.txt.bak
# 2. 重新运行 - 应该自动降级到 TagMatcher
npx tsx scripts/scan.ts --dir content/posts
# 3. 检查日志
# 应该看到:[LinkOrchestrator] Falling back to TagMatcher
# 4. 恢复
mv packages/linker/requirements.txt.bak packages/linker/requirements.txt