13.4 Wiki 知识引擎
`rust-agent-wiki` 是一个基于文件系统的 Wiki 引擎,提供类型化页面、全文搜索(Tantivy)、概念图(Petgraph + Louvain)和 Agent 集成能力。
架构概览
graph TB
subgraph "Wiki 引擎"
SP[Spaces 空间管理]
PG[Typed Pages 类型化页面]
FT[Tantivy 全文搜索]
CG[Concept Graph 概念图]
end
subgraph "存储层"
FS[文件系统]
SCHEMA[JSON Schema 验证]
SHA[SHA256 哈希]
end
subgraph "Agent 集成"
AT[Agent Tools]
IN[指令注入]
end
SP --> FS
PG --> SCHEMA
PG --> SHA
FT --> FS
CG --> PG
AT --> SP
AT --> PG
AT --> FT
IN --> SP
核心概念
Spaces(空间)
Wiki 中最高级别的组织单元,类似于项目或命名空间。每个 Space 是一个独立的目录:
wiki/
├── rust-knowledge/
│ ├── _space.yaml # Space 元数据
│ ├── async-programming/ # Typed Page 目录
│ │ ├── _page.yaml # Page 元数据
│ │ └── content.md # Page 内容
│ └── error-handling/
│ ├── _page.yaml
│ └── content.md
└── design-patterns/
├── _space.yaml
└── ...
Typed Pages(类型化页面)
每个页面可以声明类型,支持 JSON Schema 验证:
# _page.yaml
name: async-programming
title: Rust 异步编程指南
page_type: knowledge
tags: [rust, async, programming]
created: "2025-01-15T10:00:00Z"
updated: "2025-06-01T14:30:00Z"
schema_version: "1.0"
支持的内容格式: - Markdown (`.md`) - YAML (`.yaml`) - TOML (`.toml`) - JSON (`.json`)
Tantivy 全文搜索
使用 Tantivy(Rust 原生的全文搜索引擎)构建搜索索引:
use tantivy::{schema::*, Index, doc};
// 构建搜索索引
let mut schema_builder = Schema::builder();
schema_builder.add_text_field("title", TEXT | STORED);
schema_builder.add_text_field("content", TEXT);
schema_builder.add_text_field("tags", TEXT);
schema_builder.add_text_field("page_type", STRING | STORED);
schema_builder.add_text_field("space", STRING | STORED);
let schema = schema_builder.build();
let index = Index::create_in_dir("./wiki_index", schema)?;
搜索功能: - 全文检索(支持中文分词) - 标签过滤 - 页面类型过滤 - 相关性评分排序
Concept Graph(概念图)
使用 Petgraph 构建页面之间的概念关系图,通过 Louvain 社区发现算法识别主题聚类:
use petgraph::graph::{DiGraph, NodeIndex};
use petgraph::algo::louvain;
// 构建概念图
let mut graph: DiGraph<String, f64> = DiGraph::new();
let node_a = graph.add_node("Rust Async".to_string());
let node_b = graph.add_node("Tokio Runtime".to_string());
let node_c = graph.add_node("Futures".to_string());
// 添加关系(边权重表示关联强度)
graph.add_edge(node_a, node_b, 0.9);
graph.add_edge(node_a, node_c, 0.8);
graph.add_edge(node_b, node_c, 0.7);
// Louvain 社区发现
let communities = louvain::louvain_partitions(&graph);
文件系统监控
Wiki 引擎通过 `notify` crate 实现实时文件系统监控:
use notify::{Watcher, RecursiveMode, Event};
let mut watcher = notify::recommended_watcher(|event: Result<Event, _>| {
match event {
Ok(event) => {
// 检测文件变更,自动重建 Tantivy 索引
rebuild_affected_indexes(&event);
}
Err(e) => tracing::error!("Watch error: {}", e),
}
})?;
watcher.watch(Path::new("./wiki"), RecursiveMode::Recursive)?;
支持的事件: - 文件创建 → 自动建立索引 - 文件修改 → 增量更新索引 - 文件删除 → 从索引移除
Agent 集成
注册为工具
use rust_agent_wiki::WikiEngine;
let wiki = WikiEngine::new("./wiki");
let agent = AgentBuilder::new("knowledge_agent")
.chat_client(client)
.instructions("你是知识库助手。可以使用 wiki_search、wiki_page 等工具。")
.with_tool(WikiSearchTool::new(&wiki))
.with_tool(WikiPageTool::new(&wiki))
.with_tool(WikiConceptTool::new(&wiki))
.build()?;
作为上下文注入
struct WikiContextProvider {
wiki: Arc<WikiEngine>,
}
#[async_trait]
impl IContextProvider for WikiContextProvider {
fn name(&self) -> &str { "WikiContextProvider" }
fn kind(&self) -> &str { "wiki" }
async fn on_invoking(
&self,
_agent: &dyn IAgent,
_session: &dyn ISession,
messages: &[ChatMessage],
_options: &AgentRunOptions,
) -> Result<ContextResult> {
let last_user_msg = messages.iter()
.rev()
.find(|m| m.role == "user");
if let Some(msg) = last_user_msg {
// 搜索相关 Wiki 页面
let results = self.wiki.search(&msg.content(), 5).await?;
if !results.is_empty() {
let context = results.iter()
.map(|r| format!("## {}\n{}", r.title, r.snippet))
.collect::<Vec<_>>()
.join("\n\n");
return Ok(ContextResult {
instructions: Some(format!(
"以下是与当前问题相关的 Wiki 知识:\n\n{}",
context
)),
..Default::default()
});
}
}
Ok(ContextResult::default())
}
}
完整示例
use rust_agent_wiki::{WikiEngine, SpaceConfig, PageType};
use std::path::Path;
async fn setup_wiki_and_agent() -> anyhow::Result<()> {
// 1. 初始化 Wiki 引擎
let wiki = WikiEngine::new(Path::new("./wiki"))
.with_space(SpaceConfig {
name: "rust-knowledge".into(),
title: "Rust 知识库".into(),
description: "Rust 编程语言相关技术文档".into(),
})
.with_page_type(PageType::new("tutorial")
.with_schema(json!({
"type": "object",
"properties": {
"difficulty": {"type": "string", "enum": ["beginner", "intermediate", "advanced"]},
"estimated_time": {"type": "string"}
}
})))
.build()?;
// 2. 创建页面
wiki.create_page(
"rust-knowledge",
"async-programming",
PageData {
title: "Rust 异步编程".into(),
page_type: "tutorial".into(),
content: "# Rust 异步编程\n\n...".into(),
metadata: json!({
"difficulty": "intermediate",
"estimated_time": "2 hours"
}),
tags: vec!["rust".into(), "async".into(), "tokio".into()],
},
).await?;
// 3. 全文搜索
let results = wiki.search("异步编程", 5).await?;
for result in &results {
println!("- {} (相关度: {:.2})", result.title, result.score);
}
// 4. 概念图查询
let related = wiki.get_related_concepts("async-programming", 5).await?;
println!("相关概念:");
for concept in &related {
println!(" - {} (关联强度: {:.2})", concept.name, concept.strength);
}
Ok(())
}
Crate 依赖
`rust-agent-wiki` 的依赖较重量,按需引入:
| 依赖 | 用途 | |------|------| | `tantivy 0.22` | 全文搜索引擎 | | `petgraph 0.6` | 图数据结构与算法 | | `jsonschema 0.26` | JSON Schema 验证 | | `notify 8` | 文件系统事件监控 | | `serde_yaml` / `toml` | 多格式配置解析 | | `sha2` / `hex` | 内容哈希计算 | | `walkdir` | 文件目录遍历 |
注意事项
1. **Tantivy 索引大小**:全文搜索索引会占用额外磁盘空间,大致为文本内容的 2-3 倍 2. **中文分词**:Tantivy 的中文分词性能不如专用中文搜索引擎(如 jieba-rs),大规模中文内容建议评估 3. **文件锁**:Wiki 引擎使用文件系统作为存储,网络文件系统(NFS)可能导致锁问题 4. **并发写入**:目前不支持多进程并发写入同一 Wiki 空间 5. **Louvain 算法**:概念图分析在大型图上可能较慢,适合页面数量在 10K 以下的场景