Add sdk and cli example for binary payloads (#1795)
* Init * Formatting * Remove testing data * Edit * Remove dev vars * Formatting * Replace paths and other fixes * Remove test data * Edit * Refresh workflow * Kernelspec * Untouch kernelspec in batch * Edits * Cleanup * Remove dev string and formatting * Paths... * Formatting * Paths Co-authored-by: Shohei Nagata <Shohei.Nagata@microsoft.com>
This commit is contained in:
Родитель
5172b8b44d
Коммит
504cfdb5f5
|
@ -0,0 +1,30 @@
|
||||||
|
name: cli-scripts-deploy-moe-binary-payloads
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 0/4 * * *"
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- sdk-preview
|
||||||
|
paths:
|
||||||
|
- cli/deploy-moe-binary-payloads.sh
|
||||||
|
- .github/workflows/cli-scripts-deploy-moe-binary-payloads.yml
|
||||||
|
- cli/setup.sh
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: check out repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: azure login
|
||||||
|
uses: azure/login@v1
|
||||||
|
with:
|
||||||
|
creds: ${{secrets.AZ_CREDS}}
|
||||||
|
- name: setup
|
||||||
|
run: bash setup.sh
|
||||||
|
working-directory: cli
|
||||||
|
continue-on-error: true
|
||||||
|
- name: test script script
|
||||||
|
run: set -e; bash -x deploy-moe-binary-payloads.sh
|
||||||
|
working-directory: cli
|
89
.github/workflows/sdk-endpoints-online-managed-online-endpoints-binary-payloads.yml
поставляемый
Normal file
89
.github/workflows/sdk-endpoints-online-managed-online-endpoints-binary-payloads.yml
поставляемый
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
name: sdk-endpoints-online-managed-online-endpoints-binary-payloads
|
||||||
|
# This file is created by sdk/python/readme.py.
|
||||||
|
# Please do not edit directly.
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 */8 * * *"
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- sdk/python/endpoints/online/managed/**
|
||||||
|
- .github/workflows/sdk-endpoints-online-managed-online-endpoints-binary-payloads.yml
|
||||||
|
- sdk/python/dev-requirements.txt
|
||||||
|
- infra/**
|
||||||
|
- sdk/python/setup.sh
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: check out repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: setup python
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: "3.8"
|
||||||
|
- name: pip install notebook reqs
|
||||||
|
run: pip install -r sdk/python/dev-requirements.txt
|
||||||
|
- name: azure login
|
||||||
|
uses: azure/login@v1
|
||||||
|
with:
|
||||||
|
creds: ${{secrets.AZUREML_CREDENTIALS}}
|
||||||
|
- name: bootstrap resources
|
||||||
|
run: |
|
||||||
|
echo '${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}';
|
||||||
|
bash bootstrap.sh
|
||||||
|
working-directory: infra
|
||||||
|
continue-on-error: false
|
||||||
|
- name: setup SDK
|
||||||
|
run: |
|
||||||
|
source "${{ github.workspace }}/infra/sdk_helpers.sh";
|
||||||
|
source "${{ github.workspace }}/infra/init_environment.sh";
|
||||||
|
bash setup.sh
|
||||||
|
working-directory: sdk/python
|
||||||
|
continue-on-error: true
|
||||||
|
- name: setup-cli
|
||||||
|
run: |
|
||||||
|
source "${{ github.workspace }}/infra/sdk_helpers.sh";
|
||||||
|
source "${{ github.workspace }}/infra/init_environment.sh";
|
||||||
|
bash setup.sh
|
||||||
|
working-directory: cli
|
||||||
|
continue-on-error: true
|
||||||
|
- name: run endpoints/online/managed/online-endpoints-binary-payloads.ipynb
|
||||||
|
run: |
|
||||||
|
source "${{ github.workspace }}/infra/sdk_helpers.sh";
|
||||||
|
source "${{ github.workspace }}/infra/init_environment.sh";
|
||||||
|
bash "${{ github.workspace }}/infra/sdk_helpers.sh" generate_workspace_config "../../.azureml/config.json";
|
||||||
|
bash "${{ github.workspace }}/infra/sdk_helpers.sh" replace_template_values "online-endpoints-binary-payloads.ipynb";
|
||||||
|
[ -f "../../.azureml/config" ] && cat "../../.azureml/config";
|
||||||
|
papermill -k python online-endpoints-binary-payloads.ipynb online-endpoints-binary-payloads.output.ipynb
|
||||||
|
working-directory: sdk/python/endpoints/online/managed
|
||||||
|
- name: upload notebook's working folder as an artifact
|
||||||
|
if: ${{ always() }}
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: online-endpoints-binary-payloads
|
||||||
|
path: sdk/python/endpoints/online/managed
|
||||||
|
|
||||||
|
- name: Send IcM on failure
|
||||||
|
if: ${{ failure() && github.ref_type == 'branch' && (github.ref_name == 'main' || contains(github.ref_name, 'release')) }}
|
||||||
|
uses: ./.github/actions/generate-icm
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.AZUREML_ICM_CONNECTOR_HOST_NAME }}
|
||||||
|
connector_id: ${{ secrets.AZUREML_ICM_CONNECTOR_CONNECTOR_ID }}
|
||||||
|
certificate: ${{ secrets.AZUREML_ICM_CONNECTOR_CERTIFICATE }}
|
||||||
|
private_key: ${{ secrets.AZUREML_ICM_CONNECTOR_PRIVATE_KEY }}
|
||||||
|
args: |
|
||||||
|
incident:
|
||||||
|
Title: "[azureml-examples] Notebook validation failed on branch '${{ github.ref_name }}' for notebook 'endpoints/online/managed/online-endpoints-binary-payloads.ipynb'"
|
||||||
|
Summary: |
|
||||||
|
Notebook 'endpoints/online/managed/online-endpoints-binary-payloads.ipynb' is failing on branch '${{ github.ref_name }}': ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||||
|
Severity: 4
|
||||||
|
RoutingId: "github://azureml-examples"
|
||||||
|
Status: Active
|
||||||
|
Source:
|
||||||
|
IncidentId: "endpoints/online/managed/online-endpoints-binary-payloads.ipynb[${{ github.ref_name }}]"
|
|
@ -58,6 +58,7 @@ path|status|
|
||||||
[deploy-mlcompute-update-to-system-identity.sh](deploy-mlcompute-update-to-system-identity.sh)|[![deploy-mlcompute-update-to-system-identity](https://github.com/Azure/azureml-examples/workflows/cli-scripts-deploy-mlcompute-update-to-system-identity/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/cli-scripts-deploy-mlcompute-update-to-system-identity.yml)
|
[deploy-mlcompute-update-to-system-identity.sh](deploy-mlcompute-update-to-system-identity.sh)|[![deploy-mlcompute-update-to-system-identity](https://github.com/Azure/azureml-examples/workflows/cli-scripts-deploy-mlcompute-update-to-system-identity/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/cli-scripts-deploy-mlcompute-update-to-system-identity.yml)
|
||||||
[deploy-mlcompute-update-to-user-identity.sh](deploy-mlcompute-update-to-user-identity.sh)|[![deploy-mlcompute-update-to-user-identity](https://github.com/Azure/azureml-examples/workflows/cli-scripts-deploy-mlcompute-update-to-user-identity/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/cli-scripts-deploy-mlcompute-update-to-user-identity.yml)
|
[deploy-mlcompute-update-to-user-identity.sh](deploy-mlcompute-update-to-user-identity.sh)|[![deploy-mlcompute-update-to-user-identity](https://github.com/Azure/azureml-examples/workflows/cli-scripts-deploy-mlcompute-update-to-user-identity/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/cli-scripts-deploy-mlcompute-update-to-user-identity.yml)
|
||||||
[deploy-moe-autoscale.sh](deploy-moe-autoscale.sh)|[![deploy-moe-autoscale](https://github.com/Azure/azureml-examples/workflows/cli-scripts-deploy-moe-autoscale/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/cli-scripts-deploy-moe-autoscale.yml)
|
[deploy-moe-autoscale.sh](deploy-moe-autoscale.sh)|[![deploy-moe-autoscale](https://github.com/Azure/azureml-examples/workflows/cli-scripts-deploy-moe-autoscale/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/cli-scripts-deploy-moe-autoscale.yml)
|
||||||
|
[deploy-moe-binary-payloads.sh](deploy-moe-binary-payloads.sh)|[![deploy-moe-binary-payloads](https://github.com/Azure/azureml-examples/workflows/cli-scripts-deploy-moe-binary-payloads/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/cli-scripts-deploy-moe-binary-payloads.yml)
|
||||||
[deploy-moe-inference-schema.sh](deploy-moe-inference-schema.sh)|[![deploy-moe-inference-schema](https://github.com/Azure/azureml-examples/workflows/cli-scripts-deploy-moe-inference-schema/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/cli-scripts-deploy-moe-inference-schema.yml)
|
[deploy-moe-inference-schema.sh](deploy-moe-inference-schema.sh)|[![deploy-moe-inference-schema](https://github.com/Azure/azureml-examples/workflows/cli-scripts-deploy-moe-inference-schema/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/cli-scripts-deploy-moe-inference-schema.yml)
|
||||||
[deploy-moe-keyvault.sh](deploy-moe-keyvault.sh)|[![deploy-moe-keyvault](https://github.com/Azure/azureml-examples/workflows/cli-scripts-deploy-moe-keyvault/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/cli-scripts-deploy-moe-keyvault.yml)
|
[deploy-moe-keyvault.sh](deploy-moe-keyvault.sh)|[![deploy-moe-keyvault](https://github.com/Azure/azureml-examples/workflows/cli-scripts-deploy-moe-keyvault/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/cli-scripts-deploy-moe-keyvault.yml)
|
||||||
[deploy-moe-minimal-single-model-registered.sh](deploy-moe-minimal-single-model-registered.sh)|[![deploy-moe-minimal-single-model-registered](https://github.com/Azure/azureml-examples/workflows/cli-scripts-deploy-moe-minimal-single-model-registered/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/cli-scripts-deploy-moe-minimal-single-model-registered.yml)
|
[deploy-moe-minimal-single-model-registered.sh](deploy-moe-minimal-single-model-registered.sh)|[![deploy-moe-minimal-single-model-registered](https://github.com/Azure/azureml-examples/workflows/cli-scripts-deploy-moe-minimal-single-model-registered/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/cli-scripts-deploy-moe-minimal-single-model-registered.yml)
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# <set_variables>
|
||||||
|
ENDPOINT_NAME=endpt-moe-`echo $RANDOM`
|
||||||
|
ACR_NAME=$(az ml workspace show --query container_registry -o tsv | cut -d'/' -f9-)
|
||||||
|
# </set_variables>
|
||||||
|
|
||||||
|
BASE_PATH="endpoints/online/managed/binary-payloads"
|
||||||
|
|
||||||
|
# <download_sample_data>
|
||||||
|
wget https://aka.ms/peacock-pic -O endpoints/online/managed/binary-payloads/input.jpg
|
||||||
|
# </download_sample_data>
|
||||||
|
|
||||||
|
# <create_endpoint>
|
||||||
|
az ml online-endpoint create -n $ENDPOINT_NAME
|
||||||
|
# </create_endpoint>
|
||||||
|
|
||||||
|
# Check if endpoint was successful
|
||||||
|
endpoint_status=`az ml online-endpoint show --name $ENDPOINT_NAME --query "provisioning_state" -o tsv `
|
||||||
|
echo $endpoint_status
|
||||||
|
if [[ $endpoint_status == "Succeeded" ]]
|
||||||
|
then
|
||||||
|
echo "Endpoint created successfully"
|
||||||
|
else
|
||||||
|
echo "Endpoint creation failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# <create_deployment>
|
||||||
|
az ml online-deployment create -e $ENDPOINT_NAME -f $BASE_PATH/binary-payloads-deployment.yml \
|
||||||
|
--set code_configuration.scoring_script=single-file-to-file-score.py \
|
||||||
|
--all-traffic
|
||||||
|
# </create_deployment>
|
||||||
|
|
||||||
|
# <get_endpoint_details>
|
||||||
|
# Get key
|
||||||
|
echo "Getting access key..."
|
||||||
|
KEY=$(az ml online-endpoint get-credentials -n $ENDPOINT_NAME --query primaryKey -o tsv )
|
||||||
|
|
||||||
|
# Get scoring url
|
||||||
|
echo "Getting scoring url..."
|
||||||
|
SCORING_URL=$(az ml online-endpoint show -n $ENDPOINT_NAME --query scoring_uri -o tsv )
|
||||||
|
echo "Scoring url is $SCORING_URL"
|
||||||
|
# </get_endpoint_details>
|
||||||
|
|
||||||
|
# <get_logs>
|
||||||
|
az ml online-deployment get-logs -n binary-payload -e $ENDPOINT_NAME
|
||||||
|
# </get_logs>
|
||||||
|
|
||||||
|
# <check_deployment>
|
||||||
|
# Check if deployment was successful
|
||||||
|
deploy_status=`az ml online-deployment show --name binary-payload --endpoint $ENDPOINT_NAME --query "provisioning_state" -o tsv `
|
||||||
|
echo $deploy_status
|
||||||
|
if [[ $deploy_status == "Succeeded" ]]
|
||||||
|
then
|
||||||
|
echo "Deployment completed successfully"
|
||||||
|
else
|
||||||
|
echo "Deployment failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# </check_deployment>
|
||||||
|
|
||||||
|
# <test_online_endpoint_1>
|
||||||
|
curl -X POST -F "file=@endpoints/online/managed/binary-payloads/input.jpg" -H "Authorization: Bearer $KEY" $SCORING_URL \
|
||||||
|
-o endpoints/online/managed/binary-payloads/output.jpg
|
||||||
|
# <test_online_endpoint_1>
|
||||||
|
|
||||||
|
# <update_deployment2>
|
||||||
|
az ml online-deployment update -e $ENDPOINT_NAME -n binary-payload \
|
||||||
|
--set code_configuration.scoring_script="multi-file-to-json-score.py"
|
||||||
|
# </updat _deployment2>
|
||||||
|
|
||||||
|
# <test_online_endpoint_2>
|
||||||
|
curl -X POST -F "file[]=@endpoints/online/managed/binary-payloads/input.jpg" \
|
||||||
|
-F "file[]=@endpoints/online/managed/binary-payloads/output.jpg" \
|
||||||
|
-H "Authorization: Bearer $KEY" $SCORING_URL
|
||||||
|
# <test_online_endpoint_2>
|
||||||
|
|
||||||
|
# <delete_assets>
|
||||||
|
az ml online-endpoint delete -n $ENDPOINT_NAME --no-wait --yes
|
||||||
|
# </delete_assets>
|
|
@ -0,0 +1,13 @@
|
||||||
|
$schema: https://azuremlschemas.azureedge.net/latest/managedOnlineDeployment.schema.json
|
||||||
|
name: binary-payload
|
||||||
|
endpoint_name: <ENDPOINT_NAME>
|
||||||
|
model:
|
||||||
|
path: .
|
||||||
|
code_configuration:
|
||||||
|
code: code
|
||||||
|
scoring_script: <SCORING_SCRIPT>
|
||||||
|
environment:
|
||||||
|
image: mcr.microsoft.com/azureml/openmpi4.1.0-ubuntu20.04:latest
|
||||||
|
conda_file: env.yml
|
||||||
|
instance_type: Standard_DS2_v2
|
||||||
|
instance_count: 1
|
|
@ -0,0 +1,13 @@
|
||||||
|
from azureml.contrib.services.aml_request import AMLRequest, rawhttp
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
|
def init():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@rawhttp
|
||||||
|
def run(req: AMLRequest):
|
||||||
|
files = req.files.getlist("file[]")
|
||||||
|
sizes = [{"filename": f.filename, "size": Image.open(f.stream).size} for f in files]
|
||||||
|
return {"response": sizes}
|
|
@ -0,0 +1,28 @@
|
||||||
|
from azureml.contrib.services.aml_request import AMLRequest, rawhttp
|
||||||
|
from azureml.contrib.services.aml_response import AMLResponse
|
||||||
|
from PIL import Image
|
||||||
|
import io
|
||||||
|
|
||||||
|
default_resize = (128, 128)
|
||||||
|
|
||||||
|
|
||||||
|
def init():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@rawhttp
|
||||||
|
def run(req: AMLRequest):
|
||||||
|
try:
|
||||||
|
data = req.files.getlist("file")[0]
|
||||||
|
except IndexError:
|
||||||
|
return AMLResponse("No file uploaded", status_code=422)
|
||||||
|
|
||||||
|
img = Image.open(data.stream)
|
||||||
|
img = img.resize(default_resize)
|
||||||
|
|
||||||
|
output = io.BytesIO()
|
||||||
|
img.save(output, format="JPEG")
|
||||||
|
resp = AMLResponse(message=output.getvalue(), status_code=200)
|
||||||
|
resp.mimetype = "image/jpg"
|
||||||
|
|
||||||
|
return resp
|
|
@ -0,0 +1,7 @@
|
||||||
|
name: userenv
|
||||||
|
dependencies:
|
||||||
|
- python=3.10
|
||||||
|
- pip
|
||||||
|
- pip:
|
||||||
|
- pillow~=9.3
|
||||||
|
- azureml-defaults>=1.47,<2
|
|
@ -55,6 +55,7 @@ Test Status is for branch - **_main_**
|
||||||
|endpoints|online|[debug-online-endpoints-locally-in-visual-studio-code](endpoints/online/managed/debug-online-endpoints-locally-in-visual-studio-code.ipynb)|*no description* - _This sample is excluded from automated tests_|[![debug-online-endpoints-locally-in-visual-studio-code](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-debug-online-endpoints-locally-in-visual-studio-code.yml/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-debug-online-endpoints-locally-in-visual-studio-code.yml)|
|
|endpoints|online|[debug-online-endpoints-locally-in-visual-studio-code](endpoints/online/managed/debug-online-endpoints-locally-in-visual-studio-code.ipynb)|*no description* - _This sample is excluded from automated tests_|[![debug-online-endpoints-locally-in-visual-studio-code](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-debug-online-endpoints-locally-in-visual-studio-code.yml/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-debug-online-endpoints-locally-in-visual-studio-code.yml)|
|
||||||
|endpoints|online|[online-endpoints-managed-identity-sai](endpoints/online/managed/managed-identities/online-endpoints-managed-identity-sai.ipynb)|*no description* - _This sample is excluded from automated tests_|[![online-endpoints-managed-identity-sai](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-managed-identities-online-endpoints-managed-identity-sai.yml/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-managed-identities-online-endpoints-managed-identity-sai.yml)|
|
|endpoints|online|[online-endpoints-managed-identity-sai](endpoints/online/managed/managed-identities/online-endpoints-managed-identity-sai.ipynb)|*no description* - _This sample is excluded from automated tests_|[![online-endpoints-managed-identity-sai](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-managed-identities-online-endpoints-managed-identity-sai.yml/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-managed-identities-online-endpoints-managed-identity-sai.yml)|
|
||||||
|endpoints|online|[online-endpoints-managed-identity-uai](endpoints/online/managed/managed-identities/online-endpoints-managed-identity-uai.ipynb)|*no description* - _This sample is excluded from automated tests_|[![online-endpoints-managed-identity-uai](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-managed-identities-online-endpoints-managed-identity-uai.yml/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-managed-identities-online-endpoints-managed-identity-uai.yml)|
|
|endpoints|online|[online-endpoints-managed-identity-uai](endpoints/online/managed/managed-identities/online-endpoints-managed-identity-uai.ipynb)|*no description* - _This sample is excluded from automated tests_|[![online-endpoints-managed-identity-uai](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-managed-identities-online-endpoints-managed-identity-uai.yml/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-managed-identities-online-endpoints-managed-identity-uai.yml)|
|
||||||
|
|endpoints|online|[online-endpoints-binary-payloads](endpoints/online/managed/online-endpoints-binary-payloads.ipynb)|*no description*|[![online-endpoints-binary-payloads](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-online-endpoints-binary-payloads.yml/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-online-endpoints-binary-payloads.yml)|
|
||||||
|endpoints|online|[online-endpoints-inference-schema](endpoints/online/managed/online-endpoints-inference-schema.ipynb)|*no description*|[![online-endpoints-inference-schema](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-online-endpoints-inference-schema.yml/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-online-endpoints-inference-schema.yml)|
|
|endpoints|online|[online-endpoints-inference-schema](endpoints/online/managed/online-endpoints-inference-schema.ipynb)|*no description*|[![online-endpoints-inference-schema](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-online-endpoints-inference-schema.yml/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-online-endpoints-inference-schema.yml)|
|
||||||
|endpoints|online|[online-endpoints-keyvault](endpoints/online/managed/online-endpoints-keyvault.ipynb)|*no description*|[![online-endpoints-keyvault](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-online-endpoints-keyvault.yml/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-online-endpoints-keyvault.yml)|
|
|endpoints|online|[online-endpoints-keyvault](endpoints/online/managed/online-endpoints-keyvault.ipynb)|*no description*|[![online-endpoints-keyvault](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-online-endpoints-keyvault.yml/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-online-endpoints-keyvault.yml)|
|
||||||
|endpoints|online|[online-endpoints-multimodel](endpoints/online/managed/online-endpoints-multimodel.ipynb)|*no description*|[![online-endpoints-multimodel](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-online-endpoints-multimodel.yml/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-online-endpoints-multimodel.yml)|
|
|endpoints|online|[online-endpoints-multimodel](endpoints/online/managed/online-endpoints-multimodel.ipynb)|*no description*|[![online-endpoints-multimodel](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-online-endpoints-multimodel.yml/badge.svg?branch=main)](https://github.com/Azure/azureml-examples/actions/workflows/sdk-endpoints-online-managed-online-endpoints-multimodel.yml)|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
from azureml.contrib.services.aml_request import AMLRequest, rawhttp
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
|
def init():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@rawhttp
|
||||||
|
def run(req: AMLRequest):
|
||||||
|
sizes = [
|
||||||
|
{"filename": f.filename, "size": Image.open(f.stream).size}
|
||||||
|
for f in req.files.getlist("file[]")
|
||||||
|
]
|
||||||
|
|
||||||
|
return {"response": sizes}
|
|
@ -0,0 +1,30 @@
|
||||||
|
from azureml.contrib.services.aml_request import AMLRequest, rawhttp
|
||||||
|
from azureml.contrib.services.aml_response import AMLResponse
|
||||||
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from email.mime.image import MIMEImage
|
||||||
|
from PIL import Image
|
||||||
|
import io
|
||||||
|
|
||||||
|
default_resize = (128, 128)
|
||||||
|
|
||||||
|
|
||||||
|
def init():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@rawhttp
|
||||||
|
def run(req: AMLRequest):
|
||||||
|
try:
|
||||||
|
data = req.files.getlist("file")[0]
|
||||||
|
except IndexError:
|
||||||
|
return AMLResponse("No file uploaded", status_code=422)
|
||||||
|
|
||||||
|
img = Image.open(data.stream)
|
||||||
|
img = img.resize(default_resize)
|
||||||
|
|
||||||
|
output = io.BytesIO()
|
||||||
|
img.save(output, format="JPEG")
|
||||||
|
resp = AMLResponse(message=output.getvalue(), status_code=200)
|
||||||
|
resp.mimetype = "image/jpg"
|
||||||
|
|
||||||
|
return resp
|
|
@ -0,0 +1,8 @@
|
||||||
|
name: userenv
|
||||||
|
dependencies:
|
||||||
|
- python=3.10
|
||||||
|
- pip
|
||||||
|
- pip:
|
||||||
|
- pillow
|
||||||
|
- azureml-inference-server-http
|
||||||
|
- azureml-contrib-services
|
|
@ -0,0 +1,461 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Handle binary payloads from a Managed Online Endpoint"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"In this example, receiving and sending binary payloads in scoring scripts is demonstrated using the `rawhttp` decorator as well as the `AMLRequest` and `AMLResponse` objects. Without `rawhttp`, the run function is called passed the serialized JSON from the payload. Using `rawhttp`, the run function is instead passed an `AMLRequest` object, which wraps the native Flask request object used internally by the Azure Inference Server. After handling binary payloads, one can either return a JSON-serializable object as usual or use the `AMLResponse` object to have full control over the response, including returning binary payloads. "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 1. Configure parameters, assets, and clients"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 1.1 Import required libraries"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"name": "1-import-required-libraries"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from azure.ai.ml import MLClient\n",
|
||||||
|
"from azure.ai.ml.entities import (\n",
|
||||||
|
" ManagedOnlineEndpoint,\n",
|
||||||
|
" ManagedOnlineDeployment,\n",
|
||||||
|
" Model,\n",
|
||||||
|
" CodeConfiguration,\n",
|
||||||
|
" Environment,\n",
|
||||||
|
")\n",
|
||||||
|
"from azure.identity import DefaultAzureCredential\n",
|
||||||
|
"import random, os, requests"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"name": "1-import-libraries"
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"### 1.2 Set workspace details"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"name": "1-set-workspace-details"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"subscription_id = \"<SUBSCRIPTION_ID>\"\n",
|
||||||
|
"resource_group = \"<RESOURCE_GROUP>\"\n",
|
||||||
|
"workspace_name = \"<AML_WORKSPACE_NAME>\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"name": "1-set-workspace"
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"### 1.3 Set variables"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"name": "1-set-variables"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"rand = random.randint(0, 10000)\n",
|
||||||
|
"\n",
|
||||||
|
"endpoint_name = f\"endpt-moe-{rand}\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 1.4 Download sample data"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"name": "1-download-sample-data"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"url = \"https://aka.ms/peacock-pic\"\n",
|
||||||
|
"agent = f\"Python Requests/{requests.__version__} (https://github.com/Azure/azureml-examples)\"\n",
|
||||||
|
"r = requests.get(url, headers={\"User-Agent\": agent}, allow_redirects=True)\n",
|
||||||
|
"open(\"binary-payloads/input.jpg\", \"wb\").write(r.content)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 1.5 Create an MLClient Instance"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"name": "1-create-mlclient-instance"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"credential = DefaultAzureCredential()\n",
|
||||||
|
"ml_client = MLClient(\n",
|
||||||
|
" credential,\n",
|
||||||
|
" subscription_id=subscription_id,\n",
|
||||||
|
" resource_group_name=resource_group,\n",
|
||||||
|
" workspace_name=workspace_name,\n",
|
||||||
|
")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 2. Create endpoint"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"name": "2-create-endpoint"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"endpoint = ManagedOnlineEndpoint(name=endpoint_name)\n",
|
||||||
|
"endpoint = ml_client.online_endpoints.begin_create_or_update(endpoint).result()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 3. Create a Binary-to-Binary Deployment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"This script receives an image as a binary file and returns a resized image as a binary file. Both scoring scripts use the `rawhttp` decorator to change the argument passed to the run function from JSON to the entire `AMLRequest` object. This script also uses the `AMLResponse` object "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"```python\n",
|
||||||
|
"from azureml.contrib.services.aml_request import AMLRequest, rawhttp\n",
|
||||||
|
"from azureml.contrib.services.aml_response import AMLResponse\n",
|
||||||
|
"from email.mime.multipart import MIMEMultipart\n",
|
||||||
|
"from email.mime.image import MIMEImage\n",
|
||||||
|
"from PIL import Image\n",
|
||||||
|
"import io \n",
|
||||||
|
"\n",
|
||||||
|
"default_resize = (128, 128)\n",
|
||||||
|
"\n",
|
||||||
|
"def init(): \n",
|
||||||
|
" pass \n",
|
||||||
|
"\n",
|
||||||
|
"@rawhttp\n",
|
||||||
|
"def run(req : AMLRequest):\n",
|
||||||
|
" try:\n",
|
||||||
|
" data = req.files.getlist(\"file\")[0]\n",
|
||||||
|
" except IndexError:\n",
|
||||||
|
" return AMLResponse(\"No file uploaded\", status_code=422)\n",
|
||||||
|
" \n",
|
||||||
|
" img = Image.open(data.stream)\n",
|
||||||
|
" img = img.resize(default_resize)\n",
|
||||||
|
"\n",
|
||||||
|
" output = io.BytesIO()\n",
|
||||||
|
" img.save(output, format=\"JPEG\")\n",
|
||||||
|
" resp = AMLResponse(message = output.getvalue(), status_code=200)\n",
|
||||||
|
" resp.mimetype = \"image/jpg\"\n",
|
||||||
|
"\n",
|
||||||
|
" return resp\n",
|
||||||
|
"```"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 3.1 Create the deployment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"name": "3-create-deployment"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"deployment = ManagedOnlineDeployment(\n",
|
||||||
|
" name=\"binarypayloads\",\n",
|
||||||
|
" endpoint_name=endpoint_name,\n",
|
||||||
|
" model=Model(path=\"binary-payloads\"),\n",
|
||||||
|
" code_configuration=CodeConfiguration(\n",
|
||||||
|
" code=\"binary-payloads/code\", scoring_script=\"single-file-to-file-score.py\"\n",
|
||||||
|
" ),\n",
|
||||||
|
" environment=Environment(\n",
|
||||||
|
" conda_file=\"binary-payloads/env.yml\",\n",
|
||||||
|
" image=\"mcr.microsoft.com/azureml/openmpi4.1.0-ubuntu20.04:latest\",\n",
|
||||||
|
" ),\n",
|
||||||
|
" instance_type=\"Standard_DS2_v2\",\n",
|
||||||
|
" instance_count=1,\n",
|
||||||
|
")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 3.2 Create the deployment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"name": "3-create-deployment"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"deployment = ml_client.online_deployments.begin_create_or_update(deployment).result()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 3.3 Update endpoint traffic"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"name": "3-update-endpoint-traffic"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"endpoint.traffic = {\"binarypayloads\": 100}\n",
|
||||||
|
"endpoint = ml_client.online_endpoints.begin_create_or_update(endpoint).result()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 3.4 Get endpoint details"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"name": "3-get-endpoint-details"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"scoring_uri = endpoint.scoring_uri\n",
|
||||||
|
"key = ml_client.online_endpoints.get_keys(endpoint_name).primary_key"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 3.5 Test the endpoint"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"name": "3-test-endpoint"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"res = requests.post(\n",
|
||||||
|
" url=scoring_uri,\n",
|
||||||
|
" headers={\"Authorization\": f\"Bearer {key}\"},\n",
|
||||||
|
" files=[(\"file\", open(\"binary-payloads/input.jpg\", \"rb\"))],\n",
|
||||||
|
")\n",
|
||||||
|
"open(\"binary-payloads/output.jpg\", \"wb\").write(res.content)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 5. Create a Binary-to-JSON Deployment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 5.1 Examine the scoring script\n",
|
||||||
|
"This script accepts multiple image files uploaded as `file[]` and returns the sizes of the images as JSON. Both scoring scripts use the `rawhttp` decorator to change the argument passed to the run function from JSON to the entire `AMLRequest` object. However, unlike the first script this one returns a dictionary rather than an `AMLResponse` object."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"```python\n",
|
||||||
|
"from azureml.contrib.services.aml_request import AMLRequest, rawhttp\n",
|
||||||
|
"from PIL import Image\n",
|
||||||
|
"\n",
|
||||||
|
"def init(): \n",
|
||||||
|
" pass \n",
|
||||||
|
"\n",
|
||||||
|
"@rawhttp\n",
|
||||||
|
"def run(req : AMLRequest):\n",
|
||||||
|
" sizes = [{\"filename\" : f.filename,\n",
|
||||||
|
" \"size\" : Image.open(f.stream).size}\n",
|
||||||
|
" for f in req.files.getlist(\"file[]\")]\n",
|
||||||
|
"\n",
|
||||||
|
" return {\"response\" : sizes}\n",
|
||||||
|
"```"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 5.2 Update the deployment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"name": "5-update-deployment"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"deployment.code_configuration = CodeConfiguration(\n",
|
||||||
|
" code=deployment.code_configuration.code,\n",
|
||||||
|
" scoring_script=\"code/multi-file-to-json-score.py\",\n",
|
||||||
|
")\n",
|
||||||
|
"deployment = ml_client.online_deployments.begin_create_or_update(deployment).result()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 6. Test the endpoint"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 6.1 Send a request"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"name": "6-send-request"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"res = requests.post(\n",
|
||||||
|
" url=scoring_uri,\n",
|
||||||
|
" headers={\"Authorization\": f\"Bearer {key}\"},\n",
|
||||||
|
" files=[\n",
|
||||||
|
" (\"file[]\", open(\"binary-payloads/input.jpg\", \"rb\")),\n",
|
||||||
|
" (\"file[]\", open(\"binary-payloads/output.jpg\", \"rb\")),\n",
|
||||||
|
" ],\n",
|
||||||
|
")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 7. Delete assets"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 7.1 Delete the endpoint"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"name": "7-delete-endpoint"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"ml_client.online_endpoints.begin_delete(name=endpoint_name)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3.10 - SDK V2",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python310-sdkv2"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.10.4"
|
||||||
|
},
|
||||||
|
"vscode": {
|
||||||
|
"interpreter": {
|
||||||
|
"hash": "c54d4b4f21f908d21f1064b6d031502c08620e465e849bef5aa76d1f6a474870"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 2
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче