Package: instill-sdk
[!IMPORTANT]This SDK tool is under active developmentFor any bug found or featur request, feel free to open any issue regarding this SDK in ourcommunityrepo.OverviewWelcome to Instill Python SDK, where the world of AI-first application comes alive in the form of Python.Before you jump into creating your first application with this SDK tool, we recommend you to get familiar with the core concepts of Instill Product first. You can check out our documentation here:Instill CoreInstill SDKSetup[!NOTE]For setting up development environment, please refer toContributingRequirementsPython 3.8+Installation[!WARNING]If your host machine is on arm64 architecture(including Apple silicon machines, equipped with m1/m2 processors), there are some issues when installinggrpciowithincondaenvironment. You will have to manually build and install it like below. Read more about this issuehere.$GRPC_PYTHON_LDFLAGS=" -framework CoreFoundation"pipinstallgrpcio--no-binary:all:Install it directly into an activated virtual environment:$ pip install instill-sdkor add it to yourPoetryproject:$ poetry add instill-sdkCheck importAfter installation, you can check if it has been installed correctly:$ python
>>> import instill
>>> instill.__version__ConfigInstill CoreorInstill CloudinstanceBefore we can start using this SDK, you will need to properly config your target instance. We support two ways to setup the configs, which areConfig filecreate a config file under this path${HOME}/.config/instill/sdk/python/config.yml, and within that path you will need to fill in some basic parameters for your desired host.[^1][^1]: You can obtain anapi_tokenby simply going to Settings > API Tokens page from the console, no matter it isInstill CoreorInstill Cloud.Within the config file, you can define multiple instances with thealiasof your liking, later in the SDK you can refer to thisaliasto switch between instances.[^2][^2]: SDK is default to look for instance nameddefaultfirst, and will fall back to the first instance entry in the config file ifdefaultnot foundhosts:alias1:url:strsecure:booltoken:stralias2:url:strsecure:booltoken:str......Example:hosts:default:url:localhost:8080secure:falsetoken:instill_sk***cloud:url:api.instill.techsecure:truetoken:instill_sk***At runtimeIf you do not like the idea of having to create a config file, you can also setup your target instance by doing the following at the very beginning of your script.frominstill.configurationimportglobal_configglobal_config.set_default(url="api.instill.tech",token="instill_sk***",secure=True,)UsageCreate clientYou can also find some notebook exampleshereSimply import theget_clientfunction to get the client that are connected to all services with the config you setup previously.frominstill.clientsimportget_clientclient=get_client()[!NOTE]Remember to callclient.close()at the end of script to release the channel and the underlying resourcesIf you have not set upInstill VDPorInstill Model, you will get a warning like this:2023-09-2718:49:04,871.871WARNINGInstillVDPisnotserving,VDPfunctionalitieswillnotwork2023-09-2718:49:04,907.907WARNINGInstillModelisnotserving,ModelfunctionalitieswillnotworkYou can check the readiness of each service:client.mgmt_service.is_serving()# Trueclient.pipeline_service.is_serving()# Trueclient.model_service.is_serving()# TrueYou can also switch to other instancesclient.set_instance("your-instance-in-config")client.mgmt_service.instance# 'your-instance-in-config'After making sure all desired services are serving, we can check the user status by:client.mgmt_service.get_user()If you have a validapi_tokenin 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 resourcesCreate ModelLet's say we want to serve ayolov7model fromgithubwith the following configsmodel_name="yolov7"model_repo="instill-ai/model-yolov7-dvc"model_tag="v1.0-cpu"Simply import the GithubModel resource and fill in the corresponding fieldsfrominstill.resources.modelimportGithubModelyolov7=GithubModel(client=client,name=model_name,model_repo=model_repo,model_tag=model_tag,)After the creation is done, we can check the state of the model[^3][^3]:State definitionyolov7.get_state()# 1# means STATE_OFFLINENow we can deploy the modelyolov7.deploy()Check the statusyolov7.get_state()# 2# means STATE_ONLINETrigger the model with the correcttasktype[^4][^4]: Check out ourtask protocolto learn more, or read ourjson schemadirectlyfrominstill.resourcesimportmodel_pb,task_detectiontask_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 youprintthe outputs, you will get a list of specifictaskoutput, in this case is a list ofTASK_DETECTIONoutput[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 connectorWith similiar conecpt as creatingmodel, below is the steps to create ainstill model connectorFirst import our predefinedInstillModelConnectorand config dataclassInstillModelConnector2[^5][^5]: config dataclass is auto-gen from our json schema, we will refacor the source json to make the dataclass name makes more sensefrominstill.resources.schema.instillimportInstillModelConnector1frominstill.resourcesimportInstillModelConnector,connector_pb,constThen we set up the connector resource information[^6][^6]: Find out the resource definition in ourjson schema# create the config dataclass object and fill in necessary fieldsinstill_model_config=InstillModelConnector1(mode=const.INSTILL_MODEL_INTERNAL_MODE)instill_model=InstillModelConnector(client,name="instill",config=instill_model_config,)After the connector is created, the state should beSTATE_DISCONNECTEDinstill_model.get_state()==connector_pb.Connector.STATE_DISCONNECTED# TrueNow we can test the connection for the newly configured connector, to make sure the connection with the host can be establishedinstill_model.test()==connector_pb.Connector.STATE_CONNECTED# TrueCreate pipelineSince we have created aInstill Model Connectorthat connect to ourInstill Modelinstance, we can now create a pipeline that utilize bothInstill VDPandInstill ModelFirst we importPipelineclass and other helper functionsfrominstill.resources.schemaimport(instill_task_detection_input,start_task_start_metadata,end_task_end_metadata,)frominstill.resourcesimport(const,InstillModelConnector,Pipeline,create_start_operator,create_end_operator,create_recipe,populate_default_value,)To Form a pipeine, it required astartoperator and aendoperator, we have helper functions to create both# define start operator input specstart_metadata={}start_metadata.update({"input_image":start_task_start_metadata.Model1(instillFormat="image/*",title="Image",type="string",)})# create start operatorstart_operator_component=create_start_operator(start_metadata)If you wish to define multiple input fields in the start operator, simply add more"key"and"start_task_start_metadata.Model1"pair bystart_metadata.update({"input_image":start_task_start_metadata.Model1(instillFormat="{your input format}",title="{input title}",type="{input type}",)})Now we can create amodelcomponent. From the already definedinstill Model Connector, we can utilize the models served onInstill Model, import them as acomponent.# first we create the input for the component from the dataclass# 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 modelinstill_model_input=instill_task_detection_input.Input(model_namespace="admin",model_id="yolov7",image_base64="{start.input_image}",)# create model connector component from the connector resource we had created previouslyinstill_model_connector_component=instill_model.create_component(name="yolov7",inp=instill_model_input,)# define end operator input and metadata specend_operator_inp={}end_operator_inp.update({"inference_result":"{yolov7.output.objects}"})end_operator_metadata={}end_operator_metadata.update({"inference_result":end_task_end_metadata.Model1(title="result")})# create end operatorend_operator_component=create_end_operator(end_operator_inp,end_operator_metadata)We now have all the components ready for the pipeline. Next, we add them into the recipe and create a pipeline.# create a recipe to construct the pipelinerecipe=create_recipe([start_operator_component,instill_model_connector_component,end_operator_component])# create pipelineinstill_model_pipeline=Pipeline(client=client,name="instill-model-pipeline",recipe=recipe)Finally the pipeline is done, now let us test it by triggering it!# we can trigger the pipeline nowimportbase64importrequestsfromgoogle.protobuf.struct_pb2importStructi=Struct()i.update({"input_image":base64.b64encode(requests.get("https://artifacts.instill.tech/imgs/dog.jpg",timeout=5).content).decode("ascii")})# verify the outputinstill_model_pipeline([i])[0][0]["inference_result"][0]["category"]=="dog"ContributingPlease refer to theContributing Guidelinesfor more details.Community supportPlease refer to thecommunityrepository.LicenseSee theLICENSEfile for licensing information.