From 7646936c38e6b93fbe182d7b7575f67daa9e5be4 Mon Sep 17 00:00:00 2001 From: Mohit Verma Date: Thu, 16 Oct 2025 10:36:08 +0530 Subject: [PATCH 01/14] fusion commands to start and stop model --- singlestoredb/fusion/handlers/models.py | 75 +++++++++++++++++++++++ singlestoredb/fusion/handlers/utils.py | 15 +++++ singlestoredb/management/inference_api.py | 75 ++++++++++++++++++++++- 3 files changed, 164 insertions(+), 1 deletion(-) diff --git a/singlestoredb/fusion/handlers/models.py b/singlestoredb/fusion/handlers/models.py index 5bb5cefa7..9334a8735 100644 --- a/singlestoredb/fusion/handlers/models.py +++ b/singlestoredb/fusion/handlers/models.py @@ -8,6 +8,7 @@ from ..result import FusionSQLResult from .files import ShowFilesHandler from .utils import get_file_space +from .utils import get_inference_api class ShowModelsHandler(ShowFilesHandler): @@ -248,3 +249,77 @@ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]: DropModelsHandler.register(overwrite=True) + + +class StartModelHandler(SQLHandler): + """ + START MODEL model_name ; + + # Model Name + model_name = '' + + Description + ----------- + Starts an inference API model. + + Arguments + --------- + * ````: Name of the model to start. + + Example + -------- + The following command starts a model:: + + START MODEL my_model; + + See Also + -------- + * ``STOP MODEL model_name`` + * ``SHOW MODELS`` + + """ # noqa: E501 + + def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]: + inference_api = get_inference_api(params) + inference_api.start() + return None + + +StartModelHandler.register(overwrite=True) + + +class StopModelHandler(SQLHandler): + """ + STOP MODEL model_name ; + + # Model Name + model_name = '' + + Description + ----------- + Stops an inference API model. + + Arguments + --------- + * ````: Name of the model to stop. + + Example + -------- + The following command stops a model:: + + STOP MODEL my_model; + + See Also + -------- + * ``START MODEL model_name`` + * ``SHOW MODELS`` + + """ # noqa: E501 + + def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]: + inference_api = get_inference_api(params) + inference_api.stop() + return None + + +StopModelHandler.register(overwrite=True) diff --git a/singlestoredb/fusion/handlers/utils.py b/singlestoredb/fusion/handlers/utils.py index 68af2e584..4789c85bd 100644 --- a/singlestoredb/fusion/handlers/utils.py +++ b/singlestoredb/fusion/handlers/utils.py @@ -16,6 +16,8 @@ from ...management.workspace import Workspace from ...management.workspace import WorkspaceGroup from ...management.workspace import WorkspaceManager +from ...management.inference_api import InferenceAPIInfo +from ...management.inference_api import InferenceAPIManager def get_workspace_manager() -> WorkspaceManager: @@ -322,3 +324,16 @@ def get_file_space(params: Dict[str, Any]) -> FileSpace: raise ValueError(f'invalid file location: {file_location}') raise KeyError('no file space was specified') + + +def get_inference_api_manager() -> InferenceAPIManager: + """Return the inference API manager for the current project.""" + wm = get_workspace_manager() + return wm.organization.inference_apis + + +def get_inference_api(params: Dict[str, Any]) -> InferenceAPIInfo: + """Return an inference API based on model name in params.""" + inference_apis = get_inference_api_manager() + model_name = params['model_name'] + return inference_apis.get(model_name) diff --git a/singlestoredb/management/inference_api.py b/singlestoredb/management/inference_api.py index 13b6413c2..199afcee2 100644 --- a/singlestoredb/management/inference_api.py +++ b/singlestoredb/management/inference_api.py @@ -24,6 +24,7 @@ class InferenceAPIInfo(object): connection_url: str project_id: str hosting_platform: str + _manager: Optional['InferenceAPIManager'] def __init__( self, @@ -33,6 +34,7 @@ def __init__( connection_url: str, project_id: str, hosting_platform: str, + manager: Optional['InferenceAPIManager'] = None, ): self.service_id = service_id self.connection_url = connection_url @@ -40,6 +42,7 @@ def __init__( self.name = name self.project_id = project_id self.hosting_platform = hosting_platform + self._manager = manager @classmethod def from_dict( @@ -77,6 +80,34 @@ def __repr__(self) -> str: """Return string representation.""" return str(self) + def start(self) -> Dict[str, Any]: + """ + Start this inference API model. + + Returns + ------- + dict + Response from the start operation + + """ + if self._manager is None: + raise ManagementError(msg='No manager associated with this inference API') + return self._manager.start(self.name) + + def stop(self) -> Dict[str, Any]: + """ + Stop this inference API model. + + Returns + ------- + dict + Response from the stop operation + + """ + if self._manager is None: + raise ManagementError(msg='No manager associated with this inference API') + return self._manager.stop(self.name) + class InferenceAPIManager(object): """ @@ -102,4 +133,46 @@ def get(self, model_name: str) -> InferenceAPIInfo: if self._manager is None: raise ManagementError(msg='Manager not initialized') res = self._manager._get(f'inferenceapis/{self.project_id}/{model_name}').json() - return InferenceAPIInfo.from_dict(res) + inference_api = InferenceAPIInfo.from_dict(res) + inference_api._manager = self # Associate the manager + return inference_api + + def start(self, model_name: str) -> Dict[str, Any]: + """ + Start an inference API model. + + Parameters + ---------- + model_name : str + Name of the model to start + + Returns + ------- + dict + Response from the start operation + + """ + if self._manager is None: + raise ManagementError(msg='Manager not initialized') + res = self._manager._post(f'inferenceapis/{self.project_id}/{model_name}/start') + return res.json() + + def stop(self, model_name: str) -> Dict[str, Any]: + """ + Stop an inference API model. + + Parameters + ---------- + model_name : str + Name of the model to stop + + Returns + ------- + dict + Response from the stop operation + + """ + if self._manager is None: + raise ManagementError(msg='Manager not initialized') + res = self._manager._post(f'inferenceapis/{self.project_id}/{model_name}/stop') + return res.json() From 58610e11482686e45b89e9b7e9716b11a602e754 Mon Sep 17 00:00:00 2001 From: Mohit Verma Date: Thu, 16 Oct 2025 11:11:56 +0530 Subject: [PATCH 02/14] changes --- singlestoredb/management/inference_api.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/singlestoredb/management/inference_api.py b/singlestoredb/management/inference_api.py index 199afcee2..784e2464e 100644 --- a/singlestoredb/management/inference_api.py +++ b/singlestoredb/management/inference_api.py @@ -132,7 +132,7 @@ def __init__(self, manager: Optional[Manager]): def get(self, model_name: str) -> InferenceAPIInfo: if self._manager is None: raise ManagementError(msg='Manager not initialized') - res = self._manager._get(f'inferenceapis/{self.project_id}/{model_name}').json() + res = self._manager._get(f'v1/inferenceapis/{self.project_id}/{model_name}').json() inference_api = InferenceAPIInfo.from_dict(res) inference_api._manager = self # Associate the manager return inference_api @@ -154,7 +154,7 @@ def start(self, model_name: str) -> Dict[str, Any]: """ if self._manager is None: raise ManagementError(msg='Manager not initialized') - res = self._manager._post(f'inferenceapis/{self.project_id}/{model_name}/start') + res = self._manager._post(f'v1/inferenceapis/{self.project_id}/{model_name}/start') return res.json() def stop(self, model_name: str) -> Dict[str, Any]: @@ -174,5 +174,5 @@ def stop(self, model_name: str) -> Dict[str, Any]: """ if self._manager is None: raise ManagementError(msg='Manager not initialized') - res = self._manager._post(f'inferenceapis/{self.project_id}/{model_name}/stop') + res = self._manager._post(f'v1/inferenceapis/{self.project_id}/{model_name}/stop') return res.json() From b6f404cb0727f7fb5cfcf2ad46b63b43d4df253c Mon Sep 17 00:00:00 2001 From: Mohit Verma Date: Thu, 16 Oct 2025 13:24:51 +0530 Subject: [PATCH 03/14] changes --- singlestoredb/management/inference_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/singlestoredb/management/inference_api.py b/singlestoredb/management/inference_api.py index 784e2464e..f6b5018aa 100644 --- a/singlestoredb/management/inference_api.py +++ b/singlestoredb/management/inference_api.py @@ -154,7 +154,7 @@ def start(self, model_name: str) -> Dict[str, Any]: """ if self._manager is None: raise ManagementError(msg='Manager not initialized') - res = self._manager._post(f'v1/inferenceapis/{self.project_id}/{model_name}/start') + res = self._manager._post(f'inferenceapis/{self.project_id}/{model_name}/start') return res.json() def stop(self, model_name: str) -> Dict[str, Any]: @@ -174,5 +174,5 @@ def stop(self, model_name: str) -> Dict[str, Any]: """ if self._manager is None: raise ManagementError(msg='Manager not initialized') - res = self._manager._post(f'v1/inferenceapis/{self.project_id}/{model_name}/stop') + res = self._manager._post(f'inferenceapis/{self.project_id}/{model_name}/stop') return res.json() From 7eb1d1097402d20f3de1e222883462696431b1a7 Mon Sep 17 00:00:00 2001 From: Mohit Verma Date: Thu, 16 Oct 2025 13:30:22 +0530 Subject: [PATCH 04/14] changes --- singlestoredb/management/inference_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/singlestoredb/management/inference_api.py b/singlestoredb/management/inference_api.py index f6b5018aa..199afcee2 100644 --- a/singlestoredb/management/inference_api.py +++ b/singlestoredb/management/inference_api.py @@ -132,7 +132,7 @@ def __init__(self, manager: Optional[Manager]): def get(self, model_name: str) -> InferenceAPIInfo: if self._manager is None: raise ManagementError(msg='Manager not initialized') - res = self._manager._get(f'v1/inferenceapis/{self.project_id}/{model_name}').json() + res = self._manager._get(f'inferenceapis/{self.project_id}/{model_name}').json() inference_api = InferenceAPIInfo.from_dict(res) inference_api._manager = self # Associate the manager return inference_api From 44abeed31ba3e25dc29fe3f8c0bad2f3575ae9c0 Mon Sep 17 00:00:00 2001 From: Mohit Verma Date: Wed, 29 Oct 2025 12:07:13 +0530 Subject: [PATCH 05/14] pre commit checks --- singlestoredb/fusion/handlers/utils.py | 4 ++-- singlestoredb/management/inference_api.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/singlestoredb/fusion/handlers/utils.py b/singlestoredb/fusion/handlers/utils.py index 4789c85bd..f5e82b039 100644 --- a/singlestoredb/fusion/handlers/utils.py +++ b/singlestoredb/fusion/handlers/utils.py @@ -12,12 +12,12 @@ from ...management.files import FilesManager from ...management.files import FileSpace from ...management.files import manage_files +from ...management.inference_api import InferenceAPIInfo +from ...management.inference_api import InferenceAPIManager from ...management.workspace import StarterWorkspace from ...management.workspace import Workspace from ...management.workspace import WorkspaceGroup from ...management.workspace import WorkspaceManager -from ...management.inference_api import InferenceAPIInfo -from ...management.inference_api import InferenceAPIManager def get_workspace_manager() -> WorkspaceManager: diff --git a/singlestoredb/management/inference_api.py b/singlestoredb/management/inference_api.py index 199afcee2..6c23da1e4 100644 --- a/singlestoredb/management/inference_api.py +++ b/singlestoredb/management/inference_api.py @@ -154,7 +154,7 @@ def start(self, model_name: str) -> Dict[str, Any]: """ if self._manager is None: raise ManagementError(msg='Manager not initialized') - res = self._manager._post(f'inferenceapis/{self.project_id}/{model_name}/start') + res = self._manager._post(f'inferenceapis/{model_name}/start') return res.json() def stop(self, model_name: str) -> Dict[str, Any]: @@ -174,5 +174,5 @@ def stop(self, model_name: str) -> Dict[str, Any]: """ if self._manager is None: raise ManagementError(msg='Manager not initialized') - res = self._manager._post(f'inferenceapis/{self.project_id}/{model_name}/stop') + res = self._manager._post(f'inferenceapis/{model_name}/stop') return res.json() From e436a8d1a46b8a173c5807d7ce351fb80cae00a6 Mon Sep 17 00:00:00 2001 From: Mohit Verma Date: Thu, 30 Oct 2025 11:05:44 +0530 Subject: [PATCH 06/14] review changes --- singlestoredb/fusion/handlers/models.py | 35 ++++++- singlestoredb/management/inference_api.py | 115 +++++++++++++++++++--- 2 files changed, 132 insertions(+), 18 deletions(-) diff --git a/singlestoredb/fusion/handlers/models.py b/singlestoredb/fusion/handlers/models.py index 9334a8735..19ef47885 100644 --- a/singlestoredb/fusion/handlers/models.py +++ b/singlestoredb/fusion/handlers/models.py @@ -6,6 +6,7 @@ from ..handler import SQLHandler from ..result import FusionSQLResult +from .. import result from .files import ShowFilesHandler from .utils import get_file_space from .utils import get_inference_api @@ -281,8 +282,21 @@ class StartModelHandler(SQLHandler): def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]: inference_api = get_inference_api(params) - inference_api.start() - return None + operation_result = inference_api.start() + + res = FusionSQLResult() + res.add_field('Model', result.STRING) + res.add_field('Status', result.STRING) + res.add_field('Message', result.STRING) + res.set_rows([ + ( + operation_result.name, + operation_result.status, + operation_result.get_message(), + ), + ]) + + return res StartModelHandler.register(overwrite=True) @@ -318,8 +332,21 @@ class StopModelHandler(SQLHandler): def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]: inference_api = get_inference_api(params) - inference_api.stop() - return None + operation_result = inference_api.stop() + + res = FusionSQLResult() + res.add_field('Model', result.STRING) + res.add_field('Status', result.STRING) + res.add_field('Message', result.STRING) + res.set_rows([ + ( + operation_result.name, + operation_result.status, + operation_result.get_message(), + ), + ]) + + return res StopModelHandler.register(overwrite=True) diff --git a/singlestoredb/management/inference_api.py b/singlestoredb/management/inference_api.py index 6c23da1e4..c3ebcb0cf 100644 --- a/singlestoredb/management/inference_api.py +++ b/singlestoredb/management/inference_api.py @@ -10,6 +10,93 @@ from singlestoredb.management.manager import Manager +class ModelOperationResult(object): + """ + Result of a model start or stop operation. + + Attributes + ---------- + name : str + Name of the model + status : str + Current status of the model (e.g., 'Active', 'Initializing', 'Suspended') + hosting_platform : str + Hosting platform (e.g., 'Nova', 'Amazon', 'Azure') + """ + + def __init__( + self, + name: str, + status: str, + hosting_platform: str, + ): + self.name = name + self.status = status + self.hosting_platform = hosting_platform + + @classmethod + def from_start_response(cls, response: Dict[str, Any]) -> 'ModelOperationResult': + """ + Create a ModelOperationResult from a start operation response. + + Parameters + ---------- + response : dict + Response from the start endpoint + + Returns + ------- + ModelOperationResult + + """ + return cls( + name=response.get('modelName', ''), + status='Initializing', + hosting_platform=response.get('hostingPlatform', ''), + ) + + @classmethod + def from_stop_response(cls, response: Dict[str, Any]) -> 'ModelOperationResult': + """ + Create a ModelOperationResult from a stop operation response. + + Parameters + ---------- + response : dict + Response from the stop endpoint + + Returns + ------- + ModelOperationResult + + """ + return cls( + name=response.get('name', ''), + status=response.get('status', 'Suspended'), + hosting_platform=response.get('hostingPlatform', ''), + ) + + def get_message(self) -> str: + """ + Get a human-readable message about the operation. + + Returns + ------- + str + Message describing the operation result + + """ + return f"Model '{self.name}' status is now {self.status}" + + def __str__(self) -> str: + """Return string representation.""" + return vars_to_str(self) + + def __repr__(self) -> str: + """Return string representation.""" + return str(self) + + class InferenceAPIInfo(object): """ Inference API definition. @@ -80,28 +167,28 @@ def __repr__(self) -> str: """Return string representation.""" return str(self) - def start(self) -> Dict[str, Any]: + def start(self) -> ModelOperationResult: """ Start this inference API model. Returns ------- - dict - Response from the start operation + ModelOperationResult + Result object containing status information about the started model """ if self._manager is None: raise ManagementError(msg='No manager associated with this inference API') return self._manager.start(self.name) - def stop(self) -> Dict[str, Any]: + def stop(self) -> ModelOperationResult: """ Stop this inference API model. Returns ------- - dict - Response from the stop operation + ModelOperationResult + Result object containing status information about the stopped model """ if self._manager is None: @@ -137,7 +224,7 @@ def get(self, model_name: str) -> InferenceAPIInfo: inference_api._manager = self # Associate the manager return inference_api - def start(self, model_name: str) -> Dict[str, Any]: + def start(self, model_name: str) -> ModelOperationResult: """ Start an inference API model. @@ -148,16 +235,16 @@ def start(self, model_name: str) -> Dict[str, Any]: Returns ------- - dict - Response from the start operation + ModelOperationResult + Result object containing status information about the started model """ if self._manager is None: raise ManagementError(msg='Manager not initialized') res = self._manager._post(f'inferenceapis/{model_name}/start') - return res.json() + return ModelOperationResult.from_start_response(res.json()) - def stop(self, model_name: str) -> Dict[str, Any]: + def stop(self, model_name: str) -> ModelOperationResult: """ Stop an inference API model. @@ -168,11 +255,11 @@ def stop(self, model_name: str) -> Dict[str, Any]: Returns ------- - dict - Response from the stop operation + ModelOperationResult + Result object containing status information about the stopped model """ if self._manager is None: raise ManagementError(msg='Manager not initialized') res = self._manager._post(f'inferenceapis/{model_name}/stop') - return res.json() + return ModelOperationResult.from_stop_response(res.json()) From 15de5d0f5e1bf7d0e43daff26ca01a450fd7f82e Mon Sep 17 00:00:00 2001 From: Mohit Verma Date: Thu, 30 Oct 2025 11:09:34 +0530 Subject: [PATCH 07/14] checks changes --- singlestoredb/fusion/handlers/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/singlestoredb/fusion/handlers/models.py b/singlestoredb/fusion/handlers/models.py index 19ef47885..892ad74f1 100644 --- a/singlestoredb/fusion/handlers/models.py +++ b/singlestoredb/fusion/handlers/models.py @@ -4,9 +4,9 @@ from typing import Dict from typing import Optional +from .. import result from ..handler import SQLHandler from ..result import FusionSQLResult -from .. import result from .files import ShowFilesHandler from .utils import get_file_space from .utils import get_inference_api From 5b1ec30b09e7dc6d3c594bbd8fad9f56375a6379 Mon Sep 17 00:00:00 2001 From: Mohit Verma Date: Thu, 30 Oct 2025 11:50:00 +0530 Subject: [PATCH 08/14] debug issue commit --- singlestoredb/management/inference_api.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/singlestoredb/management/inference_api.py b/singlestoredb/management/inference_api.py index c3ebcb0cf..e9e32cd68 100644 --- a/singlestoredb/management/inference_api.py +++ b/singlestoredb/management/inference_api.py @@ -50,7 +50,7 @@ def from_start_response(cls, response: Dict[str, Any]) -> 'ModelOperationResult' """ return cls( - name=response.get('modelName', ''), + name=response.get('modelID', ''), status='Initializing', hosting_platform=response.get('hostingPlatform', ''), ) @@ -86,7 +86,7 @@ def get_message(self) -> str: Message describing the operation result """ - return f"Model '{self.name}' status is now {self.status}" + return f"Model is {self.status}" def __str__(self) -> str: """Return string representation.""" @@ -262,4 +262,8 @@ def stop(self, model_name: str) -> ModelOperationResult: if self._manager is None: raise ManagementError(msg='Manager not initialized') res = self._manager._post(f'inferenceapis/{model_name}/stop') - return ModelOperationResult.from_stop_response(res.json()) + response_data = res.json() + # Debug: print the actual response to see what we're getting + import json + print(f"DEBUG - Stop response: {json.dumps(response_data, indent=2, default=str)}") + return ModelOperationResult.from_stop_response(response_data) From 3da514370575c3e3f37a82f61f1ca17450fa2c15 Mon Sep 17 00:00:00 2001 From: Mohit Verma Date: Thu, 30 Oct 2025 12:03:14 +0530 Subject: [PATCH 09/14] dubug issue changes --- singlestoredb/management/inference_api.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/singlestoredb/management/inference_api.py b/singlestoredb/management/inference_api.py index e9e32cd68..cfefaf0f1 100644 --- a/singlestoredb/management/inference_api.py +++ b/singlestoredb/management/inference_api.py @@ -242,7 +242,11 @@ def start(self, model_name: str) -> ModelOperationResult: if self._manager is None: raise ManagementError(msg='Manager not initialized') res = self._manager._post(f'inferenceapis/{model_name}/start') - return ModelOperationResult.from_start_response(res.json()) + response_data = res.json() + # Debug: print the actual response to see what we're getting + import json + print(f"DEBUG - Start response: {json.dumps(response_data, indent=2, default=str)}") + return ModelOperationResult.from_start_response(response_data) def stop(self, model_name: str) -> ModelOperationResult: """ From eb318537584aa90f8caa418db140b179976130c5 Mon Sep 17 00:00:00 2001 From: Mohit Verma Date: Thu, 30 Oct 2025 12:21:54 +0530 Subject: [PATCH 10/14] response changes --- singlestoredb/fusion/handlers/models.py | 4 ---- singlestoredb/management/inference_api.py | 14 +++----------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/singlestoredb/fusion/handlers/models.py b/singlestoredb/fusion/handlers/models.py index 892ad74f1..8dc53ffce 100644 --- a/singlestoredb/fusion/handlers/models.py +++ b/singlestoredb/fusion/handlers/models.py @@ -285,12 +285,10 @@ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]: operation_result = inference_api.start() res = FusionSQLResult() - res.add_field('Model', result.STRING) res.add_field('Status', result.STRING) res.add_field('Message', result.STRING) res.set_rows([ ( - operation_result.name, operation_result.status, operation_result.get_message(), ), @@ -335,12 +333,10 @@ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]: operation_result = inference_api.stop() res = FusionSQLResult() - res.add_field('Model', result.STRING) res.add_field('Status', result.STRING) res.add_field('Message', result.STRING) res.set_rows([ ( - operation_result.name, operation_result.status, operation_result.get_message(), ), diff --git a/singlestoredb/management/inference_api.py b/singlestoredb/management/inference_api.py index cfefaf0f1..551648459 100644 --- a/singlestoredb/management/inference_api.py +++ b/singlestoredb/management/inference_api.py @@ -50,7 +50,7 @@ def from_start_response(cls, response: Dict[str, Any]) -> 'ModelOperationResult' """ return cls( - name=response.get('modelID', ''), + name=response.get('modelName', ''), status='Initializing', hosting_platform=response.get('hostingPlatform', ''), ) @@ -242,11 +242,7 @@ def start(self, model_name: str) -> ModelOperationResult: if self._manager is None: raise ManagementError(msg='Manager not initialized') res = self._manager._post(f'inferenceapis/{model_name}/start') - response_data = res.json() - # Debug: print the actual response to see what we're getting - import json - print(f"DEBUG - Start response: {json.dumps(response_data, indent=2, default=str)}") - return ModelOperationResult.from_start_response(response_data) + return ModelOperationResult.from_start_response(res.json()) def stop(self, model_name: str) -> ModelOperationResult: """ @@ -266,8 +262,4 @@ def stop(self, model_name: str) -> ModelOperationResult: if self._manager is None: raise ManagementError(msg='Manager not initialized') res = self._manager._post(f'inferenceapis/{model_name}/stop') - response_data = res.json() - # Debug: print the actual response to see what we're getting - import json - print(f"DEBUG - Stop response: {json.dumps(response_data, indent=2, default=str)}") - return ModelOperationResult.from_stop_response(response_data) + return ModelOperationResult.from_stop_response(res.json()) From a5644ab021ba882d40e6e6dbf1c2e04e81ec5ac8 Mon Sep 17 00:00:00 2001 From: Mohit Verma Date: Thu, 30 Oct 2025 12:37:23 +0530 Subject: [PATCH 11/14] Fix double-quoted string in get_message method --- singlestoredb/management/inference_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/singlestoredb/management/inference_api.py b/singlestoredb/management/inference_api.py index 551648459..124379105 100644 --- a/singlestoredb/management/inference_api.py +++ b/singlestoredb/management/inference_api.py @@ -86,7 +86,7 @@ def get_message(self) -> str: Message describing the operation result """ - return f"Model is {self.status}" + return f'Model is {self.status}' def __str__(self) -> str: """Return string representation.""" From 35b47d4482c1909922dd3625d81bea01317c27fc Mon Sep 17 00:00:00 2001 From: Mohit Verma Date: Mon, 3 Nov 2025 13:54:14 +0530 Subject: [PATCH 12/14] replaced inferenceapis with models in model routes --- singlestoredb/management/inference_api.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/singlestoredb/management/inference_api.py b/singlestoredb/management/inference_api.py index 124379105..6e67c71c2 100644 --- a/singlestoredb/management/inference_api.py +++ b/singlestoredb/management/inference_api.py @@ -219,7 +219,7 @@ def __init__(self, manager: Optional[Manager]): def get(self, model_name: str) -> InferenceAPIInfo: if self._manager is None: raise ManagementError(msg='Manager not initialized') - res = self._manager._get(f'inferenceapis/{self.project_id}/{model_name}').json() + res = self._manager._get(f'models/{self.project_id}/{model_name}').json() inference_api = InferenceAPIInfo.from_dict(res) inference_api._manager = self # Associate the manager return inference_api @@ -241,7 +241,7 @@ def start(self, model_name: str) -> ModelOperationResult: """ if self._manager is None: raise ManagementError(msg='Manager not initialized') - res = self._manager._post(f'inferenceapis/{model_name}/start') + res = self._manager._post(f'models/{model_name}/start') return ModelOperationResult.from_start_response(res.json()) def stop(self, model_name: str) -> ModelOperationResult: @@ -261,5 +261,5 @@ def stop(self, model_name: str) -> ModelOperationResult: """ if self._manager is None: raise ManagementError(msg='Manager not initialized') - res = self._manager._post(f'inferenceapis/{model_name}/stop') + res = self._manager._post(f'models/{model_name}/stop') return ModelOperationResult.from_stop_response(res.json()) From 72650d549fd08e577f3429a0e1be50bb71628d64 Mon Sep 17 00:00:00 2001 From: Mohit Verma Date: Mon, 3 Nov 2025 14:36:13 +0530 Subject: [PATCH 13/14] revert get endpoint changes --- singlestoredb/management/inference_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/singlestoredb/management/inference_api.py b/singlestoredb/management/inference_api.py index 6e67c71c2..775ccf6b9 100644 --- a/singlestoredb/management/inference_api.py +++ b/singlestoredb/management/inference_api.py @@ -219,7 +219,7 @@ def __init__(self, manager: Optional[Manager]): def get(self, model_name: str) -> InferenceAPIInfo: if self._manager is None: raise ManagementError(msg='Manager not initialized') - res = self._manager._get(f'models/{self.project_id}/{model_name}').json() + res = self._manager._get(f'inferenceapis/{self.project_id}/{model_name}').json() inference_api = InferenceAPIInfo.from_dict(res) inference_api._manager = self # Associate the manager return inference_api From e9ee4d09a6a657a8fc179739da72739c44558820 Mon Sep 17 00:00:00 2001 From: Mohit Verma Date: Fri, 7 Nov 2025 13:42:10 +0530 Subject: [PATCH 14/14] aura models show and drop commands initial commit --- singlestoredb/fusion/handlers/models.py | 94 +++++++++++++++++++++++ singlestoredb/management/inference_api.py | 92 ++++++++++++++++++++++ 2 files changed, 186 insertions(+) diff --git a/singlestoredb/fusion/handlers/models.py b/singlestoredb/fusion/handlers/models.py index 8dc53ffce..db05fed10 100644 --- a/singlestoredb/fusion/handlers/models.py +++ b/singlestoredb/fusion/handlers/models.py @@ -10,6 +10,7 @@ from .files import ShowFilesHandler from .utils import get_file_space from .utils import get_inference_api +from .utils import get_inference_api_manager class ShowModelsHandler(ShowFilesHandler): @@ -346,3 +347,96 @@ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]: StopModelHandler.register(overwrite=True) + + +class ShowInferenceAPIsHandler(SQLHandler): + """ + SHOW INFERENCE APIS ; + + Description + ----------- + Displays the list of inference APIs in the current project. + + Example + -------- + The following command lists all inference APIs:: + + SHOW INFERENCE APIS; + + See Also + -------- + * ``START MODEL model_name`` + * ``STOP MODEL model_name`` + * ``DROP INFERENCE API model_name`` + + """ # noqa: E501 + + def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]: + inference_api_manager = get_inference_api_manager() + models = inference_api_manager.show() + + res = FusionSQLResult() + res.add_field('Model Name', result.STRING) + res.add_field('Status', result.STRING) + + rows = [] + for model in models: + rows.append(( + model.name, + model.status, + )) + + res.set_rows(rows) + return res + + +ShowInferenceAPIsHandler.register(overwrite=True) + + +class DropInferenceAPIHandler(SQLHandler): + """ + DROP INFERENCE API model_name ; + + # Model Name + model_name = '' + + Description + ----------- + Drops (deletes) an inference API model. + + Arguments + --------- + * ````: Name of the model to drop. + + Example + -------- + The following command drops an inference API:: + + DROP INFERENCE API my_model; + + See Also + -------- + * ``START MODEL model_name`` + * ``STOP MODEL model_name`` + * ``SHOW INFERENCE APIS`` + + """ # noqa: E501 + + def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]: + inference_api = get_inference_api(params) + operation_result = inference_api.drop() + + res = FusionSQLResult() + res.add_field('Status', result.STRING) + res.add_field('Message', result.STRING) + res.set_rows([ + ( + operation_result.status, + operation_result.get_message(), + ), + ]) + + return res + + +DropInferenceAPIHandler.register(overwrite=True) diff --git a/singlestoredb/management/inference_api.py b/singlestoredb/management/inference_api.py index 775ccf6b9..8c18134e0 100644 --- a/singlestoredb/management/inference_api.py +++ b/singlestoredb/management/inference_api.py @@ -3,6 +3,7 @@ import os from typing import Any from typing import Dict +from typing import List from typing import Optional from .utils import vars_to_str @@ -76,6 +77,48 @@ def from_stop_response(cls, response: Dict[str, Any]) -> 'ModelOperationResult': hosting_platform=response.get('hostingPlatform', ''), ) + @classmethod + def from_drop_response(cls, response: Dict[str, Any]) -> 'ModelOperationResult': + """ + Create a ModelOperationResult from a drop operation response. + + Parameters + ---------- + response : dict + Response from the drop endpoint + + Returns + ------- + ModelOperationResult + + """ + return cls( + name=response.get('name', ''), + status=response.get('status', 'Deleted'), + hosting_platform=response.get('hostingPlatform', ''), + ) + + @classmethod + def from_show_response(cls, response: Dict[str, Any]) -> 'ModelOperationResult': + """ + Create a ModelOperationResult from a show operation response. + + Parameters + ---------- + response : dict + Response from the show endpoint (single model info) + + Returns + ------- + ModelOperationResult + + """ + return cls( + name=response.get('name', ''), + status=response.get('status', ''), + hosting_platform=response.get('hostingPlatform', ''), + ) + def get_message(self) -> str: """ Get a human-readable message about the operation. @@ -195,6 +238,20 @@ def stop(self) -> ModelOperationResult: raise ManagementError(msg='No manager associated with this inference API') return self._manager.stop(self.name) + def drop(self) -> ModelOperationResult: + """ + Drop this inference API model. + + Returns + ------- + ModelOperationResult + Result object containing status information about the dropped model + + """ + if self._manager is None: + raise ManagementError(msg='No manager associated with this inference API') + return self._manager.drop(self.name) + class InferenceAPIManager(object): """ @@ -263,3 +320,38 @@ def stop(self, model_name: str) -> ModelOperationResult: raise ManagementError(msg='Manager not initialized') res = self._manager._post(f'models/{model_name}/stop') return ModelOperationResult.from_stop_response(res.json()) + + def show(self) -> List[ModelOperationResult]: + """ + Show all inference APIs in the project. + + Returns + ------- + List[ModelOperationResult] + List of ModelOperationResult objects with status information + + """ + if self._manager is None: + raise ManagementError(msg='Manager not initialized') + res = self._manager._get('models').json() + return [ModelOperationResult.from_show_response(api) for api in res] + + def drop(self, model_name: str) -> ModelOperationResult: + """ + Drop an inference API model. + + Parameters + ---------- + model_name : str + Name of the model to drop + + Returns + ------- + ModelOperationResult + Result object containing status information about the dropped model + + """ + if self._manager is None: + raise ManagementError(msg='Manager not initialized') + res = self._manager._delete(f'models/{model_name}/drop') + return ModelOperationResult.from_drop_response(res.json())