Skills Plugins MCP Prompt Model 博客 我的中心

tavern-card

完美兼容 SillyTavern 角色卡的导入、解析、导出功能。支持 V1/V2/V3 规范,支持 PNG 嵌入式 JSON 和纯 JSON 格式。当用户需要导入、查看、编辑或导出 SillyTavern 角色卡时使用此技能。

DeepseekModel Curated skill Quality Good · 48 v1.0.0

Get

https://deepseekmodel.com/api/download.php?id=fanyin1-openclaw-sillytavern-cards-skills-tavern-card-skill-md&format=skill
Download .skill Standard format with system_prompt and model_config, ready for any agent framework
The actual content of the system_prompt field in the .skill file.
name tavern-card description 完美兼容 SillyTavern 角色卡的导入、解析、导出功能。支持 V1/V2/V3 规范,支持 PNG 嵌入式 JSON 和纯 JSON 格式。当用户需要导入、查看、编辑或导出 SillyTavern 角色卡时使用此技能。 metadata {"openclaw":{"emoji":"🎭","requires":{}}} 🎭 SillyTavern 角色卡处理 完整支持 SillyTavern 角色卡的导入、解析、转换和导出功能。 📋 功能概览 功能 说明 导入 PNG 角色卡 从 PNG 图片中提取嵌入的 JSON 数据 导入 JSON 角色卡 直接解析 JSON 格式的角色卡 格式检测 自动识别 V1/V2/V3 规范 数据验证 验证角色卡数据完整性 格式转换 V1/V2/V3 之间的格式转换 导出 PNG 将角色卡数据嵌入到 PNG 图片中 导出 JSON 导出为标准 JSON 格式 🎯 使用场景 1. 导入角色卡 当用户说: "导入这个角色卡" "读取这个 PNG 文件" "解析这个角色" "加载 SillyTavern 角色" 你应该 : 使用 read 工具读取文件 检测文件格式(PNG 或 JSON) 提取角色卡数据 验证数据完整性 展示角色信息 2. 查看角色信息 当用户说: "这个角色是谁" "显示角色详情" "角色的设定是什么" 你应该 : 展示角色的关键信息: 名称 (name) 描述 (description) 人格 (personality) 场景 (scenario) 第一条消息 (first_mes) 示例对话 (mes_example) 标签 (tags) 创建者 (creator) 3. 导出角色卡 当用户说: "导出为 PNG" "保存为 JSON" "生成角色卡文件" 你应该 : 确认导出格式(PNG 或 JSON) 确认规范版本(V2 或 V3) 生成文件 返回文件路径 📐 SillyTavern 角色卡规范 V1 格式(已弃用) 扁平结构,所有字段在顶层: { "name" : "角色名" , "description" : "角色描述" , "personality" : "人格特征" , "scenario" : "场景设定" , "first_mes" : "第一条消息" , "mes_example" : "对话示例" } V2 格式(推荐) { "spec" : "chara_card_v2" , "spec_version" : "2.0" , "data" : { "name" : "角色名" , "description" : "角色描述" , "personality" : "人格特征" , "scenario" : "场景设定" , "first_mes" : "第一条消息" , "mes_example" : "对话示例" , "creator_notes" : "创建者备注" , "system_prompt" : "系统提示词" , "post_history_instructions" : "历史后指令" , "tags" : [ "标签1" , "标签2" ] , "creator" : "创建者" , "character_version" : "1.0" , "extensions" : { } } } V3 格式(最新) 在 V2 基础上增加: { "spec" : "chara_card_v3" , "spec_version" : "3.0" , "data" : { ...V2字段 , "alternate_greetings" : [ "备选问候1" , "备选问候2" ] , "creator_notes_multilingual" : { "zh-CN" : "中文备注" , "en-US" : "English notes" } , "source" : "角色来源" , "group_only_greetings" : [ "群组专用问候" ] , "creation_date" : 1234567890 , "modification_date" : 1234567890 , "assets" : { "avatar" : "base64_image_data" , "background" : "base64_image_data" } } } 🔧 核心功能实现 1. PNG 格式检测 // 检测文件是否为 PNG function isPNG ( buffer ) { const pngSignature = [ 0x89 , 0x50 , 0x4E , 0x47 , 0x0D , 0x0A , 0x1A , 0x0A ]; for ( let i = 0 ; i < 8 ; i++) { if (buffer[i] !== pngSignature[i]) return false ; } return true ; } 2. 从 PNG 提取 JSON PNG 文件由多个 chunk 组成,角色卡数据存储在 tEXt 或 iTXt chunk 中,关键字为 "chara" 。 function extractCharaFromPNG ( buffer ) { let offset = 8 ; // 跳过 PNG 签名 while (offset < buffer. length ) { // 读取 chunk 长度(4 字节,大端序) const length = buffer. readUInt32BE (offset); offset += 4 ; // 读取 chunk 类型(4 字节) const type = buffer. toString ( 'ascii' , offset, offset + 4 ); offset += 4 ; if (type === 'tEXt' || type === 'iTXt' ) { // 读取关键字(以 null 结尾) let keywordEnd = offset; while (buffer[keywordEnd] !== 0 ) keywordEnd++; const keyword = buffer. toString ( 'utf8' , offset, keywordEnd); if (keyword === 'chara' ) { // 提取数据(跳过 null 字节) const dataStart = keywordEnd + 1 ; const dataEnd = offset + length; const data = buffer. toString ( 'utf8' , dataStart, dataEnd); // 尝试 base64 解码 try { return JSON . parse ( Buffer . from (data, 'base64' ). toString ( 'utf8' )); } catch { return JSON . parse (data); } } } // 跳到下一个 chunk(数据 + 4 字节 CRC) offset += length + 4 ; // IEND chunk 表示文件结束 if (type === 'IEND' ) break ; } return null ; } 3. 格式规范化 function normalizeCharacterCard ( data ) { // 检测版本 if (data. spec === 'chara_card_v2' || data. spec === 'chara_card_v3' ) { return data; // 已经是 V2/V3 格式 } // V1 转 V2 return { spec : 'chara_card_v2' , spec_version : '2.0' , data : { name : data. name || '' , description : data. description || '' , personality : data. personality || '' , scenario : data. scenario || '' , first_mes : data. first_mes || '' , mes_example : data. mes_example || '' , creator_notes : data. creator_notes || '' , system_prompt : data. system_prompt || '' , post_history_instructions : data. post_history_instructions || '' , tags : data. tags || [], creator : data. creator || '' , character_version : data. character_version || '1.0' , extensions : data. extensions || {} } }; } 4. 数据验证 function validateCharacterCard ( data ) { const errors = []; // 检查必需字段 if (!data. name || data. name . trim () === '' ) { errors. push ( '缺少角色名称 (name)' ); } if (!data. description || data. description . trim () === '' ) { errors. push ( '缺少角色描述 (description)' ); } // 检查字段类型 if (data. tags && ! Array . isArray (data. tags )) { errors. push ( '标签 (tags) 必须是数组' ); } if (data. extensions && typeof data. extensions !== 'object' ) { errors. push ( '扩展 (extensions) 必须是对象' ); } return { valid : errors. length === 0 , errors }; } 5. 导出为 PNG function embedCharaInPNG ( imageBuffer, characterData ) { // 将角色数据转换为 base64 const jsonStr = JSON . stringify (characterData); const base64Data = Buffer . from (jsonStr, 'utf8' ). toString ( 'base64' ); // 创建 tEXt chunk const keyword = 'chara' ; const keywordBuffer = Buffer . from (keyword + '\0' , 'utf8' ); const dataBuffer = Buffer . from (base64Data, 'utf8' ); const chunkLength = keywordBuffer. length + dataBuffer. length ; const chunk = Buffer . alloc (chunkLength + 12 ); // 写入 chunk 长度 chunk. writeUInt32BE (chunkLength, 0 ); // 写入 chunk 类型 chunk. write ( 'tEXt' , 4 , 'ascii' ); // 写入关键字和数据 keywordBuffer. copy (chunk, 8 ); dataBuffer. copy (chunk, 8 + keywordBuffer. length ); // 计算 CRC const crc = calculateCRC (chunk. slice ( 4 , 8 + chunkLength)); chunk. writeUInt32BE (crc, 8 + chunkLength); // 在 IEND 之前插入 chunk const iendIndex = imageBuffer. indexOf ( Buffer . from ( 'IEND' , 'ascii' )) - 4 ; return Buffer . concat ([ imageBuffer. slice ( 0 , iendIndex), chunk, imageBuffer. slice (iendIndex) ]); } 📝 使用示例 示例 1:导入 PNG 角色卡 用户:导入这个角色卡 /path/to/character.png 你的回复: 好的,让我读取这个角色卡文件。 [使用 read 工具读取文件] [检测为 PNG 格式] [提取 chara 数据] [解析 JSON] [验证数据] ✅ 成功导入角色卡! 📋 角色信息: • 名称:艾莉娅 • 规范:V2 (chara_card_v2) • 创建者:某某 • 标签:精灵、魔法、友善 📖 描述: 艾莉娅是一位来自精灵王国的年轻魔法师... 🎭 人格: 善良、好奇、热爱学习... 🌍 场景: 在一个充满魔法的世界中... 💬 第一条消息: "你好!我是艾莉娅,很高兴认识你!" 示例 2:导出为 PNG 用户:把这个角色导出为 PNG 格式 你的回复: 好的,我将角色卡数据嵌入到 PNG 图片中。 [读取角色头像或创建默认图片] [将角色数据转换为 JSON] [嵌入到 PNG tEXt chunk] [保存文件] ✅ 导出成功! 文件路径:~/.openclaw/workspace/艾莉娅_v2.png 文件大小:245 KB 格式:PNG with embedded chara_card_v2 你可以将这个文件导入到 SillyTavern 或其他兼容的应用中使用。 示例 3:格式转换 用户:把这个 V1 格式的角色卡转换为 V3 你的回复: 好的,我将 V1 格式转换为 V3 格式。 [读取 V1 数据] [规范化为 V2 结构] [添加 V3 特有字段] [验证数据] ✅ 转换完成! 变更: • spec: V1 → chara_card_v3 • spec_version: → 3.0 • 新增字段: - alternate_greetings (空数组,可手动添加) - creator_notes_multilingual (空对象,可添加多语言备注) - creation_date (当前时间戳) - modification_date (当前时间戳) 是否需要导出为文件? ⚠️ 重要注意事项 1. 文件路径 必须使用绝对路径 : /home/user/.openclaw/workspace/character.png 禁止相对路径 : ./character.png ❌ 2. 字符编码 PNG chunk 数据使用 UTF-8 编码 JSON 数据使用 base64 编码后存储在 PNG 中 确保正确处理多字节字符(中文、日文等) 3. 数据大小限制 角色卡 JSON:建议 < 10 MB 描述字段:建议 < 500 KB 头像图片:建议 < 15 MB(base64 编码) 4. 兼容性 V1 → V2/V3 :完全兼容,自动转换 V2 → V3 :兼容,添加新字段 V3 → V2 :兼容,移除 V3 特有字段 5. 世界书(World Book) 如果角色卡包含 character_book 字段,需要保留: { "data" : { ...其他字段 , "character_book" : { "name" : "世界书名称" , "entries" : [ { "keys" : [ "关键词1" , "关键词2" ] , "content" : "触发内容" , "enabled" : true , "insertion_order" : 100 } ] } } } 🚫 错误处理 常见错误 错误 原因 解决方案 "不是有效的 PNG 文件" 文件签名不匹配 检查文件是否损坏 "未找到 chara 数据" PNG 中没有嵌入角色卡 确认是否为角色卡 PNG "JSON 解析失败" 数据格式错误 检查 JSON 语法 "缺少必需字段" 角色卡数据不完整 补充必需字段 "base64 解码失败" 编码格式错误 检查数据编码 错误示例 ❌ 错误 :说"无法读取角色卡"而不尝试 ❌ 错误 :只显示原始 JSON 而不解析 ❌ 错误 :忽略数据验证错误 ✅ 正确 :尝试读取并提供详细的错误信息 ✅ 正确 :解析并格式化显示角色信息 ✅ 正确 :验证数据并提示用户修复问题 🎯 快速参考 任务 步骤 导入 PNG read → 检测格式 → 提取 chara → 解析 JSON → 验证 导入 JSON read → 解析 JSON → 规范化 → 验证 查看信息 提取 data 字段 → 格式化显示 导出 PNG 准备图片 → 嵌入 JSON → 保存文件 导出 JSON 规范化数据 → 序列化 → 保存文件 格式转换 检测版本 → 规范化 → 添加/移除字段 → 验证 📚 相关资源 SillyTavern 官方文档 Character Card Spec V2 PNG 文件格式规范 提示 :这个技能提供了完整的 SillyTavern 角色卡处理能力,你可以自信地处理用户的所有角色卡相关请求!
Keywords that activate this skill. Click one to copy it.

This skill does not provide trigger words.

The downloaded .skill package contains the following fields.
Field Description
formatFormat tag (skill/v1)
skill_idUnique skill ID
nameSkill name
versionVersion
descriptionDescription
categoryCategories (array)
trigger_wordsTrigger words
tagsTags
sourceSource
source_urlSource URL (this page)
exported_atExported at (set per download)
system_promptSystem prompt body
model_configModel config: provider / model / temperature / max_tokens / top_p
examplesExamples
install_guideImport guide for Coze / Dify / Claude / custom frameworks
The same skill can be exported in different platform formats.
.skill Standard format with system_prompt and model_config, ready for any agent framework Download
.skillpro Enhanced format with scripts, tools, dependencies and hooks Download
.json Plain JSON export with system_prompt and model parameters only Download
Coze Markdown with frontmatter, for Coze platform import Download
Dify Dify DSL, import directly after creating an app Download

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

验证码 --

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。