Download textnumberlib.py from qwrt/Swedish1M: direct link, hf CLI and curl.
- Browser
- Download file 6.78 kB
-
https://huggingface.co/qwrt/Swedish1M/resolve/main/textnumberlib.py
- Command line
-
hf download hf://qwrt/Swedish1M/textnumberlib.py
-
curl -L -o textnumberlib.py https://huggingface.co/qwrt/Swedish1M/resolve/main/textnumberlib.py
6.78 kB
| from transformers import Qwen3ForCausalLM | |
| import torch | |
| import torch.nn.functional as F | |
| def bits_from_interval(min_val, max_val, numbits): | |
| df = 0.5 | |
| tal = 0 | |
| my_bits = [] | |
| for i in range(numbits): | |
| if (tal < min_val and tal + df < max_val): | |
| my_bits.append(1) | |
| tal += df | |
| else: | |
| my_bits.append(0) | |
| df /= 2 | |
| return my_bits | |
| def bits_to_tal(bits): | |
| # print(f"Antal 0:or: {bits.count(0)}") | |
| # print(f"Antal 1:or: {bits.count(1)}") | |
| tal = 0 | |
| for i in range(len(bits)): | |
| tal += bits[i] * 2 ** i | |
| return tal | |
| def bits_from_tal(tal): | |
| Bits = [] | |
| while True: | |
| rest = tal % 2 | |
| Bits.append(rest) | |
| tal -= rest | |
| tal //= 2 | |
| if (tal == 0): | |
| break | |
| return Bits | |
| def bits_to_text(start, bits, min_length, model, device, do_prints=False, write=False): | |
| Bits = bits | |
| BitID = 0 | |
| text_enc = list(start.encode()) | |
| b = [] | |
| output = "" | |
| while True: | |
| # print(text_enc) | |
| if (BitID >= len(Bits) and len(output) >= min_length): | |
| break | |
| current_intervals = [] | |
| # print(text_enc) | |
| seed = torch.tensor(text_enc, dtype=torch.long)[None].to(device) | |
| with torch.no_grad(): | |
| out = model(seed) | |
| logits = out.logits # shape: (batch, seq_len, vocab_size) | |
| probs = F.softmax(logits[0, -1], dim=-1) # sannolikheter för nästa byte | |
| topk = torch.topk(probs, k=256) # de 10 troligaste | |
| value = 0 | |
| min_val = None | |
| max_val = 0 | |
| all_bits = [] | |
| remove_bits = 0 | |
| ones = 0 | |
| for prob, idx in zip(topk.values, topk.indices): | |
| min_val = max_val | |
| max_val += prob.item() | |
| current_bits = bits_from_interval(min_val, max_val, 50) | |
| all_bits.append((current_bits, idx)) | |
| prev_ones = ones | |
| ones = 0 | |
| for bit in current_bits: | |
| if (bit == 1): | |
| ones += 1 | |
| else: | |
| break | |
| if (ones - prev_ones >= 2): | |
| remove_bits += ones - prev_ones - 1 | |
| for i in range(remove_bits): | |
| current_bits.pop(0) | |
| byte_val = idx.item() | |
| try: | |
| char = bytes([byte_val]).decode("utf8") | |
| except UnicodeDecodeError: | |
| char = f"<byte {byte_val}>" # kan hända vid multi-byte UTF-8-tecken (t.ex. å, ä, ö) | |
| # print(f"{char!r}: {min_val} to {max_val}") | |
| expected_bits = [] | |
| prediction = None | |
| if (do_prints): | |
| print("alla bitsekvenser:", all_bits[:10]) | |
| for i in range(100): | |
| if (BitID < len(Bits)): | |
| bit = Bits[BitID] | |
| else: | |
| bit = 0 | |
| BitID += 1 | |
| expected_bits.append(bit) | |
| if (do_prints): | |
| print("Hittills extraherade bits:", expected_bits) | |
| my_bits = None | |
| potential = None | |
| matches = [] | |
| for c in all_bits: | |
| other_bits = c[0] | |
| idx = c[1] | |
| if (len(other_bits) < len(expected_bits)): | |
| continue | |
| match = True | |
| for j in range(len(expected_bits)): | |
| if (expected_bits[j] != other_bits[j]): | |
| match = False | |
| break | |
| if (match): | |
| matches.append(idx) | |
| if (len(matches) == 1): | |
| prediction = matches[0] | |
| # print(expected_bits) | |
| break | |
| elif (len(matches) == 0): | |
| prediction = idx | |
| text_enc.append(prediction) | |
| b.append(prediction) | |
| if (len(b) > 4): | |
| b.pop(0) | |
| try: | |
| if (write): | |
| print(bytes(b).decode("utf-8"), end='', flush=True) | |
| output += bytes(b).decode("utf-8") | |
| b = [] | |
| except: | |
| continue | |
| return output | |
| def text_to_bits(text, model, device, do_prints=False): | |
| combined = [] | |
| text_enc = list(text.encode()) | |
| intervals = [] | |
| for i in range(1, len(text_enc)): | |
| # print("------") | |
| seed = torch.tensor(text_enc[:i], dtype=torch.long)[None].to(device) | |
| expected = torch.tensor(text_enc[i], dtype=torch.long)[None].to(device) | |
| # print(expected) | |
| with torch.no_grad(): | |
| out = model(seed) | |
| logits = out.logits # shape: (batch, seq_len, vocab_size) | |
| probs = F.softmax(logits[0, -1], dim=-1) # sannolikheter för nästa byte | |
| topk = torch.topk(probs, k=256) # de 10 troligaste | |
| if (do_prints): | |
| print(bytes([text_enc[i]]).decode("utf-8", errors="replace"), probs[expected].item()) | |
| value = 0 | |
| my_and_next = None | |
| all_bits = [] | |
| min_val = None | |
| max_val = 0 | |
| remove_bits = 0 | |
| ones = 0 | |
| for prob, idx in zip(topk.values, topk.indices): | |
| min_val = max_val | |
| max_val += prob.item() | |
| current_bits = bits_from_interval(min_val, max_val, 50) | |
| prev_ones = ones | |
| ones = 0 | |
| for bit in current_bits: | |
| if (bit == 1): | |
| ones += 1 | |
| else: | |
| break | |
| if (ones - prev_ones >= 2): | |
| remove_bits += ones - prev_ones - 1 | |
| for i in range(remove_bits): | |
| current_bits.pop(0) | |
| byte_val = idx.item() | |
| try: | |
| char = bytes([byte_val]).decode("utf8") | |
| except UnicodeDecodeError: | |
| char = f"<byte {byte_val}>" # kan hända vid multi-byte UTF-8-tecken (t.ex. å, ä, ö) | |
| # print(f"{char!r}: {min_val} to {max_val}") | |
| if (idx == expected): | |
| correct_bits = current_bits | |
| else: | |
| all_bits.append(current_bits) | |
| for k in range(1, len(correct_bits)): | |
| buffer = correct_bits[:k] | |
| any_similar = False | |
| for bits in all_bits: | |
| match = True | |
| for j in range(len(buffer)): | |
| if (buffer[j] != bits[j]): | |
| match = False | |
| if (match): | |
| any_similar = True | |
| break | |
| if (not any_similar): | |
| correct_bits = buffer | |
| for bit in correct_bits: | |
| combined.append(bit) | |
| return combined |