architecture AI architecture - WangYajun369/ai-writing-platform GitHub Wiki

AI 暡块架构

适甚版本1.7.0 | 最后栞对2026-09-05

涵盖 AI 流匏对话工具箱、AI 䟧面板对话经 Agent 匕擎、RAG 向量检玢预留、内容总结、连接测试。 Agent 自劚化匕擎Rust 原生及见 Agent 匕擎架构。


目圕

  1. 架构总览
  2. 服务商配眮
  3. Rust 后端暡块
  4. 流匏对话
  5. RAG 检玢䞎 Embedding
  6. 内容总结
  7. 连接测试
  8. 前端组件
  9. 状态䞎类型
  10. AI 工具箱
  11. 关键垞量
  12. 讟计评价䞎䌘化方向

1. 架构总览

┌──────────────────────────────────────────────────────────┐
│                    前端 (React/TypeScript)                 │
│  AiSidePanel.tsx         AiToolboxPanel.tsx              │
│  (AI 对话面板·4 技胜)      (䞉栏工具箱·预讟 Prompt)          │
│       └───────────────┬───────────────┘                  │
│                 useAiChat.ts                             │
│        流匏事件监听 / 历史总结 / 错误恢倍                 │
│                       │                                  │
│  Zustand aiSlice + Jotai aiPanelOpenAtom                 │
│  tauri-bridge.tsaiApi + 组件盎调 Agent 呜什            │
├───────────────────────┌───────────────────────────────────
│                 Tauri IPC 蟹界                            │
├───────────────────────┌───────────────────────────────────
│  Rust 对话䞎总结层 commands/ai/ + commands/agent/         │
│  ┌────────────────┬────────────────┬──────────────┐      │
│  │ agent/skills.rs│   chat.rs      │ embedding.rs  │      │
│  │ engine.rs      │ 工具箱流匏对话  │ RAG/玢匕(预留) │      │
│  │ AI 面板对话     │  OpenAI SSE    │               │      │
│  │ (ReAct+工具)    │                │ summarize.rs  │      │
│  │                │                │ 章节/对话总结  │      │
│  └──────┬─────────┎───────┬────────┎────────┬──────┘      │
│         â–Œ                 â–Œ                 â–Œ             │
│  emit('agent-       emit('ai-stream-   emit('chapter-/    │
│  stream-chunk')    chunk')             conversation-      │
│  (chunk/done/      (thinking/           summary-done')    │
│   error/cancelled)  answering/retrying)                   │
└───────────────────────────────────────────────────────────┘

关键讟计决策

  1. 流匏请求完党圚 Rust 端通过 reqwest 倄理前端只通过 Tauri 事件接收增量文本规避浏览噚 CORS / 流匏解析问题
  2. 支持 Ollama 原生协议NDJSON䞎 OpenAI 兌容协议SSE䞀条路埄工具箱/总结盎连场景
  3. v1.2 èµ· AI 䟧面板对话统䞀由 Agent 匕擎驱劚useAiChat.handleSend() → execute_agent_skill默讀 writing 技胜Prompt 构建䞎䞊䞋文检玢由匕擎内郚完成工具箱保留 stream_ai_chat 盎连
  4. RAG/Embedding 䞺预留胜力后端 rag_search / trigger_embedding / check_embedding_status 呜什已实现并泚册䜆讟眮页标记「预留」圓前对话䞊䞋文由 Agent 匕擎内眮工具章节读取/搜玢提䟛triggerEmbedding 无前端 UI 接线
  5. 对话配眮AiChatConfig䞎 RAG/Embedding 配眮RagConfig完党解耊各自独立管理 API Key、端点、暡型
  6. 各服务商 API Key 独立存傚bigmodelApiKey / deepseekApiKey
  7. AI 配眮经 localStorage 持久化自劚兌容旧版扁平栌匏迁移
  8. 流匏事件䞉阶段通知thinking → answering → done

v1.0.0 变曎原 commands/ai.rs纊 1265 行已拆分䞺 ai/{chat,embedding,summarize,test}.rs 四䞪子暡块。 v1.2.0 变曎Agent 迁移䞺 Rust 原生后AI 面板对话接入 Agent 匕擎见 Agent 匕擎架构。


2. 服务商配眮

2.1 对话服务商

服务商 标识 默讀端点 默讀暡型 可选暡型
智谱 BigModel bigmodel https://open.bigmodel.cn/api/paas/v4 glm-5.1 glm-5.1
DeepSeek deepseek https://api.deepseek.com deepseek-v4-flash deepseek-v4-flash、deepseek-v4-pro
Ollama ollama http://127.0.0.1:11434 qwen2.5:7b 任意本地暡型
自定义 custom 甚户填写 甚户填写 —

2.2 RAG / Embedding 服务商

RAG 仅支持智谱 BigModelDeepSeek 䞍提䟛 Embeddings API

服务商 默讀端点 Embedding 暡型
智谱 BigModel https://open.bigmodel.cn/api/paas/v4 embedding-3

2.3 胜力对比

胜力 智谱 BigModel DeepSeek Ollama
流匏对话 ✅ ✅ ✅
深床思考 / 掚理 ✅ ✅ ❌
Embedding 向量 ✅ (embedding-3) ❌ ❌
RAG 语义检玢 ✅ ❌ ❌

2.4 默讀配眮垞量

定义于 src/components/settings/constants.ts

PROVIDER_DEFAULTS = {
  bigmodel: { endpoint: 'https://open.bigmodel.cn/api/paas/v4', model: 'glm-5.1' },
  deepseek: { endpoint: 'https://api.deepseek.com',             model: 'deepseek-v4-flash' },
  ollama:   { endpoint: 'http://127.0.0.1:11434',               model: 'qwen2.5:7b' },
  custom:   { endpoint: '',                                      model: '' },
}
RAG_PROVIDER_DEFAULTS = {
  bigmodel: { endpoint: 'https://open.bigmodel.cn/api/paas/v4', embeddingModel: 'embedding-3' },
}

3. Rust 后端暡块

文件 呜什 职莣
ai/chat.rs stream_ai_chat SSE/NDJSON 流匏对话、重试、超时、buffer 刷新
ai/embedding.rs rag_search、trigger_embedding、check_embedding_status、test_rag_connection 向量检玢、批量玢匕、状态检查
ai/summarize.rs summarize_chapter、summarize_conversation 章节总结非流匏、对话压猩滑劚窗口
ai/test.rs test_ai_connection、test_rag_connection 连通性测试

栞心数据结构

/// RAG 检玢结果
#[derive(Serialize)]
pub struct RagResult {
    pub snippet: String,
    #[serde(rename = "sourceId")]  pub source_id: String,
    #[serde(rename = "sourceTitle")] pub source_title: String,
    pub distance: f64,
}

/// 流匏对话请求参数
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StreamChatArgs {
    pub provider: String,        // "ollama" | "openai_compatible"
    pub endpoint: String,
    pub model: String,
    pub temperature: f64,
    pub max_tokens: Option<u32>,
    pub api_key: Option<String>,
    pub messages: Vec<ChatMessage>,
    pub thinking_enabled: bool,  // 掚理暡型思考暡匏
}

/// 流匏事件莟蜜掚送到前端的增量
#[derive(Debug, Clone, Serialize)]
pub struct StreamEvent {
    pub content: String,          // 环积的正匏蟓出
    pub thinking: String,         // 环积的思考过皋
    pub phase: String,            // "thinking" | "answering" | "retrying" | "done"
    pub done: bool,
    pub error: Option<String>,
    pub usage: Option<UsageInfo>, // Token/字数甚量仅 done
}

/// Embedding 玢匕状态
pub struct EmbeddingStatus {
    pub total_chapters: usize,
    pub total_world_cards: usize,
    pub indexed_chapters: usize,
    pub indexed_world_cards: usize,
    pub stale: bool,              // total > indexed 侔 > 0 时䞺 true
}

4. 流匏对话 commands/ai/chat.rs

4.1 完敎铟路

v1.2 èµ· useAiChat 已改䞺经 Agent 匕擎执行execute_agent_skillchat.rs 盎连铟路保留给 AI 工具箱AiToolboxPanel → aiApi.streamChat等场景。䞀条铟路劂䞋

铟路 AAI 䟧面板对话圓前默讀走 Agent 匕擎

甚户蟓入AI 䟧面板→ useAiChat.handleSend()
  ↓
1. 历史压猩过长时先 summarize_conversation 滑劚窗口压猩可选
  ↓
2. 泚册 listen('agent-stream-chunk')按 requestId 过滀
  ↓
3. invoke('execute_agent_skill', { skill:'writing', bookId, message, aiConfig, requestId, ... })
  ↓ [Rust commands/agent/]
4. engine.rs 组装 Prompt基础 + 场景提瀺 + 记忆段→ reqwest POST /chat/completions (stream: true)
5. 需芁䞊䞋文时调甚工具经 repository 层盎读 SQLite
  ↓
6. emit('agent-stream-chunk', { event: chunk/done/error/cancelled }) → 前端 RAF 猓冲合并枲染
  ↓
7. persistAiConversation() → localStorage结束事件后

铟路 B工具箱 / 盎连场景走 stream_ai_chat

AiToolboxPanel → aiApi.streamChat() → invoke('stream_ai_chat')
  ↓ [Rust commands/ai/chat.rs]
reqwest POST {endpoint}/chat/completions (stream: true)
  → emit('ai-stream-chunk', StreamEvent) → 前端实时枲染
  → [DONE] → 曎新消息含 usage / 思考过皋

本章 4.24.6 的客户端配眮、阶段管理、容错、协议对比䞎思考暡匏均针对铟路 Bchat.rs。

4.2 HTTP 客户端配眮

Client::builder()
    .connect_timeout(30s)        // 连接超时
    .http1_only()                // 仅 HTTP/1.1SSE 兌容
    .no_gzip().no_brotli()       // 犁甚自劚解压
    .tcp_keepalive(120s)         // 防长思考期闎断连

4.3 阶段管理

阶段 phase 诎明
总结䞭 summarizing 前眮章节总结原文 > 300 字
思考䞭 thinking 倄理 reasoning_content未收到 content
蟓出䞭 answering 收到第䞀䞪 content 增量后切换
重试䞭 retrying 眑络波劚自劚重试
完成 done 收到 [DONE] 或流自然结束

4.4 容错机制

自劚重试

  • 最倚重试 2 次指数退避1s → 2s
  • 可重试timeout、connection reset、5xx、429、空内容
  • 䞍可重试401、403、404讀证/权限问题盎接返回

双层超时

  • 10 分钟党局超时
  • 60 秒单 chunk 读取超时tokio::time::timeout刀定䞺半匀连接

断流保底

  • flush_sse_buffer() 从残留 buffer 提取最后的内容/思考/token 甹量
  • 已有内容时以 done 事件收尟附垊错误提瀺保留已生成内容而非敎䜓报错

4.5 䞀种协议对比

特性 OllamaNDJSON OpenAI 兌容SSE
端点 /api/chat /chat/completions
增量提取 message.content choices[0].delta.content
思考过皋 䞍支持 choices[0].delta.reasoning_content
结束信号 流关闭 + 最终事件 [DONE] 或流关闭
Token 限制 num_predict默讀 -1 䞍限制 max_tokens
讀证 无需 Authorization: Bearer {key}

4.6 思考暡匏

thinking_enabled = true 时DeepSeek R1 / 智谱掚理暡型

  • 解析 SSE 流䞭的 reasoning_content 字段䜜䞺思考过皋
  • 通过 phase: "thinking" 掚送前端枲染䞺可折叠区域
  • 正匏回答通过 phase: "answering" 掚送 delta.content
  • DeepSeek 额倖统计 KV Cache 呜䞭prompt_cache_hit_tokens

5. RAG 检玢䞎 Embedding commands/ai/embedding.rs

5.1 双暡匏检玢

              ┌──────────────────┐
              │    甚户查询        │
              └────────┬─────────┘
                       ↓
        ┌──────────────────────────┐
        │  embeddings 衚有数据?      │
        └──────┬────────────┬──────┘
            YES│            │NO
               ↓            ↓
    ┌──────────────────┐  ┌──────────────────┐
    │  向量语义搜玢      │  │ FTS5 / LIKE 降级  │
    │  sqlite-vec KNN   │  │  关键词匹配       │
    └────────┬─────────┘  └─────────┬────────┘
             └──────────┬───────────┘
                        ↓
              返回 Top N RagResult[]
  • 检玢范囎chapters 衚排陀蜯删陀+ world_cards 衚均按 book_id 隔犻
  • 向量搜玢查询向量经 /embeddings API 获取对 chunks_vec 虚拟衚执行 sqlite-vec KNN䜙匊距犻检玢升序取 Top Nv1.6.0 起䞍再党量内存䜙匊
  • 降级策略查询词前 20 字笊构造 LIKE '%keyword%'先搜章节、䞍足时补搜䞖界观卡片降级结果 distance 固定 0.5

v1.6.0 起语义检玢改䞺 sqlite-vec KNN玢匕向量写入 SQLite chunks_vecvec0 虚拟衚查询执行 SQL knn 距犻检玢䞍再党量加蜜 embeddings 到内存逐条䜙匊计算repository/embedding_repo.rs 绎技。

5.2 Embedding 生成流皋

1. 收集源数据
   ├── 章节SELECT id, content_html FROM chapters WHERE book_id=? AND deleted_at IS NULL
   └── 䞖界观卡片SELECT id, content_html FROM world_cards WHERE book_id=?
2. 文本预倄理
   ├── strip_html() → 去 HTML 标筟
   ├── truncate_for_embedding() → 截断到 1800 字笊
   └── 过滀空文本
3. 批量调甚 Embedding API每批 20 条
4. 写入数据库
   ├── INSERT OR REPLACE INTO embeddings (source_type, source_id, embedding, model)
   └── UPDATE world_cards SET vectorized = 1

关键参数

参数 倌 诎明
EMBEDDING_MAX_CHARS 1800 单条文本截断长床
BATCH_SIZE 20 每批 API 调甚条数
存傚栌匏 f32 → LE bytes BLOB 小端字节序

先收集党郚数据释攟 statement 锁再执行匂步 API 调甚。

5.3 Embeddings 衚

CREATE TABLE IF NOT EXISTS embeddings (
    source_type TEXT NOT NULL,   -- 'chapter' | 'world_card'
    source_id TEXT NOT NULL,
    embedding BLOB NOT NULL,     -- f32[] → LE bytes
    model TEXT NOT NULL,
    PRIMARY KEY (source_type, source_id)
);

6. 内容总结 commands/ai/summarize.rs

6.1 章节总结 summarize_chapter

  • 非流匏请求stream: false返回完敎总结
  • 默讀 System Prompt䞓䞚小诎助手300 字内总结䞻芁情节/事件/人物支持自定义
  • 支持 DeepSeek 思考暡匏
  • 返回 ChapterSummary { summary, originalChars, summaryChars, thinking }
  • 调甚场景AI 䟧面板对话原文 > 300 字自劚觊发、章节总结独立窗口
  • 章节过短< 50 字自劚跳过内容截取前 8000 字笊

6.2 对话压猩 summarize_conversation

滑劚窗口 + 摘芁压猩的双层 context 管理

┌────────────────────────────────────────┐
│              System Prompt             │
│  — 角色指什 + 卷/章节䞊䞋文 + RAG 背景    │
│  — [历史对话摘芁]压猩的旧对话         │
├─────────────────────────────────────────
│         滑劚窗口最近 N 蜮            │
│  [user] ... [assistant] ...            │
│  [user] (圓前提问)                      │
└────────────────────────────────────────┘
  • buildMessages() 仅取最近 windowSize * 2 条消息
  • 每次 done 事件后觊发 summarizeOverflowMessages()超出窗口时后台压猩䞍阻塞 UI
  • 摘芁结构 { summary, coveredUpToId, summaryChars, updatedAt }按 bookId 分组持久化coveredUpToId 保证幂等
  • contextWindowSize 配眮项默讀 10范囎 1-50旧配眮自劚迁移补䞺 10

7. 连接测试 commands/ai/test.rs

呜什 请求 成功返回 超时
test_ai_connection GET {endpoint}/models垊 Bearer Key 可甚暡型列衚最倚 10 䞪 15s
test_rag_connection POST {endpoint}/embeddings测试文本 向量绎床信息 15s

错误区分401 → "讀证倱莥"其他 → 原始错误诊情。


8. 前端组件

组件 路埄 职莣
AiSidePanel components/ai/AiSidePanel.tsx 对话面板Header连接状态指瀺噚+ MessageList + QuickHints + InputArea
useAiChat components/ai/useAiChat.ts425 行 栞心 hook发送经 Agent 匕擎 execute_agent_skill、流匏事件agent-stream-chunk、历史总结/压猩、错误恢倍
MessageBubble components/ai/MessageBubble.tsx 消息气泡Markdown 枲染 + 思考过皋折叠 + 操䜜按钮
RequestDetailModal components/ai/RequestDetailModal.tsx 请求诊情参数 / System Prompt / 章节总结 / RAG 䞊䞋文 / 消息列衚
AiToolboxPanel components/ai/AiToolboxPanel.tsx AI 工具箱䞉栏垃局独立窗口
ChapterSummaryHeader components/editor/ChapterSummaryHeader.tsx 猖蟑噚顶郚内联总结条

连接状态指瀺噚

const statusConfig = {
  idle:      { icon: CircleIcon,      color: 'text-muted-foreground/50' },
  testing:   { icon: Loader2Icon,     color: 'text-blue-500 animate-spin' },
  connected: { icon: CircleCheckIcon, color: 'text-green-500' },
  error:     { icon: CircleAlertIcon, color: 'text-red-500' },
}

消息持久化策略

操䜜 是吊写盘
addAiMessage ✅ 立即
updateAiMessage流匏高频 ❌ 仅内存
persistAiConversation流结束 ✅ 䞀次写入
删陀 / 枅空 ✅ 立即

9. 状态䞎类型

interface AiChatConfig {
  provider: 'bigmodel' | 'deepseek' | 'ollama' | 'custom'
  endpoint: string
  model: string
  temperature: number          // 0–1默讀 0.7
  maxTokens: number            // 默讀 131072
  bigmodelApiKey?: string
  deepseekApiKey?: string
  thinkingEnabled: boolean     // 默讀 true
  contextWindowSize: number    // 默讀 10范囎 1–50
}

interface RagConfig {
  // v1.2 起无 enabled 字段预留胜力䞍圱响圓前对话
  provider: 'bigmodel'         // 圓前仅智谱提䟛 Embeddings API
  endpoint: string
  embeddingModel: string       // 默讀 embedding-3
  bigmodelApiKey?: string
}

interface AiConfig { chat: AiChatConfig; rag: RagConfig }

interface AiMessage {
  id: string
  role: 'user' | 'assistant'
  content: string
  thinking: string
  phase: 'thinking' | 'answering' | 'done' | 'summarizing' | 'retrying'
  isSummarizing?: boolean
  loading?: boolean
  usage?: { inputTokens; outputTokens; inputChars; outputChars } | null
  requestPayload?: ChatRequestPayload
}

localStorage 键

键 内容
time-write-ai-config AiConfig 对象
time-write-ai-conversations Record<bookId, AiMessage[]>
time-write-ai-tool-categories AiToolCategory[]

兌容性迁移旧版扁平 AiConfig → chat/rag 分犻旧版 apiKey → 双服务商 Key旧版 aiToolPrompts → aiToolCategories。


10. AI 工具箱

䞉栏垃局巊䟧工具列衚192px→ 䞭闎蟓入区288px→ 右䟧蟓出面板匹性。

分类 工具数 包含工具
垞甚工具 7 章节总结、小诎倧纲生成、章节深床涊色、小诎扩写、续写、涊色、改写
剧情讟计 6 䞻线剧情讟定、支线分解、剧情反蜬、栞心冲突生成噚、章节细纲、系统讟定生成噚
描写蟅助 6 打斗描写、细节描写、感官描写、倖貌描写、情感描写、环境/场景描写
䞖界讟定 5 䞖界架构讟定、人物讟定、势力组织架构、境界/功法等级、物品讟定
取名神噚 5 人物名字定制、小诎乊名、叀风姓名、闚掟势力名称、地点场景取名
  • 每䞪工具的 System Prompt 可独立猖蟑留空䜿甚默讀提瀺词
  • 章节总结工具圚工具箱䞭自劚过滀有独立窗口
  • 支持 initialToolId 参数从倖郚指定默讀选䞭工具
  • 所有工具䞎分类持久化到 localStorage

11. 关键垞量

垞量 倌 诎明
EMBEDDING_MAX_CHARS 1800 单条文本截断长床
BATCH_SIZE 20 Embedding 批量生成批倧小
MAX_RETRIES 2 流匏对话最倧重试次数
SSE_READ_TIMEOUT_SECS 60 SSE 读取超时秒
GLOBAL_TIMEOUT 600 党局超时秒
CHAPTER_SUMMARY_THRESHOLD 300 章节自劚总结字数阈倌
RAG_TOP_N 3 RAG 检玢返回片段数
DEFAULT_CONTEXT_WINDOW_SIZE 10 默讀滑劚窗口蜮数
DEFAULT_MAX_TOKENS 131072 默讀最倧蟓出 Token

12. 讟计评价䞎䌘化方向

12.1 䌘点

方面 评价
架构分犻 Rust 倄理 HTTP/SSE前端仅倄理 UI规避 CORS 䞎流匏解析问题
流䞭断保技 60s 超时 + buffer 刷新 + 保留郚分内容甚户䜓验友奜
自劚重试 区分可重试/䞍可重试错误指数退避减少甚户干预
双检玢暡匏v1.6.0 后端 sqlite-vec KNN 语义 → FTS5/LIKE 降级对话䞊䞋文由 Agent 匕擎工具检玢提䟛
章节智胜总结 原文 > 300 字自劚总结节省 context token
倚绎床配眮 对话/RAG 解耊服务商独立 API Key工具箱可扩展
持久化可靠 AI 对话 800ms 防抖合并写盘 + 窗口卞蜜 / 页面隐藏 flush 兜底v1.6.0
迁移兌容 自劚检测旧版配眮栌匏并迁移甚户无感知升级
请求透明 RequestDetailModal 展瀺完敎请求蜜荷䟿于调试

12.2 䌘化方向

方向 现状 建议
Provider 扩展性 服务商硬猖码圚配眮垞量䞭 插件化或配眮驱劚的 Provider 泚册机制
Embedding 服务商 仅智谱写死 bigmodel 支持 OpenAI embeddings、本地暡型
RAG 检玢效率 ✅ 已萜地 sqlite-vec KNNv1.6.0 可继续评䌰分片 / 量化压猩等进阶䌘化
流匏断点续䌠 断连后仅保留已生成内容 长思考场景可考虑真正的断点续䌠
API Key 蜮换 每䞪服务商单 Key 支持倚 Key 莟蜜均衡 / 故障蜬移
对话富出 ✅ 已支持 Markdown / JSONv1.6.0AI 䟧蟹栏「富出对话」 可增加富出栌匏TXT / HTML䞎批量富出
章节总结猓存 每次对话郜重新总结 summary 有效期内倍甚猓存
系统默讀工具 预讟 29 䞪工具䞍可删陀/重眮 增加「恢倍默讀」功胜
请求参数可配眮性 Temperature 等䞺党局讟眮 每䞪工具可独立芆盖参数
useAiChat 䜓积 425 行v1.2 移陀 Embedding 逻蟑仍职莣蟃倚 拆分䞺 useChapterValidation / useChapterSummary / useStreamChat / useConversationCompression
RAG 接线 后端呜什已实现、前端标记预留 明确 RAG 定䜍接入讟眮页或并入 Agent 工具或移陀冗䜙呜什

12.3 安党泚意

  • API Key 存傚于 localStorage 明文未加密
  • 所有 API 通信圚 Rust 䟧进行前端无法截获
  • 连接测试䞍泄露 API Key仅验证讀证状态
  • capabilities/default.json äž­ http:allow-fetch 攟匀任意 HTTP/HTTPS 端点AI 请求必需䜆也是 CSP 收玧的权衡点见 䌘化报告 问题 8
⚠ **GitHub.com Fallback** ⚠