This is an automated email from the ASF dual-hosted git repository.
pingsutw pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/submarine.git
The following commit(s) were added to refs/heads/master by this push:
new 4ef6c66 SUBMARINE-1082. Create PyTorch serving
4ef6c66 is described below
commit 4ef6c66b8c388af2c83cc3536e4c9247f9825b9a
Author: KUAN-HSUN-LI <[email protected]>
AuthorDate: Sat Nov 27 12:33:58 2021 +0800
SUBMARINE-1082. Create PyTorch serving
### What is this PR for?
Provide PyTorch model serving using `triton inference server` in
`seldon-core`
### What type of PR is it?
[Feature]
### Todos
### What is the Jira issue?
https://issues.apache.org/jira/browse/SUBMARINE-1082
### How should this be tested?
I will provide testing cases in another PR.
### Screenshots (if appropriate)
https://user-images.githubusercontent.com/38066413/143668211-e2e06324-de40-4183-bbf8-a09c6b484d29.mp4
### Questions:
* Do the license files need updating? No
* Are there breaking changes for older versions? No
* Does this need new documentation? Yes
Author: KUAN-HSUN-LI <[email protected]>
Signed-off-by: Kevin <[email protected]>
Closes #811 from KUAN-HSUN-LI/SUBMARINE-1082 and squashes the following
commits:
68c8f20c [KUAN-HSUN-LI] SUBMARINE-1082. Create PyTorch serving
---
submarine-serve/installation/install.sh | 2 +-
.../serve/pytorch/SeldonPytorchServing.java | 45 ++++++++++++++++++++++
.../submarine/serve/utils/SeldonConstants.java | 5 +++
.../org/apache/submarine/server/api/Submitter.java | 4 +-
.../submarine/server/model/ModelManager.java | 37 +++++++++++-------
.../server/submitter/k8s/K8sSubmitter.java | 17 ++++----
website/docs/api/serve.md | 6 +--
7 files changed, 86 insertions(+), 30 deletions(-)
diff --git a/submarine-serve/installation/install.sh
b/submarine-serve/installation/install.sh
index 6eab364..75734a8 100755
--- a/submarine-serve/installation/install.sh
+++ b/submarine-serve/installation/install.sh
@@ -41,5 +41,5 @@ helm install seldon-core seldon-core-operator \
--namespace seldon-system \
--version 1.10.0 \
--set istio.enabled=true \
- --set executor.defaultEnvSecretRefName=seldon-core-init-container-secret
2> /dev/null
+ --set executor.defaultEnvSecretRefName=submarine-serve-secret 2> /dev/null
kubectl apply -f ${CURRENT_PATH}/seldon-gateway.yaml
diff --git
a/submarine-serve/src/main/java/org/apache/submarine/serve/pytorch/SeldonPytorchServing.java
b/submarine-serve/src/main/java/org/apache/submarine/serve/pytorch/SeldonPytorchServing.java
new file mode 100644
index 0000000..b7881d6
--- /dev/null
+++
b/submarine-serve/src/main/java/org/apache/submarine/serve/pytorch/SeldonPytorchServing.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.submarine.serve.pytorch;
+
+import io.kubernetes.client.models.V1ObjectMeta;
+import org.apache.submarine.serve.seldon.SeldonDeployment;
+import org.apache.submarine.serve.seldon.SeldonGraph;
+import org.apache.submarine.serve.seldon.SeldonPredictor;
+import org.apache.submarine.serve.utils.SeldonConstants;
+
+public class SeldonPytorchServing extends SeldonDeployment {
+ public SeldonPytorchServing(String name, String modelURI){
+ V1ObjectMeta v1ObjectMeta = new V1ObjectMeta();
+ v1ObjectMeta.setName(name);
+ v1ObjectMeta.setNamespace(SeldonConstants.DEFAULT_NAMESPACE);
+ setMetadata(v1ObjectMeta);
+
+ setSpec(new SeldonDeploymentSpec(SeldonConstants.KFSERVING_PROTOCOL));
+
+ SeldonGraph seldonGraph = new SeldonGraph();
+ seldonGraph.setName(name);
+ seldonGraph.setImplementation(SeldonConstants.TRITON_IMPLEMENTATION);
+ seldonGraph.setModelUri(modelURI);
+ SeldonPredictor seldonPredictor = new SeldonPredictor();
+ seldonPredictor.setSeldonGraph(seldonGraph);
+
+ addPredictor(seldonPredictor);
+ }
+}
diff --git
a/submarine-serve/src/main/java/org/apache/submarine/serve/utils/SeldonConstants.java
b/submarine-serve/src/main/java/org/apache/submarine/serve/utils/SeldonConstants.java
index bcaf0a6..e41a564 100644
---
a/submarine-serve/src/main/java/org/apache/submarine/serve/utils/SeldonConstants.java
+++
b/submarine-serve/src/main/java/org/apache/submarine/serve/utils/SeldonConstants.java
@@ -37,6 +37,11 @@ public class SeldonConstants {
public static final String SELDON_PROTOCOL = "seldon";
+ public static final String KFSERVING_PROTOCOL = "kfserving";
+
// TensorFlow
public static final String TFSERVING_IMPLEMENTATION = "TENSORFLOW_SERVER";
+
+ // PyTorch
+ public static final String TRITON_IMPLEMENTATION = "TRITON_SERVER";
}
diff --git
a/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/Submitter.java
b/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/Submitter.java
index 96e0f2b..b1066a5 100644
---
a/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/Submitter.java
+++
b/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/Submitter.java
@@ -25,7 +25,6 @@ import org.apache.submarine.server.api.experiment.Experiment;
import org.apache.submarine.server.api.experiment.ExperimentLog;
import org.apache.submarine.server.api.experiment.TensorboardInfo;
import org.apache.submarine.server.api.experiment.MlflowInfo;
-import org.apache.submarine.server.api.model.ServeResponse;
import org.apache.submarine.server.api.model.ServeSpec;
import org.apache.submarine.server.api.notebook.Notebook;
import org.apache.submarine.server.api.spec.ExperimentSpec;
@@ -127,10 +126,9 @@ public interface Submitter {
/**
* Create Serve with spec
* @param spec
- * @return object
* @throws SubmarineRuntimeException running error
*/
- ServeResponse createServe(ServeSpec spec) throws SubmarineRuntimeException;
+ void createServe(ServeSpec spec) throws SubmarineRuntimeException;
/**
diff --git
a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/ModelManager.java
b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/ModelManager.java
index 49ceb6e..3a6aa65 100644
---
a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/ModelManager.java
+++
b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/ModelManager.java
@@ -19,7 +19,6 @@
package org.apache.submarine.server.model;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.core.Response;
@@ -29,6 +28,7 @@ import org.apache.submarine.server.SubmitterManager;
import org.apache.submarine.server.api.Submitter;
import org.apache.submarine.server.api.model.ServeResponse;
import org.apache.submarine.server.api.model.ServeSpec;
+import org.apache.submarine.server.model.database.entities.ModelVersionEntity;
import org.apache.submarine.server.model.database.service.ModelVersionService;
@@ -67,11 +67,14 @@ public class ModelManager {
* Create a model serve.
*/
public ServeResponse createServe(ServeSpec spec) throws
SubmarineRuntimeException {
- checkServeSpec(spec);
- String modelURI = modelVersionService.select(spec.getModelName(),
spec.getModelVersion()).getSource();
- spec.setModelURI(modelURI);
+ setServeInfo(spec);
+
+
+ LOG.info("Create " + spec.getModelType() + " model serve");
- ServeResponse serveResponse = submitter.createServe(spec);
+ submitter.createServe(spec);
+
+ ServeResponse serveResponse = getServeResponse(spec);
return serveResponse;
}
@@ -79,9 +82,9 @@ public class ModelManager {
* Delete a model serve.
*/
public void deleteServe(ServeSpec spec) throws SubmarineRuntimeException {
- checkServeSpec(spec);
- String modelURI = modelVersionService.select(spec.getModelName(),
spec.getModelVersion()).getSource();
- spec.setModelURI(modelURI);
+ setServeInfo(spec);
+
+ LOG.info("Delete " + spec.getModelType() + " model serve");
submitter.deleteServe(spec);
}
@@ -100,11 +103,19 @@ public class ModelManager {
throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
"Invalid. Model version must be positive, but get " +
modelVersion);
}
- String modelType = spec.getModelType();
- if (!modelType.equals("tensorflow") && !modelType.equals("pytorch")) {
- throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
- "Invalid. Serve Type can only be tensorflow or pytorch, but
get " + modelType);
- }
}
}
+
+ private void setServeInfo(ServeSpec spec){
+ checkServeSpec(spec);
+
+ // Get model type and model uri from DB and set the value in the spec.
+ ModelVersionEntity modelVersion =
modelVersionService.select(spec.getModelName(), spec.getModelVersion());
+ spec.setModelURI(modelVersion.getSource());
+ spec.setModelType(modelVersion.getModelType());
+ }
+
+ private ServeResponse getServeResponse(ServeSpec spec){
+ return new ServeResponse();
+ }
}
diff --git
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java
index f99d69f..c1e8298 100644
---
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java
+++
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java
@@ -23,12 +23,13 @@ import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
@@ -50,21 +51,21 @@ import io.kubernetes.client.models.V1PersistentVolumeClaim;
import io.kubernetes.client.models.V1Pod;
import io.kubernetes.client.models.V1PodList;
import io.kubernetes.client.models.V1Status;
-import io.kubernetes.client.util.Watch;
import io.kubernetes.client.util.ClientBuilder;
import io.kubernetes.client.util.KubeConfig;
+import io.kubernetes.client.util.Watch;
import org.apache.submarine.commons.utils.SubmarineConfiguration;
import org.apache.submarine.commons.utils.exception.SubmarineRuntimeException;
+import org.apache.submarine.serve.pytorch.SeldonPytorchServing;
import org.apache.submarine.serve.seldon.SeldonDeployment;
import org.apache.submarine.serve.tensorflow.SeldonTFServing;
import org.apache.submarine.server.api.Submitter;
import org.apache.submarine.server.api.exception.InvalidSpecException;
import org.apache.submarine.server.api.experiment.Experiment;
import org.apache.submarine.server.api.experiment.ExperimentLog;
-import org.apache.submarine.server.api.experiment.TensorboardInfo;
import org.apache.submarine.server.api.experiment.MlflowInfo;
-import org.apache.submarine.server.api.model.ServeResponse;
+import org.apache.submarine.server.api.experiment.TensorboardInfo;
import org.apache.submarine.server.api.model.ServeSpec;
import org.apache.submarine.server.api.notebook.Notebook;
import org.apache.submarine.server.api.spec.ExperimentMeta;
@@ -518,7 +519,7 @@ public class K8sSubmitter implements Submitter {
}
@Override
- public ServeResponse createServe(ServeSpec spec)
+ public void createServe(ServeSpec spec)
throws SubmarineRuntimeException {
SeldonDeployment seldonDeployment = parseServeSpec(spec);
@@ -533,7 +534,6 @@ public class K8sSubmitter implements Submitter {
LOG.error(e.getMessage(), e);
throw new SubmarineRuntimeException(e.getCode(), e.getMessage());
}
- return new ServeResponse();
}
@Override
@@ -763,8 +763,7 @@ public class K8sSubmitter implements Submitter {
if (modelType.equals("tensorflow")){
seldonDeployment = new SeldonTFServing(modelName, modelURI);
} else if (modelType.equals("pytorch")){
- // TODO(KUAN-HSUN LI): create pytorch serve
- throw new SubmarineRuntimeException("Given serve type: " + modelType + "
is not supported.");
+ seldonDeployment = new SeldonPytorchServing(modelName, modelURI);
} else {
throw new SubmarineRuntimeException("Given serve type: " + modelType + "
is not supported.");
}
diff --git a/website/docs/api/serve.md b/website/docs/api/serve.md
index b4b179f..f1c3f47 100644
--- a/website/docs/api/serve.md
+++ b/website/docs/api/serve.md
@@ -23,7 +23,7 @@ under the License.
> Note: The Serv API is in the alpha stage which is subjected to incompatible
> changes in future releases.
-## Create a TensorFlow model serve
+## Create a model serve
`POST /api/v1/serve`
**Example Request**
@@ -34,7 +34,6 @@ curl -X POST -H "Content-Type: application/json" -d '
{
"modelName": "simple",
"modelVersion":1,
- "modelType":"tensorflow"
}
' http://127.0.0.1:32080/api/v1/serve
```
@@ -59,8 +58,7 @@ curl -X POST -H "Content-Type: application/json" -d '
curl -X DELETE -H "Content-Type: application/json" -d '
{
"modelName": "simple",
- "modelVersion":1,
- "modelType":"tensorflow"
+ "modelVersion":1,
}
' http://127.0.0.1:32080/api/v1/serve
```
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]