lalamo 0.3.1__py3-none-any.whl → 0.3.2__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.
lalamo/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from lalamo.model_import import REPO_TO_MODEL, ModelSpec, import_model
2
2
  from lalamo.modules import Decoder
3
3
 
4
- __version__ = "0.3.1"
4
+ __version__ = "0.3.2"
5
5
 
6
6
  __all__ = [
7
7
  "REPO_TO_MODEL",
@@ -9,12 +9,13 @@ import cattrs
9
9
  from jaxtyping import Array, DTypeLike
10
10
 
11
11
  from lalamo.modules import Decoder, DecoderConfig
12
+ from lalamo.registry_abc import RegistryABC
12
13
 
13
14
  __all__ = ["ForeignConfig"]
14
15
 
15
16
 
16
17
  @dataclass(frozen=True)
17
- class ForeignConfig:
18
+ class ForeignConfig(RegistryABC):
18
19
  _converter: ClassVar[cattrs.Converter] = cattrs.Converter()
19
20
  _converter.register_structure_hook(int | list[int], lambda v, _: v)
20
21
 
@@ -1,10 +1,13 @@
1
1
  from collections.abc import (
2
+ Callable,
2
3
  Mapping,
3
4
  )
4
5
  from dataclasses import dataclass, field
5
6
  from enum import Enum
6
7
  from pathlib import Path
8
+ from typing import ClassVar, cast, get_args, get_origin
7
9
 
10
+ import cattrs
8
11
  import jax.numpy as jnp
9
12
  from jaxtyping import Array, DTypeLike
10
13
  from safetensors.flax import load_file as load_safetensors
@@ -65,8 +68,40 @@ class ConfigMap:
65
68
  chat_template: FileSpec | None = None
66
69
 
67
70
 
71
+ def _is_foreign_config_type(t: object) -> bool:
72
+ origin = get_origin(t)
73
+ args = get_args(t)
74
+ return origin is type and len(args) == 1 and isinstance(args[0], type) and issubclass(args[0], ForeignConfig)
75
+
76
+
77
+ def _structure_foreign_config_factory(
78
+ t: object,
79
+ c: cattrs.Converter,
80
+ ) -> Callable[[object, object], type[ForeignConfig]]:
81
+ name_to_type = {t.__name__: t for t in ForeignConfig.__descendants__()}
82
+
83
+ def _hook(v: object, _t: object) -> type[ForeignConfig]:
84
+ if isinstance(v, type) and issubclass(v, ForeignConfig):
85
+ return v
86
+ return name_to_type[cast("str", v)]
87
+
88
+ return _hook
89
+
90
+
91
+ def _unstructure_foreign_config_factory(t: object, c: cattrs.Converter) -> Callable[[type[ForeignConfig]], str]:
92
+ def _hook(v: type[ForeignConfig]) -> str:
93
+ return v.__name__
94
+
95
+ return _hook
96
+
97
+
68
98
  @dataclass(frozen=True)
69
99
  class ModelSpec:
100
+ _converter: ClassVar[cattrs.Converter] = cattrs.Converter()
101
+
102
+ _converter.register_structure_hook_factory(_is_foreign_config_type, _structure_foreign_config_factory)
103
+ _converter.register_unstructure_hook_factory(_is_foreign_config_type, _unstructure_foreign_config_factory)
104
+
70
105
  vendor: str
71
106
  family: str
72
107
  name: str
@@ -83,6 +118,13 @@ class ModelSpec:
83
118
  configs: ConfigMap = field(default=ConfigMap())
84
119
  use_cases: tuple[UseCase, ...] = tuple()
85
120
 
121
+ @classmethod
122
+ def from_json(cls, json_data: dict) -> "ModelSpec":
123
+ return cls._converter.structure(json_data, cls)
124
+
125
+ def to_json(self) -> dict:
126
+ return self._converter.unstructure(self)
127
+
86
128
 
87
129
  def awq_model_spec(
88
130
  model_spec: ModelSpec,
lalamo/registry_abc.py ADDED
@@ -0,0 +1,63 @@
1
+ from abc import ABC, ABCMeta
2
+ from typing import Any
3
+ from weakref import WeakSet
4
+
5
+ __all__ = ["RegistryABC", "RegistryMeta"]
6
+
7
+
8
+ class RegistryMeta(ABCMeta):
9
+ """
10
+ Metaclass that tracks, for each subclass of RegistryABC, a per-class WeakSet
11
+ of descendants (classes that have it in their MRO) while excluding any class
12
+ that directly lists `RegistryABC` among its bases.
13
+ """
14
+
15
+ _REG_ATTR: str = "__registry_descendants__"
16
+ _ROOT: type["RegistryABC"] | None = None
17
+
18
+ def __init__(
19
+ cls: type,
20
+ name: str,
21
+ bases: tuple[type, ...],
22
+ namespace: dict[str, object],
23
+ **kwargs: Any, # noqa: ANN401
24
+ ) -> None:
25
+ super().__init__(name, bases, namespace, **kwargs) # type: ignore[call-overload]
26
+
27
+ # Give *every* class its own WeakSet (shadow any inherited attribute)
28
+ setattr(cls, RegistryMeta._REG_ATTR, WeakSet())
29
+
30
+ # Detect and remember the root exactly once
31
+ if RegistryMeta._ROOT is None and name == "RegistryABC":
32
+ RegistryMeta._ROOT = cls # type: ignore[assignment]
33
+ return
34
+
35
+ root = RegistryMeta._ROOT
36
+ if root is None:
37
+ # Extremely early import edge-case; nothing to register yet
38
+ return
39
+
40
+ # Exclude classes that directly list the root among bases
41
+ if any(b is root for b in cls.__bases__):
42
+ return
43
+
44
+ # Register this class on all qualifying ancestors below the root
45
+ for ancestor in cls.__mro__[1:]:
46
+ if isinstance(ancestor, RegistryMeta) and issubclass(ancestor, root):
47
+ getattr(ancestor, RegistryMeta._REG_ATTR).add(cls)
48
+
49
+
50
+ class RegistryABC(ABC, metaclass=RegistryMeta):
51
+ """
52
+ Abstract base tracked by RegistryMeta.
53
+
54
+ Any class defined as `class AbstractFoo(RegistryABC)` will expose a
55
+ class method `AbstractFoo.__get_descendants__()` that returns a list of
56
+ all classes having AbstractFoo in their MRO *except* those that directly
57
+ include `RegistryABC` among their bases.
58
+ """
59
+
60
+ @classmethod
61
+ def __descendants__(cls) -> tuple[type, ...]:
62
+ reg: WeakSet[type] = getattr(cls, RegistryMeta._REG_ATTR) # noqa: SLF001
63
+ return tuple(reg)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lalamo
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: JAX library for optimization and export of models for use with the UZU inference engine.
5
5
  Requires-Python: <4,>=3.12
6
6
  Description-Content-Type: text/markdown
@@ -32,7 +32,7 @@ Dynamic: license-file
32
32
  <a href="https://artifacts.trymirai.com/social/about_us.mp3"><img src="https://img.shields.io/badge/Listen-Podcast-red" alt="Listen to our podcast"></a>
33
33
  <a href="https://docsend.com/v/76bpr/mirai2025"><img src="https://img.shields.io/badge/View-Deck-red" alt="View our deck"></a>
34
34
  <a href="mailto:alexey@getmirai.co,dima@getmirai.co,aleksei@getmirai.co?subject=Interested%20in%20Mirai"><img src="https://img.shields.io/badge/Send-Email-green" alt="Contact us"></a>
35
- <a href="https://docs.trymirai.com/components/models"><img src="https://img.shields.io/badge/Read-Docs-blue" alt="Read docs"></a>
35
+ <a href="https://docs.trymirai.com/overview/lalamo"><img src="https://img.shields.io/badge/Read-Docs-blue" alt="Read docs"></a>
36
36
  [![License](https://img.shields.io/badge/License-MIT-blue)](LICENSE)
37
37
 
38
38
  # lalamo
@@ -73,3 +73,4 @@ ModelSpec(
73
73
  weights_type=WeightsType.SAFETENSORS,
74
74
  )
75
75
  ```
76
+
@@ -1,9 +1,10 @@
1
- lalamo/__init__.py,sha256=BBoNVaSUlCj5z4W_8Mo-GYkDZHVno1CmcZ370nWxDHs,217
1
+ lalamo/__init__.py,sha256=dRyzJum0gpj2OtlbbETJI0yNKvkc0-wN-dKCFoYe-k0,217
2
2
  lalamo/common.py,sha256=5NUFD26yQgOnEEk3LaQnce8n-VwJxILkEpFesHZhtQU,3820
3
3
  lalamo/language_model.py,sha256=wZGucNCPP9ReHn6fYO5TlFHTXun1QIMwaxniq9z7K5Q,10639
4
4
  lalamo/main.py,sha256=Ta3ZW-Xw3uNPEVvb2YlBOH9UhhLDV7PZjRCg6giu0ao,12275
5
5
  lalamo/message_processor.py,sha256=hxnc2ELd31VfP41sCU-WobCoW06wqZllEmIvCcyAvyo,5445
6
6
  lalamo/quantization.py,sha256=8o6ryIZLzzDYQuvBTboPfaVVdfijAKGpTxOcg3GKVD8,2752
7
+ lalamo/registry_abc.py,sha256=ENjXiD_wEH100fNjG-W5Em1L_EQ0Lf0pdRhRGvf3qZk,2197
7
8
  lalamo/sampling.py,sha256=g_dNiJyZrRqoQIiLid4cr6nRT9N5tSz3GtHr8Bt4n-E,3404
8
9
  lalamo/utils.py,sha256=Jm54CKFc6lJSggXVwF_lgiUuKEtQ55c58U-ALU6oxuk,2922
9
10
  lalamo/model_import/__init__.py,sha256=Z8pS9rbKKx1QgUy7KZtHxiNWlZhII3mdovT9d37vAxg,168
@@ -11,7 +12,7 @@ lalamo/model_import/common.py,sha256=vVCKRl9-zifMiut4lMjB5eVXOHQxw8yfD5Q7rDr153c
11
12
  lalamo/model_import/huggingface_generation_config.py,sha256=mot6VQ6ezCtEhN6VjhnvaU-nR5P5T2BuBUgpFNnWJxU,1495
12
13
  lalamo/model_import/huggingface_tokenizer_config.py,sha256=kTdgH2lle1m7zRtClO3BhgonvfZsAjeDGjPMAd1EU8E,2607
13
14
  lalamo/model_import/decoder_configs/__init__.py,sha256=Ru_lI1IjahyXZBSB5J0eWwVM6gn2ilRZW65m2sU2hMw,460
14
- lalamo/model_import/decoder_configs/common.py,sha256=OiQaYdcF2aZyUhtF6I6Wci9oIa3pyPfYSVedmzVFCuk,1792
15
+ lalamo/model_import/decoder_configs/common.py,sha256=L1oUilS4KwfnwKyWegoSZ3Tha5CqRjN6gjMhCie4Ymk,1849
15
16
  lalamo/model_import/decoder_configs/executorch.py,sha256=Kx_T-B5jumfWf9vj20We4FF0GkSkTmIYeWOss88-qYA,5266
16
17
  lalamo/model_import/decoder_configs/huggingface/__init__.py,sha256=kWHUnZDwGQCbA3Ucm-FEDr8zZ2yZ3yviPVftlNgMk30,460
17
18
  lalamo/model_import/decoder_configs/huggingface/common.py,sha256=0Q4Q4uklQkWhVBYFS_hCWmdZuEpw8Ch7jhycgbA2_NY,1899
@@ -26,7 +27,7 @@ lalamo/model_import/loaders/common.py,sha256=kkugV-bMQlN1zvGHoj3uc7z0FbXKoMtXEBT
26
27
  lalamo/model_import/loaders/executorch.py,sha256=nSvpylK8QL3nBk78P3FabLoyA87E3kv5CCpMfvuZe6Q,8886
27
28
  lalamo/model_import/loaders/huggingface.py,sha256=C0spTy9-DhQ8U7bDAyGA_i9dKgUoLR2Dv58t20KUvZs,10590
28
29
  lalamo/model_import/model_specs/__init__.py,sha256=UsKmBzNzJHVQquZxWdjGgiznnORVklE-z9Nr9Ertfqc,964
29
- lalamo/model_import/model_specs/common.py,sha256=MwyQOe1QNxX5Cw-p1Emsrx6vckG3X4Xi56RACt2oOrg,3782
30
+ lalamo/model_import/model_specs/common.py,sha256=ylW_LGQ9UpMsxlY4qxFTQVjNbbxb157zboB01rGtYzE,5201
30
31
  lalamo/model_import/model_specs/deepseek.py,sha256=Umef93_ZBuq93yYsejIRNwj3udoln1gHfrv3SK5jyMo,417
31
32
  lalamo/model_import/model_specs/gemma.py,sha256=YGWM-J7jBEL16c_LZ9F_6dgeZnf4sEPLDKngl_3FbrE,1289
32
33
  lalamo/model_import/model_specs/huggingface.py,sha256=TEkU8y95_hmUWyF-Q5hn0dE2SvXbApghAsQwhWRu4D0,431
@@ -50,9 +51,9 @@ lalamo/modules/normalization.py,sha256=YecmA0hnVVYd473FzVgxunHYA377NWMKZRfuQNB8D
50
51
  lalamo/modules/rope.py,sha256=IlL4Jz4fw6eTKXXMls1BXBAgbuB3GnP0aVB9GrF1nA8,10012
51
52
  lalamo/modules/torch_interop.py,sha256=-mujd1zI4ec2w92Hd50RtDa0K3jl6ZSnPxc5r3Fp9nU,916
52
53
  lalamo/modules/utils.py,sha256=5QTdi34kEI5jix7TfTdB0mOYZbzZUul_T1y8eWCA6lQ,262
53
- lalamo-0.3.1.dist-info/licenses/LICENSE,sha256=diHRfjSEJHD1nnEeMIfMRCjR3UERf8bT3eseD6b1ayA,1072
54
- lalamo-0.3.1.dist-info/METADATA,sha256=pkkxgoNYDIMLQuHsk4cqdaHDwBel5EQ9jWYMxF1jy40,2855
55
- lalamo-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
56
- lalamo-0.3.1.dist-info/entry_points.txt,sha256=qli7qTfnBk5WP10rOGXXEckHMtt-atJMDWd8jN89Uks,43
57
- lalamo-0.3.1.dist-info/top_level.txt,sha256=VHvWL5JN5XRG36NsN_MieJ7EwRihEOrEjyDaTdFJ-aI,7
58
- lalamo-0.3.1.dist-info/RECORD,,
54
+ lalamo-0.3.2.dist-info/licenses/LICENSE,sha256=diHRfjSEJHD1nnEeMIfMRCjR3UERf8bT3eseD6b1ayA,1072
55
+ lalamo-0.3.2.dist-info/METADATA,sha256=jsfKkDwwLTGuWZeRgFQFtWvUfWT-GUqErfhVClORnhc,2854
56
+ lalamo-0.3.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
57
+ lalamo-0.3.2.dist-info/entry_points.txt,sha256=qli7qTfnBk5WP10rOGXXEckHMtt-atJMDWd8jN89Uks,43
58
+ lalamo-0.3.2.dist-info/top_level.txt,sha256=VHvWL5JN5XRG36NsN_MieJ7EwRihEOrEjyDaTdFJ-aI,7
59
+ lalamo-0.3.2.dist-info/RECORD,,
File without changes