在 AI 编程助手日益普及的今天,Claude Code 正从单纯的代码生成工具演变为复杂工作流的协调者。Pieter Maes 最近展示了一个引人注目的案例:使用 Claude Code 处理 100 本非虚构书籍,构建语义相似性图,并实现交互式可视化前端。这个项目不仅展示了 AI 在非编码任务中的潜力,更揭示了全栈语义图构建的工程化路径。
从代码助手到工作流协调者:Claude Code 的角色转变
传统上,Claude Code 被定位为 AI 编程助手,专注于代码生成、调试和重构。然而,在这个书籍语义图项目中,Claude Code 扮演了完全不同的角色:工作流协调者和非编码任务执行者。
Pieter Maes 最初尝试构建传统的多阶段 LLM 管道,每个阶段都有精心设计的手工组装上下文。但当他简单地向 Claude Code 提供调试工具和最小提示 "find something interesting" 时,结果令人惊讶。正如他在博客中所说:"It immediately did a better job at pulling in what it needed than the pipeline I was trying to tune by hand, while requiring much less orchestration."
这种转变的核心在于 Claude Code 能够:
- 自主推断工具调用序列:比人工回忆更快地推断出所需的 CLI 调用序列
- 处理非刚性任务:自动化那些传统脚本难以处理的非刚性任务
- 支持迭代优化:通过自然语言指令调整工作流,无需重写复杂逻辑
例如,当 Pieter 改变对摘录长度的偏好时,他只需向 Claude Code 传达新偏好,Claude Code 就会查看所有现有 trail 并进行相应编辑,平衡整体含义的变化。这种灵活性在传统编程范式中几乎不可能实现。
技术架构:从 EPUB 解析到主题树构建
构建 100 本书籍的语义图需要精心设计的全栈架构。以下是核心组件及其工程实现:
1. 文本处理流水线
# 伪代码展示核心处理流程
def process_epub_pipeline(epub_path):
# 1. EPUB解析 - 使用selectolax替代BeautifulSoup
html_content = parse_epub_with_selectolax(epub_path)
# 2. 句子分割 - 使用wtpsplit的sat-6l-sm模型
sentences = split_sentences_with_wtpsplit(html_content)
# 3. 文本分块 - 500词块,尽量不打断段落
chunks = create_chunks(sentences, target_words=500)
# 4. 主题提取 - Gemini 2.5 Flash Lite
topics = extract_topics_with_gemini(chunks)
# 5. 嵌入存储 - sqlite-vec
store_embeddings_in_sqlite(topics, chunks)
关键工程决策:
- 选择 selectolax 而非 BeautifulSoup:基于速度和更简单的 API
- 500 词分块策略:平衡 token 节省与上下文完整性
- 实时清理而非预处理:仅在显示摘录时清理 EPUB 伪影,节省大量 token
2. 主题提取与去重
主题提取使用 Gemini 2.5 Flash Lite 模型,每个块提取 3-5 个主题。处理 100 本书籍消耗约 60M 输入 token,总成本约 £10。Pieter 发现提取的主题具有惊人的稳定性:"similar chunks often shared some of the exact same topic labels."
去重处理通过合并距离低于阈值的主题对来处理近义词,如 "Startup founder"、"Startup founders" 和 "Founder of startups"。
3. 图构建与树形聚类
主题集合通过以下步骤转换为可探索的图结构:
def build_semantic_graph(topics):
# 1. 创建图 - 使用igraph
graph = create_igraph_from_topics(topics)
# 2. 添加边 - 基于嵌入相似性和点互信息
add_edges_based_on_similarity(graph, topics)
# 3. 递归聚类 - Leiden算法
tree = apply_leiden_partitioning_recursive(graph)
# 4. 标签生成 - Gemini为每个聚类生成描述性标签
labels = generate_cluster_labels_with_gemini(tree)
return tree
Leiden 算法参数:
- 使用 Surprise 质量函数:无需调整参数
- 递归分区直到达到最小规模
- 每个聚类基于包含的所有主题由 Gemini 生成标签
新颖性搜索算法:工程实现细节
"有趣性" 难以量化优化,Pieter 借鉴了《Why Greatness Cannot Be Planned》中的观点,将新颖性作为搜索指导。实现方式包括:
1. 算法层面新颖性搜索
def calculate_novelty_score(topic_embedding, all_embeddings, k=10):
# 计算与k个最近邻的平均距离
distances = calculate_distances(topic_embedding, all_embeddings)
nearest_distances = sorted(distances)[:k]
novelty_score = np.mean(nearest_distances)
return novelty_score
def rank_search_results(query, topics, embeddings):
# 结合相关性和新颖性进行排序
relevance_scores = calculate_relevance(query, topics)
novelty_scores = calculate_novelty_scores(embeddings)
# 加权综合评分
combined_scores = 0.7 * relevance_scores + 0.3 * novelty_scores
return topics_sorted_by(combined_scores)
2. 提示层面新颖性引导
在提示层面,Claude Code 在构思阶段会查看所有现有 trail,并被要求避免任何概念重叠。Pieter 观察到:"This works fairly well, though it is often distracted by any topics related to secrecy, systems theory, or tacit knowledge."
交互式可视化:D3.js 前端工程实践
可视化前端采用 D3.js 构建,支持用户探索主题连接。关键工程考虑包括:
1. 数据流设计
// 简化版数据流架构
class SemanticGraphVisualizer {
constructor() {
this.graphData = null;
this.zoom = d3.zoom();
this.simulation = d3.forceSimulation();
}
async loadData() {
// 从Claude Code后端API获取数据
const response = await fetch('/api/semantic-graph');
this.graphData = await response.json();
this.initializeVisualization();
}
initializeVisualization() {
// 力导向图布局
this.simulation
.force('link', d3.forceLink().id(d => d.id))
.force('charge', d3.forceManyBody())
.force('center', d3.forceCenter());
// 交互功能
this.addZoomPanInteraction();
this.addNodeClickHandlers();
this.addSearchFunctionality();
}
}
2. 性能优化策略
- 增量渲染:仅渲染视口内的节点和边
- Web Workers:将力计算卸载到工作线程
- 虚拟化:对大型图使用虚拟滚动
- 缓存策略:本地存储常用查询结果
3. 用户体验设计
- 渐进式披露:从高级主题树开始,逐步深入细节
- 上下文保持:导航时保持相关上下文可见
- 多视图协调:同步图视图、列表视图和详情视图
CLI 工具设计:半 XML 格式与服务器架构
Claude Code 通过 CLI 工具与系统交互,这些工具采用独特的半 XML 输出格式:
<topics query="deception" count="1">
<topic id="47193" books="7" score="0.0173" label="Deception">
<chunk id="186" book="1">
<topic id="47192" label="Business deal"/>
<topic id="47108" label="Internal conflict"/>
<topic id="46623" label="Startup founders"/>
</chunk>
</topic>
</topics>
设计优势:
- 嵌套结构:支持相关内容的自然导航
- 上下文丰富:显示块包含的其他主题,提供额外探索线索
- 人类可读:虽然可能不是最 token 高效的格式,但从未达到上下文窗口限制
服务器架构优化:
# 资源加载优化
class CLIServer:
def __init__(self):
self.embedding_model = None
self.connection = None
def start_server(self):
# 首次调用时透明启动服务器进程
if not self.connection:
self.embedding_model = load_embedding_model()
self.connection = start_multiprocessing_server()
def handle_request(self, command):
# 通过multiprocessing.connection复用已加载资源
return self.connection.send_command(command)
工程挑战与解决方案
1. 成本控制
处理 100 本书籍的成本约为 £10,主要来自:
- Gemini 2.5 Flash Lite 调用:60M 输入 token
- 嵌入模型推理:google/embeddinggemma-300m
- 重排序模型:BAAI/bge-reranker-v2-m3
优化策略:
- 选择性处理:仅在实际显示时清理摘录
- 缓存重用:复用已计算的嵌入和主题
- 批量处理:优化 API 调用批处理大小
2. 主题提取稳定性
虽然 Gemini 提取的主题具有良好稳定性,但仍需处理:
- 近义词合并:基于嵌入距离阈值
- 质量过滤:过滤索引条目、致谢等无用内容
- 一致性检查:定期验证主题标签的一致性
3. 新颖性偏差
Pieter 观察到新颖性搜索可能过度关注特定主题领域:"It's as if the very act of finding connections in a corpus summons the spirit of Umberto Eco and amps up the conspiratorial thinking."
缓解策略:
- 多样性约束:强制探索不同主题领域
- 时间衰减:降低频繁出现主题的权重
- 人工引导:定期人工审查和调整搜索方向
可落地参数与监控要点
1. 生产部署参数
# 配置示例
processing:
chunk_size_words: 500
max_topics_per_chunk: 5
embedding_model: "google/embeddinggemma-300m"
reranker_model: "BAAI/bge-reranker-v2-m3"
graph:
similarity_threshold: 0.85
pmi_threshold: 0.1
leiden_resolution: 1.0
min_cluster_size: 10
search:
novelty_weight: 0.3
relevance_weight: 0.7
k_nearest_neighbors: 10
2. 监控指标
- 处理吞吐量:书籍 / 小时,块 / 秒
- 成本效率:£/ 百万 token,£/ 本书
- 主题质量:一致性得分,人工评估准确率
- 搜索效果:新颖性 - 相关性平衡,用户满意度
- 系统性能:API 响应时间,内存使用率
3. 回滚策略
- 版本化存储:所有中间结果版本化
- 检查点机制:定期保存处理状态
- A/B 测试:新旧算法并行运行比较
- 渐进式部署:逐步增加处理书籍数量
未来方向与工程启示
这个项目展示了几个重要的工程趋势:
1. AI 作为工作流协调者
Claude Code 的成功表明,AI 代理可以超越简单的任务执行,成为复杂工作流的智能协调者。这种模式特别适合:
- 非刚性任务:难以用传统脚本精确描述的工作
- 迭代优化:需要频繁调整和优化的流程
- 探索性任务:目标不明确,需要发现性学习
2. 全栈语义系统架构
从 EPUB 解析到 D3.js 可视化的完整堆栈展示了构建语义系统的工程复杂性。关键洞察包括:
- 数据流设计:平衡实时处理与批量处理的权衡
- 工具抽象:为 AI 代理设计直观的工具接口
- 可视化集成:将后端语义分析与前端交互深度集成
3. 成本感知的 AI 工程
£10 处理 100 本书的成本效益展示了 AI 工程在成本控制方面的成熟。工程团队需要:
- 精细化成本核算:按组件、按任务跟踪成本
- 优化策略组合:结合模型选择、批处理和缓存
- 价值导向设计:确保 AI 投入产生可衡量的业务价值
结语
Pieter Maes 的书籍语义图项目不仅是技术演示,更是 AI 工程实践的典范。它展示了如何将 Claude Code 从代码助手转变为工作流协调者,如何构建从文本处理到可视化展示的全栈系统,以及如何在成本控制下实现有意义的语义分析。
正如 Pieter 所反思的:"My mental model of the AI component changed: from a function mapping input to output, to a coworker I was assisting." 这种思维转变 —— 从将 AI 视为函数到视为协作伙伴 —— 可能是这个项目最重要的启示。
对于工程团队而言,这个案例提供了具体的参数、架构模式和最佳实践,可用于构建自己的语义分析系统。从 500 词分块策略到 Leiden 聚类参数,从半 XML CLI 格式到 D3.js 可视化模式,这些工程细节构成了可复用的知识资产。
在 AI 日益融入工程工作流的今天,这种全栈、成本感知、用户中心的 AI 系统设计方法,为未来的智能应用开发指明了方向。
资料来源:
- Pieter Maes, "Reading across books with Claude Code" - https://pieterma.es/syntopic-reading-claude/
- SynapseFlow 项目参考 - https://github.com/mrkingsleyobi/synapseflow
- D3.js 与 AI 代理集成模式 - https://relevanceai.com/agent-templates-software/d3-js