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,155 @@
|
|
|
1
|
+
"""PEFT-based LoRA adapters for participant-specific fine-tuning.
|
|
2
|
+
|
|
3
|
+
This module provides participant-specific LoRA adapters using HuggingFace PEFT
|
|
4
|
+
library, replacing the custom LoRA implementation with the well-maintained
|
|
5
|
+
PEFT library.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import copy
|
|
11
|
+
|
|
12
|
+
import torch.nn as nn
|
|
13
|
+
from peft import LoraConfig, get_peft_model
|
|
14
|
+
from torch import Tensor
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class DecoderWrapper(nn.Module):
|
|
18
|
+
"""Wrapper to make a decoder module compatible with PEFT.
|
|
19
|
+
|
|
20
|
+
PEFT expects a PreTrainedModel, but we often work with decoder modules.
|
|
21
|
+
This wrapper makes the decoder look like a model for PEFT purposes.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, decoder: nn.Module) -> None:
|
|
25
|
+
"""Initialize decoder wrapper.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
decoder : nn.Module
|
|
30
|
+
Decoder module to wrap.
|
|
31
|
+
"""
|
|
32
|
+
super().__init__()
|
|
33
|
+
self.decoder = decoder
|
|
34
|
+
# PEFT may check for config attribute
|
|
35
|
+
if hasattr(decoder, "config"):
|
|
36
|
+
self.config = decoder.config
|
|
37
|
+
|
|
38
|
+
def forward(
|
|
39
|
+
self, input_ids: Tensor, attention_mask: Tensor | None = None
|
|
40
|
+
) -> Tensor:
|
|
41
|
+
"""Forward pass through decoder.
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
input_ids : Tensor
|
|
46
|
+
Input token IDs, shape (batch_size, seq_len).
|
|
47
|
+
attention_mask : Tensor | None
|
|
48
|
+
Attention mask, shape (batch_size, seq_len). If None, no masking.
|
|
49
|
+
|
|
50
|
+
Returns
|
|
51
|
+
-------
|
|
52
|
+
Tensor
|
|
53
|
+
Decoder output tensor.
|
|
54
|
+
"""
|
|
55
|
+
if attention_mask is not None:
|
|
56
|
+
return self.decoder(input_ids, attention_mask=attention_mask)
|
|
57
|
+
return self.decoder(input_ids)
|
|
58
|
+
|
|
59
|
+
def __getattr__(self, name: str) -> nn.Module:
|
|
60
|
+
"""Delegate attribute access to decoder."""
|
|
61
|
+
if name in ("decoder", "config"):
|
|
62
|
+
return super().__getattr__(name) # type: ignore[return-value]
|
|
63
|
+
return getattr(self.decoder, name)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def create_participant_lora_adapter(
|
|
67
|
+
base_decoder: nn.Module,
|
|
68
|
+
rank: int = 8,
|
|
69
|
+
alpha: float = 16.0,
|
|
70
|
+
dropout: float = 0.1,
|
|
71
|
+
target_modules: list[str] | None = None,
|
|
72
|
+
) -> nn.Module:
|
|
73
|
+
"""Create a participant-specific LoRA adapter using HuggingFace PEFT.
|
|
74
|
+
|
|
75
|
+
Creates a PEFT model with LoRA adapters for participant-specific
|
|
76
|
+
fine-tuning. This replaces the custom LoRA implementation with
|
|
77
|
+
HuggingFace's well-maintained PEFT library.
|
|
78
|
+
|
|
79
|
+
Parameters
|
|
80
|
+
----------
|
|
81
|
+
base_decoder : nn.Module
|
|
82
|
+
Base decoder module to adapt (e.g., T5 decoder, BART decoder).
|
|
83
|
+
rank : int
|
|
84
|
+
LoRA rank r (default: 8).
|
|
85
|
+
alpha : float
|
|
86
|
+
LoRA scaling factor α (default: 16.0).
|
|
87
|
+
dropout : float
|
|
88
|
+
LoRA dropout probability (default: 0.1).
|
|
89
|
+
target_modules : list[str] | None
|
|
90
|
+
Target modules for LoRA injection (e.g., ["q", "v"]).
|
|
91
|
+
If None, uses default based on model architecture.
|
|
92
|
+
|
|
93
|
+
Returns
|
|
94
|
+
-------
|
|
95
|
+
nn.Module
|
|
96
|
+
Decoder module with LoRA adapters applied (compatible with original API).
|
|
97
|
+
|
|
98
|
+
Examples
|
|
99
|
+
--------
|
|
100
|
+
>>> from transformers import AutoModelForSeq2SeqLM
|
|
101
|
+
>>> model = AutoModelForSeq2SeqLM.from_pretrained("t5-small")
|
|
102
|
+
>>> decoder = model.get_decoder()
|
|
103
|
+
>>> peft_decoder = create_participant_lora_adapter(
|
|
104
|
+
... decoder,
|
|
105
|
+
... rank=8,
|
|
106
|
+
... alpha=16.0,
|
|
107
|
+
... target_modules=["q", "v"]
|
|
108
|
+
... )
|
|
109
|
+
>>> # peft_decoder now has LoRA adapters and can be used like the original decoder
|
|
110
|
+
"""
|
|
111
|
+
# Determine target modules if not provided
|
|
112
|
+
if target_modules is None:
|
|
113
|
+
# Try to infer from decoder config
|
|
114
|
+
if hasattr(base_decoder, "config"):
|
|
115
|
+
model_type = base_decoder.config.model_type.lower()
|
|
116
|
+
if "t5" in model_type:
|
|
117
|
+
target_modules = ["q", "v"]
|
|
118
|
+
elif "bart" in model_type:
|
|
119
|
+
target_modules = ["q_proj", "v_proj"]
|
|
120
|
+
else:
|
|
121
|
+
# Generic: try common attention projection names
|
|
122
|
+
target_modules = ["query", "value", "q_proj", "v_proj"]
|
|
123
|
+
else:
|
|
124
|
+
# Fallback defaults
|
|
125
|
+
target_modules = ["q", "v", "q_proj", "v_proj"]
|
|
126
|
+
|
|
127
|
+
# Create deep copy to avoid modifying original
|
|
128
|
+
decoder_copy = copy.deepcopy(base_decoder)
|
|
129
|
+
|
|
130
|
+
# Wrap decoder to make it compatible with PEFT
|
|
131
|
+
wrapped_decoder = DecoderWrapper(decoder_copy)
|
|
132
|
+
|
|
133
|
+
# Create LoRA configuration
|
|
134
|
+
lora_config = LoraConfig(
|
|
135
|
+
r=rank,
|
|
136
|
+
lora_alpha=alpha,
|
|
137
|
+
target_modules=target_modules,
|
|
138
|
+
lora_dropout=dropout,
|
|
139
|
+
bias="none", # Don't train bias parameters
|
|
140
|
+
task_type="FEATURE_EXTRACTION", # Generic task type
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
# Apply PEFT LoRA
|
|
144
|
+
peft_model = get_peft_model(wrapped_decoder, lora_config)
|
|
145
|
+
|
|
146
|
+
# Extract the adapted decoder from the PEFT model
|
|
147
|
+
# PEFT wraps the model, so we need to get the decoder back
|
|
148
|
+
if hasattr(peft_model, "base_model"):
|
|
149
|
+
# PEFT v0.6+ structure
|
|
150
|
+
if hasattr(peft_model.base_model, "decoder"):
|
|
151
|
+
return peft_model.base_model.decoder
|
|
152
|
+
return peft_model.base_model
|
|
153
|
+
else:
|
|
154
|
+
# Fallback: return the PEFT model itself (it should work as decoder)
|
|
155
|
+
return peft_model
|