From 2f9847411f8946f89a1a788e72a3b1f5fa6d1419 Mon Sep 17 00:00:00 2001 From: Heiru Wu Date: Tue, 26 Sep 2023 07:18:26 +0800 Subject: [PATCH 1/5] chore: fix typo --- instill/clients/client.py | 4 ++-- instill/resources/model.py | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/instill/clients/client.py b/instill/clients/client.py index 8e25671..16329cc 100644 --- a/instill/clients/client.py +++ b/instill/clients/client.py @@ -54,13 +54,13 @@ def __init__(self) -> None: self.mgmt_service = _get_mgmt_client() self.connector_service = _get_connector_clinet() self.pipeline_service = _get_pipeline_clinet() - self.model_serevice = _get_model_clinet() + self.model_service = _get_model_clinet() def set_instance(self, instance: str): self.mgmt_service.instance = instance self.connector_service.instance = instance self.pipeline_service.instance = instance - self.model_serevice.instance = instance + self.model_service.instance = instance def get_client() -> InstillClient: diff --git a/instill/resources/model.py b/instill/resources/model.py index 98c1e11..4ea63c6 100644 --- a/instill/resources/model.py +++ b/instill/resources/model.py @@ -15,9 +15,9 @@ def __init__( ) -> None: super().__init__() self.client = client - model = client.model_serevice.get_model(model_name=name, silent=True) + model = client.model_service.get_model(model_name=name, silent=True) if model is None: - model = client.model_serevice.create_model( + model = client.model_service.create_model( name=name, definition=definition, configuration=configuration, @@ -29,10 +29,10 @@ def __init__( def __del__(self): if self.resource is not None: - self.client.model_serevice.delete_model(self.resource.id) + self.client.model_service.delete_model(self.resource.id) def __call__(self, task_inputs: list) -> list: - return self.client.model_serevice.trigger_model(self.resource.id, task_inputs) + return self.client.model_service.trigger_model(self.resource.id, task_inputs) @property def client(self): @@ -51,7 +51,7 @@ def resource(self, resource: model_interface.Model): self._resource = resource def _update(self): - self.resource = self.client.model_serevice.get_model( + self.resource = self.client.model_service.get_model( model_name=self.resource.id ) @@ -59,18 +59,18 @@ def get_definition(self) -> model_definition_interface.ModelDefinition: return self.resource.model_definition def get_readme(self) -> str: - return self.client.model_serevice.get_model_card(self.resource.id) + return self.client.model_service.get_model_card(self.resource.id) def get_state(self) -> model_interface.Model.State: - return self.client.model_serevice.watch_model(self.resource.id) + return self.client.model_service.watch_model(self.resource.id) def deploy(self) -> model_interface.Model: - self.client.model_serevice.deploy_model(self.resource.id) + self.client.model_service.deploy_model(self.resource.id) self._update() return self._resource def undeploy(self) -> model_interface.Model: - self.client.model_serevice.undeploy_model(self.resource.id) + self.client.model_service.undeploy_model(self.resource.id) self._update() return self._resource From 20182ee8b42d0fa39083b0f9bd3064430d910051 Mon Sep 17 00:00:00 2001 From: Heiru Wu Date: Tue, 26 Sep 2023 07:18:43 +0800 Subject: [PATCH 2/5] chore: fix integration-test --- integration-test.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/integration-test.py b/integration-test.py index 8ce73ed..19032e4 100644 --- a/integration-test.py +++ b/integration-test.py @@ -46,7 +46,7 @@ # ================================================================================================================ # ===================================================== model ==================================================== - assert client.model_serevice.is_serving() + assert client.model_service.is_serving() Logger.i("model client created, assert status == serving: True") model = GithubModel( @@ -183,11 +183,7 @@ }, ) - recipe = pipeline_pb.Recipe() - recipe.version = "v1alpha" - recipe.components.append(start_operator_component) - recipe.components.append(instill_model_connector_component) - recipe.components.append(end_operator_component) + recipe = create_recipe([start_operator_component, instill_model_connector_component, end_operator_component]) instill_model_pipeline = Pipeline( client=client, name="instill-model-pipeline", recipe=recipe ) From c251a61c6dda6f56bae72899c90700cdce1d99f4 Mon Sep 17 00:00:00 2001 From: Heiru Wu Date: Tue, 26 Sep 2023 07:19:04 +0800 Subject: [PATCH 3/5] docs(readme): add usage --- README.md | 276 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 274 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9a0ada3..df0ee2c 100644 --- a/README.md +++ b/README.md @@ -91,11 +91,283 @@ hosts: ## Usage -Comming soon +### Create client +Simply import the `get_client` function to get the client that are connected to all services with the config you setup previously. -### You can find a [_notebook example_](notebooks/model_usage.ipynb) here +```python +from instill.clients import get_client + +client = get_clinet() +``` + +You can check the readiness of each service + +```python +client.mgmt_service.is_serving() +# True +client.connector_service.is_serving() +# True +client.pipeline_service.is_serving() +# True +client.model_service.is_serving() +# True +``` + +> [!NOTE] +> Depends on which project(`Instill VDP` or `Instill Model` or both) you had launched locally, some services might not be available. + +After making sure all desired services are serving, we can check the user status by + +```python +client.mgmt_service.get_user() +``` + +If you have a valid `api_token` in your config file, you should see something like this + +``` +name: "users/admin" +uid: "4767b74d-640a-4cdf-9c6d-7bb0e36098a0" +id: "admin" +type: OWNER_TYPE_USER +create_time { + seconds: 1695589596 + nanos: 36522000 +} +update_time { + seconds: 1695589749 + nanos: 544980000 +} +email: "hello@instill.tech" +first_name: "Instill" +last_name: "AI" +org_name: "Instill AI" +role: "hobbyist" +newsletter_subscription: true +cookie_token: "" +``` + +#### Now we can proceed to create resources + +### Create Model + +Let's say we want to serve a `yolov7` model from `github` with the following configs + +```python +model = { + "model_name": "yolov7", + "model_repo": "instill-ai/model-yolov7-dvc", + "model_tag": "v1.0-cpu", +} +``` + +Simply import the GithubModel resource and fill in the corresponding fields + +```python +from instill.resources.model import GithubModel + +yolov7 = GithubModel( + client=client, + name=model["model_name"], + model_repo=model["model_repo"], + model_tag=model["model_tag"], +) +``` + +After the creation is done, we can check the status of the model + +```python +yolov7.get_state() +# 1 +# means STATE_OFFLINE +``` + +> [!NOTE] +> Returned is an enum type of ModelState, check out our [openapi](https://github.com/instill-ai/protobufs/blob/main/openapiv2/openapiv2.swagger.yaml#L7018-L7031) + +Now we can deploy the model + +```python +yolov7.deploy() +``` + +Check the status + +```python +yolov7.get_state() +# 2 +# means STATE_ONLINE +``` + +Trigger the model with the correct `task` type + +> [!NOTE] +> Find out the definition in the [doc](https://www.instill.tech/docs/model/core-concepts/ai-task) + +```python +from instill.resources import model_pb, task_detection +task_inputs = [ + model_pb.TaskInput( + detection=task_detection.DetectionInput( + image_url="https://artifacts.instill.tech/imgs/dog.jpg" + ) + ), + model_pb.TaskInput( + detection=task_detection.DetectionInput( + image_url="https://artifacts.instill.tech/imgs/bear.jpg" + ) + ), + model_pb.TaskInput( + detection=task_detection.DetectionInput( + image_url="https://artifacts.instill.tech/imgs/polar-bear.jpg" + ) + ), +] + +outputs = yolov7(task_inputs=task_inputs) +``` + +Now if you `print` the outputs, you will get a list of specific `task` output, in this case is a list of `TASK_DETECTION` output + +``` +[detection { + objects { + category: "dog" + score: 0.958271801 + bounding_box { + top: 102 + left: 324 + width: 208 + height: 403 + } + } + objects { + category: "dog" + score: 0.945684791 + bounding_box { + top: 198 + left: 130 + width: 198 + height: 236 + } + } +} +, detection { + objects { + category: "bear" + score: 0.968335629 + bounding_box { + top: 85 + left: 291 + width: 554 + height: 756 + } + } +} +, detection { + objects { + category: "bear" + score: 0.948612273 + bounding_box { + top: 458 + left: 1373 + width: 1298 + height: 2162 + } + } +} +] +``` + +### Create connector + +With similiar conecpt as creating `model`, below is the script to create a `instill model connector` + +```python +from instill.resources import InstillModelConnector, connector_pb + +# specify the `Instill Model` host url +instill_model = InstillModelConnector( + client, + name="instill", + server_url="http://api-gateway:8080", +) +# after creation the state is `STATE_DISCONNECTED` +instill_model.get_state() == connector_pb.ConnectorResource.STATE_DISCONNECTED + +# we can test the connection to make sure the connection with the host can be established +instill_model.test() == connector_pb.ConnectorResource.STATE_CONNECTED +``` + +### Create pipeline + +> [!NOTE] +> Before starting to create a pipleine, we suggest you read through our [docs](https://www.instill.tech/docs/vdp/core-concepts/overview) first to grasp the core concepts + +Since we have created a `Instill Model Connector` that connect to our `Instill Model` instance, we can now create a pipeline that utilize both `Instill VDP` and `Instill Model` + +```python +from instill.resources import ( + Pipeline, + pipeline_pb, + create_start_operator, + create_end_operator, + create_recipe, +) + +# create start operator +start_operator_component = create_start_operator( + {"metadata": {"input": {"title": "input", "type": "image"}}} +) +# create end operator +end_operator_component = create_end_operator( + config={ + "input": {"output": "{ yolov7.output.objects }"}, + "metadata": {"output": {}}, + } +) +# create model connector component from the connector resource we had previously +# here we need to specify which model we want to use on our `Instill Model` instance +# in this case there is only one model we deployed, which is the yolov7 model +instill_model_connector_component = instill_model.create_component( + name="yolov7", + config={ + "input": { + "task": "TASK_DETECTION", + "image_base64": "{ start.input }", + "model_name": "users/admin/models/yolov7", + }, + }, +) +# create a recipe to construct the pipeline +recipe = create_recipe([start_operator_component, instill_model_connector_component, end_operator_component]) +# create pipeline +instill_model_pipeline = Pipeline( + client=client, name="instill-model-pipeline", recipe=recipe +) +# we can trigger the pipeline now +i = Struct() +i.update( + { + "input": base64.b64encode( + requests.get( + "https://artifacts.instill.tech/imgs/dog.jpg", timeout=5 + ).content + ).decode("ascii") + } +) +# verify the output +instill_model_pipeline([i])[0][0]["output"][0]["category"] == "dog" +``` ## Contributing Please refer to the [Contributing Guidelines](./.github/CONTRIBUTING.md) for more details. + +## Community support + +Please refer to the [community](https://github.com/instill-ai/community) repository. + +## License + +See the [LICENSE](./LICENSE) file for licensing information. From 74fad06a23323d6e6d252ec8582f9d8d224e6d0b Mon Sep 17 00:00:00 2001 From: Heiru Wu Date: Tue, 26 Sep 2023 07:24:39 +0800 Subject: [PATCH 4/5] chore: add anchor for dev setup --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index df0ee2c..07d4b10 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,9 @@ python sdk for Instill AI products ## Setup +> [!NOTE] +> For setting up development environment, please refer to [Controbuting](#contributing) + ### Requirements - Python 3.8+ From dee8434fbe67f3adcf1d80edffb108307de9c671 Mon Sep 17 00:00:00 2001 From: Heiru Wu Date: Tue, 26 Sep 2023 07:26:41 +0800 Subject: [PATCH 5/5] chore: format --- README.md | 2 +- instill/resources/model.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 07d4b10..d9b3288 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ python sdk for Instill AI products ## Setup > [!NOTE] -> For setting up development environment, please refer to [Controbuting](#contributing) +> For setting up development environment, please refer to [Contributing](#contributing) ### Requirements diff --git a/instill/resources/model.py b/instill/resources/model.py index 4ea63c6..8b927e4 100644 --- a/instill/resources/model.py +++ b/instill/resources/model.py @@ -51,9 +51,7 @@ def resource(self, resource: model_interface.Model): self._resource = resource def _update(self): - self.resource = self.client.model_service.get_model( - model_name=self.resource.id - ) + self.resource = self.client.model_service.get_model(model_name=self.resource.id) def get_definition(self) -> model_definition_interface.ModelDefinition: return self.resource.model_definition