版本: 1.0.0-rc
更新: 2026-02-24
本文档详细说明 MemoryOS-Rust 的设计原理、实现细节和关键决策。
模拟人类记忆系统:短期记忆 → 工作记忆 → 长期记忆
STM (Short-Term Memory)
↓ 自动合并
MTM (Mid-Term Memory)
↓ 热度提升
LTM (Long-Term Memory)
Redis (STM):
- ✅ 极快的读写速度(< 1ms)
- ✅ 支持 List 数据结构(FIFO 队列)
- ✅ 支持 TTL(自动过期)
- ✅ 支持分布式锁(并发控制)
Qdrant (MTM/LTM):
- ✅ 高性能向量检索
- ✅ 支持过滤和元数据
- ✅ 支持批量操作
- ✅ 现代 Rust API
STM → MTM:
// 触发条件
if stm.len() >= capacity {
// 1. 获取分布式锁
let lock = acquire_lock("consolidation");
// 2. 读取所有 STM 消息
let messages = stm.get_all();
// 3. 生成 Embedding
let embedding = generate_embedding(&messages);
// 4. 存储到 MTM
mtm.upsert(Segment {
content: messages,
embedding,
heat: 0.0,
});
// 5. 清空 STM
stm.clear();
// 6. 释放锁
release_lock(lock);
}MTM → LTM:
// 触发条件
if segment.heat > threshold {
// 1. 提取用户画像
let profile = extract_profile(&segment);
// 2. 提取知识
let knowledge = extract_knowledge(&segment);
// 3. 更新 LTM
ltm.update_profile(user_id, profile);
ltm.add_knowledge(user_id, knowledge);
}MemoryOS-Rust 选择规则提取:
struct ExtractionRule {
marker: String, // "i like"
target: RuleTarget, // Preference
format: Option<String>,
}
// 示例规则
"i like" → Preference: "likes {value}"
"i work as" → Background: "works as {value}"
"my name is" → Background: "name is {value}"优点:
- ✅ 快速(< 1ms)
- ✅ 确定性(相同输入 → 相同输出)
- ✅ 无 LLM 成本
- ✅ 可配置(环境变量)
缺点:
- ❌ 灵活性较低
- ❌ 需要预定义规则
Mem0 使用 LLM 提取:
- ✅ 灵活、智能、准确
- ❌ 慢(1-3s)
- ❌ 成本高
- ❌ 不确定性
设计决策: 优先性能和成本,牺牲部分灵活性
传统分层架构问题:
- ❌ 层与层耦合
- ❌ 难以测试
- ❌ 难以替换实现
六边形架构优势:
- ✅ 领域逻辑独立
- ✅ 易于测试(Mock 适配器)
- ✅ 易于替换实现(换数据库)
- ✅ 清晰的依赖方向
Core (领域层)
↑ 依赖
Ports (接口层)
↑ 实现
Adapters (适配器层)
↑ 调用
Gateway (网关层)
依赖倒置: Core 不依赖任何外部实现
match (redis_available, qdrant_available) {
(true, true) => {
// Full Mode: 完整功能
DefaultMemoryManager::new(redis, qdrant, llm)
}
(true, false) | (false, true) => {
// Degraded Mode: 部分功能
DegradedMemoryManager::new(
redis.map(Some),
qdrant.map(Some),
llm
)
}
(false, false) => {
// Noop Mode: 仅 LLM
NoopMemoryManager::new(llm)
}
}| 模式 | Redis | Qdrant | 功能 |
|---|---|---|---|
| Full | ✅ | ✅ | STM + MTM + LTM |
| Degraded | ✅ | ❌ | STM only |
| Degraded | ❌ | ✅ | MTM + LTM only |
| Noop | ❌ | ❌ | LLM only |
关键: 单个后端故障不影响其他能力
⚠️ 限制: 当前实现中,AppState 持有启动时的配置快照。大部分配置变更需要重启服务。 详见 CONFIG_HOT_RELOAD_LIMITATION.md
// 设计目标:后台任务定期检查配置变更
// 当前状态:后台轮询任务已移除,配置在启动时加载一次
// 原因:AppState 持有 Arc<Config> 快照,运行时替换需要重构状态管理
tokio::spawn(async move {
let mut interval = tokio::time::interval(Duration::from_secs(5));
loop {
interval.tick().await;
if config_manager.file_changed() {
match config_manager.reload() {
Ok(new_config) => {
config.store(Arc::new(new_config));
info!("✅ Config hot-reloaded");
}
Err(e) => warn!("⚠️ Config reload failed: {}", e),
}
}
}
});关键技术:
ArcSwap: 原子指针交换,无锁读取tokio::spawn: 后台异步任务SystemTime: 文件修改时间检测
当前状态:
⚠️ 受限 — AppState 持有启动时快照,大部分配置变更需重启⚠️ 详见 docs/CONFIG_HOT_RELOAD_LIMITATION.md- ✅ 无锁读取(高性能)
- ✅ 支持 K8s ConfigMap
async fn current_health(&self) -> HealthStatus {
// 1. 实时探测 Redis
let redis_status = match self.redis_storage {
Some(ref redis) => {
match redis.ping().await {
Ok(_) => "up",
Err(_) => "down",
}
}
None => "bypassed",
};
// 2. 实时探测 Qdrant
let qdrant_status = match self.qdrant_storage {
Some(ref qdrant) => {
match qdrant.health_check().await {
Ok(_) => "up",
Err(_) => "down",
}
}
None => "bypassed",
};
// 3. 计算模式
match (redis_status, qdrant_status) {
("up", "up") => HealthStatus::Ready,
("up", "down") | ("down", "up") => HealthStatus::DegradedReady,
_ => HealthStatus::NotReady,
}
}关键: 每次请求都实时探测,不使用缓存
优势:
- ✅ 反映真实状态
- ✅ 快速故障检测
- ✅ 支持动态切换
问题: 多个实例同时合并 STM
解决方案:
// 1. Fencing Lock(分布式锁)
let lock_key = format!("lock:consolidation:{}", user_id);
let fencing_token = uuid::Uuid::new_v4().to_string();
// 2. 获取锁(SET NX + TTL)
let acquired = redis.set_nx_ex(
&lock_key,
&fencing_token,
15 // 15 秒 TTL
).await?;
if !acquired {
return Err(AppError::Conflict("Consolidation in progress"));
}
// 3. Lease Renewal(续租)
tokio::spawn(async move {
let mut interval = tokio::time::interval(Duration::from_secs(5));
loop {
interval.tick().await;
redis.expire(&lock_key, 15).await;
}
});
// 4. CAS 版本控制
let current_version = get_version(user_id).await?;
let new_version = current_version + 1;
// 5. 执行操作
consolidate_stm(user_id).await?;
// 6. CAS 更新版本
let success = redis.set_if_equal(
&version_key,
current_version,
new_version
).await?;
if !success {
return Err(AppError::Conflict("Version mismatch"));
}
// 7. 释放锁
redis.del(&lock_key).await?;关键技术:
- Fencing Lock: 防止多个实例同时操作
- Lease Renewal: 防止锁过期
- CAS: 防止并发修改冲突
// 1. 生成事件 ID
let event_id = format!("{}:{}:{}",
user_id,
message.role,
hash(&message.content)
);
// 2. 检查是否已处理
let dedup_key = format!("dedup:{}", event_id);
let exists = redis.exists(&dedup_key).await?;
if exists {
return Ok(()); // 已处理,跳过
}
// 3. 标记为已处理(TTL 2 小时)
redis.set_ex(&dedup_key, "1", 7200).await?;
// 4. 处理事件
process_event(event_id, message).await?;优势:
- ✅ 防止重复处理
- ✅ 自动过期(TTL)
- ✅ 高性能(Redis)
Client
│
│ POST /v1/chat/completions
▼
Gateway (Axum)
│
│ 1. 路由匹配
│ 2. 中间件处理
▼
3-Tier Router
│
│ 3. 复杂度分析
│ 4. 选择 LLM Tier
▼
Memory Manager
│
├─► 5. 检索 STM (Redis)
│ └─► LRANGE key 0 -1
│
├─► 6. 检索 MTM (Qdrant)
│ └─► search(embedding, limit=5)
│
└─► 7. 检索 LTM (Qdrant)
├─► get_profile(user_id)
└─► search_knowledge(user_id, query)
│
▼
8. 构建上下文
│
▼
LLM Adapter
│
│ 9. 调用 LLM API
▼
External LLM
│
│ 10. 返回响应
▼
Memory Manager
│
│ 11. 存储新消息到 STM
│ 12. 检查是否需要合并
▼
Gateway
│
│ 13. 返回响应
▼
Client
struct EmbeddingCache {
cache: RwLock<HashMap<String, Vec<f32>>>,
max_size: usize, // 1000
}
// 缓存命中率:待测试
// 性能提升:待基准测试验证// Redis 连接池
let redis_pool = RedisPool::new(
max_size: 100,
min_idle: 10,
timeout: Duration::from_secs(5),
);
// Qdrant 客户端复用
let qdrant_client = Arc::new(QdrantClient::new(...));// 并行检索
let (stm, mtm, ltm) = tokio::join!(
retrieve_stm(user_id),
retrieve_mtm(user_id, query),
retrieve_ltm(user_id, query),
);选择 Rust 的原因:
- ✅ 高性能(10x+ vs Python)
- ✅ 内存安全
- ✅ 并发安全
- ✅ 类型安全
代价:
- ❌ 开发速度较慢
- ❌ 学习曲线陡峭
选择规则提取的原因:
- ✅ 性能(< 1ms vs 1-3s)
- ✅ 成本(免费 vs $0.001/次)
- ✅ 确定性
代价:
- ❌ 灵活性较低
选择 Redis 的原因:
- ✅ 持久化
- ✅ 分布式支持
- ✅ 丰富的数据结构
代价:
- ❌ 网络延迟(~1ms)
选择 Qdrant 的原因:
- ✅ 高性能
- ✅ Rust 原生 API
- ✅ 丰富的过滤功能
- ✅ 开源
将 MemoryOS 的全部记忆管理能力通过 MCP (Model Context Protocol) 标准协议暴露给 AI 助手,使 Claude Desktop、Cursor、自定义 Agent 等客户端无需手写 HTTP 集成即可调用。
| 对比维度 | HTTP REST (Gateway) | MCP Server |
|---|---|---|
| 协议 | HTTP/JSON | JSON-RPC 2.0 over stdio/SSE |
| 发现 | 需要阅读 API 文档 | 客户端自动发现 tools/resources |
| 类型安全 | 手动校验 | JSON Schema 自动生成 (schemars) |
| 适用客户端 | Web/Mobile/Backend | AI Agent (Claude, Cursor, etc.) |
| 集成成本 | 手写 HTTP client | 零代码,配置文件即接入 |
MCP 是 HTTP API 的补充而非替代。两者共享同一套 Core/Ports/Adapters 业务逻辑。
方案 A: 独立 crate memoryos-mcp (推荐)
✅ 独立二进制,按需部署
✅ stdio 传输支持(Claude Desktop 必需)
✅ 不影响 Gateway 代码
✅ 可独立测试和发布
方案 B: 嵌入 Gateway 的 /mcp 端点
❌ Gateway 启动时必须初始化 MCP
❌ 无法支持 stdio 传输
❌ 增加 Gateway 复杂度
// Cargo.toml (memoryos-mcp) — 实际实现
[dependencies]
rmcp = { version = "0.3", features = ["server", "transport-io"] }
schemars = "0.8"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
reqwest = { version = "0.12", features = ["json"] }
tokio = { version = "1", features = ["full"] }
tracing = "0.1"
clap = { version = "4", features = ["derive"] }rmcp 是官方 Rust MCP SDK,基于 tokio,与项目技术栈一致。实际使用 v0.3 版本。
每个 MCP Tool 通过 #[tool] 宏注册,rmcp 自动生成 JSON Schema:
use rmcp::tool;
use schemars::JsonSchema;
#[derive(Debug, serde::Deserialize, JsonSchema)]
pub struct AddMemoryInput {
pub user_id: String,
pub content: String,
#[serde(default)]
pub metadata: Option<serde_json::Value>,
}
#[tool(
name = "add_memory",
description = "存储对话或事实到短期记忆 (STM)"
)]
async fn add_memory(input: AddMemoryInput) -> Result<String, McpError> {
let storage = get_storage().await;
storage.add_short_term_message(
&input.user_id,
&input.content,
input.metadata,
).await?;
Ok(format!("Memory stored for user {}", input.user_id))
}MCP Server 采用 Gateway 代理模式,所有 tool call 转发到 Gateway HTTP API:
| MCP Tool | Gateway 端点 | 功能 |
|---|---|---|
add_memory |
POST /v1/memory/add |
存储消息到 STM |
search_memories |
POST /v1/memory/retrieve |
语义搜索记忆 |
get_memories |
POST /v1/memory/retrieve |
获取用户全部记忆 |
delete_memory |
POST /v1/security/gdpr/delete |
删除用户数据 (GDPR) |
query_graph |
POST /v1/graph/query |
知识图谱查询 |
chat |
POST /v1/chat |
记忆增强对话 |
health_check |
GET /v1/health |
系统健康检查 |
// stdio 模式(本地部署)
async fn run_stdio() -> Result<()> {
let transport = rmcp::transport::stdio();
let server = McpServer::new(build_tools(), build_resources());
server.serve(transport).await
}
// SSE 模式(远程部署)
async fn run_sse(addr: SocketAddr) -> Result<()> {
let transport = rmcp::transport::sse::SseServer::new(addr);
let server = McpServer::new(build_tools(), build_resources());
server.serve(transport).await
}
// CLI 入口
#[derive(clap::Parser)]
struct Cli {
#[arg(long, default_value = "stdio")]
transport: TransportMode,
#[arg(long, default_value = "127.0.0.1:3001")]
sse_addr: SocketAddr,
#[arg(long, default_value = "config.toml")]
config: PathBuf,
}MCP Resources 提供只读数据订阅,客户端可以 list + read:
use rmcp::resource;
#[resource(
uri = "memory://{user_id}/profile",
name = "User Profile",
description = "用户长期画像数据",
mime_type = "application/json"
)]
async fn user_profile(user_id: String) -> Result<String, McpError> {
let storage = get_storage().await;
let profile = storage.get_long_term(&user_id, "profile").await?;
Ok(serde_json::to_string(&profile)?)
}MCP 错误映射到 JSON-RPC error codes:
| 场景 | JSON-RPC Code | 说明 |
|---|---|---|
| 参数缺失/非法 | -32602 | Invalid params |
| 用户未找到 | -32001 | 自定义业务错误 |
| 存储不可用 | -32002 | 降级返回缓存数据 |
| 认证失败 | -32003 | API Key 无效 |
| 内部错误 | -32603 | 兜底错误 |
- 共享状态: 通过
Arc<AppState>共享存储连接池,与 Gateway 相同模式 - 认证: MCP 协议本身不含认证,stdio 模式依赖本地权限,SSE 模式通过配置的 API Key 在 tool handler 内校验
- GDPR: delete_memory tool 调用与 Gateway 相同的 GdprManager,审计记录统一
场景 1: 开发者本地使用 (stdio)
┌──────────────┐ stdio ┌──────────────┐ HTTP ┌──────────────┐
│ Claude │ ←────────────→ │ memoryos-mcp │ ──────────→ │ Gateway:8080 │
│ Desktop │ stdin/stdout │ (binary) │ │ │
└──────────────┘ └──────────────┘ └──────┬───────┘
│
┌──────▼───────┐
│ Qdrant+Redis │
└──────────────┘
场景 2: Gateway + MCP 共存 (推荐生产部署)
┌──────────────┐ ┌──────────────┐
│ Web App │──HTTP REST───→ │ Gateway:8080 │──→ Core+Adapters
└──────────────┘ └──────────────┘ ↑
│ HTTP
┌──────────────┐ ┌──────────────┐ │
│ AI Agent │──MCP stdio───→ │ MCP Server │───────┘
└──────────────┘ └──────────────┘
更新时间: 2026-02-20
版本: 0.13.0
以下设计文档中的版本号 (v0.x.0) 为历史开发标记。当前版本为 v1.0.0-rc。
服务分离: 业务 API (gateway) 和管理 API (admin) 物理隔离,部署在不同网络区域。
最小权限: RBAC 模型确保每个用户只能访问其角色允许的资源。
租户隔离: 所有数据操作自动按 tenant_id 过滤,防止跨租户数据泄漏。
pub enum Role {
SuperAdmin, // 全局管理: 租户CRUD + 所有权限
Admin, // 租户管理: 用户管理 + 数据读写 + 审计
User, // 普通用户: 数据读写
ReadOnly, // 只读用户: 仅读取
}pub enum Permission {
ReadMemory, // 读取记忆数据
WriteMemory, // 写入记忆数据
ManageUsers, // 管理用户(分配角色)
ManageTenants, // 管理租户(CRUD)
ViewAudit, // 查看审计日志
ManageConfig, // 修改系统配置
}Request → Auth Middleware → 提取 API Key
→ 查询 RbacManager → 获取 Role
→ 检查 Permission → 允许/拒绝
pub struct Tenant {
pub id: String, // UUID
pub name: String,
pub description: String,
pub max_users: u32, // 最大用户数
pub storage_quota_mb: u64, // 存储配额
pub api_rate_limit: u32, // API 调用限制/分钟
pub enabled: bool,
pub created_at: DateTime<Utc>,
}注意: 以下为计划中的数据层隔离方案,当前版本 (v0.12.1) 已实现租户管理和 RBAC 权限控制, 数据层自动过滤将在后续版本实现。
- Qdrant (计划): 所有查询添加
tenant_idpayload filter - Redis (计划): key 前缀
{tenant_id}:{key} - 审计日志: 每条记录标记
tenant_id
- 安全: 管理 API 不暴露到公网
- 独立认证: 管理员可用不同认证方式(LDAP/SSO)
- 审计清晰: 管理操作和业务操作日志分离
- 独立部署: 管理服务可以独立升级/重启
| 端点 | 方法 | 说明 |
|---|---|---|
/api/v1/tenants |
GET/POST | 租户列表/创建 |
/api/v1/tenants/:id |
GET/PUT/DELETE | 租户详情/更新/删除 |
/api/v1/users |
GET/POST | 用户列表/创建 |
/api/v1/users/:id |
GET/PUT/DELETE | 用户详情/更新/删除 |
/api/v1/users/:id/roles |
PUT | 分配角色 |
/api/v1/audit/logs |
GET | 审计日志查询 |
/api/v1/system/stats |
GET | 系统统计 |
将高频问答自动提升为 FAQ:
- ⚡ 极速响应(Router Tier 0 FAQ 直接命中,跳过 LLM,✅ v0.3.0 已实现)
- 🎯 精准匹配(相似度阈值可配置)
- 🔄 自动更新(基于访问频率和热度计算)
- 📚 知识沉淀(本地 Markdown + S3 + Confluence 导出,✅ v0.3.0 已实现)
职责: 记录和计算记忆热度
数据结构:
pub struct MidTermSegment {
pub id: Uuid,
pub user_id: String,
pub summary: String,
pub embedding: Vec<f32>,
// FAQ 热度字段
pub access_count: u32, // 访问次数
pub heat_score: f32, // 热度分数
pub last_accessed: Option<DateTime>,
pub memory_type: MemoryType, // QA/Candidate/FAQ
}
pub enum MemoryType {
QA, // 普通问答
FaqCandidate, // FAQ 候选
Faq, // 正式 FAQ
}热度计算公式:
heat_score = (access_count * 10.0)
+ (positive_feedback * 5.0)
- (days_since_created * 0.5)设计考虑:
- 访问次数权重最高(10.0)
- 时间衰减防止过时内容
- 预留反馈机制接口
职责: 扫描并提升高频问答
提升规则:
// QA → FaqCandidate
if access_count >= 10 && heat_score >= 50.0 {
promote_to_candidate();
}
// FaqCandidate → Faq
if access_count >= 20 && heat_score >= 100.0 {
promote_to_faq();
}提升历史:
pub struct PromotionRecord {
pub id: Uuid,
pub memory_id: Uuid,
pub from_type: MemoryType,
pub to_type: MemoryType,
pub reason: String,
pub heat_score: f32,
pub access_count: u32,
pub promoted_at: DateTime,
}后台任务:
// 每小时扫描一次
tokio::spawn(async move {
let mut interval = tokio::time::interval(Duration::from_secs(3600));
loop {
interval.tick().await;
let result = promoter.scan_and_promote(&mut segments).await;
tracing::info!("提升 {} 个候选", result.promoted_to_candidate.len());
}
});职责: 导出成熟 FAQ 为知识库
筛选条件:
fn filter_exportable(&self, segments: &[MidTermSegment]) -> Vec<&MidTermSegment> {
segments.iter().filter(|s| {
s.memory_type == MemoryType::Faq
&& s.access_count >= 10
&& (now - s.created_at).num_days() >= 30
}).collect()
}智能分类:
fn extract_category(&self, segment: &MidTermSegment) -> String {
let summary_lower = segment.summary.to_lowercase();
if summary_lower.contains("wifi") || summary_lower.contains("网络") {
"网络问题"
} else if summary_lower.contains("密码") {
"账号密码"
} else if summary_lower.contains("报销") {
"财务报销"
} else if summary_lower.contains("请假") {
"考勤休假"
} else {
"其他"
}
}Markdown 生成:
# FAQ 知识库
**生成时间**: 2026-02-19 00:00:00
---
## 📑 目录
- [网络问题](#网络问题)
- [账号密码](#账号密码)
- [财务报销](#财务报销)
---
## 网络问题
### 1. WiFi 密码是多少?
**访问次数**: 25 | **热度**: 245.5
**创建时间**: 2026-01-15
**最后访问**: 2026-02-18
---导出目标:
pub enum ExportTarget {
Local(String), // 本地文件系统
S3 { bucket, prefix, endpoint }, // S3/OSS
Confluence { base_url, space }, // Confluence
}用户提问
↓
检索相似记忆
↓
更新 access_count++
↓
计算 heat_score
↓
存回 Qdrant
↓
[后台任务]
↓
扫描高热度记忆
↓
提升为 FAQ
↓
[定时任务]
↓
导出为 Wiki
// 不要每次访问都写 Qdrant
// 使用内存缓存,定期批量写入
let mut batch = Vec::new();
for segment in segments {
tracker.record_access(&mut segment);
batch.push(segment);
if batch.len() >= 100 {
storage.batch_update(&batch).await?;
batch.clear();
}
}// Wiki 导出不阻塞主流程
tokio::spawn(async move {
let result = exporter.export(markdown).await;
tracing::info!("导出完成: {:?}", result);
});// 避免重复计算
pub struct HeatTracker {
cache: Arc<RwLock<HashMap<Uuid, f32>>>,
}❌ Redis 问题:
- 重启后数据丢失
- 不支持向量检索
- 难以做复杂过滤
✅ Qdrant 优势:
- 持久化存储
- 原生向量检索
- 支持元数据过滤
- 统一存储架构
渐进式提升:
- QA: 新问答,观察期
- Candidate: 高频但需验证
- FAQ: 确认高质量
防止误判:
- 避免低质量内容直接成为 FAQ
- 给人工审核留出空间
- 支持降级机制
实用性:
- S3/Confluence 需要额外配置
- 本地文件最简单
- 可以手动上传
扩展性:
- 接口已预留
- 后续可轻松添加
#[tokio::test]
async fn test_faq_lifecycle() {
// 1. 创建普通问答
let mut segment = create_qa("WiFi密码?", 0);
assert_eq!(segment.memory_type, MemoryType::QA);
// 2. 模拟 15 次访问
for _ in 0..15 {
tracker.record_access(&mut segment);
}
// 3. 检查提升为候选
assert!(tracker.should_promote(&segment));
promoter.scan_and_promote(&mut [segment]).await;
assert_eq!(segment.memory_type, MemoryType::FaqCandidate);
// 4. 继续访问,提升为 FAQ
for _ in 0..10 {
tracker.record_access(&mut segment);
}
promoter.scan_and_promote(&mut [segment]).await;
assert_eq!(segment.memory_type, MemoryType::Faq);
// 5. 导出为 Wiki
let exportable = exporter.filter_exportable(&[segment]);
assert_eq!(exportable.len(), 1);
}// 使用 LLM 自动分类
async fn classify_with_llm(&self, segment: &MidTermSegment) -> String {
let prompt = format!("将以下问题分类:{}", segment.summary);
let response = llm.complete(prompt).await?;
response.category
}// 自动翻译 FAQ
if user_lang != faq_lang {
let translated = translator.translate(faq.content, user_lang).await?;
return translated;
}// 测试不同提升阈值
if experiment_group == "A" {
threshold = 50.0;
} else {
threshold = 30.0;
}FAQ 系统通过三个核心组件实现了从问答到知识库的自动化流程:
- HeatTracker: 精确追踪访问热度
- AutoPromoter: 智能提升高频问答
- WikiExporter: 自动导出为知识库
当前状态 (v0.9.0):
- 响应速度: FAQ 直接命中绕过 LLM,具体延迟待基准测试
- 提升准确率: 基于访问次数和热度分数,待生产验证
- 导出质量: 本地 Markdown + S3 + Confluence 全部可用
实现状态:
- ✅ HeatTracker: 热度计算和追踪已实现
- ✅ AutoPromoter: 自动提升逻辑已实现
- ✅ WikiExporter: 本地 Markdown 导出已实现
- ✅ WikiExporter: S3 导出已实现 (OpenDAL S3ExportBackend, v0.3.0)
- ✅ WikiExporter: Confluence 导出已实现 (REST API ConfluenceExportBackend, v0.3.0)
- ✅ Router Tier 0: FAQ 直接命中已集成到路由器 (v0.3.0)
- ✅ FAQ 管理 API: candidates/promote/delete/history/stats (v0.3.0)
- ✅ LLM FAQ 分类: LlmFaqClassifier + /v1/admin/faq/classify API (v0.10.0)
- ✅ 错误处理和后台任务支持