Luturtun's picture
Implemented and deployed encoder + decoder approac
1f6639e
Raw
History Blame Contribute Delete
1.75 kB
"""Emoji vocabulary: one token per complete emoji.
Every emoji in the Unicode standard is a single atomic token — single codepoints,
ZWJ sequences, flags, skin-tone variants, everything. The vocabulary is derived
from the `emoji` library's EMOJI_DATA so it covers all ~5,225 valid emoji without
being restricted to what appears in training data.
Special tokens: PAD=0, BOS=1, EOS=2.
Emoji tokens: indices 3..VOCAB_SIZE-1.
"""
import emoji as _emoji_lib
PAD_ID = 0
BOS_ID = 1
EOS_ID = 2
_SPECIAL = 3
# All complete emoji strings, sorted for determinism across runs
ALL_EMOJI: list[str] = sorted(_emoji_lib.EMOJI_DATA.keys())
_emoji_to_id: dict[str, int] = {em: i + _SPECIAL for i, em in enumerate(ALL_EMOJI)}
_id_to_emoji: dict[int, str] = {i + _SPECIAL: em for i, em in enumerate(ALL_EMOJI)}
VOCAB_SIZE: int = _SPECIAL + len(ALL_EMOJI)
def get_description(emoji_str: str) -> str:
"""Return a clean English description for an emoji, e.g. '🍕' → 'pizza'."""
name = _emoji_lib.EMOJI_DATA.get(emoji_str, {}).get("en", "")
return name.strip(":").replace("_", " ").strip()
def encode(text: str) -> list[int]:
"""Encode an emoji string → [BOS, emoji_ids..., EOS].
Splits text into individual complete emoji using the emoji library.
Non-emoji characters and unknown sequences are silently skipped.
"""
tokens = [
t.chars
for t in _emoji_lib.analyze(text, non_emoji=False)
if _emoji_lib.is_emoji(t.chars) and t.chars in _emoji_to_id
]
return [BOS_ID] + [_emoji_to_id[em] for em in tokens] + [EOS_ID]
def decode(ids: list[int]) -> str:
"""Decode token IDs → emoji string, stripping BOS/EOS/PAD."""
return "".join(_id_to_emoji[i] for i in ids if i in _id_to_emoji)