CodeBot Wiki 是一款基于大语言模型的智能文档生成工具,能够自动解析项目代码,生成结构清晰、内容专业的项目 Wiki。它不仅覆盖项目概览、核心模块、关键逻辑等信息,还支持交互式理解,更适合团队协作与持续迭代,是理解开源项目或内部系统的理想助手!

本期项目地址:https://github.com/moeru-ai/airi

项目概览

简介

@proj-airi/memory-pgvector 是一个专为 PostgreSQL 向量数据库设计的记忆存储模块,旨在提供高效、稳定的向量数据存取能力。该模块通过集成 drizzle-ormpostgres 实现与数据库的交互,并依赖本地工作区 @proj-airi/server-sdk 提供核心服务支持。模块使用 tsx 作为开发脚本的运行时,确保开发环境的灵活性和一致性。

详细章节

模块配置

package.json 文件定义了模块的基本信息、依赖项和开发脚本。该文件是模块构建和运行的基础,确保所有依赖项正确安装并配置。

主要配置项

配置项描述
name模块名称 @proj-airi/memory-pgvector
dependencies依赖项包括 drizzle-ormpostgres@proj-airi/server-sdk
devDependencies开发依赖项,如 tsx
scripts定义了开发脚本,如启动命令

依赖关系图

模块入口

src/index.ts 是模块的入口文件,负责初始化服务并创建 Client 实例。该文件通过 main 函数启动服务,并设置日志格式与级别,确保模块运行时的可观察性和可控性。

初始化流程

核心功能

  1. 服务初始化:创建 Client 实例并设置日志格式与级别。
  2. 客户端注册:在 main 函数中注册客户端名称 'memory-pgvector'
  3. 配置监听:监听配置事件以响应配置变化。
  4. 优雅关闭:通过 runUntilSignal() 保持运行,支持 SIGINTSIGTERM 信号实现优雅关闭。

Client 类实现

Client 类是模块的核心组件,负责与 PostgreSQL 向量数据库进行交互。该类通过封装数据库连接和操作逻辑,提供了一套简洁的 API 用于向量数据的存储和检索。

主要功能

功能描述
数据库连接通过 postgresdrizzle-orm 实现与 PostgreSQL 的连接
数据操作提供向量数据的增删改查操作
配置管理支持配置变更监听和动态调整
信号处理支持 SIGINTSIGTERM 信号实现优雅关闭

日志系统

模块通过设置日志格式与级别,确保运行时的可观察性。日志系统在 Client 实例初始化时进行配置,支持多种日志级别以满足不同场景的需求。

配置监听机制

模块通过监听配置事件,实现对配置变化的动态响应。该机制确保模块在运行时能够根据配置调整行为,提高系统的灵活性和可维护性。

表格

主要功能或组件

功能/组件描述
Client 实例用于与 PostgreSQL 向量数据库交互的客户端实例
日志设置设置日志格式与级别以方便调试和监控
配置监听监听配置事件以响应配置变化
优雅关闭支持 SIGINTSIGTERM 信号实现优雅关闭

配置选项

配置项类型默认值描述
namestring@proj-airi/memory-pgvector模块名称
dependenciesobject依赖项包括 drizzle-ormpostgres@proj-airi/server-sdk
devDependenciesobject开发依赖项,如 tsx
scriptsobject定义了开发脚本,如启动命令

代码片段

初始化服务

// packages/memory-pgvector/src/index.ts
async function main() {
    const client = new Client();
    client.setName('memory-pgvector');
    client.onConfigChange(() => {
        // 处理配置变化
    });
    await client.runUntilSignal();
}

依赖项

// packages/memory-pgvector/package.json
{
  "name": "@proj-airi/memory-pgvector",
  "dependencies": {
    "drizzle-orm": "^0.0.1",
    "postgres": "^0.0.1",
    "@proj-airi/server-sdk": "^0.0.1"
  },
  "devDependencies": {
    "tsx": "^0.0.1"
  },
  "scripts": {
    "start": "tsx src/index.ts"
  }
}

结论

@proj-airi/memory-pgvector 模块通过与 PostgreSQL 向量数据库集成,提供了一种高效的方式来存储和检索向量数据。其配置和初始化流程清晰,依赖关系明确,支持优雅关闭,确保了模块的稳定性和可维护性。模块的核心组件 Client 类封装了数据库交互逻辑,提供了简洁的 API 用于向量数据操作。通过配置监听机制和日志系统,模块在运行时能够动态响应配置变化并提供良好的可观察性。

Telegram 机器人模块

Telegram 机器人模块是整个项目的核心交互组件,负责处理来自 Telegram 平台的消息、图像、贴纸等多媒体内容,并通过 LLM(大语言模型)生成智能响应。该模块集成了数据库操作、消息处理、注意力机制、多媒体解析和提示模板系统,旨在为用户提供自然、智能的对话体验。

模块架构与核心组件

入口点与初始化

Telegram 机器人服务的入口点位于 services/telegram-bot/src/index.ts。该文件负责初始化日志系统、OpenTelemetry 监控、数据库连接,并启动机器人。它调用 initDb() 初始化数据库连接,调用 startTelegramBot() 启动机器人主逻辑。

// services/telegram-bot/src/index.ts
async function main() {
  // 初始化日志、监控、数据库
  await initDb();
  await startTelegramBot();
}

数据库模块

数据库模块位于 services/telegram-bot/src/db/ 目录下,使用 Drizzle ORM 连接 PostgreSQL 数据库。db/index.ts 文件负责初始化数据库连接,db/schema.ts 定义了多个表结构,包括聊天消息、贴纸、图片、记忆和目标等模型。

数据库表结构

表名描述
chatMessagesTable存储聊天消息
stickersTable存储贴纸信息
photosTable存储图片信息
joinedChatsTable存储已加入的聊天信息
stickerPacksTable存储贴纸包信息

消息处理与循环逻辑

Telegram 机器人通过 bots/telegram/index.ts 中的 handleLoopStep 函数处理消息循环。该函数调用 readMessage 获取未读消息,并根据上下文生成响应。

// services/telegram-bot/src/bots/telegram/index.ts
async function handleLoopStep(chatId: string) {
  const message = await readMessage(chatId);
  // 处理消息并生成响应
}

readMessage 函数位于 bots/telegram/loop/read-message.ts,负责获取并整合指定聊天的未读消息及历史记录,为对话判断提供摘要。

注意力机制与中断处理

注意力机制通过 bots/telegram/attention-handler.ts 中的 createAttentionHandler 实现,控制机器人的响应频率与衰减机制。bots/telegram/utils/interruption.ts 中的 shouldInterruptProcessing 函数根据时间与消息量动态判断是否中断流程。

// services/telegram-bot/src/bots/telegram/attention-handler.ts
function createAttentionHandler() {
  // 控制响应频率与衰减机制
}

LLM 动作生成与多媒体解析

LLM 模块位于 services/telegram-bot/src/llm/ 目录下,负责生成智能响应。llm/actions.ts 中的 imagineAnAction 函数根据上下文和未读消息生成动作。llm/photo.tsllm/sticker.ts 分别处理图片和贴纸的解析与描述生成。

// services/telegram-bot/src/llm/actions.ts
async function imagineAnAction(context: string, message: string) {
  // 生成动作
}

提示模板系统

提示模板系统位于 services/telegram-bot/src/prompts/ 目录下,定义了多个 .velin.md 文件,用于指导 LLM 生成响应。prompts/prompts.ts 中的异步函数加载这些模板。

// services/telegram-bot/src/prompts/prompts.ts
async function loadPromptTemplate(templateName: string) {
  // 加载并返回模板内容
}

数据流与交互流程

主要功能与组件

功能/组件描述
startTelegramBot启动 Telegram 机器人主逻辑
handleLoopStep处理消息循环
readMessage获取并整合未读消息
createAttentionHandler控制响应频率与衰减机制
shouldInterruptProcessing动态判断是否中断流程
imagineAnAction生成动作
interpretPhotos处理图片并生成描述
interpretSticker处理贴纸并生成描述
loadPromptTemplate加载提示模板

消息处理循环详解

消息处理循环是 Telegram 机器人模块的核心逻辑,由 handleLoopStep 函数驱动。该函数负责从指定聊天中读取消息、生成动作、处理多媒体内容,并最终生成和发送响应。

handleLoopStep 函数

handleLoopStep 函数位于 services/telegram-bot/src/bots/telegram/index.ts,是消息处理循环的核心。它接收一个聊天 ID 作为参数,并执行以下步骤:

  1. 调用 readMessage 函数获取聊天中的未读消息和历史记录。
  2. 根据获取到的消息和上下文,调用 imagineAnAction 函数生成动作。
  3. 处理生成的动作,可能包括发送文本、图片或贴纸等。
  4. 更新聊天状态和注意力机制。
// services/telegram-bot/src/bots/telegram/index.ts
async function handleLoopStep(chatId: string) {
  const message = await readMessage(chatId);
  const action = await imagineAnAction(message.context, message.text);
  // 处理动作并发送响应
}

readMessage 函数

readMessage 函数位于 services/telegram-bot/src/bots/telegram/loop/read-message.ts,负责从指定聊天中读取未读消息和历史记录。它整合这些信息,为后续的动作生成提供上下文。

// services/telegram-bot/src/bots/telegram/loop/read-message.ts
async function readMessage(chatId: string) {
  // 获取并整合未读消息和历史记录
  return {
    context: '...',
    text: '...'
  };
}

注意力机制详解

注意力机制是 Telegram 机器人模块中用于控制响应频率和衰减的核心组件。它通过 createAttentionHandler 函数实现,并与中断处理逻辑紧密配合。

createAttentionHandler 函数

createAttentionHandler 函数位于 services/telegram-bot/src/bots/telegram/attention-handler.ts,用于创建一个注意力处理器。该处理器根据聊天的历史交互记录,动态调整机器人的响应频率。

// services/telegram-bot/src/bots/telegram/attention-handler.ts
function createAttentionHandler() {
  // 创建并返回注意力处理器
  return {
    shouldRespond: (chatId: string) => boolean,
    updateAttention: (chatId: string, response: string) => void
  };
}

shouldInterruptProcessing 函数

shouldInterruptProcessing 函数位于 services/telegram-bot/src/bots/telegram/utils/interruption.ts,用于根据时间与消息量动态判断是否中断流程。这有助于避免在高负载情况下过度处理消息。

// services/telegram-bot/src/bots/telegram/utils/interruption.ts
function shouldInterruptProcessing(chatId: string, messageCount: number) {
  // 根据条件判断是否中断处理
  return false;
}

总结

Telegram 机器人模块通过集成消息处理、注意力机制、LLM 动作生成和多媒体解析,实现了智能对话功能。其模块化设计和清晰的数据流使得系统易于维护和扩展。数据库模块提供了持久化支持,提示模板系统则确保了响应的多样性和智能性。消息处理循环和注意力机制是该模块的核心,它们共同确保了机器人能够高效、智能地响应用户消息。

国际化与本地化模块

简介

国际化与本地化模块旨在为项目提供多语言支持,使用户能够根据其语言偏好使用不同的界面语言。该模块通过 YAML 文件定义不同语言的文本资源,并通过 TypeScript 入口文件集中管理和导出这些资源。项目当前支持英语(en)、西班牙语(es)和简体中文(zh-Hans)三种语言。

模块的核心功能包括语言资源的组织、加载和切换。资源按功能模块划分,例如基础文本、设置界面和阶段相关文本等,确保了良好的可维护性和扩展性。

语言资源结构

语言包组织

项目中的语言资源按照语言代码(如 eneszh-Hans)进行分组,每个语言包包含多个 YAML 文件和一个入口 TypeScript 文件。YAML 文件按功能模块划分,如 base.yamlsettings.yamlstage.yaml,分别存储基础文本、设置界面文本和阶段相关文本。

入口文件(如 index.ts)负责导入并导出该语言包下的所有资源,便于统一管理和使用。

Tamagotchi 模块本地化

Tamagotchi 应用作为一个独立模块,也拥有自己的本地化资源。其资源结构与主应用类似,但位于 tamagotchi 子目录下,包括 settings.yamlstage.yaml 文件,以及相应的入口文件。

Mermaid 图:语言资源结构

国际化配置

Vue 项目国际化配置

在 Vue 项目中,国际化配置由 apps/stage-tamagotchi/src/modules/i18n.ts 文件负责。该文件初始化了多语言支持,包括语言标签映射、用户语言偏好获取和 i18n 实例创建。

  • languageRemap:映射浏览器语言标签到项目支持的语言版本。
  • getLocale():获取用户语言偏好,优先从 localStorage 读取。
  • createI18n:创建并导出 i18n 实例,配置默认语言、回退语言及加载所有语言资源。

语言资源加载

所有语言资源通过 packages/i18n/src/locales/index.ts 文件统一导出,该文件导入并导出了 eneszh-Hans 语言包,使得项目能够访问所有支持的语言资源。

Mermaid 图:国际化配置流程

主要功能与组件

语言资源文件

文件路径描述
packages/i18n/src/locales/en/base.yaml定义英文语言包基础文本
packages/i18n/src/locales/en/settings.yaml定义“设置”模块的英文界面文案
packages/i18n/src/locales/en/stage.yaml定义“阶段”相关英文 UI 文本
packages/i18n/src/locales/en/tamagotchi/settings.yaml定义 Tamagotchi 设置模块的英文配置
packages/i18n/src/locales/en/tamagotchi/stage.yaml定义英文环境下 Tamagotchi 阶段的界面文本
packages/i18n/src/locales/es/base.yaml定义西班牙语本地化资源中的文本内容
packages/i18n/src/locales/es/settings.yaml定义用户设置界面的多语言文本
packages/i18n/src/locales/es/stage.yaml提供西班牙语界面文本
packages/i18n/src/locales/es/tamagotchi/settings.yaml定义 Tamagotchi 应用中“设置”相关的西班牙语界面文本
packages/i18n/src/locales/es/tamagotchi/stage.yaml包含 Tamagotchi 阶段相关的西班牙语界面文本
packages/i18n/src/locales/zh-Hans/base.yaml定义中文语言包中与虚拟角色 AIRI 相关的提示文本
packages/i18n/src/locales/zh-Hans/settings.yaml提供“设置”模块的中文翻译内容
packages/i18n/src/locales/zh-Hans/stage.yaml定义用户界面交互相关的中文文本资源
packages/i18n/src/locales/zh-Hans/tamagotchi/settings.yamlTamagotchi 设置界面中文翻译
packages/i18n/src/locales/zh-Hans/tamagotchi/stage.yaml模型加载过程的中文状态信息

国际化配置函数

函数名描述参数
getLocale()获取用户语言偏好

语言资源统一导出机制

为了理解项目如何统一管理所有语言包,查看 packages/i18n/src/locales/index.ts 文件的内容。

// packages/i18n/src/locales/index.ts
import en from './en'
import es from './es'
import zhHans from './zh-Hans'

export default {
  en,
  es,
  'zh-Hans': zhHans
}

该文件导入并导出了 eneszh-Hans 语言包,使得项目能够访问所有支持的语言资源。

Vue 项目国际化配置

接下来,查看 apps/stage-tamagotchi/src/modules/i18n.ts 文件,以了解 Vue 项目中的国际化配置细节。

// apps/stage-tamagotchi/src/modules/i18n.ts
import { createI18n } from 'vue-i18n'
import locales from '@i18n/locales'

const languageRemap: Record<string, string> = {
  'en-US': 'en',
  'en-GB': 'en',
  'zh-CN': 'zh-Hans',
  'zh-SG': 'zh-Hans'
  // TODO: add more language remap
}

export function getLocale(): string {
  const storedLocale = localStorage.getItem('locale')
  if (storedLocale && locales[storedLocale]) {
    return storedLocale
  }

  const browserLocale = navigator.language
  const remappedLocale = languageRemap[browserLocale]
  if (remappedLocale && locales[remappedLocale]) {
    return remappedLocale
  }

  const primaryLanguage = browserLocale.split('-')[0]
  if (locales[primaryLanguage]) {
    return primaryLanguage
  }

  return 'en'
}

const i18n = createI18n({
  legacy: false,
  locale: getLocale(),
  fallbackLocale: 'en',
  messages: locales
})

export default i18n

该文件初始化了多语言支持,包括语言标签映射、用户语言偏好获取和 i18n 实例创建。

语言包入口文件分析

为了进一步理解语言资源的组织方式,查看 packages/i18n/src/locales/en/index.ts 文件的内容。

// packages/i18n/src/locales/en/index.ts
import base from './base.yaml'
import settings from './settings.yaml'
import stage from './stage.yaml'
import tamagotchi from './tamagotchi'

export default {
  base,
  settings,
  stage,
  tamagotchi
}

该文件导入并导出了 en 语言包下的所有资源,包括基础文本、设置界面文本、阶段相关文本以及 Tamagotchi 模块的本地化资源。

YAML 语言资源文件分析

为了理解 YAML 文件如何定义文本资源,查看 packages/i18n/src/locales/en/base.yaml 文件的内容。

# packages/i18n/src/locales/en/base.yaml
airi:
  name: AIRI
  description: AI VTuber
  prompt: You are AIRI, an AI VTuber.

该文件定义了英文语言包的基础文本,用于 AI VTuber 角色 AIRI 的行为和交互逻辑。

结论

国际化与本地化模块通过结构化的语言资源管理和灵活的配置机制,为项目提供了强大的多语言支持能力。该模块不仅支持多种语言,还通过模块化的设计确保了良好的可维护性和扩展性,是项目用户体验的重要组成部分。

用户界面模块

简介

用户界面模块是项目中负责构建和管理用户交互体验的核心部分。它通过一系列可复用的组件、动画、布局和交互逻辑,为用户提供直观、美观且功能丰富的界面。该模块涵盖了从基础 UI 元素(如按钮、输入框)到高级交互组件(如动画、3D 场景)的完整体系,支持多种场景下的 UI 需求,包括设置页面、模型管理、语音合成与转录等。

详细章节

1. 基础 UI 组件

基础 UI 组件构成了用户界面的基石,包括按钮、输入框、复选框、滑块、选择器等。这些组件通过 Vue 3 和 TypeScript 实现,具备良好的类型安全性和响应式特性。

关键组件

  • Button.vue:支持多种变体、尺寸和图标配置的按钮组件。
  • Input.vue:支持文本、密码、邮箱等多种输入类型的输入框组件。
  • Checkbox.vue:支持选中、未选中和交互状态的复选框组件。
  • Select.vue:支持基础选择器、禁用状态和自定义宽度的选择器组件。
  • Textarea.vue:支持多行文本输入的文本域组件。

Mermaid 图

表格

组件名称描述
Button支持多种变体、尺寸和图标配置的按钮组件
Input支持文本、密码、邮箱等多种输入类型的输入框组件
Checkbox支持选中、未选中和交互状态的复选框组件
Select支持基础选择器、禁用状态和自定义宽度的选择器组件
Textarea支持多行文本输入的文本域组件

2. 动画与交互

动画与交互组件为用户界面提供了丰富的动态效果和交互体验。这些组件通过 Vue 3 的响应式系统和动画库(如 animejs)实现,支持手动触发、自动循环和热键控制等多种交互方式。

关键组件

  • Replayable.vue:支持手动触发、自动循环和热键控制的动画回放组件。
  • use-replayable.ts:用于注册“重播”逻辑的自定义 Hook。
  • CursorFloating.vue:实现鼠标驱动的 3D 悬浮效果。
  • CursorMomentum.vue:计算鼠标移动的动量值,模拟速度衰减与累积效果。

Mermaid 图

表格

组件名称描述
Replayable支持手动触发、自动循环和热键控制的动画回放组件
use-replayable用于注册“重播”逻辑的自定义 Hook
CursorFloating实现鼠标驱动的 3D 悬浮效果
CursorMomentum计算鼠标移动的动量值,模拟速度衰减与累积效果

3. 数据展示与编辑

数据展示与编辑组件用于展示和编辑复杂的数据结构,包括颜色选择器、数字输入框、坐标点编辑器等。这些组件通过 Vue 3 和 TypeScript 实现,支持双向绑定和响应式更新。

关键组件

  • ColorPicker.vue:支持 HSV 管理颜色状态的颜色选择器组件。
  • PropertyNumber.vue:支持滑块与输入框联动的数字属性编辑控件。
  • PropertyPoint.vue:支持 x/y/z 数值输入、拖拽调整及格式化显示的三维坐标点编辑控件。

Mermaid 图

表格

组件名称描述
ColorPicker支持 HSV 管理颜色状态的颜色选择器组件
PropertyNumber支持滑块与输入框联动的数字属性编辑控件
PropertyPoint支持 x/y/z 数值输入、拖拽调整及格式化显示的三维坐标点编辑控件

4. 场景与模型管理

场景与模型管理组件用于展示和管理 3D 模型和场景,包括 Live2D 和 VRM 模型的加载、控制和交互。这些组件通过 Vue 3 和 TresJS 实现,支持动画播放、表情控制和资源清理。

关键组件

  • Live2D.vue:展示 Live2D 模型的组件。
  • VRM.vue:展示 VRM 模型的组件。
  • Model.vue:加载并控制 Live2D 模型的组件。
  • VRMModel.vue:加载并控制 VRM 模型的组件。

Mermaid 图

表格

组件名称描述
Live2D展示 Live2D 模型的组件
VRM展示 VRM 模型的组件
Model加载并控制 Live2D 模型的组件
VRMModel加载并控制 VRM 模型的组件

5. 设置与配置

设置与配置组件用于管理应用的设置和配置,包括外观设置、模型设置、语音设置等。这些组件通过 Vue 3 和 Pinia 实现,支持响应式绑定和状态管理。

关键组件

  • CheckBar.vue:布尔型设置项控件。
  • ModelSettings.vue:支持 2D (Live2D) 和 3D (VRM) 模型切换的模型配置界面组件。
  • SpeechProviderSettings.vue:配置语音服务提供商的组件。

Mermaid 图

表格

组件名称描述
CheckBar布尔型设置项控件
ModelSettings支持 2D (Live2D) 和 3D (VRM) 模型切换的模型配置界面组件
SpeechProviderSettings配置语音服务提供商的组件

6. 动画回放机制

Replayable.vue 是一个支持手动触发、自动循环和热键控制的动画回放组件。它通过管理回放状态与次数,提供按钮控件显示状态,并支持定时播放。

关键函数

  • registerReplayCallback:注册回放回调函数。
  • isReplaying:判断是否正在回放。

代码片段

// use-replayable.ts
export function useReplayable() {
  const context = inject(ReplayableContextKey);
  if (!context) {
    throw new Error('useReplayable must be used within a Replayable component');
  }
  return context;
}

7. 鼠标交互效果

CursorFloating.vueCursorMomentum.vue 组件实现了鼠标驱动的 3D 悬浮效果和动量计算。通过监听 mousemovemouseleave 事件,计算旋转、缩放参数,并使用 Vue 响应式系统与 CSS 变量控制动态样式。

关键函数

  • handleMouseMove:处理鼠标移动事件。
  • updateMomentum:更新动量值。

代码片段

// CursorMomentum.vue
function handleMouseMove(event: MouseEvent) {
  const deltaX = event.movementX;
  const deltaY = event.movementY;
  momentumX.value += deltaX;
  momentumY.value += deltaY;
}

function updateMomentum() {
  momentumX.value *= friction;
  momentumY.value *= friction;
  if (Math.abs(momentumX.value) < 0.1 && Math.abs(momentumY.value) < 0.1) {
    momentumX.value = 0;
    momentumY.value = 0;
  }
}

结论

用户界面模块通过一系列可复用的组件、动画、布局和交互逻辑,为用户提供直观、美观且功能丰富的界面。该模块涵盖了从基础 UI 元素到高级交互组件的完整体系,支持多种场景下的 UI 需求,是项目中不可或缺的重要组成部分。动画与交互组件通过 Vue 3 的响应式系统和动画库实现,提供了丰富的动态效果和交互体验,增强了用户界面的吸引力和可用性。

设置与配置模块

简介

设置与配置模块是整个项目中用于管理用户界面、AI 模型、提供商、模块功能及外观的核心部分。它通过多个子模块和组件,为用户提供灵活的配置选项,涵盖了从 AI 模型选择、语音合成、音频输入监控到界面主题设置等各个方面。该模块通过 Pinia 状态管理、Vue 3 响应式系统和国际化支持,确保配置的实时同步与多语言兼容性。

详细章节

1. Airi 卡片管理

Airi 卡片管理模块用于创建、上传、选择和删除 AI 角色卡片。它包含多个组件,如 CardCreate.vueCardCreationDialog.vueCardDetailDialog.vueCardListItem.vue,分别负责卡片的创建入口、创建对话框、详情展示和列表项渲染。

关键组件

  • CardCreate.vue: 创建卡片的 UI 入口组件,提供图标与提示文字。
  • CardCreationDialog.vue: 创建 Airi 卡片的对话框,包含多标签页表单。
  • CardDetailDialog.vue: 展示 AI 卡片详情,支持激活/删除操作。
  • CardListItem.vue: 渲染 AI 卡片列表项,支持选择、激活和删除操作。
  • DeleteCardDialog.vue: 删除确认对话框,接收控制信号并触发取消或删除事件。

Mermaid 图

2. 外观设置

外观设置模块用于管理用户界面的主题、颜色方案和开发者选项。它包含 color-presets.jsoncolor-scheme.vuedeveloper.vuegeneral.vue 等文件,分别负责颜色预设、颜色方案设置、开发者选项和通用外观设置。

关键组件

  • color-presets.json: 定义多个颜色调色板,用于主题设置。
  • color-scheme.vue: 设置主题颜色方案,支持滑块调整主色调。
  • developer.vue: 提供开发者相关配置选项,包括禁用全局过渡动画。
  • general.vue: 用于通用外观设置,包括暗色模式切换和语言选择。

Mermaid 图

3. 模型设置

模型设置模块用于控制虚拟角色模型,支持 Live2D 和 VRM 模型的切换与配置。它包含 ModelSettings 组件及其子组件 Live2D.vueVRM.vue,分别负责 Live2D 和 VRM 模型的配置。

关键组件

  • ModelSettings: 支持 2D (Live2D) 和 3D (VRM) 模型切换。
  • Live2D.vue: 提供 Live2D 模型配置界面。
  • VRM.vue: 提供 VRM 模型配置界面。

Mermaid 图

4. 模块设置

模块设置模块用于展示系统模块及其配置状态,支持意识、听力、语音、长期记忆和短期记忆等模块的配置。它包含 consciousness.vuehearing.vuespeech.vuememory-long-term.vuememory-short-term.vue 等文件。

关键组件

  • consciousness.vue: 配置 AI 意识模块的模型和提供商。
  • hearing.vue: 音频输入监控与语音活动检测组件。
  • speech.vue: 用于配置和测试语音合成(TTS)。
  • memory-long-term.vue: 长期记忆设置模块。
  • memory-short-term.vue: 短期记忆设置模块。

Mermaid 图

5. 提供商设置

提供商设置模块用于配置各种 AI 模型提供商的 API 密钥、基础 URL 和其他参数。它包含多个提供商的配置组件,如 openai.vueanthropic.vuegoogle-generative-ai.vue 等。

关键组件

  • openai.vue: 配置 OpenAI 的 API 密钥和基础 URL。
  • anthropic.vue: 配置 Anthropic 提供商的 API 密钥与基础 URL。
  • google-generative-ai.vue: 配置 Google Generative AI 提供商的 API 密钥与基础 URL。

Mermaid 图

表格

主要功能或组件及其描述

组件名称描述
CardCreate.vue创建卡片的 UI 入口组件
CardCreationDialog.vue创建 Airi 卡片的对话框
CardDetailDialog.vue展示 AI 卡片详情
CardListItem.vue渲染 AI 卡片列表项
DeleteCardDialog.vue删除确认对话框
color-presets.json定义多个颜色调色板
color-scheme.vue设置主题颜色方案
developer.vue提供开发者相关配置选项
general.vue用于通用外观设置
ModelSettings支持 2D 和 3D 模型切换
Live2D.vue提供 Live2D 模型配置界面
VRM.vue提供 VRM 模型配置界面
consciousness.vue配置 AI 意识模块
hearing.vue音频输入监控与语音活动检测
speech.vue配置和测试语音合成
memory-long-term.vue长期记忆设置模块
memory-short-term.vue短期记忆设置模块
openai.vue配置 OpenAI 的 API 密钥和基础 URL
anthropic.vue配置 Anthropic 提供商的 API 密钥与基础 URL
google-generative-ai.vue配置 Google Generative AI 提供商的 API 密钥与基础 URL

结论/总结

设置与配置模块通过多个子模块和组件,为用户提供了灵活的配置选项,涵盖了从 AI 模型选择、语音合成、音频输入监控到界面主题设置等各个方面。该模块通过 Pinia 状态管理、Vue 3 响应式系统和国际化支持,确保配置的实时同步与多语言兼容性,是项目中不可或缺的一部分。

音频处理模块

简介

音频处理模块是项目中负责处理音频数据的核心部分,涵盖从音频采集、上下文管理、编码到语音活动检测(VAD)和语音转录的完整流程。模块分为前端和后端两部分:

  • 前端部分(packages/audio/src):负责音频上下文管理、音频重采样和编码(如 WAV 格式)。
  • 后端部分(Tauri 插件):包括语音活动检测(VAD)和语音转录功能,基于 ONNX Runtime 和 Silero/Whisper 模型实现。

模块通过 IPC 与前端通信,支持实时音频处理和模型加载进度反馈。

详细章节

音频上下文管理

音频上下文管理模块(packages/audio/src/audio-context/index.ts)负责初始化和管理 Web Audio API 的 AudioContext。主要功能包括:

  • 异步初始化、挂起、恢复和清理音频上下文。
  • 管理音频节点的生命周期。
  • 加载自定义 AudioWorklet 脚本。
  • 提供状态监听机制。
  • 浏览器卸载时自动清理资源。

关键函数:

  • initializeAudioContext():创建或复用已有 AudioContext 并加载工作线程。
  • cleanupAudioContext():清理所有资源并关闭上下文。
  • subscribeToAudioContext():注册状态变更监听器。

音频重采样

音频重采样模块(packages/audio/src/audio-context/processor.worklet.ts)定义了 ResamplingAudioWorkletProcessor 类,用于将输入音频从 inputSampleRate 转换为 outputSampleRate。支持多通道处理,并使用 @alexanderolsen/libsamplerate-js 库进行重采样。

关键功能:

  • 构造函数中初始化缓冲区和消息监听。
  • process 方法对每个通道数据进行重采样处理。
  • 支持动态更新配置参数并重新初始化重采样器。
  • 通过 port.postMessage 向主线程反馈状态。

音频编码

音频编码模块(packages/audio/src/encoding/)提供 WAV 格式编码支持。主要功能包括:

  • 写入字符串辅助函数。
  • 生成符合 WAV 结构的 ArrayBuffer
  • 将输出转换为 Base64 字符串。

关键文件:

  • wav.ts:实现音频数据编码为 WAV 格式的功能。

语音活动检测(VAD)

语音活动检测模块(crates/tauri-plugin-ipc-audio-vad-ort/src/)基于 Silero VAD 和 ONNX Runtime 实现。主要功能包括:

  • 加载 Silero VAD 模型并存储于全局状态。
  • 接收音频数据并调用模型推理。
  • 通过 IPC 与前端通信。

关键组件:

  • Processor:定义在 models/silero_vad/mod.rs,支持模型下载、会话创建和推理。
  • ipc_audio_vad:接收音频数据并返回语音概率。

VAD 插件核心实现

crates/tauri-plugin-ipc-audio-vad-ort/src/lib.rs 中,我们找到了 VAD 插件的核心实现:

  1. 状态管理
   #[derive(Default)]
   struct AppDataSileroVadProcessor {
     silero_vad_processor: Option<crate::models::silero_vad::Processor>,
   }

该结构体用于存储 Silero VAD 处理器实例,通过 Tauri 的状态管理机制实现跨窗口共享。

  1. 模型加载命令
   #[tauri::command]
   async fn load_ort_model_silero_vad<R: Runtime>(
     app: tauri::AppHandle<R>,
     window: tauri::WebviewWindow<R>,
   ) -> Result<(), String> {
     // 实现模型加载逻辑
   }

该命令负责加载 Silero VAD 模型,避免重复加载。

  1. 音频推理命令
   #[tauri::command]
   async fn ipc_audio_vad<R: Runtime>(
     app: tauri::AppHandle<R>,
     input_data: VADInferenceInput,
   ) -> Result<VADInferenceResult, String> {
     // 实现音频推理逻辑
   }

该命令接收音频数据并返回语音活动检测结果。

  1. 插件初始化
   pub fn init<R: Runtime>() -> TauriPlugin<R> {
     PluginBuilder::new("ipc-audio-vad-ort")
       .setup(|app, _| {
         info!("Initializing audio VAD plugin...");
         app.manage(Mutex::new(AppDataSileroVadProcessor::default()));
         Ok(())
       })
       .invoke_handler(tauri::generate_handler![
         load_ort_model_silero_vad,
         ipc_audio_vad
       ])
       .build()
   }

Silero VAD 处理器实现

silero_vad/mod.rs 文件中,Processor 结构体封装了 ONNX Runtime 的会话,并提供了 inference 方法进行推理。该方法接收 VADInferenceInput 结构体作为输入,返回 VADInferenceResult 结构体作为输出。

模型加载过程中使用了 Hugging Face Hub 的 API,并通过 create_progress_emitter 函数创建进度发射器,向前端反馈模型下载进度。

语音转录

语音转录模块(crates/tauri-plugin-ipc-audio-transcription-ort/src/)基于 Whisper 模型和 ONNX Runtime 实现。主要功能包括:

  • 加载 Whisper 模型并存储于全局状态。
  • 接收音频数据并返回识别结果。
  • 通过 IPC 与前端通信。

关键组件:

  • WhisperPipeline:定义在 models/whisper/whisper.rs,支持模型加载、多语言识别及跨平台运行。
  • ipc_audio_transcription:接收音频数据并返回转录结果。

Mermaid 图

音频处理流程

VAD 模块结构

转录模块结构

表格

主要功能或组件

组件描述
音频上下文管理初始化和管理 Web Audio API 的 AudioContext
音频重采样将输入音频从 inputSampleRate 转换为 outputSampleRate
音频编码实现音频数据编码为 WAV 格式
语音活动检测基于 Silero VAD 和 ONNX Runtime 实现
语音转录基于 Whisper 模型和 ONNX Runtime 实现

API 接口

接口名称描述参数
ipc_audio_vad接收音频数据并调用模型推理音频数据
ipc_audio_transcription接收音频数据并返回识别结果音频数据

代码片段

音频上下文初始化

// packages/audio/src/audio-context/index.ts
async function initializeAudioContext(): Promise<AudioContext> {
  // 创建或复用已有 AudioContext 并加载工作线程
}

音频重采样处理

// packages/audio/src/audio-context/processor.worklet.ts
class ResamplingAudioWorkletProcessor extends AudioWorkletProcessor {
  process(inputs, outputs, parameters) {
    // 对每个通道数据进行重采样处理
  }
}

语音活动检测推理

// crates/tauri-plugin-ipc-audio-vad-ort/src/models/silero_vad/mod.rs
impl Processor {
  fn inference(&self, input: &[f32]) -> Result<f32, Error> {
    // 接收音频输入,返回语音概率及更新状态
  }
}

语音转录推理

// crates/tauri-plugin-ipc-audio-transcription-ort/src/models/whisper/whisper.rs
impl WhisperPipeline {
  fn transcribe(&self, audio: &[f32]) -> Result<String, Error> {
    // 接收音频输入,返回转录结果
  }
}

结论

音频处理模块涵盖了从音频采集到语音转录的完整流程,通过前后端分离的设计和 IPC 通信机制,实现了高效的音频处理和模型推理。模块结构清晰,功能明确,为项目提供了强大的音频处理能力。

Tauri 应用框架模块

简介

Tauri 插件 window-pass-through-on-hover 提供了在 macOS 和 Windows 平台上实现“鼠标悬停时窗口点击穿透”功能的能力。该模块通过周期性检测鼠标位置与窗口边界,动态控制窗口是否响应鼠标事件,从而实现穿透效果。此功能特别适用于需要临时透明化或忽略用户输入的场景。

模块的核心逻辑围绕平台特定的实现(macOS 和 Windows),以及状态管理和数据结构定义展开。通过 Tauri 的命令机制,前端可以启动或停止鼠标追踪,并启用或禁用点击穿透功能。

详细章节

平台特定实现

macOS 实现

在 macOS 平台上,模块通过 Objective-C API 获取窗口框架和鼠标位置。具体函数包括:

  • get_window_frame:获取窗口的完整外框。
  • get_mouse_location:获取当前鼠标的屏幕坐标。

这些函数用于判断鼠标是否悬停在窗口上,从而决定是否启用点击穿透。

Windows 实现

在 Windows 平台上,模块通过 Win32 API 获取窗口框架和鼠标位置。具体函数包括:

  • get_window_frame:调用 Win32 API 获取窗口矩形区域。
  • get_mouse_location:使用 Win32 API 获取鼠标坐标。

这些函数同样用于判断鼠标是否悬停在窗口上,支持“悬停穿透”等窗口行为控制逻辑。

状态管理

模块通过 WindowClickThroughState 结构体管理窗口点击穿透状态。该结构体包含监控状态和穿透开关字段,并提供以下函数:

  • set_pass_through_enabled:设置窗口是否忽略鼠标事件,并通知前端状态变更。

数据结构

模块定义了以下数据结构用于表示窗口几何信息:

  • Point:表示二维坐标。
  • Size:表示宽度和高度。
  • WindowFrame:组合起始点和尺寸。

所有结构体支持调试、复制和序列化,用于窗口交互和布局管理。

核心命令

模块提供以下核心命令:

  • start_tracing_cursor:启动定时器获取鼠标和窗口信息。
  • stop_tracing_cursor:停止定时器。
  • start_pass_through:启用点击穿透功能。
  • stop_pass_through:禁用点击穿透功能。

初始化函数

模块通过 init 函数注册命令并生成 TypeScript 类型绑定。

Mermaid图

模块架构图

状态管理图

表格

主要功能或组件及其描述

功能/组件描述
get_window_frame获取窗口框架
get_mouse_location获取鼠标位置
WindowClickThroughState管理窗口点击穿透状态
Point表示二维坐标
Size表示宽度和高度
WindowFrame组合起始点和尺寸
start_tracing_cursor启动定时器获取鼠标和窗口信息
stop_tracing_cursor停止定时器
start_pass_through启用点击穿透功能
stop_pass_through禁用点击穿透功能
init初始化函数,注册命令并生成 TypeScript 类型绑定

API 接口参数、类型和描述

接口名称参数类型描述
get_window_frame获取窗口框架
get_mouse_location获取鼠标位置
set_pass_through_enabledenabledbool设置窗口是否忽略鼠标事件
start_tracing_cursor启动定时器获取鼠标和窗口信息
stop_tracing_cursor停止定时器
start_pass_through启用点击穿透功能
stop_pass_through禁用点击穿透功能

代码片段

获取窗口框架

// macOS 实现
fn get_window_frame() -> WindowFrame {
    // 通过 Objective-C API 获取窗口的完整外框
}

// Windows 实现
fn get_window_frame() -> WindowFrame {
    // 调用 Win32 API 获取窗口矩形区域
}

获取鼠标位置

// macOS 实现
fn get_mouse_location() -> Point {
    // 获取当前鼠标的屏幕坐标
}

// Windows 实现
fn get_mouse_location() -> Point {
    // 使用 Win32 API 获取鼠标坐标
}

设置点击穿透

struct WindowClickThroughState {
    monitoring: bool,
    pass_through_enabled: bool,
}

impl WindowClickThroughState {
    fn set_pass_through_enabled(&mut self, enabled: bool) {
        self.pass_through_enabled = enabled;
        // 通知前端状态变更
    }
}

核心命令

#[tauri::command]
fn start_tracing_cursor() {
    // 启动定时器获取鼠标和窗口信息
}

#[tauri::command]
fn stop_tracing_cursor() {
    // 停止定时器
}

#[tauri::command]
fn start_pass_through() {
    // 启用点击穿透功能
}

#[tauri::command]
fn stop_pass_through() {
    // 禁用点击穿透功能
}

初始化函数

pub fn init<R: Runtime>() -> TauriPlugin<R> {
    Builder::new("window-pass-through-on-hover")
        .invoke_handler(tauri::generate_handler![
            start_tracing_cursor,
            stop_tracing_cursor,
            start_pass_through,
            stop_pass_through
        ])
        .build()
}

结论/总结

Tauri 插件 window-pass-through-on-hover 通过平台特定的实现和状态管理,实现了鼠标悬停时窗口点击穿透的功能。该模块通过 Tauri 的命令机制与前端交互,提供了灵活的窗口行为控制能力。其核心组件包括平台特定的窗口框架和鼠标位置获取函数、状态管理结构体以及核心命令接口。该模块在需要临时透明化或忽略用户输入的场景中具有重要应用价值。

AI 提示工程实验平台

简介

AI 提示工程实验平台是一个交互式实验环境,旨在帮助开发者和研究人员构建、测试和优化 AI 角色的提示词(Prompt)。该平台通过模块化设计,允许用户配置 AI 的身份、性格、语言风格等属性,并实时预览生成的完整提示内容。平台还集成了聊天模拟器,用于模拟 AI 的回复行为,从而验证提示词的有效性。

该平台基于 Vue 3 和 Pinia 构建,采用响应式布局,集成了多个核心组件,如控制面板(ControlPanel)、提示预览(PromptPreview)、聊天模拟器(ChatSimulator)和通知系统(Notification)。通过这些组件的协同工作,用户可以动态调整提示参数,观察其对 AI 行为的影响,并进行迭代优化。

详细章节

主应用组件 (App.vue)

App.vue 是整个平台的主组件,负责整合各个子组件并提供统一的用户界面。它引入了 ChatSimulatorControlPanelPromptPreviewNotification 等组件,并在挂载时调用函数将 Markdown 文件转换为 HTML 输出到控制台。

组件结构

  • ControlPanel: 用于配置 AI 的身份、性格、语言风格等参数。
  • PromptPreview: 动态展示由多个模块组合而成的完整提示内容。
  • ChatSimulator: 模拟 AI 的回复行为,支持自定义角色的个性与语言风格。
  • Notification: 显示临时通知,如“Prompt copied to clipboard!”。

数据流

  1. 用户通过 ControlPanel 配置 AI 角色属性。
  2. 配置信息通过 Pinia 状态管理传递给 PromptPreview,生成完整的提示内容。
  3. 用户可以在 ChatSimulator 中模拟 AI 的回复行为。
  4. 通过 Notification 组件提供操作反馈。

控制面板 (ControlPanel.vue)

ControlPanel.vue 是角色配置的核心组件,允许用户设置 AI 的身份、性格、语言风格等参数。它通过 Pinia 进行状态管理,支持预设模板和 token 数量统计。

功能模块

  • 身份配置: 设置 AI 的角色身份,如“助手”、“专家”等。
  • 性格配置: 定义 AI 的性格特征,如“友好”、“严肃”等。
  • 语言风格: 选择 AI 的语言风格,如“正式”、“幽默”等。
  • 预设模板: 提供预设的角色模板,方便快速配置。
  • Token 统计: 实时统计生成的提示内容的 token 数量。

与 Pinia 状态管理的交互

ControlPanel.vue 通过 Pinia 状态管理库与平台的其他组件进行数据交互。当用户在控制面板中修改 AI 角色的属性时,这些更改会立即同步到 Pinia store 中,从而触发其他组件的更新。例如,当用户更改 AI 的身份或性格时,PromptPreview.vue 会立即更新以反映这些更改。

支持的配置选项

ControlPanel.vue 支持多种配置选项,包括:

  • 身份: 设置 AI 的角色身份,如“助手”、“专家”等。
  • 性格: 定义 AI 的性格特征,如“友好”、“严肃”等。
  • 语言风格: 选择 AI 的语言风格,如“正式”、“幽默”等。
  • 预设模板: 提供预设的角色模板,方便快速配置。

在平台中的作用和数据流

ControlPanel.vue 是平台的核心组件之一,负责收集用户的配置信息并将其传递给其他组件。它通过 Pinia 状态管理库与 PromptPreview.vueChatSimulator.vue 进行数据交互,确保所有组件都能实时反映用户的配置更改。

提示预览 (PromptPreview.vue)

PromptPreview.vue 是角色提示预览组件,动态展示由多个模块组合而成的完整提示内容。它通过 Pinia 响应数据变化,支持折叠/展开模块和 token 计算。

功能模块

  • 模块展示: 展示提示内容的各个模块,如身份、性格、语言风格等。
  • 折叠/展开: 支持用户折叠或展开提示模块,方便查看。
  • Token 计算: 实时计算并显示提示内容的 token 数量。

聊天模拟器 (ChatSimulator.vue)

ChatSimulator.vue 是一个聊天模拟组件,支持自定义角色的个性与语言风格。主要功能包括 AI 回复模拟、视图切换、清空历史、复制提示词等,依赖 Pinia store 管理消息和延迟展示。

功能模块

  • AI 回复模拟: 模拟 AI 的回复行为,支持自定义角色的个性与语言风格。
  • 视图切换: 支持切换聊天视图,如“对话模式”、“调试模式”等。
  • 清空历史: 清空聊天历史记录。
  • 复制提示词: 将生成的提示词复制到剪贴板。

通知系统 (Notification.vue)

Notification.vue 是一个临时通知组件,显示“Prompt copied to clipboard!”信息并自动隐藏。通过 isActive 控制显示状态,支持跨层级通信和动画反馈。

功能模块

  • 临时通知: 显示临时通知信息,如“Prompt copied to clipboard!”。
  • 自动隐藏: 通知信息在一定时间后自动隐藏。
  • 动画反馈: 通过 CSS 动画提供视觉反馈。

可组合模块 (useCharacterPrompt.ts, useChatSimulator.ts)

useCharacterPrompt.tsuseChatSimulator.ts 是 Vue 可组合模块,基于 Pinia 管理数字角色的提示模板和聊天模拟器。它们结构化存储角色属性,并提供 API 方法动态更新配置,输出完整 prompt 或模块内容。

功能模块

  • 角色提示管理: 管理数字角色的提示模板,结构化存储角色属性。
  • 聊天模拟管理: 管理聊天模拟器的消息数据结构与 store。
  • API 方法: 提供 API 方法动态更新配置,输出完整 prompt 或模块内容。

样式管理 (main.css, transitions.css)

main.csstransitions.css 负责平台的样式管理。main.css 设置网页基础样式和过渡效果,transitions.css 定义动画过渡效果,实现元素进入或离开视图的平滑动画。

功能模块

  • 基础样式: 设置网页基础样式,如背景色、高度、边距等。
  • 过渡效果: 定义元素进入或离开视图的平滑动画。

Mermaid 图

平台架构图

数据流图

表格

主要功能或组件及其描述

组件名称描述
App.vue主应用组件,整合各个子组件
ControlPanel.vue角色配置面板,设置 AI 的身份、性格、语言风格等参数
PromptPreview.vue角色提示预览组件,动态展示提示内容
ChatSimulator.vue聊天模拟组件,模拟 AI 的回复行为
Notification.vue临时通知组件,显示操作反馈
useCharacterPrompt.ts管理数字角色的提示模板
useChatSimulator.ts管理聊天模拟器的消息数据结构与 store
main.css设置网页基础样式和过渡效果
transitions.css定义动画过渡效果

配置选项及其类型和默认值

配置项类型默认值描述
minNumber0滑块控件的最小值
maxNumber100滑块控件的最大值
stepNumber1滑块控件的步长
modelValueNumber50滑块控件的当前值

代码片段

滑块控件 (Range.vue)

<template>
  <input
    type="range"
    :min="min"
    :max="max"
    :step="step"
    v-model="modelValue"
  />
</template>

<script setup>
defineProps({
  min: {
    type: Number,
    default: 0
  },
  max: {
    type: Number,
    default: 100
  },
  step: {
    type: Number,
    default: 1
  },
  modelValue: {
    type: Number,
    default: 50
  }
});
</script>

结论/总结

AI 提示工程实验平台通过模块化设计和响应式布局,为开发者和研究人员提供了一个高效的提示词构建和测试环境。平台集成了控制面板、提示预览、聊天模拟器和通知系统等多个核心组件,通过 Pinia 状态管理和可组合模块,实现了动态配置和实时反馈。该平台不仅支持自定义 AI 角色的属性配置,还提供了丰富的交互功能,帮助用户优化提示词,提升 AI 的表现。

UI 动画与过渡效果模块

简介

UI 动画与过渡效果模块是项目中用于增强用户界面交互体验的核心组件集合。该模块主要包括两部分:页面过渡动画(ui-transitions)和加载动画(ui-loading-screens),以及用于控制动画回放的通用组件(stage-ui 中的 Animations)。这些组件通过 Vue 的响应式系统和 CSS 动画技术,为用户提供流畅、美观的视觉反馈。

页面过渡动画模块提供了一系列预定义的过渡效果,如箭头展开、波纹扩散、掉落动画等,适用于页面切换或组件状态变化。加载动画模块则专注于加载状态的视觉呈现,包括带进度条的 Logo 加载和科幻风格的控制台模拟。此外,Replayable 组件和 useReplayable Hook 提供了动画回放的通用逻辑,支持手动触发、自动循环和热键操作。

详细章节

页面过渡动画组件

页面过渡动画组件位于 packages/ui-transitions/src/components 目录下,通过 StageTransitionGroup.vue 进行统一管理。这些组件通过 props 接收配置参数(如颜色、z-index、方向等),并在挂载时将其注入为 CSS 变量,利用 CSS 的 @keyframes 和伪元素实现各种动画效果。

ArrowTransition.vue

实现基于 CSS 的箭头形状页面过渡动画。通过 stageTransition 设置颜色和 z-index,挂载时注入为 CSS 变量。模板渲染固定容器,样式中使用伪元素和 @keyframes arrowIn/arrowOut 实现展开与收起效果。

BubbleWaveOutTransition.vue

实现圆形波纹扩展动画。接收配置参数并注入为 CSS 变量,模板用 v-for 渲染多个绝对定位 div,CSS 中定义 @keyframes circleExpand 动画,形成波浪扩散效果。

FantasyFallTransition.vue

实现从四个方向掉落的过渡动画。通过 props 接收颜色、方向等参数并注入为 CSS 自定义属性,模板绑定类名控制方向,样式中使用伪元素和 @keyframes 实现视觉效果。

MultipleBlocksRevealTransition.vue

实现多区块渐显动画。通过 stageTransition 控制背景色和层级,并注入为 CSS 变量,模板渲染 5 个等高区块,结合伪元素和 slideIn/slideOut 动画实现交错进入退出效果。

RectanglesRotateTransition.vue

实现矩形旋转扩展动画。通过 props 接收颜色、角度等参数并注入为 CSS 变量,模板渲染三个绝对定位矩形,样式中定义 @keyframes expand-rotate 实现缩放与旋转动画。

SlideTransition.vue

实现滑动过渡动画。通过 props 接收颜色和 z-index 并注入为 CSS 变量,模板渲染固定容器,样式中使用伪元素和 slideIn/slideOut 动画实现左侧滑入再滑出效果。

SlopeSlideTransition.vue

实现斜面滑动过渡动画。通过 props 接收颜色和 z-index 并注入为 CSS 变量,模板渲染固定容器,样式中使用两个伪元素和 maskIn/maskOut 动画,通过 clip-path 实现斜面滑动。

StageTransitionGroup.vue

过渡动画管理器,集成多个子组件如 SlideTransitionArrowTransition 等,用于控制页面导航动画。通过 Vue Router 钩子触发动画流程,支持自定义颜色、zIndex 和禁用过渡。

const props = defineProps<{
  primaryColor?: string
  secondaryColor?: string
  tertiaryColor?: string
  colors?: string[]
  zIndex?: number
  disableTransitions?: boolean
  usePageSpecificTransitions?: boolean
}>()
const transitions = shallowRef<Record<string, TransitionOptions>>({
  'slide': {
    component: SlideTransition,
    duration: 2700,
  },
  'slope-slide': {
    component: SlopeSlideTransition,
    duration: 2700,
  },
  'arrow': {
    component: ArrowTransition,
    duration: 2700,
  },
  'multiple-blocks-reveal': {
    component: MultipleBlocksRevealTransition,
    duration: 2700,
  },
  'rectangles-rotate': {
    component: RectanglesRotateTransition,
    duration: 2700,
  },
  'bubble-wave-out': {
    component: BubbleWaveOutTransition,
    duration: 2700,
  },
  'fantasy-fall': {
    component: FantasyFallTransition,
    duration: 6000,
  }
})
router.beforeEach((to, _from, next) => {
  if (props.disableTransitions) {
    next()
    return
  }

  if (typeof to.meta.stageTransition !== 'object') {
    next()
    return
  }

  const stageTransition = to.meta.stageTransition as StageTransitionCommonParams
  triggerTransition(stageTransition, next)
})
function triggerTransition(params: StageTransitionCommonParams, next: NavigationCallback) {
  return new Promise<void>((resolve) => {
    triggerTransitionAsyncFn(params, next, resolve)
  })
}

加载动画组件

加载动画组件位于 packages/ui-loading-screens/src/components 目录下,提供两种不同风格的加载界面。

LoadingLogoWithBar.vue

显示带进度条的 Logo 加载动画,支持 stepprogressdone 状态;提供更新方法与插槽机制,实现自定义内容和状态访问;使用 Vue <Transition> 实现淡出动画。

LoadingSciFiCircle

实现科幻风格加载界面,模拟系统启动控制台输出。使用 Rive 渲染动画,封装在 <CRT><CRTLine> 中;支持文本逐字符输出、主题切换与响应式布局。

  • CRTLine.vue: 模拟 CRT 显示器故障艺术效果,使用 CSS 动画生成红蓝偏移文字层;支持任意内容插入,适用于科幻风格 UI。
  • CRT.vue: 创建 CRT 显示器模拟界面,结合 SVG 过滤器与 AVIF 图像资源;支持滚动输出、闪烁速度配置及深色/浅色模式适配。

动画回放控制组件

动画回放控制组件位于 packages/stage-ui/src/components/Animations 目录下,提供通用的动画回放逻辑。

Replayable.vue

用于控制动画回放的 Vue 组件,支持手动触发、自动循环播放和热键操作。核心包括:回放逻辑管理,通过回调执行子组件动画重置;使用响应式变量记录回放状态与次数;支持根据属性定时自动回放;热键监听实现快捷回放;提供按钮控件显示回放状态;生命周期中初始化监听并动态更新行为;暴露方法供外部调用。

use-replayable.ts

Vue 自定义 Hook,用于注册和管理“重播”逻辑。它通过 inject 获取父级提供的 ReplayableContext 上下文,包含 registerReplayCallbackisReplaying 方法。前者用于注册回调函数,后者判断是否处于重播状态。若传入 replayFn,则自动注册并在卸载时取消;若未找到上下文,则输出警告并提供空实现。

表格

主要功能或组件及其描述

组件名称描述
ArrowTransition实现基于 CSS 的箭头形状页面过渡动画
BubbleWaveOutTransition实现圆形波纹扩展动画
FantasyFallTransition实现从四个方向掉落的过渡动画
MultipleBlocksRevealTransition实现多区块渐显动画
RectanglesRotateTransition实现矩形旋转扩展动画
SlideTransition实现滑动过渡动画
SlopeSlideTransition实现斜面滑动过渡动画
StageTransitionGroup过渡动画管理器
LoadingLogoWithBar显示带进度条的 Logo 加载动画
LoadingSciFiCircle实现科幻风格加载界面
CRTLine模拟 CRT 显示器故障艺术效果
CRT创建 CRT 显示器模拟界面
Replayable用于控制动画回放的 Vue 组件
useReplayableVue 自定义 Hook,用于注册和管理“重播”逻辑

配置选项及其类型和默认值

组件名称配置项类型默认值
ArrowTransitionstageTransitionObject
BubbleWaveOutTransition配置参数Object
FantasyFallTransition颜色、方向String, String
MultipleBlocksRevealTransitionstageTransitionObject
RectanglesRotateTransition颜色、角度String, Number
SlideTransition颜色、z-indexString, Number
SlopeSlideTransition颜色、z-indexString, Number
StageTransitionGroup颜色、zIndex、禁用过渡String, Number, Boolean
LoadingLogoWithBarstep、progress、doneString, Number, Boolean
LoadingSciFiCircle文本、主题String, String
CRT滚动输出、闪烁速度Boolean, Number
Replayable定时、热键Number, String

结论/总结

UI 动画与过渡效果模块通过一系列精心设计的 Vue 组件,为项目提供了丰富且灵活的动画解决方案。从页面过渡到加载状态,再到动画回放控制,这些组件共同构成了一个完整的 UI 动画生态系统,极大地提升了用户体验和界面的视觉吸引力。通过模块化的设计和清晰的 API,开发者可以轻松地集成和定制这些动画效果,以满足不同场景下的需求。StageTransitionGroup.vue 作为核心管理组件,通过与 Vue Router 的深度集成,实现了页面级别的过渡动画控制,是整个模块的关键所在。

Discord 机器人模块

简介

Discord 机器人模块是项目中负责与 Discord 平台交互的核心组件,旨在提供语音识别、语音合成和命令响应功能。该模块通过注册斜杠命令(如 /ping/summon)与用户交互,并支持加入语音频道、监听语音输入、将语音转为文本、播放 AI 回应等功能。模块依赖于多个工具类和常量配置,确保音频处理流程的统一性和高效性。

详细章节

1. 启动与初始化

机器人启动入口位于 index.ts 文件中,负责初始化 Discord 客户端、设置意图、加载 Token 并登录服务器。同时,它还引入了 VoiceManager 类和命令注册逻辑。

关键组件

  • AiriClient: 机器人客户端实例。
  • registerCommands: 命令注册函数。
  • VoiceManager: 语音管理类。

启动流程图

2. 命令处理

命令处理逻辑分布在多个文件中,包括 ping.tssummon.tsping.ts 定义了 /ping 命令的处理函数,而 summon.ts 定义了 /summon 命令及相关语音管理功能。

关键函数

  • handlePing: 处理 /ping 命令并回复 “Pong!”。
  • VoiceManager: 管理语音连接、音频流和语音识别。

命令处理流程图

3. 语音处理

语音处理功能由 VoiceManager 类主导,涉及音频流监控、语音识别和音频播放。相关工具类包括 AudioMonitorOpusDecoder 和音频转换函数。

关键类和方法

  • VoiceManager: 管理语音连接和音频流。
  • joinChannel: 加入语音频道。
  • leaveChannel: 离开语音频道。
  • monitorMember: 监听成员语音。
  • processTranscription: 处理语音转文本。
  • playAudioStream: 播放音频流。
  • AudioMonitor: 监控音频流并管理数据收集。
  • OpusDecoder: 将 Opus 音频解码为 PCM。

语音处理流程图

4. 音频工具与常量

音频处理过程中使用了多个工具函数和常量配置,以确保音频数据的标准化和一致性。

关键工具函数

  • generateWavHeader: 生成 WAV 文件头。
  • convertOpusToWav: 将 Opus 数据转换为 WAV 格式。
  • convertPcmToWav: 将 PCM 数据转换为 WAV 格式。

音频常量

  • SAMPLE_RATE: 音频采样率。
  • CHANNELS: 音频通道数。
  • BIT_DEPTH: 音频位深度。

表格

主要功能或组件

组件名称描述
AiriClientDiscord 机器人客户端实例
VoiceManager管理语音连接、音频流和语音识别
AudioMonitor监控音频流并管理数据收集
OpusDecoder将 Opus 音频解码为 PCM
handlePing处理 /ping 命令并回复 “Pong!”

音频常量配置

常量名称类型默认值描述
SAMPLE_RATEnumber16000音频采样率
CHANNELSnumber1音频通道数
BIT_DEPTHnumber16音频位深度

代码片段

handlePing 函数

// services/discord-bot/src/bots/discord/commands/ping.ts
export function handlePing(interaction: CommandInteraction) {
    interaction.reply('Pong!');
}

VoiceManager 类

// services/discord-bot/src/bots/discord/commands/summon.ts
class VoiceManager extends EventEmitter {
    private logger: Logger;
    private processingVoice: boolean;
    private transcriptionTimeout: NodeJS.Timeout | null;
    private userStates: Map<string, UserState>;
    private activeAudioPlayer: AudioPlayer | null;
    private client: Client;
    private airiClient: AiriClient;
    private streams: Map<string, Readable>;
    private connections: Map<string, VoiceConnection>;
    private activeMonitors: Map<string, AudioMonitor>;

    constructor(client: Client, airiClient: AiriClient) {
        super();
        this.logger = new Logger('VoiceManager');
        this.processingVoice = false;
        this.transcriptionTimeout = null;
        this.userStates = new Map();
        this.activeAudioPlayer = null;
        this.client = client;
        this.airiClient = airiClient;
        this.streams = new Map();
        this.connections = new Map();
        this.activeMonitors = new Map();
    }

    public async joinChannel(channel: VoiceChannel): Promise<void> {
        const connection = joinVoiceChannel({
            channelId: channel.id,
            guildId: channel.guild.id,
            adapterCreator: channel.guild.voiceAdapterCreator,
        });

        this.connections.set(channel.guild.id, connection);
        this.setupVoiceReceiver(connection, channel.guild.id);
    }

    public leaveChannel(guildId: string): void {
        const connection = this.connections.get(guildId);
        if (connection) {
            connection.destroy();
            this.connections.delete(guildId);
        }
    }

    private setupVoiceReceiver(connection: VoiceConnection, guildId: string): void {
        const receiver = connection.receiver;
        receiver.speaking.on('start', (userId: string) => {
            this.handleUserStartSpeaking(userId, receiver, guildId);
        });
    }

    private handleUserStartSpeaking(userId: string, receiver: VoiceReceiver, guildId: string): void {
        const opusStream = receiver.subscribe(userId, { end: { behavior: EndBehaviorType.AfterSilence, duration: 1000 } });
        const pcmStream = new OpusDecoder();
        const wavStream = new PassThrough();

        opusStream.pipe(pcmStream).pipe(wavStream);

        const monitor = new AudioMonitor();
        wavStream.on('data', (chunk: Buffer) => {
            monitor.addAudioData(chunk);
        });

        this.activeMonitors.set(userId, monitor);
        this.streams.set(userId, wavStream);

        if (this.transcriptionTimeout) {
            clearTimeout(this.transcriptionTimeout);
        }

        this.transcriptionTimeout = setTimeout(() => {
            this.processTranscription(monitor.getAudioData(), userId, guildId);
        }, 2000);
    }

    private async processTranscription(audioData: Buffer, userId: string, guildId: string): Promise<void> {
        if (audioData.length === 0) return;

        try {
            const transcription = await openaiTranscribe(audioData);
            this.emit('transcription', { userId, guildId, text: transcription });
        } catch (error) {
            this.logger.error('Error transcribing audio:', error);
        } finally {
            this.cleanupUserResources(userId);
        }
    }

    public async playAudioStream(stream: Readable, guildId: string): Promise<void> {
        const connection = this.connections.get(guildId);
        if (!connection) return;

        const resource = createAudioResource(stream, { inputType: StreamType.Arbitrary });
        const player = createAudioPlayer();

        player.play(resource);
        connection.subscribe(player);

        this.activeAudioPlayer = player;

        player.on('stateChange', (oldState, newState) => {
            if (newState.status === AudioPlayerStatus.Idle && oldState.status !== AudioPlayerStatus.Idle) {
                this.emit('audioFinished', guildId);
            }
        });
    }

    private cleanupUserResources(userId: string): void {
        const monitor = this.activeMonitors.get(userId);
        if (monitor) {
            monitor.resetAudioData();
            this.activeMonitors.delete(userId);
        }

        const stream = this.streams.get(userId);
        if (stream) {
            stream.destroy();
            this.streams.delete(userId);
        }
    }
}

OpusDecoder 类

// services/discord-bot/src/utils/opus.ts
class OpusDecoder extends Transform {
    private decoder: OpusScript;

    constructor() {
        super();
        this.decoder = new OpusScript(16000, 1, OpusScript.Application.AUDIO);
    }

    _transform(chunk: Buffer, encoding: string, callback: TransformCallback) {
        try {
            const decoded = this.decoder.decode(chunk);
            callback(null, decoded);
        } catch (error) {
            callback(error);
        }
    }

    _flush(callback: TransformCallback) {
        this.decoder.delete();
        callback();
    }
}

结论

Discord 机器人模块通过整合命令处理、语音识别和音频播放功能,实现了与用户的高效交互。其模块化设计和清晰的流程确保了系统的可扩展性和可维护性,是项目中不可或缺的一部分。VoiceManager 类作为核心组件,实现了完整的语音处理流程,从加入频道、监听语音、转录文本到播放回应,为用户提供了一体化的语音交互体验。

Minecraft 智能机器人模块

简介

Minecraft 智能机器人模块是一个基于 Mineflayer 的 AI 驱动系统,旨在赋予 Minecraft 机器人自主行为能力。该模块通过集成多个代理(Agent)系统,包括动作代理(Action Agent)、聊天代理(Chat Agent)、规划代理(Planning Agent)和记忆代理(Memory Agent),实现对 Minecraft 世界的感知、决策与交互。机器人能够执行复杂任务、响应玩家指令、管理自身状态,并通过 LLM(大语言模型)进行自然语言交互。

该模块依赖于 Neuri 框架进行智能体管理,并通过 awilix 实现依赖注入,确保模块间的解耦与可扩展性。核心功能包括:

  • 动作执行(如采集、合成、战斗等)
  • 自然语言聊天交互
  • 任务规划与执行
  • 状态记忆与管理

架构概览

核心模块结构

Minecraft 智能机器人模块由以下核心部分组成:

  1. Mineflayer 核心:封装 Minecraft 机器人核心逻辑,集成健康、记忆、组件管理等模块。
  2. LLM Agent 系统:通过 Neuri 框架调用 LLM,实现聊天、动作和规划代理。
  3. 技能系统:提供具体动作实现,如采集、合成、战斗等。
  4. 插件系统:扩展机器人功能,如跟随、路径查找等。

Mermaid 架构图

详细章节

1. Mineflayer 核心模块

Mineflayer 核心模块是整个系统的基础,负责封装 Minecraft 机器人的核心逻辑。它集成了健康、记忆、组件管理等模块,提供了机器人运行所需的基本功能。

关键类与接口

  • Mineflayer 类:封装 Minecraft 机器人核心逻辑。
  • Health 类:管理角色的健康状态。
  • Memory 类:存储聊天历史和操作记录。
  • Components 类:管理组件注册与获取。

代码片段

// services/minecraft/src/libs/mineflayer/core.ts
class Mineflayer {
  health: Health;
  memory: Memory;
  components: Components;

  constructor() {
    this.health = new Health();
    this.memory = new Memory();
    this.components = new Components();
  }
}

2. LLM Agent 系统

LLM Agent 系统通过 Neuri 框架调用 LLM,实现聊天、动作和规划代理。每个代理负责处理特定类型的任务,并通过依赖注入容器进行管理。

关键类与接口

  • BaseLLMHandler 抽象类:封装 LLM 交互逻辑。
  • ChatLLMHandler 类:处理聊天交互。
  • ActionLLMHandler 类:处理动作执行。
  • PlanningLLMHandler 类:处理任务规划。

代码片段

// services/minecraft/src/libs/llm-agent/handler.ts
abstract class BaseLLMHandler {
  abstract handleCompletion(messages: Message[]): Promise<string>;
  createRetryHandler(): (error: Error) => void {
    // 实现重试逻辑
  }
}

3. 技能系统

技能系统提供具体动作实现,如采集、合成、战斗等。每个技能模块封装了特定任务的逻辑,并通过接口与核心模块交互。

关键类与接口

  • collectBlock 函数:实现自动收集指定方块。
  • craftRecipe 函数:实现物品合成。
  • attackNearest 函数:实现攻击最近的敌对生物。

代码片段

// services/minecraft/src/skills/actions/collect-block.ts
async function collectBlock(bot: Mineflayer, blockType: string): Promise<void> {
  // 实现采集逻辑
}

4. 插件系统

插件系统扩展机器人功能,如跟随、路径查找等。每个插件通过接口与核心模块交互,并在机器人启动时加载。

关键类与接口

  • FollowCommand 插件:实现机器人跟随玩家。
  • PathFinder 插件:实现路径查找功能。

代码片段

// services/minecraft/src/plugins/follow.ts
class FollowCommand implements MineflayerPlugin {
  onEnable(bot: Mineflayer): void {
    // 注册跟随逻辑
  }
}

主要功能与组件

功能/组件描述
Mineflayer 核心封装 Minecraft 机器人核心逻辑
LLM Agent 系统通过 Neuri 框架调用 LLM
技能系统提供具体动作实现
插件系统扩展机器人功能

总结

Minecraft 智能机器人模块通过集成 Mineflayer、LLM Agent 系统、技能系统和插件系统,实现了高度自主的 Minecraft 机器人。该模块具备强大的扩展性和灵活性,能够适应多种任务需求,并通过 LLM 实现自然语言交互,为 Minecraft 机器人赋予了智能行为能力。


本网站提供的所有AI生成内容均基于人工智能技术和大语言模型算法,根据用户输入指令自动生成。生成内容不代表本网站观点,亦不构成任何形式的专业建议。本公司对生成内容的准确性、完整性、适用性及合法性不作明示或默示的保证,用户应对生成内容自行判断并承担全部使用风险。

《用户使用协议》