Project AIRI v0.5.0 开发日志解析:Character Card 角色卡体系、浏览器实时语音链路与 WebGPU 本地推理
2026/9/10 10:38:34 网站建设 项目流程

Project AIRI v0.5.0 开发日志解析:Character Card 角色卡体系、浏览器实时语音链路与 WebGPU 本地推理

【免费下载链接】airi💖🧸 Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-sama's altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi

本文基于 Project AIRI 官方开发者日志 DevLog @ 2025.05.16(即 v0.5.0 发布日志)展开。日志记录了这几个月社区维护者在 Character Card(角色卡)支持、Tauri MCP、Android 设备接入、实时语音工作流、WebGPU 本地推理、Telegram Bot、Velin 提示词工具等多个方向的成果。读完本文,你将掌握 AIRI 角色卡(Airi Card)从导入、编辑到运行时生效的完整链路,理解 VAD/ASR/TTS 实时语音管线的设计思路,并了解浏览器端 WebGPU 推理与背景移除工具的实现细节。

这篇 DevLog 由 Project AIRI 发起人 Neko 撰写,发布于 2025 年 5 月 16 日,同时标志着 v0.5.0 版本发布。由于 3 月以来的大型 UI 重构与发布消耗了大量精力,日志坦诚地提到核心功能进展趋缓,大量工作由社区维护者完成——其中最突出的是 Character Card 支持(@LemonNekoGH@RainbowBird@LittleSound等人的贡献),以及 Tauri MCP 支持与 Android 设备连接(@LemonNekoGH)。

Character Card 角色卡:AIRI 的"灵魂容器"

什么是 Character Card?

日志用一个 Tip 框解释了 Character Card 的概念:本地优先的聊天应用(如 SillyTavern、RisuAI)或在线服务(如 JanitorAI)使用一个文件来承载每个角色的背景、性格及其他角色扮演所必需的上下文信息。角色卡是存储与分享 LLM 驱动的角色扮演角色的一种载体,而 Lorebook 在角色扮演领域扮演着另一个关键角色(日志提示读者可自行查阅 Void's Lorebook Types 与 AI Dynamic Storytelling Wiki 了解相关概念)。

在 AIRI 中,这套能力被命名为Airi Card,并沉淀为一个独立的协议包 packages/ccc(@proj-airi/ccc,Character Card protocol primitives for AIRI)。

如何在应用内启用 Airi Card

日志给出的操作路径非常明确:

  1. 进入应用Settings 页面(网页端位于应用右上角,桌面端悬停齿轮图标);
  2. 找到并点击"Airi Card"按钮,打开角色卡菜单;
  3. 进入Airi Card 编辑器,上传并编辑角色卡,完成人设个性化定制。

这套编辑器背后对应的是airi-card运行时 Store:packages/stage-ui/src/stores/modules/airi-card.ts,以及角色卡展示组件 packages/stage-ui/src/components/menu/character-card.story.vue(可在 UI 组件库中以 ReLU 为例直接试玩)。

CCv3 协议层:解析、校验与兼容性分类

社区角色卡生态的事实标准是 Character Card Spec V3(CCv3)。@proj-airi/ccc包在 packages/ccc/src/codec/characterCardV3.ts 中实现了完整的 CCv3 JSON 信封(envelope)校验。核心 API 用法如下:

import { parseCharacterCardV3 } from '@proj-airi/ccc' const { card, compatibility } = parseCharacterCardV3(jsonText) const characterName = card.data.name const versionSupport = compatibility // 'older' | 'current' | 'newer'

该实现有三个值得注意的设计决策(见 characterCardV3.ts):

  • 兼容性分类resolveCompatibilityspec_version与当前版本3比较,返回'older' | 'current' | 'newer'。旧版与更新版本的spec_version都可导入,compatibility让调用方自行决定是否向用户告警;
  • 未知字段向前兼容:所有 schema 均使用objectWithRest包裹,未来 CCv3 新增字段会原样保留在校验输出上,不会在导入/导出时被静默删除;
  • 明确错误边界:JSON 损坏或结构非法时抛出InvalidCharacterCardError,并保留原始sourceisInvalidCharacterCardError用于区分协议失败与存储/文件系统错误。

数据契约覆盖的字段(characterCardV3.ts)包括namedescriptionpersonalityscenariofirst_mesmes_examplealternate_greetingscharacter_book(角色专属 Lorebook)、character_versioncreatorcreator_notesextensionspost_history_instructionssystem_prompttagsassetsgroup_only_greetingsnicknamesource等;其中extensions还定义了depth_promptfavtalkativenessworld等社区常用扩展字段。card.ts中的 define/card.ts 进一步提供了应用侧统一的Card类型与defineCard/defineCardFn辅助函数,将 CCv3 原始字段映射为更友好的驼峰命名。

应用层:Airi Card 如何驱动运行时

导入的角色卡并不会直接注入运行时。airi-cardStore(packages/stage-ui/src/stores/modules/airi-card.ts)承担了"协议 → 应用模型 → 运行时模块"的桥接:

  • 持久化:卡片集合与激活卡片 ID 分别保存在本地存储键airi-cardsairi-card-active-id中,内置default卡(角色 ReLU)作为所有运行时配置文件的兜底回退;
  • System Prompt 组装resolveSystemPrompt,airi-card.ts):按固定顺序拼接systemPromptdescriptionpersonalityscenario以及 artistry 模块的widgetInstruction,用空行分隔。日志明确提到"位置敏感的 CCv3 字段被刻意排除",因为它们的顺序与角色语义应由 provider 消息组装层负责;
  • 模块配置合并resolveAiriExtension):角色卡通过 CCv3 的extensions.airi扩展携带 AIRI 专属运行时配置,包括consciousness(意识/LLM 的 provider 与 model)、visionspeech(provider/model/voice_id,以及 pitch、rate、ssml、language)、displayModelId(身体模型)、activeBackgroundIdartistry(绘画模块:enabled、provider、model、promptPrefix、widgetInstruction、spawnMode、autonomousEnabled/autonomousThreshold/autonomousTarget)与agents。合并时以现有配置优先、缺失时回退到全局默认值;
  • 切换即生效activateCard/applyActiveCardSettings):选中角色卡后,其模块配置会立即写入 consciousness、speech、vision、artistry 与舞台模型等运行时 Store——也就是说,切换角色卡相当于一次性切换整套人设、语音、视觉与身体模型配置。所有相关 action 均通过 Pinia 的synced选项在跨窗口间同步执行。

角色卡分享:Airi Card Package 格式

为了分享角色卡(而不只是导入他人卡),AIRI 还定义了可移植的打包格式,实现在 packages/stage-ui/src/services/airi-card-import-export.ts:

  • 导出时生成一个 ZIP 包,包含manifest.jsonformat: 'airi-character-card'version: 1card.json路径及spec: 'chara_card_v3')与card.json(CCv3 文档),若角色卡配置了显示模型,则把模型文件打包进resources.displayModel(支持 Live2D zip、Spine zip、Tachie zip、VRM 四种格式);
  • 导入时通过 valibot schema 严格校验 manifest 与 card.json,并从白名单中恢复字段(airi-card-import-export.ts);
  • 该格式刻意不是无损备份:它只包含创建编辑器允许发送方审查的字段、经过净化的 AIRI 模块子集和所选显示模型,未审查的 CCv3 元数据、自定义扩展、agent 提示词与机器本地的运行时引用都会被省略(sanitizeAiri),防止"导入即被注入"的安全风险。

实时语音链路:从 VAD 到 TTS 的简化革命

问题:旧工作流过度复杂

从 4 月 15 日起,作者发现 AIRI 中的 VAD(语音活动检测)、ASR(自动语音识别)与 TTS(语音合成)链路非常复杂且难以理解。过去没有这些抽象时,需要手动包装一个队列结构,再叠加上 Vue 响应式驱动的工作流系统,才能把大量异步任务串起来处理数据。

期间作者与@himself65合作,为 Llama Index 的新项目llama-flow(一个用于处理 LLM 流式 token 与音频字节事件流的类型安全小型库)改进与测试使用场景。得益于这种类型安全的小型库,作者开始大量实验如何简化 VAD/ASR/TTS 工作流,最终产出了 WebAI Realtime Voice Chat Examples 示例集——用300~500 行 TypeScript即可在浏览器中实现 ChatGPT 级别的实时语音对话系统(对应视频见日志附带的webai-examples-demo.MP4)。

该示例集按渐进式阶段拆分,每一步都是可复用的小件:

  • VAD:纯语音活动检测;
  • VAD + ASR:检测到语音后自动识别;
  • VAD + ASR + LLM Chat:加入大模型对话;
  • VAD + ASR + LLM Chat + TTS:完整实时语音对话闭环。

此外社区成员@luoling还基于 k2-fsa/sherpa-onnx(一个跨 macOS / Windows / Linux / Android / iOS、支持 18 种语音处理任务、12 种以上语言的项目)制作了 Sherpa ONNX 版 VAD + ASR + LLM Chat + TTS 演示。

仓库中的落地产物:VAD Worker

这一轮探索在 AIRI 仓库内也有直接对应实现:apps/stage-web/src/workers/vad/ 下的 VAD worker(vad.tsmanager.tsprocess.worklet.ts)。

vad.ts 的默认配置参数值得直接参考:

参数默认值含义
sampleRate16000采样率
speechThreshold0.3判定"开始说话"的概率阈值
exitThreshold0.1判定"停止说话"的概率阈值
minSilenceDurationMs400最短静音时长(达到即视为语句结束)
speechPadMs80语句前后保留的缓冲
minSpeechDurationMs250最短有效语音时长
maxBufferDuration30环形缓冲最大时长(秒)
newBufferSize512每帧音频块大小

模型方面通过@huggingface/transformersAutoModel.from_pretrained加载onnx-community/silero-vad(fp32 精度),在 Worker 线程中维护推理链,将 VAD 计算完全移出主线程,避免阻塞 UI。

xsAI Transformers.js:云端/本地一键切换

VAD、ASR、Chat、TTS 一系列演示工作催生了新的子项目 xsAI Transformers.js:用 Worker 承载 WebGPU 驱动的模型推理与服务,同时保持与先前成功的 xsAI 项目 API 兼容。安装方式:

npm install xsai-transformers

其意义在于(日志 Tip 框):你可以在云端 LLM/语音服务与本地 WebGPU 模型之间用一条 if 切换,从而能够在浏览器中直接实验甚至实现简单的 RAG 与重排序系统,无需任何服务端代码或后端服务器,且 Node.js 同样受支持。

WebGPU 背景移除:内置抠图工具

Character Card 生态需要大量立绘素材,作者过去常手动寻找在线抠图方案。为了摆脱外部依赖,他基于 Xenova 的工作在 AIRI 中集成了一个 WebGPU 驱动的背景移除工具,线上体验入口为 AIRI 的devtools/background-remove

仓库中的页面实现位于 apps/stage-web/src/pages/devtools/background-removal.vue,其工程要点:

  • Worker 自动降级createBackgroundRemovalAdapter()加载时自动探测 WebGPU,不可用时回退到 WASM(background-removal.vue);
  • 主线程零推理:图片先绘制到 canvas 取ImageData,再交给adapter.processImage(imageData)在 Worker 中处理,结果putImageData回 canvas 导出 PNG(background-removal.vue);
  • 批量工作流:支持多图上传、自动处理开关、逐图/全部下载(自动追加-background-removed文件名后缀)、悬停预览,并提供进度百分比与状态徽标(pending / processing / done / error)。

Velin:用前端框架编写 LLM 提示词

引入 Character Card 后,作者发现模板变量渲染与组件复用体验不佳。由此诞生了思考:"我们能不能用 Vue 或 React 这类前端框架来编写 LLM 提示词?" 这引出了 Velin(@velin-dev/core):

  • 维护可复用的组件提示词库,供其他 Agent 或角色扮演应用、甚至角色卡使用。例如:预设中世纪奇幻世界观(魔法、巨龙),创作新角色时只需专注角色本身,外层包裹世界设定即可;
  • 支持通过if/if-else控制流注入条件提示词(例如"入夜后才注入特定提示词");
  • 借助 Vue SFC 或 React JSX 解析模板、识别 props,在编写提示词时渲染表单面板用于调试测试;
  • 将整个 lorebook 与角色卡在单个交互式页面中可视化;
  • 附带可实时渲染的 Playground(可导入任意 npm 包),并提供编程式 API,支持 Markdown(MDX 开发中,MDC 已支持)。

安装方式:

npm install @velin-dev/core

Telegram Bot:动图贴纸与提示词瘦身

日志还报告了 Telegram Bot 的更新:

  • 动图贴纸理解:为 Telegram Bot 增加了处理动画贴纸(animated stickers)的能力,底层由ffmpeg驱动,现在可以读取并理解用户发送的动画贴纸甚至视频。这与仓库中 integrations/telegram-bot 的数据模型(drizzle 迁移中可见 sticker/媒体相关的表结构演化)相互印证;
  • 提示词瘦身 80%+:系统提示词此前过于庞大,作者大幅缩减其体积,节省了80% 以上的 token 用量

UI 组件与配色更新

v0.5.0 的 UI 侧新增了三个组件,均可在 AIRI 组件库中直接查看 story:

  • Tutorial stepper:引导教程用的步骤条组件;
  • File uploadInputFile):文件上传组件(背景移除工具即复用了它);
  • Textarea:多行文本输入组件。

此外还修复了颜色相关问题,并改进了排版(Typography)。Character Card 展示层(character-card.story.vue)以 ReLU 为例提供主色、辅色、背景色、文字色、文字阴影、描述文字色、副标题文字色等主题化控制项,且纯 CSS 与 JavaScript 控制布局,无需担心 canvas 计算。

v0.5.0 里程碑回顾

日志作为 v0.5.0 的发布说明,汇总了过去数周的里程碑:

  • 达成 700 stars,新增 4+ 贡献者、72+ Discord 新成员;
  • ReLU 角色设计、建模完成;
  • Roadmap v0.5 共完成92 项任务,按类别拆解:
    • UI:加载屏与教程模块、多项 bug 修复(含加载状态与 Firefox 兼容性问题);
    • Body(身体/动作):基于语义的 Motion embedding 与 RAG(开发于私有仓库moeru-ai/motion-gen);使用 embedding provider 与 DuckDB WASM 进行向量存储与检索;
    • Inputs:修复 Discord 语音频道语音识别;
    • Outputs:实验性歌唱能力;
    • Engineering:跨项目共享 UnoCSS 配置、moeru-ai/inventory中的模型目录、跨组织包重组;
    • Assets:新角色素材(贴纸、UI 元素、VTuber 标志)、语音线选择功能、角色 "Me" 与 "ReLU" 的 Live2D 建模;
    • Community Support & Marketing:日文 README 与全面文档。

其中"DuckDB WASM 向量存储"与仓库中的 packages/duckdb-wasm、packages/drizzle-duckdb-wasm 等实验包对应;跨项目 UnoCSS 配置则体现在各应用根目录共享的 uno.config.ts 之上。

结语

这篇 DevLog 折射出 Project AIRI v0.5.0 的两条主线:一是把社区成熟的角色卡生态(CCv3)深度内化为可运行、可分享、可主题化的 Airi Card 体系(从@proj-airi/ccc协议层到airi-card运行时 Store 再到分享包格式);二是把浏览器端实时语音(VAD/ASR/TTS)与本地推理(WebGPU/WASM)从"复杂且难懂"推进到"几百行代码即可复现"的可教学状态。对于想为 AIRI 写角色卡、或想理解端侧多模态管线的开发者,本文提到的 packages/ccc、airi-card.ts、airi-card-import-export.ts 与 vad.ts 是最直接的阅读起点。

【免费下载链接】airi💖🧸 Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-sama's altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询