Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ In order to do so, you need to install the func CLI. You can follow the [officia
???+ success "Verify"
Running `func version` in your terminal to verify the installation, and you should see the version of the func CLI you installed.


???+ bug "Troubleshooting"
If you see `command not found`, you may need to add the func CLI to your PATH.

Expand Down Expand Up @@ -206,9 +207,9 @@ The `sentiment-analysis-app/pyproject.toml` file contains the project configurat
Knative Function will automatically install the dependencies listed here when you build the function.

### **Step 4: Build and run your Knative Function locally (Optional)**

??? info "Click here to expand"



![Image4](images/image4.png)

In Knative Function, there are two ways to build: using the [pack build](https://github.com/knative/func/blob/8f3f718a5a036aa6b6eaa9f70c03aeea740015b9/docs/reference/func_build.md?plain=1#L46){:target="_blank"} or using the [source-to-image (s2i) build](https://github.com/knative/func/blob/4f48549c8ad4dad34bf750db243d81d503f0090f/docs/reference/func_build.md?plain=1#L43){:target="_blank"}.
Expand Down Expand Up @@ -276,7 +277,7 @@ Knative Function will automatically install the dependencies listed here when yo

In this case, you will get the full CloudEvent response:

```
```sh
Context Attributes,
specversion: 1.0
type: new-review-comment
Expand Down Expand Up @@ -319,7 +320,7 @@ func deploy -b=s2i -v
Function deployed in namespace "default" and exposed at URL:
http://sentiment-analysis-app.default.svc.cluster.local
```

!!! tip
You can find the URL of the Knative Function (Knative Service) by running the following command:

Expand All @@ -334,7 +335,6 @@ func deploy -b=s2i -v
sentiment-analysis-app http://sentiment-analysis-app.default.svc.cluster.local sentiment-analysis-app-00001 sentiment-analysis-app-00001 True
```


## **Knative Serving: scale down to zero**

![Image13](images/image13.png)
Expand Down Expand Up @@ -368,7 +368,7 @@ After deployment, the `func` CLI provides a URL to access your function. You can

Simply use Knative Function's command `func invoke` to directly send a CloudEvent to the function on your cluster:

```bash
```sh
func invoke -f=cloudevent --data='{"reviewText":"I love Knative so much"}' -v
```

Expand All @@ -380,7 +380,7 @@ func invoke -f=cloudevent --data='{"reviewText":"I love Knative so much"}' -v

If you see the response, it means that the function is running successfully.

```
```sh
Context Attributes,
specversion: 1.0
type: moderated-comment
Expand All @@ -399,23 +399,15 @@ func invoke -f=cloudevent --data='{"reviewText":"I love Knative so much"}' -v
}
```

## **Next Step**

![Image16](images/image16.png)

In this tutorial, you learned how to create a serverless function for a simple sentiment analysis service with Knative.

## **Next Step**

![Image5](images/image5.png)

Next, we'll deploy another ML service following the same procedure. We encourage you to try it yourself!
Next, we'll deploy another ML service following the same procedure.

!!! tip
Don't forget to `cd` into the root directory `/start` before proceeding.

If you feel comfortable deploying the other ML service yourself, follow this **simplified guide**:

[Go to Deploy ML workflow: Bad word filter :fontawesome-solid-paper-plane:](../page-3/create-bad-word-filter-service.md){ .md-button .md-button--primary }

If you encounter any issues, don't worry—we have a detailed tutorial ready for you.

[Solution - Go to Deploy ML workflow: Bad word filter :fontawesome-solid-paper-plane:](../page-3/solution-create-bad-word-filter-service.md){ .md-button .md-button--primary }
156 changes: 91 additions & 65 deletions docs/versioned/bookstore/page-3/create-bad-word-filter-service.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@ function: tutorial

![Image 4](images/image4.png)

As a bookstore owner, you aim to receive instant notifications in a Slack channel whenever a customer submits a new negative review comment. By leveraging Knative Function, you can set up a serverless function that contains a simple bad word filter service to tell whether the text contains any hateful/insultive speech.

If you ever get stuck, check the solution here.

[Solution - Go to Deploy ML workflow: Bad word filter :fontawesome-solid-paper-plane:](../page-3/solution-create-bad-word-filter-service.md){ .md-button .md-button--primary }
As a bookstore owner, you aim to receive instant notifications in a Slack channel whenever a customer submits a new negative review comment. By leveraging Knative Function, you can set up a serverless function that contains a simple bad word filter service to tell whether the text contains any hateful/insulting speech.

## **What Knative features will we learn about?**

Expand Down Expand Up @@ -59,78 +55,106 @@ func create -l python bad-word-filter

The file tree will look like this:

```
/start/bad-word-filter
├── func.yaml
```txt
start/bad-word-filter
├── .funcignore
├── function
│   ├── func.py
│   └── __init__.py
├── func.yaml
├── .gitignore
├── requirements.txt
├── app.sh
├── test_func.py
├── pyproject.toml
├── README.md
└── Procfile
└── func.py
└── tests
└── test_func.py
```

### **Step 2: Replace the generated code with the bad word filter logic**

![Image 5](images/image5.png)

`bad-word-filter/func.py` is the file that contains the code for the function. You can replace the generated code with the bad word filter logic. You can use the following code as a starting point:
`bad-word-filter/function/func.py` is the file that contains the code for the function. You can replace the generated code with the bad word filter logic. You can use the following code as a starting point:

???+ abstract "_bad-word-filter/function/func.py_"

???+ abstract "_bad-word-filter/func.py_"
```python
from parliament import Context
from profanity_check import predict
import logging
from cloudevents.http import CloudEvent
from profanity_check import predict

def new():
return Function()

class Function:
async def handle(self, scope, receive, send):
""" Handle all HTTP requests to this Function. The incoming CloudEvent is in scope["event"]. """
logging.info("Request Received")

# 1. Extract the CloudEvent from the scope
request_event = scope["event"]

# The function to convert the bad word filter result into a CloudEvent
def create_cloud_event(inputText, data):
attributes = {
"type": "new-review-comment",
"source": "book-review-broker",
"datacontenttype": "application/json",
"badwordfilter": data,
}

# Put the bad word filter result into a dictionary
data = {"reviewText": inputText, "badWordResult": data}

# Create a CloudEvent object
event = CloudEvent(attributes, data)
return event

def inappropriate_language_filter(text):
profanity_result = predict([text["reviewText"]])
result = "good"
if profanity_result[0] == 1:
result = "bad"

profanity_event = create_cloud_event(text["reviewText"], result)
return profanity_event

def main(context: Context):
"""
Function template
The context parameter contains the Flask request object and any
CloudEvent received with the request.
"""
print("Received CloudEvent: ", context.cloud_event)

# Add your business logic here
return inappropriate_language_filter(context.cloud_event.data)
# 2. Extract the data payload from the event, analyze and create CloudEvent
response_event = self.inappropriate_language_filter(request_event.data)

# 3. Send the response
logging.info(f"Sending response: {response_event.data}")
await send(response_event)

def create_cloud_event(self, inputText, data):
attributes = {
"type": "new-review-comment",
"source": "book-review-broker",
"datacontenttype": "application/json",
"badwordfilter": data,
}

data = {"reviewText": inputText, "badWordResult": data}

return CloudEvent(attributes, data)

def inappropriate_language_filter(self, text):
review_text = text.get("reviewText", "")
profanity_result = predict([review_text])
result = "good"
if profanity_result[0] == 1:
result = "bad"

return self.create_cloud_event(review_text, result)
```

### **Step 3: Configure the dependencies**

![Image 8](images/image8.png)
The content of `bad-word-filter/requirements.txt`:

???+ abstract "_bad-word-filter/requirements.txt_"
```plaintext
parliament-functions==0.1.0
alt-profanity-check==1.4.1.post1
cloudevents==1.10.1
The content of `bad-word-filter/pyproject.toml`:

???+ abstract "_bad-word-filter/pyproject.toml_"

```toml
[project]
name = "function"
description = ""
version = "0.1.0"
requires-python = ">=3.9"
readme = "README.md"
license = "MIT"
dependencies = [
"httpx",
"cloudevents",
"pytest",
"pytest-asyncio",
"alt-profanity-check==1.4.1.post1" # <-- add this dependency
]
authors = [
{ name="Your Name", email="you@example.com"},
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.pytest.ini_options]
asyncio_mode = "strict"
asyncio_default_fixture_loop_scope = "function"
```

### **Step 4: Deploy the function to the cluster**
Expand All @@ -139,12 +163,14 @@ The content of `bad-word-filter/requirements.txt`:
!!! note
Please enter `/bad-word-filter` when you are executing the following commands.

```plaintext
```sh
func deploy -b=s2i -v
```

???+ success "Verify"
Expect to see the following message:
```

```sh
Function deployed in namespace "default" and exposed at URL:
http://bad-word-filter.default.svc.cluster.local
```
Expand All @@ -153,14 +179,14 @@ func deploy -b=s2i -v

![Image 7](images/image7.png)

```plaintext
```sh
func invoke -f=cloudevent --data='{"reviewText":"I love Knative so much"}' -v
```

???+ success "Verify"
Expect to receive a CloudEvent response:

```plaintext
```sh
Context Attributes,
specversion: 1.0
type: new-review-comment
Expand All @@ -183,8 +209,8 @@ If you see the response, it means that the function is running successfully.

![Image 9](images/image9.png)

In this tutorial, you learned how to create a serverless function for a simple service that can detect inappropriate languages in text with Knative.
In this tutorial, you learned how to create a serverless function for a simple service that can detect inappropriate languages in text with Knative.

Next, we'll be learning how to use Knative Sequence to connect the 2 ML workflows and make sure they are executed in the order you want.
Next, we'll be learning how to use Knative Sequence to connect the 2 ML workflows and make sure they are executed in the order you want.

[Go to Create Knative Sequence :fontawesome-solid-paper-plane:](../page-4/create-sequence-to-streamline-ML-workflows.md){ .md-button .md-button--primary }
Loading
Loading