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.
- bead/__init__.py +11 -0
- bead/__main__.py +11 -0
- bead/active_learning/__init__.py +15 -0
- bead/active_learning/config.py +231 -0
- bead/active_learning/loop.py +566 -0
- bead/active_learning/models/__init__.py +24 -0
- bead/active_learning/models/base.py +852 -0
- bead/active_learning/models/binary.py +910 -0
- bead/active_learning/models/categorical.py +943 -0
- bead/active_learning/models/cloze.py +862 -0
- bead/active_learning/models/forced_choice.py +956 -0
- bead/active_learning/models/free_text.py +773 -0
- bead/active_learning/models/lora.py +365 -0
- bead/active_learning/models/magnitude.py +835 -0
- bead/active_learning/models/multi_select.py +795 -0
- bead/active_learning/models/ordinal_scale.py +811 -0
- bead/active_learning/models/peft_adapter.py +155 -0
- bead/active_learning/models/random_effects.py +639 -0
- bead/active_learning/selection.py +354 -0
- bead/active_learning/strategies.py +391 -0
- bead/active_learning/trainers/__init__.py +26 -0
- bead/active_learning/trainers/base.py +210 -0
- bead/active_learning/trainers/data_collator.py +172 -0
- bead/active_learning/trainers/dataset_utils.py +261 -0
- bead/active_learning/trainers/huggingface.py +304 -0
- bead/active_learning/trainers/lightning.py +324 -0
- bead/active_learning/trainers/metrics.py +424 -0
- bead/active_learning/trainers/mixed_effects.py +551 -0
- bead/active_learning/trainers/model_wrapper.py +509 -0
- bead/active_learning/trainers/registry.py +104 -0
- bead/adapters/__init__.py +11 -0
- bead/adapters/huggingface.py +61 -0
- bead/behavioral/__init__.py +116 -0
- bead/behavioral/analytics.py +646 -0
- bead/behavioral/extraction.py +343 -0
- bead/behavioral/merging.py +343 -0
- bead/cli/__init__.py +11 -0
- bead/cli/active_learning.py +513 -0
- bead/cli/active_learning_commands.py +779 -0
- bead/cli/completion.py +359 -0
- bead/cli/config.py +624 -0
- bead/cli/constraint_builders.py +286 -0
- bead/cli/deployment.py +859 -0
- bead/cli/deployment_trials.py +493 -0
- bead/cli/deployment_ui.py +332 -0
- bead/cli/display.py +378 -0
- bead/cli/items.py +960 -0
- bead/cli/items_factories.py +776 -0
- bead/cli/list_constraints.py +714 -0
- bead/cli/lists.py +490 -0
- bead/cli/main.py +430 -0
- bead/cli/models.py +877 -0
- bead/cli/resource_loaders.py +621 -0
- bead/cli/resources.py +1036 -0
- bead/cli/shell.py +356 -0
- bead/cli/simulate.py +840 -0
- bead/cli/templates.py +1158 -0
- bead/cli/training.py +1080 -0
- bead/cli/utils.py +614 -0
- bead/cli/workflow.py +1273 -0
- bead/config/__init__.py +68 -0
- bead/config/active_learning.py +1009 -0
- bead/config/config.py +192 -0
- bead/config/defaults.py +118 -0
- bead/config/deployment.py +217 -0
- bead/config/env.py +147 -0
- bead/config/item.py +45 -0
- bead/config/list.py +193 -0
- bead/config/loader.py +149 -0
- bead/config/logging.py +42 -0
- bead/config/model.py +49 -0
- bead/config/paths.py +46 -0
- bead/config/profiles.py +320 -0
- bead/config/resources.py +47 -0
- bead/config/serialization.py +210 -0
- bead/config/simulation.py +206 -0
- bead/config/template.py +238 -0
- bead/config/validation.py +267 -0
- bead/data/__init__.py +65 -0
- bead/data/base.py +87 -0
- bead/data/identifiers.py +97 -0
- bead/data/language_codes.py +61 -0
- bead/data/metadata.py +270 -0
- bead/data/range.py +123 -0
- bead/data/repository.py +358 -0
- bead/data/serialization.py +249 -0
- bead/data/timestamps.py +89 -0
- bead/data/validation.py +349 -0
- bead/data_collection/__init__.py +11 -0
- bead/data_collection/jatos.py +223 -0
- bead/data_collection/merger.py +154 -0
- bead/data_collection/prolific.py +198 -0
- bead/deployment/__init__.py +5 -0
- bead/deployment/distribution.py +402 -0
- bead/deployment/jatos/__init__.py +1 -0
- bead/deployment/jatos/api.py +200 -0
- bead/deployment/jatos/exporter.py +210 -0
- bead/deployment/jspsych/__init__.py +9 -0
- bead/deployment/jspsych/biome.json +44 -0
- bead/deployment/jspsych/config.py +411 -0
- bead/deployment/jspsych/generator.py +598 -0
- bead/deployment/jspsych/package.json +51 -0
- bead/deployment/jspsych/pnpm-lock.yaml +2141 -0
- bead/deployment/jspsych/randomizer.py +299 -0
- bead/deployment/jspsych/src/lib/list-distributor.test.ts +327 -0
- bead/deployment/jspsych/src/lib/list-distributor.ts +1282 -0
- bead/deployment/jspsych/src/lib/randomizer.test.ts +232 -0
- bead/deployment/jspsych/src/lib/randomizer.ts +367 -0
- bead/deployment/jspsych/src/plugins/cloze-dropdown.ts +252 -0
- bead/deployment/jspsych/src/plugins/forced-choice.ts +265 -0
- bead/deployment/jspsych/src/plugins/plugins.test.ts +141 -0
- bead/deployment/jspsych/src/plugins/rating.ts +248 -0
- bead/deployment/jspsych/src/slopit/index.ts +9 -0
- bead/deployment/jspsych/src/types/jatos.d.ts +256 -0
- bead/deployment/jspsych/src/types/jspsych.d.ts +228 -0
- bead/deployment/jspsych/templates/experiment.css +1 -0
- bead/deployment/jspsych/templates/experiment.js.template +289 -0
- bead/deployment/jspsych/templates/index.html +51 -0
- bead/deployment/jspsych/templates/randomizer.js +241 -0
- bead/deployment/jspsych/templates/randomizer.js.template +313 -0
- bead/deployment/jspsych/trials.py +723 -0
- bead/deployment/jspsych/tsconfig.json +23 -0
- bead/deployment/jspsych/tsup.config.ts +30 -0
- bead/deployment/jspsych/ui/__init__.py +1 -0
- bead/deployment/jspsych/ui/components.py +383 -0
- bead/deployment/jspsych/ui/styles.py +411 -0
- bead/dsl/__init__.py +80 -0
- bead/dsl/ast.py +168 -0
- bead/dsl/context.py +178 -0
- bead/dsl/errors.py +71 -0
- bead/dsl/evaluator.py +570 -0
- bead/dsl/grammar.lark +81 -0
- bead/dsl/parser.py +231 -0
- bead/dsl/stdlib.py +929 -0
- bead/evaluation/__init__.py +13 -0
- bead/evaluation/convergence.py +485 -0
- bead/evaluation/interannotator.py +398 -0
- bead/items/__init__.py +40 -0
- bead/items/adapters/__init__.py +70 -0
- bead/items/adapters/anthropic.py +224 -0
- bead/items/adapters/api_utils.py +167 -0
- bead/items/adapters/base.py +216 -0
- bead/items/adapters/google.py +259 -0
- bead/items/adapters/huggingface.py +1074 -0
- bead/items/adapters/openai.py +323 -0
- bead/items/adapters/registry.py +202 -0
- bead/items/adapters/sentence_transformers.py +224 -0
- bead/items/adapters/togetherai.py +309 -0
- bead/items/binary.py +515 -0
- bead/items/cache.py +558 -0
- bead/items/categorical.py +593 -0
- bead/items/cloze.py +757 -0
- bead/items/constructor.py +784 -0
- bead/items/forced_choice.py +413 -0
- bead/items/free_text.py +681 -0
- bead/items/generation.py +432 -0
- bead/items/item.py +396 -0
- bead/items/item_template.py +787 -0
- bead/items/magnitude.py +573 -0
- bead/items/multi_select.py +621 -0
- bead/items/ordinal_scale.py +569 -0
- bead/items/scoring.py +448 -0
- bead/items/validation.py +723 -0
- bead/lists/__init__.py +30 -0
- bead/lists/balancer.py +263 -0
- bead/lists/constraints.py +1067 -0
- bead/lists/experiment_list.py +286 -0
- bead/lists/list_collection.py +378 -0
- bead/lists/partitioner.py +1141 -0
- bead/lists/stratification.py +254 -0
- bead/participants/__init__.py +73 -0
- bead/participants/collection.py +699 -0
- bead/participants/merging.py +312 -0
- bead/participants/metadata_spec.py +491 -0
- bead/participants/models.py +276 -0
- bead/resources/__init__.py +29 -0
- bead/resources/adapters/__init__.py +19 -0
- bead/resources/adapters/base.py +104 -0
- bead/resources/adapters/cache.py +128 -0
- bead/resources/adapters/glazing.py +508 -0
- bead/resources/adapters/registry.py +117 -0
- bead/resources/adapters/unimorph.py +796 -0
- bead/resources/classification.py +856 -0
- bead/resources/constraint_builders.py +329 -0
- bead/resources/constraints.py +165 -0
- bead/resources/lexical_item.py +223 -0
- bead/resources/lexicon.py +744 -0
- bead/resources/loaders.py +209 -0
- bead/resources/template.py +441 -0
- bead/resources/template_collection.py +707 -0
- bead/resources/template_generation.py +349 -0
- bead/simulation/__init__.py +29 -0
- bead/simulation/annotators/__init__.py +15 -0
- bead/simulation/annotators/base.py +175 -0
- bead/simulation/annotators/distance_based.py +135 -0
- bead/simulation/annotators/lm_based.py +114 -0
- bead/simulation/annotators/oracle.py +182 -0
- bead/simulation/annotators/random.py +181 -0
- bead/simulation/dsl_extension/__init__.py +3 -0
- bead/simulation/noise_models/__init__.py +13 -0
- bead/simulation/noise_models/base.py +42 -0
- bead/simulation/noise_models/random_noise.py +82 -0
- bead/simulation/noise_models/systematic.py +132 -0
- bead/simulation/noise_models/temperature.py +86 -0
- bead/simulation/runner.py +144 -0
- bead/simulation/strategies/__init__.py +23 -0
- bead/simulation/strategies/base.py +123 -0
- bead/simulation/strategies/binary.py +103 -0
- bead/simulation/strategies/categorical.py +123 -0
- bead/simulation/strategies/cloze.py +224 -0
- bead/simulation/strategies/forced_choice.py +127 -0
- bead/simulation/strategies/free_text.py +105 -0
- bead/simulation/strategies/magnitude.py +116 -0
- bead/simulation/strategies/multi_select.py +129 -0
- bead/simulation/strategies/ordinal_scale.py +131 -0
- bead/templates/__init__.py +27 -0
- bead/templates/adapters/__init__.py +17 -0
- bead/templates/adapters/base.py +128 -0
- bead/templates/adapters/cache.py +178 -0
- bead/templates/adapters/huggingface.py +312 -0
- bead/templates/combinatorics.py +103 -0
- bead/templates/filler.py +605 -0
- bead/templates/renderers.py +177 -0
- bead/templates/resolver.py +178 -0
- bead/templates/strategies.py +1806 -0
- bead/templates/streaming.py +195 -0
- bead-0.1.0.dist-info/METADATA +212 -0
- bead-0.1.0.dist-info/RECORD +231 -0
- bead-0.1.0.dist-info/WHEEL +4 -0
- bead-0.1.0.dist-info/entry_points.txt +2 -0
- bead-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,714 @@
|
|
|
1
|
+
"""List constraint builder commands for bead CLI.
|
|
2
|
+
|
|
3
|
+
This module provides CLI commands for creating list and batch constraints.
|
|
4
|
+
List constraints apply to individual lists, while batch constraints apply
|
|
5
|
+
across all lists in a batch.
|
|
6
|
+
|
|
7
|
+
List constraints (8 types):
|
|
8
|
+
- uniqueness: No duplicate property values
|
|
9
|
+
- balance: Balanced distribution
|
|
10
|
+
- quantile: Uniform across quantiles
|
|
11
|
+
- grouped-quantile: Quantile distribution within groups
|
|
12
|
+
- conditional-uniqueness: Conditional uniqueness via DSL
|
|
13
|
+
- diversity: Minimum unique values
|
|
14
|
+
- size: List size requirements
|
|
15
|
+
- ordering: Presentation order (runtime)
|
|
16
|
+
|
|
17
|
+
Batch constraints (4 types):
|
|
18
|
+
- coverage: All values appear somewhere
|
|
19
|
+
- balance: Balanced distribution across batch
|
|
20
|
+
- diversity: Prevent values in too many lists
|
|
21
|
+
- min-occurrence: Minimum occurrences per value
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
|
|
28
|
+
import click
|
|
29
|
+
|
|
30
|
+
from bead.cli.display import print_error, print_success
|
|
31
|
+
from bead.cli.utils import parse_key_value_pairs, parse_list_option
|
|
32
|
+
from bead.lists.constraints import (
|
|
33
|
+
BalanceConstraint,
|
|
34
|
+
BatchBalanceConstraint,
|
|
35
|
+
BatchCoverageConstraint,
|
|
36
|
+
BatchDiversityConstraint,
|
|
37
|
+
BatchMinOccurrenceConstraint,
|
|
38
|
+
DiversityConstraint,
|
|
39
|
+
GroupedQuantileConstraint,
|
|
40
|
+
QuantileConstraint,
|
|
41
|
+
SizeConstraint,
|
|
42
|
+
UniquenessConstraint,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# ==================== List Constraint Commands ====================
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@click.command()
|
|
49
|
+
@click.option(
|
|
50
|
+
"--property-expression",
|
|
51
|
+
type=str,
|
|
52
|
+
required=True,
|
|
53
|
+
help="Property expression (e.g., 'item.metadata.verb')",
|
|
54
|
+
)
|
|
55
|
+
@click.option(
|
|
56
|
+
"--output",
|
|
57
|
+
"-o",
|
|
58
|
+
type=click.Path(path_type=Path),
|
|
59
|
+
required=True,
|
|
60
|
+
help="Output JSONL file",
|
|
61
|
+
)
|
|
62
|
+
@click.option(
|
|
63
|
+
"--priority",
|
|
64
|
+
type=int,
|
|
65
|
+
default=5,
|
|
66
|
+
help="Constraint priority (default: 5)",
|
|
67
|
+
)
|
|
68
|
+
def create_uniqueness(
|
|
69
|
+
property_expression: str,
|
|
70
|
+
output: Path,
|
|
71
|
+
priority: int,
|
|
72
|
+
) -> None:
|
|
73
|
+
r"""Create uniqueness constraint.
|
|
74
|
+
|
|
75
|
+
Ensures no duplicate values for a property within each list.
|
|
76
|
+
|
|
77
|
+
Examples
|
|
78
|
+
--------
|
|
79
|
+
$ bead lists create-uniqueness \\
|
|
80
|
+
--property-expression "item.metadata.verb" \\
|
|
81
|
+
-o constraints/unique_verbs.jsonl
|
|
82
|
+
"""
|
|
83
|
+
try:
|
|
84
|
+
constraint = UniquenessConstraint(
|
|
85
|
+
property_expression=property_expression,
|
|
86
|
+
priority=priority,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
output.parent.mkdir(parents=True, exist_ok=True)
|
|
90
|
+
with open(output, "w") as f:
|
|
91
|
+
f.write(constraint.model_dump_json() + "\n")
|
|
92
|
+
|
|
93
|
+
print_success(f"Created uniqueness constraint: {output}")
|
|
94
|
+
|
|
95
|
+
except Exception as e:
|
|
96
|
+
print_error(f"Failed to create uniqueness constraint: {e}")
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@click.command()
|
|
100
|
+
@click.option(
|
|
101
|
+
"--property-expression",
|
|
102
|
+
type=str,
|
|
103
|
+
required=True,
|
|
104
|
+
help="Property expression",
|
|
105
|
+
)
|
|
106
|
+
@click.option(
|
|
107
|
+
"--target-counts",
|
|
108
|
+
type=str,
|
|
109
|
+
help=(
|
|
110
|
+
"Target counts (key=value pairs, comma-separated, e.g., 'a=20,b=10'). "
|
|
111
|
+
"Omit for equal distribution."
|
|
112
|
+
),
|
|
113
|
+
)
|
|
114
|
+
@click.option(
|
|
115
|
+
"--output",
|
|
116
|
+
"-o",
|
|
117
|
+
type=click.Path(path_type=Path),
|
|
118
|
+
required=True,
|
|
119
|
+
help="Output JSONL file",
|
|
120
|
+
)
|
|
121
|
+
@click.option(
|
|
122
|
+
"--tolerance",
|
|
123
|
+
type=float,
|
|
124
|
+
default=0.1,
|
|
125
|
+
help="Tolerance (default: 0.1)",
|
|
126
|
+
)
|
|
127
|
+
@click.option(
|
|
128
|
+
"--priority",
|
|
129
|
+
type=int,
|
|
130
|
+
default=5,
|
|
131
|
+
help="Constraint priority (default: 5)",
|
|
132
|
+
)
|
|
133
|
+
def create_balance(
|
|
134
|
+
property_expression: str,
|
|
135
|
+
target_counts: str | None,
|
|
136
|
+
output: Path,
|
|
137
|
+
tolerance: float,
|
|
138
|
+
priority: int,
|
|
139
|
+
) -> None:
|
|
140
|
+
r"""Create balance constraint.
|
|
141
|
+
|
|
142
|
+
Ensures balanced distribution of property values.
|
|
143
|
+
|
|
144
|
+
Examples
|
|
145
|
+
--------
|
|
146
|
+
$ bead lists create-balance \\
|
|
147
|
+
--property-expression "item.metadata.condition" \\
|
|
148
|
+
--target-counts "control=20,experimental=10" \\
|
|
149
|
+
-o constraints/balance.jsonl
|
|
150
|
+
"""
|
|
151
|
+
try:
|
|
152
|
+
# Parse target counts (None means equal distribution)
|
|
153
|
+
counts_dict = None
|
|
154
|
+
if target_counts:
|
|
155
|
+
parsed = parse_key_value_pairs(target_counts)
|
|
156
|
+
counts_dict = {k: int(v) for k, v in parsed.items()}
|
|
157
|
+
|
|
158
|
+
constraint = BalanceConstraint(
|
|
159
|
+
property_expression=property_expression,
|
|
160
|
+
target_counts=counts_dict,
|
|
161
|
+
tolerance=tolerance,
|
|
162
|
+
priority=priority,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
output.parent.mkdir(parents=True, exist_ok=True)
|
|
166
|
+
with open(output, "w") as f:
|
|
167
|
+
f.write(constraint.model_dump_json() + "\n")
|
|
168
|
+
|
|
169
|
+
print_success(f"Created balance constraint: {output}")
|
|
170
|
+
|
|
171
|
+
except Exception as e:
|
|
172
|
+
print_error(f"Failed to create balance constraint: {e}")
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
@click.command()
|
|
176
|
+
@click.option(
|
|
177
|
+
"--property-expression",
|
|
178
|
+
type=str,
|
|
179
|
+
required=True,
|
|
180
|
+
help="Property expression",
|
|
181
|
+
)
|
|
182
|
+
@click.option(
|
|
183
|
+
"--n-quantiles",
|
|
184
|
+
type=int,
|
|
185
|
+
required=True,
|
|
186
|
+
help="Number of quantiles",
|
|
187
|
+
)
|
|
188
|
+
@click.option(
|
|
189
|
+
"--output",
|
|
190
|
+
"-o",
|
|
191
|
+
type=click.Path(path_type=Path),
|
|
192
|
+
required=True,
|
|
193
|
+
help="Output JSONL file",
|
|
194
|
+
)
|
|
195
|
+
@click.option(
|
|
196
|
+
"--priority",
|
|
197
|
+
type=int,
|
|
198
|
+
default=5,
|
|
199
|
+
help="Constraint priority (default: 5)",
|
|
200
|
+
)
|
|
201
|
+
def create_quantile(
|
|
202
|
+
property_expression: str,
|
|
203
|
+
n_quantiles: int,
|
|
204
|
+
output: Path,
|
|
205
|
+
priority: int,
|
|
206
|
+
) -> None:
|
|
207
|
+
r"""Create quantile constraint.
|
|
208
|
+
|
|
209
|
+
Ensures uniform distribution across quantiles.
|
|
210
|
+
|
|
211
|
+
Examples
|
|
212
|
+
--------
|
|
213
|
+
$ bead lists create-quantile \\
|
|
214
|
+
--property-expression "item.metadata.word_length" \\
|
|
215
|
+
--n-quantiles 4 \\
|
|
216
|
+
-o constraints/quantile.jsonl
|
|
217
|
+
"""
|
|
218
|
+
try:
|
|
219
|
+
constraint = QuantileConstraint(
|
|
220
|
+
property_expression=property_expression,
|
|
221
|
+
n_quantiles=n_quantiles,
|
|
222
|
+
priority=priority,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
output.parent.mkdir(parents=True, exist_ok=True)
|
|
226
|
+
with open(output, "w") as f:
|
|
227
|
+
f.write(constraint.model_dump_json() + "\n")
|
|
228
|
+
|
|
229
|
+
print_success(f"Created quantile constraint: {output}")
|
|
230
|
+
|
|
231
|
+
except Exception as e:
|
|
232
|
+
print_error(f"Failed to create quantile constraint: {e}")
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
@click.command()
|
|
236
|
+
@click.option(
|
|
237
|
+
"--property-expression",
|
|
238
|
+
type=str,
|
|
239
|
+
required=True,
|
|
240
|
+
help="Property expression",
|
|
241
|
+
)
|
|
242
|
+
@click.option(
|
|
243
|
+
"--group-by-expression",
|
|
244
|
+
type=str,
|
|
245
|
+
required=True,
|
|
246
|
+
help="Group-by expression",
|
|
247
|
+
)
|
|
248
|
+
@click.option(
|
|
249
|
+
"--n-quantiles",
|
|
250
|
+
type=int,
|
|
251
|
+
required=True,
|
|
252
|
+
help="Number of quantiles",
|
|
253
|
+
)
|
|
254
|
+
@click.option(
|
|
255
|
+
"--output",
|
|
256
|
+
"-o",
|
|
257
|
+
type=click.Path(path_type=Path),
|
|
258
|
+
required=True,
|
|
259
|
+
help="Output JSONL file",
|
|
260
|
+
)
|
|
261
|
+
@click.option(
|
|
262
|
+
"--priority",
|
|
263
|
+
type=int,
|
|
264
|
+
default=5,
|
|
265
|
+
help="Constraint priority (default: 5)",
|
|
266
|
+
)
|
|
267
|
+
def create_grouped_quantile(
|
|
268
|
+
property_expression: str,
|
|
269
|
+
group_by_expression: str,
|
|
270
|
+
n_quantiles: int,
|
|
271
|
+
output: Path,
|
|
272
|
+
priority: int,
|
|
273
|
+
) -> None:
|
|
274
|
+
r"""Create grouped quantile constraint.
|
|
275
|
+
|
|
276
|
+
Ensures quantile distribution within groups.
|
|
277
|
+
|
|
278
|
+
Examples
|
|
279
|
+
--------
|
|
280
|
+
$ bead lists create-grouped-quantile \\
|
|
281
|
+
--property-expression "item.metadata.frequency" \\
|
|
282
|
+
--group-by-expression "item.metadata.condition" \\
|
|
283
|
+
--n-quantiles 3 \\
|
|
284
|
+
-o constraints/grouped_quantile.jsonl
|
|
285
|
+
"""
|
|
286
|
+
try:
|
|
287
|
+
constraint = GroupedQuantileConstraint(
|
|
288
|
+
property_expression=property_expression,
|
|
289
|
+
group_by_expression=group_by_expression,
|
|
290
|
+
n_quantiles=n_quantiles,
|
|
291
|
+
priority=priority,
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
output.parent.mkdir(parents=True, exist_ok=True)
|
|
295
|
+
with open(output, "w") as f:
|
|
296
|
+
f.write(constraint.model_dump_json() + "\n")
|
|
297
|
+
|
|
298
|
+
print_success(f"Created grouped quantile constraint: {output}")
|
|
299
|
+
|
|
300
|
+
except Exception as e:
|
|
301
|
+
print_error(f"Failed to create grouped quantile constraint: {e}")
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
@click.command()
|
|
305
|
+
@click.option(
|
|
306
|
+
"--property-expression",
|
|
307
|
+
type=str,
|
|
308
|
+
required=True,
|
|
309
|
+
help="Property expression",
|
|
310
|
+
)
|
|
311
|
+
@click.option(
|
|
312
|
+
"--min-unique",
|
|
313
|
+
type=int,
|
|
314
|
+
required=True,
|
|
315
|
+
help="Minimum unique values",
|
|
316
|
+
)
|
|
317
|
+
@click.option(
|
|
318
|
+
"--output",
|
|
319
|
+
"-o",
|
|
320
|
+
type=click.Path(path_type=Path),
|
|
321
|
+
required=True,
|
|
322
|
+
help="Output JSONL file",
|
|
323
|
+
)
|
|
324
|
+
@click.option(
|
|
325
|
+
"--priority",
|
|
326
|
+
type=int,
|
|
327
|
+
default=5,
|
|
328
|
+
help="Constraint priority (default: 5)",
|
|
329
|
+
)
|
|
330
|
+
def create_diversity(
|
|
331
|
+
property_expression: str,
|
|
332
|
+
min_unique: int,
|
|
333
|
+
output: Path,
|
|
334
|
+
priority: int,
|
|
335
|
+
) -> None:
|
|
336
|
+
r"""Create diversity constraint.
|
|
337
|
+
|
|
338
|
+
Ensures minimum unique values for property.
|
|
339
|
+
|
|
340
|
+
Examples
|
|
341
|
+
--------
|
|
342
|
+
$ bead lists create-diversity \\
|
|
343
|
+
--property-expression "item.metadata.verb_class" \\
|
|
344
|
+
--min-unique 10 \\
|
|
345
|
+
-o constraints/diversity.jsonl
|
|
346
|
+
"""
|
|
347
|
+
try:
|
|
348
|
+
constraint = DiversityConstraint(
|
|
349
|
+
property_expression=property_expression,
|
|
350
|
+
min_unique_values=min_unique,
|
|
351
|
+
priority=priority,
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
output.parent.mkdir(parents=True, exist_ok=True)
|
|
355
|
+
with open(output, "w") as f:
|
|
356
|
+
f.write(constraint.model_dump_json() + "\n")
|
|
357
|
+
|
|
358
|
+
print_success(f"Created diversity constraint: {output}")
|
|
359
|
+
|
|
360
|
+
except Exception as e:
|
|
361
|
+
print_error(f"Failed to create diversity constraint: {e}")
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
@click.command()
|
|
365
|
+
@click.option(
|
|
366
|
+
"--exact-size",
|
|
367
|
+
type=int,
|
|
368
|
+
help="Exact number of items per list (mutually exclusive with min/max)",
|
|
369
|
+
)
|
|
370
|
+
@click.option(
|
|
371
|
+
"--min-size",
|
|
372
|
+
type=int,
|
|
373
|
+
help="Minimum items per list",
|
|
374
|
+
)
|
|
375
|
+
@click.option(
|
|
376
|
+
"--max-size",
|
|
377
|
+
type=int,
|
|
378
|
+
help="Maximum items per list",
|
|
379
|
+
)
|
|
380
|
+
@click.option(
|
|
381
|
+
"--output",
|
|
382
|
+
"-o",
|
|
383
|
+
type=click.Path(path_type=Path),
|
|
384
|
+
required=True,
|
|
385
|
+
help="Output JSONL file",
|
|
386
|
+
)
|
|
387
|
+
@click.option(
|
|
388
|
+
"--priority",
|
|
389
|
+
type=int,
|
|
390
|
+
default=5,
|
|
391
|
+
help="Constraint priority (default: 5)",
|
|
392
|
+
)
|
|
393
|
+
def create_size(
|
|
394
|
+
exact_size: int | None,
|
|
395
|
+
min_size: int | None,
|
|
396
|
+
max_size: int | None,
|
|
397
|
+
output: Path,
|
|
398
|
+
priority: int,
|
|
399
|
+
) -> None:
|
|
400
|
+
r"""Create size constraint.
|
|
401
|
+
|
|
402
|
+
Ensures list size requirements.
|
|
403
|
+
|
|
404
|
+
Examples
|
|
405
|
+
--------
|
|
406
|
+
$ bead lists create-size --exact-size 40 -o constraints/size.jsonl
|
|
407
|
+
$ bead lists create-size --min-size 40 --max-size 60 \\
|
|
408
|
+
-o constraints/size.jsonl
|
|
409
|
+
"""
|
|
410
|
+
try:
|
|
411
|
+
if exact_size is not None and (min_size is not None or max_size is not None):
|
|
412
|
+
raise ValueError(
|
|
413
|
+
"Cannot specify --exact-size with --min-size or --max-size"
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
if exact_size is None and min_size is None and max_size is None:
|
|
417
|
+
raise ValueError(
|
|
418
|
+
"Must specify --exact-size or at least one of --min-size/--max-size"
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
constraint = SizeConstraint(
|
|
422
|
+
exact_size=exact_size,
|
|
423
|
+
min_size=min_size,
|
|
424
|
+
max_size=max_size,
|
|
425
|
+
priority=priority,
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
output.parent.mkdir(parents=True, exist_ok=True)
|
|
429
|
+
with open(output, "w") as f:
|
|
430
|
+
f.write(constraint.model_dump_json() + "\n")
|
|
431
|
+
|
|
432
|
+
print_success(f"Created size constraint: {output}")
|
|
433
|
+
|
|
434
|
+
except Exception as e:
|
|
435
|
+
print_error(f"Failed to create size constraint: {e}")
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
# ==================== Batch Constraint Commands ====================
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
@click.command()
|
|
442
|
+
@click.option(
|
|
443
|
+
"--property-expression",
|
|
444
|
+
type=str,
|
|
445
|
+
required=True,
|
|
446
|
+
help="Property expression",
|
|
447
|
+
)
|
|
448
|
+
@click.option(
|
|
449
|
+
"--target-values",
|
|
450
|
+
type=str,
|
|
451
|
+
required=True,
|
|
452
|
+
help="Target values (comma-separated)",
|
|
453
|
+
)
|
|
454
|
+
@click.option(
|
|
455
|
+
"--min-coverage",
|
|
456
|
+
type=float,
|
|
457
|
+
default=1.0,
|
|
458
|
+
help="Minimum coverage (default: 1.0 = 100%%)",
|
|
459
|
+
)
|
|
460
|
+
@click.option(
|
|
461
|
+
"--output",
|
|
462
|
+
"-o",
|
|
463
|
+
type=click.Path(path_type=Path),
|
|
464
|
+
required=True,
|
|
465
|
+
help="Output JSONL file",
|
|
466
|
+
)
|
|
467
|
+
@click.option(
|
|
468
|
+
"--priority",
|
|
469
|
+
type=int,
|
|
470
|
+
default=5,
|
|
471
|
+
help="Constraint priority (default: 5)",
|
|
472
|
+
)
|
|
473
|
+
def create_batch_coverage(
|
|
474
|
+
property_expression: str,
|
|
475
|
+
target_values: str,
|
|
476
|
+
min_coverage: float,
|
|
477
|
+
output: Path,
|
|
478
|
+
priority: int,
|
|
479
|
+
) -> None:
|
|
480
|
+
r"""Create batch coverage constraint.
|
|
481
|
+
|
|
482
|
+
Ensures all target values appear somewhere across all lists.
|
|
483
|
+
|
|
484
|
+
Examples
|
|
485
|
+
--------
|
|
486
|
+
$ bead lists create-batch-coverage \\
|
|
487
|
+
--property-expression "item.metadata.template_id" \\
|
|
488
|
+
--target-values "0,1,2,3,4,5" \\
|
|
489
|
+
-o constraints/coverage.jsonl
|
|
490
|
+
"""
|
|
491
|
+
try:
|
|
492
|
+
values_list = parse_list_option(target_values)
|
|
493
|
+
|
|
494
|
+
constraint = BatchCoverageConstraint(
|
|
495
|
+
property_expression=property_expression,
|
|
496
|
+
target_values=values_list, # type: ignore[arg-type]
|
|
497
|
+
min_coverage=min_coverage,
|
|
498
|
+
priority=priority,
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
output.parent.mkdir(parents=True, exist_ok=True)
|
|
502
|
+
with open(output, "w") as f:
|
|
503
|
+
f.write(constraint.model_dump_json() + "\n")
|
|
504
|
+
|
|
505
|
+
print_success(f"Created batch coverage constraint: {output}")
|
|
506
|
+
|
|
507
|
+
except Exception as e:
|
|
508
|
+
print_error(f"Failed to create batch coverage constraint: {e}")
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
@click.command()
|
|
512
|
+
@click.option(
|
|
513
|
+
"--property-expression",
|
|
514
|
+
type=str,
|
|
515
|
+
required=True,
|
|
516
|
+
help="Property expression",
|
|
517
|
+
)
|
|
518
|
+
@click.option(
|
|
519
|
+
"--target-distribution",
|
|
520
|
+
type=str,
|
|
521
|
+
required=True,
|
|
522
|
+
help="Target distribution (key=value pairs, comma-separated)",
|
|
523
|
+
)
|
|
524
|
+
@click.option(
|
|
525
|
+
"--tolerance",
|
|
526
|
+
type=float,
|
|
527
|
+
default=0.05,
|
|
528
|
+
help="Tolerance (default: 0.05)",
|
|
529
|
+
)
|
|
530
|
+
@click.option(
|
|
531
|
+
"--output",
|
|
532
|
+
"-o",
|
|
533
|
+
type=click.Path(path_type=Path),
|
|
534
|
+
required=True,
|
|
535
|
+
help="Output JSONL file",
|
|
536
|
+
)
|
|
537
|
+
@click.option(
|
|
538
|
+
"--priority",
|
|
539
|
+
type=int,
|
|
540
|
+
default=5,
|
|
541
|
+
help="Constraint priority (default: 5)",
|
|
542
|
+
)
|
|
543
|
+
def create_batch_balance(
|
|
544
|
+
property_expression: str,
|
|
545
|
+
target_distribution: str,
|
|
546
|
+
tolerance: float,
|
|
547
|
+
output: Path,
|
|
548
|
+
priority: int,
|
|
549
|
+
) -> None:
|
|
550
|
+
r"""Create batch balance constraint.
|
|
551
|
+
|
|
552
|
+
Ensures balanced distribution across entire batch.
|
|
553
|
+
|
|
554
|
+
Examples
|
|
555
|
+
--------
|
|
556
|
+
$ bead lists create-batch-balance \\
|
|
557
|
+
--property-expression "item.metadata.condition" \\
|
|
558
|
+
--target-distribution "control=0.5,experimental=0.5" \\
|
|
559
|
+
-o constraints/batch_balance.jsonl
|
|
560
|
+
"""
|
|
561
|
+
try:
|
|
562
|
+
dist_dict = parse_key_value_pairs(target_distribution)
|
|
563
|
+
dist_float = {k: float(v) for k, v in dist_dict.items()}
|
|
564
|
+
|
|
565
|
+
constraint = BatchBalanceConstraint(
|
|
566
|
+
property_expression=property_expression,
|
|
567
|
+
target_distribution=dist_float,
|
|
568
|
+
tolerance=tolerance,
|
|
569
|
+
priority=priority,
|
|
570
|
+
)
|
|
571
|
+
|
|
572
|
+
output.parent.mkdir(parents=True, exist_ok=True)
|
|
573
|
+
with open(output, "w") as f:
|
|
574
|
+
f.write(constraint.model_dump_json() + "\n")
|
|
575
|
+
|
|
576
|
+
print_success(f"Created batch balance constraint: {output}")
|
|
577
|
+
|
|
578
|
+
except Exception as e:
|
|
579
|
+
print_error(f"Failed to create batch balance constraint: {e}")
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
@click.command()
|
|
583
|
+
@click.option(
|
|
584
|
+
"--property-expression",
|
|
585
|
+
type=str,
|
|
586
|
+
required=True,
|
|
587
|
+
help="Property expression",
|
|
588
|
+
)
|
|
589
|
+
@click.option(
|
|
590
|
+
"--max-lists-per-value",
|
|
591
|
+
type=int,
|
|
592
|
+
required=True,
|
|
593
|
+
help="Maximum lists per value",
|
|
594
|
+
)
|
|
595
|
+
@click.option(
|
|
596
|
+
"--output",
|
|
597
|
+
"-o",
|
|
598
|
+
type=click.Path(path_type=Path),
|
|
599
|
+
required=True,
|
|
600
|
+
help="Output JSONL file",
|
|
601
|
+
)
|
|
602
|
+
@click.option(
|
|
603
|
+
"--priority",
|
|
604
|
+
type=int,
|
|
605
|
+
default=5,
|
|
606
|
+
help="Constraint priority (default: 5)",
|
|
607
|
+
)
|
|
608
|
+
def create_batch_diversity(
|
|
609
|
+
property_expression: str,
|
|
610
|
+
max_lists_per_value: int,
|
|
611
|
+
output: Path,
|
|
612
|
+
priority: int,
|
|
613
|
+
) -> None:
|
|
614
|
+
r"""Create batch diversity constraint.
|
|
615
|
+
|
|
616
|
+
Prevents values from appearing in too many lists.
|
|
617
|
+
|
|
618
|
+
Examples
|
|
619
|
+
--------
|
|
620
|
+
$ bead lists create-batch-diversity \\
|
|
621
|
+
--property-expression "item.metadata.target_word" \\
|
|
622
|
+
--max-lists-per-value 3 \\
|
|
623
|
+
-o constraints/batch_diversity.jsonl
|
|
624
|
+
"""
|
|
625
|
+
try:
|
|
626
|
+
constraint = BatchDiversityConstraint(
|
|
627
|
+
property_expression=property_expression,
|
|
628
|
+
max_lists_per_value=max_lists_per_value,
|
|
629
|
+
priority=priority,
|
|
630
|
+
)
|
|
631
|
+
|
|
632
|
+
output.parent.mkdir(parents=True, exist_ok=True)
|
|
633
|
+
with open(output, "w") as f:
|
|
634
|
+
f.write(constraint.model_dump_json() + "\n")
|
|
635
|
+
|
|
636
|
+
print_success(f"Created batch diversity constraint: {output}")
|
|
637
|
+
|
|
638
|
+
except Exception as e:
|
|
639
|
+
print_error(f"Failed to create batch diversity constraint: {e}")
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
@click.command()
|
|
643
|
+
@click.option(
|
|
644
|
+
"--property-expression",
|
|
645
|
+
type=str,
|
|
646
|
+
required=True,
|
|
647
|
+
help="Property expression",
|
|
648
|
+
)
|
|
649
|
+
@click.option(
|
|
650
|
+
"--min-occurrences",
|
|
651
|
+
type=int,
|
|
652
|
+
required=True,
|
|
653
|
+
help="Minimum occurrences per value",
|
|
654
|
+
)
|
|
655
|
+
@click.option(
|
|
656
|
+
"--output",
|
|
657
|
+
"-o",
|
|
658
|
+
type=click.Path(path_type=Path),
|
|
659
|
+
required=True,
|
|
660
|
+
help="Output JSONL file",
|
|
661
|
+
)
|
|
662
|
+
@click.option(
|
|
663
|
+
"--priority",
|
|
664
|
+
type=int,
|
|
665
|
+
default=5,
|
|
666
|
+
help="Constraint priority (default: 5)",
|
|
667
|
+
)
|
|
668
|
+
def create_batch_min_occurrence(
|
|
669
|
+
property_expression: str,
|
|
670
|
+
min_occurrences: int,
|
|
671
|
+
output: Path,
|
|
672
|
+
priority: int,
|
|
673
|
+
) -> None:
|
|
674
|
+
r"""Create batch minimum occurrence constraint.
|
|
675
|
+
|
|
676
|
+
Ensures minimum occurrences per value across batch.
|
|
677
|
+
|
|
678
|
+
Examples
|
|
679
|
+
--------
|
|
680
|
+
$ bead lists create-batch-min-occurrence \\
|
|
681
|
+
--property-expression "item.metadata.construction" \\
|
|
682
|
+
--min-occurrences 5 \\
|
|
683
|
+
-o constraints/min_occurrence.jsonl
|
|
684
|
+
"""
|
|
685
|
+
try:
|
|
686
|
+
constraint = BatchMinOccurrenceConstraint(
|
|
687
|
+
property_expression=property_expression,
|
|
688
|
+
min_occurrences=min_occurrences,
|
|
689
|
+
priority=priority,
|
|
690
|
+
)
|
|
691
|
+
|
|
692
|
+
output.parent.mkdir(parents=True, exist_ok=True)
|
|
693
|
+
with open(output, "w") as f:
|
|
694
|
+
f.write(constraint.model_dump_json() + "\n")
|
|
695
|
+
|
|
696
|
+
print_success(f"Created batch min occurrence constraint: {output}")
|
|
697
|
+
|
|
698
|
+
except Exception as e:
|
|
699
|
+
print_error(f"Failed to create batch min occurrence constraint: {e}")
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
# Export all commands
|
|
703
|
+
__all__ = [
|
|
704
|
+
"create_uniqueness",
|
|
705
|
+
"create_balance",
|
|
706
|
+
"create_quantile",
|
|
707
|
+
"create_grouped_quantile",
|
|
708
|
+
"create_diversity",
|
|
709
|
+
"create_size",
|
|
710
|
+
"create_batch_coverage",
|
|
711
|
+
"create_batch_balance",
|
|
712
|
+
"create_batch_diversity",
|
|
713
|
+
"create_batch_min_occurrence",
|
|
714
|
+
]
|