Aventuras 静态分析:模块设计与工作原理

对象:AventurasTeam/Aventuras · 方法:纯静态分析

一、项目概览与技术栈

Aventuras 是一个「Interactive fiction with an AI that remembers」——AI 互动小说引擎, 支持冒险(多选动作 + 世界追踪)与协作写作(自由文本 + AI 建议)两种模式,桌面 + Android 双端。 技术栈(README.md:75-77):TypeScript(strict) · SvelteKit 2 · Svelte 5 runes · Tauri 2(Rust) · Tailwind + shadcn-svelte · SQLite(tauri-plugin-sql / sqlx) · Vercel AI SDK · LiquidJS · Zod · Vitest。

TypeScript 承载全部业务逻辑,Rust 只负责会撑爆 WebView 堆的字节搬运(备份/导入/同步),SQLite 落盘。 仓库结构见 docs/architecture/overview.md:7-34。

二、总体架构(ASCII)

┌────────────────────── src/ (SvelteKit 前端, TS strict, Svelte 5 runes) ─────────────────────┐
│  routes/           页面 (+page.svelte / +layout.svelte)                                    │
│  lib/components/   UI 组件;lib/stores/ 状态 (story/ui/settings 等 *.svelte.ts)             │
│  lib/services/     业务逻辑:ai/ (生成·检索·记忆·图像) · generation/ (流水线 phases) · ...   │
│  lib/types/        数据模型 (index.ts);lib/utils/ 工具                                     │
└──────────────┬──────────────────────────────────────────────────────────────────────────────┘
               │ IPC (仅传 path/id,大 payload 由 Rust 流式搬运,persistence.md:19-24)
┌──────────────▼────────── src-tauri/ (Rust, Tauri 2) ─────────────────────────────────────────┐
│  src/backup.rs 备份/恢复 · src/avt_import.rs .avt 导入 · src/sync/ LAN 同步(QR 配对)        │
│  migrations/ 001_initial.sql … 037_kept_separate.sql(sqlx 顺序迁移,LF 行尾)              │
│  gen/android/ 跟踪在库内的 Android 脚手架(勿 tauri android init)                           │
└──────────────┬──────────────────────────────────────────────────────────────────────────────┘
               │ tauri-plugin-sql / sqlx
        ┌──────▼──────┐   ┌──────────────────────────────────────┐
        │  SQLite     │   │  LLM 云端/本地 (Vercel AI SDK)        │
        │ aventura.db │   │  OpenRouter/OpenAI/Anthropic/Google/  │
        └─────────────┘   │  xAI/Groq/DeepSeek/Mistral/Z.AI/      │
                          │  NanoGPT/Chutes/Pollinations/NIM      │
                          │  + 本地 Ollama/LM Studio/llama.cpp    │
                          └──────────────────────────────────────┘

多平台组织:同一前端 + Tauri 壳,产出 Windows/macOS/Linux 桌面安装包与 Android APK(README.md:38-43)。 compileApk.sh 与 Android NDK/JDK 文档见 docs/development/release.md。 桌面与移动共享全部 AI/存储逻辑,差异仅在 Rust 能力(Android 有 WebView 堆硬上限,图片 base64 由 Rust 直通 SQLite,persistence.md:21-24)。

三、核心工作流(玩家输入 → 生成 → 记忆更新)

一条回合的编排是 GenerationPipeline.execute()(src/lib/services/generation/GenerationPipeline.ts:105)。 各阶段是注入依赖的 async 生成器(phases/ 目录),顺序为:

PreGeneration(存 retry 备份) → Retrieval(检索/记忆) → Narrative(流式叙述, 唯一致命)
   → [ Classification ∥ Translation → Image ] ∥ BackgroundImage ∥ PostGeneration(建议/风格)

阶段 1:上下文装配(phases/RetrievalPhase.ts:78),分两阶段:

阶段 2:叙述生成(phases/NarrativePhase.ts:67)

阶段 3:记忆/世界状态更新

四、模块逐一分析

4.1 AI 记忆实现(重点)

4.2 LLM Provider 抽象(重点)

4.3 故事状态模型(重点)

4.4 协作写作模式(重点)

4.5 其余关键模块

五、数据模型与持久化

六、与 Z.R.I.C 功能对照表

Z.R.I.C 功能 Aventuras 对应实现 代码位置 结论
剧本解析 无固定剧本;靠 Wizard 生成初始设定 + SillyTavern/Character Card/.avt 导入 stChatImporter、avt_import.rs、story.svelte.ts:697 部分(导入 ≠ 剧本解析)
推演分支 Branch + forkEntryId + COW 轻量分支 types/index.ts:452、migrations 013/026、story.svelte.ts:124 ✅ 有
自动判定 ClassifierService 抽取世界状态变更/在场/时间推进 generation/ClassifierService.ts:74 ✅ 有
世界状态 Character/Location/Item/StoryBeat + 三段注入 generation/WorldStateInjector.ts:195 ✅ 有(较强)
NPC 情绪记忆 章节级 emotionalTone + 角色 relationship/traits/status;无逐 NPC 情绪史(Entry.state 字段存在但从未被写,overview.md:50-53) Chapter.emotionalTone、ClassifierService.ts:411 ⚠️ 部分/间接
地图 Location.connections: string[] 字段存在,未见拓扑/地图 UI types/index.ts:341 ⚠️ 弱
触发器 StoryBeat 状态机(quest/milestone/event…)+ 关键词注入,无脚本式事件触发器 types/index.ts:370、classifier.ts:129-151 部分
时间线 TimeTracker(years/days/hours/minutes) + timeProgression + 章节 start/endTime types/index.ts:19、classifier.ts:182-186、ChapterService.ts:176-177 ✅ 有
记忆系统 章节自动摘要 + Agentic/Static 检索 + 粘性/stickiness generation/MemoryService.ts:67、AgenticRetrievalService.ts:155 ✅ 有(最强项)
本地模型 Ollama / LM Studio / llama.cpp + 本地 ComfyUI/A1111 图像 sdk/providers/registry.ts:105-130、ai/image/providers/ ✅ 有
许可 AGPL-3.0 LICENSE.md、README.md:93 ✅ AGPL-3.0

七、设计评价

优点(附代码依据)

  1. 分层清晰、依赖注入、可测试:生成阶段是注入依赖的纯 async 生成器,阶段本身不 import store/provider, 依赖在 ActionInput.svelte 组装(overview.md:91-94);phase 均可独立单测(WorldStateInjector.test.ts 等)。
  2. 记忆/上下文工程极其扎实:三段式注入 + 「量先于相关度」的 Tier3 预算 + 粘性 + 前缀缓存排序(prompts.md:67-88)
    • 章节读预算,均有实测数据支撑且写进 docs/。
  3. Provider 抽象统一且可扩展PROVIDERS 单一元数据源 + createProviderFromProfile 单一 switch
    • 每子系统一个 ServiceId/Agent Profile,检索/分类/叙述可各用不同模型(ai-services.md:5-12)。
  4. 健壮的降级与抢救:叙述外所有阶段失败不致命(overview.md:82-84);分类器失败用 jsonrepair 抢救(ClassifierService.ts:201); agentic 检索死亡仍 salvage 已付费答案(AgenticRetrievalService.ts:370)。

缺陷(附代码依据)

  1. 单一巨型门面与巨型文件ai/index.ts 达 1348 行、story.svelte.ts 超 1390 行、 WorldStateInjector.ts 944 行,职责边界靠注释维持,阅读与重构成本高。
  2. 数据模型存在死代码/两套体系Entry.state(角色情绪/关系史/阵营声望等)设计完整但从未被写入(overview.md:50-53); Lorebook 与 WorldState 两套并行实体易混淆,注释反复强调「不要搞混」(WorldStateInjector.ts:14-33)。
  3. 地图/情绪/触发器等「游戏系统」偏薄:Location 只有 connections 数组无拓扑;NPC 无情绪记忆史; StoryBeat 靠 LLM 抽状态而非确定性判定,复杂机制(如触发器)缺位——较 Z.R.I.C 的规则化剧本引擎,偏「纯 LLM 驱动」。
  4. 复杂度与认知负担高:大量「曾踩过的坑」以长注释固化在代码里(如 tier 顺序、索引稳定性、粘性不刷新), 说明隐蔽不变量多、易回归,新贡献者门槛高(CLAUDE.md 明确要求先读对应 docs/)。

八、结论

Aventuras 是一个工程化程度很高的纯 LLM 互动小说引擎: 以「追加式 StoryEntry + 章节摘要记忆 + 双池三段上下文注入 + 可替换 Provider + Tauri 跨桌面/移动」为核心, 记忆与上下文管理是其压倒性强项(自动摘要、Agentic/Static 检索、粘性、前缀缓存均有量化依据)。 相比之下,世界状态、分支、时间线具备,但地图、NPC 情绪史、确定性触发器/判定等「规则游戏系统」较弱, 更接近「会记事的 AI 讲故事机」而非规则化 TRPG 引擎。 整体适合作为记忆型 AI 叙事前端的参考实现,AGPL-3.0 许可。