glitchlings 0.1.1__py3-none-any.whl → 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
__init__.py DELETED
@@ -1,73 +0,0 @@
1
- from .zoo import (
2
- typogre,
3
- mim1c,
4
- jargoyle,
5
- redactyl,
6
- reduple,
7
- rushmore,
8
- scannequin,
9
- Glitchling,
10
- Gaggle,
11
- summon,
12
- )
13
- from .util import SAMPLE_TEXT
14
-
15
-
16
- __all__ = [
17
- "typogre",
18
- "mim1c",
19
- "jargoyle",
20
- "reduple",
21
- "rushmore",
22
- "redactyl",
23
- "scannequin",
24
- "summon",
25
- "Glitchling",
26
- "Gaggle",
27
- "SAMPLE_TEXT",
28
- ]
29
-
30
-
31
- if __name__ == "__main__":
32
- # Example usage
33
- import verifiers as vf
34
- from openai import OpenAI
35
- from dlc import prime as gl
36
- from typing import cast
37
-
38
- openai = OpenAI()
39
-
40
- # redactyl.set_param("redaction_rate", 0.5)
41
- # jargoyle.set_param("replacement_rate", 0.25)
42
-
43
- # gaggle = summon(["reduple", "mim1c", "typogre", jargoyle, "rushmore", redactyl])
44
- # corrupted = gaggle(SAMPLE_TEXT)
45
- # print(SAMPLE_TEXT, end="\n\n")
46
- # print(gaggle.pretty_diff(SAMPLE_TEXT), end="\n\n")
47
- # print(corrupted)
48
-
49
- # env = load_environment("alphabet-sort")
50
- # x = env.evaluate(client=openai, model="gpt-4.1-nano", num_examples=100)
51
- # dx = env.make_dataset(x).to_dict()
52
- # print(sum(dx["weighted_reward"]))
53
-
54
- bare_env = vf.load_environment("alphabet-sort")
55
- x = bare_env.evaluate(client=openai, model="gpt-4.1-nano", num_examples=10)
56
- dx = cast(dict[str, list[float]], bare_env.make_dataset(x).to_dict()) # type: ignore
57
- original = 100 * sum(dx["reward"]) / max(1, len(dx["reward"]))
58
-
59
- easy_env = gl.load_environment("alphabet-sort")
60
- y = easy_env.evaluate(client=openai, model="gpt-4.1-nano", num_examples=10)
61
- dy = cast(dict[str, list[float]], easy_env.make_dataset(y).to_dict()) # type: ignore
62
- easy = 100 * sum(dy["reward"]) / max(1, len(dy["reward"]))
63
- easy_drop = 100 * (original - easy) / original
64
-
65
- crazy_env = gl.load_environment("alphabet-sort", CR=gl.CR.Four)
66
- z = crazy_env.evaluate(client=openai, model="gpt-4.1-nano", num_examples=10)
67
- dz = cast(dict[str, list[float]], crazy_env.make_dataset(z).to_dict()) # type: ignore
68
- crazy = 100 * sum(dz["reward"]) / max(1, len(dz["reward"]))
69
- crazy_drop = 100 * (original - crazy) / original
70
-
71
- print(f"Base Environment: {original:.1f}%")
72
- print(f"Glitchlings (CR 1): {easy:.1f}% ({easy_drop:.1f}% drop)")
73
- print(f"Glitchlings (CR 4): {crazy:.1f}% ({crazy_drop:.1f}% drop)")
@@ -1,26 +0,0 @@
1
- ./.gitignore,sha256=oIxsd1LRy7y7yqq5k5JCrFKW4p6HlQd14lFUSLi-Qx8,144
2
- ./LICENSE,sha256=EFEP1evBfHaxsMTBjxm0sZVRp2wct8QLvHE1saII5FI,11538
3
- ./MONSTER_MANUAL.md,sha256=vdoVnUl-Zdl3gH6E51fUGlSnhxdxxIbIXVNorReJAng,9344
4
- ./PKG-INFO,sha256=2VrY4qI-J6MM_3VXAcHI0gC-8eoRYerXEj7o28XfBpc,24182
5
- ./README.md,sha256=hdQzNbHjygjeNsikdDaLRncN3H7qN9qgWhjnGWBS5WE,10121
6
- ./__init__.py,sha256=dOvJSFqrFUQvYNUHne5CmSUUwzME8rdyL-lXGNWKoL0,2365
7
- ./main.py,sha256=HZveNbsuHiHJFGhB31I_u4EK2aI7KOCevcI2ZP9u5Lw,89
8
- ./pyproject.toml,sha256=fi33wc0qVZrK_UXQv_uOXykOnGn_xBWI-kYuo8KyiZI,1675
9
- ./.github/workflows/publish.yml,sha256=0N02QrLlOaj3y9PGfl3Ns9wVgP-EaCizmcospjGGMco,1118
10
- ./dlc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- ./dlc/prime.py,sha256=FunhqcEXGUMm49WadYtWbH7MrMcYuqcmk-LPEZEEZeI,1382
12
- ./util/__init__.py,sha256=C7VPB225Uro-9MzpMpofIyTH86gYUpiYbGDxk_Jtvaw,2190
13
- ./zoo/__init__.py,sha256=vOfvSfvAZegCrJ_xEyQBfDQLVXLz6OXFepA1cmT9X58,1218
14
- ./zoo/core.py,sha256=jBigckZRNOKhg4Bnki0iTfgp8z6yI43K5SkqMBcChv4,4776
15
- ./zoo/jargoyle.py,sha256=CbhprejTP54KEaI9tWJqG-mKxCOcqKgtJvuuLb_zCZM,2972
16
- ./zoo/mim1c.py,sha256=i0K2NjeM_pLVXOmTTUPelSIMhyTRwT5zMwXJ5XFLip4,2118
17
- ./zoo/redactyl.py,sha256=V9-4XNLKzAQhqFqZ8pE6zFJatVKYdxOvBS3E8JVtoqo,2211
18
- ./zoo/reduple.py,sha256=ggrGshp-Zx-O4xA_bhbMTWp9d4DEarYV6pTftjzLvHM,1711
19
- ./zoo/rushmore.py,sha256=r67-qiNS194gXSz1Ep2TrojlOJd4O362njOnRAJFyTo,1612
20
- ./zoo/scannequin.py,sha256=-dcykPGWFrnF5nDyHQLfW9Olj-uxV1e-6DVDXgdN8rg,3765
21
- ./zoo/typogre.py,sha256=kw_lvD5a6JjYU9mwrOyicmQz3HuqxtvUVAdrGf32WrA,7872
22
- glitchlings-0.1.1.dist-info/METADATA,sha256=2VrY4qI-J6MM_3VXAcHI0gC-8eoRYerXEj7o28XfBpc,24182
23
- glitchlings-0.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
24
- glitchlings-0.1.1.dist-info/entry_points.txt,sha256=kGOwuAsjFDLtztLisaXtOouq9wFVMOJg5FzaAkg-Hto,54
25
- glitchlings-0.1.1.dist-info/licenses/LICENSE,sha256=EFEP1evBfHaxsMTBjxm0sZVRp2wct8QLvHE1saII5FI,11538
26
- glitchlings-0.1.1.dist-info/RECORD,,
main.py DELETED
@@ -1,6 +0,0 @@
1
- def main():
2
- print("Hello from glitchlings!")
3
-
4
-
5
- if __name__ == "__main__":
6
- main()
pyproject.toml DELETED
@@ -1,79 +0,0 @@
1
- [project]
2
- name = "glitchlings"
3
- version = "0.1.1"
4
- description = "Monsters for your language games."
5
- readme = "README.md"
6
- requires-python = ">=3.12"
7
-
8
- dependencies = [
9
- "confusable-homoglyphs>=3.3.1",
10
- "datasets>=4.0.0",
11
- "jellyfish>=1.2.0",
12
- ]
13
-
14
- authors = [
15
- { name = "osoleve" }
16
- ]
17
-
18
- keywords = ["nlp", "text", "adversarial", "data", "evaluation", "glitch"]
19
-
20
- classifiers = [
21
- "Development Status :: 3 - Alpha",
22
- "Intended Audience :: Developers",
23
- "License :: OSI Approved :: Apache Software License",
24
- "Programming Language :: Python",
25
- "Programming Language :: Python :: 3",
26
- "Programming Language :: Python :: 3.12",
27
- "Operating System :: OS Independent",
28
- "Topic :: Scientific/Engineering :: Artificial Intelligence",
29
- "Topic :: Software Development :: Testing",
30
- ]
31
-
32
- [project.license]
33
- file = "LICENSE"
34
-
35
- [project.urls]
36
- Homepage = "https://github.com/osoleve/glitchlings"
37
- Repository = "https://github.com/osoleve/glitchlings.git"
38
- Issues = "https://github.com/osoleve/glitchlings/issues"
39
- Changelog = "https://github.com/osoleve/glitchlings/releases"
40
-
41
- [project.scripts]
42
- glitchlings = "glitchlings.main:main"
43
-
44
- [project.optional-dependencies]
45
- jargoyle = [
46
- "nltk>=3.9.1",
47
- ]
48
- prime = [
49
- "verifiers>=0.1.3.post0",
50
- ]
51
- dev = [
52
- "pytest>=8.0.0",
53
- ]
54
-
55
- [build-system]
56
- requires = ["hatchling>=1.18"]
57
- build-backend = "hatchling.build"
58
-
59
- [tool.hatch.build]
60
- exclude = [
61
- "**/__pycache__/**",
62
- ".git/**",
63
- ".venv/**",
64
- ]
65
-
66
- [tool.hatch.build.targets.sdist]
67
- exclude = [
68
- "**/__pycache__/**",
69
- ".git/**",
70
- ".venv/**",
71
- ]
72
-
73
- [tool.hatch.build.targets.wheel]
74
- packages = ["."]
75
- exclude = [
76
- "tests/**",
77
- "tests",
78
- "**/__pycache__/**",
79
- ]
util/__init__.py DELETED
@@ -1,73 +0,0 @@
1
- import difflib
2
-
3
- SAMPLE_TEXT = "One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked."
4
-
5
-
6
- def string_diffs(a: str, b: str):
7
- """
8
- Compare two strings using SequenceMatcher and return
9
- grouped adjacent opcodes (excluding 'equal' tags).
10
-
11
- Each element is a tuple: (tag, a_text, b_text).
12
- """
13
- sm = difflib.SequenceMatcher(None, a, b)
14
- ops = []
15
- buffer = []
16
-
17
- for tag, i1, i2, j1, j2 in sm.get_opcodes():
18
- if tag == "equal":
19
- # flush any buffered operations before skipping
20
- if buffer:
21
- ops.append(buffer)
22
- buffer = []
23
- continue
24
-
25
- # append operation to buffer
26
- buffer.append((tag, a[i1:i2], b[j1:j2]))
27
-
28
- # flush trailing buffer
29
- if buffer:
30
- ops.append(buffer)
31
-
32
- return ops
33
-
34
-
35
- _KEYNEIGHBORS = {
36
- "CURATOR_QWERTY": {
37
- "a": [*"qwsz"],
38
- "b": [*"vghn "],
39
- "c": [*"xdfv "],
40
- "d": [*"serfcx"],
41
- "e": [*"wsdrf34"],
42
- "f": [*"drtgvc"],
43
- "g": [*"ftyhbv"],
44
- "h": [*"gyujnb"],
45
- "i": [*"ujko89"],
46
- "j": [*"huikmn"],
47
- "k": [*"jilom,"],
48
- "l": [*"kop;.,"],
49
- "m": [*"njk, "],
50
- "n": [*"bhjm "],
51
- "o": [*"iklp90"],
52
- "p": [*"o0-[;l"],
53
- "q": [*"was 12"],
54
- "r": [*"edft45"],
55
- "s": [*"awedxz"],
56
- "t": [*"r56ygf"],
57
- "u": [*"y78ijh"],
58
- "v": [*"cfgb "],
59
- "w": [*"q23esa"],
60
- "x": [*"zsdc "],
61
- "y": [*"t67uhg"],
62
- "z": [*"asx"],
63
- }
64
- }
65
-
66
-
67
- class KeyNeighbors:
68
- def __init__(self):
69
- for layout_name, layout in _KEYNEIGHBORS.items():
70
- setattr(self, layout_name, layout)
71
-
72
-
73
- KEYNEIGHBORS = KeyNeighbors()
zoo/jargoyle.py DELETED
@@ -1,89 +0,0 @@
1
- import random
2
- from typing import Literal, Any, cast
3
- import nltk
4
- import re
5
- from nltk.corpus import wordnet as wn
6
- from .core import Glitchling, AttackWave
7
-
8
- nltk.download("wordnet", quiet=True)
9
-
10
-
11
- def substitute_random_synonyms(
12
- text: str,
13
- replacement_rate: float = 0.1,
14
- part_of_speech: Literal["n", "v", "a", "r"] = wn.NOUN,
15
- seed: int | None = None,
16
- rng: random.Random | None = None,
17
- ) -> str:
18
- """Replace words with random WordNet synonyms.
19
-
20
- Parameters
21
- - text: Input text.
22
- - replacement_rate: Max proportion of candidate words to replace (default 0.1).
23
- - part_of_speech: WordNet POS to target. One of wn.NOUN (default), wn.VERB, wn.ADJ, wn.ADV.
24
- - rng: Optional RNG instance used for deterministic sampling.
25
- - seed: Optional seed if `rng` not provided.
26
-
27
- Determinism
28
- - Candidates collected in left-to-right order; no set() reordering.
29
- - Replacement positions chosen via rng.sample.
30
- - Synonyms sorted before rng.choice to fix ordering.
31
- - Only first synset is used for stability.
32
- """
33
- if rng is None and seed is not None:
34
- rng = random.Random(seed)
35
- elif rng is None:
36
- rng = random.Random()
37
-
38
- # Split but keep whitespace separators so we can rebuild easily
39
- tokens = re.split(r"(\s+)", text)
40
-
41
- # Collect indices of candidate tokens (even positions 0,2,.. are words given our split design)
42
- candidate_indices: list[int] = []
43
- for idx, tok in enumerate(tokens):
44
- if idx % 2 == 0 and tok and not tok.isspace():
45
- if wn.synsets(tok, pos=part_of_speech):
46
- candidate_indices.append(idx)
47
-
48
- if not candidate_indices:
49
- return text
50
-
51
- max_replacements = int(len(candidate_indices) * replacement_rate)
52
- if max_replacements <= 0:
53
- return text
54
-
55
- # Choose which positions to replace deterministically via rng.sample
56
- replace_positions = rng.sample(candidate_indices, k=max_replacements)
57
- # Process in ascending order to avoid affecting later indices
58
- replace_positions.sort()
59
-
60
- for pos in replace_positions:
61
- word = tokens[pos]
62
- synsets = wn.synsets(word, pos=part_of_speech)
63
- if not synsets:
64
- continue
65
- synset0: Any = synsets[0]
66
- lemmas_list = [lemma.name() for lemma in cast(Any, synset0).lemmas()]
67
- if not lemmas_list:
68
- continue
69
- # Normalize & dedupe deterministically
70
- synonyms = sorted(
71
- {
72
- lemma_str.replace("_", " ")
73
- for lemma_str in lemmas_list
74
- if lemma_str.lower() != word.lower()
75
- }
76
- )
77
- if not synonyms:
78
- continue
79
- replacement = rng.choice(synonyms)
80
- tokens[pos] = replacement
81
-
82
- return "".join(tokens)
83
-
84
-
85
- jargoyle = Glitchling(
86
- name="Jargoyle",
87
- corruption_function=substitute_random_synonyms,
88
- scope=AttackWave.WORD,
89
- )
File without changes