Tauri v2 + React 19 desktop app. AI summary with pause/resume and checkpoint resume, book-chat with RAG and chat sessions, unified data persistence, mind-map download/export, and a Tauri build pipeline. Co-Authored-By: Claude Code <noreply@anthropic.com>
5.4 KiB
5.4 KiB
AIService vs BookProcessingService 架构分析
文档创建时间:2026-02-07
📋 文件职责分析
aiService.ts - AI底层服务层
职责:与AI API直接交互
-
核心功能:封装所有与AI模型的直接通信
-
主要方法:
summarizeChapter()- 生成章节总结analyzeConnections()- 分析章节关联generateChapterMindMapStream()- 生成章节思维导图(流式)generateCombinedMindMapStream()- 生成整书思维导图(流式)generateContent()/generateContentStream()- 底层内容生成parseJsonResponse()- 解析AI返回的JSON
-
特点:
- 只负责调用AI API并返回结果
- 处理流式响应和普通响应
- 处理reasoning(思考过程)
- 不涉及缓存和业务逻辑
bookProcessingService.ts - 业务处理服务层
职责:电子书处理的业务逻辑和流程编排
-
核心功能:协调AI服务和缓存服务,处理电子书相关业务
-
主要方法:
groupChaptersByTag()- 按标签分组章节processSummaryGroup()- 处理文字总结模式processMindMapGroup()- 处理思维导图模式generateConnections()- 带缓存的章节关联分析generateOverallSummary()- 带缓存的全书总结mergeMindMaps()- 合并多个章节思维导图generateCombinedMindMap()- 带缓存的整书思维导图
-
特点:
- 调用
aiService来获取AI生成内容 - 集成
cacheService进行缓存管理 - 处理章节分组、流式更新节流等业务逻辑
- 添加调试日志(
console.log)
- 调用
🔗 两个文件的关系
┌─────────────────────────────────┐
│ UI组件 (SummaryPage.tsx等) │
└────────────┬────────────────────┘
│
▼
┌─────────────────────────────────┐
│ BookProcessingService │ ← 业务编排层
│ - 缓存管理 │
│ - 流程控制 │
│ - 章节分组 │
└────────────┬────────────────────┘
│
▼
┌─────────────────────────────────┐
│ AIService │ ← AI底层服务
│ - 直接调用AI API │
│ - 处理流式响应 │
│ - 解析AI返回 │
└─────────────────────────────────┘
❓ 为什么看起来有重复内容?
你观察到的"重复"实际上是分层设计导致的包装调用:
示例对比:
aiService.ts - 基础AI调用
async generateChapterMindMapStream(
content: string,
outputLanguage: SupportedLanguage = 'en',
customPrompt?: string,
abortSignal?: AbortSignal,
onStreamUpdate?: (data: { plaintext: string; mindMap: MindElixirData | null }) => void
): Promise<MindElixirData>
- ✅ 只管调用AI
- ✅ 处理流式响应
- ❌ 不管缓存
bookProcessingService.ts - 带缓存的业务调用
async processMindMapGroup(
group: TempChapterGroup,
fileName: string,
outputLanguage: SupportedLanguage,
customPrompt: string,
abortSignal: AbortSignal,
onStreamUpdate?: (data: { mindMap: MindElixirData | null }) => void
): Promise<{ group: ChapterGroup; chapters: Chapter[] }>
- ✅ 先检查缓存
- ✅ 缓存未命中时调用
aiService.generateChapterMindMapStream() - ✅ 结果写入缓存
- ✅ 处理分组逻辑
- ✅ 添加节流更新(每500ms)
🎯 使用场景
场景1:只需要AI生成,不需要缓存
const aiService = new AIService(config)
const mindMap = await aiService.generateChapterMindMapStream(
content,
'zh',
customPrompt,
signal
)
场景2:电子书处理(需要缓存+分组)
const bookService = new BookProcessingService(aiService, cacheService)
const result = await bookService.processMindMapGroup(
group,
fileName,
'zh',
customPrompt,
signal
)
// ✅ 自动处理缓存
// ✅ 第二次调用同样参数会直接返回缓存
💡 设计优点
- 单一职责:
aiService专注AI调用,bookProcessingService专注业务逻辑 - 可复用:
aiService可以在其他场景使用(不仅限于电子书处理) - 易测试:可以单独mock
aiService来测试业务逻辑 - 缓存分离:缓存逻辑不污染AI服务
⚠️ 潜在改进建议
如果觉得两个文件有些"重复",可以考虑:
- 让
bookProcessingService的所有方法都直接返回aiService的包装版本(带缓存) - 考虑是否需要在
aiService中保留非流式的方法(如generateChapterMindMap),如果都用流式可以删除 - 统一
Chapter接口的定义(目前两个文件都有定义)
总结
这不是"重复代码",而是分层架构的体现!两个服务各司其职:
- AIService:纯粹的AI API封装层
- BookProcessingService:电子书业务逻辑层(依赖AIService + CacheService)
这种设计使得代码更加模块化、可维护和可测试。