From 26577c44162e6372297aab92fc5f58ba023caa2d Mon Sep 17 00:00:00 2001 From: Omer Spillinger Date: Tue, 26 Nov 2019 11:46:55 -0800 Subject: [PATCH 1/3] Update docs and examples --- cli/cmd/cluster.go | 28 ++--- cli/cmd/completion.go | 13 +- cli/cmd/configure.go | 8 +- cli/cmd/delete.go | 2 +- cli/cmd/deploy.go | 5 +- cli/cmd/errors.go | 2 +- cli/cmd/get.go | 13 +- cli/cmd/logs.go | 4 +- cli/cmd/predict.go | 9 +- cli/cmd/root.go | 16 +-- cli/cmd/support.go | 4 +- cli/cmd/version.go | 16 +-- docs/cluster/cli.md | 103 ++++++++-------- docs/cluster/install.md | 22 ++-- docs/cluster/uninstall.md | 17 +-- docs/cluster/update.md | 10 +- examples/README.md | 4 +- examples/pytorch/answer-generator/cortex.yaml | 4 +- examples/pytorch/image-classifier/README.md | 107 ---------------- examples/pytorch/image-classifier/cortex.yaml | 3 + examples/pytorch/iris-classifier/README.md | 114 ------------------ examples/pytorch/iris-classifier/cortex.yaml | 3 +- .../iris-classifier/{src => }/model.py | 0 .../iris-classifier/{src => }/predictor.py | 0 .../pytorch/language-identifier/cortex.yaml | 3 + .../pytorch/language-identifier/predictor.py | 7 +- .../pytorch/reading-comprehender/cortex.yaml | 2 +- examples/pytorch/text-generator/README.md | 104 ---------------- .../cortex.yaml | 6 +- .../predictor.py | 0 .../requirements.txt | 2 +- .../sample.json | 0 .../model.py => mpg-estimator/trainer.py} | 19 +-- examples/tensorflow/iris-classifier/README.md | 80 ------------ .../tensorflow/sentiment-analysis/README.md | 97 --------------- .../tensorflow/sentiment-analysis/cortex.yaml | 4 +- .../tensorflow/sentiment-analysis/sample.json | 2 +- examples/tensorflow/text-generator/README.md | 86 ------------- examples/xgboost/iris-classifier/README.md | 80 ------------ 39 files changed, 164 insertions(+), 835 deletions(-) delete mode 100644 examples/pytorch/image-classifier/README.md delete mode 100644 examples/pytorch/iris-classifier/README.md rename examples/pytorch/iris-classifier/{src => }/model.py (100%) rename examples/pytorch/iris-classifier/{src => }/predictor.py (100%) delete mode 100644 examples/pytorch/text-generator/README.md rename examples/sklearn/{mpg-estimation => mpg-estimator}/cortex.yaml (50%) rename examples/sklearn/{mpg-estimation => mpg-estimator}/predictor.py (100%) rename examples/sklearn/{mpg-estimation => mpg-estimator}/requirements.txt (100%) rename examples/sklearn/{mpg-estimation => mpg-estimator}/sample.json (100%) rename examples/sklearn/{mpg-estimation/model.py => mpg-estimator/trainer.py} (53%) delete mode 100644 examples/tensorflow/iris-classifier/README.md delete mode 100644 examples/tensorflow/sentiment-analysis/README.md delete mode 100644 examples/tensorflow/text-generator/README.md delete mode 100644 examples/xgboost/iris-classifier/README.md diff --git a/cli/cmd/cluster.go b/cli/cmd/cluster.go index 4bf068accf..e0c1832e92 100644 --- a/cli/cmd/cluster.go +++ b/cli/cmd/cluster.go @@ -57,20 +57,20 @@ func init() { } func addClusterConfigFlag(cmd *cobra.Command) { - cmd.PersistentFlags().StringVarP(&flagClusterConfig, "config", "c", "", "path to a Cortex cluster configuration file") + cmd.PersistentFlags().StringVarP(&flagClusterConfig, "config", "c", "", "path to a cluster configuration file") cmd.PersistentFlags().SetAnnotation("config", cobra.BashCompFilenameExt, configFileExts) } var clusterCmd = &cobra.Command{ Use: "cluster", - Short: "manage a Cortex cluster", - Long: "Manage a Cortex cluster", + Short: "manage a cluster", + Long: "manage a cluster", } var upCmd = &cobra.Command{ Use: "up", - Short: "spin up a Cortex cluster", - Long: `This command spins up a Cortex cluster on your AWS account.`, + Short: "spin up a cluster", + Long: `spin up a cluster`, Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { if err := checkDockerRunning(); err != nil { @@ -97,8 +97,8 @@ var upCmd = &cobra.Command{ var updateCmd = &cobra.Command{ Use: "update", - Short: "update a Cortex cluster", - Long: `This command updates a Cortex cluster.`, + Short: "update a cluster", + Long: `update a cluster`, Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { if err := checkDockerRunning(); err != nil { @@ -126,8 +126,8 @@ var updateCmd = &cobra.Command{ var infoCmd = &cobra.Command{ Use: "info", - Short: "get information about a Cortex cluster", - Long: `This command gets information about a Cortex cluster.`, + Short: "get information about a cluster", + Long: "get information about a cluster", Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { if err := checkDockerRunning(); err != nil { @@ -145,7 +145,7 @@ var infoCmd = &cobra.Command{ if err != nil { errors.Exit(err) } - if strings.Contains(out, "there isn't a cortex cluster") { + if strings.Contains(out, "there is no cluster") { errors.Exit() } @@ -176,8 +176,8 @@ var infoCmd = &cobra.Command{ var downCmd = &cobra.Command{ Use: "down", - Short: "spin down a Cortex cluster", - Long: `This command spins down a Cortex cluster.`, + Short: "spin down a cluster", + Long: `spin down a cluster.`, Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { if err := checkDockerRunning(); err != nil { @@ -267,14 +267,14 @@ func refreshCachedClusterConfig(awsCreds *AWSCredentials) *clusterconfig.Cluster } if userClusterConfig.Region == nil { - errors.Exit(fmt.Sprintf("unable to find an existing cortex cluster; please configure \"%s\" to the s3 region of an existing cortex cluster or create a cortex cluster with `cortex cluster up`", clusterconfig.RegionKey)) + errors.Exit(fmt.Sprintf("unable to find an existing cluster; please configure \"%s\" to the s3 region of an existing cluster or create a cluster with `cortex cluster up`", clusterconfig.RegionKey)) } out, err := runRefreshClusterConfig(userClusterConfig, awsCreds) if err != nil { errors.Exit(err) } - if strings.Contains(out, "there isn't a cortex cluster") { + if strings.Contains(out, "there is no cluster") { errors.Exit() } diff --git a/cli/cmd/completion.go b/cli/cmd/completion.go index 6ffc03b8be..f184fea320 100644 --- a/cli/cmd/completion.go +++ b/cli/cmd/completion.go @@ -26,16 +26,15 @@ import ( var completionCmd = &cobra.Command{ Use: "completion", Short: "generate bash completion scripts", - Long: `Generate bash completion scripts. + Long: `generate bash completion scripts -Add this to your bashrc or bash profile: +add this to your bashrc or bash profile: source <(cortex completion) -Or run: - echo 'source <(cortex completion)' >> ~/.bash_profile # Mac - echo 'source <(cortex completion)' >> ~/.bashrc # Linux +or run: + echo 'source <(cortex completion)' >> ~/.bash_profile # mac + echo 'source <(cortex completion)' >> ~/.bashrc # linux -This will also add the "cx" alias. -Note: Cortex CLI completion requires the bash_completion package to be installed on your system. +this will also add the "cx" alias (note: cli completion requires the bash_completion package to be installed on your system) `, Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { diff --git a/cli/cmd/configure.go b/cli/cmd/configure.go index 86026ef59d..d43d101041 100644 --- a/cli/cmd/configure.go +++ b/cli/cmd/configure.go @@ -33,11 +33,9 @@ func init() { var configureCmd = &cobra.Command{ Use: "configure", - Short: "configure the CLI", - Long: `This command configures the Cortex URL and AWS credentials -in order to authenticate and send requests to Cortex. -The configuration is stored in ~/.cortex.`, - Args: cobra.NoArgs, + Short: "configure the cli", + Long: "configure the cli", + Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { if flagPrint { cliConfig := getDefaults() diff --git a/cli/cmd/delete.go b/cli/cmd/delete.go index db46455763..cd60287866 100644 --- a/cli/cmd/delete.go +++ b/cli/cmd/delete.go @@ -38,7 +38,7 @@ func init() { var deleteCmd = &cobra.Command{ Use: "delete [DEPLOYMENT_NAME]", Short: "delete a deployment", - Long: `This command deletes a deployment from the cluster.`, + Long: "delete a deployment", Args: cobra.MaximumNArgs(1), Run: func(cmd *cobra.Command, args []string) { var appName string diff --git a/cli/cmd/deploy.go b/cli/cmd/deploy.go index 14ca490be1..c9c3e3c72a 100644 --- a/cli/cmd/deploy.go +++ b/cli/cmd/deploy.go @@ -45,9 +45,8 @@ func init() { var deployCmd = &cobra.Command{ Use: "deploy", Short: "create or update a deployment", - Long: `This command sends all project configuration and code to Cortex. -If validations pass, Cortex will attempt to create the desired state.`, - Args: cobra.NoArgs, + Long: "create or update a deployment", + Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { deploy(flagDeployForce, flagDeployRefresh) }, diff --git a/cli/cmd/errors.go b/cli/cmd/errors.go index 549b46c846..0b11f92743 100644 --- a/cli/cmd/errors.go +++ b/cli/cmd/errors.go @@ -129,7 +129,7 @@ func ErrorFailedConnectURL(url url.URL) error { func ErrorFailedToConnectOperator(urlStr string) error { return Error{ Kind: ErrFailedToConnectOperator, - message: fmt.Sprintf("failed to connect to the operator (%s), run `cortex configure` if you need to update the operator URL", urlStr), + message: fmt.Sprintf("failed to connect to the operator (%s), run `cortex configure` if you need to update the operator endpoint", urlStr), } } diff --git a/cli/cmd/get.go b/cli/cmd/get.go index 86810ea99e..5633a9c9c7 100644 --- a/cli/cmd/get.go +++ b/cli/cmd/get.go @@ -57,10 +57,9 @@ func init() { var getCmd = &cobra.Command{ Use: "get [API_NAME]", - Short: "get information about APIs", - Long: `This command displays information about APIs. -Adding the -v or --verbose flag displays additional information.`, - Args: cobra.RangeArgs(0, 1), + Short: "get information about deployments", + Long: "get information about resources", + Args: cobra.RangeArgs(0, 1), Run: func(cmd *cobra.Command, args []string) { rerun(func() (string, error) { return runGet(cmd, args) @@ -424,7 +423,7 @@ func classificationMetricsTable(apiMetrics schema.APIMetrics) string { func describeModelInput(groupStatus *resource.APIGroupStatus, apiEndpoint string) string { if groupStatus.ReadyUpdated+groupStatus.ReadyStaleCompute == 0 { - return "the model's input schema will be available when the API is live" + return "the model's input schema will be available when the api is live" } apiSummary, err := getAPISummary(apiEndpoint) @@ -462,7 +461,7 @@ func describeModelInput(groupStatus *resource.APIGroupStatus, apiEndpoint string func getAPISummary(apiEndpoint string) (*schema.APISummary, error) { req, err := http.NewRequest("GET", apiEndpoint, nil) if err != nil { - return nil, errors.Wrap(err, "unable to request API summary") + return nil, errors.Wrap(err, "unable to request api summary") } req.Header.Set("Content-Type", "application/json") response, err := httpsNoVerifyClient.makeRequest(req) @@ -473,7 +472,7 @@ func getAPISummary(apiEndpoint string) (*schema.APISummary, error) { var apiSummary schema.APISummary err = json.DecodeWithNumber(response, &apiSummary) if err != nil { - return nil, errors.Wrap(err, "unable to parse API summary response") + return nil, errors.Wrap(err, "unable to parse api summary response") } for _, featureSignature := range apiSummary.ModelSignature { diff --git a/cli/cmd/logs.go b/cli/cmd/logs.go index 97421ed9a1..61fc0c9c46 100644 --- a/cli/cmd/logs.go +++ b/cli/cmd/logs.go @@ -31,8 +31,8 @@ func init() { var logsCmd = &cobra.Command{ Use: "logs API_NAME", - Short: "get logs for an API", - Long: `This command streams logs from a deployed API.`, + Short: "stream logs from an api", + Long: "stream logs from an api", Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { resourceName := args[0] diff --git a/cli/cmd/predict.go b/cli/cmd/predict.go index 13937ac0e1..18a682585b 100644 --- a/cli/cmd/predict.go +++ b/cli/cmd/predict.go @@ -35,15 +35,14 @@ var predictDebug bool func init() { addAppNameFlag(predictCmd) addEnvFlag(predictCmd) - predictCmd.Flags().BoolVar(&predictDebug, "debug", false, "Predict with debug mode") + predictCmd.Flags().BoolVar(&predictDebug, "debug", false, "predict with debug mode") } var predictCmd = &cobra.Command{ Use: "predict API_NAME SAMPLE_FILE", - Short: "make a prediction request", - Long: `This command makes a prediction request using -a JSON file and displays the response.`, - Args: cobra.ExactArgs(2), + Short: "make a prediction request using a json file", + Long: "make a prediction request using a json file", + Args: cobra.ExactArgs(2), Run: func(cmd *cobra.Command, args []string) { apiName := args[0] sampleJSONPath := args[1] diff --git a/cli/cmd/root.go b/cli/cmd/root.go index 0169980560..0c21175e9c 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -70,7 +70,7 @@ var rootCmd = &cobra.Command{ Use: "cortex", Aliases: []string{"cx"}, Short: "deploy machine learning models in production", - Long: `Deploy machine learning models in production`, + Long: `deploy machine learning models in production`, } func Execute() { @@ -106,11 +106,11 @@ func updateRootUsage() { return defaultUsageFunc(cmd) } - usage = strings.Replace(usage, "Usage:\n cortex [command]\n\nAliases:\n cortex, cx\n\n", "", 1) - usage = strings.Replace(usage, "Available Commands:", "Deployment commands:", 1) - usage = strings.Replace(usage, "\n cluster", "\n\nCluster commands:\n cluster", 1) - usage = strings.Replace(usage, "\n configure", "\n\nOther commands:\n configure", 1) - usage = strings.Replace(usage, "\nUse \"cortex", " help help about any command\n\nFlags:\n -h, --help help for cortex\n\nUse \"cortex", 1) + usage = strings.Replace(usage, "usage:\n cortex [command]\n\naliases:\n cortex, cx\n\n", "", 1) + usage = strings.Replace(usage, "available commands:", "deployment commands:", 1) + usage = strings.Replace(usage, "\n cluster", "\n\ncluster commands:\n cluster", 1) + usage = strings.Replace(usage, "\n configure", "\n\nother commands:\n configure", 1) + usage = strings.Replace(usage, "\nUse \"cortex", " help help about any command\n\nflags:\n -h, --help help for cortex\n\nUse \"cortex", 1) cmd.Print(usage) @@ -136,11 +136,11 @@ func addAppNameFlag(cmd *cobra.Command) { cmd.PersistentFlags().StringVarP(&flagAppName, "deployment", "d", "", "deployment name") } -var resourceTypesHelp = fmt.Sprintf("\nResource Types:\n %s\n", strings.Join(resource.VisibleTypes.StringList(), "\n ")) +var resourceTypesHelp = fmt.Sprintf("\nresource types:\n %s\n", strings.Join(resource.VisibleTypes.StringList(), "\n ")) func addResourceTypesToHelp(cmd *cobra.Command) { usage := cmd.UsageTemplate() - usage = strings.Replace(usage, "\nFlags:\n", resourceTypesHelp+"\nFlags:\n", 1) + usage = strings.Replace(usage, "\nflags:\n", resourceTypesHelp+"\nflags:\n", 1) cmd.SetUsageTemplate(usage) } diff --git a/cli/cmd/support.go b/cli/cmd/support.go index 914f6570a9..e434381b12 100644 --- a/cli/cmd/support.go +++ b/cli/cmd/support.go @@ -66,8 +66,8 @@ var supportPrompValidation = &cr.PromptValidation{ var supportCmd = &cobra.Command{ Use: "support", - Short: "send a support request to Cortex maintainers", - Long: `This command sends a support request to the Cortex maintainers`, + Short: "send a support request to the maintainers", + Long: "send a support request to the maintainers", Run: func(cmd *cobra.Command, args []string) { supportRequest := &SupportRequest{} err := cr.ReadPrompt(supportRequest, supportPrompValidation) diff --git a/cli/cmd/version.go b/cli/cmd/version.go index 35efe015e7..89e2a8d30a 100644 --- a/cli/cmd/version.go +++ b/cli/cmd/version.go @@ -33,29 +33,29 @@ func init() { var versionCmd = &cobra.Command{ Use: "version", - Short: "print the version of the CLI and cluster", - Long: `This command prints the version of the CLI and cluster`, + Short: "print the cli and cluster versions", + Long: `print the cli and cluster versions`, Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { if !isCLIConfigured() { - fmt.Println("CLI version: " + consts.CortexVersion + "\n") - fmt.Println("Run `cortex configure` to connect the CLI to a Cortex cluster") + fmt.Println("cli version: " + consts.CortexVersion + "\n") + fmt.Println("run `cortex configure` to connect the cli to a cluster") return } httpResponse, err := HTTPGet("/info") if err != nil { - fmt.Println("CLI version: " + consts.CortexVersion + "\n") + fmt.Println("cli version: " + consts.CortexVersion + "\n") errors.Exit(err) } var infoResponse schema.InfoResponse err = json.Unmarshal(httpResponse, &infoResponse) if err != nil { - fmt.Println("CLI version: " + consts.CortexVersion + "\n") + fmt.Println("cli version: " + consts.CortexVersion + "\n") errors.Exit(err, "/info", string(httpResponse)) } - fmt.Println("CLI version: " + consts.CortexVersion) - fmt.Println("Cluster version: " + infoResponse.ClusterConfig.APIVersion) + fmt.Println("cli version: " + consts.CortexVersion) + fmt.Println("cluster version: " + infoResponse.ClusterConfig.APIVersion) }, } diff --git a/docs/cluster/cli.md b/docs/cluster/cli.md index 076728266d..9e829e00d6 100644 --- a/docs/cluster/cli.md +++ b/docs/cluster/cli.md @@ -3,28 +3,27 @@ ## deploy ```text -This command sends all project configuration and code to Cortex. -If validations pass, Cortex will attempt to create the desired state. +create or update a deployment -Usage: +usage: cortex deploy [flags] -Flags: +flags: -e, --env string environment (default "default") -f, --force override the in-progress deployment update -h, --help help for deploy - -r, --refresh re-deploy all APIs with cleared cache and rolling updates + -r, --refresh re-deploy all apis with cleared cache and rolling updates ``` ## get ```text -Get information about resources. +get information about resources -Usage: +usage: cortex get [RESOURCE_NAME] [flags] -Flags: +flags: -a, --all-deployments list all deployments -d, --deployment string deployment name -e, --env string environment (default "default") @@ -37,12 +36,12 @@ Flags: ## logs ```text -This command streams logs from a deployed API. +stream logs from an api -Usage: +usage: cortex logs API_NAME [flags] -Flags: +flags: -d, --deployment string deployment name -e, --env string environment (default "default") -h, --help help for logs @@ -51,13 +50,12 @@ Flags: ## predict ```text -This command makes a prediction request using -a JSON file and displays the response. +make a prediction request using a json file -Usage: +usage: cortex predict API_NAME SAMPLE_FILE [flags] -Flags: +flags: --debug Predict with debug mode -d, --deployment string deployment name -e, --env string environment (default "default") @@ -67,12 +65,12 @@ Flags: ## delete ```text -This command deletes a deployment from the cluster. +delete a deployment -Usage: +usage: cortex delete [DEPLOYMENT_NAME] [flags] -Flags: +flags: -e, --env string environment (default "default") -h, --help help for delete -c, --keep-cache keep cached data for the deployment @@ -81,64 +79,64 @@ Flags: ## cluster up ```text -This command spins up a Cortex cluster on your AWS account. +spin up a cluster -Usage: +usage: cortex cluster up [flags] -Flags: - -c, --config string path to a Cortex cluster configuration file +flags: + -c, --config string path to a cortex cluster configuration file -h, --help help for up ``` ## cluster info ```text -This command gets information about a Cortex cluster. +get information about a cluster -Usage: +usage: cortex cluster info [flags] -Flags: - -c, --config string path to a Cortex cluster configuration file +flags: + -c, --config string path to a cortex cluster configuration file -h, --help help for info ``` ## cluster update ```text -This command updates a Cortex cluster. +update a cluster -Usage: +usage: cortex cluster update [flags] -Flags: - -c, --config string path to a Cortex cluster configuration file +flags: + -c, --config string path to a cortex cluster configuration file -h, --help help for update ``` ## cluster down ```text -This command spins down a Cortex cluster. +spin down a cluster -Usage: +usage: cortex cluster down [flags] -Flags: - -c, --config string path to a Cortex cluster configuration file +flags: + -c, --config string path to a cortex cluster configuration file -h, --help help for down ``` ## version ```text -This command prints the version of the CLI and cluster. +print the cli and cluster versions -Usage: +usage: cortex version [flags] -Flags: +flags: -e, --env string environment (default "default") -h, --help help for version ``` @@ -146,14 +144,12 @@ Flags: ## configure ```text -This command configures the Cortex URL and AWS credentials -in order to authenticate and send requests to Cortex. -The configuration is stored in ~/.cortex. +configure the cli -Usage: +usage: cortex configure [flags] -Flags: +flags: -e, --env string environment (default "default") -h, --help help for configure -p, --print print the configuration @@ -162,32 +158,31 @@ Flags: ## support ```text -This command sends a support request to the Cortex maintainers +send a support request to the maintainers -Usage: +usage: cortex support [flags] -Flags: +flags: -h, --help help for support ``` ## completion ```text -Generate bash completion scripts. +generate bash completion scripts -Add this to your bashrc or bash profile: +add this to your bashrc or bash profile: source <(cortex completion) -Or run: - echo 'source <(cortex completion)' >> ~/.bash_profile # Mac - echo 'source <(cortex completion)' >> ~/.bashrc # Linux +or run: + echo 'source <(cortex completion)' >> ~/.bash_profile # mac + echo 'source <(cortex completion)' >> ~/.bashrc # linux -This will also add the "cx" alias. -Note: Cortex CLI completion requires the bash_completion package to be installed on your system. +this will also add the "cx" alias (note: cli completion requires the bash_completion package to be installed on your system) -Usage: +usage: cortex completion [flags] -Flags: +flags: -h, --help help for completion ``` diff --git a/docs/cluster/install.md b/docs/cluster/install.md index 934ce86e08..86ba6be430 100644 --- a/docs/cluster/install.md +++ b/docs/cluster/install.md @@ -12,10 +12,10 @@ See [cluster configuration](config.md) to learn how you can customize your clust ```bash # Install the Cortex CLI on your machine -bash -c "$(curl -sS https://raw.githubusercontent.com/cortexlabs/cortex/master/get-cli.sh)" +$ bash -c "$(curl -sS https://raw.githubusercontent.com/cortexlabs/cortex/master/get-cli.sh)" # Provision infrastructure on AWS and install Cortex -cortex cluster up +$ cortex cluster up ``` Note: This will create resources in your AWS account which aren't included in the free tier, e.g. an EKS cluster, two Elastic Load Balancers, and EC2 instances (quantity and type as specified above). To use GPU nodes, you may need to subscribe to the [EKS-optimized AMI with GPU Support](https://aws.amazon.com/marketplace/pp/B07GRHFXGM) and [file an AWS support ticket](https://console.aws.amazon.com/support/cases#/create?issueType=service-limit-increase&limitType=ec2-instances) to increase the limit for your desired instance type. @@ -26,31 +26,31 @@ Note: This will create resources in your AWS account which aren't included in th ```bash # Clone the Cortex repository -git clone -b master https://github.com/cortexlabs/cortex.git +$ git clone -b master https://github.com/cortexlabs/cortex.git # Navigate to the iris classifier example -cd cortex/examples/sklearn/iris-classifier +$ cd cortex/examples/sklearn/iris-classifier # Deploy the model to the cluster -cortex deploy +$ cortex deploy # View the status of the deployment -cortex get --watch +$ cortex get --watch # Get the API's endpoint -cortex get classifier +$ cortex get classifier # Classify a sample -curl -X POST -H "Content-Type: application/json" \ - -d '{ "sepal_length": 5.2, "sepal_width": 3.6, "petal_length": 1.4, "petal_width": 0.3 }' \ - +$ curl -X POST -H "Content-Type: application/json" \ + -d '{ "sepal_length": 5.2, "sepal_width": 3.6, "petal_length": 1.4, "petal_width": 0.3 }' \ + ``` ## Cleanup ```bash # Delete the deployment -cortex delete iris +$ cortex delete iris ``` See [uninstall](uninstall.md) if you'd like to uninstall Cortex. diff --git a/docs/cluster/uninstall.md b/docs/cluster/uninstall.md index a811e4ca39..865caa758d 100644 --- a/docs/cluster/uninstall.md +++ b/docs/cluster/uninstall.md @@ -5,16 +5,17 @@ 1. [AWS credentials](aws.md) 2. [Docker](https://docs.docker.com/install) 3. [Cortex CLI](install.md) +4. [AWS CLI](https://aws.amazon.com/cli) ## Uninstalling Cortex ```bash # Spin down the cluster -cortex cluster down +$ cortex cluster down # Uninstall the CLI -sudo rm /usr/local/bin/cortex -rm -rf ~/.cortex +$ sudo rm /usr/local/bin/cortex +$ rm -rf ~/.cortex ``` If you modified your bash profile, you may wish to remove `source <(cortex completion)`. @@ -23,13 +24,13 @@ If you modified your bash profile, you may wish to remove `source <(cortex compl ```bash # Set AWS credentials -export AWS_ACCESS_KEY_ID=*** -export AWS_SECRET_ACCESS_KEY=*** +$ export AWS_ACCESS_KEY_ID=*** +$ export AWS_SECRET_ACCESS_KEY=*** # Delete the S3 bucket -aws s3 ls -aws s3 rb --force s3:// +$ aws s3 ls +$ aws s3 rb --force s3:// # Delete the log group -aws logs describe-log-groups --log-group-name-prefix= --query logGroups[*].[logGroupName] --output text | xargs -I {} aws logs delete-log-group --log-group-name {} +$ aws logs describe-log-groups --log-group-name-prefix= --query logGroups[*].[logGroupName] --output text | xargs -I {} aws logs delete-log-group --log-group-name {} ``` diff --git a/docs/cluster/update.md b/docs/cluster/update.md index f01147d8af..34aa68ba3b 100644 --- a/docs/cluster/update.md +++ b/docs/cluster/update.md @@ -10,7 +10,7 @@ See [cluster configuration](config.md) to learn how you can customize your cluster. ```bash -cortex cluster update +$ cortex cluster update ``` ## Upgrading to a newer version of Cortex @@ -19,14 +19,14 @@ cortex cluster update ```bash # Spin down your cluster -cortex cluster down +$ cortex cluster down # Update your CLI -bash -c "$(curl -sS https://raw.githubusercontent.com/cortexlabs/cortex/master/get-cli.sh)" +$ bash -c "$(curl -sS https://raw.githubusercontent.com/cortexlabs/cortex/master/get-cli.sh)" # Confirm version -cortex version +$ cortex version # Spin up your cluster -cortex cluster up +$ cortex cluster up ``` diff --git a/examples/README.md b/examples/README.md index d23d39fb17..156ca5cc2b 100644 --- a/examples/README.md +++ b/examples/README.md @@ -32,4 +32,6 @@ ## scikit-learn -- [MPG estimation with scikit-learn](sklearn/mpg-estimation): deploy a linear regression model to estimate MPG. +- [Iris classification](sklearn/mpg-estimation): deploy a model to classify iris flowers. + +- [MPG estimation](sklearn/mpg-estimation): deploy a linear regression model to estimate MPG. diff --git a/examples/pytorch/answer-generator/cortex.yaml b/examples/pytorch/answer-generator/cortex.yaml index bd546df0b3..75a87ff42f 100644 --- a/examples/pytorch/answer-generator/cortex.yaml +++ b/examples/pytorch/answer-generator/cortex.yaml @@ -6,7 +6,7 @@ predictor: path: predictor.py metadata: - device: cpu # use "cuda" to run on GPUs + device: cuda # use "cpu" to run on CPUs compute: - cpu: 1 + gpu: 1 mem: 4G diff --git a/examples/pytorch/image-classifier/README.md b/examples/pytorch/image-classifier/README.md deleted file mode 100644 index 12069c50e1..0000000000 --- a/examples/pytorch/image-classifier/README.md +++ /dev/null @@ -1,107 +0,0 @@ -# Deploy Image Classification as an API - -This example shows how to deploy a pretrained image classifier from TorchVision. - -## Predictor - -We implement Cortex's Predictor interface to load the model and make predictions. Cortex will use this implementation to serve the model as an autoscaling API. - -### Initialization - -We can place our code to download and initialize the model in the body of the implementation: - -```python -# predictor.py - -# download the pretrained AlexNet model -model = torchvision.models.alexnet(pretrained=True) -model.eval() - -# declare the necessary image preprocessing -normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) -preprocess = transforms.Compose( - [transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), normalize] -) - -# download the labels -labels = requests.get( - "https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt" -).text.split("\n")[1:] -``` - -### Predict - -The `predict()` function will be triggered once per request. The AlexNet model requires a 2-dimensional array of 3-valued tuples representing the RGB values for each pixel in the image, but the API should accept a simple input format such as a URL to an image. Also, instead of returning the model's output as an array of probabilities, the API should return the class name with the highest probability. We use the `predict()` function to download the image specified by the url in the request, process it, feed it to the model, convert the model output weights to a label, and return the label: - -```python -# predictor.py - -def predict(sample, metadata): - image = requests.get(sample["url"]).content - img_pil = Image.open(BytesIO(image)) - img_tensor = preprocess(img_pil) - img_tensor.unsqueeze_(0) - with torch.no_grad(): - prediction = model(img_tensor) - _, index = prediction[0].max(0) - return labels[index] -``` - -See [predictor.py](./predictor.py) for the complete code. - -## Define a deployment - -A `deployment` specifies a set of resources that are deployed together. An `api` makes our implementation available as a web service that can serve real-time predictions. This configuration will deploy the implementation specified in `predictor.py`: - -```yaml -# cortex.yaml - -- kind: deployment - name: image - -- kind: api - name: classifier - predictor: - path: predictor.py -``` - -## Deploy to AWS - -`cortex deploy` takes the declarative configuration from `cortex.yaml` and creates it on the cluster: - -```bash -$ cortex deploy - -creating classifier -``` - -Behind the scenes, Cortex containerizes our implementation, makes it servable using Flask, exposes the endpoint with a load balancer, and orchestrates the workload on Kubernetes. - -We can track the statuses of the APIs using `cortex get`: - -```bash -$ cortex get classifier --watch - -status up-to-date available requested last update avg latency -live 1 1 1 12s - -``` - -The output above indicates that one replica of the API was requested and is available to serve predictions. Cortex will automatically launch more replicas if the load increases and spin down replicas if there is unused capacity. - -## Serve real-time predictions - -We can use `curl` to test our prediction service: - -```bash -$ cortex get classifier - -endpoint: http://***.amazonaws.com/image/classifier - -$ curl http://***.amazonaws.com/image/classifier \ - -X POST -H "Content-Type: application/json" \ - -d '{"url": "https://i.imgur.com/PzXprwl.jpg"}' - -"hotdog" -``` - -Any questions? [chat with us](https://gitter.im/cortexlabs/cortex). diff --git a/examples/pytorch/image-classifier/cortex.yaml b/examples/pytorch/image-classifier/cortex.yaml index 0782b8a621..a399c3ff7e 100644 --- a/examples/pytorch/image-classifier/cortex.yaml +++ b/examples/pytorch/image-classifier/cortex.yaml @@ -5,3 +5,6 @@ name: classifier predictor: path: predictor.py + compute: + gpu: 1 + mem: 4G diff --git a/examples/pytorch/iris-classifier/README.md b/examples/pytorch/iris-classifier/README.md deleted file mode 100644 index bda16d547b..0000000000 --- a/examples/pytorch/iris-classifier/README.md +++ /dev/null @@ -1,114 +0,0 @@ -# Deploy a PyTorch iris classifier - -This example shows how to deploy a classifier trained on the famous [iris data set](https://archive.ics.uci.edu/ml/datasets/iris) in PyTorch. The PyTorch model being deployed can be found [here](./src/my_model.py). - -## Predictor - -We implement Cortex's Predictor interface to load the model and make predictions. Cortex will use this implementation to serve the model as an autoscaling API. - -### Initialization - -We can place our code to download and initialize the model in the `init()` function. The PyTorch model class is defined in [src/model.py](./src/model.py), and we assume that we've already trained the model and uploaded the state_dict (weights) to S3. - -```python -# predictor.py - -from model import IrisNet - -# instantiate the model -model = IrisNet() - -# define the labels -labels = ["iris-setosa", "iris-versicolor", "iris-virginica"] - -def init(model_path, metadata): - # model_path is a local path pointing to your model weights file - model.load_state_dict(torch.load(model_path)) - model.eval() -``` - -### Predict - -The `predict()` function will be triggered once per request. We extract the features from the sample sent in the request, feed them to the model, and respond with a human-readable label: - -```python -# predictor.py - -def predict(sample, metadata): - input_tensor = torch.FloatTensor( - [ - [ - sample["sepal_length"], - sample["sepal_width"], - sample["petal_length"], - sample["petal_width"], - ] - ] - ) - - output = model(input_tensor) - return labels[torch.argmax(output[0])] -``` - -See [predictor.py](./src/predictor.py) for the complete code. - -## Define a deployment - -A `deployment` specifies a set of resources that are deployed together. An `api` makes our implementation available as a web service that can serve real-time predictions. This configuration will deploy the implementation specified in `predictor.py`. Note that the `metadata` will be passed into the `init()` function, and we specify the `python_path` in the so we can import our model as `from my_model import IrisNet` instead of `from src.my_model import IrisNet` in `predictor.py`. - -```yaml -# cortex.yaml - -- kind: deployment - name: iris - -- kind: api - name: classifier - predictor: - path: src/predictor.py - python_path: src/ - model: s3://cortex-examples/pytorch/iris-classifier/weights.pth - tracker: - model_type: classification -``` - -## Deploy to AWS - -`cortex deploy` takes the declarative configuration from `cortex.yaml` and creates it on the cluster: - -```bash -$ cortex deploy - -creating classifier -``` - -Behind the scenes, Cortex containerizes our implementation, makes it servable using Flask, exposes the endpoint with a load balancer, and orchestrates the workload on Kubernetes. - -We can track the status of a deployment using `cortex get`: - -```bash -$ cortex get classifier --watch - -status up-to-date available requested last update avg latency -live 1 1 1 8s - -``` - -The output above indicates that one replica of the API was requested and is available to serve predictions. Cortex will automatically launch more replicas if the load increases and spin down replicas if there is unused capacity. - -## Serve real-time predictions - -We can use `curl` to test our prediction service: - -```bash -$ cortex get classifier - -endpoint: http://***.amazonaws.com/iris/classifier - -$ curl http://***.amazonaws.com/iris/classifier \ - -X POST -H "Content-Type: application/json" \ - -d '{"sepal_length": 5.2, "sepal_width": 3.6, "petal_length": 1.4, "petal_width": 0.3}' - -"iris-setosa" -``` - -Any questions? [chat with us](https://gitter.im/cortexlabs/cortex). diff --git a/examples/pytorch/iris-classifier/cortex.yaml b/examples/pytorch/iris-classifier/cortex.yaml index 937c38d7a9..3c0ecbdb66 100644 --- a/examples/pytorch/iris-classifier/cortex.yaml +++ b/examples/pytorch/iris-classifier/cortex.yaml @@ -4,8 +4,7 @@ - kind: api name: classifier predictor: - path: src/predictor.py - python_path: src/ + path: predictor.py model: s3://cortex-examples/pytorch/iris-classifier/weights.pth tracker: model_type: classification diff --git a/examples/pytorch/iris-classifier/src/model.py b/examples/pytorch/iris-classifier/model.py similarity index 100% rename from examples/pytorch/iris-classifier/src/model.py rename to examples/pytorch/iris-classifier/model.py diff --git a/examples/pytorch/iris-classifier/src/predictor.py b/examples/pytorch/iris-classifier/predictor.py similarity index 100% rename from examples/pytorch/iris-classifier/src/predictor.py rename to examples/pytorch/iris-classifier/predictor.py diff --git a/examples/pytorch/language-identifier/cortex.yaml b/examples/pytorch/language-identifier/cortex.yaml index 7473c7382c..42557bee15 100644 --- a/examples/pytorch/language-identifier/cortex.yaml +++ b/examples/pytorch/language-identifier/cortex.yaml @@ -7,3 +7,6 @@ path: predictor.py tracker: model_type: classification + compute: + gpu: 1 + mem: 4G diff --git a/examples/pytorch/language-identifier/predictor.py b/examples/pytorch/language-identifier/predictor.py index 19b934dc0e..2cf8ffc951 100644 --- a/examples/pytorch/language-identifier/predictor.py +++ b/examples/pytorch/language-identifier/predictor.py @@ -1,10 +1,9 @@ import wget import fasttext -wget.download( - "https://dl.fbaipublicfiles.com/fasttext/supervised-models/lid.176.bin", "lid.176.bin" -) -model = fasttext.load_model("lid.176.bin") + +wget.download("https://dl.fbaipublicfiles.com/fasttext/supervised-models/lid.176.bin", "model") +model = fasttext.load_model("model") def predict(sample, metadata): diff --git a/examples/pytorch/reading-comprehender/cortex.yaml b/examples/pytorch/reading-comprehender/cortex.yaml index e5600560b1..3546c94871 100644 --- a/examples/pytorch/reading-comprehender/cortex.yaml +++ b/examples/pytorch/reading-comprehender/cortex.yaml @@ -6,5 +6,5 @@ predictor: path: predictor.py compute: - cpu: 1 + gpu: 1 mem: 4G diff --git a/examples/pytorch/text-generator/README.md b/examples/pytorch/text-generator/README.md deleted file mode 100644 index 6d7cb6458c..0000000000 --- a/examples/pytorch/text-generator/README.md +++ /dev/null @@ -1,104 +0,0 @@ -# Self-host HuggingFace's GPT-2 as a service - -This example shows how to deploy [HuggingFace's DistilGPT2](https://github.com/huggingface/transformers/tree/master/examples/distillation) model as a service on AWS. DistilGPT2 is a compressed version of OpenAI's GPT-2. - -## Predictor - -We implement Cortex's Predictor interface to load the model and make predictions. Cortex will use this implementation to serve the model as an autoscaling API. - -### Initialization - -We can place our code to download and initialize the model in the body of the implementation, and we can load it onto a GPU in the `init()` function: - -```python -# predictor.py - -# download the pretrained DistilGPT2 model and set it to evaluation -model = GPT2LMHeadModel.from_pretrained("distilgpt2") -model.eval() - -# download the tokenizer -tokenizer = GPT2Tokenizer.from_pretrained("distilgpt2") - -def init(model_path, metadata): - # load the model onto the device specified in the metadata field of our api configuration - model.to(metadata["device"]) -``` - -### Predict - -The `predict()` function will be triggered once per request. We tokenize the input, run it through the model, decode the output, and respond with the generated text. - -```python -# predictor.py - -def predict(sample, metadata): - indexed_tokens = tokenizer.encode(sample["text"]) - output = sample_sequence(model, metadata['num_words'], indexed_tokens, device=metadata['device']) - return tokenizer.decode( - output[0, 0:].tolist(), clean_up_tokenization_spaces=True, skip_special_tokens=True - ) -``` - -See [predictor.py](./predictor.py) for the complete code. - -## Define a deployment - -A `deployment` specifies a set of resources that are deployed together. An `api` makes our implementation available as a web service that can serve real-time predictions. This configuration will deploy the implementation specified in `predictor.py`: - -```yaml -# cortex.yaml - -- kind: deployment - name: text - -- kind: api - name: generator - predictor: - path: predictor.py - metadata: - num_words: 50 # generate 50 words per request - device: cuda # run on GPU - compute: - gpu: 1 - cpu: 1 -``` - -## Deploy to AWS - -`cortex deploy` takes the declarative configuration from `cortex.yaml` and creates it on the cluster. - -```bash -$ cortex deploy - -creating generator -``` - -Behind the scenes, Cortex containerizes our implementation, makes it servable using Flask, exposes the endpoint with a load balancer, and orchestrates the workload on Kubernetes. - -We can track the status of a deployment using `cortex get`: - -```bash -$ cortex get generator --watch - -status up-to-date available requested last update avg latency -live 1 1 1 9m - -``` - -The output above indicates that one replica of the API was requested and is available to serve predictions. Cortex will automatically launch more replicas if the load increases and spin down replicas if there is unused capacity. - -## Serve real-time predictions - -We can use `curl` to test our prediction service: - -```bash -$ cortex get generator - -endpoint: http://***.amazonaws.com/text/generator - -$ curl http://***.amazonaws.com/text/generator \ - -X POST -H "Content-Type: application/json" \ - -d '{"text": "machine learning"}' -``` - -Any questions? [chat with us](https://gitter.im/cortexlabs/cortex). diff --git a/examples/sklearn/mpg-estimation/cortex.yaml b/examples/sklearn/mpg-estimator/cortex.yaml similarity index 50% rename from examples/sklearn/mpg-estimation/cortex.yaml rename to examples/sklearn/mpg-estimator/cortex.yaml index f98f689ebb..7e7b773225 100644 --- a/examples/sklearn/mpg-estimation/cortex.yaml +++ b/examples/sklearn/mpg-estimator/cortex.yaml @@ -1,8 +1,8 @@ - kind: deployment - name: auto + name: mpg - kind: api - name: mpg + name: estimator predictor: path: predictor.py - model: s3://cortex-examples/sklearn/mpg-estimation/linreg + model: s3://cortex-examples/sklearn/mpg-estimator/linreg diff --git a/examples/sklearn/mpg-estimation/predictor.py b/examples/sklearn/mpg-estimator/predictor.py similarity index 100% rename from examples/sklearn/mpg-estimation/predictor.py rename to examples/sklearn/mpg-estimator/predictor.py diff --git a/examples/sklearn/mpg-estimation/requirements.txt b/examples/sklearn/mpg-estimator/requirements.txt similarity index 100% rename from examples/sklearn/mpg-estimation/requirements.txt rename to examples/sklearn/mpg-estimator/requirements.txt index 5d36e22b63..99c556c375 100644 --- a/examples/sklearn/mpg-estimation/requirements.txt +++ b/examples/sklearn/mpg-estimator/requirements.txt @@ -1,4 +1,4 @@ mlflow -scikit-learn pandas numpy +scikit-learn diff --git a/examples/sklearn/mpg-estimation/sample.json b/examples/sklearn/mpg-estimator/sample.json similarity index 100% rename from examples/sklearn/mpg-estimation/sample.json rename to examples/sklearn/mpg-estimator/sample.json diff --git a/examples/sklearn/mpg-estimation/model.py b/examples/sklearn/mpg-estimator/trainer.py similarity index 53% rename from examples/sklearn/mpg-estimation/model.py rename to examples/sklearn/mpg-estimator/trainer.py index 4a85c0a069..2ac73865a7 100644 --- a/examples/sklearn/mpg-estimation/model.py +++ b/examples/sklearn/mpg-estimator/trainer.py @@ -1,22 +1,23 @@ import mlflow.sklearn -import pandas as pd -import numpy as np +import pandas +import numpy from sklearn.linear_model import LinearRegression from sklearn.model_selection import train_test_split -df = pd.read_csv( +df = pandas.read_csv( "https://www.uio.no/studier/emner/sv/oekonomi/ECON4150/v16/statacourse/datafiles/auto.csv" ) -df = df.replace("?", np.nan) +df = df.replace("?", numpy.nan) df = df.dropna() df = df.drop(["name", "origin", "year"], axis=1) # drop categorical variables for simplicity -X = df.drop("mpg", axis=1) -y = df[["mpg"]] - -X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1) +data = df.drop("mpg", axis=1) +labels = df[["mpg"]] +training_data, test_data, training_labels, test_labels = train_test_split(data, labels) model = LinearRegression() -model.fit(X_train, y_train) +model.fit(training_data, training_labels) +accuracy = model.score(test_data, test_labels) +print("accuracy: {:.2f}".format(accuracy)) mlflow.sklearn.save_model(model, "linreg") diff --git a/examples/tensorflow/iris-classifier/README.md b/examples/tensorflow/iris-classifier/README.md deleted file mode 100644 index 274007a666..0000000000 --- a/examples/tensorflow/iris-classifier/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# Deploy an iris classifier - -This example shows how to deploy a classifier trained on the famous [iris data set](https://archive.ics.uci.edu/ml/datasets/iris). - -## Define a deployment - -A `deployment` specifies a set of resources that are deployed together. An `api` makes our exported model available as a web service that can serve real-time predictions. This configuration will deploy our model from the `cortex-examples` S3 bucket: - -```yaml -# cortex.yaml - -- kind: deployment - name: iris - -- kind: api - name: classifier - tensorflow: - model: s3://cortex-examples/tensorflow/iris-classifier/nn - request_handler: handler.py - tracker: - model_type: classification -``` - - -You can run the code that generated the exported model used in this example [here](https://colab.research.google.com/github/cortexlabs/cortex/blob/master/examples/tensorflow/iris-classifier/tensorflow.ipynb). - -## Add request handling - -The API should convert the model’s prediction to a human readable label before responding. This can be implemented in a request handler file: - -```python -# handler.py - -labels = ["iris-setosa", "iris-versicolor", "iris-virginica"] - -def post_inference(prediction, metadata): - label_index = int(prediction["class_ids"][0]) - return labels[label_index] -``` - -## Deploy to AWS - -`cortex deploy` takes the declarative configuration from `cortex.yaml` and creates it on the cluster: - -```bash -$ cortex deploy - -creating classifier -``` - -Behind the scenes, Cortex containerizes our implementation, makes it servable using Flask, exposes the endpoint with a load balancer, and orchestrates the workload on Kubernetes. - -We can track the status of a deployment using `cortex get`: - -```bash -$ cortex get classifier --watch - -status up-to-date available requested last update avg latency -live 1 1 1 8s - -``` - -The output above indicates that one replica of the API was requested and is available to serve predictions. Cortex will automatically launch more replicas if the load increases and spin down replicas if there is unused capacity. - -## Serve real-time predictions - -We can use `curl` to test our prediction service: - -```bash -$ cortex get classifier - -endpoint: http://***.amazonaws.com/iris/classifier - -$ curl http://***.amazonaws.com/iris/classifier \ - -X POST -H "Content-Type: application/json" \ - -d '{"sepal_length": 5.2, "sepal_width": 3.6, "petal_length": 1.4, "petal_width": 0.3}' - -"iris-setosa" -``` - -Any questions? [chat with us](https://gitter.im/cortexlabs/cortex). diff --git a/examples/tensorflow/sentiment-analysis/README.md b/examples/tensorflow/sentiment-analysis/README.md deleted file mode 100644 index 79f1812d3e..0000000000 --- a/examples/tensorflow/sentiment-analysis/README.md +++ /dev/null @@ -1,97 +0,0 @@ -# Deploy a BERT sentiment analysis API - -This example shows how to deploy a sentiment analysis classifier trained using [BERT](https://github.com/google-research/bert). - -## Define a deployment - -A `deployment` specifies a set of resources that are deployed together. An `api` makes our exported model available as a web service that can serve real-time predictions. This configuration will download the model from the `cortex-examples` S3 bucket, and will preprocess the payload and postprocess the inference with functions defined in `handler.py`. - -```yaml -# cortex.yaml - -- kind: deployment - name: sentiment - -- kind: api - name: classifier - tensorflow: - model: s3://cortex-examples/tensorflow/sentiment-analysis/bert - request_handler: handler.py - tracker: - model_type: classification -``` - - -You can run the code that generated the exported BERT model [here](https://colab.research.google.com/github/cortexlabs/cortex/blob/master/examples/tensorflow/sentiment-analysis/bert.ipynb). - -## Add request handling - -The model requires tokenized input for inference, but the API should accept strings of natural language as input. It should also map the model’s integer predictions to the actual sentiment label. This can be implemented in a request handler file. Define a `pre_inference()` function to tokenize request payloads and a `post_inference()` function to map inference output to labels before responding to the client: - -```python -# handler.py - -import tensorflow as tf -import tensorflow_hub as hub -from bert import tokenization, run_classifier - -labels = ["negative", "positive"] - -with tf.Graph().as_default(): - bert_module = hub.Module("https://tfhub.dev/google/bert_uncased_L-12_H-768_A-12/1") - info = bert_module(signature="tokenization_info", as_dict=True) - with tf.Session() as sess: - vocab_file, do_lower_case = sess.run([info["vocab_file"], info["do_lower_case"]]) -tokenizer = tokenization.FullTokenizer(vocab_file=vocab_file, do_lower_case=do_lower_case) - - -def pre_inference(sample, signature, metadata): - input_example = run_classifier.InputExample(guid="", text_a=sample["review"], label=0) - input_feature = run_classifier.convert_single_example(0, input_example, [0, 1], 128, tokenizer) - return {"input_ids": [input_feature.input_ids]} - - -def post_inference(prediction, signature, metadata): - return labels[prediction["labels"][0]] -``` - -## Deploy to AWS - -`cortex deploy` takes the declarative configuration from `cortex.yaml` and creates it on the cluster: - -```bash -$ cortex deploy - -creating classifier -``` - -Behind the scenes, Cortex containerizes our implementation, makes it servable using Flask, exposes the endpoint with a load balancer, and orchestrates the workload on Kubernetes. - -We can track the status of a deployment using `cortex get`: - -```bash -$ cortex get classifier --watch - -status up-to-date available requested last update avg latency -live 1 1 1 8s - -``` - -The output above indicates that one replica of the API was requested and is available to serve predictions. Cortex will automatically launch more replicas if the load increases and spin down replicas if there is unused capacity. - -## Serve real-time predictions - -We can use `curl` to test our prediction service: - -```bash -$ cortex get classifier - -endpoint: http://***.amazonaws.com/sentiment/classifier - -$ curl http://***.amazonaws.com/sentiment/classifier \ - -X POST -H "Content-Type: application/json" \ - -d '{"review": "The movie was great!"}' - -"positive" -``` - -Any questions? [chat with us](https://gitter.im/cortexlabs/cortex). diff --git a/examples/tensorflow/sentiment-analysis/cortex.yaml b/examples/tensorflow/sentiment-analysis/cortex.yaml index 76bf2db4a0..22bc740c60 100644 --- a/examples/tensorflow/sentiment-analysis/cortex.yaml +++ b/examples/tensorflow/sentiment-analysis/cortex.yaml @@ -2,9 +2,9 @@ name: sentiment - kind: api - name: classifier + name: analyzer tensorflow: - model: s3://cortex-examples/tensorflow/sentiment-analysis/bert + model: s3://cortex-examples/tensorflow/sentiment-analyzer/bert request_handler: handler.py tracker: model_type: classification diff --git a/examples/tensorflow/sentiment-analysis/sample.json b/examples/tensorflow/sentiment-analysis/sample.json index 6312e4643b..45f2bacadb 100644 --- a/examples/tensorflow/sentiment-analysis/sample.json +++ b/examples/tensorflow/sentiment-analysis/sample.json @@ -1,3 +1,3 @@ { - "review": "The movie was great!" + "review": "The movie was amazing!" } diff --git a/examples/tensorflow/text-generator/README.md b/examples/tensorflow/text-generator/README.md deleted file mode 100644 index 1d9c96653f..0000000000 --- a/examples/tensorflow/text-generator/README.md +++ /dev/null @@ -1,86 +0,0 @@ -# Self-host OpenAI's GPT-2 as a service - -This example shows how to deploy OpenAI's GPT-2 model as a service on AWS. - -## Define a deployment - -A `deployment` specifies a set of resources that are deployed together. An `api` makes our exported model available as a web service that can serve real-time predictions. This configuration will download the 124M GPT-2 model from the `cortex-examples` S3 bucket, preprocess the payload and postprocess the inference with functions defined in `handler.py`, and deploy each replica of the API on 1 GPU: - -```yaml -# cortex.yaml - -- kind: deployment - name: text - -- kind: api - name: generator - tensorflow: - model: s3://cortex-examples/text-generator/gpt-2/124M - request_handler: handler.py - compute: - cpu: 1 - gpu: 1 -``` - - -You can run the code that generated the exported GPT-2 model [here](https://colab.research.google.com/github/cortexlabs/cortex/blob/master/examples/tensorflow/text-generator/gpt-2.ipynb). - -## Add request handling - -The model requires encoded data for inference, but the API should accept strings of natural language as input. It should also decode the inference output as human-readable text. - -```python -# handler.py - -from encoder import get_encoder -encoder = get_encoder() - -def pre_inference(sample, signature, metadata): - context = encoder.encode(sample["text"]) - return {"context": [context]} - -def post_inference(prediction, signature, metadata): - response = prediction["sample"] - return encoder.decode(response) -``` - -## Deploy to AWS - -`cortex deploy` takes the declarative configuration from `cortex.yaml` and creates it on the cluster. - -```bash -$ cortex deploy - -creating generator -``` - -Behind the scenes, Cortex containerizes our implementation, makes it servable using Flask, exposes the endpoint with a load balancer, and orchestrates the workload on Kubernetes. - -We can track the status of a deployment using `cortex get`: - -```bash -$ cortex get generator --watch - -status up-to-date available requested last update avg latency -live 1 1 1 8s - -``` - -The output above indicates that one replica of the API was requested and is available to serve predictions. Cortex will automatically launch more replicas if the load increases and spin down replicas if there is unused capacity. - -## Serve real-time predictions - -```bash -$ cortex get generator - -We can use `curl` to test our prediction service: - -endpoint: http://***.amazonaws.com/text/generator - -$ curl http://***.amazonaws.com/text/generator \ - -X POST -H "Content-Type: application/json" \ - -d '{"text": "machine learning"}' - -Machine learning, with more than one thousand researchers around the world today, are looking to create computer-driven machine learning algorithms that can also be applied to human and social problems, such as education, health care, employment, medicine, politics, or the environment... -``` - -Any questions? [chat with us](https://gitter.im/cortexlabs/cortex). diff --git a/examples/xgboost/iris-classifier/README.md b/examples/xgboost/iris-classifier/README.md deleted file mode 100644 index e276414604..0000000000 --- a/examples/xgboost/iris-classifier/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# Deploy an iris classifier - -This example shows how to deploy a classifier trained on the famous [iris data set](https://archive.ics.uci.edu/ml/datasets/iris). - -## Define a deployment - -A `deployment` specifies a set of resources that are deployed together. An `api` makes our exported model available as a web service that can serve real-time predictions. This configuration will deploy our model from the `cortex-examples` S3 bucket: - -```yaml -# cortex.yaml - -- kind: deployment - name: iris - -- kind: api - name: xgboost - onnx: - model: s3://cortex-examples/xgboost/iris-classifier/gbtree.onnx - request_handler: handler.py - tracker: - model_type: classification -``` - - -You can run the code that generated the exported model used in this example [here](https://colab.research.google.com/github/cortexlabs/cortex/blob/master/examples/xgboost/iris-classifier/xgboost.ipynb). - -## Add request handling - -The API should convert the model’s prediction to a human readable label before responding. This can be implemented in a request handler file: - -```python -# handler.py - -labels = ["iris-setosa", "iris-versicolor", "iris-virginica"] - -def post_inference(prediction, metadata): - label_index = int(prediction["class_ids"][0]) - return labels[label_index] -``` - -## Deploy to AWS - -`cortex deploy` takes the declarative configuration from `cortex.yaml` and creates it on the cluster: - -```bash -$ cortex deploy - -creating classifier -``` - -Behind the scenes, Cortex containerizes our implementation, makes it servable using Flask, exposes the endpoint with a load balancer, and orchestrates the workload on Kubernetes. - -We can track the status of a deployment using `cortex get`: - -```bash -$ cortex get classifier --watch - -status up-to-date available requested last update avg latency -live 1 1 1 8s - -``` - -The output above indicates that one replica of the API was requested and is available to serve predictions. Cortex will automatically launch more replicas if the load increases and spin down replicas if there is unused capacity. - -## Serve real-time predictions - -We can use `curl` to test our prediction service: - -```bash -$ cortex get classifier - -endpoint: http://***.amazonaws.com/iris/classifier - -$ curl http://***.amazonaws.com/iris/classifier \ - -X POST -H "Content-Type: application/json" \ - -d '{"sepal_length": 5.2, "sepal_width": 3.6, "petal_length": 1.4, "petal_width": 0.3}' - -"iris-setosa" -``` - -Any questions? [chat with us](https://gitter.im/cortexlabs/cortex). From 5467ca63e7fe8a0dbfc5de0086d2dfbbc88d8bc3 Mon Sep 17 00:00:00 2001 From: David Eliahu Date: Tue, 26 Nov 2019 12:41:40 -0800 Subject: [PATCH 2/3] Update no cluster error --- cli/cmd/cluster.go | 4 ++++ manager/info.sh | 3 ++- manager/install.sh | 3 ++- manager/refresh.sh | 3 ++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/cli/cmd/cluster.go b/cli/cmd/cluster.go index e0c1832e92..9d33c91dc0 100644 --- a/cli/cmd/cluster.go +++ b/cli/cmd/cluster.go @@ -145,6 +145,8 @@ var infoCmd = &cobra.Command{ if err != nil { errors.Exit(err) } + + // note: if modifying this string, search the codebase for it and change all occurrences if strings.Contains(out, "there is no cluster") { errors.Exit() } @@ -274,6 +276,8 @@ func refreshCachedClusterConfig(awsCreds *AWSCredentials) *clusterconfig.Cluster if err != nil { errors.Exit(err) } + + // note: if modifying this string, search the codebase for it and change all occurrences if strings.Contains(out, "there is no cluster") { errors.Exit() } diff --git a/manager/info.sh b/manager/info.sh index cb5f140e4d..2bf61f8ab6 100755 --- a/manager/info.sh +++ b/manager/info.sh @@ -27,7 +27,8 @@ function get_apis_endpoint() { } if ! eksctl utils describe-stacks --cluster=$CORTEX_CLUSTER_NAME --region=$CORTEX_REGION >/dev/null 2>&1; then - echo "error: there isn't a cortex cluster named \"$CORTEX_CLUSTER_NAME\" in $CORTEX_REGION; please update your configuration to point to an existing cortex cluster or create a cortex cluster with \`cortex cluster up\`" + # note: if modifying this string, search the codebase for it and change all occurrences + echo "error: there is no cluster named \"$CORTEX_CLUSTER_NAME\" in $CORTEX_REGION; please update your configuration to point to an existing cortex cluster or create a cortex cluster with \`cortex cluster up\`" exit 1 fi diff --git a/manager/install.sh b/manager/install.sh index b914b6eaa8..43b6094c44 100755 --- a/manager/install.sh +++ b/manager/install.sh @@ -28,7 +28,8 @@ function ensure_eks() { # No cluster if [ $cluster_info_exit_code -ne 0 ]; then if [ "$arg1" = "--update" ]; then - echo "error: there isn't a cortex cluster named \"$CORTEX_CLUSTER_NAME\" in $CORTEX_REGION; please update your configuration to point to an existing cortex cluster or create a cortex cluster with \`cortex cluster up\`" + # note: if modifying this string, search the codebase for it and change all occurrences + echo "error: there is no cluster named \"$CORTEX_CLUSTER_NAME\" in $CORTEX_REGION; please update your configuration to point to an existing cortex cluster or create a cortex cluster with \`cortex cluster up\`" exit 1 fi diff --git a/manager/refresh.sh b/manager/refresh.sh index c0a690ccff..c8e73462ee 100755 --- a/manager/refresh.sh +++ b/manager/refresh.sh @@ -18,7 +18,8 @@ set -e if ! eksctl utils describe-stacks --cluster=$CORTEX_CLUSTER_NAME --region=$CORTEX_REGION >/dev/null 2>&1; then - echo "error: there isn't a cortex cluster named \"$CORTEX_CLUSTER_NAME\" in $CORTEX_REGION; please update your configuration to point to an existing cortex cluster or create a cortex cluster with \`cortex cluster up\`" + # note: if modifying this string, search the codebase for it and change all occurrences + echo "error: there is no cluster named \"$CORTEX_CLUSTER_NAME\" in $CORTEX_REGION; please update your configuration to point to an existing cortex cluster or create a cortex cluster with \`cortex cluster up\`" exit 1 fi From 6cd39db262a82b467fbc6210c88e6348ef3bec2f Mon Sep 17 00:00:00 2001 From: vishal Date: Tue, 26 Nov 2019 15:55:12 -0500 Subject: [PATCH 3/3] Cleanup round #2 --- README.md | 4 +- cli/cmd/cluster.go | 5 -- cli/cmd/configure.go | 1 - cli/cmd/delete.go | 1 - cli/cmd/deploy.go | 3 +- cli/cmd/get.go | 1 - cli/cmd/logs.go | 1 - cli/cmd/predict.go | 1 - cli/cmd/root.go | 16 +----- cli/cmd/support.go | 1 - cli/cmd/version.go | 1 - docs/cluster/cli.md | 56 +++++++++---------- docs/cluster/install.md | 22 ++++---- docs/cluster/uninstall.md | 16 +++--- docs/cluster/update.md | 10 ++-- docs/packaging/tensorflow.md | 2 +- examples/README.md | 6 +- examples/pytorch/answer-generator/cortex.yaml | 1 + examples/pytorch/image-classifier/cortex.yaml | 1 + .../pytorch/language-identifier/cortex.yaml | 1 + .../pytorch/reading-comprehender/cortex.yaml | 1 + examples/pytorch/text-generator/cortex.yaml | 2 +- examples/sklearn/mpg-estimator/trainer.py | 8 +-- .../tensorflow/sentiment-analysis/sample.json | 3 - .../bert.ipynb | 4 +- .../cortex.yaml | 0 .../handler.py | 0 .../requirements.txt | 0 .../tensorflow/sentiment-analyzer/sample.json | 3 + 29 files changed, 76 insertions(+), 95 deletions(-) delete mode 100644 examples/tensorflow/sentiment-analysis/sample.json rename examples/tensorflow/{sentiment-analysis => sentiment-analyzer}/bert.ipynb (99%) rename examples/tensorflow/{sentiment-analysis => sentiment-analyzer}/cortex.yaml (100%) rename examples/tensorflow/{sentiment-analysis => sentiment-analyzer}/handler.py (100%) rename examples/tensorflow/{sentiment-analysis => sentiment-analyzer}/requirements.txt (100%) create mode 100644 examples/tensorflow/sentiment-analyzer/sample.json diff --git a/README.md b/README.md index c2ebb2810a..90cb13018a 100644 --- a/README.md +++ b/README.md @@ -106,8 +106,8 @@ The CLI sends configuration and code to the cluster every time you run `cortex d ## Examples - -- [Sentiment analysis](https://github.com/cortexlabs/cortex/tree/0.10/examples/tensorflow/sentiment-analysis) in TensorFlow with BERT + +- [Sentiment analysis](https://github.com/cortexlabs/cortex/tree/0.10/examples/tensorflow/sentiment-analyzer) in TensorFlow with BERT - [Image classification](https://github.com/cortexlabs/cortex/tree/0.10/examples/tensorflow/image-classifier) in TensorFlow with Inception - [Text generation](https://github.com/cortexlabs/cortex/tree/0.10/examples/pytorch/text-generator) in PyTorch with DistilGPT2 - [Reading comprehension](https://github.com/cortexlabs/cortex/tree/0.10/examples/pytorch/text-generator) in PyTorch with ELMo-BiDAF diff --git a/cli/cmd/cluster.go b/cli/cmd/cluster.go index e0c1832e92..64715603d2 100644 --- a/cli/cmd/cluster.go +++ b/cli/cmd/cluster.go @@ -64,13 +64,11 @@ func addClusterConfigFlag(cmd *cobra.Command) { var clusterCmd = &cobra.Command{ Use: "cluster", Short: "manage a cluster", - Long: "manage a cluster", } var upCmd = &cobra.Command{ Use: "up", Short: "spin up a cluster", - Long: `spin up a cluster`, Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { if err := checkDockerRunning(); err != nil { @@ -98,7 +96,6 @@ var upCmd = &cobra.Command{ var updateCmd = &cobra.Command{ Use: "update", Short: "update a cluster", - Long: `update a cluster`, Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { if err := checkDockerRunning(); err != nil { @@ -127,7 +124,6 @@ var updateCmd = &cobra.Command{ var infoCmd = &cobra.Command{ Use: "info", Short: "get information about a cluster", - Long: "get information about a cluster", Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { if err := checkDockerRunning(); err != nil { @@ -177,7 +173,6 @@ var infoCmd = &cobra.Command{ var downCmd = &cobra.Command{ Use: "down", Short: "spin down a cluster", - Long: `spin down a cluster.`, Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { if err := checkDockerRunning(); err != nil { diff --git a/cli/cmd/configure.go b/cli/cmd/configure.go index d43d101041..570840ec3b 100644 --- a/cli/cmd/configure.go +++ b/cli/cmd/configure.go @@ -34,7 +34,6 @@ func init() { var configureCmd = &cobra.Command{ Use: "configure", Short: "configure the cli", - Long: "configure the cli", Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { if flagPrint { diff --git a/cli/cmd/delete.go b/cli/cmd/delete.go index cd60287866..98dcd9579d 100644 --- a/cli/cmd/delete.go +++ b/cli/cmd/delete.go @@ -38,7 +38,6 @@ func init() { var deleteCmd = &cobra.Command{ Use: "delete [DEPLOYMENT_NAME]", Short: "delete a deployment", - Long: "delete a deployment", Args: cobra.MaximumNArgs(1), Run: func(cmd *cobra.Command, args []string) { var appName string diff --git a/cli/cmd/deploy.go b/cli/cmd/deploy.go index c9c3e3c72a..30552583ae 100644 --- a/cli/cmd/deploy.go +++ b/cli/cmd/deploy.go @@ -38,14 +38,13 @@ var flagDeployRefresh bool func init() { deployCmd.PersistentFlags().BoolVarP(&flagDeployForce, "force", "f", false, "override the in-progress deployment update") - deployCmd.PersistentFlags().BoolVarP(&flagDeployRefresh, "refresh", "r", false, "re-deploy all APIs with cleared cache and rolling updates") + deployCmd.PersistentFlags().BoolVarP(&flagDeployRefresh, "refresh", "r", false, "re-deploy all apis with cleared cache and rolling updates") addEnvFlag(deployCmd) } var deployCmd = &cobra.Command{ Use: "deploy", Short: "create or update a deployment", - Long: "create or update a deployment", Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { deploy(flagDeployForce, flagDeployRefresh) diff --git a/cli/cmd/get.go b/cli/cmd/get.go index 5633a9c9c7..4140c9e814 100644 --- a/cli/cmd/get.go +++ b/cli/cmd/get.go @@ -58,7 +58,6 @@ func init() { var getCmd = &cobra.Command{ Use: "get [API_NAME]", Short: "get information about deployments", - Long: "get information about resources", Args: cobra.RangeArgs(0, 1), Run: func(cmd *cobra.Command, args []string) { rerun(func() (string, error) { diff --git a/cli/cmd/logs.go b/cli/cmd/logs.go index 61fc0c9c46..ecd6bb5c8d 100644 --- a/cli/cmd/logs.go +++ b/cli/cmd/logs.go @@ -32,7 +32,6 @@ func init() { var logsCmd = &cobra.Command{ Use: "logs API_NAME", Short: "stream logs from an api", - Long: "stream logs from an api", Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { resourceName := args[0] diff --git a/cli/cmd/predict.go b/cli/cmd/predict.go index 18a682585b..6a5e9bf962 100644 --- a/cli/cmd/predict.go +++ b/cli/cmd/predict.go @@ -41,7 +41,6 @@ func init() { var predictCmd = &cobra.Command{ Use: "predict API_NAME SAMPLE_FILE", Short: "make a prediction request using a json file", - Long: "make a prediction request using a json file", Args: cobra.ExactArgs(2), Run: func(cmd *cobra.Command, args []string) { apiName := args[0] diff --git a/cli/cmd/root.go b/cli/cmd/root.go index 0c21175e9c..77ffe002e4 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -31,7 +31,6 @@ import ( "github.com/cortexlabs/cortex/pkg/lib/slices" s "github.com/cortexlabs/cortex/pkg/lib/strings" libtime "github.com/cortexlabs/cortex/pkg/lib/time" - "github.com/cortexlabs/cortex/pkg/operator/api/resource" ) var cmdStr string @@ -70,7 +69,6 @@ var rootCmd = &cobra.Command{ Use: "cortex", Aliases: []string{"cx"}, Short: "deploy machine learning models in production", - Long: `deploy machine learning models in production`, } func Execute() { @@ -106,11 +104,11 @@ func updateRootUsage() { return defaultUsageFunc(cmd) } - usage = strings.Replace(usage, "usage:\n cortex [command]\n\naliases:\n cortex, cx\n\n", "", 1) - usage = strings.Replace(usage, "available commands:", "deployment commands:", 1) + usage = strings.Replace(usage, "Usage:\n cortex [command]\n\nAliases:\n cortex, cx\n\n", "", 1) + usage = strings.Replace(usage, "Available Commands:", "deployment commands:", 1) usage = strings.Replace(usage, "\n cluster", "\n\ncluster commands:\n cluster", 1) usage = strings.Replace(usage, "\n configure", "\n\nother commands:\n configure", 1) - usage = strings.Replace(usage, "\nUse \"cortex", " help help about any command\n\nflags:\n -h, --help help for cortex\n\nUse \"cortex", 1) + usage = strings.Replace(usage, "\n\nUse \"cortex [command] --help\" for more information about a command.", "", 1) cmd.Print(usage) @@ -136,14 +134,6 @@ func addAppNameFlag(cmd *cobra.Command) { cmd.PersistentFlags().StringVarP(&flagAppName, "deployment", "d", "", "deployment name") } -var resourceTypesHelp = fmt.Sprintf("\nresource types:\n %s\n", strings.Join(resource.VisibleTypes.StringList(), "\n ")) - -func addResourceTypesToHelp(cmd *cobra.Command) { - usage := cmd.UsageTemplate() - usage = strings.Replace(usage, "\nflags:\n", resourceTypesHelp+"\nflags:\n", 1) - cmd.SetUsageTemplate(usage) -} - func getTerminalWidth() int { cmd := exec.Command("stty", "size") cmd.Stdin = os.Stdin diff --git a/cli/cmd/support.go b/cli/cmd/support.go index e434381b12..e7a713ceaf 100644 --- a/cli/cmd/support.go +++ b/cli/cmd/support.go @@ -67,7 +67,6 @@ var supportPrompValidation = &cr.PromptValidation{ var supportCmd = &cobra.Command{ Use: "support", Short: "send a support request to the maintainers", - Long: "send a support request to the maintainers", Run: func(cmd *cobra.Command, args []string) { supportRequest := &SupportRequest{} err := cr.ReadPrompt(supportRequest, supportPrompValidation) diff --git a/cli/cmd/version.go b/cli/cmd/version.go index 89e2a8d30a..1ae69301d8 100644 --- a/cli/cmd/version.go +++ b/cli/cmd/version.go @@ -34,7 +34,6 @@ func init() { var versionCmd = &cobra.Command{ Use: "version", Short: "print the cli and cluster versions", - Long: `print the cli and cluster versions`, Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { if !isCLIConfigured() { diff --git a/docs/cluster/cli.md b/docs/cluster/cli.md index 9e829e00d6..da2e7100e6 100644 --- a/docs/cluster/cli.md +++ b/docs/cluster/cli.md @@ -5,10 +5,10 @@ ```text create or update a deployment -usage: +Usage: cortex deploy [flags] -flags: +Flags: -e, --env string environment (default "default") -f, --force override the in-progress deployment update -h, --help help for deploy @@ -18,12 +18,12 @@ flags: ## get ```text -get information about resources +get information about deployments -usage: - cortex get [RESOURCE_NAME] [flags] +Usage: + cortex get [API_NAME] [flags] -flags: +Flags: -a, --all-deployments list all deployments -d, --deployment string deployment name -e, --env string environment (default "default") @@ -38,10 +38,10 @@ flags: ```text stream logs from an api -usage: +Usage: cortex logs API_NAME [flags] -flags: +Flags: -d, --deployment string deployment name -e, --env string environment (default "default") -h, --help help for logs @@ -52,10 +52,10 @@ flags: ```text make a prediction request using a json file -usage: +Usage: cortex predict API_NAME SAMPLE_FILE [flags] -flags: +Flags: --debug Predict with debug mode -d, --deployment string deployment name -e, --env string environment (default "default") @@ -67,10 +67,10 @@ flags: ```text delete a deployment -usage: +Usage: cortex delete [DEPLOYMENT_NAME] [flags] -flags: +Flags: -e, --env string environment (default "default") -h, --help help for delete -c, --keep-cache keep cached data for the deployment @@ -81,10 +81,10 @@ flags: ```text spin up a cluster -usage: +Usage: cortex cluster up [flags] -flags: +Flags: -c, --config string path to a cortex cluster configuration file -h, --help help for up ``` @@ -94,10 +94,10 @@ flags: ```text get information about a cluster -usage: +Usage: cortex cluster info [flags] -flags: +Flags: -c, --config string path to a cortex cluster configuration file -h, --help help for info ``` @@ -107,10 +107,10 @@ flags: ```text update a cluster -usage: +Usage: cortex cluster update [flags] -flags: +Flags: -c, --config string path to a cortex cluster configuration file -h, --help help for update ``` @@ -120,10 +120,10 @@ flags: ```text spin down a cluster -usage: +Usage: cortex cluster down [flags] -flags: +Flags: -c, --config string path to a cortex cluster configuration file -h, --help help for down ``` @@ -133,10 +133,10 @@ flags: ```text print the cli and cluster versions -usage: +Usage: cortex version [flags] -flags: +Flags: -e, --env string environment (default "default") -h, --help help for version ``` @@ -146,10 +146,10 @@ flags: ```text configure the cli -usage: +Usage: cortex configure [flags] -flags: +Flags: -e, --env string environment (default "default") -h, --help help for configure -p, --print print the configuration @@ -160,10 +160,10 @@ flags: ```text send a support request to the maintainers -usage: +Usage: cortex support [flags] -flags: +Flags: -h, --help help for support ``` @@ -180,9 +180,9 @@ or run: this will also add the "cx" alias (note: cli completion requires the bash_completion package to be installed on your system) -usage: +Usage: cortex completion [flags] -flags: +Flags: -h, --help help for completion ``` diff --git a/docs/cluster/install.md b/docs/cluster/install.md index 86ba6be430..199a00d068 100644 --- a/docs/cluster/install.md +++ b/docs/cluster/install.md @@ -12,10 +12,10 @@ See [cluster configuration](config.md) to learn how you can customize your clust ```bash # Install the Cortex CLI on your machine -$ bash -c "$(curl -sS https://raw.githubusercontent.com/cortexlabs/cortex/master/get-cli.sh)" +bash -c "$(curl -sS https://raw.githubusercontent.com/cortexlabs/cortex/master/get-cli.sh)" # Provision infrastructure on AWS and install Cortex -$ cortex cluster up +cortex cluster up ``` Note: This will create resources in your AWS account which aren't included in the free tier, e.g. an EKS cluster, two Elastic Load Balancers, and EC2 instances (quantity and type as specified above). To use GPU nodes, you may need to subscribe to the [EKS-optimized AMI with GPU Support](https://aws.amazon.com/marketplace/pp/B07GRHFXGM) and [file an AWS support ticket](https://console.aws.amazon.com/support/cases#/create?issueType=service-limit-increase&limitType=ec2-instances) to increase the limit for your desired instance type. @@ -26,31 +26,31 @@ Note: This will create resources in your AWS account which aren't included in th ```bash # Clone the Cortex repository -$ git clone -b master https://github.com/cortexlabs/cortex.git +git clone -b master https://github.com/cortexlabs/cortex.git # Navigate to the iris classifier example -$ cd cortex/examples/sklearn/iris-classifier +cd cortex/examples/sklearn/iris-classifier # Deploy the model to the cluster -$ cortex deploy +cortex deploy # View the status of the deployment -$ cortex get --watch +cortex get --watch # Get the API's endpoint -$ cortex get classifier +cortex get classifier # Classify a sample -$ curl -X POST -H "Content-Type: application/json" \ - -d '{ "sepal_length": 5.2, "sepal_width": 3.6, "petal_length": 1.4, "petal_width": 0.3 }' \ - +curl -X POST -H "Content-Type: application/json" \ + -d '{ "sepal_length": 5.2, "sepal_width": 3.6, "petal_length": 1.4 "petal_width": 0.3 }' \ + ``` ## Cleanup ```bash # Delete the deployment -$ cortex delete iris +cortex delete iris ``` See [uninstall](uninstall.md) if you'd like to uninstall Cortex. diff --git a/docs/cluster/uninstall.md b/docs/cluster/uninstall.md index 865caa758d..d8abe08290 100644 --- a/docs/cluster/uninstall.md +++ b/docs/cluster/uninstall.md @@ -11,11 +11,11 @@ ```bash # Spin down the cluster -$ cortex cluster down +cortex cluster down # Uninstall the CLI -$ sudo rm /usr/local/bin/cortex -$ rm -rf ~/.cortex +sudo rm /usr/local/bin/cortex +rm -rf ~/.cortex ``` If you modified your bash profile, you may wish to remove `source <(cortex completion)`. @@ -24,13 +24,13 @@ If you modified your bash profile, you may wish to remove `source <(cortex compl ```bash # Set AWS credentials -$ export AWS_ACCESS_KEY_ID=*** -$ export AWS_SECRET_ACCESS_KEY=*** +export AWS_ACCESS_KEY_ID=*** +export AWS_SECRET_ACCESS_KEY=*** # Delete the S3 bucket -$ aws s3 ls -$ aws s3 rb --force s3:// +aws s3 ls +aws s3 rb --force s3:// # Delete the log group -$ aws logs describe-log-groups --log-group-name-prefix= --query logGroups[*].[logGroupName] --output text | xargs -I {} aws logs delete-log-group --log-group-name {} +aws logs describe-log-groups --log-group-name-prefix= --query logGroups[*].[logGroupName] --output text | xargs -I {} aws logs delete-log-group --log-group-name {} ``` diff --git a/docs/cluster/update.md b/docs/cluster/update.md index 34aa68ba3b..f01147d8af 100644 --- a/docs/cluster/update.md +++ b/docs/cluster/update.md @@ -10,7 +10,7 @@ See [cluster configuration](config.md) to learn how you can customize your cluster. ```bash -$ cortex cluster update +cortex cluster update ``` ## Upgrading to a newer version of Cortex @@ -19,14 +19,14 @@ $ cortex cluster update ```bash # Spin down your cluster -$ cortex cluster down +cortex cluster down # Update your CLI -$ bash -c "$(curl -sS https://raw.githubusercontent.com/cortexlabs/cortex/master/get-cli.sh)" +bash -c "$(curl -sS https://raw.githubusercontent.com/cortexlabs/cortex/master/get-cli.sh)" # Confirm version -$ cortex version +cortex version # Spin up your cluster -$ cortex cluster up +cortex cluster up ``` diff --git a/docs/packaging/tensorflow.md b/docs/packaging/tensorflow.md index 54ce920f13..93fe0b8e35 100644 --- a/docs/packaging/tensorflow.md +++ b/docs/packaging/tensorflow.md @@ -1,7 +1,7 @@ # Packaging TensorFlow models -Export your trained model and upload the export directory, or a checkpoint directory containing the export directory (which is usually the case if you used `estimator.train_and_evaluate`). An example is shown below (here is the [complete example](https://github.com/cortexlabs/cortex/blob/master/examples/tensorflow/sentiment-analysis)): +Export your trained model and upload the export directory, or a checkpoint directory containing the export directory (which is usually the case if you used `estimator.train_and_evaluate`). An example is shown below (here is the [complete example](https://github.com/cortexlabs/cortex/blob/master/examples/tensorflow/sentiment-analyzer)): ```Python import tensorflow as tf diff --git a/examples/README.md b/examples/README.md index 156ca5cc2b..5eb1d127a9 100644 --- a/examples/README.md +++ b/examples/README.md @@ -8,7 +8,7 @@ - [Image classification with Inception V3](tensorflow/image-classifier): deploy an Inception V3 model to classify images. -- [Sentiment analysis with BERT](tensorflow/sentiment-analysis): deploy a BERT model to classify sentiment. +- [Sentiment analysis with BERT](tensorflow/sentiment-analyzer): deploy a BERT model for sentiment analysis. ## PyTorch @@ -32,6 +32,6 @@ ## scikit-learn -- [Iris classification](sklearn/mpg-estimation): deploy a model to classify iris flowers. +- [Iris classification](sklearn/iris-classifier): deploy a model to classify iris flowers. -- [MPG estimation](sklearn/mpg-estimation): deploy a linear regression model to estimate MPG. +- [MPG estimation](sklearn/mpg-estimator): deploy a linear regression model to estimate MPG. diff --git a/examples/pytorch/answer-generator/cortex.yaml b/examples/pytorch/answer-generator/cortex.yaml index 75a87ff42f..85c673b897 100644 --- a/examples/pytorch/answer-generator/cortex.yaml +++ b/examples/pytorch/answer-generator/cortex.yaml @@ -8,5 +8,6 @@ metadata: device: cuda # use "cpu" to run on CPUs compute: + cpu: 1 gpu: 1 mem: 4G diff --git a/examples/pytorch/image-classifier/cortex.yaml b/examples/pytorch/image-classifier/cortex.yaml index a399c3ff7e..2a649e7403 100644 --- a/examples/pytorch/image-classifier/cortex.yaml +++ b/examples/pytorch/image-classifier/cortex.yaml @@ -6,5 +6,6 @@ predictor: path: predictor.py compute: + cpu: 1 gpu: 1 mem: 4G diff --git a/examples/pytorch/language-identifier/cortex.yaml b/examples/pytorch/language-identifier/cortex.yaml index 42557bee15..9f5609ae56 100644 --- a/examples/pytorch/language-identifier/cortex.yaml +++ b/examples/pytorch/language-identifier/cortex.yaml @@ -8,5 +8,6 @@ tracker: model_type: classification compute: + cpu: 1 gpu: 1 mem: 4G diff --git a/examples/pytorch/reading-comprehender/cortex.yaml b/examples/pytorch/reading-comprehender/cortex.yaml index 3546c94871..0477bbd898 100644 --- a/examples/pytorch/reading-comprehender/cortex.yaml +++ b/examples/pytorch/reading-comprehender/cortex.yaml @@ -6,5 +6,6 @@ predictor: path: predictor.py compute: + cpu: 1 gpu: 1 mem: 4G diff --git a/examples/pytorch/text-generator/cortex.yaml b/examples/pytorch/text-generator/cortex.yaml index 7867b28029..6bfa106b37 100644 --- a/examples/pytorch/text-generator/cortex.yaml +++ b/examples/pytorch/text-generator/cortex.yaml @@ -9,5 +9,5 @@ num_words: 50 device: cuda # use "cpu" to run on CPUs compute: - gpu: 1 cpu: 1 + gpu: 1 diff --git a/examples/sklearn/mpg-estimator/trainer.py b/examples/sklearn/mpg-estimator/trainer.py index 2ac73865a7..7cec1e1925 100644 --- a/examples/sklearn/mpg-estimator/trainer.py +++ b/examples/sklearn/mpg-estimator/trainer.py @@ -1,14 +1,14 @@ import mlflow.sklearn -import pandas -import numpy +import pandas as pd +import numpy as np from sklearn.linear_model import LinearRegression from sklearn.model_selection import train_test_split -df = pandas.read_csv( +df = pd.read_csv( "https://www.uio.no/studier/emner/sv/oekonomi/ECON4150/v16/statacourse/datafiles/auto.csv" ) -df = df.replace("?", numpy.nan) +df = df.replace("?", np.nan) df = df.dropna() df = df.drop(["name", "origin", "year"], axis=1) # drop categorical variables for simplicity data = df.drop("mpg", axis=1) diff --git a/examples/tensorflow/sentiment-analysis/sample.json b/examples/tensorflow/sentiment-analysis/sample.json deleted file mode 100644 index 45f2bacadb..0000000000 --- a/examples/tensorflow/sentiment-analysis/sample.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "review": "The movie was amazing!" -} diff --git a/examples/tensorflow/sentiment-analysis/bert.ipynb b/examples/tensorflow/sentiment-analyzer/bert.ipynb similarity index 99% rename from examples/tensorflow/sentiment-analysis/bert.ipynb rename to examples/tensorflow/sentiment-analyzer/bert.ipynb index 41a0472a1b..b307e282b6 100644 --- a/examples/tensorflow/sentiment-analysis/bert.ipynb +++ b/examples/tensorflow/sentiment-analyzer/bert.ipynb @@ -933,7 +933,7 @@ "source": [ "AWS_ACCESS_KEY_ID = \"\" #@param {type:\"string\"}\n", "AWS_SECRET_ACCESS_KEY = \"\" #@param {type:\"string\"}\n", - "S3_UPLOAD_PATH = \"s3://my-bucket/sentiment-analysis/bert\" #@param {type:\"string\"}\n", + "S3_UPLOAD_PATH = \"s3://my-bucket/sentiment-analyzer/bert\" #@param {type:\"string\"}\n", "\n", "import sys\n", "import re\n", @@ -997,7 +997,7 @@ }, "source": [ "\n", - "That's it! See the [example on GitHub](https://github.com/cortexlabs/cortex/tree/master/examples/sentiment-analysis) for how to deploy the model as an API." + "That's it! See the [example on GitHub](https://github.com/cortexlabs/cortex/tree/master/examples/sentiment-analyzer) for how to deploy the model as an API." ] } ] diff --git a/examples/tensorflow/sentiment-analysis/cortex.yaml b/examples/tensorflow/sentiment-analyzer/cortex.yaml similarity index 100% rename from examples/tensorflow/sentiment-analysis/cortex.yaml rename to examples/tensorflow/sentiment-analyzer/cortex.yaml diff --git a/examples/tensorflow/sentiment-analysis/handler.py b/examples/tensorflow/sentiment-analyzer/handler.py similarity index 100% rename from examples/tensorflow/sentiment-analysis/handler.py rename to examples/tensorflow/sentiment-analyzer/handler.py diff --git a/examples/tensorflow/sentiment-analysis/requirements.txt b/examples/tensorflow/sentiment-analyzer/requirements.txt similarity index 100% rename from examples/tensorflow/sentiment-analysis/requirements.txt rename to examples/tensorflow/sentiment-analyzer/requirements.txt diff --git a/examples/tensorflow/sentiment-analyzer/sample.json b/examples/tensorflow/sentiment-analyzer/sample.json new file mode 100644 index 0000000000..c433e33216 --- /dev/null +++ b/examples/tensorflow/sentiment-analyzer/sample.json @@ -0,0 +1,3 @@ +{ + "review": "the movie was amazing!" +}