This commit is contained in:
sefgsefg 2025-04-15 00:34:40 +00:00 committed by GitHub
commit 2ccd411e5e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
145 changed files with 53169 additions and 37430 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,68 +1,68 @@
# Chinese-multiperson-voice-recognition-using-transfer-learning
This is an example of applying transfer learning to the Chinese multi-person voice recognition application. Transfer learning is an AI technique used to enhance the training accuracy of use cases when the dataset is small or the training accuracy is low given the high noise of the original dataset. Multi-person voice recognition is known to contain high noise in the dataset. Chinese voice voice recognition has gained much progress recently thanks to the effort by the big name company such as Google. However many issues remain unsolved. Multi-person Chinese voice recognition is one of them. This example provieds not only multi-person Chinese voice sample dataset, but applied a transfer learning technique to the CNN trained model of the Chinese voice samples dataset. Satisfactory results can be achieved through transfer learning after an initial CNN training.
This example provides a feasibility evidence of the transfer learning techniques, and it is our wish to convert the transfer learning technique to a Kubeflow asset through this illustration case. A transfer learning pipeline will be constructed to make kubeflow user easy to adapt to their model for training accuracy enhancement. Eventually, other users can benefit from such convenient features of the kubeflow resources.
usage briefing:
1.Process audio files and convert them into spectrograms.
2.Establish experimental data, divide them into 3 categories, and set them into CNN network training.
3.Perform two training sessions to improve accuracy.
4.Compare training methods.
Tools used:
1. TensorFlow
2. Anaconda
3. Python3.7
1. preprocess(spectrograms production)
![image](https://user-images.githubusercontent.com/58965086/122675714-48a34700-d20d-11eb-81d7-865209ac8367.png)
2. import spectrogram files.
![image](https://user-images.githubusercontent.com/58965086/122675748-712b4100-d20d-11eb-96cd-1523b9329020.png)
![image](https://user-images.githubusercontent.com/58965086/122675762-8011f380-d20d-11eb-90db-f7b8942571d5.png)
3. build training dataset:
divide the dataset into training, validation, and testing sets.
![image](https://user-images.githubusercontent.com/58965086/122675818-b8b1cd00-d20d-11eb-836a-08fa3e870823.png)
4. build CNN taining:
![image](https://user-images.githubusercontent.com/58965086/122675838-d54e0500-d20d-11eb-8076-8dc78600a779.png)
5. first training
![image](https://user-images.githubusercontent.com/58965086/122675851-e565e480-d20d-11eb-8ad4-4dada12f70a0.png)
![image](https://user-images.githubusercontent.com/58965086/122675854-ea2a9880-d20d-11eb-82f8-4ad9fc506386.png)
6. first training result:
![image](https://user-images.githubusercontent.com/58965086/122675877-03cbe000-d20e-11eb-8f64-1c4ad9cec5a8.png)
7. visualize the result
![image](https://user-images.githubusercontent.com/58965086/122675890-1b0acd80-d20e-11eb-84da-1793cac58fe2.png)
![image](https://user-images.githubusercontent.com/58965086/122675896-2100ae80-d20e-11eb-8901-240b7d9b3566.png)
8. import VGG16 model
![image](https://user-images.githubusercontent.com/58965086/122675911-37a70580-d20e-11eb-95ab-a4a652fa79ab.png)
![image](https://user-images.githubusercontent.com/58965086/122675916-3e357d00-d20e-11eb-99ab-a5d22facba9c.png)
9. use conv_base model to extract features and labels
![image](https://user-images.githubusercontent.com/58965086/122675969-7937b080-d20e-11eb-885d-c5f202b3457a.png)
10. training
![image](https://user-images.githubusercontent.com/58965086/122676010-92d8f800-d20e-11eb-8826-5b599bc78b4b.png)
11. visualize the results
![image](https://user-images.githubusercontent.com/58965086/122676032-a71cf500-d20e-11eb-82fc-a2a468340a53.png)
12. build confusion matrix
![image](https://user-images.githubusercontent.com/58965086/122676055-c1ef6980-d20e-11eb-81af-c394696124c7.png)
13. visualiz the confusion matrix
![image](https://user-images.githubusercontent.com/58965086/122676069-d7fd2a00-d20e-11eb-8dcb-064f8406e9a4.png)
14. sample Chinese multiperson voice spectrogram files are added
15. sample VGG16 transfer learning code: vgg16.ipynb is added to the repository
# Chinese-multiperson-voice-recognition-using-transfer-learning
This is an example of applying transfer learning to the Chinese multi-person voice recognition application. Transfer learning is an AI technique used to enhance the training accuracy of use cases when the dataset is small or the training accuracy is low given the high noise of the original dataset. Multi-person voice recognition is known to contain high noise in the dataset. Chinese voice voice recognition has gained much progress recently thanks to the effort by the big name company such as Google. However many issues remain unsolved. Multi-person Chinese voice recognition is one of them. This example provieds not only multi-person Chinese voice sample dataset, but applied a transfer learning technique to the CNN trained model of the Chinese voice samples dataset. Satisfactory results can be achieved through transfer learning after an initial CNN training.
This example provides a feasibility evidence of the transfer learning techniques, and it is our wish to convert the transfer learning technique to a Kubeflow asset through this illustration case. A transfer learning pipeline will be constructed to make kubeflow user easy to adapt to their model for training accuracy enhancement. Eventually, other users can benefit from such convenient features of the kubeflow resources.
usage briefing:
1.Process audio files and convert them into spectrograms.
2.Establish experimental data, divide them into 3 categories, and set them into CNN network training.
3.Perform two training sessions to improve accuracy.
4.Compare training methods.
Tools used:
1. TensorFlow
2. Anaconda
3. Python3.7
1. preprocess(spectrograms production)
![image](https://user-images.githubusercontent.com/58965086/122675714-48a34700-d20d-11eb-81d7-865209ac8367.png)
2. import spectrogram files.
![image](https://user-images.githubusercontent.com/58965086/122675748-712b4100-d20d-11eb-96cd-1523b9329020.png)
![image](https://user-images.githubusercontent.com/58965086/122675762-8011f380-d20d-11eb-90db-f7b8942571d5.png)
3. build training dataset:
divide the dataset into training, validation, and testing sets.
![image](https://user-images.githubusercontent.com/58965086/122675818-b8b1cd00-d20d-11eb-836a-08fa3e870823.png)
4. build CNN taining:
![image](https://user-images.githubusercontent.com/58965086/122675838-d54e0500-d20d-11eb-8076-8dc78600a779.png)
5. first training
![image](https://user-images.githubusercontent.com/58965086/122675851-e565e480-d20d-11eb-8ad4-4dada12f70a0.png)
![image](https://user-images.githubusercontent.com/58965086/122675854-ea2a9880-d20d-11eb-82f8-4ad9fc506386.png)
6. first training result:
![image](https://user-images.githubusercontent.com/58965086/122675877-03cbe000-d20e-11eb-8f64-1c4ad9cec5a8.png)
7. visualize the result
![image](https://user-images.githubusercontent.com/58965086/122675890-1b0acd80-d20e-11eb-84da-1793cac58fe2.png)
![image](https://user-images.githubusercontent.com/58965086/122675896-2100ae80-d20e-11eb-8901-240b7d9b3566.png)
8. import VGG16 model
![image](https://user-images.githubusercontent.com/58965086/122675911-37a70580-d20e-11eb-95ab-a4a652fa79ab.png)
![image](https://user-images.githubusercontent.com/58965086/122675916-3e357d00-d20e-11eb-99ab-a5d22facba9c.png)
9. use conv_base model to extract features and labels
![image](https://user-images.githubusercontent.com/58965086/122675969-7937b080-d20e-11eb-885d-c5f202b3457a.png)
10. training
![image](https://user-images.githubusercontent.com/58965086/122676010-92d8f800-d20e-11eb-8826-5b599bc78b4b.png)
11. visualize the results
![image](https://user-images.githubusercontent.com/58965086/122676032-a71cf500-d20e-11eb-82fc-a2a468340a53.png)
12. build confusion matrix
![image](https://user-images.githubusercontent.com/58965086/122676055-c1ef6980-d20e-11eb-81af-c394696124c7.png)
13. visualiz the confusion matrix
![image](https://user-images.githubusercontent.com/58965086/122676069-d7fd2a00-d20e-11eb-8dcb-064f8406e9a4.png)
14. sample Chinese multiperson voice spectrogram files are added
15. sample VGG16 transfer learning code: vgg16.ipynb is added to the repository

File diff suppressed because one or more lines are too long

View File

@ -1,43 +1,43 @@
# Objective
Here we convert the https://www.kaggle.com/competitions/facial-keypoints-detection code to kfp-pipeline
The objective of this task is to predict keypoint positions on face images
# Testing enviornment
The pipeline is tested on `Kubeflow 1.4` and `kfp 1.1.2` , it should be compatible with previous releases of Kubeflow . kfp version used for testing is 1.1.2 which can be installed as `pip install kfp==1.1.2`
# Components used
## Docker
Docker is used to create an enviornment to run each component.
## Kubeflow pipelines
Kubeflow pipelines connect each docker component and create a pipeline. Each Kubeflow pipeline is reproducable workflow wherein we pass input arguments and run entire workflow.
# Docker
We start with creating a docker account on dockerhub (https://hub.docker.com/). We signup with our individual email. After signup is compelete login to docker using your username and password using the command `docker login` on your terminal
## Build train image
Navigate to `train` directory, create a folder named `my_data` and put your `training.zip` and `test.zip` data from Kaggle repo in this folder and build docker image using :
```
docker build -t <docker_username>/<docker_imagename>:<tag> .
```
In my case this is:
```
docker build -t hubdocker76/demotrain:v1 .
```
## Build evaluate image
Navigate to eval directory and build docker image using :
```
docker build -t <docker_username>/<docker_imagename>:<tag> .
```
In my case this is:
```
docker build -t hubdocker76/demoeval:v2 .
```
# Kubeflow pipelines
Go to generate-pipeline and run `python3 my_pipeline.py` this will generate a yaml file. which we can upload to Kubeflow pipelines UI and create a Run from it.
# Sample pipeline to run on Kubeflow
Navigate to directory `geneate-pipeline` and run `python3 my_pipeline.py` this will generate yaml file. I have named this yaml as `face_pipeline_01.yaml`. Please upload this pipeline on Kubeflow and start a Run.
# Objective
Here we convert the https://www.kaggle.com/competitions/facial-keypoints-detection code to kfp-pipeline
The objective of this task is to predict keypoint positions on face images
# Testing enviornment
The pipeline is tested on `Kubeflow 1.4` and `kfp 1.1.2` , it should be compatible with previous releases of Kubeflow . kfp version used for testing is 1.1.2 which can be installed as `pip install kfp==1.1.2`
# Components used
## Docker
Docker is used to create an enviornment to run each component.
## Kubeflow pipelines
Kubeflow pipelines connect each docker component and create a pipeline. Each Kubeflow pipeline is reproducable workflow wherein we pass input arguments and run entire workflow.
# Docker
We start with creating a docker account on dockerhub (https://hub.docker.com/). We signup with our individual email. After signup is compelete login to docker using your username and password using the command `docker login` on your terminal
## Build train image
Navigate to `train` directory, create a folder named `my_data` and put your `training.zip` and `test.zip` data from Kaggle repo in this folder and build docker image using :
```
docker build -t <docker_username>/<docker_imagename>:<tag> .
```
In my case this is:
```
docker build -t hubdocker76/demotrain:v1 .
```
## Build evaluate image
Navigate to eval directory and build docker image using :
```
docker build -t <docker_username>/<docker_imagename>:<tag> .
```
In my case this is:
```
docker build -t hubdocker76/demoeval:v2 .
```
# Kubeflow pipelines
Go to generate-pipeline and run `python3 my_pipeline.py` this will generate a yaml file. which we can upload to Kubeflow pipelines UI and create a Run from it.
# Sample pipeline to run on Kubeflow
Navigate to directory `geneate-pipeline` and run `python3 my_pipeline.py` this will generate yaml file. I have named this yaml as `face_pipeline_01.yaml`. Please upload this pipeline on Kubeflow and start a Run.

View File

@ -1,42 +1,42 @@
import kfp
from kfp import dsl
def SendMsg(trial, epoch, patience):
vop = dsl.VolumeOp(name="pvc",
resource_name="pvc", size='1Gi',
modes=dsl.VOLUME_MODE_RWO)
return dsl.ContainerOp(
name = 'Train',
image = 'hubdocker76/demotrain:v1',
command = ['python3', 'train.py'],
arguments=[
'--trial', trial,
'--epoch', epoch,
'--patience', patience
],
pvolumes={
'/data': vop.volume
}
)
def GetMsg(comp1):
return dsl.ContainerOp(
name = 'Evaluate',
image = 'hubdocker76/demoeval:v2',
pvolumes={
'/data': comp1.pvolumes['/data']
},
command = ['python3', 'eval.py']
)
@dsl.pipeline(
name = 'face pipeline',
description = 'pipeline to detect facial landmarks')
def passing_parameter(trial, epoch, patience):
comp1 = SendMsg(trial, epoch, patience)
comp2 = GetMsg(comp1)
if __name__ == '__main__':
import kfp.compiler as compiler
compiler.Compiler().compile(passing_parameter, __file__ + '.yaml')
import kfp
from kfp import dsl
def SendMsg(trial, epoch, patience):
vop = dsl.VolumeOp(name="pvc",
resource_name="pvc", size='1Gi',
modes=dsl.VOLUME_MODE_RWO)
return dsl.ContainerOp(
name = 'Train',
image = 'hubdocker76/demotrain:v1',
command = ['python3', 'train.py'],
arguments=[
'--trial', trial,
'--epoch', epoch,
'--patience', patience
],
pvolumes={
'/data': vop.volume
}
)
def GetMsg(comp1):
return dsl.ContainerOp(
name = 'Evaluate',
image = 'hubdocker76/demoeval:v2',
pvolumes={
'/data': comp1.pvolumes['/data']
},
command = ['python3', 'eval.py']
)
@dsl.pipeline(
name = 'face pipeline',
description = 'pipeline to detect facial landmarks')
def passing_parameter(trial, epoch, patience):
comp1 = SendMsg(trial, epoch, patience)
comp2 = GetMsg(comp1)
if __name__ == '__main__':
import kfp.compiler as compiler
compiler.Compiler().compile(passing_parameter, __file__ + '.yaml')

View File

@ -1,90 +1,90 @@
body {
background-color: azure;
text-align: center;
font-family: fantasy;
}
#title {
font-size: 10vh;
}
#center {
margin-left: 10%;
margin-right: 10%;
width: 80vw;
height: 80vh;
opacity: 2.0;
background-color: blanchedalmond;
border: 5px solid #666;
border-radius: 50px;
box-shadow:-9px 12px 9px black
}
#input {
float: left;
width: 50%;
height: 100%;
}
#output {
float: right;
width: 50%;
height: 100%;
}
.content-title {
font-size: 5vh;
margin: 2%;
}
textarea {
margin: 5%;
width: 90%;
font-size: 4vh;
}
input {
width: 30%;
height: 10%;
font-size: 4vh;
font-family: fantasy;
background-color: lawngreen;
border-radius: 50px;
}
.content-setting {
font-size: 4vh;
text-align: left;
margin-left: 5%;
}
#preprocess {
border: 5px solid grey;
border-radius: 10px;
width: 87%;
height: 25%;
margin: 5%;
background-color: white;
font-size: 4vh;
overflow: auto;
word-break: break-all;
word-wrap: break-word;
text-align: left;
font-family: monospace;
}
table {
border: 5px solid grey;
border-radius: 10px;
font-size: 4vh;
margin: 5%;
width: 90%;
height: 25%;
background-color: white;
}
.predict-title {
width: 33.33%;
height: 20%;
color: green;
body {
background-color: azure;
text-align: center;
font-family: fantasy;
}
#title {
font-size: 10vh;
}
#center {
margin-left: 10%;
margin-right: 10%;
width: 80vw;
height: 80vh;
opacity: 2.0;
background-color: blanchedalmond;
border: 5px solid #666;
border-radius: 50px;
box-shadow:-9px 12px 9px black
}
#input {
float: left;
width: 50%;
height: 100%;
}
#output {
float: right;
width: 50%;
height: 100%;
}
.content-title {
font-size: 5vh;
margin: 2%;
}
textarea {
margin: 5%;
width: 90%;
font-size: 4vh;
}
input {
width: 30%;
height: 10%;
font-size: 4vh;
font-family: fantasy;
background-color: lawngreen;
border-radius: 50px;
}
.content-setting {
font-size: 4vh;
text-align: left;
margin-left: 5%;
}
#preprocess {
border: 5px solid grey;
border-radius: 10px;
width: 87%;
height: 25%;
margin: 5%;
background-color: white;
font-size: 4vh;
overflow: auto;
word-break: break-all;
word-wrap: break-word;
text-align: left;
font-family: monospace;
}
table {
border: 5px solid grey;
border-radius: 10px;
font-size: 4vh;
margin: 5%;
width: 90%;
height: 25%;
background-color: white;
}
.predict-title {
width: 33.33%;
height: 20%;
color: green;
}

View File

@ -1,156 +1,156 @@
<!DOCTYPE html>
<html>
<head>
<title>Kubeflow - NLP</title>
</head>
<body>
<div id="title">Kubeflow - NLP</div>
<div id="center">
<div id="input">
<div class="content-title">Message</div>
<form action="{{ url_for('predict')}}" method="POST" style="height: 70vh;">
<textarea name="message" id="message" placeholder="...Please enter here" style="height: 60%;">{% print(message) %}</textarea>
<input type="submit" value="Predict">
</form>
</div>
<div id="output">
<div class="content-title">Result</div>
<div class="content-setting" style="color: red;">Positive +</div>
<div class="content-setting" style="color: blue;">Negative -</div>
<div id="preprocess">
{% print(data) %}
</div>
<table border="1">
<tr>
<td class="predict-title">Numpy</td>
<td class="predict-title">SKlearn</td>
<td class="predict-title">Pytorch</td>
<td class="predict-title">SVM</td>
</tr>
<tr>
<td>
{% if my_prediction_np == 1%}
<div style="font-size: 8vh; color: red;">+</div>
{% elif my_prediction_np == 0%}
<div style="font-size: 8vh; color: blue;">-</div>
{% endif %}
</td>
<td>
{% if my_prediction_skl == 1%}
<div style="font-size: 8vh; color: red;">+</div>
{% elif my_prediction_skl == 0%}
<div style="font-size: 8vh; color: blue;">-</div>
{% endif %}
</td>
<td>
{% if my_prediction_toc == 1%}
<div style="font-size: 8vh; color: red;">+</div>
{% elif my_prediction_toc == 0%}
<div style="font-size: 8vh; color: blue;">-</div>
{% endif %}
</td>
<td>
{% if my_prediction_svm == 1%}
<div style="font-size: 8vh; color: red;">+</div>
{% elif my_prediction_svm == 0%}
<div style="font-size: 8vh; color: blue;">-</div>
{% endif %}
</td>
</tr>
</table>
</div>
</div>
</body>
<style type="text/css">
body {
background-color: azure;
text-align: center;
font-family: fantasy;
}
#title {
font-size: 10vh;
}
#center {
margin-left: 10%;
margin-right: 10%;
width: 80vw;
height: 80vh;
opacity: 2.0;
background-color: blanchedalmond;
border: 5px solid #666;
border-radius: 50px;
box-shadow:-9px 12px 9px black
}
#input {
float: left;
width: 50%;
height: 100%;
}
#output {
float: right;
width: 50%;
height: 100%;
}
.content-title {
font-size: 5vh;
margin: 2%;
}
textarea {
margin: 5%;
width: 90%;
font-size: 4vh;
}
input {
width: 30%;
height: 10%;
font-size: 4vh;
font-family: fantasy;
background-color: lawngreen;
border-radius: 50px;
}
.content-setting {
font-size: 4vh;
text-align: left;
margin-left: 5%;
}
#preprocess {
border: 5px solid grey;
border-radius: 10px;
width: 88.1%;
height: 25%;
margin: 5%;
background-color: white;
font-size: 4vh;
overflow: auto;
word-break: break-all;
word-wrap: break-word;
text-align: left;
font-family: monospace;
}
table {
border: 5px solid grey;
border-radius: 10px;
font-size: 4vh;
margin: 5%;
width: 90%;
height: 25%;
background-color: white;
}
.predict-title {
width: 25%;
height: 20%;
color: green;
}
</style>
<!DOCTYPE html>
<html>
<head>
<title>Kubeflow - NLP</title>
</head>
<body>
<div id="title">Kubeflow - NLP</div>
<div id="center">
<div id="input">
<div class="content-title">Message</div>
<form action="{{ url_for('predict')}}" method="POST" style="height: 70vh;">
<textarea name="message" id="message" placeholder="...Please enter here" style="height: 60%;">{% print(message) %}</textarea>
<input type="submit" value="Predict">
</form>
</div>
<div id="output">
<div class="content-title">Result</div>
<div class="content-setting" style="color: red;">Positive +</div>
<div class="content-setting" style="color: blue;">Negative -</div>
<div id="preprocess">
{% print(data) %}
</div>
<table border="1">
<tr>
<td class="predict-title">Numpy</td>
<td class="predict-title">SKlearn</td>
<td class="predict-title">Pytorch</td>
<td class="predict-title">SVM</td>
</tr>
<tr>
<td>
{% if my_prediction_np == 1%}
<div style="font-size: 8vh; color: red;">+</div>
{% elif my_prediction_np == 0%}
<div style="font-size: 8vh; color: blue;">-</div>
{% endif %}
</td>
<td>
{% if my_prediction_skl == 1%}
<div style="font-size: 8vh; color: red;">+</div>
{% elif my_prediction_skl == 0%}
<div style="font-size: 8vh; color: blue;">-</div>
{% endif %}
</td>
<td>
{% if my_prediction_toc == 1%}
<div style="font-size: 8vh; color: red;">+</div>
{% elif my_prediction_toc == 0%}
<div style="font-size: 8vh; color: blue;">-</div>
{% endif %}
</td>
<td>
{% if my_prediction_svm == 1%}
<div style="font-size: 8vh; color: red;">+</div>
{% elif my_prediction_svm == 0%}
<div style="font-size: 8vh; color: blue;">-</div>
{% endif %}
</td>
</tr>
</table>
</div>
</div>
</body>
<style type="text/css">
body {
background-color: azure;
text-align: center;
font-family: fantasy;
}
#title {
font-size: 10vh;
}
#center {
margin-left: 10%;
margin-right: 10%;
width: 80vw;
height: 80vh;
opacity: 2.0;
background-color: blanchedalmond;
border: 5px solid #666;
border-radius: 50px;
box-shadow:-9px 12px 9px black
}
#input {
float: left;
width: 50%;
height: 100%;
}
#output {
float: right;
width: 50%;
height: 100%;
}
.content-title {
font-size: 5vh;
margin: 2%;
}
textarea {
margin: 5%;
width: 90%;
font-size: 4vh;
}
input {
width: 30%;
height: 10%;
font-size: 4vh;
font-family: fantasy;
background-color: lawngreen;
border-radius: 50px;
}
.content-setting {
font-size: 4vh;
text-align: left;
margin-left: 5%;
}
#preprocess {
border: 5px solid grey;
border-radius: 10px;
width: 88.1%;
height: 25%;
margin: 5%;
background-color: white;
font-size: 4vh;
overflow: auto;
word-break: break-all;
word-wrap: break-word;
text-align: left;
font-family: monospace;
}
table {
border: 5px solid grey;
border-radius: 10px;
font-size: 4vh;
margin: 5%;
width: 90%;
height: 25%;
background-color: white;
}
.predict-title {
width: 25%;
height: 20%;
color: green;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -0,0 +1,24 @@
FROM nodered/node-red:2.2.3-12
ARG PREFIX
ENV NODE_OPTIONS=--max_old_space_size=128
USER root
RUN apk update && \
apk add py3-pip python3-dev libffi-dev
USER root
RUN apk update && \
apk add py3-pip
RUN apk update && apk add python3-dev
USER node-red
# Copy package.json to the WORKDIR so npm builds all
# of your added nodes modules for Node-RED
COPY package.json .
RUN npm install --unsafe-perm --no-update-notifier --no-fund --only=production
ADD scripts/entrypoint.sh .
ENTRYPOINT ["./entrypoint.sh"]

View File

@ -0,0 +1,3 @@
#!/usr/bin/env bash
docker compose build

View File

@ -0,0 +1 @@
{"version":"1","format":"xl-single","id":"fd84d37c-ca41-455e-91a5-092551ea2351","xl":{"version":"3","this":"b6e74063-d6f7-410f-ad3f-4e8fe53877e1","sets":[["b6e74063-d6f7-410f-ad3f-4e8fe53877e1"]],"distributionAlgo":"SIPMOD+PARITY"}}

View File

@ -0,0 +1,43 @@
version: '3.7'
services:
node-red:
image: reg.footprint-ai.com/public/kube-nodered:latest
build:
context: .
dockerfile: Dockerfile
labels:
com.docker.compose.container-number: "1"
environment:
- TZ=Asia/Taipei
- USERDIR=$USERDIR
- NODE_RED_CREDENTIAL_SECRET=noderedtutorial
- KUBEFLOW_HOST=$KUBEFLOW_HOST
- KUBEFLOW_USERNAME=$KUBEFLOW_USERNAME
- KUBEFLOW_PASSWORD=$KUBEFLOW_PASSWORD
- MINIO_HOST=$MINIO_HOST
- MINIO_ROOT_USER=$MINIO_ROOT_USER
- MINIO_ROOT_PASSWORD=$MINIO_ROOT_PASSWORD
ports:
- "1880:1880"
networks:
- node-red-net
volumes:
- ./:/data
minio:
image: minio/minio
command: server --console-address ":9001" /data
expose:
- "9000"
environment:
- MINIO_ROOT_USER=$MINIO_ROOT_USER
- MINIO_ROOT_PASSWORD=$MINIO_ROOT_PASSWORD
ports:
- "9001:9001"
- "9000:9000"
volumes:
- ./data:/data
networks:
node-red-net:

View File

@ -0,0 +1,446 @@
{
"node-red": {
"name": "node-red",
"version": "2.2.3",
"local": false,
"user": false,
"nodes": {
"inject": {
"name": "inject",
"types": [
"inject"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/common/20-inject.js"
},
"debug": {
"name": "debug",
"types": [
"debug"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/common/21-debug.js"
},
"complete": {
"name": "complete",
"types": [
"complete"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/common/24-complete.js"
},
"catch": {
"name": "catch",
"types": [
"catch"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/common/25-catch.js"
},
"status": {
"name": "status",
"types": [
"status"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/common/25-status.js"
},
"link": {
"name": "link",
"types": [
"link in",
"link out",
"link call"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/common/60-link.js"
},
"comment": {
"name": "comment",
"types": [
"comment"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/common/90-comment.js"
},
"unknown": {
"name": "unknown",
"types": [
"unknown"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/common/98-unknown.js"
},
"function": {
"name": "function",
"types": [
"function"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/function/10-function.js"
},
"switch": {
"name": "switch",
"types": [
"switch"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/function/10-switch.js"
},
"change": {
"name": "change",
"types": [
"change"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/function/15-change.js"
},
"range": {
"name": "range",
"types": [
"range"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/function/16-range.js"
},
"template": {
"name": "template",
"types": [
"template"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/function/80-template.js"
},
"delay": {
"name": "delay",
"types": [
"delay"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/function/89-delay.js"
},
"trigger": {
"name": "trigger",
"types": [
"trigger"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/function/89-trigger.js"
},
"exec": {
"name": "exec",
"types": [
"exec"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/function/90-exec.js"
},
"rbe": {
"name": "rbe",
"types": [
"rbe"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/function/rbe.js"
},
"tls": {
"name": "tls",
"types": [
"tls-config"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/network/05-tls.js"
},
"httpproxy": {
"name": "httpproxy",
"types": [
"http proxy"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/network/06-httpproxy.js"
},
"mqtt": {
"name": "mqtt",
"types": [
"mqtt in",
"mqtt out",
"mqtt-broker"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/network/10-mqtt.js"
},
"httpin": {
"name": "httpin",
"types": [
"http in",
"http response"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/network/21-httpin.js"
},
"httprequest": {
"name": "httprequest",
"types": [
"http request"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/network/21-httprequest.js"
},
"websocket": {
"name": "websocket",
"types": [
"websocket in",
"websocket out",
"websocket-listener",
"websocket-client"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/network/22-websocket.js"
},
"tcpin": {
"name": "tcpin",
"types": [
"tcp in",
"tcp out",
"tcp request"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/network/31-tcpin.js"
},
"udp": {
"name": "udp",
"types": [
"udp in",
"udp out"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/network/32-udp.js"
},
"CSV": {
"name": "CSV",
"types": [
"csv"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/parsers/70-CSV.js"
},
"HTML": {
"name": "HTML",
"types": [
"html"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/parsers/70-HTML.js"
},
"JSON": {
"name": "JSON",
"types": [
"json"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/parsers/70-JSON.js"
},
"XML": {
"name": "XML",
"types": [
"xml"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/parsers/70-XML.js"
},
"YAML": {
"name": "YAML",
"types": [
"yaml"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/parsers/70-YAML.js"
},
"split": {
"name": "split",
"types": [
"split",
"join"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/sequence/17-split.js"
},
"sort": {
"name": "sort",
"types": [
"sort"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/sequence/18-sort.js"
},
"batch": {
"name": "batch",
"types": [
"batch"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/sequence/19-batch.js"
},
"file": {
"name": "file",
"types": [
"file",
"file in"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/storage/10-file.js"
},
"watch": {
"name": "watch",
"types": [
"watch"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red",
"file": "/usr/src/node-red/node_modules/@node-red/nodes/core/storage/23-watch.js"
}
}
},
"node-red-contrib-autoai-pipeline": {
"name": "node-red-contrib-autoai-pipeline",
"version": "0.0.1",
"local": true,
"user": false,
"nodes": {
"fl": {
"name": "fl",
"types": [
"RAG"
],
"enabled": true,
"local": true,
"user": false,
"module": "node-red-contrib-autoai-pipeline",
"file": "/data/main/node_modules/autoAI pipeline/RAG/RAG.js"
}
}
},
"node-red-contrib-pythonshell": {
"name": "node-red-contrib-pythonshell",
"version": "1.5.4",
"local": false,
"user": false,
"nodes": {
"pythonshell": {
"name": "pythonshell",
"types": [
"pythonshell in"
],
"enabled": true,
"local": false,
"user": false,
"module": "node-red-contrib-pythonshell",
"file": "/usr/src/node-red/node_modules/node-red-contrib-pythonshell/src/pythonshell.js"
}
}
}
}

View File

@ -0,0 +1,20 @@
{
"_": {
"editor": {
"view": {
"view-store-zoom": false,
"view-store-position": false,
"view-show-grid": true,
"view-snap-grid": true,
"view-grid-size": 20,
"view-node-status": true,
"view-node-show-label": true,
"view-show-tips": true,
"view-show-welcome-tours": true
},
"tours": {
"welcome": "2.2.3"
}
}
}
}

View File

@ -0,0 +1,17 @@
{
"_": {
"editor": {
"view": {
"view-store-zoom": false,
"view-store-position": false,
"view-show-grid": true,
"view-snap-grid": true,
"view-grid-size": 20,
"view-node-status": true,
"view-node-show-label": true,
"view-show-tips": true,
"view-show-welcome-tours": true
}
}
}
}

View File

@ -0,0 +1,650 @@
[
{
"id": "f6f2187d.f17ca8",
"type": "tab",
"label": "Flow 1",
"disabled": false,
"info": ""
},
{
"id": "c9fd2f76f856879d",
"type": "tab",
"label": "base flow",
"disabled": false,
"info": "",
"env": []
},
{
"id": "e0941514f4cd8be3",
"type": "tab",
"label": "流程1",
"disabled": false,
"info": "",
"env": []
},
{
"id": "3cc11d24.ff01a2",
"type": "comment",
"z": "f6f2187d.f17ca8",
"name": "WARNING: please check you have started this container with a volume that is mounted to /data\\n otherwise any flow changes are lost when you redeploy or upgrade the container\\n (e.g. upgrade to a more recent node-red docker image).\\n If you are using named volumes you can ignore this warning.\\n Double click or see info side panel to learn how to start Node-RED in Docker to save your work",
"info": "\nTo start docker with a bind mount volume (-v option), for example:\n\n```\ndocker run -it -p 1880:1880 -v /home/user/node_red_data:/data --name mynodered nodered/node-red\n```\n\nwhere `/home/user/node_red_data` is a directory on your host machine where you want to store your flows.\n\nIf you do not do this then you can experiment and redploy flows, but if you restart or upgrade the container the flows will be disconnected and lost. \n\nThey will still exist in a hidden data volume, which can be recovered using standard docker techniques, but that is much more complex than just starting with a named volume as described above.",
"x": 350,
"y": 80,
"wires": []
},
{
"id": "b126ea03f7d74573",
"type": "debug",
"z": "f6f2187d.f17ca8",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 450,
"y": 440,
"wires": []
},
{
"id": "692c86b087eed4a0",
"type": "pythonshell in",
"z": "f6f2187d.f17ca8",
"name": "install dependency",
"pyfile": "/data/main/py/install.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 270,
"y": 300,
"wires": [
[
"0b5c3b39a424dc6a"
]
]
},
{
"id": "0b5c3b39a424dc6a",
"type": "debug",
"z": "f6f2187d.f17ca8",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": true,
"complete": "payload",
"targetType": "msg",
"statusVal": "payload",
"statusType": "auto",
"x": 470,
"y": 300,
"wires": []
},
{
"id": "3b1a0675389769a1",
"type": "comment",
"z": "f6f2187d.f17ca8",
"name": "install python dependency",
"info": "",
"x": 370,
"y": 240,
"wires": []
},
{
"id": "04e11dfd70107dcf",
"type": "comment",
"z": "f6f2187d.f17ca8",
"name": "read experiemnt data from kfp",
"info": "",
"x": 380,
"y": 380,
"wires": []
},
{
"id": "ffe395298ffe40e0",
"type": "pythonshell in",
"z": "f6f2187d.f17ca8",
"name": "list experiments",
"pyfile": "/data/main/py/api_examples/list_experiments.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 260,
"y": 440,
"wires": [
[
"b126ea03f7d74573"
]
]
},
{
"id": "d7c0bb24de178d22",
"type": "RAG",
"z": "f6f2187d.f17ca8",
"name": "",
"url": "",
"data_name": "",
"huggingface_token": "",
"embedding_model": "",
"LLM_model": "",
"Pinecone_token": "",
"Pinecone_index": "",
"host": "",
"username": "",
"userpassword": "",
"x": 390,
"y": 580,
"wires": [
[]
]
},
{
"id": "b33d174d94620977",
"type": "debug",
"z": "c9fd2f76f856879d",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 730,
"y": 240,
"wires": []
},
{
"id": "6b5130cec3efaf0a",
"type": "debug",
"z": "c9fd2f76f856879d",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 320,
"wires": []
},
{
"id": "84f40c6e98828bb5",
"type": "debug",
"z": "c9fd2f76f856879d",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 770,
"y": 400,
"wires": []
},
{
"id": "1a03c8eab24f2d9d",
"type": "pythonshell in",
"z": "c9fd2f76f856879d",
"name": "test",
"pyfile": "/data/main/py/model35.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 510,
"y": 520,
"wires": [
[
"241bb407c3b1a512"
]
]
},
{
"id": "241bb407c3b1a512",
"type": "debug",
"z": "c9fd2f76f856879d",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 730,
"y": 520,
"wires": []
},
{
"id": "9211da9222209e48",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 140,
"wires": []
},
{
"id": "f2394d82583d42d2",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "install dependency",
"pyfile": "/data/main/py/install.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 550,
"y": 80,
"wires": [
[
"cec42d56788a6d86"
]
]
},
{
"id": "cec42d56788a6d86",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": true,
"complete": "payload",
"targetType": "msg",
"statusVal": "payload",
"statusType": "auto",
"x": 750,
"y": 80,
"wires": []
},
{
"id": "6df33a3d52decf56",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "list experiments",
"pyfile": "/data/main/py/api_examples/list_experiments.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 540,
"y": 140,
"wires": [
[
"9211da9222209e48"
]
]
},
{
"id": "20410c4e397c7805",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "list_pipelines",
"pyfile": "/data/main/py/api_examples/list_pipelines.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 530,
"y": 200,
"wires": [
[
"8400360595296c8f"
]
]
},
{
"id": "8400360595296c8f",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 200,
"wires": []
},
{
"id": "20ae5c175bd4bd4d",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "upload_pipeline",
"pyfile": "/data/main/py/api_examples/upload_pipeline.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 540,
"y": 260,
"wires": [
[
"711b376a156b58a2"
]
]
},
{
"id": "711b376a156b58a2",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 260,
"wires": []
},
{
"id": "5dc55b480c912ba0",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "create_experiment",
"pyfile": "/data/main/py/api_examples/create_experiment.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 550,
"y": 320,
"wires": [
[
"47ae84a2b85aec74"
]
]
},
{
"id": "47ae84a2b85aec74",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 320,
"wires": []
},
{
"id": "bf79cd5247e6d498",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "create_run.py",
"pyfile": "/data/main/py/api_examples/create_run.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 540,
"y": 380,
"wires": [
[
"41280a3e2bd16bf1"
]
]
},
{
"id": "41280a3e2bd16bf1",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 380,
"wires": []
},
{
"id": "9c2a05f63fa71bc7",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "delete_experiment",
"pyfile": "/data/main/py/api_examples/delete_experiment.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 550,
"y": 440,
"wires": [
[
"5a77999e669b4c06"
]
]
},
{
"id": "5a77999e669b4c06",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 440,
"wires": []
},
{
"id": "ef4b5e874d4c37ab",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "delete_pipeline",
"pyfile": "/data/main/py/api_examples/delete_pipeline.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 540,
"y": 500,
"wires": [
[
"29e24d1ea757f2c6"
]
]
},
{
"id": "29e24d1ea757f2c6",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 500,
"wires": []
},
{
"id": "a2c4616e7a1591b7",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "delete_run.py",
"pyfile": "/data/main/py/api_examples/delete_run.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 540,
"y": 560,
"wires": [
[
"5f127d565442e111"
]
]
},
{
"id": "5f127d565442e111",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 560,
"wires": []
},
{
"id": "80de59953d4b8556",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "get_run",
"pyfile": "/data/main/py/api_examples/get_run.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 520,
"y": 620,
"wires": [
[
"4ccad67787ec0207"
]
]
},
{
"id": "4ccad67787ec0207",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 620,
"wires": []
},
{
"id": "45cde0d735c7fa70",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "kfp_login.py",
"pyfile": "/data/main/py/api_examples/kfp_login.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 530,
"y": 680,
"wires": [
[
"9f35716a8bed686e"
]
]
},
{
"id": "9f35716a8bed686e",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 680,
"wires": []
},
{
"id": "b33bc4ad7e423460",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "kfp_login.py",
"pyfile": "/data/main/py/api_examples/kfp_namespace.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 530,
"y": 740,
"wires": [
[
"a139fa9944b79f94"
]
]
},
{
"id": "a139fa9944b79f94",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 740,
"wires": []
}
]

View File

@ -0,0 +1,697 @@
[
{
"id": "f6f2187d.f17ca8",
"type": "tab",
"label": "Flow 1",
"disabled": false,
"info": ""
},
{
"id": "c9fd2f76f856879d",
"type": "tab",
"label": "base flow",
"disabled": false,
"info": "",
"env": []
},
{
"id": "e0941514f4cd8be3",
"type": "tab",
"label": "流程1",
"disabled": false,
"info": "",
"env": []
},
{
"id": "3cc11d24.ff01a2",
"type": "comment",
"z": "f6f2187d.f17ca8",
"name": "WARNING: please check you have started this container with a volume that is mounted to /data\\n otherwise any flow changes are lost when you redeploy or upgrade the container\\n (e.g. upgrade to a more recent node-red docker image).\\n If you are using named volumes you can ignore this warning.\\n Double click or see info side panel to learn how to start Node-RED in Docker to save your work",
"info": "\nTo start docker with a bind mount volume (-v option), for example:\n\n```\ndocker run -it -p 1880:1880 -v /home/user/node_red_data:/data --name mynodered nodered/node-red\n```\n\nwhere `/home/user/node_red_data` is a directory on your host machine where you want to store your flows.\n\nIf you do not do this then you can experiment and redploy flows, but if you restart or upgrade the container the flows will be disconnected and lost. \n\nThey will still exist in a hidden data volume, which can be recovered using standard docker techniques, but that is much more complex than just starting with a named volume as described above.",
"x": 350,
"y": 80,
"wires": []
},
{
"id": "b126ea03f7d74573",
"type": "debug",
"z": "f6f2187d.f17ca8",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 450,
"y": 440,
"wires": []
},
{
"id": "692c86b087eed4a0",
"type": "pythonshell in",
"z": "f6f2187d.f17ca8",
"name": "install dependency",
"pyfile": "/data/main/py/install.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 270,
"y": 300,
"wires": [
[
"0b5c3b39a424dc6a"
]
]
},
{
"id": "0b5c3b39a424dc6a",
"type": "debug",
"z": "f6f2187d.f17ca8",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": true,
"complete": "payload",
"targetType": "msg",
"statusVal": "payload",
"statusType": "auto",
"x": 470,
"y": 300,
"wires": []
},
{
"id": "3b1a0675389769a1",
"type": "comment",
"z": "f6f2187d.f17ca8",
"name": "install python dependency",
"info": "",
"x": 370,
"y": 240,
"wires": []
},
{
"id": "04e11dfd70107dcf",
"type": "comment",
"z": "f6f2187d.f17ca8",
"name": "read experiemnt data from kfp",
"info": "",
"x": 380,
"y": 380,
"wires": []
},
{
"id": "ffe395298ffe40e0",
"type": "pythonshell in",
"z": "f6f2187d.f17ca8",
"name": "list experiments",
"pyfile": "/data/main/py/api_examples/list_experiments.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 260,
"y": 440,
"wires": [
[
"b126ea03f7d74573"
]
]
},
{
"id": "d7c0bb24de178d22",
"type": "RAG",
"z": "f6f2187d.f17ca8",
"name": "",
"url": "https://arxiv.org/pdf/2207.02696.pdf",
"data_name": "/yolov7.pdf",
"huggingface_token": "",
"embedding_model": "sentence-transformers/all-MiniLM-L6-v2",
"LLM_model": "openai-community/gpt2",
"Pinecone_token": "",
"Pinecone_index": "test1",
"host": "",
"username": "",
"userpassword": "",
"x": 390,
"y": 580,
"wires": [
[
"a4743858ec1f39eb"
]
]
},
{
"id": "e659035ebcd2420d",
"type": "inject",
"z": "f6f2187d.f17ca8",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 250,
"y": 580,
"wires": [
[
"d7c0bb24de178d22"
]
]
},
{
"id": "a4743858ec1f39eb",
"type": "debug",
"z": "f6f2187d.f17ca8",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 530,
"y": 580,
"wires": []
},
{
"id": "b33d174d94620977",
"type": "debug",
"z": "c9fd2f76f856879d",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 730,
"y": 240,
"wires": []
},
{
"id": "6b5130cec3efaf0a",
"type": "debug",
"z": "c9fd2f76f856879d",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 320,
"wires": []
},
{
"id": "84f40c6e98828bb5",
"type": "debug",
"z": "c9fd2f76f856879d",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 770,
"y": 400,
"wires": []
},
{
"id": "1a03c8eab24f2d9d",
"type": "pythonshell in",
"z": "c9fd2f76f856879d",
"name": "test",
"pyfile": "/data/main/py/model35.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 510,
"y": 520,
"wires": [
[
"241bb407c3b1a512"
]
]
},
{
"id": "241bb407c3b1a512",
"type": "debug",
"z": "c9fd2f76f856879d",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 730,
"y": 520,
"wires": []
},
{
"id": "9211da9222209e48",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 140,
"wires": []
},
{
"id": "f2394d82583d42d2",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "install dependency",
"pyfile": "/data/main/py/install.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 550,
"y": 80,
"wires": [
[
"cec42d56788a6d86"
]
]
},
{
"id": "cec42d56788a6d86",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": true,
"complete": "payload",
"targetType": "msg",
"statusVal": "payload",
"statusType": "auto",
"x": 750,
"y": 80,
"wires": []
},
{
"id": "6df33a3d52decf56",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "list experiments",
"pyfile": "/data/main/py/api_examples/list_experiments.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 540,
"y": 140,
"wires": [
[
"9211da9222209e48"
]
]
},
{
"id": "20410c4e397c7805",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "list_pipelines",
"pyfile": "/data/main/py/api_examples/list_pipelines.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 530,
"y": 200,
"wires": [
[
"8400360595296c8f"
]
]
},
{
"id": "8400360595296c8f",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 200,
"wires": []
},
{
"id": "20ae5c175bd4bd4d",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "upload_pipeline",
"pyfile": "/data/main/py/api_examples/upload_pipeline.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 540,
"y": 260,
"wires": [
[
"711b376a156b58a2"
]
]
},
{
"id": "711b376a156b58a2",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 260,
"wires": []
},
{
"id": "5dc55b480c912ba0",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "create_experiment",
"pyfile": "/data/main/py/api_examples/create_experiment.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 550,
"y": 320,
"wires": [
[
"47ae84a2b85aec74"
]
]
},
{
"id": "47ae84a2b85aec74",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 320,
"wires": []
},
{
"id": "bf79cd5247e6d498",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "create_run.py",
"pyfile": "/data/main/py/api_examples/create_run.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 540,
"y": 380,
"wires": [
[
"41280a3e2bd16bf1"
]
]
},
{
"id": "41280a3e2bd16bf1",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 380,
"wires": []
},
{
"id": "9c2a05f63fa71bc7",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "delete_experiment",
"pyfile": "/data/main/py/api_examples/delete_experiment.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 550,
"y": 440,
"wires": [
[
"5a77999e669b4c06"
]
]
},
{
"id": "5a77999e669b4c06",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 440,
"wires": []
},
{
"id": "ef4b5e874d4c37ab",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "delete_pipeline",
"pyfile": "/data/main/py/api_examples/delete_pipeline.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 540,
"y": 500,
"wires": [
[
"29e24d1ea757f2c6"
]
]
},
{
"id": "29e24d1ea757f2c6",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 500,
"wires": []
},
{
"id": "a2c4616e7a1591b7",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "delete_run.py",
"pyfile": "/data/main/py/api_examples/delete_run.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 540,
"y": 560,
"wires": [
[
"5f127d565442e111"
]
]
},
{
"id": "5f127d565442e111",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 560,
"wires": []
},
{
"id": "80de59953d4b8556",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "get_run",
"pyfile": "/data/main/py/api_examples/get_run.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 520,
"y": 620,
"wires": [
[
"4ccad67787ec0207"
]
]
},
{
"id": "4ccad67787ec0207",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 620,
"wires": []
},
{
"id": "45cde0d735c7fa70",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "kfp_login.py",
"pyfile": "/data/main/py/api_examples/kfp_login.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 530,
"y": 680,
"wires": [
[
"9f35716a8bed686e"
]
]
},
{
"id": "9f35716a8bed686e",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 680,
"wires": []
},
{
"id": "b33bc4ad7e423460",
"type": "pythonshell in",
"z": "e0941514f4cd8be3",
"name": "kfp_login.py",
"pyfile": "/data/main/py/api_examples/kfp_namespace.py",
"virtualenv": "",
"continuous": true,
"stdInData": false,
"python3": true,
"x": 530,
"y": 740,
"wires": [
[
"a139fa9944b79f94"
]
]
},
{
"id": "a139fa9944b79f94",
"type": "debug",
"z": "e0941514f4cd8be3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 750,
"y": 740,
"wires": []
}
]

View File

@ -0,0 +1,3 @@
{
"$": "debb1e3e4666ba98dd5189a6e20b7e40jk4="
}

View File

@ -0,0 +1,91 @@
<script type="text/javascript">
RED.nodes.registerType('RAG', {
category: 'function',
color: '#7F8C8D',
defaults: {
name: { value: "" },
url:{value:""},
data_name:{value:""},
huggingface_token:{value:""},
embedding_model:{value:""},
LLM_model:{value:""},
Pinecone_token:{value:""},
Pinecone_index:{value:""},
host:{value:""},
username:{value:""},
userpassword:{value:""},
},
inputs: 1,
outputs: 1,
icon: "font-awesome/fa-file-text",
label: function() {
return this.name ||"RAG";
},
oneditprepare:{
},
});
</script>
<script type="text/x-red" data-template-name="RAG">
<div class="form-row">
<label for="node-input-name">Name</label>
<input type="text" id="node-input-name" placeholder="Name" />
</div>
<div class="form-row ">
<label for="node-input-url"><i class="fa"></i>url</label>
<input type="text" id="node-input-url" />
</div>
<div class="form-row ">
<label for="node-input-data_name"><i class="fa"></i>data_name</label>
<input type="text" id="node-input-data_name" />
</div>
<div class="form-row ">
<label for="node-input-huggingface_token"><i class="fa"></i>huggingface_token</label>
<input type="text" id="node-input-huggingface_token" />
</div>
<div class="form-row ">
<label for="node-input-embedding_model"><i class="fa"></i>embedding_model</label>
<input type="text" id="node-input-embedding_model" />
</div>
<div class="form-row ">
<label for="node-input-LLM_model"><i class="fa"></i>LLM_model</label>
<input type="text" id="node-input-LLM_model" />
</div>
<div class="form-row ">
<label for="node-input-Pinecone_token"><i class="fa"></i>Pinecone_token</label>
<input type="text" id="node-input-Pinecone_token" />
</div>
<div class="form-row ">
<label for="node-input-Pinecone_index"><i class="fa"></i>Pinecone_index</label>
<input type="text" id="node-input-Pinecone_index" />
</div>
<div class="form-row ">
<label for="node-input-host"><i class="fa"></i>host</label>
<input type="text" id="node-input-host" />
</div>
<div class="form-row ">
<label for="node-input-username"><i class="fa"></i>username</label>
<input type="text" id="node-input-username" />
</div>
<div class="form-row ">
<label for="node-input-userpassword"><i class="fa"></i>userpassword</label>
<input type="text" id="node-input-userpassword" />
</div>
</script>

View File

@ -0,0 +1,120 @@
const util = require('util');
const snippets = require('../snippets');
const fs = require("fs");
const spawn = require('child_process').spawn;
class PythonshellNode {
constructor(config) {
this.spawn = spawn;
this.onStatus = ()=>{};
}
onInput(msg, node, out, err) {
this.pyfile = msg.path;
var spawnCmd = "python3";
this.py = this.spawn(spawnCmd, ['-u', this.pyfile], {
cwd: this.pyfile.substring(0, this.pyfile.lastIndexOf('/'))
});
this.onStatus({fill:"green",shape:"dot",text:"Standby"});
var py = this.py;
var dataString = '';
var errString = '';
py.stdout.on('data', data => {
clearTimeout(this.standbyTimer)
this.onStatus({fill:"green",shape:"dot",text:"Processing data"});
let dataStr = data.toString();
let lines = dataStr.split('\n');
for (let line of lines) {
if (line.startsWith("COLUMN_NAMES:")) {
msg.col_names = line.split("COLUMN_NAMES:")[1].trim();
}else if (line.startsWith("Classnames:")){
msg.classnames = line.split("Classnames:")[1].trim();
}else if (line.trim() !== "") {
dataString += line + "\n";
}
}
if (dataString != ""){
node.warn(dataString.trim());
}
dataString = '';
this.standbyTimer = setTimeout(()=>{
this.onStatus({fill:"green",shape:"dot",text:"Standby"})
}, 2000)
});
py.stderr.on('data', data => {
errString += String(data);
this.onStatus({fill:"red",shape:"dot",text:"Error: " + errString});
});
py.stderr.on('error', console.log)
py.stdout.on('error', console.log)
py.stdin.on('error', console.log)
py.on('error', console.log)
py.on('close', code => {
if (code) {
err('exit code: ' + code + ', ' + errString);
this.onStatus({fill:"red",shape:"dot",text:"Exited: " + code})
} else {
out(msg);
this.onStatus({fill:"green",shape:"dot",text:"Done"})
}
this.py = null;
setTimeout(()=>{
this.onStatus({})
}, 2000)
});
};
onClose() {
if (this.py) {
this.py.kill();
this.py = null;
}
}
setStatusCallback(callback) {
this.onStatus = callback;
}
}
module.exports = function(RED) {
function RAG(config) {
RED.nodes.createNode(this,config);
var node = this;
var pyNode = new PythonshellNode(config);
pyNode.setStatusCallback(node.status.bind(node));
var script = '';
node.on('input', function(msg) {
msg.path= "/data/main/py/RAG.py"
script = util.format(snippets.RAG, config.url, config.data_name, config.huggingface_token, config.embedding_model,
config.LLM_model, config.Pinecone_token, config.Pinecone_index, config.host, config.username, config.userpassword)
fs.writeFile(msg.path, script, function (err) {
if (err) {
node.error('Failed to write to file: ' + err.message);
return;
}
});
pyNode.onInput(msg, node, function(result) {
msg.payload = config.client_num;
node.send(msg);
}, function(error) {
node.error(error);
});
});
node.on('close', ()=>pyNode.onClose());
}
RED.nodes.registerType("RAG", RAG);
}

View File

@ -0,0 +1,19 @@
{
"name": "node-red-contrib-autoai-pipeline",
"version": "0.0.1",
"description": "A set of Node-RED node to run pipeline on kubeflow",
"scripts": {
"test": "./node_modules/mocha/bin/mocha"
},
"license": "ISC",
"keywords": [ "node-red" ],
"node-red": {
"nodes": {
"fl": "RAG/RAG.js"
}
},
"devDependencies": {
"mocha": "^5.0.4"
}
}

View File

@ -0,0 +1,342 @@
'use strict';
const RAG =
`
import kfp
from kfp import dsl
from kfp.components import func_to_container_op
from typing import NamedTuple
def RAG()-> NamedTuple('Outputs', [("output",str)]):
import torch
import requests
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Pinecone
from langchain_community.document_loaders import PyPDFLoader, OnlinePDFLoader
import os
import sys
from pinecone import Pinecone
from langchain_pinecone import PineconeVectorStore
from langchain.embeddings import HuggingFaceEmbeddings
import pinecone
from transformers import AutoTokenizer, AutoModelForCausalLM
from transformers import pipeline
from langchain import HuggingFacePipeline, PromptTemplate
from langchain.chains import RetrievalQA
from huggingface_hub import login
url = '%s'#Ex: "https://arxiv.org/pdf/2207.02696.pdf", a yolov7 pdf
data_name = '%s'#Ex: "/yolov7.pdf"
huggingface_token = '%s'
embedding_model = '%s'#Ex: "sentence-transformers/all-MiniLM-L6-v2"
LLM_model = '%s'#Ex: "openai-community/gpt2" or "meta-llama/Llama-2-7b-chat-hf"
Pinecone_token = '%s'
Pinecone_index = '%s'
r = requests.get(url, stream=True)
with open(data_name, 'wb') as fd:
fd.write(r.content)
loader = PyPDFLoader(data_name)
data = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=20)
docs = text_splitter.split_documents(data)
embeddings = HuggingFaceEmbeddings(model_name=embedding_model)
PINE_KEY = os.environ.get("PINECONE_API_KEY", Pinecone_token)
pc = Pinecone(api_key=Pinecone_token)
os.environ["PINECONE_API_KEY"] = Pinecone_token
index = pc.Index(Pinecone_index)
index_name = Pinecone_index
docsearch = PineconeVectorStore.from_documents(docs, embedding=embeddings, index_name=index_name)
login(huggingface_token)
tokenizer = AutoTokenizer.from_pretrained(LLM_model)
model = AutoModelForCausalLM.from_pretrained(LLM_model,
device_map='auto',
torch_dtype=torch.float16,
use_auth_token=True,
load_in_8bit=True # If you don't use GPU, comment this parameter
)
model = pipeline("text-generation",
model=model,
tokenizer= tokenizer,
torch_dtype=torch.bfloat16,
device_map="auto",
max_new_tokens = 512,
do_sample=True,
top_k=30,
num_return_sequences=3,
eos_token_id=tokenizer.eos_token_id
)
llm=HuggingFacePipeline(pipeline=model, model_kwargs={'temperature':0.1})
SYSTEM_PROMPT = """Use the following pieces of context to answer the question at the end.
If you don't know the answer, just say that you don't know, don't try to make up an answer."""
B_INST, E_INST = "[INST]", "[/INST]"
B_SYS, E_SYS = "<<SYS>>\\n", "\\n<</SYS>>\\n\\n"
SYSTEM_PROMPT = B_SYS + SYSTEM_PROMPT + E_SYS
instruction = """
{context}
Question: {question}
"""
template = B_INST + SYSTEM_PROMPT + instruction + E_INST
prompt = PromptTemplate(template=template, input_variables=["context", "question"])
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=docsearch.as_retriever(search_kwargs={"k":3}),
return_source_documents=True,
chain_type_kwargs={"prompt": prompt},)
question = questions
result = qa_chain(question)
print(result['result'])
output = result['result']
return(output)
RAG_op = func_to_container_op(RAG,packages_to_install = [
'requests',
'langchain',
'langchain-community',
'pypdf',
'pinecone-client',
'langchain_pinecone',
'sentence_transformers',
'googletrans==3.1.0a0',
'transformers',
'torch',
'bitsandbytes',
'accelerate',
'urllib3==1.26.15'
])
@dsl.pipeline()
def rag_pipeline():
rag_task = RAG_op().set_gpu_limit(1)
from kfp import compiler
compiler.Compiler().compile(rag_pipeline, 'RAG_pipeline.yaml')
import time
import kfp_server_api
import os
import requests
import string
import random
import json
from kfp import dsl
from kfp.components import func_to_container_op, OutputPath
from kfp_server_api.rest import ApiException
from pprint import pprint
from kfp_login import get_istio_auth_session
from kfp_namespace import retrieve_namespaces
host = "%s"
username = "%s"
password = "%s"
auth_session = get_istio_auth_session(
url=host,
username=username,
password=password
)
# The client must configure the authentication and authorization parameters
# in accordance with the API server security policy.
# Examples for each auth method are provided below, use the example that
# satisfies your auth use case.
# Configure API key authorization: Bearer
configuration = kfp_server_api.Configuration(
host = os.path.join(host, "pipeline"),
)
configuration.debug = True
namespaces = retrieve_namespaces(host, auth_session)
#print("available namespace: {}".format(namespaces))
def random_suffix() :
return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10))
# Enter a context with an instance of the API client
with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client:
# Create an instance of the Experiment API class
experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client)
name="experiment-" + random_suffix()
description="This is a experiment for RAG."
resource_reference_key_id = namespaces[0]
resource_references=[kfp_server_api.models.ApiResourceReference(
key=kfp_server_api.models.ApiResourceKey(
type=kfp_server_api.models.ApiResourceType.NAMESPACE,
id=resource_reference_key_id
),
relationship=kfp_server_api.models.ApiRelationship.OWNER
)]
body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created.
try:
# Creates a new experiment.
experiment_api_response = experiment_api_instance.create_experiment(body)
experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved.
except ApiException as e:
print("Exception when calling ExperimentServiceApi->create_experiment: %s\\n" % e)
# Create an instance of the pipeline API class
api_instance = kfp_server_api.PipelineUploadServiceApi(api_client)
uploadfile="RAG_pipeline.yaml"
name='pipeline-' + random_suffix()
description="This is a RAG pipline."
try:
pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description)
pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved.
except ApiException as e:
print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\\n" % e)
# Create an instance of the run API class
run_api_instance = kfp_server_api.RunServiceApi(api_client)
display_name = 'RAG' + random_suffix()
description = "This is a RAG run."
pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id)
resource_reference_key_id = namespaces[0]
resource_references=[kfp_server_api.models.ApiResourceReference(
key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT),
relationship=kfp_server_api.models.ApiRelationship.OWNER )]
body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun |
try:
# Creates a new run.
run_api_response = run_api_instance.create_run(body)
run_id = run_api_response.run.id # str | The ID of the run to be retrieved.
except ApiException as e:
print("Exception when calling RunServiceApi->create_run: %s\\n" % e)
Completed_flag = False
polling_interval = 10 # Time in seconds between polls
while not Completed_flag:
try:
time.sleep(1)
# Finds a specific run by ID.
api_instance = run_api_instance.get_run(run_id)
output = api_instance.pipeline_runtime.workflow_manifest
output = json.loads(output)
#print(output)
try:
nodes = output['status']['nodes']
conditions = output['status']['conditions'] # Comfirm completion.
except KeyError:
nodes = {}
conditions = []
output_value = None
Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False
'''''
def find_all_keys(node):
if isinstance(node, dict):
for key in node.keys():
print("Key:", key)
find_all_keys(node[key])
elif isinstance(node, list):
for item in node:
find_all_keys(item)
# Call the function with your JSON data
find_all_keys(output)
'''''
except ApiException as e:
print("Exception when calling RunServiceApi->get_run: %s\\n" % e)
break
if not Completed_flag:
print("Pipeline is still running. Waiting...")
time.sleep(polling_interval-1)
found_final_pvc_name = False # Add a variable to track if the PVC name has been found
def find_final_pvc_name(node):
global found_final_pvc_name # Declare the variable as global
if not found_final_pvc_name: # If the PVC name has not been found yet
if isinstance(node, dict):
if 'parameters' in node:
parameters = node['parameters']
for parameter in parameters:
if 'name' in parameter and parameter['name'] == 'mypvc-name':
value = parameter.get('value')
if value and not value.startswith('{{') and not value.endswith('}}'):
found_final_pvc_name = True # Set to True after finding the PVC name
print("mypvc-name:", value)
return value
for key, value in node.items():
result = find_final_pvc_name(value)
if result:
return result
elif isinstance(node, list):
for item in node:
result = find_final_pvc_name(item)
if result:
return result
return None
find_final_pvc_name(output) # Call the function to find final_pvc_name
found_model_func_accuracy = False
def find_model_func_accuracy(node):
global found_model_func_accuracy # Declare the variable as global
if not found_model_func_accuracy: # If the model-func-accuracy has not been found yet
if isinstance(node, dict):
if 'parameters' in node:
parameters = node['parameters']
for parameter in parameters:
if 'name' in parameter and parameter['name'] == 'model-func-accuracy':
value = parameter.get('value')
if value and not value.startswith('{{') and not value.endswith('}}'):
found_model_func_accuracy = True # Set to True after finding model-func-accuracy
print("Model Accuracy:", value)
return value
for key, value in node.items():
result = find_model_func_accuracy(value)
if result:
return result
elif isinstance(node, list):
for item in node:
result = find_model_func_accuracy(item)
if result:
return result
return None
find_model_func_accuracy(output)
`;
module.exports = {
RAG
};

View File

@ -0,0 +1,6 @@
{
"name": "node-red-project",
"description": "A Node-RED Project",
"version": "0.0.1",
"private": true
}

View File

@ -0,0 +1,59 @@
from __future__ import print_function
import string
import random
import time
import kfp_server_api
import os
import requests
import kfp
import json
from kfp_server_api.rest import ApiException
from pprint import pprint
from kfp_login import get_istio_auth_session
from kfp_namespace import retrieve_namespaces
host = os.getenv("KUBEFLOW_HOST")
username = os.getenv("KUBEFLOW_USERNAME")
password = os.getenv("KUBEFLOW_PASSWORD")
auth_session = get_istio_auth_session(
url=host,
username=username,
password=password
)
# The client must configure the authentication and authorization parameters
# in accordance with the API server security policy.
# Examples for each auth method are provided below, use the example that
# satisfies your auth use case.
# Configure API key authorization: Bearer
configuration = kfp_server_api.Configuration(
host = os.path.join(host, "pipeline"),
)
configuration.debug = True
namespaces = retrieve_namespaces(host, auth_session)
#print("available namespace: {}".format(namespaces))
# Enter a context with an instance of the API client
with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client:
# Create an instance of the API class
api_instance = kfp_server_api.ExperimentServiceApi(api_client)
name="<change yours>" # str | The ID of the name to be create.
description='<change yours>' # str | The description experiment.
resource_reference_key_id = namespaces[0]
resource_references=[kfp_server_api.models.ApiResourceReference(
key=kfp_server_api.models.ApiResourceKey(
type=kfp_server_api.models.ApiResourceType.NAMESPACE,
id=resource_reference_key_id
),
relationship=kfp_server_api.models.ApiRelationship.OWNER
)]
body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created.
try:
# Creates a new experiment.
api_response = api_instance.create_experiment(body)
pprint(api_response)
except ApiException as e:
print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e)

View File

@ -0,0 +1,58 @@
from __future__ import print_function
import string
import random
import time
import kfp_server_api
import os
import requests
import kfp
import json
from pprint import pprint
from kfp_server_api.rest import ApiException
from kfp_login import get_istio_auth_session
from kfp_namespace import retrieve_namespaces
host = os.getenv("KUBEFLOW_HOST")
username = os.getenv("KUBEFLOW_USERNAME")
password = os.getenv("KUBEFLOW_PASSWORD")
auth_session = get_istio_auth_session(
url=host,
username=username,
password=password
)
# The client must configure the authentication and authorization parameters
# in accordance with the API server security policy.
# Examples for each auth method are provided below, use the example that
# satisfies your auth use case.
# Configure API key authorization: Bearer
configuration = kfp_server_api.Configuration(
host = os.path.join(host, "pipeline"),
)
configuration.debug = True
namespaces = retrieve_namespaces(host, auth_session)
#print("available namespace: {}".format(namespaces))
# Enter a context with an instance of the API client
with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client:
# Create an instance of the API class
api_instance = kfp_server_api.RunServiceApi(api_client)
pipeline_id = '<change yours>' # str | The ID of the pipeline.
experiment_id = '<change yours>' # str | The ID of the experiment.
display_name = '<change yours>' # str | The name of the run to be create.
description = '<change yours>' # str | The description of run.
pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id)
resource_reference_key_id = namespaces[0]
resource_references=[kfp_server_api.models.ApiResourceReference(
key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT),
relationship=kfp_server_api.models.ApiRelationship.OWNER )]
body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun |
try:
# Creates a new run.
api_response = api_instance.create_run(body)
pprint(api_response)
except ApiException as e:
print("Exception when calling RunServiceApi->create_run: %s\n" % e)

View File

@ -0,0 +1,51 @@
from __future__ import print_function
import string
import random
import time
import kfp_server_api
import os
import requests
import kfp
import json
from kfp_server_api.rest import ApiException
from pprint import pprint
from kfp_login import get_istio_auth_session
from kfp_namespace import retrieve_namespaces
host = os.getenv("KUBEFLOW_HOST")
username = os.getenv("KUBEFLOW_USERNAME")
password = os.getenv("KUBEFLOW_PASSWORD")
auth_session = get_istio_auth_session(
url=host,
username=username,
password=password
)
# The client must configure the authentication and authorization parameters
# in accordance with the API server security policy.
# Examples for each auth method are provided below, use the example that
# satisfies your auth use case.
# Configure API key authorization: Bearer
configuration = kfp_server_api.Configuration(
host = os.path.join(host, "pipeline"),
)
configuration.debug = True
namespaces = retrieve_namespaces(host, auth_session)
#print("available namespace: {}".format(namespaces))
# Enter a context with an instance of the API client
with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client:
# Create an instance of the API class
api_instance = kfp_server_api.ExperimentServiceApi(api_client)
experiment_id = '<change yours>' # str | The ID of the experiment to be deleted.
try:
# Deletes an experiment without deleting the experiment's runs and recurring runs.
# To avoid unexpected behaviors, delete an experiment's runs and recurring runs before deleting the experiment.
api_response = api_instance.delete_experiment(experiment_id)
pprint(api_response)
except ApiException as e:
print("Exception when calling ExperimentServiceApi->delete_experiment: %s\n" % e)

View File

@ -0,0 +1,50 @@
from __future__ import print_function
import string
import random
import time
import kfp_server_api
import os
import requests
import kfp
import json
from kfp_server_api.rest import ApiException
from pprint import pprint
from kfp_login import get_istio_auth_session
from kfp_namespace import retrieve_namespaces
host = os.getenv("KUBEFLOW_HOST")
username = os.getenv("KUBEFLOW_USERNAME")
password = os.getenv("KUBEFLOW_PASSWORD")
auth_session = get_istio_auth_session(
url=host,
username=username,
password=password
)
# The client must configure the authentication and authorization parameters
# in accordance with the API server security policy.
# Examples for each auth method are provided below, use the example that
# satisfies your auth use case.
# Configure API key authorization: Bearer
configuration = kfp_server_api.Configuration(
host = os.path.join(host, "pipeline"),
)
configuration.debug = True
namespaces = retrieve_namespaces(host, auth_session)
#print("available namespace: {}".format(namespaces))
# Enter a context with an instance of the API client
with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client:
# Create an instance of the API class
api_instance = kfp_server_api.PipelineServiceApi(api_client)
id = '<change yours>' # str | The ID of the pipeline to be deleted.
try:
# Deletes a pipeline and its pipeline versions.
api_response = api_instance.delete_pipeline(id)
pprint(api_response)
except ApiException as e:
print("Exception when calling PipelineServiceApi->delete_pipeline: %s\n" % e)

View File

@ -0,0 +1,50 @@
from __future__ import print_function
import string
import random
import time
import kfp_server_api
import os
import requests
import kfp
import json
from kfp_server_api.rest import ApiException
from pprint import pprint
from kfp_login import get_istio_auth_session
from kfp_namespace import retrieve_namespaces
host = os.getenv("KUBEFLOW_HOST")
username = os.getenv("KUBEFLOW_USERNAME")
password = os.getenv("KUBEFLOW_PASSWORD")
auth_session = get_istio_auth_session(
url=host,
username=username,
password=password
)
# The client must configure the authentication and authorization parameters
# in accordance with the API server security policy.
# Examples for each auth method are provided below, use the example that
# satisfies your auth use case.
# Configure API key authorization: Bearer
configuration = kfp_server_api.Configuration(
host = os.path.join(host, "pipeline"),
)
configuration.debug = True
namespaces = retrieve_namespaces(host, auth_session)
#print("available namespace: {}".format(namespaces))
# Enter a context with an instance of the API client
with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client:
# Create an instance of the API class
api_instance = kfp_server_api.RunServiceApi(api_client)
id = '<change yours>' # str | The ID of the run to be deleted.
try:
# Deletes a run.
api_response = api_instance.delete_run(id)
pprint(api_response)
except ApiException as e:
print("Exception when calling RunServiceApi->delete_run: %s\n" % e)

View File

@ -0,0 +1,64 @@
from __future__ import print_function
import time
import kfp_server_api
import os
import requests
from kfp_server_api.rest import ApiException
from pprint import pprint
from kfp_login import get_istio_auth_session
from kfp_namespace import retrieve_namespaces
import json
host = os.getenv("KUBEFLOW_HOST")
username = os.getenv("KUBEFLOW_USERNAME")
password = os.getenv("KUBEFLOW_PASSWORD")
auth_session = get_istio_auth_session(
url=host,
username=username,
password=password
)
# The client must configure the authentication and authorization parameters
# in accordance with the API server security policy.
# Examples for each auth method are provided below, use the example that
# satisfies your auth use case.
# Configure API key authorization: Bearer
configuration = kfp_server_api.Configuration(
host = os.path.join(host, "pipeline"),
)
configuration.debug = True
namespaces = retrieve_namespaces(host, auth_session)
#print("available namespace: {}".format(namespaces))
# Enter a context with an instance of the API client
with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client:
# Create an instance of the API class
api_instance = kfp_server_api.RunServiceApi(api_client)
run_id = '<change yours>' # str | The ID of the run to be retrieved.
try:
# Finds a specific run by ID.
api_response = api_instance.get_run(run_id)
output = api_response.pipeline_runtime.workflow_manifest
output = json.loads(output)
nodes = output['status']['nodes']
conditions = output['status']['conditions'] # Comfirm completion.
output_value = None
for node_id, node in nodes.items():
if 'inputs' in node and 'parameters' in node['inputs']:
for parameter in node['inputs']['parameters']:
if parameter['name'] == 'decision-tree-classifier-Accuracy':
output_value = parameter['value']
break
if output_value is not None:
print(f"Decision Tree Classifier Accuracy: {output_value}")
else:
print("Parameter not found.")
except ApiException as e:
print("Exception when calling RunServiceApi->get_run: %s\n" % e)

View File

@ -0,0 +1,93 @@
import re
from urllib.parse import urlsplit
import requests
# NOTE: the following code is referred from https://github.com/kubeflow/website/issues/2916
def get_istio_auth_session(url: str, username: str, password: str) -> dict:
"""
Determine if the specified URL is secured by Dex and try to obtain a session cookie.
WARNING: only Dex `staticPasswords` and `LDAP` authentication are currently supported
(we default default to using `staticPasswords` if both are enabled)
:param url: Kubeflow server URL, including protocol
:param username: Dex `staticPasswords` or `LDAP` username
:param password: Dex `staticPasswords` or `LDAP` password
:return: auth session information
"""
# define the default return object
auth_session = {
"endpoint_url": url, # KF endpoint URL
"redirect_url": None, # KF redirect URL, if applicable
"dex_login_url": None, # Dex login URL (for POST of credentials)
"is_secured": None, # True if KF endpoint is secured
"session_cookie": None # Resulting session cookies in the form "key1=value1; key2=value2"
}
# use a persistent session (for cookies)
with requests.Session() as s:
################
# Determine if Endpoint is Secured
################
resp = s.get(url, allow_redirects=True)
if resp.status_code != 200:
raise RuntimeError(
f"HTTP status code '{resp.status_code}' for GET against: {url}"
)
auth_session["redirect_url"] = resp.url
# if we were NOT redirected, then the endpoint is UNSECURED
if len(resp.history) == 0:
auth_session["is_secured"] = False
return auth_session
else:
auth_session["is_secured"] = True
################
# Get Dex Login URL
################
redirect_url_obj = urlsplit(auth_session["redirect_url"])
# if we are at `/auth?=xxxx` path, we need to select an auth type
if re.search(r"/auth$", redirect_url_obj.path):
# default to "staticPasswords" auth type
redirect_url_obj = redirect_url_obj._replace(
path=re.sub(r"/auth$", "/auth/local", redirect_url_obj.path)
)
# if we are at `/auth/xxxx/login` path, then no further action is needed (we can use it for login POST)
if re.search(r"/auth/.*/login$", redirect_url_obj.path):
auth_session["dex_login_url"] = redirect_url_obj.geturl()
# else, we need to be redirected to the actual login page
else:
# this GET should redirect us to the `/auth/xxxx/login` path
resp = s.get(redirect_url_obj.geturl(), allow_redirects=True)
if resp.status_code != 200:
raise RuntimeError(
f"HTTP status code '{resp.status_code}' for GET against: {redirect_url_obj.geturl()}"
)
# set the login url
auth_session["dex_login_url"] = resp.url
################
# Attempt Dex Login
################
resp = s.post(
auth_session["dex_login_url"],
data={"login": username, "password": password},
allow_redirects=True
)
if len(resp.history) == 0:
raise RuntimeError(
f"Login credentials were probably invalid - "
f"No redirect after POST to: {auth_session['dex_login_url']}"
)
# store the session cookies in a "key1=value1; key2=value2" string
auth_session["session_cookie"] = "; ".join([f"{c.name}={c.value}" for c in s.cookies])
return auth_session

View File

@ -0,0 +1,19 @@
import os
import requests
from typing import TypedDict
def retrieve_namespaces(host: str, auth_session: TypedDict) -> str:
workgroup_endpoint = os.path.join(host, "api/workgroup/env-info")
cookies = {}
cookie_tokens = auth_session["session_cookie"].split("=")
print(cookie_tokens[0])
cookies[cookie_tokens[0]]=cookie_tokens[1]
resp = requests.get(workgroup_endpoint, cookies=cookies)
if resp.status_code != 200:
raise RuntimeError(
f"HTTP status code '{resp.status_code}' for GET against: {workgroup_endpoint}"
)
return [ns["namespace"] for ns in resp.json()["namespaces"] if
ns["role"]=="owner"]

View File

@ -0,0 +1,44 @@
from __future__ import print_function
import time
import kfp_server_api
import os
import requests
from kfp_server_api.rest import ApiException
from pprint import pprint
from kfp_login import get_istio_auth_session
from kfp_namespace import retrieve_namespaces
host = os.getenv("KUBEFLOW_HOST")
username = os.getenv("KUBEFLOW_USERNAME")
password = os.getenv("KUBEFLOW_PASSWORD")
auth_session = get_istio_auth_session(
url=host,
username=username,
password=password
)
# The client must configure the authentication and authorization parameters
# in accordance with the API server security policy.
# Examples for each auth method are provided below, use the example that
# satisfies your auth use case.
# Configure API key authorization: Bearer
configuration = kfp_server_api.Configuration(
host = os.path.join(host, "pipeline"),
)
configuration.debug = True
namespaces = retrieve_namespaces(host, auth_session)
print("available namespace: {}".format(namespaces))
# Enter a context with an instance of the API client
with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client:
# Create an instance of the API class
api_instance = kfp_server_api.ExperimentServiceApi(api_client)
resource_reference_key_type = "NAMESPACE"
resource_reference_key_id = namespaces[0]
list_experiment_response = api_instance.list_experiment(resource_reference_key_type=resource_reference_key_type, resource_reference_key_id=resource_reference_key_id)
for experiment in list_experiment_response.experiments:
pprint(experiment)

View File

@ -0,0 +1,43 @@
from __future__ import print_function
import string
import time
import kfp_server_api
import os
import requests
import kfp
import json
from pprint import pprint
from kfp_server_api.rest import ApiException
from kfp_login import get_istio_auth_session
from kfp_namespace import retrieve_namespaces
host = os.getenv("KUBEFLOW_HOST")
username = os.getenv("KUBEFLOW_USERNAME")
password = os.getenv("KUBEFLOW_PASSWORD")
auth_session = get_istio_auth_session(
url=host,
username=username,
password=password
)
# The client must configure the authentication and authorization parameters
# in accordance with the API server security policy.
# Examples for each auth method are provided below, use the example that
# satisfies your auth use case.
# Configure API key authorization: Bearer
configuration = kfp_server_api.Configuration(
host = os.path.join(host, "pipeline"),
)
configuration.debug = True
namespaces = retrieve_namespaces(host, auth_session)
#print("available namespace: {}".format(namespaces))
# Enter a context with an instance of the API client
with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client:
api_instance = kfp_server_api.PipelineServiceApi(api_client)
list_pipeline_response = api_instance.list_pipelines()
for pipelines in list_pipeline_response.pipelines:
print(pipelines)

View File

@ -0,0 +1,52 @@
from __future__ import print_function
import string
import random
import time
import kfp_server_api
import os
import requests
from kfp_server_api.rest import ApiException
from kfp_login import get_istio_auth_session
from kfp_namespace import retrieve_namespaces
host = os.getenv("KUBEFLOW_HOST")
username = os.getenv("KUBEFLOW_USERNAME")
password = os.getenv("KUBEFLOW_PASSWORD")
auth_session = get_istio_auth_session(
url=host,
username=username,
password=password
)
# The client must configure the authentication and authorization parameters
# in accordance with the API server security policy.
# Examples for each auth method are provided below, use the example that
# satisfies your auth use case.
# Configure API key authorization: Bearer
configuration = kfp_server_api.Configuration(
host = os.path.join(host, "pipeline"),
)
configuration.debug = True
namespaces = retrieve_namespaces(host, auth_session)
print("available namespace: {}".format(namespaces))
def random_suffix() -> string:
return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10))
# Enter a context with an instance of the API client
with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client:
# Create an instance of the API class
api_instance = kfp_server_api.PipelineUploadServiceApi(api_client)
uploadfile='<change yours>' # The yaml file in your local path.
name='pipeline-' + random_suffix()
description='<change yours>' # str | The description of pipeline.
try:
api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description)
print(api_response)
except ApiException as e:
print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e)

View File

@ -0,0 +1,205 @@
from __future__ import print_function
import re
import kfp
import time
import kfp_server_api
import os
import requests
import string
import random
import json
from kfp import dsl
from kfp import components
from kfp.components import func_to_container_op, OutputPath
from kfp_server_api.rest import ApiException
from pprint import pprint
from kfp_login import get_istio_auth_session
from kfp_namespace import retrieve_namespaces
host = ""
username = ""
password = ""
auth_session = get_istio_auth_session(
url=host,
username=username,
password=password
)
# The client must configure the authentication and authorization parameters
# in accordance with the API server security policy.
# Examples for each auth method are provided below, use the example that
# satisfies your auth use case.
# Configure API key authorization: Bearer
configuration = kfp_server_api.Configuration(
host = os.path.join(host, "pipeline"),
)
configuration.debug = True
namespaces = retrieve_namespaces(host, auth_session)
#print("available namespace: {}".format(namespaces))
namespaces = str(namespaces)
namespaces = namespaces[2:-2]
#print(namespaces)
kfserving_op = components.load_component_from_url('https://raw.githubusercontent.com/kubeflow/pipelines/master/components/kserve/component.yaml')
@dsl.pipeline(
name='KFServing pipeline',
description='A pipeline for KFServing with PVC.'
)
def kfservingPipeline(
action='apply',
namespace=namespaces,
pvc_name='undefined', # change pvc_name
model_name='model01'): # change model_name
# specify the model dir located on pvc
model_pvc_uri = 'pvc://{}/{}/'.format(pvc_name, model_name)
# create inference service resource named by model_name
isvc_yaml = '''
apiVersion: "serving.kserve.io/v1beta1"
kind: "InferenceService"
metadata:
name: {}
namespace: {}
spec:
predictor:
sklearn:
storageUri: {}
resources:
limits:
cpu: "100m"
requests:
cpu: "100m"
'''.format(model_name, namespace, model_pvc_uri)
kfserving = kfserving_op(
action=action,
inferenceservice_yaml=isvc_yaml,
)
kfserving.set_cpu_request("500m").set_cpu_limit("500m")
return([isvc_yaml])
# Compile pipeline
kfp.compiler.Compiler().compile(kfservingPipeline, 'sklearn-kserve.yaml')
host = "http://140.128.102.163:31740"
username = "kubeflow02@gmail.com"
password = "tkiizd"
auth_session = get_istio_auth_session(
url=host,
username=username,
password=password
)
# The client must configure the authentication and authorization parameters
# in accordance with the API server security policy.
# Examples for each auth method are provided below, use the example that
# satisfies your auth use case.
# Configure API key authorization: Bearer
configuration = kfp_server_api.Configuration(
host = os.path.join(host, "pipeline"),
)
configuration.debug = True
namespaces = retrieve_namespaces(host, auth_session)
#print("available namespace: {}".format(namespaces))
def random_suffix() :
return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10))
# Enter a context with an instance of the API client
with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client:
# Create an instance of the Experiment API class
experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client)
name="experiment-" + random_suffix()
description="This is a experiment for only_kfserving."
resource_reference_key_id = namespaces[0]
resource_references=[kfp_server_api.models.ApiResourceReference(
key=kfp_server_api.models.ApiResourceKey(
type=kfp_server_api.models.ApiResourceType.NAMESPACE,
id=resource_reference_key_id
),
relationship=kfp_server_api.models.ApiRelationship.OWNER
)]
body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created.
try:
# Creates a new experiment.
experiment_api_response = experiment_api_instance.create_experiment(body)
experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved.
except ApiException as e:
print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e)
# Create an instance of the pipeline API class
api_instance = kfp_server_api.PipelineUploadServiceApi(api_client)
uploadfile='sklearn-kserve.yaml'
name='pipeline-' + random_suffix()
description="This is a only_kfserving pipline."
try:
pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description)
pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved.
except ApiException as e:
print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e)
# Create an instance of the run API class
run_api_instance = kfp_server_api.RunServiceApi(api_client)
display_name = 'run_only_kfserving' + random_suffix()
description = "This is a only_kfserving run."
pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id)
resource_reference_key_id = namespaces[0]
resource_references=[kfp_server_api.models.ApiResourceReference(
key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT),
relationship=kfp_server_api.models.ApiRelationship.OWNER )]
body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun |
try:
# Creates a new run.
run_api_response = run_api_instance.create_run(body)
run_id = run_api_response.run.id # str | The ID of the run to be retrieved.
except ApiException as e:
print("Exception when calling RunServiceApi->create_run: %s\n" % e)
Completed_flag = False
polling_interval = 10 # Time in seconds between polls
while not Completed_flag:
try:
time.sleep(1)
# Finds a specific run by ID.
api_instance = run_api_instance.get_run(run_id)
output = api_instance.pipeline_runtime.workflow_manifest
output = json.loads(output)
try:
nodes = output['status']['nodes']
conditions = output['status']['conditions'] # Confirm completion.
except KeyError:
nodes = {}
conditions = []
Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False
except ApiException as e:
print("Exception when calling RunServiceApi->get_run: %s\n" % e)
break
if not Completed_flag:
print("Pipeline is still running. Waiting...")
time.sleep(polling_interval-1)
else:
print("Successful Deployment!")

View File

@ -0,0 +1,93 @@
import re
from urllib.parse import urlsplit
import requests
# NOTE: the following code is referred from https://github.com/kubeflow/website/issues/2916
def get_istio_auth_session(url: str, username: str, password: str) -> dict:
"""
Determine if the specified URL is secured by Dex and try to obtain a session cookie.
WARNING: only Dex `staticPasswords` and `LDAP` authentication are currently supported
(we default default to using `staticPasswords` if both are enabled)
:param url: Kubeflow server URL, including protocol
:param username: Dex `staticPasswords` or `LDAP` username
:param password: Dex `staticPasswords` or `LDAP` password
:return: auth session information
"""
# define the default return object
auth_session = {
"endpoint_url": url, # KF endpoint URL
"redirect_url": None, # KF redirect URL, if applicable
"dex_login_url": None, # Dex login URL (for POST of credentials)
"is_secured": None, # True if KF endpoint is secured
"session_cookie": None # Resulting session cookies in the form "key1=value1; key2=value2"
}
# use a persistent session (for cookies)
with requests.Session() as s:
################
# Determine if Endpoint is Secured
################
resp = s.get(url, allow_redirects=True)
if resp.status_code != 200:
raise RuntimeError(
f"HTTP status code '{resp.status_code}' for GET against: {url}"
)
auth_session["redirect_url"] = resp.url
# if we were NOT redirected, then the endpoint is UNSECURED
if len(resp.history) == 0:
auth_session["is_secured"] = False
return auth_session
else:
auth_session["is_secured"] = True
################
# Get Dex Login URL
################
redirect_url_obj = urlsplit(auth_session["redirect_url"])
# if we are at `/auth?=xxxx` path, we need to select an auth type
if re.search(r"/auth$", redirect_url_obj.path):
# default to "staticPasswords" auth type
redirect_url_obj = redirect_url_obj._replace(
path=re.sub(r"/auth$", "/auth/local", redirect_url_obj.path)
)
# if we are at `/auth/xxxx/login` path, then no further action is needed (we can use it for login POST)
if re.search(r"/auth/.*/login$", redirect_url_obj.path):
auth_session["dex_login_url"] = redirect_url_obj.geturl()
# else, we need to be redirected to the actual login page
else:
# this GET should redirect us to the `/auth/xxxx/login` path
resp = s.get(redirect_url_obj.geturl(), allow_redirects=True)
if resp.status_code != 200:
raise RuntimeError(
f"HTTP status code '{resp.status_code}' for GET against: {redirect_url_obj.geturl()}"
)
# set the login url
auth_session["dex_login_url"] = resp.url
################
# Attempt Dex Login
################
resp = s.post(
auth_session["dex_login_url"],
data={"login": username, "password": password},
allow_redirects=True
)
if len(resp.history) == 0:
raise RuntimeError(
f"Login credentials were probably invalid - "
f"No redirect after POST to: {auth_session['dex_login_url']}"
)
# store the session cookies in a "key1=value1; key2=value2" string
auth_session["session_cookie"] = "; ".join([f"{c.name}={c.value}" for c in s.cookies])
return auth_session

View File

@ -0,0 +1,19 @@
import os
import requests
from typing import TypedDict
def retrieve_namespaces(host: str, auth_session: TypedDict) -> str:
workgroup_endpoint = os.path.join(host, "api/workgroup/env-info")
cookies = {}
cookie_tokens = auth_session["session_cookie"].split("=")
print(cookie_tokens[0])
cookies[cookie_tokens[0]]=cookie_tokens[1]
resp = requests.get(workgroup_endpoint, cookies=cookies)
if resp.status_code != 200:
raise RuntimeError(
f"HTTP status code '{resp.status_code}' for GET against: {workgroup_endpoint}"
)
return [ns["namespace"] for ns in resp.json()["namespaces"] if
ns["role"]=="owner"]

View File

@ -0,0 +1,27 @@
import os
import subprocess
def python3_version():
return subprocess.check_call(["python3", "--version"])
def which(command):
return subprocess.check_call(["which", command])
def pip3_install_requirements():
return subprocess.check_call(["pip3", "install", "-r", "requirements.txt",
"--user"])
def pip3_install_kfp_sever_api():
return subprocess.check_call(["pip3", "install",
"git+https://github.com/kubeflow/pipelines.git@1.8.19#subdirectory=backend/api/python_http_client",
"--user"])
def pip3_install_kfp():
return subprocess.check_call(["pip3", "install", "kfp==1.7", "--user"])
python3_version()
pip3_install_requirements()
#pip3_install_kfp_sever_api()
pip3_install_kfp()
print("done")

View File

@ -0,0 +1,93 @@
import re
from urllib.parse import urlsplit
import requests
# NOTE: the following code is referred from https://github.com/kubeflow/website/issues/2916
def get_istio_auth_session(url: str, username: str, password: str) -> dict:
"""
Determine if the specified URL is secured by Dex and try to obtain a session cookie.
WARNING: only Dex `staticPasswords` and `LDAP` authentication are currently supported
(we default default to using `staticPasswords` if both are enabled)
:param url: Kubeflow server URL, including protocol
:param username: Dex `staticPasswords` or `LDAP` username
:param password: Dex `staticPasswords` or `LDAP` password
:return: auth session information
"""
# define the default return object
auth_session = {
"endpoint_url": url, # KF endpoint URL
"redirect_url": None, # KF redirect URL, if applicable
"dex_login_url": None, # Dex login URL (for POST of credentials)
"is_secured": None, # True if KF endpoint is secured
"session_cookie": None # Resulting session cookies in the form "key1=value1; key2=value2"
}
# use a persistent session (for cookies)
with requests.Session() as s:
################
# Determine if Endpoint is Secured
################
resp = s.get(url, allow_redirects=True)
if resp.status_code != 200:
raise RuntimeError(
f"HTTP status code '{resp.status_code}' for GET against: {url}"
)
auth_session["redirect_url"] = resp.url
# if we were NOT redirected, then the endpoint is UNSECURED
if len(resp.history) == 0:
auth_session["is_secured"] = False
return auth_session
else:
auth_session["is_secured"] = True
################
# Get Dex Login URL
################
redirect_url_obj = urlsplit(auth_session["redirect_url"])
# if we are at `/auth?=xxxx` path, we need to select an auth type
if re.search(r"/auth$", redirect_url_obj.path):
# default to "staticPasswords" auth type
redirect_url_obj = redirect_url_obj._replace(
path=re.sub(r"/auth$", "/auth/local", redirect_url_obj.path)
)
# if we are at `/auth/xxxx/login` path, then no further action is needed (we can use it for login POST)
if re.search(r"/auth/.*/login$", redirect_url_obj.path):
auth_session["dex_login_url"] = redirect_url_obj.geturl()
# else, we need to be redirected to the actual login page
else:
# this GET should redirect us to the `/auth/xxxx/login` path
resp = s.get(redirect_url_obj.geturl(), allow_redirects=True)
if resp.status_code != 200:
raise RuntimeError(
f"HTTP status code '{resp.status_code}' for GET against: {redirect_url_obj.geturl()}"
)
# set the login url
auth_session["dex_login_url"] = resp.url
################
# Attempt Dex Login
################
resp = s.post(
auth_session["dex_login_url"],
data={"login": username, "password": password},
allow_redirects=True
)
if len(resp.history) == 0:
raise RuntimeError(
f"Login credentials were probably invalid - "
f"No redirect after POST to: {auth_session['dex_login_url']}"
)
# store the session cookies in a "key1=value1; key2=value2" string
auth_session["session_cookie"] = "; ".join([f"{c.name}={c.value}" for c in s.cookies])
return auth_session

View File

@ -0,0 +1,19 @@
import os
import requests
from typing import TypedDict
def retrieve_namespaces(host: str, auth_session: TypedDict) -> str:
workgroup_endpoint = os.path.join(host, "api/workgroup/env-info")
cookies = {}
cookie_tokens = auth_session["session_cookie"].split("=")
print(cookie_tokens[0])
cookies[cookie_tokens[0]]=cookie_tokens[1]
resp = requests.get(workgroup_endpoint, cookies=cookies)
if resp.status_code != 200:
raise RuntimeError(
f"HTTP status code '{resp.status_code}' for GET against: {workgroup_endpoint}"
)
return [ns["namespace"] for ns in resp.json()["namespaces"] if
ns["role"]=="owner"]

View File

@ -0,0 +1,131 @@
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: only-decision-tree-
annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.20, pipelines.kubeflow.org/pipeline_compilation_time: '2023-04-28T21:42:00.682134',
pipelines.kubeflow.org/pipeline_spec: '{"description": "Applies Decision Tree
for classification problem.", "name": "only_decision_tree"}'}
labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.20}
spec:
entrypoint: only-decision-tree
templates:
- name: decision-tree-classifier
container:
args: []
command: [python, decision_tree.py, --data, /tmp/inputs/Data/data, --accuracy,
/tmp/outputs/Accuracy/data]
image: lightnighttw/kubeflow:decision_tree_v2
resources:
limits:
cpu: 2
inputs:
artifacts:
- {name: download-data-function-Data, path: /tmp/inputs/Data/data}
outputs:
parameters:
- name: decision-tree-classifier-Accuracy
valueFrom: {path: /tmp/outputs/Accuracy/data}
artifacts:
- {name: decision-tree-classifier-Accuracy, path: /tmp/outputs/Accuracy/data}
metadata:
labels:
pipelines.kubeflow.org/kfp_sdk_version: 1.8.20
pipelines.kubeflow.org/pipeline-sdk-type: kfp
pipelines.kubeflow.org/enable_caching: "true"
annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Trains
a decision tree classifier", "implementation": {"container": {"command":
["python", "decision_tree.py", "--data", {"inputPath": "Data"}, "--accuracy",
{"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:decision_tree_v2"}},
"inputs": [{"description": "Path where data is stored.", "name": "Data",
"type": "LocalPath"}], "name": "Decision Tree classifier", "outputs": [{"description":
"Accuracy metric", "name": "Accuracy", "type": "Float"}]}', pipelines.kubeflow.org/component_ref: '{"digest":
"c5c232a9654213b3b222693949b71a5d561d04ed09543c20b6f8f2eab651ae0b", "url":
"decision_tree/decision_tree.yaml"}'}
- name: download-data-function
container:
args: []
command: [python, download_data.py, --data, /tmp/outputs/Data/data]
image: lightnighttw/kubeflow:download_data
resources:
limits:
cpu: 2
outputs:
artifacts:
- {name: download-data-function-Data, path: /tmp/outputs/Data/data}
metadata:
labels:
pipelines.kubeflow.org/kfp_sdk_version: 1.8.20
pipelines.kubeflow.org/pipeline-sdk-type: kfp
pipelines.kubeflow.org/enable_caching: "true"
annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Download
toy data from sklearn datasets", "implementation": {"container": {"command":
["python", "download_data.py", "--data", {"outputPath": "Data"}], "image":
"lightnighttw/kubeflow:download_data"}}, "name": "Download Data Function",
"outputs": [{"description": "Path where data will be stored.", "name": "Data",
"type": "LocalPath"}]}', pipelines.kubeflow.org/component_ref: '{"digest":
"467750defdccfec51c3af2a7eb853f74235f5f97329006d72bf33ff6e15ed02d", "url":
"download_data/download_data.yaml"}'}
- name: only-decision-tree
dag:
tasks:
- name: decision-tree-classifier
template: decision-tree-classifier
dependencies: [download-data-function]
arguments:
artifacts:
- {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'}
- {name: download-data-function, template: download-data-function}
- name: show-results
template: show-results
dependencies: [decision-tree-classifier]
arguments:
parameters:
- {name: decision-tree-classifier-Accuracy, value: '{{tasks.decision-tree-classifier.outputs.parameters.decision-tree-classifier-Accuracy}}'}
- name: show-results
container:
args: [--decision-tree, '{{inputs.parameters.decision-tree-classifier-Accuracy}}']
command:
- sh
- -ec
- |
program_path=$(mktemp)
printf "%s" "$0" > "$program_path"
python3 -u "$program_path" "$@"
- |
def show_results(decision_tree):
# the results are shown.
print(f"Decision tree (accuracy): {decision_tree}")
import argparse
_parser = argparse.ArgumentParser(prog='Show results', description='')
_parser.add_argument("--decision-tree", dest="decision_tree", type=float, required=True, default=argparse.SUPPRESS)
_parsed_args = vars(_parser.parse_args())
_outputs = show_results(**_parsed_args)
image: python:3.7
resources:
limits:
cpu: 2
inputs:
parameters:
- {name: decision-tree-classifier-Accuracy}
metadata:
labels:
pipelines.kubeflow.org/kfp_sdk_version: 1.8.20
pipelines.kubeflow.org/pipeline-sdk-type: kfp
pipelines.kubeflow.org/enable_caching: "true"
annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container":
{"args": ["--decision-tree", {"inputValue": "decision_tree"}], "command":
["sh", "-ec", "program_path=$(mktemp)\nprintf \"%s\" \"$0\" > \"$program_path\"\npython3
-u \"$program_path\" \"$@\"\n", "def show_results(decision_tree):\n #
the results are shown.\n\n print(f\"Decision tree (accuracy): {decision_tree}\")\n\nimport
argparse\n_parser = argparse.ArgumentParser(prog=''Show results'', description='''')\n_parser.add_argument(\"--decision-tree\",
dest=\"decision_tree\", type=float, required=True, default=argparse.SUPPRESS)\n_parsed_args
= vars(_parser.parse_args())\n\n_outputs = show_results(**_parsed_args)\n"],
"image": "python:3.7"}}, "inputs": [{"name": "decision_tree", "type": "Float"}],
"name": "Show results"}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"decision_tree":
"{{inputs.parameters.decision-tree-classifier-Accuracy}}"}'}
arguments:
parameters: []
serviceAccountName: pipeline-runner

View File

@ -0,0 +1,131 @@
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: only-logistic-regression-
annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.20, pipelines.kubeflow.org/pipeline_compilation_time: '2023-04-28T21:47:07.033809',
pipelines.kubeflow.org/pipeline_spec: '{"description": "Applies Logistic Regression
for classification problem.", "name": "only_logistic_regression"}'}
labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.20}
spec:
entrypoint: only-logistic-regression
templates:
- name: download-data-function
container:
args: []
command: [python, download_data.py, --data, /tmp/outputs/Data/data]
image: lightnighttw/kubeflow:download_data
resources:
limits:
cpu: 2
outputs:
artifacts:
- {name: download-data-function-Data, path: /tmp/outputs/Data/data}
metadata:
labels:
pipelines.kubeflow.org/kfp_sdk_version: 1.8.20
pipelines.kubeflow.org/pipeline-sdk-type: kfp
pipelines.kubeflow.org/enable_caching: "true"
annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Download
toy data from sklearn datasets", "implementation": {"container": {"command":
["python", "download_data.py", "--data", {"outputPath": "Data"}], "image":
"lightnighttw/kubeflow:download_data"}}, "name": "Download Data Function",
"outputs": [{"description": "Path where data will be stored.", "name": "Data",
"type": "LocalPath"}]}', pipelines.kubeflow.org/component_ref: '{"digest":
"467750defdccfec51c3af2a7eb853f74235f5f97329006d72bf33ff6e15ed02d", "url":
"download_data/download_data.yaml"}'}
- name: logistic-regression-classifier
container:
args: []
command: [python, logistic_regression.py, --data, /tmp/inputs/Data/data, --accuracy,
/tmp/outputs/Accuracy/data]
image: lightnighttw/kubeflow:logistic_regression
resources:
limits:
cpu: 2
inputs:
artifacts:
- {name: download-data-function-Data, path: /tmp/inputs/Data/data}
outputs:
parameters:
- name: logistic-regression-classifier-Accuracy
valueFrom: {path: /tmp/outputs/Accuracy/data}
artifacts:
- {name: logistic-regression-classifier-Accuracy, path: /tmp/outputs/Accuracy/data}
metadata:
labels:
pipelines.kubeflow.org/kfp_sdk_version: 1.8.20
pipelines.kubeflow.org/pipeline-sdk-type: kfp
pipelines.kubeflow.org/enable_caching: "true"
annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Trains
a Logistic Regression Classifier", "implementation": {"container": {"command":
["python", "logistic_regression.py", "--data", {"inputPath": "Data"}, "--accuracy",
{"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:logistic_regression"}},
"inputs": [{"description": "Path where data is stored.", "name": "Data",
"type": "LocalPath"}], "name": "Logistic Regression Classifier", "outputs":
[{"description": "Accuracy metric", "name": "Accuracy", "type": "Float"}]}',
pipelines.kubeflow.org/component_ref: '{"digest": "a8d1e77d07d18a75bef200aee96f35136833fc4bb535f33fd949a307beb094c2",
"url": "logistic_regression/logistic_regression.yaml"}'}
- name: only-logistic-regression
dag:
tasks:
- {name: download-data-function, template: download-data-function}
- name: logistic-regression-classifier
template: logistic-regression-classifier
dependencies: [download-data-function]
arguments:
artifacts:
- {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'}
- name: show-results
template: show-results
dependencies: [logistic-regression-classifier]
arguments:
parameters:
- {name: logistic-regression-classifier-Accuracy, value: '{{tasks.logistic-regression-classifier.outputs.parameters.logistic-regression-classifier-Accuracy}}'}
- name: show-results
container:
args: [--logistic-regression, '{{inputs.parameters.logistic-regression-classifier-Accuracy}}']
command:
- sh
- -ec
- |
program_path=$(mktemp)
printf "%s" "$0" > "$program_path"
python3 -u "$program_path" "$@"
- |
def show_results(logistic_regression):
# the results are shown.
print(f"Logistic regression (accuracy): {logistic_regression}")
import argparse
_parser = argparse.ArgumentParser(prog='Show results', description='')
_parser.add_argument("--logistic-regression", dest="logistic_regression", type=float, required=True, default=argparse.SUPPRESS)
_parsed_args = vars(_parser.parse_args())
_outputs = show_results(**_parsed_args)
image: python:3.7
resources:
limits:
cpu: 2
inputs:
parameters:
- {name: logistic-regression-classifier-Accuracy}
metadata:
labels:
pipelines.kubeflow.org/kfp_sdk_version: 1.8.20
pipelines.kubeflow.org/pipeline-sdk-type: kfp
pipelines.kubeflow.org/enable_caching: "true"
annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container":
{"args": ["--logistic-regression", {"inputValue": "logistic_regression"}],
"command": ["sh", "-ec", "program_path=$(mktemp)\nprintf \"%s\" \"$0\" >
\"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", "def show_results(logistic_regression):\n #
the results are shown.\n\n print(f\"Logistic regression (accuracy): {logistic_regression}\")\n\nimport
argparse\n_parser = argparse.ArgumentParser(prog=''Show results'', description='''')\n_parser.add_argument(\"--logistic-regression\",
dest=\"logistic_regression\", type=float, required=True, default=argparse.SUPPRESS)\n_parsed_args
= vars(_parser.parse_args())\n\n_outputs = show_results(**_parsed_args)\n"],
"image": "python:3.7"}}, "inputs": [{"name": "logistic_regression", "type":
"Float"}], "name": "Show results"}', pipelines.kubeflow.org/component_ref: '{}',
pipelines.kubeflow.org/arguments.parameters: '{"logistic_regression": "{{inputs.parameters.logistic-regression-classifier-Accuracy}}"}'}
arguments:
parameters: []
serviceAccountName: pipeline-runner

View File

@ -0,0 +1,131 @@
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: three-pipeline-
annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.20, pipelines.kubeflow.org/pipeline_compilation_time: '2023-04-28T22:03:53.972623',
pipelines.kubeflow.org/pipeline_spec: '{"description": "Applies random forest
for classification problem.", "name": "Three Pipeline"}'}
labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.20}
spec:
entrypoint: three-pipeline
templates:
- name: download-data-function
container:
args: []
command: [python, download_data.py, --data, /tmp/outputs/Data/data]
image: lightnighttw/kubeflow:download_data
resources:
limits:
cpu: 2
outputs:
artifacts:
- {name: download-data-function-Data, path: /tmp/outputs/Data/data}
metadata:
labels:
pipelines.kubeflow.org/kfp_sdk_version: 1.8.20
pipelines.kubeflow.org/pipeline-sdk-type: kfp
pipelines.kubeflow.org/enable_caching: "true"
annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Download
toy data from sklearn datasets", "implementation": {"container": {"command":
["python", "download_data.py", "--data", {"outputPath": "Data"}], "image":
"lightnighttw/kubeflow:download_data"}}, "name": "Download Data Function",
"outputs": [{"description": "Path where data will be stored.", "name": "Data",
"type": "LocalPath"}]}', pipelines.kubeflow.org/component_ref: '{"digest":
"467750defdccfec51c3af2a7eb853f74235f5f97329006d72bf33ff6e15ed02d", "url":
"download_data/download_data.yaml"}'}
- name: random-forest-classifier
container:
args: []
command: [python, randomforest.py, --data, /tmp/inputs/Data/data, --accuracy,
/tmp/outputs/Accuracy/data]
image: lightnighttw/kubeflow:random_forest_v4
resources:
limits:
cpu: 2
inputs:
artifacts:
- {name: download-data-function-Data, path: /tmp/inputs/Data/data}
outputs:
parameters:
- name: random-forest-classifier-Accuracy
valueFrom: {path: /tmp/outputs/Accuracy/data}
artifacts:
- {name: random-forest-classifier-Accuracy, path: /tmp/outputs/Accuracy/data}
metadata:
labels:
pipelines.kubeflow.org/kfp_sdk_version: 1.8.20
pipelines.kubeflow.org/pipeline-sdk-type: kfp
pipelines.kubeflow.org/enable_caching: "true"
annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Trains
a random forest classifier", "implementation": {"container": {"command":
["python", "randomforest.py", "--data", {"inputPath": "Data"}, "--accuracy",
{"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:random_forest_v4"}},
"inputs": [{"description": "Path where data is stored.", "name": "Data",
"type": "LocalPath"}], "name": "Random Forest classifier", "outputs": [{"description":
"Accuracy metric", "name": "Accuracy", "type": "Float"}]}', pipelines.kubeflow.org/component_ref: '{"digest":
"7b6a0d03d7954a2b4dc7ad9295871e1780c784799f719f7365b37f1a96a6f824", "url":
"randomForest/random_forest.yaml"}'}
- name: show-results
container:
args: [--random-forest, '{{inputs.parameters.random-forest-classifier-Accuracy}}']
command:
- sh
- -ec
- |
program_path=$(mktemp)
printf "%s" "$0" > "$program_path"
python3 -u "$program_path" "$@"
- |
def show_results(random_forest):
# the results are shown.
print(f"Random forest (accuracy): {random_forest}")
import argparse
_parser = argparse.ArgumentParser(prog='Show results', description='')
_parser.add_argument("--random-forest", dest="random_forest", type=float, required=True, default=argparse.SUPPRESS)
_parsed_args = vars(_parser.parse_args())
_outputs = show_results(**_parsed_args)
image: python:3.7
resources:
limits:
cpu: 2
inputs:
parameters:
- {name: random-forest-classifier-Accuracy}
metadata:
labels:
pipelines.kubeflow.org/kfp_sdk_version: 1.8.20
pipelines.kubeflow.org/pipeline-sdk-type: kfp
pipelines.kubeflow.org/enable_caching: "true"
annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container":
{"args": ["--random-forest", {"inputValue": "random_forest"}], "command":
["sh", "-ec", "program_path=$(mktemp)\nprintf \"%s\" \"$0\" > \"$program_path\"\npython3
-u \"$program_path\" \"$@\"\n", "def show_results(random_forest):\n #
the results are shown.\n\n print(f\"Random forest (accuracy): {random_forest}\")\n\nimport
argparse\n_parser = argparse.ArgumentParser(prog=''Show results'', description='''')\n_parser.add_argument(\"--random-forest\",
dest=\"random_forest\", type=float, required=True, default=argparse.SUPPRESS)\n_parsed_args
= vars(_parser.parse_args())\n\n_outputs = show_results(**_parsed_args)\n"],
"image": "python:3.7"}}, "inputs": [{"name": "random_forest", "type": "Float"}],
"name": "Show results"}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"random_forest":
"{{inputs.parameters.random-forest-classifier-Accuracy}}"}'}
- name: three-pipeline
dag:
tasks:
- {name: download-data-function, template: download-data-function}
- name: random-forest-classifier
template: random-forest-classifier
dependencies: [download-data-function]
arguments:
artifacts:
- {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'}
- name: show-results
template: show-results
dependencies: [random-forest-classifier]
arguments:
parameters:
- {name: random-forest-classifier-Accuracy, value: '{{tasks.random-forest-classifier.outputs.parameters.random-forest-classifier-Accuracy}}'}
arguments:
parameters: []
serviceAccountName: pipeline-runner

View File

@ -0,0 +1,229 @@
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: three-pipeline-
annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9, pipelines.kubeflow.org/pipeline_compilation_time: '2023-04-28T12:05:44.365082',
pipelines.kubeflow.org/pipeline_spec: '{"description": "Applies Decision Tree,
random forest and Logistic Regression for classification problem.", "name":
"Three Pipeline"}'}
labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9}
spec:
entrypoint: three-pipeline
templates:
- name: decision-tree-classifier
container:
args: []
command: [python, decision_tree.py, --data, /tmp/inputs/Data/data, --accuracy,
/tmp/outputs/Accuracy/data]
image: lightnighttw/kubeflow:decision_tree_v2
resources:
limits:
cpu: 2
inputs:
artifacts:
- {name: download-data-function-Data, path: /tmp/inputs/Data/data}
outputs:
parameters:
- name: decision-tree-classifier-Accuracy
valueFrom: {path: /tmp/outputs/Accuracy/data}
artifacts:
- {name: decision-tree-classifier-Accuracy, path: /tmp/outputs/Accuracy/data}
metadata:
labels:
pipelines.kubeflow.org/kfp_sdk_version: 1.8.9
pipelines.kubeflow.org/pipeline-sdk-type: kfp
pipelines.kubeflow.org/enable_caching: "true"
annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Trains
a decision tree classifier", "implementation": {"container": {"command":
["python", "decision_tree.py", "--data", {"inputPath": "Data"}, "--accuracy",
{"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:decision_tree_v2"}},
"inputs": [{"description": "Path where data is stored.", "name": "Data",
"type": "LocalPath"}], "name": "Decision Tree classifier", "outputs": [{"description":
"Accuracy metric", "name": "Accuracy", "type": "Float"}]}', pipelines.kubeflow.org/component_ref: '{"digest":
"c5c232a9654213b3b222693949b71a5d561d04ed09543c20b6f8f2eab651ae0b", "url":
"decision_tree/decision_tree.yaml"}'}
- name: download-data-function
container:
args: []
command: [python, download_data.py, --data, /tmp/outputs/Data/data]
image: lightnighttw/kubeflow:download_data
resources:
limits:
cpu: 2
outputs:
artifacts:
- {name: download-data-function-Data, path: /tmp/outputs/Data/data}
metadata:
labels:
pipelines.kubeflow.org/kfp_sdk_version: 1.8.9
pipelines.kubeflow.org/pipeline-sdk-type: kfp
pipelines.kubeflow.org/enable_caching: "true"
annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Download
toy data from sklearn datasets", "implementation": {"container": {"command":
["python", "download_data.py", "--data", {"outputPath": "Data"}], "image":
"lightnighttw/kubeflow:download_data"}}, "name": "Download Data Function",
"outputs": [{"description": "Path where data will be stored.", "name": "Data",
"type": "LocalPath"}]}', pipelines.kubeflow.org/component_ref: '{"digest":
"467750defdccfec51c3af2a7eb853f74235f5f97329006d72bf33ff6e15ed02d", "url":
"download_data/download_data.yaml"}'}
- name: logistic-regression-classifier
container:
args: []
command: [python, logistic_regression.py, --data, /tmp/inputs/Data/data, --accuracy,
/tmp/outputs/Accuracy/data]
image: lightnighttw/kubeflow:logistic_regression
resources:
limits:
cpu: 2
inputs:
artifacts:
- {name: download-data-function-Data, path: /tmp/inputs/Data/data}
outputs:
parameters:
- name: logistic-regression-classifier-Accuracy
valueFrom: {path: /tmp/outputs/Accuracy/data}
artifacts:
- {name: logistic-regression-classifier-Accuracy, path: /tmp/outputs/Accuracy/data}
metadata:
labels:
pipelines.kubeflow.org/kfp_sdk_version: 1.8.9
pipelines.kubeflow.org/pipeline-sdk-type: kfp
pipelines.kubeflow.org/enable_caching: "true"
annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Trains
a Logistic Regression Classifier", "implementation": {"container": {"command":
["python", "logistic_regression.py", "--data", {"inputPath": "Data"}, "--accuracy",
{"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:logistic_regression"}},
"inputs": [{"description": "Path where data is stored.", "name": "Data",
"type": "LocalPath"}], "name": "Logistic Regression Classifier", "outputs":
[{"description": "Accuracy metric", "name": "Accuracy", "type": "Float"}]}',
pipelines.kubeflow.org/component_ref: '{"digest": "a8d1e77d07d18a75bef200aee96f35136833fc4bb535f33fd949a307beb094c2",
"url": "logistic_regression/logistic_regression.yaml"}'}
- name: random-forest-classifier
container:
args: []
command: [python, randomforest.py, --data, /tmp/inputs/Data/data, --accuracy,
/tmp/outputs/Accuracy/data]
image: lightnighttw/kubeflow:random_forest_v4
resources:
limits:
cpu: 2
inputs:
artifacts:
- {name: download-data-function-Data, path: /tmp/inputs/Data/data}
outputs:
parameters:
- name: random-forest-classifier-Accuracy
valueFrom: {path: /tmp/outputs/Accuracy/data}
artifacts:
- {name: random-forest-classifier-Accuracy, path: /tmp/outputs/Accuracy/data}
metadata:
labels:
pipelines.kubeflow.org/kfp_sdk_version: 1.8.9
pipelines.kubeflow.org/pipeline-sdk-type: kfp
pipelines.kubeflow.org/enable_caching: "true"
annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Train
a random forest classifier", "implementation": {"container": {"command":
["python", "randomforest.py", "--data", {"inputPath": "Data"}, "--accuracy",
{"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:random_forest_v4"}},
"inputs": [{"description": "Path where data is stored.", "name": "Data",
"type": "LocalPath"}], "name": "Random Forest classifier", "outputs": [{"description":
"Accuracy metric", "name": "Accuracy", "type": "Float"}]}', pipelines.kubeflow.org/component_ref: '{"digest":
"b49b12da3371976eddf41d662685bb49d71b419d516de65efdd90938d2c706bc", "url":
"randomForest/random_forest.yaml"}'}
- name: show-results
container:
args: [--decision-tree, '{{inputs.parameters.decision-tree-classifier-Accuracy}}',
--logistic-regression, '{{inputs.parameters.logistic-regression-classifier-Accuracy}}',
--random-forest, '{{inputs.parameters.random-forest-classifier-Accuracy}}']
command:
- sh
- -ec
- |
program_path=$(mktemp)
printf "%s" "$0" > "$program_path"
python3 -u "$program_path" "$@"
- |
def show_results(decision_tree, logistic_regression, random_forest):
# Given the outputs from decision_tree and logistic regression components
# the results are shown.
print(f"Decision tree (accuracy): {decision_tree}")
print(f"Logistic regression (accuracy): {logistic_regression}")
print(f"Random forest (accuracy): {random_forest}")
import argparse
_parser = argparse.ArgumentParser(prog='Show results', description='')
_parser.add_argument("--decision-tree", dest="decision_tree", type=float, required=True, default=argparse.SUPPRESS)
_parser.add_argument("--logistic-regression", dest="logistic_regression", type=float, required=True, default=argparse.SUPPRESS)
_parser.add_argument("--random-forest", dest="random_forest", type=float, required=True, default=argparse.SUPPRESS)
_parsed_args = vars(_parser.parse_args())
_outputs = show_results(**_parsed_args)
image: python:3.7
resources:
limits:
cpu: 2
inputs:
parameters:
- {name: decision-tree-classifier-Accuracy}
- {name: logistic-regression-classifier-Accuracy}
- {name: random-forest-classifier-Accuracy}
metadata:
labels:
pipelines.kubeflow.org/kfp_sdk_version: 1.8.9
pipelines.kubeflow.org/pipeline-sdk-type: kfp
pipelines.kubeflow.org/enable_caching: "true"
annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container":
{"args": ["--decision-tree", {"inputValue": "decision_tree"}, "--logistic-regression",
{"inputValue": "logistic_regression"}, "--random-forest", {"inputValue":
"random_forest"}], "command": ["sh", "-ec", "program_path=$(mktemp)\nprintf
\"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n",
"def show_results(decision_tree, logistic_regression, random_forest):\n #
Given the outputs from decision_tree and logistic regression components\n #
the results are shown.\n\n print(f\"Decision tree (accuracy): {decision_tree}\")\n print(f\"Logistic
regression (accuracy): {logistic_regression}\")\n print(f\"Random forest
(accuracy): {random_forest}\")\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Show
results'', description='''')\n_parser.add_argument(\"--decision-tree\",
dest=\"decision_tree\", type=float, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"--logistic-regression\",
dest=\"logistic_regression\", type=float, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"--random-forest\",
dest=\"random_forest\", type=float, required=True, default=argparse.SUPPRESS)\n_parsed_args
= vars(_parser.parse_args())\n\n_outputs = show_results(**_parsed_args)\n"],
"image": "python:3.7"}}, "inputs": [{"name": "decision_tree", "type": "Float"},
{"name": "logistic_regression", "type": "Float"}, {"name": "random_forest",
"type": "Float"}], "name": "Show results"}', pipelines.kubeflow.org/component_ref: '{}',
pipelines.kubeflow.org/arguments.parameters: '{"decision_tree": "{{inputs.parameters.decision-tree-classifier-Accuracy}}",
"logistic_regression": "{{inputs.parameters.logistic-regression-classifier-Accuracy}}",
"random_forest": "{{inputs.parameters.random-forest-classifier-Accuracy}}"}'}
- name: three-pipeline
dag:
tasks:
- name: decision-tree-classifier
template: decision-tree-classifier
dependencies: [download-data-function]
arguments:
artifacts:
- {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'}
- {name: download-data-function, template: download-data-function}
- name: logistic-regression-classifier
template: logistic-regression-classifier
dependencies: [download-data-function]
arguments:
artifacts:
- {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'}
- name: random-forest-classifier
template: random-forest-classifier
dependencies: [download-data-function]
arguments:
artifacts:
- {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'}
- name: show-results
template: show-results
dependencies: [decision-tree-classifier, logistic-regression-classifier, random-forest-classifier]
arguments:
parameters:
- {name: decision-tree-classifier-Accuracy, value: '{{tasks.decision-tree-classifier.outputs.parameters.decision-tree-classifier-Accuracy}}'}
- {name: logistic-regression-classifier-Accuracy, value: '{{tasks.logistic-regression-classifier.outputs.parameters.logistic-regression-classifier-Accuracy}}'}
- {name: random-forest-classifier-Accuracy, value: '{{tasks.random-forest-classifier.outputs.parameters.random-forest-classifier-Accuracy}}'}
arguments:
parameters: []
serviceAccountName: pipeline-runner

View File

@ -0,0 +1,4 @@
setuptools
wheel
PyYAML==5.3.1
minio

View File

@ -0,0 +1,184 @@
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: kfserving-pipeline-
annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.7.0, pipelines.kubeflow.org/pipeline_compilation_time: '2023-11-14T09:23:34.926467',
pipelines.kubeflow.org/pipeline_spec: '{"description": "A pipeline for KFServing
with PVC.", "inputs": [{"default": "apply", "name": "action", "optional": true},
{"default": "kubeflow02", "name": "namespace", "optional": true}, {"default":
"undefined", "name": "pvc_name", "optional": true}, {"default": "model01", "name":
"model_name", "optional": true}], "name": "KFServing pipeline"}'}
labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.7.0}
spec:
entrypoint: kfserving-pipeline
templates:
- name: kfserving-pipeline
inputs:
parameters:
- {name: action}
- {name: model_name}
- {name: namespace}
- {name: pvc_name}
dag:
tasks:
- name: serve-a-model-with-kserve
template: serve-a-model-with-kserve
arguments:
parameters:
- {name: action, value: '{{inputs.parameters.action}}'}
- {name: model_name, value: '{{inputs.parameters.model_name}}'}
- {name: namespace, value: '{{inputs.parameters.namespace}}'}
- {name: pvc_name, value: '{{inputs.parameters.pvc_name}}'}
- name: serve-a-model-with-kserve
container:
args:
- -u
- kservedeployer.py
- --action
- '{{inputs.parameters.action}}'
- --model-name
- ''
- --model-uri
- ''
- --canary-traffic-percent
- '100'
- --namespace
- ''
- --framework
- ''
- --runtime-version
- latest
- --resource-requests
- '{"cpu": "0.5", "memory": "512Mi"}'
- --resource-limits
- '{"cpu": "1", "memory": "1Gi"}'
- --custom-model-spec
- '{}'
- --autoscaling-target
- '0'
- --service-account
- ''
- --enable-istio-sidecar
- "True"
- --output-path
- /tmp/outputs/InferenceService_Status/data
- --inferenceservice-yaml
- |2
apiVersion: "serving.kserve.io/v1beta1"
kind: "InferenceService"
metadata:
name: {{inputs.parameters.model_name}}
namespace: {{inputs.parameters.namespace}}
spec:
predictor:
sklearn:
storageUri: pvc://{{inputs.parameters.pvc_name}}/{{inputs.parameters.model_name}}/
resources:
limits:
cpu: "100m"
requests:
cpu: "100m"
- --watch-timeout
- '300'
- --min-replicas
- '-1'
- --max-replicas
- '-1'
- --request-timeout
- '60'
- --enable-isvc-status
- "True"
command: [python]
image: quay.io/aipipeline/kserve-component:v0.11.1
resources:
limits: {cpu: 500m}
requests: {cpu: 500m}
inputs:
parameters:
- {name: action}
- {name: model_name}
- {name: namespace}
- {name: pvc_name}
outputs:
artifacts:
- {name: serve-a-model-with-kserve-InferenceService-Status, path: /tmp/outputs/InferenceService_Status/data}
metadata:
labels:
pipelines.kubeflow.org/kfp_sdk_version: 1.7.0
pipelines.kubeflow.org/pipeline-sdk-type: kfp
pipelines.kubeflow.org/enable_caching: "true"
annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Serve
Models using KServe", "implementation": {"container": {"args": ["-u", "kservedeployer.py",
"--action", {"inputValue": "Action"}, "--model-name", {"inputValue": "Model
Name"}, "--model-uri", {"inputValue": "Model URI"}, "--canary-traffic-percent",
{"inputValue": "Canary Traffic Percent"}, "--namespace", {"inputValue":
"Namespace"}, "--framework", {"inputValue": "Framework"}, "--runtime-version",
{"inputValue": "Runtime Version"}, "--resource-requests", {"inputValue":
"Resource Requests"}, "--resource-limits", {"inputValue": "Resource Limits"},
"--custom-model-spec", {"inputValue": "Custom Model Spec"}, "--autoscaling-target",
{"inputValue": "Autoscaling Target"}, "--service-account", {"inputValue":
"Service Account"}, "--enable-istio-sidecar", {"inputValue": "Enable Istio
Sidecar"}, "--output-path", {"outputPath": "InferenceService Status"}, "--inferenceservice-yaml",
{"inputValue": "InferenceService YAML"}, "--watch-timeout", {"inputValue":
"Watch Timeout"}, "--min-replicas", {"inputValue": "Min Replicas"}, "--max-replicas",
{"inputValue": "Max Replicas"}, "--request-timeout", {"inputValue": "Request
Timeout"}, "--enable-isvc-status", {"inputValue": "Enable ISVC Status"}],
"command": ["python"], "image": "quay.io/aipipeline/kserve-component:v0.11.1"}},
"inputs": [{"default": "create", "description": "Action to execute on KServe",
"name": "Action", "type": "String"}, {"default": "", "description": "Name
to give to the deployed model", "name": "Model Name", "type": "String"},
{"default": "", "description": "Path of the S3 or GCS compatible directory
containing the model.", "name": "Model URI", "type": "String"}, {"default":
"100", "description": "The traffic split percentage between the candidate
model and the last ready model", "name": "Canary Traffic Percent", "type":
"String"}, {"default": "", "description": "Kubernetes namespace where the
KServe service is deployed.", "name": "Namespace", "type": "String"}, {"default":
"", "description": "Machine Learning Framework for Model Serving.", "name":
"Framework", "type": "String"}, {"default": "latest", "description": "Runtime
Version of Machine Learning Framework", "name": "Runtime Version", "type":
"String"}, {"default": "{\"cpu\": \"0.5\", \"memory\": \"512Mi\"}", "description":
"CPU and Memory requests for Model Serving", "name": "Resource Requests",
"type": "String"}, {"default": "{\"cpu\": \"1\", \"memory\": \"1Gi\"}",
"description": "CPU and Memory limits for Model Serving", "name": "Resource
Limits", "type": "String"}, {"default": "{}", "description": "Custom model
runtime container spec in JSON", "name": "Custom Model Spec", "type": "String"},
{"default": "0", "description": "Autoscaling Target Number", "name": "Autoscaling
Target", "type": "String"}, {"default": "", "description": "ServiceAccount
to use to run the InferenceService pod", "name": "Service Account", "type":
"String"}, {"default": "True", "description": "Whether to enable istio sidecar
injection", "name": "Enable Istio Sidecar", "type": "Bool"}, {"default":
"{}", "description": "Raw InferenceService serialized YAML for deployment",
"name": "InferenceService YAML", "type": "String"}, {"default": "300", "description":
"Timeout seconds for watching until InferenceService becomes ready.", "name":
"Watch Timeout", "type": "String"}, {"default": "-1", "description": "Minimum
number of InferenceService replicas", "name": "Min Replicas", "type": "String"},
{"default": "-1", "description": "Maximum number of InferenceService replicas",
"name": "Max Replicas", "type": "String"}, {"default": "60", "description":
"Specifies the number of seconds to wait before timing out a request to
the component.", "name": "Request Timeout", "type": "String"}, {"default":
"True", "description": "Specifies whether to store the inference service
status as the output parameter", "name": "Enable ISVC Status", "type": "Bool"}],
"name": "Serve a model with KServe", "outputs": [{"description": "Status
JSON output of InferenceService", "name": "InferenceService Status", "type":
"String"}]}', pipelines.kubeflow.org/component_ref: '{"digest": "b0379af21c170410b8b1a9606cb6cad63f99b0af53c2a5c1f0af397b53c81cd7",
"url": "https://raw.githubusercontent.com/kubeflow/pipelines/master/components/kserve/component.yaml"}',
pipelines.kubeflow.org/arguments.parameters: '{"Action": "{{inputs.parameters.action}}",
"Autoscaling Target": "0", "Canary Traffic Percent": "100", "Custom Model
Spec": "{}", "Enable ISVC Status": "True", "Enable Istio Sidecar": "True",
"Framework": "", "InferenceService YAML": "\napiVersion: \"serving.kserve.io/v1beta1\"\nkind:
\"InferenceService\"\nmetadata:\n name: {{inputs.parameters.model_name}}\n namespace:
{{inputs.parameters.namespace}}\nspec:\n predictor:\n sklearn:\n storageUri:
pvc://{{inputs.parameters.pvc_name}}/{{inputs.parameters.model_name}}/\n resources:\n limits:\n cpu:
\"100m\"\n requests:\n cpu: \"100m\"\n", "Max Replicas":
"-1", "Min Replicas": "-1", "Model Name": "", "Model URI": "", "Namespace":
"", "Request Timeout": "60", "Resource Limits": "{\"cpu\": \"1\", \"memory\":
\"1Gi\"}", "Resource Requests": "{\"cpu\": \"0.5\", \"memory\": \"512Mi\"}",
"Runtime Version": "latest", "Service Account": "", "Watch Timeout": "300"}'}
arguments:
parameters:
- {name: action, value: apply}
- {name: namespace, value: kubeflow02}
- {name: pvc_name, value: undefined}
- {name: model_name, value: model01}
serviceAccountName: pipeline-runner

View File

@ -0,0 +1,498 @@
/**
* This is the default settings file provided by Node-RED.
*
* It can contain any valid JavaScript code that will get run when Node-RED
* is started.
*
* Lines that start with // are commented out.
* Each entry should be separated from the entries above and below by a comma ','
*
* For more information about individual settings, refer to the documentation:
* https://nodered.org/docs/user-guide/runtime/configuration
*
* The settings are split into the following sections:
* - Flow File and User Directory Settings
* - Security
* - Server Settings
* - Runtime Settings
* - Editor Settings
* - Node Settings
*
**/
module.exports = {
/*******************************************************************************
* Flow File and User Directory Settings
* - flowFile
* - credentialSecret
* - flowFilePretty
* - userDir
* - nodesDir
******************************************************************************/
/** The file containing the flows. If not set, defaults to flows_<hostname>.json **/
flowFile: 'flows.json',
/** By default, credentials are encrypted in storage using a generated key. To
* specify your own secret, set the following property.
* If you want to disable encryption of credentials, set this property to false.
* Note: once you set this property, do not change it - doing so will prevent
* node-red from being able to decrypt your existing credentials and they will be
* lost.
*/
//credentialSecret: "a-secret-key",
credentialSecret: process.env.NODE_RED_CREDENTIAL_SECRET,
/** By default, the flow JSON will be formatted over multiple lines making
* it easier to compare changes when using version control.
* To disable pretty-printing of the JSON set the following property to false.
*/
flowFilePretty: true,
/** By default, all user data is stored in a directory called `.node-red` under
* the user's home directory. To use a different location, the following
* property can be used
*/
//userDir: '/home/nol/.node-red/',
/** Node-RED scans the `nodes` directory in the userDir to find local node files.
* The following property can be used to specify an additional directory to scan.
*/
//nodesDir: '/home/nol/.node-red/nodes',
/*******************************************************************************
* Security
* - adminAuth
* - https
* - httpsRefreshInterval
* - requireHttps
* - httpNodeAuth
* - httpStaticAuth
******************************************************************************/
/** To password protect the Node-RED editor and admin API, the following
* property can be used. See http://nodered.org/docs/security.html for details.
*/
//adminAuth: {
// type: "credentials",
// users: [{
// username: "admin",
// password: "$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN.",
// permissions: "*"
// }]
//},
/** The following property can be used to enable HTTPS
* This property can be either an object, containing both a (private) key
* and a (public) certificate, or a function that returns such an object.
* See http://nodejs.org/api/https.html#https_https_createserver_options_requestlistener
* for details of its contents.
*/
/** Option 1: static object */
//https: {
// key: require("fs").readFileSync('privkey.pem'),
// cert: require("fs").readFileSync('cert.pem')
//},
/** Option 2: function that returns the HTTP configuration object */
// https: function() {
// // This function should return the options object, or a Promise
// // that resolves to the options object
// return {
// key: require("fs").readFileSync('privkey.pem'),
// cert: require("fs").readFileSync('cert.pem')
// }
// },
/** If the `https` setting is a function, the following setting can be used
* to set how often, in hours, the function will be called. That can be used
* to refresh any certificates.
*/
//httpsRefreshInterval : 12,
/** The following property can be used to cause insecure HTTP connections to
* be redirected to HTTPS.
*/
//requireHttps: true,
/** To password protect the node-defined HTTP endpoints (httpNodeRoot),
* including node-red-dashboard, or the static content (httpStatic), the
* following properties can be used.
* The `pass` field is a bcrypt hash of the password.
* See http://nodered.org/docs/security.html#generating-the-password-hash
*/
//httpNodeAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."},
//httpStaticAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."},
/*******************************************************************************
* Server Settings
* - uiPort
* - uiHost
* - apiMaxLength
* - httpServerOptions
* - httpAdminRoot
* - httpAdminMiddleware
* - httpNodeRoot
* - httpNodeCors
* - httpNodeMiddleware
* - httpStatic
******************************************************************************/
/** the tcp port that the Node-RED web server is listening on */
uiPort: process.env.PORT || 1880,
/** By default, the Node-RED UI accepts connections on all IPv4 interfaces.
* To listen on all IPv6 addresses, set uiHost to "::",
* The following property can be used to listen on a specific interface. For
* example, the following would only allow connections from the local machine.
*/
//uiHost: "127.0.0.1",
/** The maximum size of HTTP request that will be accepted by the runtime api.
* Default: 5mb
*/
//apiMaxLength: '5mb',
/** The following property can be used to pass custom options to the Express.js
* server used by Node-RED. For a full list of available options, refer
* to http://expressjs.com/en/api.html#app.settings.table
*/
//httpServerOptions: { },
/** By default, the Node-RED UI is available at http://localhost:1880/
* The following property can be used to specify a different root path.
* If set to false, this is disabled.
*/
//httpAdminRoot: '/admin',
/** The following property can be used to add a custom middleware function
* in front of all admin http routes. For example, to set custom http
* headers. It can be a single function or an array of middleware functions.
*/
// httpAdminMiddleware: function(req,res,next) {
// // Set the X-Frame-Options header to limit where the editor
// // can be embedded
// //res.set('X-Frame-Options', 'sameorigin');
// next();
// },
/** Some nodes, such as HTTP In, can be used to listen for incoming http requests.
* By default, these are served relative to '/'. The following property
* can be used to specifiy a different root path. If set to false, this is
* disabled.
*/
//httpNodeRoot: '/red-nodes',
/** The following property can be used to configure cross-origin resource sharing
* in the HTTP nodes.
* See https://github.com/troygoode/node-cors#configuration-options for
* details on its contents. The following is a basic permissive set of options:
*/
//httpNodeCors: {
// origin: "*",
// methods: "GET,PUT,POST,DELETE"
//},
/** If you need to set an http proxy please set an environment variable
* called http_proxy (or HTTP_PROXY) outside of Node-RED in the operating system.
* For example - http_proxy=http://myproxy.com:8080
* (Setting it here will have no effect)
* You may also specify no_proxy (or NO_PROXY) to supply a comma separated
* list of domains to not proxy, eg - no_proxy=.acme.co,.acme.co.uk
*/
/** The following property can be used to add a custom middleware function
* in front of all http in nodes. This allows custom authentication to be
* applied to all http in nodes, or any other sort of common request processing.
* It can be a single function or an array of middleware functions.
*/
//httpNodeMiddleware: function(req,res,next) {
// // Handle/reject the request, or pass it on to the http in node by calling next();
// // Optionally skip our rawBodyParser by setting this to true;
// //req.skipRawBodyParser = true;
// next();
//},
/** When httpAdminRoot is used to move the UI to a different root path, the
* following property can be used to identify a directory of static content
* that should be served at http://localhost:1880/.
*/
//httpStatic: '/home/nol/node-red-static/',
/*******************************************************************************
* Runtime Settings
* - lang
* - logging
* - contextStorage
* - exportGlobalContextKeys
* - externalModules
******************************************************************************/
/** Uncomment the following to run node-red in your preferred language.
* Available languages include: en-US (default), ja, de, zh-CN, zh-TW, ru, ko
* Some languages are more complete than others.
*/
// lang: "de",
/** Configure the logging output */
logging: {
/** Only console logging is currently supported */
console: {
/** Level of logging to be recorded. Options are:
* fatal - only those errors which make the application unusable should be recorded
* error - record errors which are deemed fatal for a particular request + fatal errors
* warn - record problems which are non fatal + errors + fatal errors
* info - record information about the general running of the application + warn + error + fatal errors
* debug - record information which is more verbose than info + info + warn + error + fatal errors
* trace - record very detailed logging + debug + info + warn + error + fatal errors
* off - turn off all logging (doesn't affect metrics or audit)
*/
level: "info",
/** Whether or not to include metric events in the log output */
metrics: false,
/** Whether or not to include audit events in the log output */
audit: false
}
},
/** Context Storage
* The following property can be used to enable context storage. The configuration
* provided here will enable file-based context that flushes to disk every 30 seconds.
* Refer to the documentation for further options: https://nodered.org/docs/api/context/
*/
//contextStorage: {
// default: {
// module:"localfilesystem"
// },
//},
/** `global.keys()` returns a list of all properties set in global context.
* This allows them to be displayed in the Context Sidebar within the editor.
* In some circumstances it is not desirable to expose them to the editor. The
* following property can be used to hide any property set in `functionGlobalContext`
* from being list by `global.keys()`.
* By default, the property is set to false to avoid accidental exposure of
* their values. Setting this to true will cause the keys to be listed.
*/
exportGlobalContextKeys: false,
/** Configure how the runtime will handle external npm modules.
* This covers:
* - whether the editor will allow new node modules to be installed
* - whether nodes, such as the Function node are allowed to have their
* own dynamically configured dependencies.
* The allow/denyList options can be used to limit what modules the runtime
* will install/load. It can use '*' as a wildcard that matches anything.
*/
externalModules: {
// autoInstall: false, /** Whether the runtime will attempt to automatically install missing modules */
// autoInstallRetry: 30, /** Interval, in seconds, between reinstall attempts */
// palette: { /** Configuration for the Palette Manager */
// allowInstall: true, /** Enable the Palette Manager in the editor */
// allowUpdate: true, /** Allow modules to be updated in the Palette Manager */
// allowUpload: true, /** Allow module tgz files to be uploaded and installed */
// allowList: ['*'],
// denyList: [],
// allowUpdateList: ['*'],
// denyUpdateList: []
// },
// modules: { /** Configuration for node-specified modules */
// allowInstall: true,
// allowList: [],
// denyList: []
// }
},
/*******************************************************************************
* Editor Settings
* - disableEditor
* - editorTheme
******************************************************************************/
/** The following property can be used to disable the editor. The admin API
* is not affected by this option. To disable both the editor and the admin
* API, use either the httpRoot or httpAdminRoot properties
*/
//disableEditor: false,
/** Customising the editor
* See https://nodered.org/docs/user-guide/runtime/configuration#editor-themes
* for all available options.
*/
editorTheme: {
/** The following property can be used to set a custom theme for the editor.
* See https://github.com/node-red-contrib-themes/theme-collection for
* a collection of themes to chose from.
*/
//theme: "",
/** To disable the 'Welcome to Node-RED' tour that is displayed the first
* time you access the editor for each release of Node-RED, set this to false
*/
//tours: false,
palette: {
/** The following property can be used to order the categories in the editor
* palette. If a node's category is not in the list, the category will get
* added to the end of the palette.
* If not set, the following default order is used:
*/
//categories: ['subflows', 'common', 'function', 'network', 'sequence', 'parser', 'storage'],
},
projects: {
/** To enable the Projects feature, set this value to true */
enabled: false,
workflow: {
/** Set the default projects workflow mode.
* - manual - you must manually commit changes
* - auto - changes are automatically committed
* This can be overridden per-user from the 'Git config'
* section of 'User Settings' within the editor
*/
mode: "manual"
}
},
codeEditor: {
/** Select the text editor component used by the editor.
* Defaults to "ace", but can be set to "ace" or "monaco"
*/
lib: "ace",
options: {
/** The follow options only apply if the editor is set to "monaco"
*
* theme - must match the file name of a theme in
* packages/node_modules/@node-red/editor-client/src/vendor/monaco/dist/theme
* e.g. "tomorrow-night", "upstream-sunburst", "github", "my-theme"
*/
theme: "vs",
/** other overrides can be set e.g. fontSize, fontFamily, fontLigatures etc.
* for the full list, see https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandaloneeditorconstructionoptions.html
*/
//fontSize: 14,
//fontFamily: "Cascadia Code, Fira Code, Consolas, 'Courier New', monospace",
//fontLigatures: true,
}
}
},
/*******************************************************************************
* Node Settings
* - fileWorkingDirectory
* - functionGlobalContext
* - functionExternalModules
* - nodeMessageBufferMaxLength
* - ui (for use with Node-RED Dashboard)
* - debugUseColors
* - debugMaxLength
* - execMaxBufferSize
* - httpRequestTimeout
* - mqttReconnectTime
* - serialReconnectTime
* - socketReconnectTime
* - socketTimeout
* - tcpMsgQueueSize
* - inboundWebSocketTimeout
* - tlsConfigDisableLocalFiles
* - webSocketNodeVerifyClient
******************************************************************************/
/** The working directory to handle relative file paths from within the File nodes
* defaults to the working directory of the Node-RED process.
*/
//fileWorkingDirectory: "",
/** Allow the Function node to load additional npm modules directly */
functionExternalModules: true,
/** The following property can be used to set predefined values in Global Context.
* This allows extra node modules to be made available with in Function node.
* For example, the following:
* functionGlobalContext: { os:require('os') }
* will allow the `os` module to be accessed in a Function node using:
* global.get("os")
*/
functionGlobalContext: {
// os:require('os'),
},
/** The maximum number of messages nodes will buffer internally as part of their
* operation. This applies across a range of nodes that operate on message sequences.
* defaults to no limit. A value of 0 also means no limit is applied.
*/
//nodeMessageBufferMaxLength: 0,
/** If you installed the optional node-red-dashboard you can set it's path
* relative to httpNodeRoot
* Other optional properties include
* readOnly:{boolean},
* middleware:{function or array}, (req,res,next) - http middleware
* ioMiddleware:{function or array}, (socket,next) - socket.io middleware
*/
//ui: { path: "ui" },
/** Colourise the console output of the debug node */
//debugUseColors: true,
/** The maximum length, in characters, of any message sent to the debug sidebar tab */
debugMaxLength: 1000,
/** Maximum buffer size for the exec node. Defaults to 10Mb */
//execMaxBufferSize: 10000000,
/** Timeout in milliseconds for HTTP request connections. Defaults to 120s */
//httpRequestTimeout: 120000,
/** Retry time in milliseconds for MQTT connections */
mqttReconnectTime: 15000,
/** Retry time in milliseconds for Serial port connections */
serialReconnectTime: 15000,
/** Retry time in milliseconds for TCP socket connections */
//socketReconnectTime: 10000,
/** Timeout in milliseconds for TCP server socket connections. Defaults to no timeout */
//socketTimeout: 120000,
/** Maximum number of messages to wait in queue while attempting to connect to TCP socket
* defaults to 1000
*/
//tcpMsgQueueSize: 2000,
/** Timeout in milliseconds for inbound WebSocket connections that do not
* match any configured node. Defaults to 5000
*/
//inboundWebSocketTimeout: 5000,
/** To disable the option for using local files for storing keys and
* certificates in the TLS configuration node, set this to true.
*/
//tlsConfigDisableLocalFiles: true,
/** The following property can be used to verify websocket connection attempts.
* This allows, for example, the HTTP request headers to be checked to ensure
* they include valid authentication information.
*/
//webSocketNodeVerifyClient: function(info) {
// /** 'info' has three properties:
// * - origin : the value in the Origin header
// * - req : the HTTP request
// * - secure : true if req.connection.authorized or req.connection.encrypted is set
// *
// * The function should return true if the connection should be accepted, false otherwise.
// *
// * Alternatively, if this function is defined to accept a second argument, callback,
// * it can be used to verify the client asynchronously.
// * The callback takes three arguments:
// * - result : boolean, whether to accept the connection or not
// * - code : if result is false, the HTTP error status to return
// * - reason: if result is false, the HTTP reason string to return
// */
//},
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,127 @@
{
"name": "node-red",
"version": "2.2.3",
"description": "Low-code programming for event-driven applications",
"homepage": "http://nodered.org",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/node-red/node-red.git"
},
"private": "true",
"scripts": {
"start": "node $NODE_OPTIONS node_modules/node-red/red.js",
"test": "grunt",
"build": "grunt build",
"dev": "grunt dev",
"build-dev": "grunt build-dev",
"docs": "grunt docs"
},
"contributors": [
{
"name": "Nick O'Leary"
},
{
"name": "Dave Conway-Jones"
}
],
"dependencies": {
"acorn": "8.7.0",
"acorn-walk": "8.2.0",
"ajv": "8.10.0",
"async-mutex": "0.3.2",
"basic-auth": "2.0.1",
"bcryptjs": "2.4.3",
"body-parser": "1.19.1",
"cheerio": "1.0.0-rc.10",
"clone": "2.1.2",
"content-type": "1.0.4",
"cookie": "0.4.2",
"cookie-parser": "1.4.6",
"cors": "2.8.5",
"cronosjs": "1.7.1",
"denque": "2.0.1",
"express": "4.17.2",
"express-session": "1.17.2",
"form-data": "4.0.0",
"fs-extra": "10.0.0",
"fs.notify": "0.0.4",
"got": "11.8.3",
"hash-sum": "2.0.0",
"hpagent": "0.1.2",
"https-proxy-agent": "5.0.0",
"i18next": "21.6.11",
"iconv-lite": "0.6.3",
"is-utf8": "0.2.1",
"js-yaml": "3.14.1",
"json-stringify-safe": "5.0.1",
"jsonata": "1.8.6",
"lodash.clonedeep": "^4.5.0",
"media-typer": "1.1.0",
"memorystore": "1.6.7",
"mime": "3.0.0",
"moment-timezone": "0.5.34",
"mqtt": "4.3.5",
"multer": "1.4.4",
"mustache": "4.2.0",
"node-red": "2.2.3",
"node-red-admin": "^2.2.3",
"node-red-contrib-pythonshell": "github:namgk/node-red-contrib-pythonshell",
"nopt": "5.0.0",
"oauth2orize": "1.11.1",
"on-headers": "1.0.2",
"passport": "0.5.2",
"passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2",
"raw-body": "2.4.3",
"semver": "7.3.5",
"tar": "6.1.11",
"tough-cookie": "4.0.0",
"uglify-js": "3.15.1",
"uuid": "8.3.2",
"ws": "7.5.6",
"xml2js": "0.4.23"
},
"optionalDependencies": {
"bcrypt": "5.0.1"
},
"devDependencies": {
"dompurify": "2.3.6",
"grunt": "1.5.2",
"grunt-chmod": "~1.1.1",
"grunt-cli": "~1.4.3",
"grunt-concurrent": "3.0.0",
"grunt-contrib-clean": "~2.0.0",
"grunt-contrib-compress": "2.0.0",
"grunt-contrib-concat": "~1.0.1",
"grunt-contrib-copy": "~1.0.0",
"grunt-contrib-jshint": "3.1.1",
"grunt-contrib-uglify": "5.0.1",
"grunt-contrib-watch": "~1.1.0",
"grunt-jsdoc": "2.4.1",
"grunt-jsdoc-to-markdown": "6.0.0",
"grunt-jsonlint": "2.1.3",
"grunt-mkdir": "~1.1.0",
"grunt-npm-command": "~0.1.2",
"grunt-sass": "~3.1.0",
"grunt-simple-mocha": "~0.4.1",
"grunt-simple-nyc": "^3.0.1",
"i18next-http-backend": "1.3.2",
"jquery-i18next": "1.2.1",
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
"marked": "4.0.12",
"minami": "1.2.3",
"mocha": "9.2.0",
"node-red-node-test-helper": "^0.2.7",
"nodemon": "2.0.15",
"proxy": "^1.0.2",
"sass": "1.49.7",
"should": "13.2.3",
"sinon": "11.1.2",
"stoppable": "^1.1.0",
"supertest": "6.2.2"
},
"engines": {
"node": ">=12"
}
}

View File

@ -0,0 +1,14 @@
#!/usr/bin/env bash
target=$1
if [ "$#" -eq 1 ]
then
USERDIR=/data/$target
fi
echo "run with userdir=$USERDIR"
USERDIR=$USERDIR docker compose up
#USERDIR=$USERDIR docker compose convert

View File

@ -0,0 +1,14 @@
#!/bin/bash
trap stop SIGINT SIGTERM
function stop() {
kill $CHILD_PID
wait $CHILD_PID
}
/usr/local/bin/node $NODE_OPTIONS node_modules/node-red/red.js --userDir $USERDIR &
CHILD_PID="$!"
wait "${CHILD_PID}"

View File

@ -0,0 +1,48 @@
# RAG-on-kubeflow-with-nodered
A simple example of RAG on kubeflow with node-red
## Implementation
```
git clone https://github.com/sefgsefg/RAG-pipeline-with-nodered.git
```
```
cd RAG_with_node-red/example
```
```
./run.sh main
```
Problem solve: -bash: ./run.sh: Permission denied
```
chmod +x run.sh
```
```
cd scripts
```
```
chmod +x entrypoint.sh
```
```
cd ..
```
Run ./run.sh main again
```
./run.sh main
```
1.Insstall dependency and build the RAG flow on node-red.
![](https://github.com/sefgsefg/RAG-pipeline-with-nodered/blob/main/node-red_1.png)
2.Double click the RAG node and edit the infos.
![](https://github.com/sefgsefg/RAG-pipeline-with-nodered/blob/main/node-red_2.png)
3.Deploy and run the flow. It will run on the kubeflow pipeline.
![](https://github.com/sefgsefg/RAG-pipeline-with-nodered/blob/main/pipeline.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
kaggle
pandas
tqdm
wget
lightgbm
pyarrow
fastparquet
kaggle
pandas
tqdm
wget
lightgbm
pyarrow
fastparquet

View File

@ -1,348 +1,348 @@
# Objective
This example is based on the Bluebook for bulldozers competition (https://www.kaggle.com/competitions/bluebook-for-bulldozers/overview). The objective of this exercise is to predict the sale price of bulldozers sold at auctions.
## Environment
This pipeline was tested using Kubeflow 1.4 and kfp 1.1.2 and x86-64 and ARM based system which includes all Intel and AMD based CPU's and M1/M2 series Macbooks.
## Step 1: Setup Kubeflow as a Service
- If you havent already, sign up (https://www.arrikto.com/kubeflow-as-a-service/)
- Deploy Kubeflow
## Step 2: Launch a Notebook Server
- Bump memory to 2GB and vCPUs to 2
## Step 3: Clone the Project Repo to Your Notebook
- (Kubeflow as a Service) Open up a terminal in the Notebook Server and git clone the kubeflow/examples repository
```
git clone https://github.com/kubeflow/examples
```
## Step 4: Setup DockerHub and Docker
- If you havent already, sign up (https://hub.docker.com/) for DockerHub
- If you havent already, install Docker Desktop (https://www.docker.com/products/docker-desktop/) locally OR install the Docker command line utility (https://docs.docker.com/get-docker/) and enter `sudo docker login` command in your terminal and log into Docker with your your DockerHub username and password
## Step 5: Setup Kaggle
- If you havent already done so, sign up (https://www.kaggle.com/) for Kaggle
- (On Kaggle) Generate an API token (https://www.kaggle.com/docs/api)
- (Kubeflow as a Service) Create a Kubernetes secret
```
kubectl create secret generic kaggle-secret --from-literal=KAGGLE_USERNAME=<username> --from-literal=KAGGLE_KEY=<api_token>
```
## Step 6: Install Git
- (Locally) If you dont have it already, install Git (https://github.com/git-guides/install-git)
## Step 7: Clone the Project Repo Locally
- (Locally) Git clone the `kubeflow/examples` repository
```
git clone https://github.com/kubeflow/examples
```
## Step 8: Create a PodDefault Resource
- (Kubeflow as a Service) Navigate to the `bluebook-for-bulldozers-kaggle-competition directory`
- Create a resource.yaml file
resource.yaml:
```
apiVersion: "kubeflow.org/v1alpha1"
kind: PodDefault
metadata:
name: kaggle-access
spec:
selector:
matchLabels:
kaggle-secret: "true"
desc: "kaggle-access"
volumeMounts:
- name: secret-volume
mountPath: /secret/kaggle
volumes:
- name: secret-volume
secret:
secretName: kaggle-secret
```
<img width="660" alt="image3" src="https://user-images.githubusercontent.com/17012391/177049116-b4186ec3-becb-40ea-973a-27bc52f90619.png">
- Apply resource.yaml using `kubectl apply -f resource.yaml`
## Step 9: Explore the load-data directory
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/load-data` directory
- Open up the `load.py` file
- Note the code in this file that will perform the actions required in the “load-data” pipeline step
<img width="209" alt="image7" src="https://user-images.githubusercontent.com/17012391/177049222-dab4c362-f06d-42ca-a07c-e61a0b301670.png">
## Step 10: Build the load Docker Image
- (Locally) Navigate to the bluebook-for-bulldozers-kaggle-competition/pipeline-components/load-data directory
- Build the Docker image if locally you are using arm64 (Apple M1)
```
docker build --platform=linux/amd64 -t <docker_username>/<docker_imagename>:<tag>-amd64 .
```
- OR build the Docker image if locally you are using amd64
```
docker build -t <docker_username>/<docker_imagename>:<tag> .
```
## Step 11: Push the load Docker Image to DockerHub
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/load-data` directory
- Push the Docker image if locally you are using arm64 (Apple M1)
```
docker push <docker_username>/<docker_imagename>:<tag>-amd64
```
- OR build the Docker image if locally you are using amd64
```
docker push <docker_username>/<docker_imagename>:<tag>
```
## Step 12: Explore the preprocess directory
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/preprocess` directory
- Open up the `preprocess.py` file
- Note the code in this file that will perform the actions required in the “preprocess” pipeline step
<img width="209" alt="image5" src="https://user-images.githubusercontent.com/17012391/177049651-623fb24a-69c0-4a28-bbe1-3a360719b9ce.png">
## Step 13: Build the preprocess Docker Image
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/preprocess` directory
- Build the Docker image if locally you are using arm64 (Apple M1)
```
docker build --platform=linux/amd64 -t <docker_username>/<docker_imagename>:<tag>-amd64 .
```
- OR build the Docker image if locally you are using amd64
```
docker build -t <docker_username>/<docker_imagename>:<tag> .
```
## Step 14: Push the preprocess Docker Image to DockerHub
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/preprocess` directory
- Push the Docker image if locally you are using arm64 (Apple M1)
```
docker push <docker_username>/<docker_imagename>:<tag>-amd64
```
- OR build the Docker image if locally you are using amd64
```
docker push <docker_username>/<docker_imagename>:<tag>
```
## Step 15: Explore the train directory
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/train` directory
- Open up the train.py file
- Note the code in this file that will perform the actions required in the “train” pipeline step
![image2](https://user-images.githubusercontent.com/17012391/177051233-a32e87db-7771-4b5f-9afe-141063733262.png)
## Step 16: Build the train Docker Image
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/train` directory
- Build the Docker image if locally you are using arm64 (Apple M1)
```
docker build --platform=linux/amd64 -t <docker_username>/<docker_imagename>:<tag>-amd64 .
```
- OR build the Docker image if locally you are using amd64
```
docker build -t <docker_username>/<docker_imagename>:<tag> .
```
## Step 17: Push the train Docker Image to DockerHub
- (Locally) Navigate to the bluebook-for-bulldozers-kaggle-competition/pipeline-components/train directory
- Push the Docker image if locally you are using arm64 (Apple M1)
```
docker push <docker_username>/<docker_imagename>:<tag>-amd64
```
- OR build the Docker image if locally you are using amd64
```
docker push <docker_username>/<docker_imagename>:<tag>
```
## Step 18: Explore the test directory
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/test` directory
- Open up the `test.py` file
- Note the code in this file that will perform the actions required in the “test” pipeline step
<img width="237" alt="image6" src="https://user-images.githubusercontent.com/17012391/177051308-31b27ad7-71f3-47af-a068-de381fe64b5b.png">
## Step 19: Build the test Docker Image
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/test` directory
- Build the Docker image if locally you are using arm64 (Apple M1)
```
docker build --platform=linux/amd64 -t <docker_username>/<docker_imagename>:<tag>-amd64 .
```
- OR build the Docker image if locally you are using amd64
```
docker build -t <docker_username>/<docker_imagename>:<tag> .
```
## Step 20: Push the test Docker Image to DockerHub
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/test` directory
- Push the Docker image if locally you are using arm64 (Apple M1)
```
docker push <docker_username>/<docker_imagename>:<tag>-amd64
```
- OR build the Docker image if locally you are using amd64
```
docker push <docker_username>/<docker_imagename>:<tag>
```
## Step 21: Modify the blue-book-for-bulldozers-kfp.py file
(Kubeflow as a Service) Navigate to the `bluebook-for-bulldozers-kaggle-competition` directory
Update the `bluebook-for-bulldozers-kaggle-competition-kfp.py` with accurate Docker Image inputs
```
return dsl.ContainerOp(
name = 'load-data',
image = '<dockerhub username>/<image name>:<tag>',
—-----
def PreProcess(comp1):
return dsl.ContainerOp(
name = 'preprocess',
image = '<dockerhub username>/<image name>:<tag>',
—-----
def Train(comp2):
return dsl.ContainerOp(
name = 'train',
image = '<dockerhub username>/<image name>:<tag>',
—-----
def Test(comp3):
return dsl.ContainerOp(
name = 'test',
image = '<dockerhub username>/<image name>:<tag>',
```
## Step 22: Generate a KFP Pipeline yaml File
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition` directory and delete the existing `blue-book-for-bulldozers-kaggle-competition-kfp.yaml` file
- (Kubeflow as a Service) Navigate to the `bluebook-for-bulldozers-kaggle-competition` directory
Build a python virtual environment:
Step a) Update pip
```
python3 -m pip install --upgrade pip
```
Step b) Install virtualenv
```
sudo pip3 install virtualenv
```
Step c) Check the installed version of venv
```
virtualenv --version
```
Step d) Name your virtual enviornment as kfp
```
virtualenv kfp
```
Step e) Activate your venv.
```
source kfp/bin/activate
```
After this virtual environment will get activated. Now in our activated venv we need to install following packages:
```
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install -y git python3-pip
python3 -m pip install kfp==1.1.2
```
After installing packages create the yaml file
Inside venv point your terminal to a path which contains our kfp file to build pipeline (blue-book-for-bulldozers-kaggle-competition-kfp.py) and run these commands to generate a `yaml` file for the Pipeline:
```
blue-book-for-bulldozers-kaggle-competition-kfp.py
```
<img width="496" alt="Screenshot 2022-07-04 at 12 01 51 AM" src="https://user-images.githubusercontent.com/17012391/177052742-4dae4647-b51b-4f36-94b0-3114130c756b.png">
- Download the `bluebook-for-bulldozers-kaggle-competition.yaml` file that was created to your local `bluebook-for-bulldozers-kaggle-competition` directory
## Step 23: Create an Experiment
- (Kubeflow as a Service) Within the Kubeflow Central Dashboard, navigate to the Experiments (KFP) > Create Experiment view
- Name the experiment and click Next
- Click on Experiments (KFP) to view the experiment you just created
## Step 24: Create a Pipeline
- (Kubeflow as a Service) Within the Kubeflow Central Dashboard, navigate to the Pipelines > +Upload Pipeline view
- Name the pipeline
- Click on Upload a file
- Upload the local bluebook-for-bulldozers-kaggle-competition.py.yaml file
- Click Create
Step 25: Create a Run
- (Kubeflow as a Service) Click on Create Run in the view from the previous step
- Choose the experiment we created in Step 23
- Click Start
- Click on the run name to view the runtime execution graph
<img width="285" alt="Screenshot 2022-07-04 at 12 04 43 AM" src="https://user-images.githubusercontent.com/17012391/177052835-d2cde097-7354-4cac-8876-7d89244864d3.png">
## Troubleshooting Tips:
While running the pipeline as mentioned above you may come across this error:
![kaggle-secret-error-01](https://user-images.githubusercontent.com/17012391/175290593-aac58d80-0d9f-47bd-bd20-46e6f5207210.PNG)
errorlog:
```
kaggle.rest.ApiException: (403)
Reason: Forbidden
HTTP response headers: HTTPHeaderDict({'Content-Type': 'application/json', 'Date': 'Thu, 23 Jun 2022 11:31:18 GMT', 'Access-Control-Allow-Credentials': 'true', 'Set-Cookie': 'ka_sessionid=6817a347c75399a531148e19cad0aaeb; max-age=2626560; path=/, GCLB=CIGths3--ebbUg; path=/; HttpOnly', 'Transfer-Encoding': 'chunked', 'Vary':
HTTP response body: b'{"code":403,"message":"You must accept this competition\\u0027s rules before you\\u0027ll be able to download files."}'
```
This error occours for two reasons:
- Your Kaggle account is not verified with your phone number.
- Rules for this specific competitions are not accepted.
Lets accept Rules of Bulldozers competition
![kaggle-secret-error-02](https://user-images.githubusercontent.com/17012391/175291406-7a30e06d-fc05-44c3-b33c-bccd31b381bd.PNG)
Click on "I Understand and Accept". After this you will be prompted to verify your account using your phone number:
![kaggle-secret-error-03](https://user-images.githubusercontent.com/17012391/175291608-daad1a47-119a-4e47-b48b-4f878d65ddd7.PNG)
Add your phone number and Kaggle will send the code to your number, enter this code and verify your account. ( Note: pipeline wont run if your Kaggle account is not verified )
## Success
After the kaggle account is verified pipeline run is successful we will get the following:
<img width="1380" alt="Screenshot 2022-06-10 at 12 04 48 AM" src="https://user-images.githubusercontent.com/17012391/172920115-ccefd333-c500-4577-afcb-8487c2208371.png">
# Objective
This example is based on the Bluebook for bulldozers competition (https://www.kaggle.com/competitions/bluebook-for-bulldozers/overview). The objective of this exercise is to predict the sale price of bulldozers sold at auctions.
## Environment
This pipeline was tested using Kubeflow 1.4 and kfp 1.1.2 and x86-64 and ARM based system which includes all Intel and AMD based CPU's and M1/M2 series Macbooks.
## Step 1: Setup Kubeflow as a Service
- If you havent already, sign up (https://www.arrikto.com/kubeflow-as-a-service/)
- Deploy Kubeflow
## Step 2: Launch a Notebook Server
- Bump memory to 2GB and vCPUs to 2
## Step 3: Clone the Project Repo to Your Notebook
- (Kubeflow as a Service) Open up a terminal in the Notebook Server and git clone the kubeflow/examples repository
```
git clone https://github.com/kubeflow/examples
```
## Step 4: Setup DockerHub and Docker
- If you havent already, sign up (https://hub.docker.com/) for DockerHub
- If you havent already, install Docker Desktop (https://www.docker.com/products/docker-desktop/) locally OR install the Docker command line utility (https://docs.docker.com/get-docker/) and enter `sudo docker login` command in your terminal and log into Docker with your your DockerHub username and password
## Step 5: Setup Kaggle
- If you havent already done so, sign up (https://www.kaggle.com/) for Kaggle
- (On Kaggle) Generate an API token (https://www.kaggle.com/docs/api)
- (Kubeflow as a Service) Create a Kubernetes secret
```
kubectl create secret generic kaggle-secret --from-literal=KAGGLE_USERNAME=<username> --from-literal=KAGGLE_KEY=<api_token>
```
## Step 6: Install Git
- (Locally) If you dont have it already, install Git (https://github.com/git-guides/install-git)
## Step 7: Clone the Project Repo Locally
- (Locally) Git clone the `kubeflow/examples` repository
```
git clone https://github.com/kubeflow/examples
```
## Step 8: Create a PodDefault Resource
- (Kubeflow as a Service) Navigate to the `bluebook-for-bulldozers-kaggle-competition directory`
- Create a resource.yaml file
resource.yaml:
```
apiVersion: "kubeflow.org/v1alpha1"
kind: PodDefault
metadata:
name: kaggle-access
spec:
selector:
matchLabels:
kaggle-secret: "true"
desc: "kaggle-access"
volumeMounts:
- name: secret-volume
mountPath: /secret/kaggle
volumes:
- name: secret-volume
secret:
secretName: kaggle-secret
```
<img width="660" alt="image3" src="https://user-images.githubusercontent.com/17012391/177049116-b4186ec3-becb-40ea-973a-27bc52f90619.png">
- Apply resource.yaml using `kubectl apply -f resource.yaml`
## Step 9: Explore the load-data directory
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/load-data` directory
- Open up the `load.py` file
- Note the code in this file that will perform the actions required in the “load-data” pipeline step
<img width="209" alt="image7" src="https://user-images.githubusercontent.com/17012391/177049222-dab4c362-f06d-42ca-a07c-e61a0b301670.png">
## Step 10: Build the load Docker Image
- (Locally) Navigate to the bluebook-for-bulldozers-kaggle-competition/pipeline-components/load-data directory
- Build the Docker image if locally you are using arm64 (Apple M1)
```
docker build --platform=linux/amd64 -t <docker_username>/<docker_imagename>:<tag>-amd64 .
```
- OR build the Docker image if locally you are using amd64
```
docker build -t <docker_username>/<docker_imagename>:<tag> .
```
## Step 11: Push the load Docker Image to DockerHub
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/load-data` directory
- Push the Docker image if locally you are using arm64 (Apple M1)
```
docker push <docker_username>/<docker_imagename>:<tag>-amd64
```
- OR build the Docker image if locally you are using amd64
```
docker push <docker_username>/<docker_imagename>:<tag>
```
## Step 12: Explore the preprocess directory
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/preprocess` directory
- Open up the `preprocess.py` file
- Note the code in this file that will perform the actions required in the “preprocess” pipeline step
<img width="209" alt="image5" src="https://user-images.githubusercontent.com/17012391/177049651-623fb24a-69c0-4a28-bbe1-3a360719b9ce.png">
## Step 13: Build the preprocess Docker Image
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/preprocess` directory
- Build the Docker image if locally you are using arm64 (Apple M1)
```
docker build --platform=linux/amd64 -t <docker_username>/<docker_imagename>:<tag>-amd64 .
```
- OR build the Docker image if locally you are using amd64
```
docker build -t <docker_username>/<docker_imagename>:<tag> .
```
## Step 14: Push the preprocess Docker Image to DockerHub
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/preprocess` directory
- Push the Docker image if locally you are using arm64 (Apple M1)
```
docker push <docker_username>/<docker_imagename>:<tag>-amd64
```
- OR build the Docker image if locally you are using amd64
```
docker push <docker_username>/<docker_imagename>:<tag>
```
## Step 15: Explore the train directory
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/train` directory
- Open up the train.py file
- Note the code in this file that will perform the actions required in the “train” pipeline step
![image2](https://user-images.githubusercontent.com/17012391/177051233-a32e87db-7771-4b5f-9afe-141063733262.png)
## Step 16: Build the train Docker Image
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/train` directory
- Build the Docker image if locally you are using arm64 (Apple M1)
```
docker build --platform=linux/amd64 -t <docker_username>/<docker_imagename>:<tag>-amd64 .
```
- OR build the Docker image if locally you are using amd64
```
docker build -t <docker_username>/<docker_imagename>:<tag> .
```
## Step 17: Push the train Docker Image to DockerHub
- (Locally) Navigate to the bluebook-for-bulldozers-kaggle-competition/pipeline-components/train directory
- Push the Docker image if locally you are using arm64 (Apple M1)
```
docker push <docker_username>/<docker_imagename>:<tag>-amd64
```
- OR build the Docker image if locally you are using amd64
```
docker push <docker_username>/<docker_imagename>:<tag>
```
## Step 18: Explore the test directory
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/test` directory
- Open up the `test.py` file
- Note the code in this file that will perform the actions required in the “test” pipeline step
<img width="237" alt="image6" src="https://user-images.githubusercontent.com/17012391/177051308-31b27ad7-71f3-47af-a068-de381fe64b5b.png">
## Step 19: Build the test Docker Image
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/test` directory
- Build the Docker image if locally you are using arm64 (Apple M1)
```
docker build --platform=linux/amd64 -t <docker_username>/<docker_imagename>:<tag>-amd64 .
```
- OR build the Docker image if locally you are using amd64
```
docker build -t <docker_username>/<docker_imagename>:<tag> .
```
## Step 20: Push the test Docker Image to DockerHub
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition/pipeline-components/test` directory
- Push the Docker image if locally you are using arm64 (Apple M1)
```
docker push <docker_username>/<docker_imagename>:<tag>-amd64
```
- OR build the Docker image if locally you are using amd64
```
docker push <docker_username>/<docker_imagename>:<tag>
```
## Step 21: Modify the blue-book-for-bulldozers-kfp.py file
(Kubeflow as a Service) Navigate to the `bluebook-for-bulldozers-kaggle-competition` directory
Update the `bluebook-for-bulldozers-kaggle-competition-kfp.py` with accurate Docker Image inputs
```
return dsl.ContainerOp(
name = 'load-data',
image = '<dockerhub username>/<image name>:<tag>',
—-----
def PreProcess(comp1):
return dsl.ContainerOp(
name = 'preprocess',
image = '<dockerhub username>/<image name>:<tag>',
—-----
def Train(comp2):
return dsl.ContainerOp(
name = 'train',
image = '<dockerhub username>/<image name>:<tag>',
—-----
def Test(comp3):
return dsl.ContainerOp(
name = 'test',
image = '<dockerhub username>/<image name>:<tag>',
```
## Step 22: Generate a KFP Pipeline yaml File
- (Locally) Navigate to the `bluebook-for-bulldozers-kaggle-competition` directory and delete the existing `blue-book-for-bulldozers-kaggle-competition-kfp.yaml` file
- (Kubeflow as a Service) Navigate to the `bluebook-for-bulldozers-kaggle-competition` directory
Build a python virtual environment:
Step a) Update pip
```
python3 -m pip install --upgrade pip
```
Step b) Install virtualenv
```
sudo pip3 install virtualenv
```
Step c) Check the installed version of venv
```
virtualenv --version
```
Step d) Name your virtual enviornment as kfp
```
virtualenv kfp
```
Step e) Activate your venv.
```
source kfp/bin/activate
```
After this virtual environment will get activated. Now in our activated venv we need to install following packages:
```
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install -y git python3-pip
python3 -m pip install kfp==1.1.2
```
After installing packages create the yaml file
Inside venv point your terminal to a path which contains our kfp file to build pipeline (blue-book-for-bulldozers-kaggle-competition-kfp.py) and run these commands to generate a `yaml` file for the Pipeline:
```
blue-book-for-bulldozers-kaggle-competition-kfp.py
```
<img width="496" alt="Screenshot 2022-07-04 at 12 01 51 AM" src="https://user-images.githubusercontent.com/17012391/177052742-4dae4647-b51b-4f36-94b0-3114130c756b.png">
- Download the `bluebook-for-bulldozers-kaggle-competition.yaml` file that was created to your local `bluebook-for-bulldozers-kaggle-competition` directory
## Step 23: Create an Experiment
- (Kubeflow as a Service) Within the Kubeflow Central Dashboard, navigate to the Experiments (KFP) > Create Experiment view
- Name the experiment and click Next
- Click on Experiments (KFP) to view the experiment you just created
## Step 24: Create a Pipeline
- (Kubeflow as a Service) Within the Kubeflow Central Dashboard, navigate to the Pipelines > +Upload Pipeline view
- Name the pipeline
- Click on Upload a file
- Upload the local bluebook-for-bulldozers-kaggle-competition.py.yaml file
- Click Create
Step 25: Create a Run
- (Kubeflow as a Service) Click on Create Run in the view from the previous step
- Choose the experiment we created in Step 23
- Click Start
- Click on the run name to view the runtime execution graph
<img width="285" alt="Screenshot 2022-07-04 at 12 04 43 AM" src="https://user-images.githubusercontent.com/17012391/177052835-d2cde097-7354-4cac-8876-7d89244864d3.png">
## Troubleshooting Tips:
While running the pipeline as mentioned above you may come across this error:
![kaggle-secret-error-01](https://user-images.githubusercontent.com/17012391/175290593-aac58d80-0d9f-47bd-bd20-46e6f5207210.PNG)
errorlog:
```
kaggle.rest.ApiException: (403)
Reason: Forbidden
HTTP response headers: HTTPHeaderDict({'Content-Type': 'application/json', 'Date': 'Thu, 23 Jun 2022 11:31:18 GMT', 'Access-Control-Allow-Credentials': 'true', 'Set-Cookie': 'ka_sessionid=6817a347c75399a531148e19cad0aaeb; max-age=2626560; path=/, GCLB=CIGths3--ebbUg; path=/; HttpOnly', 'Transfer-Encoding': 'chunked', 'Vary':
HTTP response body: b'{"code":403,"message":"You must accept this competition\\u0027s rules before you\\u0027ll be able to download files."}'
```
This error occours for two reasons:
- Your Kaggle account is not verified with your phone number.
- Rules for this specific competitions are not accepted.
Lets accept Rules of Bulldozers competition
![kaggle-secret-error-02](https://user-images.githubusercontent.com/17012391/175291406-7a30e06d-fc05-44c3-b33c-bccd31b381bd.PNG)
Click on "I Understand and Accept". After this you will be prompted to verify your account using your phone number:
![kaggle-secret-error-03](https://user-images.githubusercontent.com/17012391/175291608-daad1a47-119a-4e47-b48b-4f878d65ddd7.PNG)
Add your phone number and Kaggle will send the code to your number, enter this code and verify your account. ( Note: pipeline wont run if your Kaggle account is not verified )
## Success
After the kaggle account is verified pipeline run is successful we will get the following:
<img width="1380" alt="Screenshot 2022-06-10 at 12 04 48 AM" src="https://user-images.githubusercontent.com/17012391/172920115-ccefd333-c500-4577-afcb-8487c2208371.png">

View File

@ -1,62 +1,62 @@
import kfp
from kfp import dsl
def LoadData():
vop = dsl.VolumeOp(name="pvc",
resource_name="pvc", size='1Gi',
modes=dsl.VOLUME_MODE_RWO)
return dsl.ContainerOp(
name = 'load-data',
image = 'hubdocker76/bulldozers:v6',
command = ['python3', 'load.py'],
pvolumes={
'/data': vop.volume
}
)
def PreProcess(comp1):
return dsl.ContainerOp(
name = 'preprocess',
image = 'hubdocker76/bulldozers-preprocess:v1',
pvolumes={
'/data': comp1.pvolumes['/data']
},
command = ['python3', 'preprocess.py']
)
def Train(comp2):
return dsl.ContainerOp(
name = 'train',
image = 'hubdocker76/bulldozers-train:v2',
pvolumes={
'/data': comp2.pvolumes['/data']
},
command = ['python3', 'train.py']
)
def Test(comp3):
return dsl.ContainerOp(
name = 'test',
image = 'hubdocker76/bulldozers-test:v2',
pvolumes={
'/data': comp3.pvolumes['/data']
},
command = ['python3', 'test.py']
)
@dsl.pipeline(
name = 'blue book for bulldozers',
description = 'pipeline to run blue book for bulldozers')
def passing_parameter():
comp1 = LoadData().add_pod_label("kaggle-secret", "true")
comp2 = PreProcess(comp1)
comp3 = Train(comp2)
comp4 = Test(comp3)
if __name__ == '__main__':
import kfp.compiler as compiler
compiler.Compiler().compile(passing_parameter, __file__[:-3]+ '.yaml')
import kfp
from kfp import dsl
def LoadData():
vop = dsl.VolumeOp(name="pvc",
resource_name="pvc", size='1Gi',
modes=dsl.VOLUME_MODE_RWO)
return dsl.ContainerOp(
name = 'load-data',
image = 'hubdocker76/bulldozers:v6',
command = ['python3', 'load.py'],
pvolumes={
'/data': vop.volume
}
)
def PreProcess(comp1):
return dsl.ContainerOp(
name = 'preprocess',
image = 'hubdocker76/bulldozers-preprocess:v1',
pvolumes={
'/data': comp1.pvolumes['/data']
},
command = ['python3', 'preprocess.py']
)
def Train(comp2):
return dsl.ContainerOp(
name = 'train',
image = 'hubdocker76/bulldozers-train:v2',
pvolumes={
'/data': comp2.pvolumes['/data']
},
command = ['python3', 'train.py']
)
def Test(comp3):
return dsl.ContainerOp(
name = 'test',
image = 'hubdocker76/bulldozers-test:v2',
pvolumes={
'/data': comp3.pvolumes['/data']
},
command = ['python3', 'test.py']
)
@dsl.pipeline(
name = 'blue book for bulldozers',
description = 'pipeline to run blue book for bulldozers')
def passing_parameter():
comp1 = LoadData().add_pod_label("kaggle-secret", "true")
comp2 = PreProcess(comp1)
comp3 = Train(comp2)
comp4 = Test(comp3)
if __name__ == '__main__':
import kfp.compiler as compiler
compiler.Compiler().compile(passing_parameter, __file__[:-3]+ '.yaml')

View File

0
code_search/docker/ks/submit_code_embeddings_job.sh Executable file → Normal file
View File

0
code_search/docker/ks/update_index.sh Executable file → Normal file
View File

0
code_search/docker/t2t/t2t-entrypoint.sh Executable file → Normal file
View File

0
code_search/docker/ui/build.sh Executable file → Normal file
View File

View File

@ -1,4 +0,0 @@
local components = std.extVar("__ksonnet/components");
components + {
// Insert user-specified overrides here.
}

View File

@ -1,9 +0,0 @@
{
// Warning: Do not define a global "image" as that will end up overriding
// the image parameter for all components. Define more specific names
// e.g. "dataflowImage", "trainerCpuImage", "trainerGpuImage",
workingDir: "gs://code-search-demo/20181104",
dataDir: "gs://code-search-demo/20181104/data",
project: "code-search-demo",
experiment: "demo-trainer-11-07-dist-sync-gpu",
}

View File

@ -1,8 +0,0 @@
local base = import "base.libsonnet";
// uncomment if you reference ksonnet-lib
// local k = import "k.libsonnet";
base {
// Insert user-specified overrides here. For example if a component is named \"nginx-deployment\", you might have something like:\n")
// "nginx-deployment"+: k.deployment.mixin.metadata.labels({foo: "bar"})
}

View File

@ -1,22 +0,0 @@
local params = std.extVar('__ksonnet/params');
local globals = import 'globals.libsonnet';
local envParams = params {
components+: {
"t2t-code-search"+: {},
"t2t-code-search-datagen"+: {
githubTable: '',
},
"submit-preprocess-job"+: {
githubTable: '',
},
"search-index-server"+: {
},
},
};
{
components: {
[x]: envParams.components[x] + globals
for x in std.objectFields(envParams.components)
},
}

View File

@ -1,7 +0,0 @@
{
// Warning: Do not define a global "image" as that will end up overriding
// the image parameter for all components. Define more specific names
// e.g. "dataflowImage", "trainerCpuImage", "trainerGpuImage",
experiment: "pipeline",
waitUntilFinish: "true",
}

View File

@ -1,8 +0,0 @@
local base = import "base.libsonnet";
// uncomment if you reference ksonnet-lib
// local k = import "k.libsonnet";
base + {
// Insert user-specified overrides here. For example if a component is named \"nginx-deployment\", you might have something like:\n")
// "nginx-deployment"+: k.deployment.mixin.metadata.labels({foo: "bar"})
}

View File

@ -1,12 +0,0 @@
local params = std.extVar("__ksonnet/params");
local globals = import "globals.libsonnet";
local envParams = params + {
components +: {
},
};
{
components: {
[x]: envParams.components[x] + globals, for x in std.objectFields(envParams.components)
},
}

View File

View File

@ -1,62 +1,62 @@
import kfp
from kfp import dsl
def create_pv():
return dsl.VolumeOp(
name="create_pv",
resource_name="kfp-pvc",
size="1Gi",
modes=dsl.VOLUME_MODE_RWO
)
def parallel_1(vol_name: str):
cop = dsl.ContainerOp(
name='generate_data',
image='bash:5.1',
command=['sh', '-c'],
arguments=['echo 1 | tee /mnt/out1.txt']
)
cop.container.set_image_pull_policy('IfNotPresent')
cop.add_pvolumes({'/mnt': dsl.PipelineVolume(pvc=vol_name)})
return cop
def parallel_2(vol_name: str):
cop = dsl.ContainerOp(
name='generate_data',
image='bash:5.1',
command=['sh', '-c'],
arguments=['echo 2 | tee /mnt/out2.txt']
)
cop.container.set_image_pull_policy('IfNotPresent')
cop.add_pvolumes({'/mnt': dsl.PipelineVolume(pvc=vol_name)})
return cop
def parallel_3(vol_name: str):
cop = dsl.ContainerOp(
name='generate_data',
image='bash:5.1',
command=['sh', '-c'],
arguments=['echo 3 | tee /mnt/out3.txt']
)
cop.container.set_image_pull_policy('IfNotPresent')
cop.add_pvolumes({'/mnt': dsl.PipelineVolume(pvc=vol_name)})
return cop
@dsl.pipeline(
name="Kubeflow volume parallel example",
description="Demonstrate the use case of volume on Kubeflow pipeline.")
def volume_parallel():
vop = create_pv()
cop1 = parallel_1(vop.outputs["name"]).after(vop)
cop2 = parallel_2(vop.outputs["name"]).after(vop)
cop3 = parallel_3(vop.outputs["name"]).after(vop)
if __name__ == "__main__":
import kfp.compiler as compiler
import kfp
from kfp import dsl
def create_pv():
return dsl.VolumeOp(
name="create_pv",
resource_name="kfp-pvc",
size="1Gi",
modes=dsl.VOLUME_MODE_RWO
)
def parallel_1(vol_name: str):
cop = dsl.ContainerOp(
name='generate_data',
image='bash:5.1',
command=['sh', '-c'],
arguments=['echo 1 | tee /mnt/out1.txt']
)
cop.container.set_image_pull_policy('IfNotPresent')
cop.add_pvolumes({'/mnt': dsl.PipelineVolume(pvc=vol_name)})
return cop
def parallel_2(vol_name: str):
cop = dsl.ContainerOp(
name='generate_data',
image='bash:5.1',
command=['sh', '-c'],
arguments=['echo 2 | tee /mnt/out2.txt']
)
cop.container.set_image_pull_policy('IfNotPresent')
cop.add_pvolumes({'/mnt': dsl.PipelineVolume(pvc=vol_name)})
return cop
def parallel_3(vol_name: str):
cop = dsl.ContainerOp(
name='generate_data',
image='bash:5.1',
command=['sh', '-c'],
arguments=['echo 3 | tee /mnt/out3.txt']
)
cop.container.set_image_pull_policy('IfNotPresent')
cop.add_pvolumes({'/mnt': dsl.PipelineVolume(pvc=vol_name)})
return cop
@dsl.pipeline(
name="Kubeflow volume parallel example",
description="Demonstrate the use case of volume on Kubeflow pipeline.")
def volume_parallel():
vop = create_pv()
cop1 = parallel_1(vop.outputs["name"]).after(vop)
cop2 = parallel_2(vop.outputs["name"]).after(vop)
cop3 = parallel_3(vop.outputs["name"]).after(vop)
if __name__ == "__main__":
import kfp.compiler as compiler
compiler.Compiler().compile(volume_parallel, __file__ + ".yaml")

0
demos/simple_pipeline/gpu-example-pipeline.py Executable file → Normal file
View File

0
demos/yelp_demo/demo_setup/create_context.sh Executable file → Normal file
View File

0
demos/yelp_demo/pipelines/gpu-example-pipeline.py Executable file → Normal file
View File

0
demos/yelp_demo/yelp/yelp_sentiment/worker_launcher.sh Executable file → Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
pandas==1.1.5
seaborn==0.9.0
tensorflow==2.3.0
wget==3.2
pandas==1.1.5
seaborn==0.9.0
tensorflow==2.3.0
wget==3.2

Some files were not shown because too many files have changed in this diff Show More