Skip to content

Commit 0a94418

Browse files
committed
byom support
#76
1 parent 06202ae commit 0a94418

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

mindsdb_sdk/connectors/rest_api.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,19 @@ def upload_file(self, name: str, df: pd.DataFrame):
141141
)
142142
_raise_for_status(r)
143143

144+
@_try_relogin
145+
def upload_byom(self, name: str, code: str, requirements: str):
146+
147+
url = self.url + f'/api/handlers/byom/{name}'
148+
r = self.session.put(
149+
url,
150+
files={
151+
'code': code,
152+
'modules': requirements,
153+
}
154+
)
155+
_raise_for_status(r)
156+
144157
def status(self) -> dict:
145158

146159
r = self.session.get(self.url + f'/api/status')

mindsdb_sdk/ml_engines.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ class MLEngines(CollectionBase):
4545
4646
>>> con.ml_engines.drop('openai1')
4747
48+
Upload BYOM model. After uploading a new ml engin will be availbe to create new model from it.
49+
50+
>>> model_code = open('/path/to/model/code').read()
51+
>>> model_requirements = open('/path/to/model/requirements').read()
52+
>>> ml_engine = con.ml_engines.create_byom(
53+
... 'my_byom_engine',
54+
... code=model_code,
55+
... requirements=model_requirements
56+
...)
57+
4858
"""
4959

5060
def __init__(self, api):
@@ -101,6 +111,25 @@ def create(self, name: str, handler: Union[str, Handler], connection_data: dict
101111

102112
return MLEngine(name, handler, connection_data)
103113

114+
def create_byom(self, name: str, code: str, requirements: Union[str, List[str]] = None):
115+
"""
116+
Create new BYOM ML engine and return it
117+
118+
:param code: model python code in string
119+
:param requirements: requirements for model. Optional if there is no special requirements.
120+
It can be content of 'requirement.txt' file or list of strings (item for every requirement).
121+
:return: created BYOM ml engine object
122+
"""
123+
124+
if requirements is None:
125+
requirements = ''
126+
elif isinstance(requirements, list):
127+
requirements = '\n'.join(requirements)
128+
129+
self.api.upload_byom(name, code, requirements)
130+
131+
return MLEngine(name, 'byom', {})
132+
104133
def drop(self, name: str):
105134
"""
106135
Drop ml engine by name

tests/test_sdk.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,27 @@ def test_flow(self, mock_post, mock_put):
700700
con.ml_engines.drop('openai1')
701701
check_sql_call(mock_post, 'DROP ML_ENGINE openai1')
702702

703+
# byom
704+
model = '''
705+
import pandas as pd
706+
707+
class CustomPredictor():
708+
709+
def train(self, df, target_col, args=None):
710+
711+
self.target_col=target_col
712+
713+
def predict(self, df):
714+
return pd.Dataframe([{'predict': self.target_col}])
715+
'''
716+
requirements = '''pandas'''
717+
718+
con.ml_engines.create_byom('b1', model, requirements)
719+
call_args = mock_put.call_args
720+
assert call_args[0][0] == 'https://cloud.mindsdb.com/api/handlers/byom/b1'
721+
assert call_args[1]['files']['code'] == model
722+
assert call_args[1]['files']['modules'] == requirements
723+
703724
def check_project(self, project, database):
704725
self.check_project_views( project, database)
705726

0 commit comments

Comments
 (0)