bead 0.1.0__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.
Files changed (231) hide show
  1. bead/__init__.py +11 -0
  2. bead/__main__.py +11 -0
  3. bead/active_learning/__init__.py +15 -0
  4. bead/active_learning/config.py +231 -0
  5. bead/active_learning/loop.py +566 -0
  6. bead/active_learning/models/__init__.py +24 -0
  7. bead/active_learning/models/base.py +852 -0
  8. bead/active_learning/models/binary.py +910 -0
  9. bead/active_learning/models/categorical.py +943 -0
  10. bead/active_learning/models/cloze.py +862 -0
  11. bead/active_learning/models/forced_choice.py +956 -0
  12. bead/active_learning/models/free_text.py +773 -0
  13. bead/active_learning/models/lora.py +365 -0
  14. bead/active_learning/models/magnitude.py +835 -0
  15. bead/active_learning/models/multi_select.py +795 -0
  16. bead/active_learning/models/ordinal_scale.py +811 -0
  17. bead/active_learning/models/peft_adapter.py +155 -0
  18. bead/active_learning/models/random_effects.py +639 -0
  19. bead/active_learning/selection.py +354 -0
  20. bead/active_learning/strategies.py +391 -0
  21. bead/active_learning/trainers/__init__.py +26 -0
  22. bead/active_learning/trainers/base.py +210 -0
  23. bead/active_learning/trainers/data_collator.py +172 -0
  24. bead/active_learning/trainers/dataset_utils.py +261 -0
  25. bead/active_learning/trainers/huggingface.py +304 -0
  26. bead/active_learning/trainers/lightning.py +324 -0
  27. bead/active_learning/trainers/metrics.py +424 -0
  28. bead/active_learning/trainers/mixed_effects.py +551 -0
  29. bead/active_learning/trainers/model_wrapper.py +509 -0
  30. bead/active_learning/trainers/registry.py +104 -0
  31. bead/adapters/__init__.py +11 -0
  32. bead/adapters/huggingface.py +61 -0
  33. bead/behavioral/__init__.py +116 -0
  34. bead/behavioral/analytics.py +646 -0
  35. bead/behavioral/extraction.py +343 -0
  36. bead/behavioral/merging.py +343 -0
  37. bead/cli/__init__.py +11 -0
  38. bead/cli/active_learning.py +513 -0
  39. bead/cli/active_learning_commands.py +779 -0
  40. bead/cli/completion.py +359 -0
  41. bead/cli/config.py +624 -0
  42. bead/cli/constraint_builders.py +286 -0
  43. bead/cli/deployment.py +859 -0
  44. bead/cli/deployment_trials.py +493 -0
  45. bead/cli/deployment_ui.py +332 -0
  46. bead/cli/display.py +378 -0
  47. bead/cli/items.py +960 -0
  48. bead/cli/items_factories.py +776 -0
  49. bead/cli/list_constraints.py +714 -0
  50. bead/cli/lists.py +490 -0
  51. bead/cli/main.py +430 -0
  52. bead/cli/models.py +877 -0
  53. bead/cli/resource_loaders.py +621 -0
  54. bead/cli/resources.py +1036 -0
  55. bead/cli/shell.py +356 -0
  56. bead/cli/simulate.py +840 -0
  57. bead/cli/templates.py +1158 -0
  58. bead/cli/training.py +1080 -0
  59. bead/cli/utils.py +614 -0
  60. bead/cli/workflow.py +1273 -0
  61. bead/config/__init__.py +68 -0
  62. bead/config/active_learning.py +1009 -0
  63. bead/config/config.py +192 -0
  64. bead/config/defaults.py +118 -0
  65. bead/config/deployment.py +217 -0
  66. bead/config/env.py +147 -0
  67. bead/config/item.py +45 -0
  68. bead/config/list.py +193 -0
  69. bead/config/loader.py +149 -0
  70. bead/config/logging.py +42 -0
  71. bead/config/model.py +49 -0
  72. bead/config/paths.py +46 -0
  73. bead/config/profiles.py +320 -0
  74. bead/config/resources.py +47 -0
  75. bead/config/serialization.py +210 -0
  76. bead/config/simulation.py +206 -0
  77. bead/config/template.py +238 -0
  78. bead/config/validation.py +267 -0
  79. bead/data/__init__.py +65 -0
  80. bead/data/base.py +87 -0
  81. bead/data/identifiers.py +97 -0
  82. bead/data/language_codes.py +61 -0
  83. bead/data/metadata.py +270 -0
  84. bead/data/range.py +123 -0
  85. bead/data/repository.py +358 -0
  86. bead/data/serialization.py +249 -0
  87. bead/data/timestamps.py +89 -0
  88. bead/data/validation.py +349 -0
  89. bead/data_collection/__init__.py +11 -0
  90. bead/data_collection/jatos.py +223 -0
  91. bead/data_collection/merger.py +154 -0
  92. bead/data_collection/prolific.py +198 -0
  93. bead/deployment/__init__.py +5 -0
  94. bead/deployment/distribution.py +402 -0
  95. bead/deployment/jatos/__init__.py +1 -0
  96. bead/deployment/jatos/api.py +200 -0
  97. bead/deployment/jatos/exporter.py +210 -0
  98. bead/deployment/jspsych/__init__.py +9 -0
  99. bead/deployment/jspsych/biome.json +44 -0
  100. bead/deployment/jspsych/config.py +411 -0
  101. bead/deployment/jspsych/generator.py +598 -0
  102. bead/deployment/jspsych/package.json +51 -0
  103. bead/deployment/jspsych/pnpm-lock.yaml +2141 -0
  104. bead/deployment/jspsych/randomizer.py +299 -0
  105. bead/deployment/jspsych/src/lib/list-distributor.test.ts +327 -0
  106. bead/deployment/jspsych/src/lib/list-distributor.ts +1282 -0
  107. bead/deployment/jspsych/src/lib/randomizer.test.ts +232 -0
  108. bead/deployment/jspsych/src/lib/randomizer.ts +367 -0
  109. bead/deployment/jspsych/src/plugins/cloze-dropdown.ts +252 -0
  110. bead/deployment/jspsych/src/plugins/forced-choice.ts +265 -0
  111. bead/deployment/jspsych/src/plugins/plugins.test.ts +141 -0
  112. bead/deployment/jspsych/src/plugins/rating.ts +248 -0
  113. bead/deployment/jspsych/src/slopit/index.ts +9 -0
  114. bead/deployment/jspsych/src/types/jatos.d.ts +256 -0
  115. bead/deployment/jspsych/src/types/jspsych.d.ts +228 -0
  116. bead/deployment/jspsych/templates/experiment.css +1 -0
  117. bead/deployment/jspsych/templates/experiment.js.template +289 -0
  118. bead/deployment/jspsych/templates/index.html +51 -0
  119. bead/deployment/jspsych/templates/randomizer.js +241 -0
  120. bead/deployment/jspsych/templates/randomizer.js.template +313 -0
  121. bead/deployment/jspsych/trials.py +723 -0
  122. bead/deployment/jspsych/tsconfig.json +23 -0
  123. bead/deployment/jspsych/tsup.config.ts +30 -0
  124. bead/deployment/jspsych/ui/__init__.py +1 -0
  125. bead/deployment/jspsych/ui/components.py +383 -0
  126. bead/deployment/jspsych/ui/styles.py +411 -0
  127. bead/dsl/__init__.py +80 -0
  128. bead/dsl/ast.py +168 -0
  129. bead/dsl/context.py +178 -0
  130. bead/dsl/errors.py +71 -0
  131. bead/dsl/evaluator.py +570 -0
  132. bead/dsl/grammar.lark +81 -0
  133. bead/dsl/parser.py +231 -0
  134. bead/dsl/stdlib.py +929 -0
  135. bead/evaluation/__init__.py +13 -0
  136. bead/evaluation/convergence.py +485 -0
  137. bead/evaluation/interannotator.py +398 -0
  138. bead/items/__init__.py +40 -0
  139. bead/items/adapters/__init__.py +70 -0
  140. bead/items/adapters/anthropic.py +224 -0
  141. bead/items/adapters/api_utils.py +167 -0
  142. bead/items/adapters/base.py +216 -0
  143. bead/items/adapters/google.py +259 -0
  144. bead/items/adapters/huggingface.py +1074 -0
  145. bead/items/adapters/openai.py +323 -0
  146. bead/items/adapters/registry.py +202 -0
  147. bead/items/adapters/sentence_transformers.py +224 -0
  148. bead/items/adapters/togetherai.py +309 -0
  149. bead/items/binary.py +515 -0
  150. bead/items/cache.py +558 -0
  151. bead/items/categorical.py +593 -0
  152. bead/items/cloze.py +757 -0
  153. bead/items/constructor.py +784 -0
  154. bead/items/forced_choice.py +413 -0
  155. bead/items/free_text.py +681 -0
  156. bead/items/generation.py +432 -0
  157. bead/items/item.py +396 -0
  158. bead/items/item_template.py +787 -0
  159. bead/items/magnitude.py +573 -0
  160. bead/items/multi_select.py +621 -0
  161. bead/items/ordinal_scale.py +569 -0
  162. bead/items/scoring.py +448 -0
  163. bead/items/validation.py +723 -0
  164. bead/lists/__init__.py +30 -0
  165. bead/lists/balancer.py +263 -0
  166. bead/lists/constraints.py +1067 -0
  167. bead/lists/experiment_list.py +286 -0
  168. bead/lists/list_collection.py +378 -0
  169. bead/lists/partitioner.py +1141 -0
  170. bead/lists/stratification.py +254 -0
  171. bead/participants/__init__.py +73 -0
  172. bead/participants/collection.py +699 -0
  173. bead/participants/merging.py +312 -0
  174. bead/participants/metadata_spec.py +491 -0
  175. bead/participants/models.py +276 -0
  176. bead/resources/__init__.py +29 -0
  177. bead/resources/adapters/__init__.py +19 -0
  178. bead/resources/adapters/base.py +104 -0
  179. bead/resources/adapters/cache.py +128 -0
  180. bead/resources/adapters/glazing.py +508 -0
  181. bead/resources/adapters/registry.py +117 -0
  182. bead/resources/adapters/unimorph.py +796 -0
  183. bead/resources/classification.py +856 -0
  184. bead/resources/constraint_builders.py +329 -0
  185. bead/resources/constraints.py +165 -0
  186. bead/resources/lexical_item.py +223 -0
  187. bead/resources/lexicon.py +744 -0
  188. bead/resources/loaders.py +209 -0
  189. bead/resources/template.py +441 -0
  190. bead/resources/template_collection.py +707 -0
  191. bead/resources/template_generation.py +349 -0
  192. bead/simulation/__init__.py +29 -0
  193. bead/simulation/annotators/__init__.py +15 -0
  194. bead/simulation/annotators/base.py +175 -0
  195. bead/simulation/annotators/distance_based.py +135 -0
  196. bead/simulation/annotators/lm_based.py +114 -0
  197. bead/simulation/annotators/oracle.py +182 -0
  198. bead/simulation/annotators/random.py +181 -0
  199. bead/simulation/dsl_extension/__init__.py +3 -0
  200. bead/simulation/noise_models/__init__.py +13 -0
  201. bead/simulation/noise_models/base.py +42 -0
  202. bead/simulation/noise_models/random_noise.py +82 -0
  203. bead/simulation/noise_models/systematic.py +132 -0
  204. bead/simulation/noise_models/temperature.py +86 -0
  205. bead/simulation/runner.py +144 -0
  206. bead/simulation/strategies/__init__.py +23 -0
  207. bead/simulation/strategies/base.py +123 -0
  208. bead/simulation/strategies/binary.py +103 -0
  209. bead/simulation/strategies/categorical.py +123 -0
  210. bead/simulation/strategies/cloze.py +224 -0
  211. bead/simulation/strategies/forced_choice.py +127 -0
  212. bead/simulation/strategies/free_text.py +105 -0
  213. bead/simulation/strategies/magnitude.py +116 -0
  214. bead/simulation/strategies/multi_select.py +129 -0
  215. bead/simulation/strategies/ordinal_scale.py +131 -0
  216. bead/templates/__init__.py +27 -0
  217. bead/templates/adapters/__init__.py +17 -0
  218. bead/templates/adapters/base.py +128 -0
  219. bead/templates/adapters/cache.py +178 -0
  220. bead/templates/adapters/huggingface.py +312 -0
  221. bead/templates/combinatorics.py +103 -0
  222. bead/templates/filler.py +605 -0
  223. bead/templates/renderers.py +177 -0
  224. bead/templates/resolver.py +178 -0
  225. bead/templates/strategies.py +1806 -0
  226. bead/templates/streaming.py +195 -0
  227. bead-0.1.0.dist-info/METADATA +212 -0
  228. bead-0.1.0.dist-info/RECORD +231 -0
  229. bead-0.1.0.dist-info/WHEEL +4 -0
  230. bead-0.1.0.dist-info/entry_points.txt +2 -0
  231. bead-0.1.0.dist-info/licenses/LICENSE +21 -0
bead/dsl/context.py ADDED
@@ -0,0 +1,178 @@
1
+ """Evaluation context for constraint DSL.
2
+
3
+ This module provides the EvaluationContext class that manages variable
4
+ bindings and function lookups during constraint evaluation.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from collections.abc import Callable
10
+ from typing import Any
11
+
12
+ from bead.dsl.errors import EvaluationError
13
+
14
+
15
+ class EvaluationContext:
16
+ """Evaluation context for constraint expressions.
17
+
18
+ The context provides:
19
+ - Variable bindings (e.g., item attributes)
20
+ - Function registry (built-in and custom functions)
21
+ - Parent context chain for scoping
22
+
23
+ Parameters
24
+ ----------
25
+ parent : EvaluationContext | None
26
+ Parent context for variable/function lookup chain.
27
+
28
+ Examples
29
+ --------
30
+ >>> ctx = EvaluationContext()
31
+ >>> ctx.set_variable("x", 42)
32
+ >>> ctx.get_variable("x")
33
+ 42
34
+ >>> ctx.set_function("double", lambda x: x * 2)
35
+ >>> ctx.call_function("double", [5])
36
+ 10
37
+ """
38
+
39
+ def __init__(self, parent: EvaluationContext | None = None) -> None:
40
+ self._variables: dict[str, Any] = {}
41
+ self._functions: dict[str, Callable[..., Any]] = {}
42
+ self._parent = parent
43
+
44
+ def set_variable(self, name: str, value: Any) -> None:
45
+ """Set a variable in the context.
46
+
47
+ Parameters
48
+ ----------
49
+ name : str
50
+ Variable name.
51
+ value : Any
52
+ Variable value.
53
+ """
54
+ self._variables[name] = value
55
+
56
+ def get_variable(self, name: str) -> Any:
57
+ """Get a variable from the context (searches parent chain).
58
+
59
+ Parameters
60
+ ----------
61
+ name : str
62
+ Variable name.
63
+
64
+ Returns
65
+ -------
66
+ Any
67
+ Variable value.
68
+
69
+ Raises
70
+ ------
71
+ EvaluationError
72
+ If variable is not defined in context or parent chain.
73
+ """
74
+ if name in self._variables:
75
+ return self._variables[name]
76
+ if self._parent is not None:
77
+ return self._parent.get_variable(name)
78
+ raise EvaluationError(f"Undefined variable: {name}")
79
+
80
+ def has_variable(self, name: str) -> bool:
81
+ """Check if variable exists in context or parent chain.
82
+
83
+ Parameters
84
+ ----------
85
+ name : str
86
+ Variable name.
87
+
88
+ Returns
89
+ -------
90
+ bool
91
+ True if variable exists, False otherwise.
92
+ """
93
+ if name in self._variables:
94
+ return True
95
+ if self._parent is not None:
96
+ return self._parent.has_variable(name)
97
+ return False
98
+
99
+ def set_function(self, name: str, func: Callable[..., Any]) -> None:
100
+ """Register a function in the context.
101
+
102
+ Parameters
103
+ ----------
104
+ name : str
105
+ Function name.
106
+ func : Callable[..., Any]
107
+ Function to register.
108
+ """
109
+ self._functions[name] = func
110
+
111
+ def call_function(self, name: str, args: list[Any]) -> Any:
112
+ """Call a function with arguments.
113
+
114
+ Parameters
115
+ ----------
116
+ name : str
117
+ Function name.
118
+ args : list[Any]
119
+ Function arguments.
120
+
121
+ Returns
122
+ -------
123
+ Any
124
+ Function return value.
125
+
126
+ Raises
127
+ ------
128
+ EvaluationError
129
+ If function is not defined or call fails.
130
+ """
131
+ if name in self._functions:
132
+ try:
133
+ return self._functions[name](*args)
134
+ except TypeError as e:
135
+ raise EvaluationError(f"Function call failed for '{name}': {e}") from e
136
+ if self._parent is not None:
137
+ return self._parent.call_function(name, args)
138
+ raise EvaluationError(f"Undefined function: {name}")
139
+
140
+ def has_function(self, name: str) -> bool:
141
+ """Check if function exists in context or parent chain.
142
+
143
+ Parameters
144
+ ----------
145
+ name : str
146
+ Function name.
147
+
148
+ Returns
149
+ -------
150
+ bool
151
+ True if function exists, False otherwise.
152
+ """
153
+ if name in self._functions:
154
+ return True
155
+ if self._parent is not None:
156
+ return self._parent.has_function(name)
157
+ return False
158
+
159
+ def create_child(self) -> EvaluationContext:
160
+ """Create a child context with this context as parent.
161
+
162
+ Returns
163
+ -------
164
+ EvaluationContext
165
+ New child context.
166
+
167
+ Examples
168
+ --------
169
+ >>> parent = EvaluationContext()
170
+ >>> parent.set_variable("x", 10)
171
+ >>> child = parent.create_child()
172
+ >>> child.get_variable("x")
173
+ 10
174
+ >>> child.set_variable("y", 20)
175
+ >>> child.get_variable("y")
176
+ 20
177
+ """
178
+ return EvaluationContext(parent=self)
bead/dsl/errors.py ADDED
@@ -0,0 +1,71 @@
1
+ """DSL-specific exceptions."""
2
+
3
+ from __future__ import annotations
4
+
5
+
6
+ class DSLError(Exception):
7
+ """Base exception for DSL errors."""
8
+
9
+ pass
10
+
11
+
12
+ class ParseError(DSLError):
13
+ """Exception raised when parsing fails.
14
+
15
+ Parameters
16
+ ----------
17
+ message
18
+ Error message describing what went wrong during parsing.
19
+ line
20
+ Line number where the error occurred (1-indexed). None if unknown.
21
+ column
22
+ Column number where the error occurred (1-indexed). None if unknown.
23
+ text
24
+ The text that caused the error. None if unavailable.
25
+
26
+ Attributes
27
+ ----------
28
+ line : int | None
29
+ Line number where error occurred.
30
+ column : int | None
31
+ Column number where error occurred.
32
+ text : str | None
33
+ Text that caused the error.
34
+
35
+ Examples
36
+ --------
37
+ >>> try:
38
+ ... raise ParseError("Unexpected token", line=5, column=12, text="@invalid")
39
+ ... except ParseError as e:
40
+ ... print(e.line, e.column)
41
+ 5 12
42
+ """
43
+
44
+ def __init__(
45
+ self,
46
+ message: str,
47
+ line: int | None = None,
48
+ column: int | None = None,
49
+ text: str | None = None,
50
+ ) -> None:
51
+ self.line = line
52
+ self.column = column
53
+ self.text = text
54
+ super().__init__(message)
55
+
56
+ def __str__(self) -> str:
57
+ """Return formatted error message."""
58
+ parts = [super().__str__()]
59
+ if self.line is not None:
60
+ parts.append(f" at line {self.line}")
61
+ if self.column is not None:
62
+ parts.append(f", column {self.column}")
63
+ if self.text is not None:
64
+ parts.append(f"\n {self.text}")
65
+ return "".join(parts)
66
+
67
+
68
+ class EvaluationError(DSLError):
69
+ """Exception raised when evaluation fails."""
70
+
71
+ pass