maxframe 2.2.0__cp38-cp38-macosx_10_9_universal2.whl → 2.3.0rc1__cp38-cp38-macosx_10_9_universal2.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.

Potentially problematic release.


This version of maxframe might be problematic. Click here for more details.

Files changed (114) hide show
  1. maxframe/_utils.cpython-38-darwin.so +0 -0
  2. maxframe/codegen/core.py +3 -2
  3. maxframe/codegen/spe/dataframe/merge.py +4 -0
  4. maxframe/codegen/spe/dataframe/misc.py +2 -0
  5. maxframe/codegen/spe/dataframe/reduction.py +18 -0
  6. maxframe/codegen/spe/dataframe/sort.py +9 -1
  7. maxframe/codegen/spe/dataframe/tests/test_reduction.py +13 -0
  8. maxframe/codegen/spe/dataframe/tseries.py +9 -0
  9. maxframe/codegen/spe/learn/contrib/lightgbm.py +4 -3
  10. maxframe/codegen/spe/tensor/datasource.py +1 -0
  11. maxframe/config/config.py +3 -0
  12. maxframe/conftest.py +10 -0
  13. maxframe/core/base.py +2 -1
  14. maxframe/core/entity/tileables.py +2 -0
  15. maxframe/core/graph/core.cpython-38-darwin.so +0 -0
  16. maxframe/core/graph/entity.py +7 -1
  17. maxframe/core/mode.py +6 -1
  18. maxframe/dataframe/__init__.py +2 -2
  19. maxframe/dataframe/arithmetic/__init__.py +4 -0
  20. maxframe/dataframe/arithmetic/maximum.py +33 -0
  21. maxframe/dataframe/arithmetic/minimum.py +33 -0
  22. maxframe/dataframe/core.py +98 -106
  23. maxframe/dataframe/datasource/core.py +6 -0
  24. maxframe/dataframe/datasource/direct.py +57 -0
  25. maxframe/dataframe/datasource/read_csv.py +19 -11
  26. maxframe/dataframe/datasource/read_odps_query.py +29 -6
  27. maxframe/dataframe/datasource/read_odps_table.py +32 -10
  28. maxframe/dataframe/datasource/read_parquet.py +38 -39
  29. maxframe/dataframe/datastore/__init__.py +6 -0
  30. maxframe/dataframe/datastore/direct.py +268 -0
  31. maxframe/dataframe/datastore/to_odps.py +6 -0
  32. maxframe/dataframe/extensions/flatjson.py +2 -1
  33. maxframe/dataframe/groupby/__init__.py +5 -1
  34. maxframe/dataframe/groupby/aggregation.py +10 -6
  35. maxframe/dataframe/groupby/apply_chunk.py +1 -3
  36. maxframe/dataframe/groupby/core.py +20 -4
  37. maxframe/dataframe/indexing/__init__.py +2 -1
  38. maxframe/dataframe/indexing/insert.py +45 -17
  39. maxframe/dataframe/merge/__init__.py +3 -0
  40. maxframe/dataframe/merge/combine.py +244 -0
  41. maxframe/dataframe/misc/__init__.py +14 -3
  42. maxframe/dataframe/misc/check_unique.py +41 -10
  43. maxframe/dataframe/misc/drop.py +31 -0
  44. maxframe/dataframe/misc/infer_dtypes.py +251 -0
  45. maxframe/dataframe/misc/map.py +31 -18
  46. maxframe/dataframe/misc/repeat.py +159 -0
  47. maxframe/dataframe/misc/tests/test_misc.py +35 -1
  48. maxframe/dataframe/missing/checkna.py +3 -2
  49. maxframe/dataframe/reduction/__init__.py +10 -5
  50. maxframe/dataframe/reduction/aggregation.py +6 -6
  51. maxframe/dataframe/reduction/argmax.py +7 -4
  52. maxframe/dataframe/reduction/argmin.py +7 -4
  53. maxframe/dataframe/reduction/core.py +18 -9
  54. maxframe/dataframe/reduction/mode.py +144 -0
  55. maxframe/dataframe/reduction/nunique.py +10 -3
  56. maxframe/dataframe/reduction/tests/test_reduction.py +12 -0
  57. maxframe/dataframe/sort/__init__.py +9 -2
  58. maxframe/dataframe/sort/argsort.py +7 -1
  59. maxframe/dataframe/sort/core.py +1 -1
  60. maxframe/dataframe/sort/rank.py +147 -0
  61. maxframe/dataframe/tseries/__init__.py +19 -0
  62. maxframe/dataframe/tseries/at_time.py +61 -0
  63. maxframe/dataframe/tseries/between_time.py +122 -0
  64. maxframe/dataframe/utils.py +30 -26
  65. maxframe/learn/contrib/llm/core.py +16 -7
  66. maxframe/learn/contrib/llm/deploy/__init__.py +13 -0
  67. maxframe/learn/contrib/llm/deploy/config.py +221 -0
  68. maxframe/learn/contrib/llm/deploy/core.py +247 -0
  69. maxframe/learn/contrib/llm/deploy/framework.py +35 -0
  70. maxframe/learn/contrib/llm/deploy/loader.py +360 -0
  71. maxframe/learn/contrib/llm/deploy/tests/__init__.py +13 -0
  72. maxframe/learn/contrib/llm/deploy/tests/test_register_models.py +359 -0
  73. maxframe/learn/contrib/llm/models/__init__.py +1 -0
  74. maxframe/learn/contrib/llm/models/dashscope.py +12 -6
  75. maxframe/learn/contrib/llm/models/managed.py +76 -11
  76. maxframe/learn/contrib/llm/models/openai.py +72 -0
  77. maxframe/learn/contrib/llm/tests/__init__.py +13 -0
  78. maxframe/learn/contrib/llm/tests/test_core.py +34 -0
  79. maxframe/learn/contrib/llm/tests/test_openai.py +187 -0
  80. maxframe/learn/contrib/llm/tests/test_text_gen.py +155 -0
  81. maxframe/learn/contrib/llm/text.py +348 -42
  82. maxframe/learn/contrib/models.py +4 -1
  83. maxframe/learn/contrib/xgboost/classifier.py +2 -0
  84. maxframe/learn/contrib/xgboost/core.py +31 -7
  85. maxframe/learn/contrib/xgboost/predict.py +4 -2
  86. maxframe/learn/contrib/xgboost/regressor.py +5 -0
  87. maxframe/learn/contrib/xgboost/train.py +2 -0
  88. maxframe/learn/preprocessing/_data/min_max_scaler.py +34 -23
  89. maxframe/learn/preprocessing/_data/standard_scaler.py +34 -25
  90. maxframe/learn/utils/__init__.py +1 -0
  91. maxframe/learn/utils/extmath.py +42 -9
  92. maxframe/learn/utils/odpsio.py +80 -11
  93. maxframe/lib/filesystem/_oss_lib/common.py +2 -0
  94. maxframe/lib/mmh3.cpython-38-darwin.so +0 -0
  95. maxframe/opcodes.py +9 -1
  96. maxframe/remote/core.py +4 -0
  97. maxframe/serialization/core.cpython-38-darwin.so +0 -0
  98. maxframe/serialization/tests/test_serial.py +2 -2
  99. maxframe/tensor/arithmetic/__init__.py +1 -1
  100. maxframe/tensor/arithmetic/core.py +2 -2
  101. maxframe/tensor/arithmetic/tests/test_arithmetic.py +0 -9
  102. maxframe/tensor/core.py +3 -0
  103. maxframe/tensor/misc/copyto.py +1 -1
  104. maxframe/tests/test_udf.py +61 -0
  105. maxframe/tests/test_utils.py +8 -5
  106. maxframe/udf.py +103 -7
  107. maxframe/utils.py +61 -8
  108. {maxframe-2.2.0.dist-info → maxframe-2.3.0rc1.dist-info}/METADATA +1 -2
  109. {maxframe-2.2.0.dist-info → maxframe-2.3.0rc1.dist-info}/RECORD +113 -90
  110. maxframe_client/session/task.py +8 -1
  111. maxframe_client/tests/test_session.py +24 -0
  112. maxframe/dataframe/arrays.py +0 -864
  113. {maxframe-2.2.0.dist-info → maxframe-2.3.0rc1.dist-info}/WHEEL +0 -0
  114. {maxframe-2.2.0.dist-info → maxframe-2.3.0rc1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,122 @@
1
+ # Copyright 1999-2025 Alibaba Group Holding Ltd.
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 numpy as np
16
+
17
+ from ... import opcodes
18
+ from ...core import get_output_types
19
+ from ...serialization.serializables import AnyField, Int32Field, StringField
20
+ from ..operators import DataFrameOperator, DataFrameOperatorMixin
21
+ from ..utils import parse_index, validate_axis
22
+
23
+
24
+ class DataFrameBetweenTime(DataFrameOperator, DataFrameOperatorMixin):
25
+ _op_type_ = opcodes.BETWEEN_TIME
26
+
27
+ start_time = AnyField("start_time")
28
+ end_time = AnyField("end_time")
29
+ inclusive = StringField("inclusive")
30
+ axis = Int32Field("axis")
31
+
32
+ def __call__(self, df_or_series):
33
+ self._output_types = get_output_types(df_or_series)
34
+ out_params = df_or_series.params
35
+
36
+ new_shape = list(df_or_series.shape)
37
+ new_shape[self.axis] = np.nan
38
+ out_params["shape"] = tuple(new_shape)
39
+
40
+ idx_key_params = (df_or_series, self.start_time, self.end_time, self.inclusive)
41
+ if self.axis == 0:
42
+ out_params["index_value"] = parse_index(
43
+ df_or_series.index_value.to_pandas()[:0], idx_key_params
44
+ )
45
+ else:
46
+ out_params["columns_value"] = parse_index(
47
+ df_or_series.columns_value.to_pandas()[:0], idx_key_params
48
+ )
49
+
50
+ return self.new_tileable([df_or_series], **out_params)
51
+
52
+
53
+ def between_time(df_or_series, start_time, end_time, inclusive="both", axis=0):
54
+ """
55
+ Select values between particular times of the day (e.g., 9:00-9:30 AM).
56
+
57
+ By setting ``start_time`` to be later than ``end_time``,
58
+ you can get the times that are *not* between the two times.
59
+
60
+ Parameters
61
+ ----------
62
+ start_time : datetime.time or str
63
+ Initial time as a time filter limit.
64
+ end_time : datetime.time or str
65
+ End time as a time filter limit.
66
+ inclusive : {"both", "neither", "left", "right"}, default "both"
67
+ Include boundaries; whether to set each bound as closed or open.
68
+ axis : {0 or 'index', 1 or 'columns'}, default 0
69
+ Determine range time on index or columns value.
70
+ For `Series` this parameter is unused and defaults to 0.
71
+
72
+ Returns
73
+ -------
74
+ Series or DataFrame
75
+ Data from the original object filtered to the specified dates range.
76
+
77
+ Raises
78
+ ------
79
+ TypeError
80
+ If the index is not a :class:`DatetimeIndex`
81
+
82
+ See Also
83
+ --------
84
+ at_time : Select values at a particular time of the day.
85
+ first : Select initial periods of time series based on a date offset.
86
+ last : Select final periods of time series based on a date offset.
87
+ DatetimeIndex.indexer_between_time : Get just the index locations for
88
+ values between particular times of the day.
89
+
90
+ Examples
91
+ --------
92
+ >>> import maxframe.dataframe as md
93
+ >>> i = md.date_range('2018-04-09', periods=4, freq='1D20min')
94
+ >>> ts = md.DataFrame({'A': [1, 2, 3, 4]}, index=i)
95
+ >>> ts.execute()
96
+ A
97
+ 2018-04-09 00:00:00 1
98
+ 2018-04-10 00:20:00 2
99
+ 2018-04-11 00:40:00 3
100
+ 2018-04-12 01:00:00 4
101
+
102
+ >>> ts.between_time('0:15', '0:45').execute()
103
+ A
104
+ 2018-04-10 00:20:00 2
105
+ 2018-04-11 00:40:00 3
106
+
107
+ You get the times that are *not* between two times by setting
108
+ ``start_time`` later than ``end_time``:
109
+
110
+ >>> ts.between_time('0:45', '0:15').execute()
111
+ A
112
+ 2018-04-09 00:00:00 1
113
+ 2018-04-12 01:00:00 4
114
+ """
115
+ axis = validate_axis(axis, df_or_series)
116
+ op = DataFrameBetweenTime(
117
+ start_time=start_time,
118
+ end_time=end_time,
119
+ inclusive=inclusive,
120
+ axis=axis,
121
+ )
122
+ return op(df_or_series)
@@ -25,9 +25,9 @@ from typing import TYPE_CHECKING, Any, Callable, List, Optional
25
25
 
26
26
  import numpy as np
27
27
  import pandas as pd
28
- from pandas.api.types import is_string_dtype
29
28
  from pandas.core.dtypes.inference import is_dict_like, is_list_like
30
29
 
30
+ from ..config.validators import dtype_backend_validator
31
31
  from ..core import ENTITY_TYPE, Entity, ExecutableTuple, OutputType, get_output_types
32
32
  from ..lib.dtypes_extension import ExternalBlobDtype, SolidBlob
33
33
  from ..lib.mmh3 import hash as mmh_hash
@@ -36,7 +36,6 @@ from ..utils import (
36
36
  ModulePlaceholder,
37
37
  is_full_slice,
38
38
  lazy_import,
39
- make_dtype,
40
39
  make_dtypes,
41
40
  quiet_stdio,
42
41
  sbytes,
@@ -105,9 +104,9 @@ def hash_dtypes(dtypes, size):
105
104
  return [dtypes[index] for index in hashed_indexes]
106
105
 
107
106
 
108
- def sort_dataframe_inplace(df, *axis):
107
+ def sort_dataframe_inplace(df, *axis, **kw):
109
108
  for ax in axis:
110
- df.sort_index(axis=ax, inplace=True)
109
+ df.sort_index(axis=ax, inplace=True, **kw)
111
110
  return df
112
111
 
113
112
 
@@ -1024,27 +1023,21 @@ def create_sa_connection(con, **kwargs):
1024
1023
  engine.dispose()
1025
1024
 
1026
1025
 
1027
- def to_arrow_dtypes(dtypes, test_df=None):
1028
- from .arrays import ArrowStringDtype
1026
+ def to_arrow_dtypes(dtypes):
1027
+ from ..io.odpsio.schema import pandas_dtypes_to_arrow_schema
1029
1028
 
1029
+ arrow_schema = pandas_dtypes_to_arrow_schema(dtypes)
1030
1030
  new_dtypes = dtypes.copy()
1031
1031
  for i in range(len(dtypes)):
1032
- dtype = dtypes.iloc[i]
1033
- if is_string_dtype(dtype):
1034
- if test_df is not None:
1035
- series = test_df.iloc[:, i]
1036
- # check value
1037
- non_na_series = series[series.notna()]
1038
- if len(non_na_series) > 0:
1039
- first_value = non_na_series.iloc[0]
1040
- if isinstance(first_value, str):
1041
- new_dtypes.iloc[i] = ArrowStringDtype()
1042
- else: # pragma: no cover
1043
- # empty, set arrow string dtype
1044
- new_dtypes.iloc[i] = ArrowStringDtype()
1045
- else:
1046
- # empty, set arrow string dtype
1047
- new_dtypes.iloc[i] = ArrowStringDtype()
1032
+ arrow_type = arrow_schema.types[i]
1033
+ dt = dtypes.iloc[i]
1034
+ if isinstance(dt, pd.api.extensions.ExtensionDtype):
1035
+ # make existing extension dtype consistent
1036
+ new_dtypes.iloc[i] = dt
1037
+ elif arrow_type == pa.string():
1038
+ new_dtypes.iloc[i] = pd.StringDtype("pyarrow")
1039
+ else:
1040
+ new_dtypes.iloc[i] = ArrowDtype(arrow_type)
1048
1041
  return new_dtypes
1049
1042
 
1050
1043
 
@@ -1482,7 +1475,8 @@ def infer_dataframe_return_value(
1482
1475
  elementwise=elementwise or False,
1483
1476
  )
1484
1477
 
1485
- ret_output_type = ret_dtypes = None
1478
+ ret_output_type = None
1479
+ ret_dtypes = dtypes
1486
1480
  maybe_agg = False
1487
1481
  build_kw = build_kw or {}
1488
1482
  obj_key = df_obj.key
@@ -1529,7 +1523,8 @@ def infer_dataframe_return_value(
1529
1523
  f'please specify `output_type` as "dataframe"'
1530
1524
  )
1531
1525
  ret_output_type = ret_output_type or OutputType.dataframe
1532
- ret_dtypes = ret_dtypes or infer_df_obj.dtypes
1526
+ if ret_dtypes is None:
1527
+ ret_dtypes = infer_df_obj.dtypes
1533
1528
  else:
1534
1529
  if output_type is not None and output_type == OutputType.dataframe:
1535
1530
  raise TypeError(
@@ -1549,7 +1544,7 @@ def infer_dataframe_return_value(
1549
1544
  return InferredDataFrameMeta(
1550
1545
  ret_output_type,
1551
1546
  make_dtypes(ret_dtypes),
1552
- make_dtype(dtype),
1547
+ make_dtypes(dtype),
1553
1548
  name,
1554
1549
  ret_index_value,
1555
1550
  maybe_agg,
@@ -1562,7 +1557,7 @@ def infer_dataframe_return_value(
1562
1557
  return InferredDataFrameMeta(
1563
1558
  output_type,
1564
1559
  make_dtypes(dtypes),
1565
- make_dtype(dtype),
1560
+ make_dtypes(dtype),
1566
1561
  name,
1567
1562
  ret_index_value,
1568
1563
  maybe_agg,
@@ -1645,3 +1640,12 @@ def call_groupby_with_params(df_or_series, groupby_params: dict):
1645
1640
  if selection:
1646
1641
  res = res[selection]
1647
1642
  return res
1643
+
1644
+
1645
+ def validate_dtype_backend(value):
1646
+ if isinstance(value, bool):
1647
+ # compatibility for legacy use_arrow_dtype property
1648
+ value = "pyarrow" if value else "numpy"
1649
+ if not dtype_backend_validator(value):
1650
+ raise ValueError(f"Invalid dtype_backend: {value}")
1651
+ return value
@@ -20,12 +20,16 @@ import pandas as pd
20
20
  from ....core.entity.output_types import OutputType
21
21
  from ....core.operator.base import Operator
22
22
  from ....core.operator.core import TileableOperatorMixin
23
- from ....dataframe.core import SERIES_TYPE
24
23
  from ....dataframe.operators import DataFrameOperatorMixin
25
24
  from ....dataframe.utils import parse_index
26
25
  from ....serialization.serializables import Int32Field
27
26
  from ....serialization.serializables.core import Serializable
28
- from ....serialization.serializables.field import AnyField, DictField, StringField
27
+ from ....serialization.serializables.field import (
28
+ AnyField,
29
+ BoolField,
30
+ DictField,
31
+ StringField,
32
+ )
29
33
 
30
34
 
31
35
  class LLM(Serializable):
@@ -55,11 +59,7 @@ class LLMTaskOperator(Operator, DataFrameOperatorMixin):
55
59
  col_name = list(outputs.keys())
56
60
  columns = parse_index(pd.Index(col_name), store_data=True)
57
61
  out_dtypes = pd.Series(list(outputs.values()), index=col_name)
58
- index_value = index or (
59
- parse_index(pd.RangeIndex(-1), data)
60
- if isinstance(data, SERIES_TYPE)
61
- else data.index_value
62
- )
62
+ index_value = index or data.index_value
63
63
 
64
64
  return self.new_dataframe(
65
65
  inputs=[data],
@@ -75,3 +75,12 @@ class LLMTextGenOperator(LLMTaskOperator, TileableOperatorMixin):
75
75
 
76
76
  def get_output_dtypes(self) -> Dict[str, np.dtype]:
77
77
  return {"response": np.dtype("O"), "success": np.dtype("bool")}
78
+
79
+
80
+ class LLMTextEmbeddingOp(LLMTaskOperator, TileableOperatorMixin):
81
+ dimensions = Int32Field("dimensions", default=None)
82
+ encoding_format = StringField("encoding_format", default=None)
83
+ simple_output = BoolField("simple_output", default=False)
84
+
85
+ def get_output_dtypes(self) -> Dict[str, np.dtype]:
86
+ return {"response": np.dtype("O"), "success": np.dtype("bool")}
@@ -0,0 +1,13 @@
1
+ # Copyright 1999-2025 Alibaba Group Holding Ltd.
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.
@@ -0,0 +1,221 @@
1
+ # Copyright 1999-2025 Alibaba Group Holding Ltd.
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 copy import deepcopy
16
+ from typing import Any, Dict, List, Optional, Union
17
+
18
+ from .....protocol import Serializable
19
+ from .....serialization.serializables import StringField
20
+ from .....serialization.serializables.field import (
21
+ DictField,
22
+ EnumField,
23
+ Int32Field,
24
+ ListField,
25
+ )
26
+ from .....serialization.serializables.field_type import FieldTypes
27
+ from .framework import InferenceFrameworkEnum
28
+
29
+
30
+ class ModelDeploymentConfig(Serializable):
31
+ """
32
+ Model deployment configuration for extending MaxFrame with custom models.
33
+
34
+ This configuration is designed for users who need to deploy models that are not
35
+ available within MaxFrame's built-in model offerings. It provides a way to specify
36
+ custom deployment solutions by informing each MaxFrame worker which framework to use,
37
+ which model path to load, and how to load it.
38
+
39
+ The configuration assumes that models are already set up in the container image or
40
+ mounted paths, and uses the current deploy_config to load them. Users are responsible
41
+ for ensuring the runtime environment state and compatibility.
42
+
43
+ Parameters
44
+ ----------
45
+ model_name: str
46
+ The name of the model.
47
+ model_file: str
48
+ The file path of the model.
49
+ inference_framework_type: InferenceFrameworkEnum
50
+ The inference framework of the model.
51
+ required_resource_files: List[Union[str, Any]]
52
+ The required resource files of the model.
53
+ load_params: Dict[str, Any]
54
+ The load params of the model.
55
+ required_cpu: int
56
+ The required cpu of the model.
57
+ required_memory: int
58
+ The required memory of the model.
59
+ required_gu: int
60
+ The required gu of the model.
61
+ required_gpu_memory: int
62
+ The required gpu memory of the model.
63
+ device: str
64
+ The device of the model. One of "cpu" or "cuda".
65
+ properties: Dict[str, Any]
66
+ The properties of the model.
67
+ tags: List[str]
68
+ The tags of the model.
69
+
70
+ Notes
71
+ -----
72
+ - Preview version for model deployments, all fields could be changed in the future.
73
+
74
+ **User Responsibility Notice**: Users must have a complete understanding of what
75
+ they are computing and ensure they fully comprehend the implications of their
76
+ configuration choices. You are responsible for:
77
+
78
+ * Ensuring model compatibility with the specified inference framework
79
+ * Verifying that model files exist and are accessible in the runtime environment
80
+ * Confirming that resource requirements (CPU, memory, GPU) are adequate
81
+ * Validating that all dependencies and libraries are properly installed
82
+ * Understanding the computational behavior and characteristics of your chosen model
83
+
84
+ Examples
85
+ --------
86
+ >>> from maxframe.learn.contrib.llm.deploy.config import ModelDeploymentConfig
87
+ >>> from maxframe.learn.contrib.llm.deploy.framework import InferenceFrameworkEnum
88
+ >>> from maxframe.learn.contrib.llm.models.managed import ManagedTextGenLLM
89
+
90
+ >>> # Configure model deployment with VLLM framework
91
+ >>> model_config = ModelDeploymentConfig(
92
+ ... # Path to the model files (assumed to be available in container/mount)
93
+ ... model_file="/models/Qwen3-4B-Instruct-2507-FP8",
94
+ ... # Use VLLM serving framework for text generation
95
+ ... inference_framework_type=InferenceFrameworkEnum.VLLM_SERVE_TEXT,
96
+ ... # Framework-specific loading parameters
97
+ ... load_params={
98
+ ... "max_context_tokens": 4096, # Maximum context length for the model
99
+ ... "max_startup_wait_seconds": 600 # Max wait time for model startup
100
+ ... },
101
+ ... # Target device for inference
102
+ ... device="cuda",
103
+ ... # Resource requirements (2 GPU units)
104
+ ... required_gu=2,
105
+ ... # Model tags for capabilities
106
+ ... tags=["text-generation"],
107
+ ... )
108
+
109
+ >>> # Create managed LLM instance with the deployment configuration
110
+ >>> llm = ManagedTextGenLLM(name="my-model", deploy_config=model_config)
111
+ >>> # Generate text using the deployed model.
112
+ >>> result_df = llm.generate(
113
+ ... df, # Input DataFrame containing prompts
114
+ ... prompt_template=messages, # Template for formatting prompts
115
+ ... running_options={
116
+ ... "max_context_tokens": 4096, # Runtime context limit
117
+ ... },
118
+ ... params={
119
+ ... "temperature": 0.7, # Sampling temperature
120
+ ... "max_tokens": 2048 # Maximum tokens to generate
121
+ ... },
122
+ ... )
123
+
124
+ To make this model config working with the ManagedTextGenLLM,
125
+ you need to provide a custom image with the required dependencies and model files.
126
+
127
+ """
128
+
129
+ model_name: str = StringField("model_name")
130
+ model_file: str = StringField("model_file")
131
+ inference_framework_type: InferenceFrameworkEnum = EnumField(
132
+ "inference_framework_type", enum_type=InferenceFrameworkEnum
133
+ )
134
+ required_resource_files: List[Union[str, Any]] = ListField(
135
+ "required_resource_files", field_type=FieldTypes.any, default_factory=list
136
+ )
137
+ load_params: Dict[str, Any] = DictField(
138
+ "load_params",
139
+ key_type=FieldTypes.string,
140
+ value_type=FieldTypes.any,
141
+ default_factory=dict,
142
+ )
143
+ required_cpu: Optional[int] = Int32Field("required_cpu", default=None)
144
+ required_memory: Optional[int] = Int32Field("required_memory", default=None)
145
+ required_gu: Optional[int] = Int32Field("required_gu", default=None)
146
+ required_gpu_memory: Optional[int] = Int32Field("required_gpu_memory", default=None)
147
+ device: str = StringField("device")
148
+ properties: Dict[str, Any] = DictField(
149
+ "properties",
150
+ key_type=FieldTypes.string,
151
+ value_type=FieldTypes.any,
152
+ default_factory=dict,
153
+ )
154
+ tags: List[str] = ListField(
155
+ "tags",
156
+ field_type=FieldTypes.string,
157
+ default_factory=list,
158
+ )
159
+
160
+ def is_reasoning_model(self):
161
+ if self.properties is None:
162
+ return False
163
+ return self.properties.get("reasoning_model", False)
164
+
165
+ def copy(self) -> "ModelDeploymentConfig":
166
+ return deepcopy(self)
167
+
168
+ def __eq__(self, other):
169
+ if not isinstance(other, ModelDeploymentConfig):
170
+ return False
171
+
172
+ return (
173
+ self.model_name == other.model_name
174
+ and self.model_file == other.model_file
175
+ and self.inference_framework_type == other.inference_framework_type
176
+ and self.required_resource_files == other.required_resource_files
177
+ and self.load_params == other.load_params
178
+ and self.required_cpu == other.required_cpu
179
+ and self.required_memory == other.required_memory
180
+ and self.required_gu == other.required_gu
181
+ and self.required_gpu_memory == other.required_gpu_memory
182
+ and self.device == other.device
183
+ and self.properties == other.properties
184
+ and self.tags == other.tags
185
+ )
186
+
187
+ def __hash__(self):
188
+ return hash(
189
+ (
190
+ self.model_name,
191
+ self.model_file,
192
+ self.inference_framework_type,
193
+ self.required_resource_files,
194
+ self.load_params,
195
+ self.required_cpu,
196
+ self.required_memory,
197
+ self.required_gu,
198
+ self.required_gpu_memory,
199
+ self.device,
200
+ self.properties,
201
+ self.tags,
202
+ )
203
+ )
204
+
205
+ def check_validity(self):
206
+ required_fields = [
207
+ "model_name",
208
+ "model_file",
209
+ "inference_framework_type",
210
+ "device",
211
+ ]
212
+ for field in required_fields:
213
+ if getattr(self, field) is None:
214
+ raise ValueError(f"{field} is required")
215
+
216
+ one_of_fields = ["required_cpu", "required_gu"]
217
+ if not any(getattr(self, field) is not None for field in one_of_fields):
218
+ raise ValueError(f"At least one of {one_of_fields} is required")
219
+
220
+ if not self.tags:
221
+ raise ValueError("tags is required")