Table of Contents

CharaCard

The CharaCard specification covers three formats and describes its interaction with the PNG specification. As with any community-defined specification, the precise meanings and definitions are somewhat fluid and determined only by a specific implementation. The most common implementations being SillyTavern and Character Hub. This page documents the CharaCard specification, as generally implemented by the myriad of archives and interfaces which interact with these items - not just the most popular.

CharaCard Structure

Character Cards are usually distributed as PNG images or JSON text documents. The JSON document directly contains the CharaCard JSON structure, while the PNG contains the same JSON CharaCard structure as metadata. Note that the PNG is not a polymorphic JSON/PNG hybrid file, but a fully standards-compliant (if unusually constructed) PNG, with metadata which can be decoded back into a JSON CharaCard structure.

When parsing these fields, many implementations omit unsupported fields from generated output. It is recommended to handle invalid/missing fields as gracefully as possible, while populating as many as possible when exporting/generating cards.

CCv1

Version 1 was created with TavernAI, and is long obsolete. This standard is not backwards compatible and provided as a matter of historical interest. All fields are required and utilized as part of prompt generation.

JSON Structure

Field Name Type Description
description String Overall description of setting/background of the Card.
first_mes String The initial message presented by the Card on first chat.
mes_example String Example Card messages to align Card response style.
name String Name of card and character within card.
personality String Description of Card Character nature specifically.
scenario String Specific scenario that the Card and user are engaging with.

CCv2

CCv3

CharaCard Version 3 is backwards compatible, adding only optional, additional fields.

JSON Structure

Field Name Type Description
spec String Either 'chara_card_v2' or 'chara_card_v3' depending on version.
spec_version String Either '2.0' or '3.0' depending on version.
data Object This object is described below.

Data Object

Field Name Type Description
name String Name of card and character within card.
description String Overall description of setting/background of the Card.
personality String Description of Card Character nature specifically.
scenario String Specific scenario that the Card and user are engaging with.
first_mes String The initial message presented by the Card on first chat.
mes_example String Example Card messages to align Card response style.
creator_notes String Notes about the card. Not used in prompt generation.
system_prompt String System prompt replacement. Rarely superior to the one configured by your interface.
post_history_instructions String Placed after chat messages in history. Traditionally used for jailbreak instructions, but this is no longer recommended.
alternate_greetings String Extra first_mes for users to select between when starting the chat.
character_book Object CharacterBook object, see Lorebooks below for more information.
tags String Array Short strings describing genres in the card.
creator String Name of the Card author. Not used in prompt generation.
character_version String Version provided by the Card author. Not used in prompt generation.
extensions Object Can be anything the generator populates here.
New CCv3 Fields
assets Asset Array Array of Asset objects (see below). Uncommon.
nickname String When present, nickname is the name of the character in the Card, and name can be a different name for the Card itself.
creator_notes_multilingual Object An object of <language code>:<creator notes in that language>. Uncommon.
source String Array Various URLs constituting the 'source' of the card. Uncommon.
group_only_greetings String Array Like alternate_greetings, but only shown when the card is in a group chat.
creation_date Number Unix timestamp in ms.
modification_date Number Unix timestamp in ms.

Asset object

Field Name Type
type String
uri String
name String
ext String

There are more details to be added here, especially with regards to RisuAI's divergent implementations.

Lorebook

A Lorebook is a simple, effective way to implement RAG, enhancing a Character Card without exploding token usage. Basically, when key words appear in the history, a Lorebook adds additional content to the prompt if token space is allowed.

Interfaces rarely implement all Lorebook features. It is recommended to rely on as few features as possible when writing these structures.

JSON Structure

Field Name Type Description
name String This field is often missing!
description String Not used in prompt generation.
scan_depth Number How many messages to look back into for key matches.
token_budget String Limits the amount of tokens used by the lorebook.
recursive_scanning String Controls the ability of entries to trigger other entries.
extensions Object Can be anything the generator populates here.
entries Entry Array

Entry Object

Field Name Type Description
keys String Array Text matches which trigger this entry.
content String The content which is added to the prompt when this entry is triggered.
extensions Object Can be anything the generator populates here.
enabled Boolean
insertion_order Number Sorts different entries when triggered - lower values inserted higher.
case_sensitive Boolean Controls case sensitivity when looking for key matches.
use_regex Boolean If true, keys contain valid regex which should be used for finding a match.
constant Boolean If true, always activated.
name String Name of this entry. Not used in prompt generation.
priority Number If token limits are reached, lower priority values are omitted first.
id Number/String Both Number and String values have been encountered. In either case, this is not used in prompt generation.
comment String Additional note or comment left by the author. Not used in prompt generation.
selective Boolean If true, require match from both keys and secondary_keys to trigger entry.
secondary_keys String Array Text matches referenced by selective to further restrict entry activation.
position String Either 'before_char' or 'after_char', determining position of entry relative to character definitions in prompt.

PNG

A PNG file is far more than an array of bytes forming an image. While some interfaces can retrieve data from disordered chunks or incorrectly typed metadata, the following specifications seem to define the only reliable way to build Character Cards for various interfaces.

Chunk Organization

“A PNG file consists of a PNG signature followed by a series of chunks,” (via libpng). While the precise and beautiful design of the format is beyond this page, we can consider a PNG to have the following chunks:

CharaCard metadata is required to inhabit an tEXt metadata fragment. While metadata is typically placed after the header and before the image (exiftool warns of this). However, CharaCard (and several implementations) require this tEXt metadata chunk to appear at the very end of the PNG, immediately before the End. The resulting structure should be in the following format:

tEXt Chunk Composition

The tEXt Chunk is specified here. Essentially, it has a “keyword” and “text” field. While your API may vary, this keyword field must be set to “chara” for CCv2 metadata, and “ccv3” for CCv3 metadata. If building a CCv3 card, it is wise to duplicate the structure to the “chara” key as well. The “text” is a CharaCard JSON structure that has been base64 encoded.

Implementation Sketch

libpng is one of few libraries capable of precisely constructing a PNG in this way. What follows is a sketch of how LocalTavern uses libpng to take an input PNG and set the metadata.

//prepare in_png with png_create_read_struct
//prepare out_png with png_create_write_struct
//prepare in_info and out_info with png_create_info_struct(in/out_png)
 
//configure in_png to read from file/memory
png_read_png(in_png, in_info, PNG_TRANSFORM_IDENTITY, NULL);
 
//At this point, in_png and in_info have the input file successfully prepared
//  out_png and out_info are ready for writing, but are currently blank.
 
//Build png_text structures for tEXt as follows:
//key_count could be 1 or 2 depending on chara or ccv3 and chara
png_text *text_chunks = (png_text *)malloc(sizeof(png_text) * key_count);
for (int i = 0; i < key_count; i++) {
  text_chunks[i].compression = -1;
  text_chunks[i].key = key; //pointer to key (chara/ccv3)
  text_chunks[i].text = data; //pointer to data (base64-encoded JSON)
  text_chunks[i].text_length = data_len;
  text_chunks[i].itxt_length = 0;
  text_chunks[i].lang = NULL;
  text_chunks[i].lang_key = NULL;
}
 
//modify read PNG to remove any tEXt fields.
png_free_data(in_png, in_info, PNG_FREE_TEXT, -1);
 
//At this point, write fields from read PNG into the write PNG fields
png_write_info(out_png, in_info);
 
//Write image chunks
png_bytep *row_pointers = png_get_rows(read_png, read_info);
if (!row_pointers) {
  fprintf(stderr, "No IDAT (image data) found in image\n");
  exit(1);
}
png_set_text(out_png, row_pointers);
 
//Specify the tEXt metadata
//This has to be performed after image chunks have been written to place the tEXt correctly.
png_set_text(out_png, in_info, text_chunks, key_count);
 
//Closeout written PNG
png_write_end(out_png, in_info);

Note that this is only a sketch - memory management, file I/O, and further implementation is left as an exercise for the reader.

Other CharaCard "Standards"

malfoyslastname's specification collection here. Considers implementations of SillyTavern and agnai.

kwaroran's CCv3 specification here. Elements of this seem to be extremely aspirational and/or dubious. e.g. Decorators seem to have zero adoption.