mostlyai-engine 1.5.6__tar.gz → 1.5.7__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.5.6 → mostlyai_engine-1.5.7}/PKG-INFO +7 -7
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/__init__.py +1 -1
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_language/engine/base.py +21 -5
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_language/engine/hf_engine.py +17 -10
- mostlyai_engine-1.5.7/mostlyai/engine/_language/engine/vllm_engine.py +174 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_language/generation.py +14 -6
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_language/lstm.py +5 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_language/training.py +3 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_tabular/training.py +3 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_training_utils.py +17 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/pyproject.toml +8 -8
- mostlyai_engine-1.5.6/mostlyai/engine/_language/engine/vllm_engine.py +0 -223
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/.gitignore +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/LICENSE +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/README.md +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_common.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_dtypes.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/__init__.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/language/__init__.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/language/categorical.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/language/datetime.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/language/numeric.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/language/text.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/tabular/__init__.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/tabular/categorical.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/tabular/character.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/tabular/datetime.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/tabular/itt.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/tabular/lat_long.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/tabular/numeric.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_language/__init__.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_language/common.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_language/encoding.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_language/engine/__init__.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_language/tokenizer_utils.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_language/xgrammar_utils.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_memory.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_tabular/__init__.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_tabular/argn.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_tabular/common.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_tabular/encoding.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_tabular/fairness.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_tabular/generation.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_workspace.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/analysis.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/domain.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/encoding.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/generation.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/logging.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/random_state.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/splitting.py +0 -0
- {mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/training.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mostlyai-engine
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.7
|
|
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
|
|
@@ -37,15 +37,15 @@ Requires-Dist: psutil<6,>=5.9.5
|
|
|
37
37
|
Requires-Dist: pyarrow>=16.0.0
|
|
38
38
|
Requires-Dist: setuptools>=77.0.3
|
|
39
39
|
Requires-Dist: tokenizers>=0.21.0
|
|
40
|
-
Requires-Dist: torch<2.
|
|
41
|
-
Requires-Dist: torchaudio<2.
|
|
42
|
-
Requires-Dist: torchvision<0.
|
|
43
|
-
Requires-Dist: transformers
|
|
44
|
-
Requires-Dist: xgrammar>=0.1.
|
|
40
|
+
Requires-Dist: torch<2.9.0,>=2.8.0
|
|
41
|
+
Requires-Dist: torchaudio<2.9.0,>=2.8.0
|
|
42
|
+
Requires-Dist: torchvision<0.24.0,>=0.23.0
|
|
43
|
+
Requires-Dist: transformers>=4.55.0
|
|
44
|
+
Requires-Dist: xgrammar>=0.1.21
|
|
45
45
|
Provides-Extra: gpu
|
|
46
46
|
Requires-Dist: bitsandbytes==0.42.0; (sys_platform == 'darwin') and extra == 'gpu'
|
|
47
47
|
Requires-Dist: bitsandbytes>=0.45.5; (sys_platform == 'linux') and extra == 'gpu'
|
|
48
|
-
Requires-Dist: vllm==0.
|
|
48
|
+
Requires-Dist: vllm==0.10.2; (sys_platform == 'linux' or sys_platform == 'darwin') and extra == 'gpu'
|
|
49
49
|
Description-Content-Type: text/markdown
|
|
50
50
|
|
|
51
51
|
# Synthetic Data Engine 💎
|
|
@@ -22,7 +22,7 @@ from mostlyai.engine.splitting import split
|
|
|
22
22
|
from mostlyai.engine.training import train
|
|
23
23
|
|
|
24
24
|
__all__ = ["split", "analyze", "encode", "train", "generate", "init_logging", "set_random_state"]
|
|
25
|
-
__version__ = "1.5.
|
|
25
|
+
__version__ = "1.5.7"
|
|
26
26
|
|
|
27
27
|
# suppress specific warning related to os.fork() in multi-threaded processes
|
|
28
28
|
warnings.filterwarnings("ignore", category=DeprecationWarning, message=".*multi-threaded.*fork.*")
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
from abc import ABC, abstractmethod
|
|
16
|
-
from collections.abc import Generator
|
|
17
16
|
from dataclasses import dataclass
|
|
18
17
|
|
|
19
18
|
from pydantic import BaseModel
|
|
@@ -26,10 +25,6 @@ class EngineMetrics:
|
|
|
26
25
|
|
|
27
26
|
|
|
28
27
|
class LanguageEngine(ABC):
|
|
29
|
-
@abstractmethod
|
|
30
|
-
def initialize_logits_processors(self, schemas: Generator[BaseModel]):
|
|
31
|
-
pass
|
|
32
|
-
|
|
33
28
|
@abstractmethod
|
|
34
29
|
def generate(
|
|
35
30
|
self, text: list[str], sampling_temperature: float, sampling_top_p: float
|
|
@@ -47,3 +42,24 @@ class LanguageEngine(ABC):
|
|
|
47
42
|
@abstractmethod
|
|
48
43
|
def cleanup(self):
|
|
49
44
|
pass
|
|
45
|
+
|
|
46
|
+
def update_json_constraints(self, schemas: list[BaseModel] | None) -> None:
|
|
47
|
+
"""Update JSON schema constraints for the next generation call.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
schemas: Schema constraints to apply to the next generate() call.
|
|
51
|
+
None to clear any existing constraints.
|
|
52
|
+
|
|
53
|
+
Default implementation does nothing.
|
|
54
|
+
Engines that support JSON constraints should override this method.
|
|
55
|
+
"""
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
def can_reuse_schemas(self) -> bool:
|
|
59
|
+
"""Whether the engine can reuse JSON schema constraints across batches with different sizes.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
True if the engine can handle variable batch sizes with reused schema constraints,
|
|
63
|
+
False if schema constraints need to be recreated for each batch.
|
|
64
|
+
"""
|
|
65
|
+
return True
|
{mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_language/engine/hf_engine.py
RENAMED
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
import time
|
|
18
|
-
from collections.abc import Generator
|
|
19
18
|
from os import PathLike
|
|
20
19
|
from pathlib import Path
|
|
21
20
|
|
|
@@ -75,15 +74,6 @@ class HuggingFaceEngine(LanguageEngine):
|
|
|
75
74
|
def supports_json_enforcing(self) -> bool:
|
|
76
75
|
return self._json_enforcing_possible
|
|
77
76
|
|
|
78
|
-
def initialize_logits_processors(self, schemas: Generator[BaseModel]):
|
|
79
|
-
compiled_grammars = create_compiled_grammars(
|
|
80
|
-
schemas=schemas,
|
|
81
|
-
tokenizer=self.tokenizer,
|
|
82
|
-
vocab_size=self._model_config.vocab_size,
|
|
83
|
-
is_peft_adapter=self.is_peft_adapter,
|
|
84
|
-
)
|
|
85
|
-
self._logits_processors = [LogitsProcessor(list(compiled_grammars))]
|
|
86
|
-
|
|
87
77
|
def generate(
|
|
88
78
|
self, text: list[str], sampling_temperature: float, sampling_top_p: float
|
|
89
79
|
) -> tuple[list[int], EngineMetrics]:
|
|
@@ -124,3 +114,20 @@ class HuggingFaceEngine(LanguageEngine):
|
|
|
124
114
|
|
|
125
115
|
def cleanup(self):
|
|
126
116
|
pass
|
|
117
|
+
|
|
118
|
+
def update_json_constraints(self, schemas: list[BaseModel] | None) -> None:
|
|
119
|
+
"""Update JSON schema constraints for the next generation call."""
|
|
120
|
+
if schemas:
|
|
121
|
+
compiled_grammars = create_compiled_grammars(
|
|
122
|
+
schemas=schemas,
|
|
123
|
+
tokenizer=self.tokenizer,
|
|
124
|
+
vocab_size=self._model_config.vocab_size,
|
|
125
|
+
is_peft_adapter=self.is_peft_adapter,
|
|
126
|
+
)
|
|
127
|
+
self._logits_processors = [LogitsProcessor(list(compiled_grammars))]
|
|
128
|
+
else:
|
|
129
|
+
self._logits_processors = None
|
|
130
|
+
|
|
131
|
+
def can_reuse_schemas(self) -> bool:
|
|
132
|
+
"""HuggingFaceEngine cannot reuse LogitsProcessor across different batch sizes."""
|
|
133
|
+
return False
|
|
@@ -0,0 +1,174 @@
|
|
|
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
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import os
|
|
18
|
+
|
|
19
|
+
os.environ["VLLM_USE_V1"] = "1"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
import time
|
|
23
|
+
from os import PathLike
|
|
24
|
+
|
|
25
|
+
import torch
|
|
26
|
+
from peft import PeftConfig
|
|
27
|
+
from pydantic import BaseModel
|
|
28
|
+
from transformers import AutoConfig, AutoTokenizer
|
|
29
|
+
from vllm import LLM, SamplingParams
|
|
30
|
+
from vllm.config import _get_and_verify_max_len
|
|
31
|
+
from vllm.distributed import cleanup_dist_env_and_memory
|
|
32
|
+
from vllm.inputs.data import TokensPrompt
|
|
33
|
+
from vllm.lora.request import LoRARequest
|
|
34
|
+
from vllm.sampling_params import GuidedDecodingParams
|
|
35
|
+
|
|
36
|
+
from mostlyai.engine._language.common import is_bf16_supported
|
|
37
|
+
from mostlyai.engine._language.engine.base import EngineMetrics, LanguageEngine
|
|
38
|
+
from mostlyai.engine._language.tokenizer_utils import tokenize_fn
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def get_dynamic_gpu_memory_utilization(utilization_ratio: float = 0.9) -> float:
|
|
42
|
+
"""
|
|
43
|
+
Calculate dynamic GPU memory utilization based on available memory.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
utilization_ratio: Fraction of available GPU memory to use (default: 0.9)
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
GPU memory utilization as a fraction.
|
|
50
|
+
"""
|
|
51
|
+
if not torch.cuda.is_available():
|
|
52
|
+
return utilization_ratio # fallback for non-GPU environments
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
# Get free and total memory from CUDA
|
|
56
|
+
free_memory, total_memory = torch.cuda.mem_get_info()
|
|
57
|
+
|
|
58
|
+
# Use specified ratio of free memory
|
|
59
|
+
target_memory = free_memory * utilization_ratio
|
|
60
|
+
utilization = target_memory / total_memory
|
|
61
|
+
|
|
62
|
+
# Ensure utilization is within reasonable bounds (0.1 to 0.95)
|
|
63
|
+
return max(0.1, min(0.95, utilization))
|
|
64
|
+
|
|
65
|
+
except Exception:
|
|
66
|
+
# Fallback to provided ratio if anything goes wrong
|
|
67
|
+
return utilization_ratio
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class VLLMEngine(LanguageEngine):
|
|
71
|
+
def __init__(
|
|
72
|
+
self, model_path: PathLike | str, device: torch.device, max_new_tokens: int, tokenizer_max_length: int
|
|
73
|
+
):
|
|
74
|
+
self.device = device
|
|
75
|
+
self.tokenizer_max_length = tokenizer_max_length
|
|
76
|
+
self.max_new_tokens = max_new_tokens
|
|
77
|
+
|
|
78
|
+
peft_config = PeftConfig.from_pretrained(model_path)
|
|
79
|
+
base_config = AutoConfig.from_pretrained(peft_config.base_model_name_or_path)
|
|
80
|
+
|
|
81
|
+
model_path = str(model_path)
|
|
82
|
+
self._lora_request = LoRARequest("adapter", 1, model_path)
|
|
83
|
+
config_max_model_len = _get_and_verify_max_len(
|
|
84
|
+
base_config, tokenizer_config=None, max_model_len=None, disable_sliding_window=False, sliding_window=None
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
self.llm = LLM(
|
|
88
|
+
model=peft_config.base_model_name_or_path,
|
|
89
|
+
tokenizer=model_path,
|
|
90
|
+
max_model_len=min(config_max_model_len, self.tokenizer_max_length + max_new_tokens),
|
|
91
|
+
enable_lora=True,
|
|
92
|
+
dtype=torch.bfloat16 if is_bf16_supported(device) else torch.float16,
|
|
93
|
+
# enforce_eager=True, # results in big slowdown, but is needed when running pytest locally
|
|
94
|
+
swap_space=0,
|
|
95
|
+
disable_log_stats=True,
|
|
96
|
+
tensor_parallel_size=torch.cuda.device_count(),
|
|
97
|
+
gpu_memory_utilization=get_dynamic_gpu_memory_utilization(),
|
|
98
|
+
)
|
|
99
|
+
self.tokenizer = AutoTokenizer.from_pretrained(
|
|
100
|
+
model_path,
|
|
101
|
+
padding_side="left",
|
|
102
|
+
truncation_side="left",
|
|
103
|
+
legacy=True,
|
|
104
|
+
# these must be False at initialization, as we manually add them later in tokenize_fn
|
|
105
|
+
add_bos_token=False,
|
|
106
|
+
add_eos_token=False,
|
|
107
|
+
)
|
|
108
|
+
self._prepared_schemas = None
|
|
109
|
+
|
|
110
|
+
def get_default_batch_size(self) -> int:
|
|
111
|
+
return 192
|
|
112
|
+
|
|
113
|
+
def supports_json_enforcing(self) -> bool:
|
|
114
|
+
return True
|
|
115
|
+
|
|
116
|
+
def generate(
|
|
117
|
+
self, text: list[str], sampling_temperature: float, sampling_top_p: float
|
|
118
|
+
) -> tuple[list[int], EngineMetrics]:
|
|
119
|
+
tokenize_kwargs = dict(
|
|
120
|
+
tokenizer=self.tokenizer,
|
|
121
|
+
return_tensors=None,
|
|
122
|
+
add_bos_token=True,
|
|
123
|
+
add_eos_token=False,
|
|
124
|
+
padding=False,
|
|
125
|
+
truncation=True,
|
|
126
|
+
max_length=self.tokenizer_max_length, # truncates input
|
|
127
|
+
)
|
|
128
|
+
t_tokenize = time.time()
|
|
129
|
+
inputs = tokenize_fn(text=text, **tokenize_kwargs)
|
|
130
|
+
tokenize_time = time.time() - t_tokenize
|
|
131
|
+
|
|
132
|
+
actual_batch_size = len(inputs["input_ids"])
|
|
133
|
+
|
|
134
|
+
# Create sampling params with guided decoding if schemas are prepared
|
|
135
|
+
effective_schemas = self._prepared_schemas
|
|
136
|
+
|
|
137
|
+
sampling_params = []
|
|
138
|
+
for i in range(actual_batch_size):
|
|
139
|
+
guided_decoding = None
|
|
140
|
+
if effective_schemas and i < len(effective_schemas):
|
|
141
|
+
# Convert Pydantic model to JSON schema for guided decoding
|
|
142
|
+
schema_dict = effective_schemas[i].model_json_schema()
|
|
143
|
+
guided_decoding = GuidedDecodingParams(json=schema_dict)
|
|
144
|
+
|
|
145
|
+
sampling_params.append(
|
|
146
|
+
SamplingParams(
|
|
147
|
+
max_tokens=self.max_new_tokens,
|
|
148
|
+
temperature=sampling_temperature,
|
|
149
|
+
top_p=sampling_top_p,
|
|
150
|
+
guided_decoding=guided_decoding,
|
|
151
|
+
)
|
|
152
|
+
)
|
|
153
|
+
t_generate = time.time()
|
|
154
|
+
outputs = self.llm.generate(
|
|
155
|
+
prompts=[TokensPrompt(prompt_token_ids=token_ids) for token_ids in inputs["input_ids"]],
|
|
156
|
+
sampling_params=sampling_params,
|
|
157
|
+
use_tqdm=False,
|
|
158
|
+
lora_request=self._lora_request,
|
|
159
|
+
)
|
|
160
|
+
generate_time = time.time() - t_generate
|
|
161
|
+
metrics = EngineMetrics(tokenize_time=tokenize_time, generate_time=generate_time)
|
|
162
|
+
return [r.outputs[0].token_ids for r in outputs], metrics
|
|
163
|
+
|
|
164
|
+
def cleanup(self):
|
|
165
|
+
del self.llm
|
|
166
|
+
cleanup_dist_env_and_memory()
|
|
167
|
+
|
|
168
|
+
def update_json_constraints(self, schemas: list[BaseModel] | None) -> None:
|
|
169
|
+
"""Update JSON schema constraints for the next generation call."""
|
|
170
|
+
self._prepared_schemas = list(schemas) if schemas else None
|
|
171
|
+
|
|
172
|
+
def can_reuse_schemas(self) -> bool:
|
|
173
|
+
"""VLLMEngine can handle variable batch sizes since it creates sampling params per sample."""
|
|
174
|
+
return True
|
|
@@ -287,15 +287,18 @@ def generate(
|
|
|
287
287
|
enforce_json_output = engine.supports_json_enforcing()
|
|
288
288
|
_LOG.info(f"{enforce_json_output=}")
|
|
289
289
|
|
|
290
|
-
|
|
291
|
-
|
|
290
|
+
# Check if we can optimize by reusing schemas/constraints across batches
|
|
291
|
+
can_reuse_schemas = len(seeded_tgt_columns) == 0 and engine.can_reuse_schemas()
|
|
292
|
+
|
|
293
|
+
# Prepare schemas once if optimization is possible
|
|
294
|
+
if enforce_json_output and can_reuse_schemas:
|
|
292
295
|
t0 = time.time()
|
|
293
|
-
|
|
296
|
+
schemas_for_optimization = create_schemas(
|
|
294
297
|
size=batch_size,
|
|
295
298
|
stats=tgt_stats,
|
|
296
299
|
rare_category_replacement_method=rare_category_replacement_method,
|
|
297
300
|
)
|
|
298
|
-
engine.
|
|
301
|
+
engine.update_json_constraints(schemas_for_optimization)
|
|
299
302
|
total_logits_processor_build_time += time.time() - t0
|
|
300
303
|
|
|
301
304
|
# keep at most 500k samples in memory before decoding and writing to disk
|
|
@@ -309,16 +312,21 @@ def generate(
|
|
|
309
312
|
ctx_batch = ctx_data.iloc[samples_processed : samples_processed + batch_size]
|
|
310
313
|
ctx_keys = ctx_batch[ctx_primary_key]
|
|
311
314
|
|
|
312
|
-
if
|
|
315
|
+
# Update JSON constraints if needed per-batch (when schema reuse is not possible)
|
|
316
|
+
if enforce_json_output and not can_reuse_schemas:
|
|
313
317
|
t0 = time.time()
|
|
314
318
|
schemas = create_schemas(
|
|
315
319
|
seed_df=seed_data_batch,
|
|
316
320
|
stats=tgt_stats,
|
|
317
321
|
rare_category_replacement_method=rare_category_replacement_method,
|
|
318
322
|
)
|
|
319
|
-
engine.
|
|
323
|
+
engine.update_json_constraints(schemas)
|
|
320
324
|
total_logits_processor_build_time += time.time() - t0
|
|
325
|
+
elif not enforce_json_output:
|
|
326
|
+
# Clear any existing constraints if JSON enforcement is disabled
|
|
327
|
+
engine.update_json_constraints(None)
|
|
321
328
|
|
|
329
|
+
# Generate outputs using single generate method
|
|
322
330
|
outputs, metrics = engine.generate(
|
|
323
331
|
encoded_ctx_batch["ctx"].tolist(),
|
|
324
332
|
sampling_temperature=sampling_temperature,
|
|
@@ -25,6 +25,11 @@ _LOG = logging.getLogger(__name__)
|
|
|
25
25
|
class LSTMFromScratchConfig(PretrainedConfig):
|
|
26
26
|
model_type = model_id = "MOSTLY_AI/LSTMFromScratch-3m"
|
|
27
27
|
|
|
28
|
+
# Map standard transformer attributes to our custom LSTM attributes
|
|
29
|
+
attribute_map = {
|
|
30
|
+
"num_hidden_layers": "num_layers",
|
|
31
|
+
}
|
|
32
|
+
|
|
28
33
|
def __init__(
|
|
29
34
|
self,
|
|
30
35
|
vocab_size: int | None = None,
|
|
@@ -63,6 +63,7 @@ from mostlyai.engine._training_utils import (
|
|
|
63
63
|
ModelCheckpoint,
|
|
64
64
|
ProgressMessage,
|
|
65
65
|
check_early_training_exit,
|
|
66
|
+
gpu_memory_cleanup,
|
|
66
67
|
)
|
|
67
68
|
from mostlyai.engine._workspace import Workspace, ensure_workspace_dir
|
|
68
69
|
from mostlyai.engine.domain import DifferentialPrivacyConfig, ModelStateStrategy
|
|
@@ -277,6 +278,7 @@ def _gpu_estimate_max_batch_size(
|
|
|
277
278
|
return batch_size
|
|
278
279
|
|
|
279
280
|
|
|
281
|
+
@gpu_memory_cleanup
|
|
280
282
|
def train(
|
|
281
283
|
*,
|
|
282
284
|
model: str = "MOSTLY_AI/LSTMFromScratch-3m",
|
|
@@ -865,4 +867,5 @@ def train(
|
|
|
865
867
|
)
|
|
866
868
|
# ensure everything gets uploaded
|
|
867
869
|
upload_model_data_callback()
|
|
870
|
+
|
|
868
871
|
_LOG.info(f"TRAIN_LANGUAGE finished in {time.time() - t0_:.2f}s")
|
|
@@ -63,6 +63,7 @@ from mostlyai.engine._training_utils import (
|
|
|
63
63
|
ModelCheckpoint,
|
|
64
64
|
ProgressMessage,
|
|
65
65
|
check_early_training_exit,
|
|
66
|
+
gpu_memory_cleanup,
|
|
66
67
|
)
|
|
67
68
|
from mostlyai.engine._workspace import Workspace, ensure_workspace_dir
|
|
68
69
|
from mostlyai.engine.domain import DifferentialPrivacyConfig, ModelStateStrategy
|
|
@@ -337,6 +338,7 @@ def _calculate_average_trn_loss(trn_sample_losses: list[torch.Tensor], n: int |
|
|
|
337
338
|
################
|
|
338
339
|
|
|
339
340
|
|
|
341
|
+
@gpu_memory_cleanup
|
|
340
342
|
def train(
|
|
341
343
|
*,
|
|
342
344
|
model: str = "MOSTLY_AI/Medium",
|
|
@@ -867,4 +869,5 @@ def train(
|
|
|
867
869
|
progress.update(completed=steps, total=steps, message=progress_message)
|
|
868
870
|
# ensure everything gets uploaded
|
|
869
871
|
upload_model_data_callback()
|
|
872
|
+
|
|
870
873
|
_LOG.info(f"TRAIN_TABULAR finished in {time.time() - t0:.2f}s")
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import abc
|
|
16
|
+
import functools
|
|
17
|
+
import gc
|
|
16
18
|
import logging
|
|
17
19
|
import time
|
|
18
20
|
|
|
@@ -157,3 +159,18 @@ def check_early_training_exit(workspace: Workspace, trn_cnt: int, val_cnt: int)
|
|
|
157
159
|
trn_files = workspace.encoded_data_trn.fetch_all()
|
|
158
160
|
val_files = workspace.encoded_data_val.fetch_all()
|
|
159
161
|
return any((len(trn_files) == 0, len(val_files) == 0, trn_cnt == 0, val_cnt == 0))
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def gpu_memory_cleanup(func):
|
|
165
|
+
"""Decorator to clean up GPU memory after function execution."""
|
|
166
|
+
|
|
167
|
+
@functools.wraps(func)
|
|
168
|
+
def wrapper(*args, **kwargs):
|
|
169
|
+
try:
|
|
170
|
+
return func(*args, **kwargs)
|
|
171
|
+
finally:
|
|
172
|
+
for _ in range(5):
|
|
173
|
+
gc.collect()
|
|
174
|
+
torch.cuda.empty_cache()
|
|
175
|
+
|
|
176
|
+
return wrapper
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mostlyai-engine"
|
|
3
|
-
version = "1.5.
|
|
3
|
+
version = "1.5.7"
|
|
4
4
|
description = "Synthetic Data Engine"
|
|
5
5
|
authors = [{ name = "MOSTLY AI", email = "dev@mostly.ai" }]
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -25,31 +25,31 @@ classifiers = [
|
|
|
25
25
|
]
|
|
26
26
|
|
|
27
27
|
dependencies = [
|
|
28
|
-
"setuptools>=77.0.3", # similar to vllm 0.
|
|
28
|
+
"setuptools>=77.0.3", # similar to vllm 0.10.1.1
|
|
29
29
|
"numpy>=2.0.0",
|
|
30
30
|
"pandas~=2.2.0",
|
|
31
31
|
"pyarrow>=16.0.0",
|
|
32
32
|
"joblib>=1.4.2",
|
|
33
33
|
"psutil>=5.9.5,<6", # upgrade when colab psutil is updated
|
|
34
34
|
"tokenizers>=0.21.0",
|
|
35
|
-
"transformers>=4.
|
|
35
|
+
"transformers>=4.55.0", # updated (removed ,<4.54.0), similar to vllm 0.10.1.1
|
|
36
36
|
"datasets>=3.0.0",
|
|
37
37
|
"accelerate>=1.5.0",
|
|
38
38
|
"peft>=0.12.0",
|
|
39
39
|
"huggingface-hub[hf-xet]>=0.30.2",
|
|
40
40
|
"opacus>=1.5.4",
|
|
41
|
-
"xgrammar>=0.1.
|
|
41
|
+
"xgrammar>=0.1.21", # for vllm 0.10.1.1 compatibility (=0.1.21)
|
|
42
42
|
"json-repair>=0.47.0",
|
|
43
|
-
"torch>=2.
|
|
44
|
-
"torchaudio>=2.
|
|
45
|
-
"torchvision>=0.
|
|
43
|
+
"torch>=2.8.0,<2.9.0", # for vllm 0.10.2 compatibility
|
|
44
|
+
"torchaudio>=2.8.0,<2.9.0", # for vllm 0.10.2 compatibility
|
|
45
|
+
"torchvision>=0.23.0,<0.24.0" # for vllm 0.10.2 compatibility
|
|
46
46
|
]
|
|
47
47
|
|
|
48
48
|
[project.optional-dependencies]
|
|
49
49
|
gpu = [
|
|
50
50
|
"bitsandbytes==0.42.0; sys_platform == 'darwin'",
|
|
51
51
|
"bitsandbytes>=0.45.5; sys_platform == 'linux'",
|
|
52
|
-
"vllm==0.
|
|
52
|
+
"vllm==0.10.2; sys_platform == 'linux' or sys_platform == 'darwin'",
|
|
53
53
|
]
|
|
54
54
|
|
|
55
55
|
[dependency-groups]
|
|
@@ -1,223 +0,0 @@
|
|
|
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
|
-
from __future__ import annotations
|
|
16
|
-
|
|
17
|
-
import os
|
|
18
|
-
|
|
19
|
-
# Per-Request Logits Processors are not supported in V1 (https://docs.vllm.ai/en/latest/getting_started/v1_user_guide.html#feature-model)
|
|
20
|
-
# Global Logits Processors will be new mechanism to use, but it is not yet released
|
|
21
|
-
# Here is PR for it: https://github.com/vllm-project/vllm/pull/13360
|
|
22
|
-
os.environ["VLLM_USE_V1"] = "0"
|
|
23
|
-
|
|
24
|
-
import contextlib
|
|
25
|
-
import gc
|
|
26
|
-
import time
|
|
27
|
-
from collections.abc import Generator
|
|
28
|
-
from os import PathLike
|
|
29
|
-
|
|
30
|
-
import torch
|
|
31
|
-
import xgrammar as xgr
|
|
32
|
-
from peft import PeftConfig
|
|
33
|
-
from pydantic import BaseModel
|
|
34
|
-
from transformers import AutoConfig, AutoTokenizer
|
|
35
|
-
from vllm import LLM, SamplingParams
|
|
36
|
-
from vllm.config import _get_and_verify_max_len
|
|
37
|
-
from vllm.distributed import destroy_distributed_environment, destroy_model_parallel
|
|
38
|
-
from vllm.lora.request import LoRARequest
|
|
39
|
-
from vllm.platforms import current_platform
|
|
40
|
-
|
|
41
|
-
from mostlyai.engine._language.common import is_bf16_supported
|
|
42
|
-
from mostlyai.engine._language.engine.base import EngineMetrics, LanguageEngine
|
|
43
|
-
from mostlyai.engine._language.tokenizer_utils import tokenize_fn
|
|
44
|
-
from mostlyai.engine._language.xgrammar_utils import create_compiled_grammars
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def cleanup_dist_env_and_memory():
|
|
48
|
-
"""Copy from current main of vllm replace by import when possible"""
|
|
49
|
-
destroy_model_parallel()
|
|
50
|
-
destroy_distributed_environment()
|
|
51
|
-
with contextlib.suppress(AssertionError):
|
|
52
|
-
torch.distributed.destroy_process_group()
|
|
53
|
-
gc.collect()
|
|
54
|
-
if not current_platform.is_cpu():
|
|
55
|
-
torch.cuda.empty_cache()
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class XGrammarLogitsProcessor:
|
|
59
|
-
"""
|
|
60
|
-
Inspired by [XGrammarLogitsProcessor](https://github.com/vllm-project/vllm/blob/a43aa183dc0cb2639044c15d272e0ce1941392b0/vllm/model_executor/guided_decoding/xgrammar_decoding.py#L280).
|
|
61
|
-
VLLM's XGrammarLogitsProcessor can be reused.
|
|
62
|
-
"""
|
|
63
|
-
|
|
64
|
-
def __init__(self, compiled_grammar: xgr.CompiledGrammar):
|
|
65
|
-
self.compiled_grammar = compiled_grammar
|
|
66
|
-
self.tokenizer_info = compiled_grammar.tokenizer_info
|
|
67
|
-
self.batch_size = 1
|
|
68
|
-
|
|
69
|
-
self.matchers: list[xgr.GrammarMatcher] | None = None
|
|
70
|
-
self.token_bitmask: torch.Tensor | None = None
|
|
71
|
-
self.prefilled = False
|
|
72
|
-
|
|
73
|
-
def __call__(self, input_ids: tuple[int], scores: torch.Tensor) -> torch.Tensor:
|
|
74
|
-
# lazily initialize GrammarMatchers and bitmask
|
|
75
|
-
if self.matchers is None:
|
|
76
|
-
self.matchers = [xgr.GrammarMatcher(self.compiled_grammar) for _ in range(self.batch_size)]
|
|
77
|
-
self.token_bitmask = xgr.allocate_token_bitmask(self.batch_size, self.tokenizer_info.vocab_size)
|
|
78
|
-
|
|
79
|
-
if not self.prefilled:
|
|
80
|
-
# have not sampled a token yet
|
|
81
|
-
self.prefilled = True
|
|
82
|
-
else:
|
|
83
|
-
for i, matcher in enumerate(self.matchers):
|
|
84
|
-
if not matcher.is_terminated():
|
|
85
|
-
sampled_token = input_ids[-1]
|
|
86
|
-
assert self.matchers[i].accept_token(sampled_token)
|
|
87
|
-
|
|
88
|
-
for i, matcher in enumerate(self.matchers):
|
|
89
|
-
if not matcher.is_terminated():
|
|
90
|
-
matcher.fill_next_token_bitmask(self.token_bitmask, i)
|
|
91
|
-
|
|
92
|
-
# token_bitmask is a CPU tensor for use with accept_token and
|
|
93
|
-
# fill_next_token_bitmask so we move it to the device of scores
|
|
94
|
-
device_type = scores.device.type
|
|
95
|
-
dtype = scores.dtype
|
|
96
|
-
if device_type != "cuda":
|
|
97
|
-
# xgrammar on cpu only supports float32 scores
|
|
98
|
-
# see: https://github.com/mlc-ai/xgrammar/blob/c1b64920cad24f44f235778c1c00bb52d57da01a/python/xgrammar/kernels/apply_token_bitmask_inplace_cpu.py#L22
|
|
99
|
-
scores = scores.to("cpu").float().unsqueeze(0)
|
|
100
|
-
|
|
101
|
-
# Note: In this method, if the tensors have different dimensions
|
|
102
|
-
# on CPU device fails, but on GPU it runs without error. Hence the
|
|
103
|
-
# unsqueeze above for scores, to match the token bitmask shape
|
|
104
|
-
xgr.apply_token_bitmask_inplace(scores, self.token_bitmask.to(scores.device, non_blocking=True))
|
|
105
|
-
if device_type != "cuda":
|
|
106
|
-
scores = scores.to(dtype).to(device_type).squeeze()
|
|
107
|
-
return scores
|
|
108
|
-
|
|
109
|
-
def clone(self) -> XGrammarLogitsProcessor:
|
|
110
|
-
"""Create a new instance with shared compiled grammar but separate state"""
|
|
111
|
-
new_processor = XGrammarLogitsProcessor(self.compiled_grammar)
|
|
112
|
-
|
|
113
|
-
# create fresh matchers for the new sequence
|
|
114
|
-
if self.matchers is not None:
|
|
115
|
-
new_processor.matchers = [xgr.GrammarMatcher(self.compiled_grammar) for _ in range(self.batch_size)]
|
|
116
|
-
|
|
117
|
-
# create a new token bitmask with the same size
|
|
118
|
-
if self.token_bitmask is not None:
|
|
119
|
-
new_processor.token_bitmask = self.token_bitmask
|
|
120
|
-
|
|
121
|
-
new_processor.batch_size = self.batch_size
|
|
122
|
-
|
|
123
|
-
# reset prefilled state for new sequence
|
|
124
|
-
new_processor.prefilled = False
|
|
125
|
-
|
|
126
|
-
return new_processor
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
class VLLMEngine(LanguageEngine):
|
|
130
|
-
def __init__(
|
|
131
|
-
self, model_path: PathLike | str, device: torch.device, max_new_tokens: int, tokenizer_max_length: int
|
|
132
|
-
):
|
|
133
|
-
self.device = device
|
|
134
|
-
self.tokenizer_max_length = tokenizer_max_length
|
|
135
|
-
self.max_new_tokens = max_new_tokens
|
|
136
|
-
|
|
137
|
-
peft_config = PeftConfig.from_pretrained(model_path)
|
|
138
|
-
base_config = AutoConfig.from_pretrained(peft_config.base_model_name_or_path)
|
|
139
|
-
|
|
140
|
-
model_path = str(model_path)
|
|
141
|
-
self._lora_request = LoRARequest("adapter", 1, model_path)
|
|
142
|
-
config_max_model_len = _get_and_verify_max_len(
|
|
143
|
-
base_config, max_model_len=None, disable_sliding_window=None, sliding_window_len=None
|
|
144
|
-
)
|
|
145
|
-
self.llm = LLM(
|
|
146
|
-
model=peft_config.base_model_name_or_path,
|
|
147
|
-
tokenizer=model_path,
|
|
148
|
-
device=device.type,
|
|
149
|
-
max_model_len=min(config_max_model_len, self.tokenizer_max_length + max_new_tokens),
|
|
150
|
-
enable_lora=True,
|
|
151
|
-
dtype=torch.bfloat16 if is_bf16_supported(device) else torch.float16,
|
|
152
|
-
# enforce_eager=True, # results in big slowdown, but is needed when running pytest locally
|
|
153
|
-
swap_space=0,
|
|
154
|
-
disable_log_stats=True,
|
|
155
|
-
tensor_parallel_size=torch.cuda.device_count(),
|
|
156
|
-
)
|
|
157
|
-
self.tokenizer = AutoTokenizer.from_pretrained(
|
|
158
|
-
model_path,
|
|
159
|
-
padding_side="left",
|
|
160
|
-
truncation_side="left",
|
|
161
|
-
legacy=True,
|
|
162
|
-
# these must be False at initialization, as we manually add them later in tokenize_fn
|
|
163
|
-
add_bos_token=False,
|
|
164
|
-
add_eos_token=False,
|
|
165
|
-
)
|
|
166
|
-
self._logits_processors = None
|
|
167
|
-
|
|
168
|
-
def get_default_batch_size(self) -> int:
|
|
169
|
-
return 192
|
|
170
|
-
|
|
171
|
-
def supports_json_enforcing(self) -> bool:
|
|
172
|
-
return True
|
|
173
|
-
|
|
174
|
-
def initialize_logits_processors(self, schemas: Generator[BaseModel]):
|
|
175
|
-
compiled_grammars = create_compiled_grammars(
|
|
176
|
-
schemas=schemas,
|
|
177
|
-
tokenizer=self.llm.get_tokenizer(),
|
|
178
|
-
vocab_size=self.llm.llm_engine.get_model_config().get_vocab_size(),
|
|
179
|
-
is_peft_adapter=True,
|
|
180
|
-
)
|
|
181
|
-
self._logits_processors = [XGrammarLogitsProcessor(compiled_grammar) for compiled_grammar in compiled_grammars]
|
|
182
|
-
|
|
183
|
-
def generate(
|
|
184
|
-
self, text: list[str], sampling_temperature: float, sampling_top_p: float
|
|
185
|
-
) -> tuple[list[int], EngineMetrics]:
|
|
186
|
-
tokenize_kwargs = dict(
|
|
187
|
-
tokenizer=self.tokenizer,
|
|
188
|
-
return_tensors=None,
|
|
189
|
-
add_bos_token=True,
|
|
190
|
-
add_eos_token=False,
|
|
191
|
-
padding=False,
|
|
192
|
-
truncation=True,
|
|
193
|
-
max_length=self.tokenizer_max_length, # truncates input
|
|
194
|
-
)
|
|
195
|
-
t_tokenize = time.time()
|
|
196
|
-
inputs = tokenize_fn(text=text, **tokenize_kwargs)
|
|
197
|
-
tokenize_time = time.time() - t_tokenize
|
|
198
|
-
|
|
199
|
-
actual_batch_size = len(inputs["input_ids"])
|
|
200
|
-
sampling_params = [
|
|
201
|
-
SamplingParams(
|
|
202
|
-
max_tokens=self.max_new_tokens,
|
|
203
|
-
temperature=sampling_temperature,
|
|
204
|
-
top_p=sampling_top_p,
|
|
205
|
-
logits_processors=[lp],
|
|
206
|
-
)
|
|
207
|
-
for lp in self._logits_processors[:actual_batch_size]
|
|
208
|
-
]
|
|
209
|
-
t_generate = time.time()
|
|
210
|
-
outputs = self.llm.generate(
|
|
211
|
-
prompts=None,
|
|
212
|
-
prompt_token_ids=inputs["input_ids"],
|
|
213
|
-
sampling_params=sampling_params,
|
|
214
|
-
use_tqdm=False,
|
|
215
|
-
lora_request=self._lora_request,
|
|
216
|
-
)
|
|
217
|
-
generate_time = time.time() - t_generate
|
|
218
|
-
metrics = EngineMetrics(tokenize_time=tokenize_time, generate_time=generate_time)
|
|
219
|
-
return [r.outputs[0].token_ids for r in outputs], metrics
|
|
220
|
-
|
|
221
|
-
def cleanup(self):
|
|
222
|
-
del self.llm
|
|
223
|
-
cleanup_dist_env_and_memory()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/language/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/language/datetime.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/language/numeric.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/language/text.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/tabular/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/tabular/character.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/tabular/datetime.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/tabular/itt.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/tabular/lat_long.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_encoding_types/tabular/numeric.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/mostlyai/engine/_language/engine/__init__.py
RENAMED
|
File without changes
|
{mostlyai_engine-1.5.6 → mostlyai_engine-1.5.7}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|