Tarul commited on
Commit
96b8dd1
·
verified ·
1 Parent(s): 2fe464b

Upload pxg_tiny/config.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. pxg_tiny/config.py +121 -0
pxg_tiny/config.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """PXG-Tiny shared configuration: master palette, tokenizer, classes, model dims.
2
+
3
+ Single source of truth imported by both the training pipeline and the
4
+ inference runtime. All sprites are represented as 16x16 grids of *master
5
+ palette indices* (0 = fully transparent alpha, 1..31 = opaque colors).
6
+ This makes reconstruction byte-exact by construction and keeps the
7
+ generation vocabulary tiny (32 visual symbols).
8
+ """
9
+
10
+ IMG = 16 # sprite resolution (16x16, even, inside the 8..256 schema band)
11
+ N_COLORS = 32 # visual vocabulary size: index 0 = transparent, 1..31 colors
12
+
13
+ # ---------------------------------------------------------------------------
14
+ # Master palette (index -> RGBA). Hand-crafted to span the classic
15
+ # warm_fantasy / nes / cool_sci_fi flavor families while staying <= 31 opaque
16
+ # colors so a single byte encodes any pixel.
17
+ # ---------------------------------------------------------------------------
18
+ PALETTE = {
19
+ 1: (248, 248, 248), # white / specular
20
+ 2: (217, 221, 230), # pale gray
21
+ 3: (183, 191, 204), # silver
22
+ 4: (120, 129, 142), # gray
23
+ 5: (69, 76, 87), # charcoal
24
+ 6: (23, 23, 31), # ink (outline black)
25
+ 7: (212, 61, 51), # red
26
+ 8: (140, 35, 32), # maroon
27
+ 9: (232, 137, 46), # orange / terracotta
28
+ 10: (242, 193, 46), # gold
29
+ 11: (255, 232, 107), # lemon (gold highlight)
30
+ 12: (127, 201, 79), # lime
31
+ 13: (76, 154, 68), # green mid
32
+ 14: (44, 106, 53), # forest dark
33
+ 15: (55, 179, 171), # teal
34
+ 16: (159, 223, 240), # ice / cyan highlight
35
+ 17: (79, 147, 220), # sky blue
36
+ 18: (45, 71, 127), # navy deep
37
+ 19: (124, 80, 173), # purple
38
+ 20: (180, 140, 224), # light violet
39
+ 21: (168, 123, 35), # bronze (dark gold)
40
+ 22: (242, 203, 160), # peach
41
+ 23: (221, 182, 113), # sand
42
+ 24: (244, 230, 192), # cream ivory
43
+ 25: (165, 116, 74), # tan wood
44
+ 26: (122, 78, 42), # brown mid
45
+ 27: (76, 48, 26), # dark wood
46
+ 28: (111, 117, 57), # moss olive
47
+ 29: (185, 230, 197), # mint pale (slime)
48
+ 30: (93, 114, 136), # steel blue-gray
49
+ 31: (238, 173, 174), # blush soft pink
50
+ }
51
+
52
+ # ---------------------------------------------------------------------------
53
+ # Text tokenizer (char-level with byte-fallback buckets).
54
+ # id 0 = <pad>, 1 = <bos>, 2 = <sep>, 3..6 punctuation, 7..32 a-z,
55
+ # 33..62 byte-fallback buckets (ord % 30 + 33), 63 spare.
56
+ # Deterministic, lossless round-trip on the supported charset; any other
57
+ # Unicode character folds into its byte-fallback bucket (documented lossy
58
+ # fold for exotic input, mirrors the "byte fallback" philosophy of the big
59
+ # sibling project).
60
+ # ---------------------------------------------------------------------------
61
+ CHARSET = "abcdefghijklmnopqrstuvwxyz ,:-:'"
62
+ PAD_ID, BOS_ID, SEP_ID = 0, 1, 2
63
+ _TEXT_VOCAB = 64 # total text-side embedding width
64
+ CAP_LEN = 32 # fixed padded caption slot count (incl. <pad>)
65
+ PREFIX_LEN = 8 # intent-encoder output prefix vectors fed to decoder
66
+
67
+
68
+ def encode_char(c: str) -> int:
69
+ if c == " ": return 3
70
+ if c == ",": return 4
71
+ if c == "-": return 5
72
+ if c == ":": return 6
73
+ if "a" <= c <= "z":
74
+ return 7 + ord(c) - ord("a")
75
+ if c == "'": return 39
76
+ # byte fallback bucket for anything else (digits, unicode, etc.)
77
+ fb = c.encode("utf-8", "replace")[0] # first UTF-8 byte as int
78
+ return 33 + (fb % 30)
79
+
80
+
81
+ def decode_char(i: int):
82
+ if i == 3: return " "
83
+ if i == 4: return ","
84
+ if i == 5: return "-"
85
+ if i == 6: return ":"
86
+ if 7 <= i <= 32: return chr(ord("a") + i - 7)
87
+ if i == 39: return "'"
88
+ if 33 <= i <= 38 or 40 <= i <= 62: return "?" # fallback bucket: unknown glyph
89
+ return None # control specials
90
+
91
+
92
+ def encode_caption(text: str):
93
+ """text -> list of CAP_LEN ids, left-padded slot layout:
94
+ [<pad>...]<chars>. No <bos>/<sep> needed: the prefix encoder consumes the
95
+ whole 32-slot window positionally."""
96
+ ids = [encode_char(c) for c in text.lower()][:CAP_LEN]
97
+ return [PAD_ID] * (CAP_LEN - len(ids)) + ids
98
+
99
+
100
+ def decode_caption(ids) -> str:
101
+ out = []
102
+ for i in ids:
103
+ c = decode_char(int(i))
104
+ if c is not None:
105
+ out.append(c)
106
+ return "".join(out).strip()
107
+
108
+
109
+ # ---------------------------------------------------------------------------
110
+ # Generation model geometry (extremely tiny on purpose).
111
+ # ---------------------------------------------------------------------------
112
+ D_MODEL = 96
113
+ N_LAYERS = 4
114
+ N_HEADS = 4 # 24-dim heads
115
+ FF_HIDDEN = 256 # ffn_mult ~= 2.7 (lean by design)
116
+ SEQ_VIS = IMG * IMG # 256 autoregressive visual positions
117
+ POS_TOTAL = PREFIX_LEN + SEQ_VIS # 264 learned positions
118
+
119
+ SAMPLING = {"temperature": 0.85, "top_k": 10}
120
+
121
+ APPROX_PARAMS = 483_040 # exact: encoder + 4-block decoder + heads