Skip to content

Commit b389c3d

Browse files
author
twitter-team
committed
Open-sourcing pushservice
Pushservice is the main recommendation service we use to surface recommendations to our users via notifications. It fetches candidates from various sources, ranks them in order of relevance, and applies filters to determine the best one to send.
1 parent 01dbfee commit b389c3d

File tree

309 files changed

+42796
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

309 files changed

+42796
-0
lines changed

README.md

+10
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ The core components of the For You Timeline included in this repository are list
4848
| | [visibility-filters](visibilitylib/README.md) | Responsible for filtering Twitter content to support legal compliance, improve product quality, increase user trust, protect revenue through the use of hard-filtering, visible product treatments, and coarse-grained downranking. |
4949
| | [timelineranker](timelineranker/README.md) | Legacy service which provides relevance-scored tweets from the Earlybird Search Index and UTEG service. |
5050

51+
### Recommended Notifications
52+
53+
The core components that power Recommended Notifications included in this repository are listed below:
54+
55+
| Type | Component | Description |
56+
|------------|------------|------------|
57+
| Service | [pushservice](pushservice/README.md) | Main recommendation service at Twitter used to surface recommendations to our users via notifications.
58+
| Ranking | [pushservice-light-ranker](pushservice/src/main/python/models/light_ranking/README.md) | Light Ranker model used by pushservice to rank Tweets. Bridges candidate generation and heavy ranking by pre-selecting highly-relevant candidates from the initial huge candidate pool. |
59+
| | [pushservice-heavy-ranker](pushservice/src/main/python/models/heavy_ranking/README.md) | Multi-task learning model to predict the probabilities that the target users will open and engage with the sent notifications. |
60+
5161
## Build and test code
5262

5363
We include Bazel BUILD files for most components, but not a top-level BUILD or WORKSPACE file. We plan to add a more complete build and test system in the future.

pushservice/BUILD.bazel

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
alias(
2+
name = "frigate-pushservice",
3+
target = ":frigate-pushservice_lib",
4+
)
5+
6+
target(
7+
name = "frigate-pushservice_lib",
8+
dependencies = [
9+
"frigate/frigate-pushservice-opensource/src/main/scala/com/twitter/frigate/pushservice",
10+
],
11+
)
12+
13+
jvm_binary(
14+
name = "bin",
15+
basename = "frigate-pushservice",
16+
main = "com.twitter.frigate.pushservice.PushServiceMain",
17+
runtime_platform = "java11",
18+
tags = ["bazel-compatible"],
19+
dependencies = [
20+
"3rdparty/jvm/ch/qos/logback:logback-classic",
21+
"finatra/inject/inject-logback/src/main/scala",
22+
"frigate/frigate-pushservice-opensource/src/main/scala/com/twitter/frigate/pushservice",
23+
"loglens/loglens-logback/src/main/scala/com/twitter/loglens/logback",
24+
"twitter-server/logback-classic/src/main/scala",
25+
],
26+
excludes = [
27+
exclude("com.twitter.translations", "translations-twitter"),
28+
exclude("org.apache.hadoop", "hadoop-aws"),
29+
exclude("org.tensorflow"),
30+
scala_exclude("com.twitter", "ckoia-scala"),
31+
],
32+
)
33+
34+
jvm_app(
35+
name = "bundle",
36+
basename = "frigate-pushservice-package-dist",
37+
archive = "zip",
38+
binary = ":bin",
39+
tags = ["bazel-compatible"],
40+
)
41+
42+
python3_library(
43+
name = "mr_model_constants",
44+
sources = [
45+
"config/deepbird/constants.py",
46+
],
47+
tags = ["bazel-compatible"],
48+
)

pushservice/readme.md

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Pushservice
2+
3+
Pushservice is the main push recommendation service at Twitter used to generate recommendation-based notifications for users. It currently powers two functionalities:
4+
5+
- RefreshForPushHandler: This handler determines whether to send a recommendation push to a user based on their ID. It generates the best push recommendation item and coordinates with downstream services to deliver it
6+
- SendHandler: This handler determines and manage whether send the push to users based on the given target user details and the provided push recommendation item
7+
8+
## Overview
9+
10+
### RefreshForPushHandler
11+
12+
RefreshForPushHandler follows these steps:
13+
14+
- Building Target and checking eligibility
15+
- Builds a target user object based on the given user ID
16+
- Performs target-level filterings to determine if the target is eligible for a recommendation push
17+
- Fetch Candidates
18+
- Retrieves a list of potential candidates for the push by querying various candidate sources using the target
19+
- Candidate Hydration
20+
- Hydrates the candidate details with batch calls to different downstream services.
21+
- Pre-rank Filtering, also called Light Filtering
22+
- Filters the hydrated candidates with lightweight RPC calls.
23+
- Rank
24+
- Perform feature hydration for candidates and target user
25+
- Performs light ranking on candidates
26+
- Performs heavy ranking on candidates
27+
- Take Step, also called Heavy Filtering
28+
- Takes the top-ranked candidates one by one and applies heavy filtering until one candidate passes all filter steps
29+
- Send
30+
- Calls the appropriate downstream service to deliver the eligible candidate as a push and in-app notification to the target user
31+
32+
### SendHandler
33+
34+
SendHandler follows these steps:
35+
36+
- Building Target
37+
- Builds a target user object based on the given user ID
38+
- Candidate Hydration
39+
- Hydrates the candidate details with batch calls to different downstream services.
40+
- Feature Hydration
41+
- Perform feature hydration for candidates and target user
42+
- Take Step, also called Heavy Filtering
43+
- Perform filterings and validation checking for the given candidate
44+
- Send
45+
- Calls the appropriate downstream service to deliver the given candidate as a push and/or in-app notification to the target user
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
python37_binary(
2+
name = "update_warm_start_checkpoint",
3+
source = "update_warm_start_checkpoint.py",
4+
tags = ["no-mypy"],
5+
dependencies = [
6+
":deep_norm_lib",
7+
"3rdparty/python/_closures/frigate/frigate-pushservice-opensource/src/main/python/models/heavy_ranking:update_warm_start_checkpoint",
8+
],
9+
)
10+
11+
python3_library(
12+
name = "params_lib",
13+
sources = ["params.py"],
14+
tags = ["no-mypy"],
15+
dependencies = [
16+
"3rdparty/python/pydantic:default",
17+
"src/python/twitter/deepbird/projects/magic_recs/v11/lib:params_lib",
18+
],
19+
)
20+
21+
python3_library(
22+
name = "features_lib",
23+
sources = ["features.py"],
24+
tags = ["no-mypy"],
25+
dependencies = [
26+
":params_lib",
27+
"src/python/twitter/deepbird/projects/magic_recs/libs",
28+
"twml:twml-nodeps",
29+
],
30+
)
31+
32+
python3_library(
33+
name = "model_pools_lib",
34+
sources = ["model_pools.py"],
35+
tags = ["no-mypy"],
36+
dependencies = [
37+
":features_lib",
38+
":params_lib",
39+
"src/python/twitter/deepbird/projects/magic_recs/v11/lib:model_lib",
40+
],
41+
)
42+
43+
python3_library(
44+
name = "graph_lib",
45+
sources = ["graph.py"],
46+
tags = ["no-mypy"],
47+
dependencies = [
48+
":params_lib",
49+
"src/python/twitter/deepbird/projects/magic_recs/libs",
50+
],
51+
)
52+
53+
python3_library(
54+
name = "run_args_lib",
55+
sources = ["run_args.py"],
56+
tags = ["no-mypy"],
57+
dependencies = [
58+
":features_lib",
59+
":params_lib",
60+
"twml:twml-nodeps",
61+
],
62+
)
63+
64+
python3_library(
65+
name = "deep_norm_lib",
66+
sources = ["deep_norm.py"],
67+
tags = ["no-mypy"],
68+
dependencies = [
69+
":features_lib",
70+
":graph_lib",
71+
":model_pools_lib",
72+
":params_lib",
73+
":run_args_lib",
74+
"src/python/twitter/deepbird/projects/magic_recs/libs",
75+
"src/python/twitter/deepbird/util/data",
76+
"twml:twml-nodeps",
77+
],
78+
)
79+
80+
python3_library(
81+
name = "eval_lib",
82+
sources = ["eval.py"],
83+
tags = ["no-mypy"],
84+
dependencies = [
85+
":features_lib",
86+
":graph_lib",
87+
":model_pools_lib",
88+
":params_lib",
89+
":run_args_lib",
90+
"src/python/twitter/deepbird/projects/magic_recs/libs",
91+
"twml:twml-nodeps",
92+
],
93+
)
94+
95+
python37_binary(
96+
name = "deep_norm",
97+
source = "deep_norm.py",
98+
dependencies = [
99+
":deep_norm_lib",
100+
"3rdparty/python/_closures/frigate/frigate-pushservice-opensource/src/main/python/models/heavy_ranking:deep_norm",
101+
"twml",
102+
],
103+
)
104+
105+
python37_binary(
106+
name = "eval",
107+
source = "eval.py",
108+
dependencies = [
109+
":eval_lib",
110+
"3rdparty/python/_closures/frigate/frigate-pushservice-opensource/src/main/python/models/heavy_ranking:eval",
111+
"twml",
112+
],
113+
)
114+
115+
python3_library(
116+
name = "mlwf_libs",
117+
tags = ["no-mypy"],
118+
dependencies = [
119+
":deep_norm_lib",
120+
"twml",
121+
],
122+
)
123+
124+
python37_binary(
125+
name = "train_model",
126+
source = "deep_norm.py",
127+
dependencies = [
128+
":deep_norm_lib",
129+
"3rdparty/python/_closures/frigate/frigate-pushservice-opensource/src/main/python/models/heavy_ranking:train_model",
130+
],
131+
)
132+
133+
python37_binary(
134+
name = "train_model_local",
135+
source = "deep_norm.py",
136+
dependencies = [
137+
":deep_norm_lib",
138+
"3rdparty/python/_closures/frigate/frigate-pushservice-opensource/src/main/python/models/heavy_ranking:train_model_local",
139+
"twml",
140+
],
141+
)
142+
143+
python37_binary(
144+
name = "eval_model_local",
145+
source = "eval.py",
146+
dependencies = [
147+
":eval_lib",
148+
"3rdparty/python/_closures/frigate/frigate-pushservice-opensource/src/main/python/models/heavy_ranking:eval_model_local",
149+
"twml",
150+
],
151+
)
152+
153+
python37_binary(
154+
name = "eval_model",
155+
source = "eval.py",
156+
dependencies = [
157+
":eval_lib",
158+
"3rdparty/python/_closures/frigate/frigate-pushservice-opensource/src/main/python/models/heavy_ranking:eval_model",
159+
],
160+
)
161+
162+
python37_binary(
163+
name = "mlwf_model",
164+
source = "deep_norm.py",
165+
dependencies = [
166+
":mlwf_libs",
167+
"3rdparty/python/_closures/frigate/frigate-pushservice-opensource/src/main/python/models/heavy_ranking:mlwf_model",
168+
],
169+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Notification Heavy Ranker Model
2+
3+
## Model Context
4+
There are 4 major components of Twitter notifications recommendation system: 1) candidate generation 2) light ranking 3) heavy ranking & 4) quality control. This notification heavy ranker model is the core ranking model for the personalised notifications recommendation. It's a multi-task learning model to predict the probabilities that the target users will open and engage with the sent notifications.
5+
6+
7+
## Directory Structure
8+
- BUILD: this file defines python library dependencies
9+
- deep_norm.py: this file contains how to set up continuous training, model evaluation and model exporting for the notification heavy ranker model
10+
- eval.py: the main python entry file to set up the overall model evaluation pipeline
11+
- features.py: this file contains importing feature list and support functions for feature engineering
12+
- graph.py: this file defines how to build the tensorflow graph with specified model architecture, loss function and training configuration
13+
- model_pools.py: this file defines the available model types for the heavy ranker
14+
- params.py: this file defines hyper-parameters used in the notification heavy ranker
15+
- run_args.py: this file defines command line parameters to run model training & evaluation
16+
- update_warm_start_checkpoint.py: this file contains the support to modify checkpoints of the given saved heavy ranker model
17+
- lib/BUILD: this file defines python library dependencies for tensorflow model architecture
18+
- lib/layers.py: this file defines different type of convolution layers to be used in the heavy ranker model
19+
- lib/model.py: this file defines the module containing ClemNet, the heavy ranker model type
20+
- lib/params.py: this file defines parameters used in the heavy ranker model

pushservice/src/main/python/models/heavy_ranking/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)