def list_runs(request: Request, project_id: int, experiment_id: Text) -> JSONResponse: """Get runs list. Args: project_id {int}: project id experiment_id {Text}: experiment id Returns: starlette.responses.JSONResponse """ log_request(request) project_manager = ProjectManager() url = project_manager.get_internal_tracking_uri(project_id) resp = requests.post(url=f'{url}/api/2.0/preview/mlflow/runs/search', json={'experiment_ids': [experiment_id]}) if resp.status_code != HTTPStatus.OK: return error_response(http_response_code=resp.status_code, message=resp.json().get('message')) runs = resp.json().get('runs', []) for run in runs: run['id'] = run.get('info', {}).get('run_id') return JSONResponse(runs)
def get_model(request: Request, model_id: Text, project_id: int) -> JSONResponse: """Get model. Args: model_id {Text}: model id (name) project_id {int}: project id Returns: starlette.responses.JSONResponse """ log_request(request) project_manager = ProjectManager() url = project_manager.get_internal_tracking_uri(project_id) model_resp = requests.post( url=f'{url}/api/2.0/preview/mlflow/registered-models/get-details', json={'registered_model': {'name': model_id}} ) if model_resp.status_code != HTTPStatus.OK: return error_response( http_response_code=model_resp.status_code, message=model_resp.json().get('message') ) registered_model_detailed = model_resp.json().get('registered_model_detailed', {}) model = { 'id': registered_model_detailed.get('registered_model', {}).get('name'), 'project_id': project_id, 'creation_timestamp': registered_model_detailed.get('creation_timestamp'), 'last_updated_timestamp': registered_model_detailed.get('last_updated_timestamp') } return JSONResponse(model)
def update_project( request: Request, project_id: int, name: Text = Form(None), description: Text = Form(None) ) -> JSONResponse: """Update project. Args: project_id {int}: project id name {Text}: project name description {Text}: project description Returns: starlette.responses.JSONResponse """ log_request(request, { 'project_id': project_id, 'name': name, 'description': description }) project_manager = ProjectManager() if name is not None: project_manager.update_project_name(project_id, name) if description is not None: project_manager.update_project_description(project_id, description) project = project_manager.get_project(project_id) return JSONResponse(project)
def create_deployment(request: Request, project_id: int, model_id: Text, version: Text, type: Text) -> JSONResponse: """Create deployment. Args: project_id {int}: project id model_id {Text}: model id (name) version {Text}: model version type {Text}: deployment type Returns: starlette.responses.JSONResponse """ # pylint: disable=redefined-builtin log_request(request, { 'project_id': project_id, 'model_id': model_id, 'version': version, 'type': type }) model_uri = get_model_version_uri(project_id, model_id, version) deploy_resp = requests.post( url='http://deploy:9000/deployments', data={ 'project_id': project_id, 'model_id': model_id, 'version': version, 'model_uri': model_uri, 'type': type } ) return JSONResponse(deploy_resp.json(), deploy_resp.status_code)
def delete_experiment(request: Request, experiment_id: Text, project_id: int) -> JSONResponse: """Delete experiment. Args: experiment_id {Text}: experiment id project_id {int}: project id Returns: starlette.responses.JSONResponse """ log_request(request, { 'project_id': project_id, 'experiment_id': experiment_id }) project_manager = ProjectManager() url = project_manager.get_internal_tracking_uri(project_id) experiment_resp = requests.post( url=f'{url}/api/2.0/preview/mlflow/experiments/delete', json={'experiment_id': experiment_id}) if experiment_resp.status_code != HTTPStatus.OK: return error_response(http_response_code=experiment_resp.status_code, message=experiment_resp.json().get('message')) return JSONResponse({'experiment_id': experiment_id})
def delete_model(request: Request, model_id: Text, project_id: int) -> JSONResponse: """Delete model. Args: model_id {Text}: model id (name) project_id {int}: project id Returns: starlette.responses.JSONResponse """ log_request(request, { 'project_id': project_id, 'model_id': model_id }) project_manager = ProjectManager() url = project_manager.get_internal_tracking_uri(project_id) model_resp = requests.delete( url=f'{url}/api/2.0/preview/mlflow/registered-models/delete', json={'registered_model': {'name': model_id}} ) if model_resp.status_code != HTTPStatus.OK: return error_response( http_response_code=model_resp.status_code, message=model_resp.json().get('message') ) return JSONResponse({'model_id': model_id})
def list_models(request: Request, project_id: int) -> JSONResponse: """Get models list. Args: project_id {int}: project id Returns: starlette.responses.JSONResponse """ log_request(request) project_manager = ProjectManager() url = project_manager.get_internal_tracking_uri(project_id) resp = requests.get(f'{url}/api/2.0/preview/mlflow/registered-models/list') registered_models = [] for model in resp.json().get('registered_models_detailed', []): registered_models.append({ 'id': model.get('registered_model', {}).get('name'), 'project_id': project_id, 'creation_timestamp': model.get('creation_timestamp'), 'last_updated_timestamp': model.get('last_updated_timestamp') }) return JSONResponse(registered_models)
def list_deployments(request: Request) -> JSONResponse: """Get deployments list. Returns: starlette.responses.JSONResponse """ log_request(request) deployments = requests.get('http://deploy:9000/deployments').json() return JSONResponse(deployments)
def healthcheck(request: Request) -> Text: """Get healthcheck. Returns: Text: OK """ log_request(request) return 'OK'
def list_experiments(request: Request, project_id: int) -> JSONResponse: """Get experiments list. Args: project_id {int}: project id Returns: starlette.responses.JSONResponse """ log_request(request) project_manager = ProjectManager() url = project_manager.get_internal_tracking_uri(project_id) resp = requests.get(url=f'{url}/api/2.0/preview/mlflow/experiments/list') experiments = [] for exp in resp.json().get('experiments'): experiment_id = exp.get('experiment_id') runs_resp = requests.get( f'{url}/api/2.0/preview/mlflow/runs/search?experiment_ids=[{experiment_id}]' ) runs = runs_resp.json().get('runs', []) creation_time = '' last_update_time = '' """ if corresponding tags are empty then fields: * creation_time = start_time of the first run; * last_update_time = end_time of the last run. """ if len(runs) > 0: creation_time = runs[len(runs) - 1].get('info', {}).get('start_time') last_update_time = runs[0].get('info', {}).get('end_time') tags = {tag['key']: tag['value'] for tag in exp.get('tags', [])} experiments.append({ 'id': experiment_id, 'user_id': tags.get('user_id', ''), 'name': exp.get('name'), 'artifact_location': exp.get('artifact_location'), 'lifecycle_stage': exp.get('lifecycle_stage'), 'last_update_time': tags.get('last_update_time', last_update_time), 'creation_time': tags.get('creation_time', creation_time), 'description': tags.get('mlflow.note.content', ''), 'project_id': tags.get('project_id', project_id) }) return JSONResponse(experiments)
def list_projects(request: Request) -> JSONResponse: """Get projects list. Returns: starlette.responses.JSONResponse """ log_request(request) project_manager = ProjectManager() projects = project_manager.list_projects() return JSONResponse(projects)
def register_model( request: Request, project_id: int, name: Text = Form(...), source: Text = Form(...), run_id: Text = Form(...) ) -> JSONResponse: """Register model. Args: project_id {int}: project id name {Text}: model name source {Text}: path to model package run_id {Text}: run id Returns: starlette.responses.JSONResponse """ log_request(request, { 'project_id': project_id, 'name': name, 'source': source, 'run_id': run_id }) project_manager = ProjectManager() if not is_model(source): raise ModelDoesNotExistError(f'Model {source} does not exist or is not MLflow model') url = project_manager.get_internal_tracking_uri(project_id) requests.post( url=f'{url}/api/2.0/preview/mlflow/registered-models/create', json={'name': name} ) requests.post( url=f'{url}/api/2.0/preview/mlflow/model-versions/create', json={ 'name': name, 'source': source, 'run_id': run_id } ) model_resp = requests.post( url=f'{url}/api/2.0/preview/mlflow/registered-models/get-details', json={'registered_model': {'name': name}} ) registered_model_detailed = model_resp.json().get('registered_model_detailed', {}) model = { 'id': name, 'project_id': project_id, 'creation_timestamp': registered_model_detailed.get('creation_timestamp'), 'last_updated_timestamp': registered_model_detailed.get('last_updated_timestamp') } return JSONResponse(model, HTTPStatus.CREATED)
def get_deployment(request: Request, deployment_id: int) -> JSONResponse: """Get deployment. Args: deployment_id {int}: deployment id Returns: starlette.responses.JSONResponse """ log_request(request) deploy_resp = requests.get(f'http://deploy:9000/deployments/{deployment_id}') return JSONResponse(deploy_resp.json(), deploy_resp.status_code)
def ping(request: Request, deployment_id: int) -> Response: """Ping deployment. Args: deployment_id {int}: deployment id Returns: starlette.responses.JSONResponse """ log_request(request) deploy_resp = requests.get(f'http://deploy:9000/deployments/{deployment_id}/ping') return JSONResponse(deploy_resp.text, status_code=deploy_resp.status_code)
def get_project(request: Request, project_id: int) -> JSONResponse: # pylint: disable=invalid-name,redefined-builtin """Get project. Args: project_id {int}: project id Returns: starlette.responses.JSONResponse """ log_request(request) project_manager = ProjectManager() project = project_manager.get_project(project_id) return JSONResponse(project)
def stat(request: Request) -> JSONResponse: """Get statistics of resources usage. Returns: starlette.responses.JSONResponse """ log_request(request) project_manager = ProjectManager() return JSONResponse( dict(projects=project_manager.running_projects_stat(), system=system_stat()))
def run_deployment(request: Request, deployment_id: int) -> JSONResponse: """Run deployment. Args: deployment_id {int}: deployment id Returns: starlette.responses.JSONResponse """ log_request(request, { 'deployment_id': deployment_id }) deploy_resp = requests.put(f'http://deploy:9000/deployments/{deployment_id}/run') return JSONResponse(deploy_resp.json(), deploy_resp.status_code)
def get_validation_report( request: Request, deployment_id: int, timestamp_from: float, timestamp_to: float) -> JSONResponse: log_request(request) deploy_resp = requests.get( f'http://deploy:9000/deployments/{deployment_id}/validation-report?' f'timestamp_from={timestamp_from}×tamp_to={timestamp_to}' ) return JSONResponse(deploy_resp.json(), status_code=deploy_resp.status_code)
def delete_deployment(request: Request, deployment_id: int) -> JSONResponse: """Delete deployment (mark deployment as deleted). Args: deployment_id {int}: deployment id Returns: starlette.responses.JSONResponse """ log_request(request, { 'deployment_id': deployment_id }) deploy_resp = requests.delete(f'http://deploy:9000/deployments/{deployment_id}') return JSONResponse(deploy_resp.json(), deploy_resp.status_code)
def get_experiment(request: Request, experiment_id: Text, project_id: int) -> JSONResponse: """Get experiment. Args: experiment_id {Text}: experiment id project_id {int}: project id Returns: starlette.responses.JSONResponse """ log_request(request) project_manager = ProjectManager() url = project_manager.get_internal_tracking_uri(project_id) experiment_resp = requests.get( url= f'{url}/api/2.0/preview/mlflow/experiments/get?experiment_id={experiment_id}' ) if experiment_resp.status_code != HTTPStatus.OK: return error_response(http_response_code=experiment_resp.status_code, message=experiment_resp.json().get('message')) experiment = experiment_resp.json().get('experiment') experiment_id = experiment.get('experiment_id') runs_resp = requests.get( f'{url}/api/2.0/preview/mlflow/runs/search?experiment_ids=[{experiment_id}]' ) runs = runs_resp.json().get('runs', []) creation_time = '' last_update_time = '' """ if corresponding tags are empty then fields: * creation_time = start_time of the first run; * last_update_time = end_time of the last run. """ if len(runs) > 0: creation_time = runs[len(runs) - 1].get('info', {}).get('start_time') last_update_time = runs[0].get('info', {}).get('end_time') experiment['id'] = experiment.pop('experiment_id') tags = {tag['key']: tag['value'] for tag in experiment.pop('tags', [])} experiment['description'] = tags.get('mlflow.note.content', '') experiment['user_id'] = tags.get('user_id', '') experiment['project_id'] = tags.get('project_id', project_id) experiment['creation_time'] = tags.get('creation_time', creation_time) experiment['last_update_time'] = tags.get('last_update_time', last_update_time) return JSONResponse(experiment)
def restore(request: Request, project_id: int) -> JSONResponse: # pylint: disable=invalid-name,redefined-builtin """Restore project. Args: project_id {int}: project id Returns: starlette.responses.JSONResponse """ log_request(request, {'project_id': project_id}) project_manager = ProjectManager() project_manager.restore(project_id) project = project_manager.get_project(project_id) return JSONResponse(project, HTTPStatus.OK)
def list_artifacts(request: Request, project_id: int, run_id: Text) -> JSONResponse: """Get artifacts list. Args: project_id {int}: project id run_id {int}: run_id Returns: starlette.responses.JSONResponse """ log_request(request, {'project_id': project_id, 'run_id': run_id}) project_manager = ProjectManager() url = project_manager.get_internal_tracking_uri(project_id) runs_resp = requests.get( url=f'{url}/api/2.0/preview/mlflow/artifacts/list?run_id={run_id}') if runs_resp.status_code != HTTPStatus.OK: return error_response(http_response_code=runs_resp.status_code, message=runs_resp.json().get('message')) runs = runs_resp.json() root_uri = runs.get('root_uri') files = runs.get('files', []) runs_list = [] for i, file in enumerate(files): runs_resp = requests.get( url=f'{url}/api/2.0/preview/mlflow/runs/get?run_id={run_id}', ) run = runs_resp.json() run_info = run.get('run', {}).get('info', {}) experiment_id = run_info.get('experiment_id') runs_list.append({ 'id': f'{project_id}{experiment_id}{run_id}{i}', 'project_id': project_id, 'experiment_id': experiment_id, 'run_id': run_id, 'type': str(get_artifact_type(root_uri, file)), 'creation_timestamp': run_info.get('start_time'), 'root_uri': root_uri, 'path': file.get('path') }) return JSONResponse(runs_list)
def project_healthcheck(request: Request, project_id: int) -> JSONResponse: # pylint: disable=invalid-name,redefined-builtin """Get project healthcheck (check if project's tracking server process was started). Args: project_id {int}: project id Returns: starlette.responses.JSONResponse """ log_request(request) project_manager = ProjectManager() project = project_manager.get_project(project_id) is_running = project_manager._is_running(project_id) if is_running: return JSONResponse(project, HTTPStatus.OK) else: return JSONResponse(project, HTTPStatus.BAD_REQUEST)
def create_project( request: Request, name: Text = Form(...), description: Text = Form('') ) -> JSONResponse: """Create project. Args: name {Text}: project name description {Text}: project description Returns: starlette.responses.JSONResponse """ log_request(request, {'name': name, 'description': description}) project_manager = ProjectManager() project_id = project_manager.create_project(name, description) project = project_manager.get_project(project_id) return JSONResponse(project, HTTPStatus.CREATED)
def ping(request: Request, project_id: int) -> JSONResponse: """Ping project's tracking server. Args: project_id {int}: project id Returns: starlette.responses.JSONResponse """ log_request(request) project_manager = ProjectManager() url = project_manager.get_internal_tracking_uri(project_id) project = project_manager.get_project(project_id) try: requests.get(url) return JSONResponse(project, HTTPStatus.OK) except requests.exceptions.ConnectionError: return JSONResponse(project, HTTPStatus.BAD_REQUEST)
def predict(request: Request, deployment_id: int, data: Text = Form(...)) -> JSONResponse: """Predict data on deployment. Args: deployment_id {int}: deployment id data {Text}: data to predict Returns: starlette.responses.JSONResponse """ log_request(request, { 'deployment_id': deployment_id, 'data': data }) deploy_resp = requests.post( url=f'http://deploy:9000/deployments/{deployment_id}/predict', data={'data': data} ) return JSONResponse(deploy_resp.json(), deploy_resp.status_code)
def run_project(request: Request, project_id: int) -> JSONResponse: # pylint: disable=invalid-name,redefined-builtin """Run project's tracking server. Args: project_id {int}: project id Returns: starlette.responses.JSONResponse """ log_request(request, {'project_id': project_id}) project_manager = ProjectManager() running = project_manager.run(project_id) if not running: return error_response( http_response_code=HTTPStatus.INTERNAL_SERVER_ERROR, message='Internal error, tracking server has terminated') project = project_manager.get_project(project_id) return JSONResponse(project, HTTPStatus.OK)
def list_model_versions(request: Request, project_id: int, model_id: Optional[Text] = None) -> JSONResponse: """Get model versions list. Args: project_id {int}: project id model_id {Text}: model id (name) Returns: starlette.responses.JSONResponse """ log_request(request) model_versions = get_model_versions(project_id) if model_id is not None: check_if_project_and_model_exist(project_id, model_id) model_versions = filter_model_versions(model_versions, model_id) versions = [] for version_info in model_versions: model_version = version_info.get('model_version', {}) version_number = model_version.get('version') model_id = model_version.get('registered_model', {}).get('name') versions.append({ 'id': model_id + version_number, 'model_id': model_id, 'project_id': project_id, 'version': version_number, 'creation_timestamp': version_info.get('creation_timestamp'), 'last_updated_timestamp': version_info.get('last_updated_timestamp'), 'run_id': version_info.get('run_id'), 'model_uri': version_info.get('source') }) return JSONResponse(versions)
def get_run(request: Request, run_id: Text, project_id: int) -> JSONResponse: """Get run. Args: run_id {Text}: run id project_id {int}: project id Returns: starlette.responses.JSONResponse """ log_request(request) project_manager = ProjectManager() url = project_manager.get_internal_tracking_uri(project_id) resp = requests.get( url=f'{url}/api/2.0/preview/mlflow/runs/get?run_id={run_id}', ) if resp.status_code != HTTPStatus.OK: return error_response(http_response_code=resp.status_code, message=resp.json().get('message')) run = resp.json().get('run') run['id'] = run.get('info', {}).get('run_id') return JSONResponse(run)
def get_model_version(request: Request, version: Text, project_id: int, model_id: Text) -> JSONResponse: """Get model versions list. Args: project_id {int}: project id model_id {Text}: model id (name) Returns: starlette.responses.JSONResponse """ log_request(request) check_if_project_and_model_exist(project_id, model_id) model_versions = filter_model_versions(get_model_versions(project_id), model_id) for version_info in model_versions: model_version = version_info.get('model_version', {}) version_number = model_version.get('version') if version_number == version: return JSONResponse({ 'id': version_number, 'model_id': model_version.get('registered_model', {}).get('name'), 'project_id': project_id, 'version': version_number, 'creation_timestamp': version_info.get('creation_timestamp'), 'last_updated_timestamp': version_info.get('last_updated_timestamp'), 'run_id': version_info.get('run_id'), 'model_uri': version_info.get('source') }) return error_response( http_response_code=HTTPStatus.NOT_FOUND, message=f'Version {version} of model {model_id} in project {project_id} not found' )