mostlyai-engine 1.4.0__tar.gz → 1.4.2__tar.gz
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.
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/PKG-INFO +6 -6
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/__init__.py +3 -2
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_common.py +0 -33
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/encoding.py +0 -3
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/generation.py +0 -3
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/training.py +9 -7
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_tabular/encoding.py +1 -3
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_tabular/generation.py +0 -3
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_tabular/training.py +0 -3
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/analysis.py +1 -3
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/encoding.py +2 -4
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/generation.py +0 -4
- mostlyai_engine-1.4.2/mostlyai/engine/random_state.py +49 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/splitting.py +2 -5
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/training.py +0 -4
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/pyproject.toml +8 -8
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/.gitignore +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/LICENSE +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/README.md +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_dtypes.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/__init__.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/language/__init__.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/language/categorical.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/language/datetime.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/language/numeric.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/language/text.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/tabular/__init__.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/tabular/categorical.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/tabular/character.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/tabular/datetime.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/tabular/itt.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/tabular/lat_long.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/tabular/numeric.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/__init__.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/common.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/engine/__init__.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/engine/base.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/engine/hf_engine.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/engine/vllm_engine.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/lstm.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/tokenizer_utils.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/xgrammar_utils.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_memory.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_tabular/__init__.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_tabular/argn.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_tabular/common.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_tabular/fairness.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_training_utils.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_workspace.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/domain.py +0 -0
- {mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/logging.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mostlyai-engine
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.2
|
|
4
4
|
Summary: Synthetic Data Engine
|
|
5
5
|
Project-URL: homepage, https://github.com/mostly-ai/mostlyai-engine
|
|
6
6
|
Project-URL: repository, https://github.com/mostly-ai/mostlyai-engine
|
|
@@ -35,17 +35,17 @@ Requires-Dist: pandas~=2.2.0
|
|
|
35
35
|
Requires-Dist: peft>=0.12.0
|
|
36
36
|
Requires-Dist: psutil<6,>=5.9.5
|
|
37
37
|
Requires-Dist: pyarrow>=16.0.0
|
|
38
|
-
Requires-Dist: setuptools
|
|
38
|
+
Requires-Dist: setuptools>=77.0.3
|
|
39
39
|
Requires-Dist: tokenizers>=0.21.0
|
|
40
40
|
Requires-Dist: torch<2.6.1,>=2.6.0
|
|
41
41
|
Requires-Dist: torchaudio<2.6.1,>=2.6.0
|
|
42
42
|
Requires-Dist: torchvision<0.21.1,>=0.21.0
|
|
43
43
|
Requires-Dist: transformers>=4.51.0
|
|
44
|
-
Requires-Dist: xgrammar>=0.1.
|
|
44
|
+
Requires-Dist: xgrammar>=0.1.18
|
|
45
45
|
Provides-Extra: gpu
|
|
46
|
-
Requires-Dist: bitsandbytes
|
|
47
|
-
Requires-Dist: bitsandbytes
|
|
48
|
-
Requires-Dist: vllm==0.8.
|
|
46
|
+
Requires-Dist: bitsandbytes==0.42.0; (sys_platform == 'darwin') and extra == 'gpu'
|
|
47
|
+
Requires-Dist: bitsandbytes>=0.45.5; (sys_platform == 'linux') and extra == 'gpu'
|
|
48
|
+
Requires-Dist: vllm==0.8.5.post1; (sys_platform == 'linux' or sys_platform == 'darwin') and extra == 'gpu'
|
|
49
49
|
Description-Content-Type: text/markdown
|
|
50
50
|
|
|
51
51
|
# Synthetic Data Engine 💎
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import warnings
|
|
15
15
|
|
|
16
16
|
from mostlyai.engine.logging import init_logging
|
|
17
|
+
from mostlyai.engine.random_state import set_random_state
|
|
17
18
|
from mostlyai.engine.splitting import split
|
|
18
19
|
from mostlyai.engine.analysis import analyze
|
|
19
20
|
from mostlyai.engine.training import train
|
|
@@ -21,8 +22,8 @@ from mostlyai.engine.encoding import encode
|
|
|
21
22
|
from mostlyai.engine.generation import generate
|
|
22
23
|
|
|
23
24
|
|
|
24
|
-
__all__ = ["split", "analyze", "encode", "train", "generate", "init_logging"]
|
|
25
|
-
__version__ = "1.4.
|
|
25
|
+
__all__ = ["split", "analyze", "encode", "train", "generate", "init_logging", "set_random_state"]
|
|
26
|
+
__version__ = "1.4.2"
|
|
26
27
|
|
|
27
28
|
# suppress specific warning related to os.fork() in multi-threaded processes
|
|
28
29
|
warnings.filterwarnings("ignore", category=DeprecationWarning, message=".*multi-threaded.*fork.*")
|
|
@@ -16,9 +16,7 @@ import inspect
|
|
|
16
16
|
import itertools
|
|
17
17
|
import json
|
|
18
18
|
import logging
|
|
19
|
-
import os
|
|
20
19
|
import platform
|
|
21
|
-
import struct
|
|
22
20
|
import time
|
|
23
21
|
from functools import wraps
|
|
24
22
|
from pathlib import Path
|
|
@@ -883,34 +881,3 @@ def dp_non_rare(value_counts: dict[str, int], epsilon: float, threshold: int = 5
|
|
|
883
881
|
|
|
884
882
|
def get_stochastic_rare_threshold(min_threshold: int = 5, noise_multiplier: float = 3) -> int:
|
|
885
883
|
return min_threshold + int(noise_multiplier * np.random.uniform())
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
def set_random_state(random_state: int | None = None, worker: bool = False):
|
|
889
|
-
def get_random_int_from_os() -> int:
|
|
890
|
-
# 32-bit, cryptographically secure random int from os
|
|
891
|
-
return int(struct.unpack("I", os.urandom(4))[0])
|
|
892
|
-
|
|
893
|
-
if worker: # worker process
|
|
894
|
-
if "MOSTLYAI_ENGINE_SEED" in os.environ:
|
|
895
|
-
random_state = int(os.environ["MOSTLYAI_ENGINE_SEED"])
|
|
896
|
-
else:
|
|
897
|
-
# normally, the seed should have been set in the main process
|
|
898
|
-
# but if not (e.g. in tests), we fallback to generating a random seed here
|
|
899
|
-
random_state = get_random_int_from_os()
|
|
900
|
-
else: # main process
|
|
901
|
-
if random_state is not None:
|
|
902
|
-
_LOG.info(f"Global random_state set to `{random_state}`")
|
|
903
|
-
|
|
904
|
-
if random_state is None:
|
|
905
|
-
random_state = get_random_int_from_os()
|
|
906
|
-
|
|
907
|
-
os.environ["MOSTLYAI_ENGINE_SEED"] = str(random_state)
|
|
908
|
-
|
|
909
|
-
import random
|
|
910
|
-
import numpy as np
|
|
911
|
-
import torch
|
|
912
|
-
|
|
913
|
-
random.seed(random_state)
|
|
914
|
-
np.random.seed(random_state)
|
|
915
|
-
torch.manual_seed(random_state)
|
|
916
|
-
torch.cuda.manual_seed_all(random_state)
|
|
@@ -27,7 +27,6 @@ from mostlyai.engine._common import (
|
|
|
27
27
|
ProgressCallback,
|
|
28
28
|
ProgressCallbackWrapper,
|
|
29
29
|
TABLE_COLUMN_INFIX,
|
|
30
|
-
set_random_state,
|
|
31
30
|
)
|
|
32
31
|
from mostlyai.engine._workspace import ensure_workspace_dir, Workspace, reset_dir
|
|
33
32
|
from mostlyai.engine._encoding_types.language.categorical import encode_language_categorical
|
|
@@ -158,11 +157,9 @@ def _encode_partition(
|
|
|
158
157
|
def encode(
|
|
159
158
|
workspace_dir: str | Path | None = None,
|
|
160
159
|
update_progress: ProgressCallback | None = None,
|
|
161
|
-
random_state: int | None = None,
|
|
162
160
|
) -> None:
|
|
163
161
|
_LOG.info("ENCODE_LANGUAGE started")
|
|
164
162
|
t0 = time.time()
|
|
165
|
-
set_random_state(random_state)
|
|
166
163
|
with ProgressCallbackWrapper(update_progress) as progress:
|
|
167
164
|
workspace_dir = ensure_workspace_dir(workspace_dir)
|
|
168
165
|
workspace = Workspace(workspace_dir)
|
|
@@ -33,7 +33,6 @@ from mostlyai.engine._common import (
|
|
|
33
33
|
FixedSizeSampleBuffer,
|
|
34
34
|
ProgressCallback,
|
|
35
35
|
ProgressCallbackWrapper,
|
|
36
|
-
set_random_state,
|
|
37
36
|
)
|
|
38
37
|
from mostlyai.engine._encoding_types.language.categorical import decode_language_categorical
|
|
39
38
|
from mostlyai.engine._encoding_types.language.datetime import decode_language_datetime
|
|
@@ -150,11 +149,9 @@ def generate(
|
|
|
150
149
|
device: torch.device | str | None = None,
|
|
151
150
|
workspace_dir: str | Path = "engine-ws",
|
|
152
151
|
update_progress: ProgressCallback | None = None,
|
|
153
|
-
random_state: int | None = None,
|
|
154
152
|
):
|
|
155
153
|
_LOG.info("GENERATE_LANGUAGE started")
|
|
156
154
|
t0_ = time.time()
|
|
157
|
-
set_random_state(random_state)
|
|
158
155
|
os.environ["VLLM_LOGGING_LEVEL"] = "WARNING"
|
|
159
156
|
os.environ["VLLM_NO_DEPRECATION_WARNING"] = "1"
|
|
160
157
|
|
|
@@ -38,7 +38,7 @@ from opacus.utils.batch_memory_manager import wrap_data_loader
|
|
|
38
38
|
|
|
39
39
|
from torch.utils.data import DataLoader
|
|
40
40
|
|
|
41
|
-
from mostlyai.engine._common import ProgressCallback, ProgressCallbackWrapper, TABLE_COLUMN_INFIX
|
|
41
|
+
from mostlyai.engine._common import ProgressCallback, ProgressCallbackWrapper, TABLE_COLUMN_INFIX
|
|
42
42
|
from mostlyai.engine._language.common import (
|
|
43
43
|
is_bf16_supported,
|
|
44
44
|
load_base_model_and_config,
|
|
@@ -75,7 +75,7 @@ _LOG = logging.getLogger(__name__)
|
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
def _physical_batch_size_heuristic(
|
|
78
|
-
no_of_records: int, no_of_model_params: int, max_tokens: int, device: torch.device
|
|
78
|
+
no_of_records: int, no_of_model_params: int, max_tokens: int, model_id: str, device: torch.device
|
|
79
79
|
) -> int:
|
|
80
80
|
"""
|
|
81
81
|
Calculate the physical batch size that fits in memory.
|
|
@@ -84,16 +84,19 @@ def _physical_batch_size_heuristic(
|
|
|
84
84
|
no_of_records (int): Number of records in the training dataset.
|
|
85
85
|
no_of_model_params (int): Number of model parameters.
|
|
86
86
|
max_tokens (int): Maximum number of tokens that are in the training dataset.
|
|
87
|
+
model_id (str): Model ID.
|
|
87
88
|
device (torch.device): Device to run training on.
|
|
88
89
|
|
|
89
90
|
Returns:
|
|
90
91
|
Batch size (int)
|
|
91
92
|
"""
|
|
92
93
|
min_batches = 8
|
|
93
|
-
max_batch_size = max(1, no_of_records // min_batches)
|
|
94
94
|
|
|
95
95
|
if device.type == "cuda":
|
|
96
|
-
|
|
96
|
+
if model_id == LSTMFromScratchConfig.model_id:
|
|
97
|
+
batch_size = 64 # empirically tuned for LSTM to have a better training dynamics
|
|
98
|
+
else:
|
|
99
|
+
batch_size = 2**10 # 1024, max 10 reductions
|
|
97
100
|
else:
|
|
98
101
|
if no_of_model_params < 10_000_000:
|
|
99
102
|
batch_size = 32
|
|
@@ -101,7 +104,7 @@ def _physical_batch_size_heuristic(
|
|
|
101
104
|
batch_size = 16 if max_tokens < 100 else 8
|
|
102
105
|
else:
|
|
103
106
|
batch_size = 8 if max_tokens < 100 else 4
|
|
104
|
-
|
|
107
|
+
max_batch_size = 2 ** int(np.log2(no_of_records / min_batches)) if no_of_records > 0 else 1
|
|
105
108
|
return int(np.clip(a=batch_size, a_min=1, a_max=max_batch_size))
|
|
106
109
|
|
|
107
110
|
|
|
@@ -281,11 +284,9 @@ def train(
|
|
|
281
284
|
device: torch.device | str | None = None,
|
|
282
285
|
workspace_dir: str | Path = "engine-ws",
|
|
283
286
|
update_progress: ProgressCallback | None = None,
|
|
284
|
-
random_state: int | None = None,
|
|
285
287
|
):
|
|
286
288
|
_LOG.info("TRAIN_LANGUAGE started")
|
|
287
289
|
t0_ = time.time()
|
|
288
|
-
set_random_state(random_state)
|
|
289
290
|
workspace_dir = ensure_workspace_dir(workspace_dir)
|
|
290
291
|
workspace = Workspace(workspace_dir)
|
|
291
292
|
|
|
@@ -502,6 +503,7 @@ def train(
|
|
|
502
503
|
no_of_records=trn_cnt,
|
|
503
504
|
no_of_model_params=no_of_model_params,
|
|
504
505
|
max_tokens=max_tokens,
|
|
506
|
+
model_id=model.config.model_type,
|
|
505
507
|
device=device,
|
|
506
508
|
)
|
|
507
509
|
batch_size = max(1, min(batch_size, trn_cnt))
|
|
@@ -35,7 +35,6 @@ from mostlyai.engine._common import (
|
|
|
35
35
|
SDEC_SUB_COLUMN_PREFIX,
|
|
36
36
|
ProgressCallback,
|
|
37
37
|
ProgressCallbackWrapper,
|
|
38
|
-
set_random_state,
|
|
39
38
|
)
|
|
40
39
|
from mostlyai.engine._encoding_types.tabular.categorical import encode_categorical
|
|
41
40
|
from mostlyai.engine._encoding_types.tabular.character import encode_character
|
|
@@ -45,6 +44,7 @@ from mostlyai.engine._encoding_types.tabular.lat_long import encode_latlong
|
|
|
45
44
|
from mostlyai.engine._encoding_types.tabular.numeric import encode_numeric
|
|
46
45
|
from mostlyai.engine.domain import ModelEncodingType
|
|
47
46
|
from mostlyai.engine._workspace import Workspace, ensure_workspace_dir, reset_dir
|
|
47
|
+
from mostlyai.engine.random_state import set_random_state
|
|
48
48
|
|
|
49
49
|
_LOG = logging.getLogger(__name__)
|
|
50
50
|
|
|
@@ -52,11 +52,9 @@ _LOG = logging.getLogger(__name__)
|
|
|
52
52
|
def encode(
|
|
53
53
|
workspace_dir: str | Path | None = None,
|
|
54
54
|
update_progress: ProgressCallback | None = None,
|
|
55
|
-
random_state: int | None = None,
|
|
56
55
|
) -> None:
|
|
57
56
|
_LOG.info("ENCODE_TABULAR started")
|
|
58
57
|
t0 = time.time()
|
|
59
|
-
set_random_state(random_state)
|
|
60
58
|
with ProgressCallbackWrapper(update_progress) as progress:
|
|
61
59
|
# build paths based on workspace dir
|
|
62
60
|
workspace_dir = ensure_workspace_dir(workspace_dir)
|
|
@@ -61,7 +61,6 @@ from mostlyai.engine._common import (
|
|
|
61
61
|
get_sequence_length_stats,
|
|
62
62
|
get_sub_columns_from_cardinalities,
|
|
63
63
|
is_sequential,
|
|
64
|
-
set_random_state,
|
|
65
64
|
trim_sequences,
|
|
66
65
|
get_sub_columns_nested_from_cardinalities,
|
|
67
66
|
persist_data_part,
|
|
@@ -689,11 +688,9 @@ def generate(
|
|
|
689
688
|
device: torch.device | str | None = None,
|
|
690
689
|
workspace_dir: str | Path = "engine-ws",
|
|
691
690
|
update_progress: ProgressCallback | None = None,
|
|
692
|
-
random_state: int | None = None,
|
|
693
691
|
) -> None:
|
|
694
692
|
_LOG.info("GENERATE_TABULAR started")
|
|
695
693
|
t0 = time.time()
|
|
696
|
-
set_random_state(random_state)
|
|
697
694
|
with ProgressCallbackWrapper(update_progress) as progress:
|
|
698
695
|
# build paths based on workspace dir
|
|
699
696
|
workspace_dir = ensure_workspace_dir(workspace_dir)
|
|
@@ -59,7 +59,6 @@ from mostlyai.engine._common import (
|
|
|
59
59
|
SDEC_SUB_COLUMN_PREFIX,
|
|
60
60
|
ProgressCallback,
|
|
61
61
|
ProgressCallbackWrapper,
|
|
62
|
-
set_random_state,
|
|
63
62
|
)
|
|
64
63
|
from mostlyai.engine._tabular.common import load_model_weights
|
|
65
64
|
from mostlyai.engine._training_utils import (
|
|
@@ -350,11 +349,9 @@ def train(
|
|
|
350
349
|
device: torch.device | str | None = None,
|
|
351
350
|
workspace_dir: str | Path = "engine-ws",
|
|
352
351
|
update_progress: ProgressCallback | None = None,
|
|
353
|
-
random_state: int | None = None,
|
|
354
352
|
):
|
|
355
353
|
_LOG.info("TRAIN_TABULAR started")
|
|
356
354
|
t0 = time.time()
|
|
357
|
-
set_random_state(random_state)
|
|
358
355
|
workspace_dir = ensure_workspace_dir(workspace_dir)
|
|
359
356
|
workspace = Workspace(workspace_dir)
|
|
360
357
|
with ProgressCallbackWrapper(
|
|
@@ -39,7 +39,6 @@ from mostlyai.engine._common import (
|
|
|
39
39
|
is_a_list,
|
|
40
40
|
is_sequential,
|
|
41
41
|
read_json,
|
|
42
|
-
set_random_state,
|
|
43
42
|
write_json,
|
|
44
43
|
TABLE_COLUMN_INFIX,
|
|
45
44
|
ProgressCallback,
|
|
@@ -87,6 +86,7 @@ from mostlyai.engine._workspace import (
|
|
|
87
86
|
ensure_workspace_dir,
|
|
88
87
|
reset_dir,
|
|
89
88
|
)
|
|
89
|
+
from mostlyai.engine.random_state import set_random_state
|
|
90
90
|
|
|
91
91
|
_LOG = logging.getLogger(__name__)
|
|
92
92
|
|
|
@@ -109,7 +109,6 @@ def analyze(
|
|
|
109
109
|
differential_privacy: DifferentialPrivacyConfig | None = None,
|
|
110
110
|
workspace_dir: str | Path = "engine-ws",
|
|
111
111
|
update_progress: ProgressCallback | None = None,
|
|
112
|
-
random_state: int | None = None,
|
|
113
112
|
) -> None:
|
|
114
113
|
"""
|
|
115
114
|
Generates (privacy-safe) column-level statistics of the original data, that has been `split` into the workspace.
|
|
@@ -128,7 +127,6 @@ def analyze(
|
|
|
128
127
|
|
|
129
128
|
_LOG.info("ANALYZE started")
|
|
130
129
|
t0 = time.time()
|
|
131
|
-
set_random_state(random_state)
|
|
132
130
|
with ProgressCallbackWrapper(update_progress) as progress:
|
|
133
131
|
# build paths based on workspace dir
|
|
134
132
|
workspace_dir = ensure_workspace_dir(workspace_dir)
|
|
@@ -23,7 +23,6 @@ def encode(
|
|
|
23
23
|
*,
|
|
24
24
|
workspace_dir: str | Path = "engine-ws",
|
|
25
25
|
update_progress: ProgressCallback | None = None,
|
|
26
|
-
random_state: int | None = None,
|
|
27
26
|
) -> None:
|
|
28
27
|
"""
|
|
29
28
|
Encodes data in the workspace that has already been split and analyzed.
|
|
@@ -35,14 +34,13 @@ def encode(
|
|
|
35
34
|
Args:
|
|
36
35
|
workspace_dir: Directory path for workspace.
|
|
37
36
|
update_progress: Callback for progress updates.
|
|
38
|
-
random_state: Seed for the random number generators.
|
|
39
37
|
"""
|
|
40
38
|
model_type = resolve_model_type(workspace_dir)
|
|
41
39
|
if model_type == ModelType.tabular:
|
|
42
40
|
from mostlyai.engine._tabular.encoding import encode as encode_tabular
|
|
43
41
|
|
|
44
|
-
return encode_tabular(workspace_dir=workspace_dir, update_progress=update_progress
|
|
42
|
+
return encode_tabular(workspace_dir=workspace_dir, update_progress=update_progress)
|
|
45
43
|
else:
|
|
46
44
|
from mostlyai.engine._language.encoding import encode as encode_language
|
|
47
45
|
|
|
48
|
-
return encode_language(workspace_dir=workspace_dir, update_progress=update_progress
|
|
46
|
+
return encode_language(workspace_dir=workspace_dir, update_progress=update_progress)
|
|
@@ -41,7 +41,6 @@ def generate(
|
|
|
41
41
|
fairness: FairnessConfig | dict | None = None,
|
|
42
42
|
workspace_dir: str | Path = "engine-ws",
|
|
43
43
|
update_progress: ProgressCallback | None = None,
|
|
44
|
-
random_state: int | None = None,
|
|
45
44
|
) -> None:
|
|
46
45
|
"""
|
|
47
46
|
Generates synthetic data from a trained model.
|
|
@@ -64,7 +63,6 @@ def generate(
|
|
|
64
63
|
fairness: Configuration for fairness constraints. Only applicable for tabular models.
|
|
65
64
|
workspace_dir: Directory path for workspace.
|
|
66
65
|
update_progress: Callback for progress updates.
|
|
67
|
-
random_state: Seed for the random number generators.
|
|
68
66
|
"""
|
|
69
67
|
model_type = resolve_model_type(workspace_dir)
|
|
70
68
|
if model_type == ModelType.tabular:
|
|
@@ -84,7 +82,6 @@ def generate(
|
|
|
84
82
|
device=device,
|
|
85
83
|
workspace_dir=workspace_dir,
|
|
86
84
|
update_progress=update_progress,
|
|
87
|
-
random_state=random_state,
|
|
88
85
|
)
|
|
89
86
|
else:
|
|
90
87
|
from mostlyai.engine._language.generation import generate as generate_language
|
|
@@ -106,5 +103,4 @@ def generate(
|
|
|
106
103
|
device=device,
|
|
107
104
|
workspace_dir=workspace_dir,
|
|
108
105
|
update_progress=update_progress,
|
|
109
|
-
random_state=random_state,
|
|
110
106
|
)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Copyright 2025 MOSTLY AI
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import logging
|
|
16
|
+
import os
|
|
17
|
+
import random
|
|
18
|
+
import struct
|
|
19
|
+
|
|
20
|
+
import numpy as np
|
|
21
|
+
import torch
|
|
22
|
+
|
|
23
|
+
_LOG = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def set_random_state(random_state: int | None = None, worker: bool = False):
|
|
27
|
+
def get_random_int_from_os() -> int:
|
|
28
|
+
# 32-bit, cryptographically secure random int from os
|
|
29
|
+
return int(struct.unpack("I", os.urandom(4))[0])
|
|
30
|
+
|
|
31
|
+
if worker: # worker process
|
|
32
|
+
if "MOSTLYAI_ENGINE_SEED" in os.environ:
|
|
33
|
+
random_state = int(os.environ["MOSTLYAI_ENGINE_SEED"])
|
|
34
|
+
else:
|
|
35
|
+
# don't set seed for worker process if not set in main process
|
|
36
|
+
return
|
|
37
|
+
else: # main process
|
|
38
|
+
if random_state is not None:
|
|
39
|
+
_LOG.info(f"Global random_state set to `{random_state}`")
|
|
40
|
+
|
|
41
|
+
if random_state is None:
|
|
42
|
+
random_state = get_random_int_from_os()
|
|
43
|
+
|
|
44
|
+
os.environ["MOSTLYAI_ENGINE_SEED"] = str(random_state)
|
|
45
|
+
|
|
46
|
+
random.seed(random_state)
|
|
47
|
+
np.random.seed(random_state)
|
|
48
|
+
torch.manual_seed(random_state)
|
|
49
|
+
torch.cuda.manual_seed_all(random_state)
|
|
@@ -20,7 +20,7 @@ import time
|
|
|
20
20
|
import warnings
|
|
21
21
|
from pathlib import Path
|
|
22
22
|
|
|
23
|
-
from mostlyai.engine._common import ProgressCallbackWrapper, ProgressCallback
|
|
23
|
+
from mostlyai.engine._common import ProgressCallbackWrapper, ProgressCallback
|
|
24
24
|
from mostlyai.engine._dtypes import (
|
|
25
25
|
is_date_dtype,
|
|
26
26
|
is_float_dtype,
|
|
@@ -75,10 +75,9 @@ def split(
|
|
|
75
75
|
tgt_encoding_types: dict[str, str | ModelEncodingType] | None = None,
|
|
76
76
|
ctx_encoding_types: dict[str, str | ModelEncodingType] | None = None,
|
|
77
77
|
n_partitions: int = 1,
|
|
78
|
-
trn_val_split: float = 0.
|
|
78
|
+
trn_val_split: float = 0.8,
|
|
79
79
|
workspace_dir: str | Path = "engine-ws",
|
|
80
80
|
update_progress: ProgressCallback | None = None,
|
|
81
|
-
random_state: int | None = None,
|
|
82
81
|
) -> None:
|
|
83
82
|
"""
|
|
84
83
|
Splits the provided original data into training and validation sets, and stores these as partitioned Parquet files.
|
|
@@ -105,11 +104,9 @@ def split(
|
|
|
105
104
|
trn_val_split: Fraction of data to use for training, with the remaining data used for validation.
|
|
106
105
|
workspace_dir: Path to the workspace directory where files will be created.
|
|
107
106
|
update_progress: A custom progress callback.
|
|
108
|
-
random_state: Seed for the random number generators.
|
|
109
107
|
"""
|
|
110
108
|
_LOG.info("SPLIT started")
|
|
111
109
|
t0 = time.time()
|
|
112
|
-
set_random_state(random_state)
|
|
113
110
|
with ProgressCallbackWrapper(update_progress) as progress:
|
|
114
111
|
# validate input
|
|
115
112
|
if tgt_primary_key and tgt_primary_key not in tgt_data:
|
|
@@ -38,7 +38,6 @@ def train(
|
|
|
38
38
|
workspace_dir: str | Path = "engine-ws",
|
|
39
39
|
update_progress: ProgressCallback | None = None,
|
|
40
40
|
upload_model_data_callback: Callable | None = None,
|
|
41
|
-
random_state: int | None = None,
|
|
42
41
|
) -> None:
|
|
43
42
|
"""
|
|
44
43
|
Trains a model with optional early stopping and differential privacy.
|
|
@@ -61,7 +60,6 @@ def train(
|
|
|
61
60
|
workspace_dir: Directory path for workspace. Training outputs are stored in ModelStore subdirectory.
|
|
62
61
|
update_progress: Callback function to report training progress.
|
|
63
62
|
upload_model_data_callback: Callback function to upload model data during training.
|
|
64
|
-
random_state: Seed for the random number generators.
|
|
65
63
|
"""
|
|
66
64
|
model_type = resolve_model_type(workspace_dir)
|
|
67
65
|
if model_type == ModelType.tabular:
|
|
@@ -82,7 +80,6 @@ def train(
|
|
|
82
80
|
model_state_strategy=model_state_strategy,
|
|
83
81
|
device=device,
|
|
84
82
|
max_sequence_window=max_sequence_window if max_sequence_window else args["max_sequence_window"].default,
|
|
85
|
-
random_state=random_state,
|
|
86
83
|
)
|
|
87
84
|
else:
|
|
88
85
|
from mostlyai.engine._language.training import train as train_language
|
|
@@ -104,5 +101,4 @@ def train(
|
|
|
104
101
|
upload_model_data_callback=upload_model_data_callback,
|
|
105
102
|
model_state_strategy=model_state_strategy,
|
|
106
103
|
device=device,
|
|
107
|
-
random_state=random_state,
|
|
108
104
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mostlyai-engine"
|
|
3
|
-
version = "1.4.
|
|
3
|
+
version = "1.4.2"
|
|
4
4
|
description = "Synthetic Data Engine"
|
|
5
5
|
authors = [{ name = "MOSTLY AI", email = "dev@mostly.ai" }]
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -25,7 +25,7 @@ classifiers = [
|
|
|
25
25
|
]
|
|
26
26
|
|
|
27
27
|
dependencies = [
|
|
28
|
-
"setuptools>=
|
|
28
|
+
"setuptools>=77.0.3", # similar to vllm 0.8.5.post1
|
|
29
29
|
"numpy>=1.26.3",
|
|
30
30
|
"pandas~=2.2.0",
|
|
31
31
|
"pyarrow>=16.0.0",
|
|
@@ -38,18 +38,18 @@ dependencies = [
|
|
|
38
38
|
"peft>=0.12.0",
|
|
39
39
|
"huggingface-hub[hf-xet]>=0.30.2",
|
|
40
40
|
"opacus>=1.5.2", # switch to 1.5.4 (once released) to allow numpy 2
|
|
41
|
-
"xgrammar>=0.1.
|
|
41
|
+
"xgrammar>=0.1.18", # for vllm 0.8.5.post1 compatibility
|
|
42
42
|
"json-repair>=0.30.0",
|
|
43
43
|
"torch>=2.6.0,<2.6.1",
|
|
44
|
-
"torchaudio>=2.6.0,<2.6.1", # for vllm 0.8.
|
|
45
|
-
"torchvision>=0.21.0,<0.21.1" # for vllm 0.8.
|
|
44
|
+
"torchaudio>=2.6.0,<2.6.1", # for vllm 0.8.5.post1 compatibility
|
|
45
|
+
"torchvision>=0.21.0,<0.21.1" # for vllm 0.8.5.post1 compatibility
|
|
46
46
|
]
|
|
47
47
|
|
|
48
48
|
[project.optional-dependencies]
|
|
49
49
|
gpu = [
|
|
50
|
-
"bitsandbytes
|
|
51
|
-
"bitsandbytes>=0.
|
|
52
|
-
"vllm==0.8.
|
|
50
|
+
"bitsandbytes==0.42.0; sys_platform == 'darwin'",
|
|
51
|
+
"bitsandbytes>=0.45.5; sys_platform == 'linux'",
|
|
52
|
+
"vllm==0.8.5.post1; sys_platform == 'linux' or sys_platform == 'darwin'",
|
|
53
53
|
]
|
|
54
54
|
|
|
55
55
|
[dependency-groups]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/language/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/language/datetime.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/language/numeric.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/language/text.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/tabular/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/tabular/character.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/tabular/datetime.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/tabular/itt.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/tabular/lat_long.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_encoding_types/tabular/numeric.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/engine/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/engine/hf_engine.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/engine/vllm_engine.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyai_engine-1.4.0 → mostlyai_engine-1.4.2}/mostlyai/engine/_language/tokenizer_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|