Skip to content

Commit

Permalink
Merge pull request #86 from NimbleBoxAI/v1
Browse files Browse the repository at this point in the history
New LMAO v4 backend [0.13.0rc4]
  • Loading branch information
yashbonde committed May 24, 2023
2 parents 8f551da + 7d4957f commit 9d03779
Show file tree
Hide file tree
Showing 59 changed files with 6,133 additions and 1,540 deletions.
19 changes: 1 addition & 18 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -140,27 +140,10 @@ cython_debug/

# our ignores
.DS_Store
*.cfg
notebooks/
__ignore/
.vscode/
serve_fp.py
*.pt
*.onnx
*.pb

# you have recipes, and then you have dark magic!
__dark_magic/
__secret/

# not need to add / in symlink
.nbx
nbox-kernel
yolov4-trainer-nbox
example_jobs/gperc_model/
ex_jobs
hyperloop
scripts
konark/
_modules/
nbox/_jobs
scripts
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ Copyright 2018- The NimbleBox.ai team. All rights reserved.
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2021-22 NimbleBox.ai
Copyright 2021-23 NimbleBox.ai

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ pip install nbox
pip install nbox
```

# Stability and Compatibility

Status: The library is currently undergoing heavy development.

☝️ Important Note: Current major version is zero (v0.x.x) to accommodate rapid development and fast iteration while getting early feedback from users (feedback on APIs are appreciated!). **The public API need not change** without a major version update before v1.0.0 release.

# 🤷Why NimbleBox

- Write and execute code in Python
Expand Down
39 changes: 30 additions & 9 deletions nbox/assets/exe.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,34 @@ os.environ["PYTHONUNBUFFERED"] = "true" # so print comes when it should come
import fire
import inspect
from functools import lru_cache, partial
from {{ file_name }} import {{ fn_name }}

from nbox import Operator, logger
import nbox.utils as U
from nbox.lib.dist import NBXLet

@lru_cache(1)
def get_op(cloud = False) -> Operator:
def get_op(cloud = False):
# The beauty of this function is that it ensures that the operator class is loaded only once

# first try except is to catch any issues during the import itself
try:
# import user code, add this to the try/except because if the code does not exit and there
# is an infinite loop, there can be a whole bunch of side effects, ex: 100s of LMAO live trackers
from {{ file_name }} import {{ fn_name }}

# we still want to ensure that user initialises `nbox` first so their environment variables are
# always going to hold true
import nbox.utils as U
from nbox import Operator, logger

except Exception as e:
# again import the nbox things so that we can log the traceback and exit the program
import nbox.utils as U
from nbox import Operator, logger

U.log_traceback()
logger.error(f"Failed to load operator: {e}")
U.hard_exit_program(1)

# second is to initialise it as an Operator
try:
# load the operator
obj = {{ init_code }}
if not type(obj) == Operator and {{ load_operator }}:
# there is an initial level of precaution that we use during deployment, but we are adding simple
Expand All @@ -31,7 +49,6 @@ def get_op(cloud = False) -> Operator:
obj = Operator.from_fn(obj)
else:
raise ValueError("{{ fn_name }} is not an Operator or class or function")

# at this point there is a guarantee that obj is an Operator
op: Operator = obj
except Exception as e:
Expand All @@ -48,10 +65,14 @@ def get_op(cloud = False) -> Operator:
U.log_traceback()
logger.error(f"Failed to remote initialise operator: {e}")
U.hard_exit_program(1)
return op

# now import the class as well and return a builder function
from nbox.lib.dist import NBXLet
return lambda : NBXLet(op = op)

if __name__ == "__main__":
nbxlet = NBXLet(op = get_op(cloud = True))
builder = get_op(cloud = True)
nbxlet = builder()
fire.Fire({
"run": nbxlet.run, # NBX-Jobs
"serve": partial(
Expand Down
92 changes: 73 additions & 19 deletions nbox/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
"""
import os
import json
import socket
import requests
import webbrowser
from typing import Dict
from getpass import getpass
from functools import lru_cache
from dataclasses import dataclass

import nbox.utils as U
from nbox.utils import join, logger, lo
Expand Down Expand Up @@ -46,7 +48,22 @@ class JobDetails(object):
job_id: str
run_id: str

# class DeployDetails(object):
class DeployDetails(object):
deployment_id: str
model_id: str


@dataclass
class AgentDetails():
group_id: str
instance_id: str
nbx_type: str


NBX_JOB_TYPE = "job"
NBX_DEPLOY_TYPE = "deploy"
NBX_LOCAL_TYPE = "local"


class NBXClient:
def __init__(self, nbx_url = "https://app.nimblebox.ai"):
Expand Down Expand Up @@ -175,30 +192,62 @@ def __call__(self, item, default=None, reload: bool = False):

@property
def workspace_id(self) -> str:
return self.get(AuthConfig.workspace_id) or self.get(AuthConfig._workspace_id)
return self.get(AuthConfig.workspace_id, "") or self.get(AuthConfig._workspace_id, "")

@property
def workspace_name(self) -> str:
return self(AuthConfig.workspace_name, "")

@property
def nbx_url(self) -> str:
return self.get(AuthConfig.url)
return self.get(AuthConfig.url, "")

@property
def access_token(self) -> str:
return self.get(AuthConfig.access_token)
return self.get(AuthConfig.access_token, "")

@property
def username(self) -> str:
return self.get(AuthConfig.username)
return self.get(AuthConfig.username, "")

@property
def run_details(self):
return secret(AuthConfig.nbx_pod_run, {})

def get_agent_details(self) -> Dict[str, str]:
if ConfigString.nbx_pod_run in self.secrets:
@property
def inside_pod(self) -> bool:
return self.inside_job_pod or self.inside_deploy_pod

@property
def inside_job_pod(self) -> bool:
return ConfigString.nbx_pod_run in self.secrets

@property
def inside_deploy_pod(self) -> bool:
return ConfigString.nbx_pod_deploy in self.secrets

def get_agent_details(self) -> AgentDetails:
if self.inside_job_pod:
run_data = self.secrets[ConfigString.nbx_pod_run]
jd = JobDetails()
jd.job_id = run_data.get("job_id", None)
jd.run_id = run_data.get("token", None)
return jd
# elif ConfigString.nbx_pod_deploy in self.secrets:
# return self.secrets[ConfigString.nbx_pod_deploy]
return {}
out = AgentDetails(
group_id = run_data.get("job_id", None),
instance_id = run_data.get("token", None),
nbx_type = NBX_JOB_TYPE
)
elif self.inside_deploy_pod:
deploy_data = self.secrets[ConfigString.nbx_pod_deploy]
out = AgentDetails(
group_id = deploy_data.get("deployment_id", None),
instance_id = deploy_data.get("model_id", None),
nbx_type = NBX_DEPLOY_TYPE
)
else:
out = AgentDetails(
group_id = f"local-{socket.gethostname()}",
instance_id = f"{socket.gethostbyname(socket.gethostname())}-{os.getpid()}",
nbx_type = NBX_LOCAL_TYPE
)
return out


def init_secret():
Expand All @@ -211,10 +260,13 @@ def init_secret():
logger.info(lo(
f"workspace details",
workspace_id = secret.workspace_id,
workspace_name = AuthConfig.workspace_name,
workspace_name = secret.workspace_name,
token_present = len(secret.access_token) > 0,
nbx_url = secret.nbx_url,
))

if not secret.workspace_id:
raise Exception("Workspace ID not found. Please run `nbox login` to login to NimbleBox.")
return secret
else:
logger.info(f"Skipping authentication as NBOX_NO_AUTH is set to True")
Expand All @@ -231,10 +283,12 @@ def auth_info_pb():
from nbox.hyperloop.common.common_pb2 import NBXAuthInfo

return NBXAuthInfo(
username = secret(AuthConfig.username),
workspace_id = secret(AuthConfig.workspace_id) or secret(AuthConfig._workspace_id),
access_token = secret(AuthConfig.access_token),
username = secret.username,
workspace_id = secret.workspace_id,
access_token = secret.access_token,
)

def inside_pod():
return secret(AuthConfig.nbx_pod_run, False) or secret(AuthConfig.nbx_pod_deploy, False)
if secret is None:
raise Exception("Secrets not initialized. Cannot determine where am I.")
return secret.inside_pod
28 changes: 16 additions & 12 deletions nbox/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,21 @@
from typing import Dict, Any

import nbox.utils as U
from nbox.jobs import Job, Serve
from nbox.init import nbox_ws_v1
from nbox.auth import init_secret, AuthConfig, secret
from nbox.instance import Instance
from nbox.sub_utils.ssh import tunnel
from nbox.relics import Relics
from nbox.lmao import LmaoCLI
from nbox.lmao_v4 import LmaoCLI as Lmaov4CLI
from nbox.version import __version__ as V
from nbox.nbxlib.fire import NBXFire
from nbox.projects import Project
from nbox.utils import logger, lo
from nbox.plugins.base import PluginCLI

# from nbox.jobs import Job, Serve
from nbox.jd_core import JobsCli, ServeCli

class Config(object):
def update(self, workspace_id: str):
"""Set global config for `nbox`"""
Expand All @@ -42,7 +44,7 @@ def update(self, workspace_id: str):
redo = not data or (workspace_id not in data)
if redo:
workspaces = requests.get(
secret(AuthConfig.url) + f"/api/v1/workspace",
secret.nbx_url + f"/api/v1/workspace",
headers = nbox_ws_v1._session.headers
).json()["data"]
# workspaces = nbox_ws_v1.workspace()
Expand Down Expand Up @@ -71,11 +73,11 @@ def show(self):
"""Pretty print global config for `nbox`"""
logger.info(lo(
"nbox config:",
workspace_name = secret(AuthConfig.workspace_name),
workspace_id = secret(AuthConfig.workspace_id),
username = secret(AuthConfig.username),
workspace_name = secret.workspace_id,
workspace_id = secret.workspace_id,
username = secret.username,
nbox = V,
URL = secret(AuthConfig.url),
URL = secret.nbx_url,
))

def clear(self):
Expand All @@ -86,7 +88,7 @@ def clear(self):

def open_home():
"""Open current NBX platform"""
webbrowser.open(secret(AuthConfig.url))
webbrowser.open(secret.nbx_url)


def get(api_end: str, no_pp: bool = False, **kwargs):
Expand Down Expand Up @@ -179,22 +181,24 @@ def main():
"build" : Instance,
"config" : Config,
"get" : get,
"jobs" : Job,
"lmao" : LmaoCLI,
# "jobs" : Job,
"jobs" : JobsCli,
# "lmao" : LmaoCLI,
"lmao" : Lmaov4CLI,
"login" : login,
"open" : open_home,
"plugins" : PluginCLI,
"projects" : Project,
"relics" : Relics,
"serve" : Serve,
# "serve" : Serve,
"serve" : ServeCli,
"tunnel" : tunnel,
"version" : version,
"why" : why,
"ws" : NBXWS_CLI,
}

fire.Fire(component)
# NBXFire(component)

if __name__ == "__main__":
main()
Loading

0 comments on commit 9d03779

Please sign in to comment.