Visitar URL original
Add more steps in module 0 · feast-dev/feast-workshop@df87ade · GitHub
Skip to content

Commit df87ade

Browse files
committed
Add more steps in module 0
Signed-off-by: Danny Chiao <danny@tecton.ai>
1 parent 983d608 commit df87ade

8 files changed

Lines changed: 183 additions & 18 deletions

File tree

‎.github/workflows/feast_plan.yml‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Feast plan
2+
3+
on: [pull_request] # Should be triggered once then manually if possible
4+
5+
jobs:
6+
build:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- name: Setup Python
10+
id: setup-python
11+
uses: actions/setup-python@v2
12+
with:
13+
python-version: "3.7"
14+
architecture: x64
15+
16+
# Get the registry from the previous step and run `feast plan`
17+
- uses: actions/checkout@v2
18+
- name: Install feast
19+
run: pip install feast
20+
- name: Capture `feast plan` in a variable
21+
id: feast_plan
22+
run: |
23+
body=$(cd module_0/feature_repo_aws; feast plan)
24+
body="${body//'%'/'%25'}"
25+
body="${body//$'\n'/'%0A'}"
26+
body="${body//$'\r'/'%0D'}"
27+
echo "::set-output name=body::$body"
28+
29+
# Post a comment on the PR with the results of `feast plan`
30+
- name: Create comment
31+
uses: peter-evans/create-or-update-comment@v1
32+
if: ${{ steps.feast_plan.outputs.body }}
33+
with:
34+
issue-number: ${{ github.event.pull_request.number }}
35+
body: |
36+
${{ steps.feast_plan.outputs.body }}

‎module_0/README.md‎

Lines changed: 128 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ We focus on a specific example (that does not include online features + models):
66
- **Use case**: building a platform for data scientists to share features for training offline models
77
- **Stack**: you have data in a combination of data warehouses (to be explored in a future module) and data lakes (e.g. S3)
88

9-
# 1. Mapping to Feast concepts
9+
# Mapping to Feast concepts
1010
To support this, you'll need:
1111
| Concept | Requirements |
1212
| :-------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -16,19 +16,65 @@ To support this, you'll need:
1616
| Registry | In `feature_store.yaml`, specifying a path (within an existing S3 bucket) the registry is written to. Users + model servers will pull from this to get the latest registered features + metadata |
1717
| Transformations | Feast supports last mile transformations with `OnDemandFeatureView`s that can be re-used |
1818

19-
# 2. User flows
19+
# User flows
2020
There are three user groups here worth considering. The ML platform team, the data scientists, and the ML engineers scheduling models in batch.
2121

22-
## 2a. ML Platform Team
22+
## User flow 1: ML Platform Team
2323
The team here sets up the centralized Feast feature repository in GitHub. This is what's seen in `feature_repo_aws/`.
2424

25+
### Step 0: Setup S3 bucket for registry and file sources
26+
This assumes you have an AWS account & Terraform setup. If you don't:
27+
- Set up an AWS account & setup your credentials as per the [AWS quickstart](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-creds)
28+
- Install [Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli#install-terraform)
29+
30+
31+
We've made a simple Terraform project to help with S3 bucket creation:
32+
```bash
33+
cd infra/
34+
terraform init
35+
terraform apply
36+
```
37+
38+
Output:
39+
```bash
40+
aws_s3_bucket.feast_bucket: Creating...
41+
aws_s3_bucket.feast_bucket: Creation complete after 3s [id=feast-workshop-danny]
42+
aws_s3_bucket_acl.feast_bucket_acl: Creating...
43+
aws_s3_object.driver_stats_upload: Creating...
44+
aws_s3_bucket_acl.feast_bucket_acl: Creation complete after 0s [id=feast-workshop-danny,private]
45+
aws_s3_object.driver_stats_upload: Creation complete after 1s [id=driver_stats.parquet]
46+
47+
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
48+
49+
Outputs:
50+
51+
project_bucket = "s3://feast-workshop-danny"
52+
project_name = "danny"
53+
```
54+
2555
### Step 1: Setup the feature repo
26-
Here, the first thing a platform team needs to do is setup the `feature_store.yaml` within a version controlled repo like GitHub:
56+
The first thing a platform team needs to do is setup the `feature_store.yaml` within a version controlled repo like GitHub. We've setup a sample feature repository in `feature_repo_aws/`
57+
58+
There are two files in `feature_repo_aws` you need to change to point to your S3 bucket:
2759

60+
**data_sources.py**
61+
```python
62+
driver_stats = FileSource(
63+
name="driver_stats_source",
64+
path="s3://[INSERT YOUR BUCKET]/driver_stats.parquet",
65+
s3_endpoint_override="http://s3.us-west-2.amazonaws.com", # Needed since s3fs defaults to us-east-1
66+
timestamp_field="event_timestamp",
67+
created_timestamp_column="created",
68+
description="A table describing the stats of a driver based on hourly logs",
69+
owner="test2@gmail.com",
70+
)
71+
```
72+
73+
**feature_store.yaml**
2874
```yaml
2975
project: feast_demo_aws
3076
provider: aws
31-
registry: s3://[YOUR BUCKET]/registry.pb
77+
registry: s3://[INSERT YOUR BUCKET]/registry.pb
3278
online_store: null
3379
offline_store:
3480
type: file
@@ -37,7 +83,7 @@ flags:
3783
on_demand_transforms: true
3884
```
3985
40-
A quick explanation of what's happening here:
86+
A quick explanation of what's happening in this `feature_store.yaml`:
4187

4288
| Key | What it does | Example |
4389
| :-------------- | :----------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------- |
@@ -54,20 +100,37 @@ A quick explanation of what's happening here:
54100
- **Project**
55101
- Users can only request features from a single project
56102
- **Provider**
57-
- Defaults can be easily overriden in `feature_store.yaml`.
58-
- For example, one can use the `aws` provider and specify Snowflake as the offline store.
103+
- Default offline or online store choices can be easily overriden in `feature_store.yaml`.
104+
- For example, one can use the `aws` provider and specify Snowflake as the offline store:
105+
```yaml
106+
project: feast_demo_aws
107+
provider: aws
108+
registry: s3://[INSERT YOUR BUCKET]/registry.pb
109+
online_store: null
110+
offline_store:
111+
type: snowflake.offline
112+
account: SNOWFLAKE_DEPLOYMENT_URL
113+
user: SNOWFLAKE_USER
114+
password: SNOWFLAKE_PASSWORD
115+
role: SNOWFLAKE_ROLE
116+
warehouse: SNOWFLAKE_WAREHOUSE
117+
database: SNOWFLAKE_DATABASE
118+
119+
```
59120
- **Offline Store**
60121
- We recommend users use data warehouses or Spark as their offline store for performant training dataset generation.
61-
- Here, we use file sources for instructional purposes. This will directly read from files (local or remote) and use Dask to execute point-in-time joins.
122+
- In this workshop, we use file sources for instructional purposes. This will directly read from files (local or remote) and use Dask to execute point-in-time joins.
62123
- A project can only support one type of offline store (cannot mix Snowflake + file for example)
63124
- Each offline store has its own configurations which map to YAML. (e.g. see [BigQueryOfflineStoreConfig](https://rtd.feast.dev/en/master/index.html#feast.infra.offline_stores.bigquery.BigQueryOfflineStoreConfig)):
64125
- **Online Store**
65-
- If you don't need to power real time models with fresh features, this is not needed.
66-
- If you are precomputing predictions in batch ("batch scoring"), then the online store is optional. You should be using the offline store and running `feature_store.get_historical_features`
126+
- You only need this if you're powering real time models (e.g. inferring in response to user requests)
127+
- If you are precomputing predictions in batch (aka batch scoring), then the online store is optional. You should be using the offline store and running `feature_store.get_historical_features`. We touch on this later in this module.
67128
- Each online store has its own configurations which map to YAML. (e.g. [RedisOnlineStoreConfig](https://rtd.feast.dev/en/master/feast.infra.online_stores.html#feast.infra.online_stores.redis.RedisOnlineStoreConfig))
68129
With the `feature_store.yaml` setup, you can now run `feast apply` to create & populate the registry.
69130

70-
### Step 2: Adding the feature repo to version control
131+
### Step 2: Adding the feature repo to version control & set up CI/CD
132+
133+
The feature repository is already created for you on GitHub.
71134

72135
<img src="ci_cd_flow.png" width=600 style="padding: 10px 0">
73136

@@ -76,10 +139,62 @@ We setup CI/CD to automatically manage the registry. You'll want e.g. a GitHub w
76139
- on PR merge, runs `feast apply`.
77140

78141
#### **feast plan**
79-
See [feast_plan.yml](https://github.com/feast-dev/feast-demo/blob/main/.github/workflows/feast_plan.yml) as an example of a workflow that automatically runs `feast plan` on new incoming PRs, which alerts you on what changes will occur.
142+
Go ahead and run `feast plan` in your directory. Sample output:
143+
```bash
144+
Created entity driver
145+
Created feature view driver_hourly_stats
146+
Created feature service model_v2
147+
148+
No changes to infrastructure
149+
```
150+
151+
We recommend automatically running `feast plan` on incoming PRs to describe what changes will occur when the PR merges.
80152
- This is useful for helping PR reviewers understand the effects of a change.
81153
- One example is whether a PR may change features that are already depended on in production by another model (e.g. `FeatureService`).
82154

155+
An example GitHub workflow (See [feast_plan.yml](../.github/workflows/feast_plan.yml), which is setup in this workshop repo)
156+
157+
```yaml
158+
name: Feast plan
159+
160+
on: [pull_request]
161+
162+
jobs:
163+
build:
164+
runs-on: ubuntu-latest
165+
steps:
166+
- name: Setup Python
167+
id: setup-python
168+
uses: actions/setup-python@v2
169+
with:
170+
python-version: "3.7"
171+
architecture: x64
172+
173+
# Get the registry from the previous step and run `feast plan`
174+
- uses: actions/checkout@v2
175+
- name: Install feast
176+
run: pip install feast
177+
- name: Capture `feast plan` in a variable
178+
id: feast_plan
179+
run: |
180+
body=$(cd module_0/feature_repo_aws; feast plan)
181+
body="${body//'%'/'%25'}"
182+
body="${body//$'\n'/'%0A'}"
183+
body="${body//$'\r'/'%0D'}"
184+
echo "::set-output name=body::$body"
185+
186+
# Post a comment on the PR with the results of `feast plan`
187+
- name: Create comment
188+
uses: peter-evans/create-or-update-comment@v1
189+
if: ${{ steps.feast_plan.outputs.body }}
190+
with:
191+
issue-number: ${{ github.event.pull_request.number }}
192+
body: |
193+
${{ steps.feast_plan.outputs.body }}
194+
```
195+
196+
![](feast_plan_CI.png)
197+
83198
#### **feast apply**
84199
This will parse the feature, data source, and feature service definitions and publish them to the registry. It may also setup some tables in the online store to materialize batch features to.
85200

‎module_0/feast_plan_CI.png‎

147 KB
Loading

‎module_0/feature_repo_aws/data_sources.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
driver_stats = FileSource(
44
name="driver_stats_source",
5-
path="s3://feast-spark-workshop-test/driver_stats.parquet", # TODO: Replace with your bucket
5+
path="s3://feast-workshop-danny/driver_stats.parquet", # TODO: Replace with your bucket
66
s3_endpoint_override="http://s3.us-west-2.amazonaws.com", # Needed since s3fs defaults to us-east-1
77
timestamp_field="event_timestamp",
88
created_timestamp_column="created",
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
project: feast_demo_aws
22
provider: aws
3-
registry: s3://feast-spark-workshop-test/registry.pb # TODO: Replace with your bucket
3+
registry: s3://feast-workshop-danny/registry.pb # TODO: Replace with your bucket
44
online_store: null
55
offline_store:
66
type: file

‎module_0/infra/main.tf‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ provider "aws" {
33
}
44

55
resource "aws_s3_bucket" "feast_bucket" {
6-
bucket = "feast-spark-workshop-test"
7-
acl = "private"
6+
bucket = "feast-workshop-${var.project_name}"
87
force_destroy = true
98
}
109

11-
resource "aws_s3_bucket_object" "driver_stats_upload" {
10+
resource "aws_s3_bucket_acl" "feast_bucket_acl" {
11+
bucket = aws_s3_bucket.feast_bucket.bucket
12+
acl = "private"
13+
}
14+
15+
resource "aws_s3_object" "driver_stats_upload" {
1216
bucket = aws_s3_bucket.feast_bucket.bucket
1317
key = "driver_stats.parquet"
1418
source = "${path.module}/driver_stats.parquet"

‎module_0/infra/outputs.tf‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
output "project_name" {
2+
value = var.project_name
3+
}
4+
output "project_bucket" {
5+
value = "s3://${aws_s3_bucket.feast_bucket.bucket}"
6+
}

‎module_0/infra/variables.tf‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
variable "project_name" {
2+
type = string
3+
description = "The project identifier is used to uniquely namespace resources"
4+
}

0 commit comments

Comments
 (0)