Files
my_ebook-to-mindmap/docs/architecture-aiservice-vs-bookprocessing.md
gavindiazandClaude Code 31ca07ea7a feat: ebook-to-mindmap desktop app with AI summary, book chat and mind-map export
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>
2026-09-25 23:00:24 +08:00

5.4 KiB
Raw Permalink Blame History

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
)
// ✅ 自动处理缓存
// ✅ 第二次调用同样参数会直接返回缓存

💡 设计优点

  1. 单一职责:aiService专注AI调用,bookProcessingService专注业务逻辑
  2. 可复用:aiService可以在其他场景使用(不仅限于电子书处理)
  3. 易测试:可以单独mock aiService来测试业务逻辑
  4. 缓存分离:缓存逻辑不污染AI服务

⚠️ 潜在改进建议

如果觉得两个文件有些"重复",可以考虑:

  1. 让bookProcessingService的所有方法都直接返回aiService的包装版本(带缓存)
  2. 考虑是否需要在aiService中保留非流式的方法(如generateChapterMindMap),如果都用流式可以删除
  3. 统一Chapter接口的定义(目前两个文件都有定义)

总结

这不是"重复代码",而是分层架构的体现!两个服务各司其职:

  • AIService:纯粹的AI API封装层
  • BookProcessingService:电子书业务逻辑层(依赖AIService + CacheService)

这种设计使得代码更加模块化、可维护和可测试。