maxframe 2.2.0__cp310-cp310-macosx_10_9_universal2.whl → 2.3.0rc1__cp310-cp310-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-310-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-310-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-310-darwin.so +0 -0
  95. maxframe/opcodes.py +9 -1
  96. maxframe/remote/core.py +4 -0
  97. maxframe/serialization/core.cpython-310-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,359 @@
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 json
16
+ import os.path
17
+ from typing import List
18
+
19
+ import pytest
20
+
21
+ from ..core import (
22
+ ResourceNameTemplate,
23
+ _registered_llm_models,
24
+ clean_registered_model,
25
+ get_registered_model_config,
26
+ register_model_deployments,
27
+ )
28
+ from ..framework import InferenceFrameworkEnum
29
+ from ..loader import (
30
+ DeploymentConfigBase,
31
+ DeploymentConfigResourceRequirement,
32
+ FrameworkDeploymentConfig,
33
+ ModelDeploymentConfig,
34
+ _model_config_to_json,
35
+ register_models_from_json_file,
36
+ )
37
+
38
+ current_dir = os.path.dirname(os.path.abspath(__file__))
39
+
40
+
41
+ @pytest.fixture
42
+ def qwen2_5_0_5b_model():
43
+ model_name = "Qwen2.5-0.5B-instruct"
44
+ model_file_resource = ResourceNameTemplate(
45
+ project="bigdata_public_dataset",
46
+ schema="data_plus_ai_{region_id}",
47
+ name="Qwen2.5-0.5B-Instruct.Q8_0.gguf",
48
+ )
49
+
50
+ common_load_params = {
51
+ "chat_format": "qwen",
52
+ "flash_attn": True,
53
+ "cache-type-k": "q8_0",
54
+ "cache-type-v": "q8_0",
55
+ "defrag-thold": "1",
56
+ }
57
+ common_config = DeploymentConfigBase.from_json(
58
+ {
59
+ "properties": {"family": "Qwen2.5", "type": "instruct"},
60
+ "load_params": common_load_params,
61
+ }
62
+ )
63
+
64
+ load_params = {"n_threads": 2, "n_batch": 1024, "n_ctx": 32768, "verbose": False}
65
+ calc_resources = DeploymentConfigResourceRequirement(cpu=2, memory=8)
66
+ deployment_llama_cpp_python = FrameworkDeploymentConfig(
67
+ model_file="Qwen2.5-0.5B-Instruct.Q8_0.gguf",
68
+ framework=InferenceFrameworkEnum.LLAMA_CPP_PYTHON_TEXT.value,
69
+ device="cpu",
70
+ model_file_resources=[model_file_resource],
71
+ load_params=load_params,
72
+ resource_requirements=calc_resources,
73
+ )
74
+ deployment_llama_server = FrameworkDeploymentConfig(
75
+ model_file="Qwen2.5-0.5B-Instruct.Q8_0.gguf",
76
+ framework=InferenceFrameworkEnum.LLAMA_CPP_SERVE_TEXT.value,
77
+ device="cpu",
78
+ model_file_resources=[model_file_resource],
79
+ load_params=load_params,
80
+ resource_requirements=calc_resources,
81
+ )
82
+ deployments = [deployment_llama_cpp_python, deployment_llama_server]
83
+
84
+ return ModelDeploymentConfig(
85
+ model_name=model_name,
86
+ tags=["tag"],
87
+ common_config=common_config,
88
+ deployments=deployments,
89
+ )
90
+
91
+
92
+ @pytest.fixture
93
+ def qwen3_8b_model():
94
+ json_config = """
95
+ {
96
+ "model_name": "Qwen3-0.6B",
97
+ "model_identifier": "qwen3-0.6b",
98
+ "common_config": {
99
+ "properties": {
100
+ "family": "Qwen3",
101
+ "reasoning_model": true
102
+ },
103
+ "load_params": {
104
+ "flash_attn": true,
105
+ "cache-type-k": "q8_0",
106
+ "cache-type-v": "q8_0",
107
+ "defrag-thold": "1",
108
+ "n_threads": 2,
109
+ "n_batch": 1024,
110
+ "n_ctx": 32768,
111
+ "verbose": false
112
+ },
113
+ "model_file": "Qwen3-0.6B-Q8_0.gguf",
114
+ "model_file_resources": [
115
+ {
116
+ "project": "bigdata_public_dataset",
117
+ "schema": "data_plus_ai_{region_id}",
118
+ "name": "Qwen3-0.6B-Q8_0.gguf"
119
+ }
120
+ ],
121
+ "resource_requirements": {
122
+ "cpu": 2,
123
+ "memory": 8
124
+ }
125
+ },
126
+ "deployments": [
127
+ {
128
+ "framework": "LLAMA_CPP_SERVE:TEXT",
129
+ "device": "cpu",
130
+ "load_params": {},
131
+ "resource_requirements": {},
132
+ "properties": {}
133
+ },
134
+ {
135
+ "framework": "LLAMA_CPP_PYTHON:TEXT",
136
+ "device": "cpu",
137
+ "load_params": {},
138
+ "resource_requirements": {
139
+ "cpu": 2,
140
+ "memory": 8
141
+ },
142
+ "properties": {}
143
+ }
144
+ ],
145
+ "tags": []
146
+ }
147
+ """
148
+ model = ModelDeploymentConfig.from_json(json.loads(json_config))
149
+ return model
150
+
151
+
152
+ @pytest.fixture
153
+ def models(qwen2_5_0_5b_model, qwen3_8b_model):
154
+ model_list = [qwen2_5_0_5b_model, qwen3_8b_model]
155
+ import uuid
156
+
157
+ test_json_path = os.path.join(current_dir, f"./test_models_{uuid.uuid4()}.json")
158
+ try:
159
+ with open(test_json_path, "w") as f:
160
+ f.write(_model_config_to_json(model_list))
161
+
162
+ yield test_json_path, model_list
163
+ finally:
164
+ clean_registered_model()
165
+ if os.path.exists(test_json_path):
166
+ os.remove(test_json_path)
167
+
168
+
169
+ def test_serialize_and_deserialize(qwen2_5_0_5b_model):
170
+ serialized = qwen2_5_0_5b_model.to_json()
171
+ deserialized = ModelDeploymentConfig.from_json(serialized)
172
+ assert serialized == deserialized.to_json()
173
+
174
+
175
+ def test_register_models():
176
+ clean_registered_model()
177
+ register_model_deployments(
178
+ model_name="mock_model",
179
+ model_file="DeepSeek-R1-Distill-Qwen-1.5B-Q8_0.gguf",
180
+ inference_frameworks=InferenceFrameworkEnum.LLAMA_CPP_PYTHON_TEXT,
181
+ required_resources=[
182
+ ResourceNameTemplate(
183
+ project="test",
184
+ schema=None,
185
+ name="DeepSeek-R1-Distill-Qwen-1.5B-Q8_0.gguf",
186
+ ),
187
+ ],
188
+ default_load_params={
189
+ "n_threads": 3,
190
+ "n_threads_batch": 512,
191
+ "n_batch": 512,
192
+ "flash_attn": True,
193
+ "verbose": True,
194
+ "n_ctx": 32 * 1024,
195
+ },
196
+ required_cpu=2,
197
+ required_memory=8,
198
+ device="cpu",
199
+ properties={"reasoning_model": True},
200
+ )
201
+
202
+ cpu_model_config = get_registered_model_config(
203
+ "mock_model",
204
+ expected_device="cpu",
205
+ expected_inference_framework=InferenceFrameworkEnum.LLAMA_CPP_PYTHON_TEXT,
206
+ )
207
+ assert cpu_model_config is not None
208
+ assert cpu_model_config is get_registered_model_config(
209
+ "mock_model", expected_device="cpu"
210
+ )
211
+ general_config = get_registered_model_config("mock_model")
212
+ assert cpu_model_config.model_name == general_config.model_name
213
+ assert cpu_model_config.device == general_config.device
214
+ assert cpu_model_config.device == "cpu"
215
+ assert cpu_model_config.required_memory == 8
216
+ assert cpu_model_config.required_cpu == 2
217
+ assert cpu_model_config.required_resource_files == [
218
+ ResourceNameTemplate(
219
+ project="test", schema=None, name="DeepSeek-R1-Distill-Qwen-1.5B-Q8_0.gguf"
220
+ )
221
+ ]
222
+ assert cpu_model_config.load_params.get("flash_attn") is True
223
+
224
+ register_model_deployments(
225
+ model_name="mock_model",
226
+ model_file="DeepSeek-R1-Distill-Qwen-1.5B-Q8_0.gguf",
227
+ inference_frameworks=InferenceFrameworkEnum.LLAMA_CPP_PYTHON_TEXT,
228
+ required_resources=[],
229
+ default_load_params={},
230
+ required_cpu=2,
231
+ required_memory=8,
232
+ device="gpu",
233
+ properties={"reasoning_model": True},
234
+ )
235
+ gpu_model_config = get_registered_model_config("mock_model", expected_device="gpu")
236
+ cpu_model_config_again = get_registered_model_config(
237
+ "mock_model", expected_device="cpu"
238
+ )
239
+ assert cpu_model_config.model_name == cpu_model_config_again.model_name
240
+ assert cpu_model_config.device == cpu_model_config_again.device
241
+ assert cpu_model_config.device != gpu_model_config.device
242
+
243
+ with pytest.raises(ValueError):
244
+ register_model_deployments(
245
+ model_name="mock_model",
246
+ model_file="DeepSeek-R1-Distill-Qwen-1.5B-Q8_0.gguf",
247
+ inference_frameworks=InferenceFrameworkEnum.LLAMA_CPP_PYTHON_TEXT,
248
+ required_resources=[],
249
+ default_load_params={},
250
+ required_cpu=2,
251
+ required_memory=8,
252
+ device="gpu",
253
+ properties={"reasoning_model": True},
254
+ )
255
+
256
+
257
+ def test_model_config_register(models):
258
+ clean_registered_model()
259
+ import os
260
+
261
+ test_json_path, model_list = models
262
+ model_list: List[ModelDeploymentConfig]
263
+
264
+ with pytest.raises(FileNotFoundError):
265
+ register_models_from_json_file(
266
+ os.path.join(current_dir, "test_models_not_exist.json")
267
+ )
268
+
269
+ test_config_path = os.path.join(current_dir, test_json_path)
270
+ register_models_from_json_file(test_config_path)
271
+
272
+ deployments = []
273
+ for model in model_list:
274
+ deployments.extend(model.deployments)
275
+
276
+ assert len(_registered_llm_models) == len(model_list)
277
+
278
+ for model in model_list:
279
+ model_name = model.model_name.lower()
280
+ assert model_name in _registered_llm_models.keys()
281
+
282
+ for deployments in model.deployments:
283
+ assert deployments.device in _registered_llm_models[model_name]
284
+ assert (
285
+ InferenceFrameworkEnum.from_string(deployments.framework)
286
+ in _registered_llm_models[model_name][deployments.device]
287
+ )
288
+
289
+
290
+ def test_resource_name_template():
291
+ """Test ResourceNameTemplate functionality."""
292
+ # Test with single variable
293
+ template = ResourceNameTemplate(
294
+ project="test_project", schema="schema_{region_id}", name="resource_{region_id}"
295
+ )
296
+
297
+ result = template.build_full_resource_name({"region_id": "cn-hangzhou"})
298
+ assert "cn_hangzhou" in result
299
+
300
+ # Test with multiple variables and hyphen replacement
301
+ template2 = ResourceNameTemplate(
302
+ project="my_project",
303
+ schema="schema_{region_id}_{env}",
304
+ name="resource_{region_id}_{version}",
305
+ )
306
+
307
+ result2 = template2.build_full_resource_name(
308
+ {"region_id": "us-west-1", "env": "prod-test", "version": "v1-2-3"}
309
+ )
310
+ assert "us_west_1" in result2
311
+ assert "prod_test" in result2
312
+ assert "v1_2_3" in result2
313
+
314
+ # Test equality and hash
315
+ template3 = ResourceNameTemplate("proj", "schema", "name")
316
+ template4 = ResourceNameTemplate("proj", "schema", "name")
317
+ template5 = ResourceNameTemplate("proj2", "schema", "name")
318
+
319
+ assert template3 == template4
320
+ assert template3 != template5
321
+ assert hash(template3) == hash(template4)
322
+ assert hash(template3) != hash(template5)
323
+
324
+
325
+ @pytest.mark.parametrize(
326
+ "input_string,expected_enum",
327
+ [
328
+ ("LLAMA_CPP_PYTHON:TEXT", InferenceFrameworkEnum.LLAMA_CPP_PYTHON_TEXT),
329
+ ("LLAMA_CPP_SERVE:TEXT", InferenceFrameworkEnum.LLAMA_CPP_SERVE_TEXT),
330
+ ("DASH_SCOPE:TEXT", InferenceFrameworkEnum.DASH_SCOPE_TEXT),
331
+ ("DASH_SCOPE:MULTIMODAL", InferenceFrameworkEnum.DASH_SCOPE_MULTIMODAL),
332
+ ("VLLM_SERVE:TEXT", InferenceFrameworkEnum.VLLM_SERVE_TEXT),
333
+ ("OPENAI_REMOTE:TEXT", InferenceFrameworkEnum.OPENAI_REMOTE_TEXT),
334
+ ("OTHER", InferenceFrameworkEnum.OTHER),
335
+ (
336
+ InferenceFrameworkEnum.DASH_SCOPE_TEXT,
337
+ InferenceFrameworkEnum.DASH_SCOPE_TEXT,
338
+ ),
339
+ ],
340
+ )
341
+ def test_inference_framework_enum_success(input_string, expected_enum):
342
+ result = InferenceFrameworkEnum.from_string(input_string)
343
+ assert result == expected_enum
344
+
345
+
346
+ @pytest.mark.parametrize(
347
+ "input_string",
348
+ [
349
+ "INVALID_FRAMEWORK",
350
+ "",
351
+ "llama_cpp_python:text",
352
+ "LLAMA_CPP_PYTHON:Text",
353
+ "UNKNOWN:FRAMEWORK",
354
+ ],
355
+ )
356
+ def test_inference_framework_enum_failure(input_string):
357
+ """Test that invalid inputs raise appropriate exceptions."""
358
+ with pytest.raises(ValueError):
359
+ InferenceFrameworkEnum.from_string(input_string)
@@ -13,3 +13,4 @@
13
13
  # limitations under the License.
14
14
 
15
15
  from .dashscope import DashScopeMultiModalLLM, DashScopeTextLLM
16
+ from .openai import OpenAICompatibleTextLLM
@@ -19,7 +19,7 @@ from .....serialization.serializables.core import Serializable
19
19
  from .....serialization.serializables.field import StringField
20
20
  from ..core import LLMTextGenOperator
21
21
  from ..multi_modal import MultiModalLLM
22
- from ..text import TextLLM
22
+ from ..text import TextGenLLM
23
23
 
24
24
 
25
25
  class DashScopeLLMMixin(Serializable):
@@ -33,7 +33,7 @@ class DashScopeLLMMixin(Serializable):
33
33
  raise ValueError(f"{k} is not supported")
34
34
 
35
35
 
36
- class DashScopeTextLLM(TextLLM, DashScopeLLMMixin):
36
+ class DashScopeTextLLM(TextGenLLM, DashScopeLLMMixin):
37
37
  """
38
38
  DashScope text LLM.
39
39
  """
@@ -59,7 +59,7 @@ class DashScopeTextLLM(TextLLM, DashScopeLLMMixin):
59
59
  prompt_template: Dict[str, Any],
60
60
  params: Dict[str, Any] = None,
61
61
  ):
62
- return DashScopeTextGenerationOperator(
62
+ return DashScopeTextGenerationOp(
63
63
  model=self,
64
64
  prompt_template=prompt_template,
65
65
  params=params,
@@ -93,16 +93,22 @@ class DashScopeMultiModalLLM(MultiModalLLM, DashScopeLLMMixin):
93
93
  params: Dict[str, Any] = None,
94
94
  ):
95
95
  # TODO add precheck here
96
- return DashScopeMultiModalGenerationOperator(
96
+ return DashScopeMultiModalGenerationOp(
97
97
  model=self,
98
98
  prompt_template=prompt_template,
99
99
  params=params,
100
100
  )(data)
101
101
 
102
102
 
103
- class DashScopeTextGenerationOperator(LLMTextGenOperator):
103
+ class DashScopeTextGenerationOp(LLMTextGenOperator):
104
104
  _op_type_ = opcodes.DASHSCOPE_TEXT_GENERATION
105
+ _legacy_name = "DashScopeTextGenerationOperator"
105
106
 
106
107
 
107
- class DashScopeMultiModalGenerationOperator(LLMTextGenOperator):
108
+ class DashScopeMultiModalGenerationOp(LLMTextGenOperator):
108
109
  _op_type_ = opcodes.DASHSCOPE_MULTI_MODAL_GENERATION
110
+ _legacy_name = "DashScopeMultiModalGenerationOperator"
111
+
112
+
113
+ DashScopeTextGenerationOperator = DashScopeTextGenerationOp
114
+ DashScopeMultiModalGenerationOperator = DashScopeMultiModalGenerationOp
@@ -12,26 +12,34 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from typing import Any, Dict, List
15
+ from typing import Any, Dict, List, Union
16
16
 
17
17
  from ..... import opcodes
18
- from .....serialization.serializables import StringField
19
- from ..core import LLMTextGenOperator
20
- from ..text import TextLLM
18
+ from .....serialization.serializables import BoolField, ReferenceField, StringField
19
+ from ..core import LLMTextEmbeddingOp, LLMTextGenOperator
20
+ from ..deploy.config import ModelDeploymentConfig
21
+ from ..text import TextEmbeddingModel, TextGenLLM
21
22
 
22
23
 
23
- class ManagedLLMTextGenOperator(LLMTextGenOperator):
24
+ class ManagedLLMTextGenOp(LLMTextGenOperator):
24
25
  _op_type_ = opcodes.MANAGED_TEXT_MODAL_GENERATION
26
+ _legacy_name = "ManagedLLMTextGenOperator"
25
27
 
26
28
  inference_framework: str = StringField("inference_framework", default=None)
29
+ simple_output: bool = BoolField("simple_output", default=False)
27
30
 
28
31
 
29
- class ManagedTextLLM(TextLLM):
32
+ class ManagedTextGenLLM(TextGenLLM):
30
33
  """
31
34
  Managed text LLM by MaxFrame.
32
35
  """
33
36
 
34
- def __init__(self, name: str):
37
+ _legacy_name = "ManagedTextLLM" # since v2.3.0
38
+ deploy_config: ModelDeploymentConfig = ReferenceField(
39
+ "deploy_config", reference_type=ModelDeploymentConfig, default=None
40
+ )
41
+
42
+ def __init__(self, name: str, deploy_config: ModelDeploymentConfig = None):
35
43
  """
36
44
  Initialize a managed text LLM.
37
45
 
@@ -39,16 +47,73 @@ class ManagedTextLLM(TextLLM):
39
47
  ----------
40
48
  name : str
41
49
  The managed text LLM name to use.
50
+ deploy_config : ModelDeploymentConfig
51
+ The model deployment config to use.
42
52
  """
43
- super().__init__(name=name)
53
+ if deploy_config:
54
+ deploy_config.model_name = name
55
+ deploy_config.check_validity()
56
+ super().__init__(name=name, deploy_config=deploy_config)
44
57
 
45
58
  def generate(
46
59
  self,
47
60
  data,
48
- prompt_template: List[Dict[str, Any]],
61
+ prompt_template: Union[str, List[Dict[str, Any]]],
62
+ simple_output: bool = False,
49
63
  params: Dict[str, Any] = None,
50
64
  **kw
51
65
  ):
52
- return ManagedLLMTextGenOperator(
53
- model=self, prompt_template=prompt_template, params=params, **kw
66
+ return ManagedLLMTextGenOp(
67
+ model=self,
68
+ prompt_template=prompt_template,
69
+ simple_output=simple_output,
70
+ params=params,
71
+ **kw,
54
72
  )(data)
73
+
74
+
75
+ # since v2.3.0, text llm has more types
76
+ ManagedTextLLM = ManagedTextGenLLM # for old client compatibility
77
+
78
+
79
+ class ManagedLLMTextEmbeddingOp(LLMTextEmbeddingOp):
80
+ _op_type_ = opcodes.LLM_TEXT_EMBEDDING_TASK
81
+ inference_framework: str = StringField("inference_framework", default=None)
82
+
83
+
84
+ class ManagedTextEmbeddingModel(TextEmbeddingModel):
85
+ """
86
+ Managed text embedder by MaxFrame.
87
+ """
88
+
89
+ def __init__(self, name: str):
90
+ """
91
+ Initialize a managed text embedder.
92
+ Parameters
93
+ ----------
94
+ name : str
95
+ The managed text embedder name to use.
96
+ """
97
+ super().__init__(name=name)
98
+
99
+ def embed(
100
+ self,
101
+ series,
102
+ dimensions: int = None,
103
+ encoding_format: str = None,
104
+ simple_output: bool = False,
105
+ params: Dict[str, Any] = None,
106
+ **kw
107
+ ):
108
+ return ManagedLLMTextEmbeddingOp(
109
+ model=self,
110
+ dimensions=dimensions,
111
+ encoding_format=encoding_format,
112
+ simple_output=simple_output,
113
+ params=params,
114
+ task="text-embedding",
115
+ **kw,
116
+ )(series)
117
+
118
+
119
+ ManagedLLMTextGenOperator = ManagedLLMTextGenOp
@@ -0,0 +1,72 @@
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 typing import Any, Dict, List
16
+
17
+ from ..... import opcodes
18
+ from .....serialization.serializables.field import BoolField, Int32Field, StringField
19
+ from ..core import LLM, LLMTextGenOperator
20
+ from ..text import TextGenLLM
21
+
22
+
23
+ class OpenAICompatibleLLM(LLM):
24
+ """
25
+ Remote OpenAI-compatible text LLM.
26
+ """
27
+
28
+ base_url: str = StringField("base_url")
29
+ api_key: str = StringField("api_key")
30
+ batch_size: int = Int32Field("batch_size", default=None)
31
+ batch_timeout: int = Int32Field("batch_timeout", default=None)
32
+
33
+
34
+ class OpenAICompatibleTextLLM(TextGenLLM, OpenAICompatibleLLM):
35
+ def __init__(self, name: str, base_url: str, api_key: str):
36
+ """
37
+ Initialize a remote OpenAI-compatible text LLM.
38
+
39
+ Parameters
40
+ ----------
41
+ name : str
42
+ The remote model name to use.
43
+ base_url : str
44
+ The base URL of the OpenAI-compatible API service.
45
+ api_key : str
46
+ The API key for authentication.
47
+ """
48
+ super().__init__(name=name)
49
+ self.base_url = base_url
50
+ self.api_key = api_key
51
+
52
+ def generate(
53
+ self,
54
+ data,
55
+ prompt_template: List[Dict[str, Any]],
56
+ simple_output: bool = False,
57
+ params: Dict[str, Any] = None,
58
+ **kw
59
+ ):
60
+ return OpenAICompatibleTextGenOp(
61
+ model=self,
62
+ prompt_template=prompt_template,
63
+ simple_output=simple_output,
64
+ params=params,
65
+ **kw,
66
+ )(data)
67
+
68
+
69
+ class OpenAICompatibleTextGenOp(LLMTextGenOperator):
70
+ _op_type_ = opcodes.OPENAI_COMPATIBLE_TEXT_GENERATION
71
+
72
+ simple_output = BoolField("simple_output", default=False)
@@ -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,34 @@
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 core as llm_core
18
+
19
+
20
+ def test_text_gen_operator_output_dtypes():
21
+ op = llm_core.LLMTextGenOperator()
22
+ dtypes = op.get_output_dtypes()
23
+ assert dtypes["response"] == np.dtype("O")
24
+ assert dtypes["success"] == np.dtype("bool")
25
+
26
+
27
+ def test_text_embedding_operator_output_dtypes_and_defaults():
28
+ op = llm_core.LLMTextEmbeddingOp()
29
+ dtypes = op.get_output_dtypes()
30
+ assert dtypes["response"] == np.dtype("O")
31
+ assert dtypes["success"] == np.dtype("bool")
32
+ assert op.simple_output is False
33
+ assert op.dimensions is None
34
+ assert op.encoding_format is None