QwEmotion-RP-Embed-0.6B-v0.1
QwEmotion-RP is an emotion classification model trained to determine a character emotion base on a single input message. The model is trained on all 28 emotions that are compatible with SillyTaverns Character Expressions sprites.
The goal is to create a dedicated model for determining emotions that can be loaded purely in RAM and utilizing only the CPU.
To use the model as it was intended, it is recommended to run llamacpp with the arg --device none for pure CPU inference.
Disclaimer: SillyTavern's Character Expressions extension does not yet accept embedding models. For now this is just a demo that can be played around with.
Usage
Prompting Directions:
Queries: Typically you want your quries to be a single bot chat message: the one you need the character sprite decided for.
Documents: You want the documents to each be a single word, all of which are names of emotions. The following is the list of emotions this model was trained to classify, sorted in alphabetical order:
emotions: [
"admiration", "amusement", "anger", "annoyance",
"approval", "caring", "confusion", "curiosity",
"desire", "disappointment", "disapproval", "disgust",
"embarrassment", "excitement", "fear", "gratitude",
"grief", "joy", "love", "nervousness",
"neutral", "optimism", "pride", "realization",
"relief", "remorse", "sadness", "surprise"
]
Direct Usage (Sentence Transformers)
First install the Sentence Transformers library:
pip install -U sentence-transformers
Then you can load this model and run inference.
from sentence_transformers import SentenceTransformer
# Download from the 🤗 Hub
model = SentenceTransformer("sentence_transformers_model_id")
# Run inference
sentences = [
'Jerald\'s chains rattled as he twisted toward the barred window, throwing off questing hands like a dog shaking water. His glare could have cut steel. The women\'s whimpers died against the concrete walls.\n\n"Had enough." The words cracked like a whip. "Your pet died in that alley outside Huntsville, buried him myself. These girls you\'ve hollowed out? Not my problem."\n\nHe surged forward, chains biting into his wrists. The closest girl stumbled back, eyes wide. Good. Let them see.\n\n"You want leverage?" His laugh came harsh, tasting of blood. "Try again. I watched men die screaming on my table, begging for mothers who weren\'t coming. You think this performance scares me?" He spat at the window. "Find a new trick."',
'disapproval',
'excitement',
]
embeddings = model.encode(sentences)
print(embeddings.shape)
# [3, 1024]
# Get the similarity scores for the embeddings
similarities = model.similarity(embeddings, embeddings)
print(similarities)
# tensor([[1.0000, 0.4001, 0.1208],
# [0.4001, 1.0000, 0.0439],
# [0.1208, 0.0439, 1.0000]])
Out-of-Scope Use
The model is trained specifically on emotion classification, and is unlikely to offer any sort of improvement on other tasks.
Bias, Risks and Limitations
Bots that play as more than one character are likely to confuse the model. It is recommended to use a dedicated narrator bot rather than having main characters also play the role of any side charcters.
Model Details
Model Description
- Model Type: Sentence Transformer
- Base model: unsloth/Qwen3-Embedding-0.6B
- Maximum Sequence Length: 8192 tokens
- Output Dimensionality: 1024 dimensions
- Similarity Function: Cosine Similarity
- Supported Modalities: Text, Message
Model Sources
- Documentation: Sentence Transformers Documentation
- Repository: Sentence Transformers on GitHub
- Hugging Face: Sentence Transformers on Hugging Face
Full Model Architecture
SentenceTransformer(
(0): Transformer({'transformer_task': 'feature-extraction', 'modality_config': {'text': {'method': 'forward', 'method_output_name': 'last_hidden_state'}, 'message': {'method': 'forward', 'method_output_name': 'last_hidden_state', 'format': 'flat'}}, 'module_output_name': 'token_embeddings', 'max_seq_length': 8192, 'do_lower_case': False, 'architecture': 'PeftModelForFeatureExtraction'})
(1): Pooling({'embedding_dimension': 1024, 'pooling_mode': 'lasttoken', 'include_prompt': True})
(2): Normalize({})
)
Training Details
This model was finetuned with Unsloth.
based on unsloth/Qwen3-Embedding-0.6B
This is a sentence-transformers model finetuned from unsloth/Qwen3-Embedding-0.6B. It maps sentences & paragraphs to a 1024-dimensional dense vector space and can be used for retrieval.
Training Datasets
some-rp-v3 (synthetically augmented)
HF Repo: ToastyPigeon/some-rp-v3
-
Size: 499
-
Messages: ~10k
-
Messages Used: 4096
-
Columns: anchor and positive
practical-dreamer-RPGPT_PublicDomain (synthetically augmented)
HF Repo: agentlans/practical-dreamer-RPGPT_PublicDomain
-
Size: 3k
-
Messages: +128k
-
Messages Used: 8192
-
Columns: anchor and positive
emotion (minor column augmentation)
HF Repo dair-ai/emotion
-
Split:
train -
Size: 16k
-
Subset Used: 4096
-
Columns: anchor and positive
Combined dataset statistics
- Size: 16,384 training samples
- Columns: anchor and positive
- Approximate statistics based on the first 100 samples:
anchor positive type string string modality text text details min: 11 tokensmean: 110.47 tokensmax: 630 tokens min: 6 tokensmean: 7.07 tokensmax: 9 tokens - Samples:
anchor positive eyes widen with concern, her heart racing at the revelation Who might this person be, Mr. Svidrigailov? And what is the nature of the danger they face? fear raises an eyebrow, observing Pangloss's experiment I can't say I've ever seen anything quite like this before. What brings you to such an extraordinary place? curiosity Her breath hitched traitorously as he slicked against her, pleasure blooming where it shouldn't. God. The slow press, deliberate and obscene, had her nails digging half-moons into her own palms.She went still beneath him. Waiting. Pretending she wasn't counting heartbeats until they synchronized. He probably wanted gratitude, or tears, or some theatrical performance of female surrender."I suppose," she said, voice soft as dust. Not venom. The venom was reserved for Deborah Listing, CDC agent, who'd walked into this trap alone like some rookie with an anthropology degree and hero fantasies. Backup existed. She'd chosen not to use it. Always about the story, wasn't it? The great investigator who needed no partner.The anger tasted metallic, like pennies against her tongue. anger - Loss: MultipleNegativesRankingLoss with these parameters:
{ "scale": 20.0, "similarity_fct": "cos_sim", "gather_across_devices": false, "directions": [ "query_to_doc" ], "partition_mode": "joint", "hardness_mode": null, "hardness_strength": 0.0 }
Training Hyperparameters
Non-Default Hyperparameters
per_device_train_batch_size: 128gradient_accumulation_steps: 2learning_rate: 3e-05num_train_epochs: 5lr_scheduler_type: constant_with_warmupwarmup_ratio: 0.03bf16: Truebatch_sampler: no_duplicates
All Hyperparameters
overwrite_output_dir: Falsedo_predict: Falseprediction_loss_only: Trueper_device_train_batch_size: 128per_device_eval_batch_size: 8per_gpu_train_batch_size: Noneper_gpu_eval_batch_size: Nonegradient_accumulation_steps: 2eval_accumulation_steps: Nonetorch_empty_cache_steps: Nonelearning_rate: 3e-05weight_decay: 0.0adam_beta1: 0.9adam_beta2: 0.999adam_epsilon: 1e-08max_grad_norm: 1.0num_train_epochs: 5max_steps: -1lr_scheduler_type: constant_with_warmuplr_scheduler_kwargs: {}warmup_ratio: 0.03warmup_steps: 0log_level: passivelog_level_replica: warninglog_on_each_node: Truelogging_nan_inf_filter: Truesave_safetensors: Truesave_on_each_node: Falsesave_only_model: Falserestore_callback_states_from_checkpoint: Falseno_cuda: Falseuse_cpu: Falseuse_mps_device: Falseseed: 42data_seed: Nonejit_mode_eval: Falseuse_ipex: Falsebf16: Truefp16: Falsefp16_opt_level: O1half_precision_backend: autobf16_full_eval: Falsefp16_full_eval: Falsetf32: Nonelocal_rank: 0ddp_backend: Nonetpu_num_cores: Nonetpu_metrics_debug: Falsedebug: []dataloader_drop_last: Falsedataloader_num_workers: 0dataloader_prefetch_factor: Nonepast_index: -1disable_tqdm: Falseremove_unused_columns: Truelabel_names: Noneload_best_model_at_end: Falseignore_data_skip: Falsefsdp: []fsdp_min_num_params: 0fsdp_config: {'min_num_params': 0, 'xla': False, 'xla_fsdp_v2': False, 'xla_fsdp_grad_ckpt': False}fsdp_transformer_layer_cls_to_wrap: Noneaccelerator_config: {'split_batches': False, 'dispatch_batches': None, 'even_batches': True, 'use_seedable_sampler': True, 'non_blocking': False, 'gradient_accumulation_kwargs': None}parallelism_config: Nonedeepspeed: Nonelabel_smoothing_factor: 0.0optim: adamw_torch_fusedoptim_args: Noneadafactor: Falsegroup_by_length: Falselength_column_name: lengthddp_find_unused_parameters: Noneddp_bucket_cap_mb: Noneddp_broadcast_buffers: Falsedataloader_pin_memory: Truedataloader_persistent_workers: Falseskip_memory_metrics: Trueuse_legacy_prediction_loop: Falsepush_to_hub: Falseresume_from_checkpoint: Nonehub_model_id: Nonehub_strategy: every_savehub_private_repo: Nonehub_always_push: Falsehub_revision: Nonegradient_checkpointing: Falsegradient_checkpointing_kwargs: Noneinclude_inputs_for_metrics: Falseinclude_for_metrics: []eval_do_concat_batches: Truefp16_backend: autopush_to_hub_model_id: Nonepush_to_hub_organization: Nonemp_parameters:auto_find_batch_size: Falsefull_determinism: Falsetorchdynamo: Noneray_scope: lastddp_timeout: 1800torch_compile: Falsetorch_compile_backend: Nonetorch_compile_mode: Noneinclude_tokens_per_second: Falseinclude_num_input_tokens_seen: Falseneftune_noise_alpha: Noneoptim_target_modules: Nonebatch_eval_metrics: Falseeval_on_start: Falseuse_liger_kernel: Falseliger_kernel_config: Noneeval_use_gather_object: Falseaverage_tokens_across_devices: Falseprompts: Nonebatch_sampler: no_duplicatesmulti_dataset_batch_sampler: proportionalrouter_mapping: {}learning_rate_mapping: {}
Training Logs
| Epoch | Step | Training Loss |
|---|---|---|
| 0.125 | 8 | 3.0001 |
| 0.25 | 16 | 2.6569 |
| 0.375 | 24 | 2.3473 |
| 0.5 | 32 | 2.1054 |
| 0.625 | 40 | 1.8691 |
| 0.75 | 48 | 1.8289 |
| 0.875 | 56 | 1.7245 |
| 1.0 | 64 | 1.7657 |
| 1.125 | 72 | 1.5872 |
| 1.25 | 80 | 1.5302 |
| 1.375 | 88 | 1.6031 |
| 1.5 | 96 | 1.3617 |
| 1.625 | 104 | 1.4144 |
| 1.75 | 112 | 1.3664 |
| 1.875 | 120 | 1.2939 |
| 2.0 | 128 | 1.2614 |
| 2.125 | 136 | 1.332 |
| 2.25 | 144 | 1.3237 |
| 2.375 | 152 | 1.3376 |
| 2.5 | 160 | 1.2685 |
| 2.625 | 168 | 1.2464 |
| 2.75 | 176 | 1.2427 |
| 2.875 | 184 | 1.2654 |
| 3.0 | 192 | 1.2842 |
| 3.125 | 200 | 1.1585 |
| 3.25 | 208 | 1.3114 |
| 3.375 | 216 | 1.1102 |
| 3.5 | 224 | 1.1936 |
| 3.625 | 232 | 1.2455 |
| 3.75 | 240 | 1.1715 |
| 3.875 | 248 | 1.1167 |
| 4.0 | 256 | 1.1093 |
| 4.125 | 264 | 1.2329 |
| 4.25 | 272 | 1.1711 |
| 4.375 | 280 | 1.1465 |
| 4.5 | 288 | 1.0195 |
| 4.625 | 296 | 1.164 |
| 4.75 | 304 | 1.1046 |
| 4.875 | 312 | 1.0447 |
| 5.0 | 320 | 0.9356 |
Training Time
- Training: 15.0 minutes
Framework Versions
- Python: 3.11.15
- Sentence Transformers: 5.5.1
- Transformers: 4.56.2
- PyTorch: 2.10.0+cu128
- Accelerate: 1.14.0
- Datasets: 4.3.0
- Tokenizers: 0.22.2
Citation
BibTeX
Sentence Transformers
@inproceedings{reimers-2019-sentence-bert,
title = "Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks",
author = "Reimers, Nils and Gurevych, Iryna",
booktitle = "Proceedings of the 2019 Conference on Empirical Methods in Natural Language Processing",
month = "11",
year = "2019",
publisher = "Association for Computational Linguistics",
url = "https://arxiv.org/abs/1908.10084",
}
MultipleNegativesRankingLoss
@misc{oord2019representationlearningcontrastivepredictive,
title={Representation Learning with Contrastive Predictive Coding},
author={Aaron van den Oord and Yazhe Li and Oriol Vinyals},
year={2019},
eprint={1807.03748},
archivePrefix={arXiv},
primaryClass={cs.LG},
url={https://arxiv.org/abs/1807.03748},
}