Project AIRI 角色卡片实战:手写 CCv3 模板,打包导入 AIRI Card 包只靠 6 步
【免费下载链接】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
读完这篇实战指南,你能从零手写一份 AIRI Card 包——一个manifest.json加card.json的 ZIP 容器——并把它顺利导入 Project AIRI,同时看懂 Character Card V3(CCv3)各字段的填写讲究。先说一个必须记住的强警告:AIRI Card 包不是无损 CCv3 备份,标签、示例对话等元数据在导入后不会原样回来。
导入方的要求:AIRI Card 包必须长什么样
结论先行:AIRI 的导入控件只收 ZIP,且 ZIP 根目录必须同时躺着manifest.json和card.json。最小包结构如下:
my-airi-card.zip ├── manifest.json └── card.json最小manifest.json的四个值全部是写死的字面量,一个字符都不能差:
{ "format": "airi-character-card", "version": 1, "card": { "path": "card.json", "spec": "chara_card_v3" } }| 字段 | 固定取值 | 作用 | 出错时的表现 |
|---|---|---|---|
format | airi-character-card | 包格式标识,AIRI 据此认出这是自己的卡片包 | 导入失败(invalid-file) |
version | 1 | 包格式版本号 | 导入失败(invalid-file) |
card.path | card.json | 卡片 JSON 在包内的路径 | 导入失败(invalid-file) |
card.spec | chara_card_v3 | 声明卡片遵循 CCv3 规范 | 导入失败(invalid-file) |
这些校验由导入服务packages/stage-ui/src/services/airi-card-import-export.ts完成:manifest 的四个值用 valibot 的字面量严格比对,任何偏差都直接拒绝。
为什么直接上传单个 JSON 会失败
因为导入流程的第一步就是解压 ZIP 并确认根目录存在manifest.json,缺文件时抛missing-file错误;文件找到了还要先JSON.parse再逐字段过 schema,语法或字面量不对就是invalid-file。换句话说,单个 JSON 在流程的第一关就出局了——导入端根本没有"宽松模式"。
逐字段填好 card.json:CCv3 字段分组速查
card.json就是一份标准 CCv3 文档。AIRI 导入端的校验比通用 CCv3 解析器更挑剔:spec必须是字面量chara_card_v3,spec_version必须是字符串"3.0",其余data字段多数可缺省。按用途可以把字段分成五组:
- 身份组:
name、nickname、description、personality——告诉模型"这个角色是谁"。 - 交互组:
scenario、first_mes、alternate_greetings——首次见面场景与开场白。 - 元信息组:
creator_notes、character_version——给创作者自己看的备注与版本号。 - 指令组:
system_prompt、post_history_instructions——附加系统提示与历史后指令,可留空。 - 扩展组:
extensions——AIRI 运行时配置挂在extensions.airi下,单独一节讲。
{ "spec": "chara_card_v3", "spec_version": "3.0", "data": { "name": "Example Character", "nickname": "Example", "description": "A short description of who this character is.", "personality": "Curious, warm, and a little playful.", "scenario": "This character is meeting the user for the first time.", "first_mes": "Hello! Nice to meet you.", "alternate_greetings": [], "creator_notes": "", "character_version": "1.0.0", "system_prompt": "", "post_history_instructions": "", "extensions": {} } }字段速查:
| 字段 | 类型 | 作用 | 建议取值 |
|---|---|---|---|
name | string | 角色名,必填;AIRI 界面显示以它为准 | 角色正式名 |
nickname | string | 昵称,可选 | 常用称呼 |
description | string | 身份描述,最重要的人设字段 | 1–3 句,写清"她/他是谁" |
personality | string | 性格,影响说话与行为风格 | 3–5 个特质词或短句 |
scenario | string | 首次见面场景设定 | 一句话交代场合 |
first_mes | string | 开场白,会成为对话首条助手消息 | 符合人设的打招呼 |
alternate_greetings | string[] | 备选开场白,与首条合并成问候语列表 | 2–3 条短句,可为空数组 |
creator_notes | string | 创作者备注,不影响实际回复 | 创作思路、版权说明 |
character_version | string | 卡片版本号 | 1.0.0起,迭代时递增 |
system_prompt | string | 附加系统提示 | 不需要就留空串 |
post_history_instructions | string | 历史记录之后的追加指令(Jailbreak 段) | 留空串即可 |
extensions | object | 扩展配置,AIRI 运行时偏好写在airi键下 | 手写时给{} |
缺省时导入端会自动补齐默认值:description、personality、scenario、first_mes、creator_notes、system_prompt、post_history_instructions缺省为空字符串,alternate_greetings缺省为空数组,character_version缺省为1.0.0。所以上面模板里的空串与空数组就是"合法的最小形态"。
关于spec_version的兼容分级:更底层的解析器(packages/ccc/src/codec/characterCardV3.ts)会把卡片版本号与当前实现(3)比较,分成older/current/newer三级——更新版本的卡片能被解析并保留未知字段,兼容级别会传回上层用于提示用户。但手写卡片请固定写"3.0":导入端的 schema 只认这个字面量。
extensions.airi:留空还是填
extensions.airi是 AIRI 挂在卡片上的运行时配置,完整结构定义在packages/stage-ui/src/types/airiCard.ts。各子模块含义:
consciousness:provider+model,决定角色"意识"由哪家模型提供;vision:视觉理解提供方与模型;speech:语音合成的提供方、模型与音色voice_id,结构里还支持pitch、rate、ssml、language;displayModelId:指向 AIRI 显示模型库中某条记录的 ID;artistry:图像生成偏好,含provider、model、promptPrefix、spawnMode(bg/widget/inline/bg_widget)、autonomousEnabled(自主画家开关)、autonomousThreshold等;agents:各代理(如 Minecraft)的提示词与开关。
{ "extensions": { "airi": { "modules": { "consciousness": { "provider": "", "model": "" }, "vision": { "provider": "", "model": "" }, "speech": { "provider": "", "model": "", "voice_id": "" }, "artistry": { "provider": "", "model": "", "promptPrefix": "", "spawnMode": "bg", "autonomousEnabled": false } }, "agents": {} } } }💡 建议:手写模板时
extensions保持空对象{}。这些字段通常由 AIRI 卡片编辑器自动生成,为"看起来完整"而填入无效的 provider 或 model,只会让卡片带着无法解析的配置进入运行时。
导入后 AIRI 不会还给你的东西:字段白名单
这是全文最需要内化的一节。导入与导出共用同一套字段白名单(同样实现在airi-card-import-export.ts):
保留的 CCv3 字段:name、nickname、character_version、description、personality、scenario、first_mes、alternate_greetings、creator_notes、system_prompt、post_history_instructions,共 11 个;外加清洗后的extensions.airi子集——consciousness、vision、speech(只留 provider、model、voice_id)、artistry中的安全字段,以及一个空的agents。
被丢弃的内容:group_only_greetings、mes_example、creator、tags等未列入白名单的 CCv3 元数据(测试里能看到它们被归一化为空串/空数组);extensions下除airi之外的任意第三方扩展键;以及extensions.airi里的本机引用,如activeBackgroundId、artistry.workflowId、代理提示词等。官方测试(packages/stage-ui/src/services/airi-card-import-export.test.ts)专门验证了"对外部手工编辑过的包 JSON 也强制执行白名单"这一行为。
字段在 CCv3 与 AIRI 内部模型之间的映射关系:
| CCv3 字段 | AIRI 内部字段 | 说明 |
|---|---|---|
first_mes | greetings[0] | 首条问候语 |
alternate_greetings | greetings[1..] | 追加进问候语数组 |
character_version | version | 卡片版本号 |
creator_notes | notes | 创作者备注 |
system_prompt | systemPrompt | 系统提示 |
post_history_instructions | postHistoryInstructions | 历史后指令 |
导出侧(packages/ccc/src/export/json.ts)另有几个固定行为:first_mes取greetings[0],其余问候语进alternate_greetings;消息示例按<START>\n分隔符序列化进mes_example;extensions会注入默认值depth_prompt(depth 4、role 为system)、fav: false、talkativeness: 0.5。
⚠️ 如果你原卡带有世界观书、示例对话、标签、创建者信息等元数据,请在仓库外另行保留原始 CCv3 文件作为无损备份——导入 AIRI 再导出,拿回来的不会是原样。
进阶:给 AIRI 角色卡片捆绑显示模型
不带模型的卡片只有前面两个文件。要捆绑 Live2D / Spine / Tachie / VRM 显示模型时,AIRI 导出的包里会多出models/目录,manifest 里增加resources.displayModel声明:
{ "resources": { "displayModel": { "path": "models/body-model.vrm", "format": "vrm", "name": "AvatarSample_A.vrm" } } }format只接受四个取值:live2d-zip(Live2dZip)、spine-zip(SpineZip)、tachie-zip(TachieZip)、vrm(VRM);path由 AIRI 导出时统一生成,形如models/body-model.{扩展名},其中 tachie 使用复合扩展名models/body-model.tachie.zip;- 导入时 AIRI 读取该文件、注册进本机显示模型库,得到新的本地模型 ID——导入方不需要原作者机器上的模型 ID;
- 导出时的边界情况:若卡片引用的模型是预设模型(ID 以
display-model-开头)而本地恰好缺失,导出会直接报invalid-file(Missing local display model)。先补齐本地模型,再导出。
从模板到导入:6 步上手
- 填
card.json:从上面模板复制,替换name、description、personality、scenario、first_mes; - 可选字段保持留空:不用的字段维持空串/空数组,
extensions给{}; - 写
manifest.json:四个固定值——airi-character-card、1、card.json、chara_card_v3——逐字照抄,不许改; - 放入 ZIP 根目录:两个 JSON 放同一 ZIP 的根层,禁止套子文件夹;
- 打包前做 JSON 语法校验:用任意 JSON 校验器分别确认两个文件合法,语法错误会在导入端直接判
invalid-file; - 在 AIRI 中导入:打开设置 → AIRI 卡,选择或拖入 ZIP 文件,页面会依次完成 ZIP 有效性、manifest 结构、card.json 结构三道校验;捆绑了显示模型的包还会顺带注册模型文件。

导入失败?先查这张速查表
| 报错现象 | 原因 |
|---|---|
Invalid zip file | 文件不是合法 ZIP 归档(比如直接选了单个 JSON) |
Missing manifest.json | ZIP 根目录缺少 manifest,或 JSON 被放进了子文件夹 |
Missing card.json | 根目录缺少卡片文件,或card.path写错导致按错误路径查找 |
Invalid manifest.json | JSON 语法错误,或format/version/card.path/card.spec任一固定值不匹配 |
Invalid card.json | JSON 语法错误,或spec/spec_version不是chara_card_v3/3.0 |
Missing display model file | manifest 声明了resources.displayModel,但包内对应路径下没有模型文件 |
导入失败的信息会原样提示在页面上,对照这张表基本能一步定位问题出在哪一层。
交付前自检
- ZIP 根目录同时包含
manifest.json与card.json,没有套子文件夹; format、version、card.path、card.spec与spec、spec_version全部精确为airi-character-card/1/card.json/chara_card_v3/chara_card_v3/3.0;- 原始 CCv3 文件已另行留底,作为无损备份。
三个勾都打上,你的第一张 AIRI 角色卡片就离上线只差一次拖拽了。
【免费下载链接】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),仅供参考