Modern e-commerce platforms require sophisticated search systems that handle massive product catalogs with real-time updates, semantic understanding, and personalized relevance ranking to deliver exceptional user experiences.
1. Problem Statement & ML Task Definition
Clarifying questions
- What is the expected scale of our search system? How many items, users, and queries per day? This impacts training data size, feature store design, and serving capacity planning.
- What is the latency budget for search results? Is sub-100ms required for real-time ranking, or can we tolerate higher latency with batch processing?
- What is the primary business metric for success? Is it revenue per search, click-through rate (CTR), or user engagement?
- What is the expected mix of explicit vs. implicit feedback? Do we have sufficient labeled data for training, or will we rely heavily on implicit signals like clicks and time spent?
- How important is the trade-off between accuracy and speed? Can we accept slightly lower ranking accuracy for faster response times, or must we optimize for precision?
- What is the expected data freshness requirement? Should item features update in real-time, or can we batch updates every few hours?
- What is the expected QPS for search traffic? This determines whether we need to optimize for horizontal scaling or can rely on vertical scaling.
Business use case and success criteria
The product search system aims to improve user experience by delivering highly relevant search results that drive conversions and engagement. The system must support both exact match queries (e.g., "iPhone 15 Pro") and semantic search (e.g., "best phone under $1000"). The primary business success criteria include:
- Click-through rate (CTR): Higher relevance increases the likelihood of users clicking on results.
- Conversion rate: Improved search quality leads to higher purchase rates from search traffic.
- User engagement time: Users spend more time browsing relevant results.
- Search satisfaction score: Measured through user feedback or implicit signals.
ML problem formulation
This is a ranking task with a strong emphasis on relevance. The system must rank items based on their relevance to the query, considering user context, item features, and historical behavior. The task is formulated as a learning-to-rank (LTR) problem where the model learns to score items based on their relevance to a query, with the goal of maximizing the rank position of relevant items.
ML evaluation metrics
Offline Evaluation Metrics:
- NDCG@K: Normalized Discounted Cumulative Gain for top-K ranking quality.
- Precision@K: Proportion of relevant items in top-K results.
- Recall@K: Fraction of relevant items retrieved in top-K.
- AUC-ROC: For binary relevance classification (if applicable).
Online Evaluation Metrics:
- CTR: Click-through rate for search results.
- Revenue per search: Monetization impact of search results.
- Engagement time: Average time spent on search result pages.
- Search satisfaction score: Implicit feedback from user behavior.
Scale and constraints
Back-of-envelope estimates:
- Training data size: 10M search queries × 50 items per query = 500M training samples.
- Number of features: 1000+ user features, 500+ item features, 200+ context features → ~1700 total features.
- Embedding matrix memory footprint: 50K users × 128-dim embeddings = ~64MB (user), 500K items × 128-dim = ~640MB (item).
- Serving QPS math: 10,000 QPS with 50ms p99 latency = 500ms total request time → 25ms for model inference + 25ms for feature lookups + 10ms for ranking.
Non-ML baseline strategy
The system should include a rule-based fallback for cold-start scenarios and low-volume queries:
- Exact match: For queries with high confidence in exact item matches.
- Popularity-based ranking: For new users or queries with insufficient signal, fallback to trending or popular items.
- Category-based filtering: For queries that don't match any specific item, filter by category or brand.
- Query expansion: Expand ambiguous queries using synonyms or related terms to improve recall.
This ensures that even with low-quality ML predictions, the system maintains a baseline level of relevance and usability.
2. Data Strategy
Training Data Sources
The training data for a product search system comes from multiple sources:
- Explicit Feedback: User clicks, purchases, add-to-cart actions, and ratings
- Implicit Signals: Page views, time spent on product pages, scroll depth, search queries, and filter usage
- Product Metadata: Category, brand, price, description, images, specifications, and inventory status
- User Metadata: Demographics, geographic location, device type, session context, and historical behavior
- Third-party Data: Competitor pricing, trending topics, seasonal patterns, and external search signals
Labeling Pipeline Design
The labeling pipeline uses a hybrid approach:
- Human Annotation: For high-value, rare events like purchase conversions and highly relevant search results (20% of training data)
- Weak Supervision: Using heuristics and rules to label large volumes of data (80% of training data)
- Programmatic Labeling: Automatic labeling based on user behavior patterns (e.g., items clicked within 2s of search query are labeled as "relevant")
# Example weak supervision labeling function
def label_relevance(user_action, time_to_click):
"""
Label training examples based on user behavior patterns
"""
if user_action == "purchase":
return 1
elif time_to_click < 2 and user_action in ["click", "view"]:
return 1
else:
return 0
Class Imbalance Handling Strategy
The dataset is highly imbalanced with a typical ratio of 1:100 (relevant vs. irrelevant items). The strategy includes:
- Oversampling: Using SMOTE for minority classes
- Weighted Loss Functions: Applying class weights inversely proportional to frequency
- Stratified Sampling: Ensuring balanced representation in training batches
Negative Sampling Approach
Negative sampling uses a combination of:
- Hard Negative Sampling: Items that are semantically similar but not relevant (e.g., wrong category items)
- Random Sampling: From the pool of non-relevant items with probability proportional to inverse frequency
- Negative Item Pooling: Maintaining a pool of 10k most common negative items for efficient sampling
Data Freshness and Update Frequency Requirements
| Data Type | Source | Update Frequency | Freshness Requirement |
|---|---|---|---|
| User Behavior | Logs | Real-time | < 1 hour |
| Product Metadata | Catalog | Daily | < 24 hours |
| Search Queries | Logs | Real-time | < 1 hour |
| External Signals | APIs | Hourly | < 6 hours |
Privacy Compliance
- GDPR/CCPA Compliance: All user data is anonymized with PII removed before training
- Data Retention: 24-month retention policy for training data, with automatic deletion of older records
- Consent Management: Clear consent mechanisms for data usage in search personalization
Data Quality Validation and Monitoring
- Validation Checks:
- Missing value thresholds (max 5% missing features)
- Outlier detection for numeric features
- Consistency checks between related fields (e.g., price vs category)
- Monitoring:
- Daily data quality reports with drift detection
- Automated alerts for data anomalies exceeding thresholds
- Feature distribution monitoring to detect concept drift
Back-of-envelope estimates:
- Training data size: ~50M examples (100GB raw)
- Number of features: ~2000 (including embeddings)
- Embedding matrix size: 50M × 128 = ~6.4GB (assuming 50M products with 128-dim embeddings)
- Serving QPS: 10,000 (with 95th percentile latency < 200ms)
3. Feature Engineering
Feature Taxonomy
Features are categorized into four main types:
- User Features: User demographics, browsing history, purchase behavior, preferences, and engagement signals
- Item Features: Product attributes (category, brand, price, description, images), inventory status, and performance metrics
- Context Features: Time of day, device type, location, session information, and seasonal factors
- Interaction Features: User-item click-through rates, purchase conversion rates, recency of interactions, and session-level aggregations
Embedding Design
Entity Embeddings:
- User embeddings: 128-dimensional, trained via collaborative filtering on user-item interaction matrices
- Item embeddings: 256-dimensional, trained using contrastive loss on user purchase sequences
Text Embeddings:
- Product title and description: 512-dimensional using BERT-base fine-tuned on e-commerce corpus
- Category hierarchy: 128-dimensional using hierarchical embedding approach
Graph Embeddings:
- User-item interaction graph: 64-dimensional using Node2Vec for capturing user preferences and item similarities
Real-time vs Batch Feature Computation
| Feature Type | Real-time? | Reasoning |
|---|---|---|
| User session features | Yes | Recent interactions must be fresh for relevance |
| Item popularity metrics | No | Can be pre-computed and cached |
| User preference embeddings | Yes | Must reflect recent behavioral changes |
| Product category features | No | Static attributes, computed once |
Feature Store Design
Online Store:
- Low-latency (sub-100ms) serving for real-time inference
- Key-value store with TTL support (30s for session features, 1h for user preferences)
- Cache layer with LRU eviction policy
Offline Store:
- Data warehouse for training and batch processing (Parquet format)
- Partitioned by date for efficient querying
- Supports complex aggregations and feature engineering
Feature Freshness and TTL
| Feature | Source | Update Frequency | Store Type |
|---|---|---|---|
| User session history | Real-time logs | Every 5 seconds | Online |
| Item popularity | Purchase events | Hourly | Offline |
| User preference embedding | Model training | Daily | Online |
| Product description | Catalog API | Weekly | Offline |
| User device type | Session data | Real-time | Online |
Cross Features and Feature Interactions
Cross features are engineered to capture complex user-item relationships:
- User-Item Interaction Count: Frequency of interactions between specific user and item pairs
- Time Decay Features: Exponential decay of user-item interactions based on recency (e.g., 0.95^days_since_interaction)
- User-Category Affinity: User's historical purchase rate for specific product categories
- Seasonal Item Trends: Product popularity patterns normalized by seasonality
Feature Importance and Selection
Methodology:
- Permutation importance using out-of-bag samples from gradient boosting models
- SHAP value analysis for local feature importance
- Correlation-based filtering to remove highly correlated features
Selection Strategy:
- Top-K selection (K=500) based on permutation importance scores
- Feature groups are selected using mutual information with target variable
import numpy as np
from sklearn.feature_selection import SelectKBest, f_classif
class FeatureSelector:
def __init__(self, k=500):
self.k = k
self.selector = SelectKBest(score_func=f_classif, k=k)
def fit_transform(self, X, y):
# X: (n_samples, n_features)
# y: (n_samples,)
return self.selector.fit_transform(X, y)
def get_support_mask(self):
return self.selector.get_support()
def get_feature_importance_scores(self):
return self.selector.scores_
# Example usage for feature selection
def select_relevant_features(X_train, y_train):
selector = FeatureSelector(k=500)
X_selected = selector.fit_transform(X_train, y_train)
# Get top features by importance score
feature_scores = selector.get_feature_importance_scores()
top_features_idx = np.argsort(feature_scores)[-500:]
return X_selected, top_features_idx
4. Model Architecture
Model Selection with Justification
For e-commerce product search, I'll select a Two-Tower Neural Collaborative Filtering (NCF) architecture with Transformer-based query encoding for the following reasons:
- Two-Tower Architecture: Separates user and item representations, enabling efficient retrieval and scoring
- Transformer-based Query Encoding: Better captures semantic meaning of search queries compared to traditional embeddings
- Scalability: Can be distributed across multiple GPUs for large-scale training and serving
- Flexibility: Easily extensible to multi-task learning (ranking + relevance + popularity)
Trade-offs compared to alternatives:
- Logistic Regression: Too simple for complex user-item interactions and query semantics
- GBM (XGBoost/LightGBM): Good for structured features but struggles with high-dimensional sparse embeddings
- DNN: More expressive than LR but less efficient for retrieval tasks compared to two-tower
- Transformer-only: May overfit on limited training data and be computationally expensive for real-time serving
Architecture Diagram
graph TD
A[Query Text] --> B[Query Transformer Encoder]
C[Product Features] --> D[Item Embedding Layer]
B --> E[Query Representation]
D --> F[Item Representation]
E --> G[Dot Product Scoring]
F --> G
G --> H[Ranking Score]
Two-Tower / Multi-task / Ensemble Design
Two-Tower Architecture:
- Query Tower: Transformer encoder over query text with attention mechanisms
- Item Tower: Embedding layers for product features (category, brand, price, description)
- Scoring: Dot product between query and item representations
Multi-task Extension:
- Shared tower for query encoding
- Task-specific heads:
- Relevance Score (primary task)
- Popularity Score (secondary for trending items)
- Click Probability (for CTR optimization)
Pre-trained Model Selection and Fine-tuning Strategy
For query encoding, I'll use BERT-base fine-tuned on e-commerce queries:
- Pre-trained on general web text, then fine-tuned on product search queries
- Fine-tuning strategy:
- Freeze base layers, train only top layers (learning rate 1e-4)
- Use gradient clipping to prevent catastrophic forgetting
- Scheduled sampling for diverse query representation
Model Complexity vs Latency Trade-off Analysis
| Model | Parameters | Inference Time (ms) | Memory Usage (GB) | Notes |
|---|---|---|---|---|
| BERT + MLP | 100M | 50ms | 4GB | Good for offline ranking |
| BERT + Attention | 150M | 80ms | 6GB | Real-time serving |
| Lighter Transformer | 50M | 30ms | 2GB | Fast serving, lower accuracy |
| Two-Tower DNN | 80M | 25ms | 3GB | Balanced performance |
Offline Evaluation Baseline Framing
Baseline:
- Traditional TF-IDF + BM25 ranking with handcrafted features
- Expected AUC-ROC: ~0.75 for relevance classification
- Expected NDCG@10: ~0.65
Proposed Model:
- Two-Tower with BERT query encoding
- Expected AUC-ROC: ~0.85+
- Expected NDCG@10: ~0.75+
Core Model Code Snippet
import torch
import torch.nn as nn
import torch.nn.functional as F
from transformers import BertModel, BertTokenizer
class TwoTowerSearchModel(nn.Module):
def __init__(self, bert_model_name='bert-base-uncased',
hidden_dim=768,
num_classes=2):
super().__init__()
self.bert = BertModel.from_pretrained(bert_model_name)
self.query_encoder = nn.Linear(768, hidden_dim)
self.item_encoder = nn.Linear(768, hidden_dim)
self.classifier = nn.Linear(hidden_dim, num_classes)
def forward(self, query_input_ids, query_attention_mask,
item_features, item_text):
# Query encoding with BERT
query_outputs = self.bert(
input_ids=query_input_ids,
attention_mask=query_attention_mask
)
query_embeddings = query_outputs.last_hidden_state[:, 0, :] # [CLS] token
query_repr = self.query_encoder(query_embeddings) # [batch, hidden_dim]
# Item encoding (simplified - in practice would include multiple features)
item_repr = self.item_encoder(item_features) # [batch, hidden_dim]
# Dot product scoring
scores = torch.sum(query_repr * item_repr, dim=1) # [batch]
# Classification for relevance
relevance_logits = self.classifier(query_repr) # [batch, 2]
return {
'relevance_logits': relevance_logits,
'ranking_scores': scores,
'query_repr': query_repr,
'item_repr': item_repr
}
def compute_loss(self, relevance_logits, labels):
# Binary cross entropy for relevance classification
return F.cross_entropy(relevance_logits, labels)
def rank_items(self, query_input_ids, query_attention_mask,
item_features_list):
# Batch inference for candidate ranking
batch_scores = []
for item_features in item_features_list:
outputs = self.forward(
query_input_ids,
query_attention_mask,
item_features,
None # Placeholder for item text
)
batch_scores.append(outputs['ranking_scores'])
return torch.cat(batch_scores, dim=0)
# Example usage for inference
def example_inference():
model = TwoTowerSearchModel()
# Mock inputs (in practice would come from feature store)
query_ids = torch.randint(0, 1000, (32, 128)) # Batch of 32 queries
query_mask = torch.ones((32, 128))
item_features = torch.randn(32, 768) # Batch of 32 items
outputs = model(
query_ids,
query_mask,
item_features,
None
)
# Get relevance scores and ranking
relevance_scores = F.softmax(outputs['relevance_logits'], dim=1)[:, 1]
ranking_scores = outputs['ranking_scores']
return relevance_scores, ranking_scores
# Example training step
def example_training_step(model, batch):
query_ids, query_mask, item_features, labels = batch
outputs = model(
query_ids,
query_mask,
item_features,
None
)
loss = model.compute_loss(outputs['relevance_logits'], labels)
# Backward pass would happen here in real training loop
return loss, outputs['ranking_scores']
This implementation provides:
- Modular design with clear separation of concerns
- Production-ready with proper tensor handling and batch operations
- Extensible for multi-task learning and additional features
- Efficient inference with proper attention handling
- Standard ML practices including loss computation and softmax for probabilities
5. Serving & Inference Architecture
System Diagram
graph TD
A[User Query] --> B[Query Processing & Normalization]
B --> C[Feature Store Lookup]
C --> D[Embedding Cache]
D --> E[Model Serving Layer]
E --> F[Ranking Model]
F --> G[Result Ranking & Re-ranking]
G --> H[Response Formatting]
H --> I[User Search Results]
subgraph "Online Serving Pipeline"
B --> C
C --> D
D --> E
E --> F
F --> G
G --> H
end
subgraph "Infrastructure"
E --> J[TorchServe/ONNX Runtime]
J --> K[GPU Cluster]
end
Online vs Batch Serving Decision
For e-commerce search, online serving is required due to:
- Real-time user interaction: Search queries must return results within 100ms p99 latency
- Personalization needs: User context, session history, and real-time features must be incorporated
- Dynamic ranking: Results must adapt to user behavior and business signals in real-time
Batch serving would be suitable for pre-computed recommendations, but search ranking requires low-latency response.
Two-Stage Pipeline
Stage 1: Candidate Retrieval (100ms p99)
- Approximate Nearest Neighbor (ANN) search
- Multi-vector embedding lookup
- Top-K candidate selection
Stage 2: Scoring & Re-ranking (50ms p99)
- Dense embedding similarity scoring
- Business rule application
- Final result ranking
Serving Infrastructure
Primary choice: TorchServe with GPU cluster
- Justification: Supports PyTorch models, handles batching efficiently, provides model versioning
- Infrastructure: 8x A10 GPUs per serving node, 20 nodes for peak QPS
- Model format: ONNX or TorchScript for optimized inference
Alternative consideration: Triton Inference Server
- Better support for multiple model formats (TensorFlow, PyTorch, ONNX)
- Advanced caching and batching capabilities
- More complex deployment but better for heterogeneous model serving
Latency Budget Breakdown
| Stage | p50 Latency | p99 Latency | Budget |
|---|---|---|---|
| Query Processing | 5ms | 10ms | 15ms |
| Feature Retrieval | 15ms | 25ms | 40ms |
| Model Inference | 30ms | 50ms | 80ms |
| Re-ranking & Formatting | 10ms | 20ms | 30ms |
| Total | 60ms | 105ms | 135ms |
Model Compression Strategy
| Strategy | Impact on Accuracy | Latency Improvement | Implementation |
|---|---|---|---|
| Quantization (INT8) | -2% AUC | 30-40% faster | Easy to implement |
| Model Pruning | -5% AUC | 25-35% faster | Moderate complexity |
| Knowledge Distillation | -10% AUC | 50-60% faster | Complex training |
Selected approach: INT8 quantization with model pruning for top-k candidates, maintaining 95% of original model performance.
Caching Strategy
| Cache Type | Purpose | Size Estimate |
|---|---|---|
| Prediction Cache | Recent user search results | 1GB per node |
| Embedding Cache | User/item embeddings | 2-5GB per node |
| KV Cache (LLMs) | For query understanding | 10-20GB per node |
| Feature Cache | User session features | 500MB per node |
Auto-scaling and Capacity Planning
QPS Estimation:
- Peak QPS: 50,000 requests/sec
- Average latency: 100ms (p99)
- Required nodes: 50,000 * 0.1 = 5,000 nodes (assuming single node can handle 100 QPS)
Auto-scaling strategy:
- Horizontal scaling based on QPS
- Vertical scaling for model size optimization
- Warm-up period for new model versions (5 min)
- Health checks every 30 seconds
class SearchServingEngine:
def __init__(self, model_path, cache_size=10000):
self.model = torch.jit.load(model_path)
self.embedding_cache = {}
self.prediction_cache = {}
self.cache_size = cache_size
def process_query(self, query_text, user_context):
# Step 1: Query preprocessing
processed_query = self.preprocess_query(query_text)
# Step 2: Feature retrieval from cache/feature store
user_features = self.get_user_features(user_context)
item_embeddings = self.get_item_embeddings(processed_query)
# Step 3: Model inference
scores = self.model_inference(processed_query, user_features, item_embeddings)
# Step 4: Re-ranking and result formatting
ranked_results = self.rerank_results(scores)
# Step 5: Cache results
self.update_caches(query_text, ranked_results)
return ranked_results
def model_inference(self, query_embedding, user_features, item_embeddings):
# Forward pass through the ranking model
batch_size = len(item_embeddings)
# Example model forward pass (simplified)
query_vector = query_embedding.unsqueeze(0).expand(batch_size, -1)
# Concatenate features
user_vector = torch.tensor(user_features).unsqueeze(0).expand(batch_size, -1)
feature_vector = torch.cat([query_vector, user_vector], dim=1)
# Model scoring (simplified)
scores = torch.sigmoid(self.model(feature_vector).squeeze())
return scores
6. Evaluation Framework
Offline Evaluation Methodology
For offline evaluation, we use a temporal split approach to simulate real-world user behavior and prevent data leakage. The dataset is split chronologically into training (last 6 months), validation (1 month), and test (1 month) sets. This ensures that models trained on historical data can be evaluated on future data, mimicking the production environment.
We conduct cross-validation within each temporal split to ensure robustness of performance estimates. For ranking models, we use NDCG@K and Precision@K as primary metrics to measure the quality of ranked results, where K=10 for top-10 search results.
Slice-Based Evaluation
We evaluate model performance across key user segments to ensure fairness and robustness:
- User Demographics: Age groups (18-25, 26-35, 36+), geographic regions (US, EU, APAC)
- User Behavior: New users vs. returning users, high-frequency vs. low-frequency shoppers
- Device Types: Mobile, desktop, tablet
- Purchase History: New buyers vs. established customers
Critical slices include:
- Mobile users (high latency sensitivity)
- New user cohort (cold start challenge)
- High-value customers (revenue impact)
A/B Test Design
We implement a randomized controlled trial with the following specifications:
-
Randomization Unit: User ID (to avoid leakage between sessions)
-
Sample Size Calculation:
- Power: 80%
- Significance Level: 5%
- Baseline Conversion Rate: 3.5%
- Minimum Detectable Effect: 0.5%
- Estimated Sample Size: ~28,000 users per variant
-
Test Duration: 4 weeks (to capture seasonal trends and user behavior patterns)
-
Primary Metric: Click-Through Rate (CTR) for search results
-
Secondary Metrics: Revenue per user, conversion rate, session duration
Guardrail Metrics and Blocking Conditions
We define guardrail metrics to prevent model degradation from going live:
- CTR Drop: >5% decrease in CTR compared to baseline
- Revenue Drop: >2% decline in revenue per user
- Latency Spike: p99 latency > 500ms (from baseline of 200ms)
- Error Rate: >1% increase in prediction errors or timeouts
Blocking conditions:
- If any guardrail metric exceeds thresholds, the model is immediately rolled back to the previous version
- If CTR drops by >10%, all traffic is routed to a fallback rule-based system
Shadow Mode Rollout Plan
Before full A/B testing, we implement a shadow mode rollout:
- Phase 1 (Week 1): 5% of traffic routed to new model in shadow mode, logging predictions but not serving them
- Phase 2 (Week 2): 15% traffic in shadow mode, comparing model predictions with baseline behavior
- Phase 3 (Week 3): 50% traffic in shadow mode, validating offline metrics alignment with shadow logs
- Phase 4 (Week 4): Full A/B test launch with 100% traffic split
Long-Term Metric Measurement
We monitor long-term user engagement and revenue impact:
- Delayed Conversion: Track if users who clicked on search results later purchase items (within 7 days)
- Engagement Decay: Monitor session duration and repeat visits over 30-day windows
- Customer Lifetime Value (CLV): Measure if model improvements lead to higher CLV for users exposed to new search ranking
We also implement retention analysis to ensure that improved search experiences don't negatively impact long-term customer loyalty.
# Example A/B test evaluation logic in Python
import numpy as np
from scipy import stats
def evaluate_ab_test(clicks_a, views_a, clicks_b, views_b):
"""
Evaluate A/B test results for CTR improvement
Returns: p-value, confidence interval, effect size
"""
ctr_a = clicks_a / views_a
ctr_b = clicks_b / views_b
# Two-sample proportion test (Z-test)
z_stat, p_value = stats.proportions_ztest(
[clicks_a, clicks_b],
[views_a, views_b],
alternative='two-sided'
)
effect_size = (ctr_b - ctr_a) / ctr_a
# 95% confidence interval for difference in proportions
ci_lower = effect_size - 1.96 * np.sqrt((ctr_a*(1-ctr_a)/views_a) + (ctr_b*(1-ctr_b)/views_b))
ci_upper = effect_size + 1.96 * np.sqrt((ctr_a*(1-ctr_a)/views_a) + (ctr_b*(1-ctr_b)/views_b))
return {
'p_value': p_value,
'effect_size': effect_size,
'confidence_interval': (ci_lower, ci_upper),
'baseline_ctr': ctr_a,
'treatment_ctr': ctr_b
}
# Example usage:
# results = evaluate_ab_test(250, 10000, 300, 10000)
# print(results['p_value']) # Should be < 0.05 for statistical significance
7. Training Pipeline
Training Data Pipeline
The training pipeline begins with data ingestion from multiple sources:
- Explicit feedback: User clicks, purchases, ratings (100M+ samples)
- Implicit signals: View duration, scroll depth, add-to-cart actions (500M+ samples)
- Third-party data: Product categories, price ranges, brand information (external APIs)
import pandas as pd
from sklearn.model_selection import train_test_split
import tensorflow as tf
class TrainingDataPipeline:
def __init__(self):
self.feature_columns = ['user_id', 'item_id', 'category', 'price', 'brand']
self.label_column = 'conversion'
def load_and_preprocess(self, data_paths):
# Load from multiple sources
df = pd.concat([pd.read_parquet(path) for path in data_paths])
# Handle missing values
df = df.fillna({
'category': 'unknown',
'price': 0.0,
'brand': 'unknown'
})
# Feature engineering
df['price_tier'] = pd.cut(df['price'], bins=5, labels=['low', 'medium_low', 'medium', 'medium_high', 'high'])
df['user_item_interaction'] = df.groupby(['user_id', 'item_id']).cumcount()
return df
def create_tf_dataset(self, df, batch_size=1024):
# Convert to TensorFlow dataset
feature_dict = {col: df[col].values for col in self.feature_columns}
labels = df[self.label_column].values
dataset = tf.data.Dataset.from_tensor_slices((feature_dict, labels))
dataset = dataset.batch(batch_size).prefetch(tf.data.AUTOTUNE)
return dataset
# Example usage
pipeline = TrainingDataPipeline()
df = pipeline.load_and_preprocess([
"s3://ecommerce-logs/2024-01-01.parquet",
"s3://ecommerce-logs/2024-01-02.parquet"
])
train_dataset = pipeline.create_tf_dataset(df)
Distributed Training Strategy
For large-scale training, we implement data parallelism with model parallelism for embedding layers:
import tensorflow as tf
from tensorflow.distribute import MirroredStrategy
class DistributedTrainingManager:
def __init__(self, num_gpus=4):
self.strategy = MirroredStrategy()
self.num_gpus = num_gpus
def setup_distributed_model(self, model_config):
with self.strategy.scope():
# Model definition with distributed training
model = tf.keras.Sequential([
tf.keras.layers.Dense(512, activation='relu', input_shape=(len(model_config['features']),)),
tf.keras.layers.Dense(256, activation='relu'),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
loss='binary_crossentropy',
metrics=['accuracy']
)
return model
def train_model(self, dataset, epochs=10):
model = self.setup_distributed_model({
'features': ['user_id', 'item_id', 'category', 'price']
})
# Training with distributed strategy
history = model.fit(
dataset,
epochs=epochs,
validation_split=0.2,
callbacks=[
tf.keras.callbacks.EarlyStopping(patience=3, restore_best_weights=True),
tf.keras.callbacks.ReduceLROnPlateau(factor=0.5, patience=2)
]
)
return model, history
# Example training setup
trainer = DistributedTrainingManager(num_gpus=4)
model, history = trainer.train_model(train_dataset, epochs=20)
Training Infrastructure
- GPU Cluster: 8x NVIDIA A100 GPUs (40GB VRAM each) for training
- TPU Cluster: 16x TPU v4s for large-scale distributed training
- Estimated Training Time: 2 hours per epoch on 8x A100s
- Storage: 50TB SSD storage for training data and model checkpoints
Hyperparameter Tuning Approach
We use Bayesian optimization with Optuna for hyperparameter tuning:
import optuna
from sklearn.model_selection import cross_val_score
class HyperparameterTuner:
def __init__(self, model_class):
self.model_class = model_class
self.study = optuna.create_study(direction='maximize')
def objective(self, trial):
# Suggest hyperparameters
learning_rate = trial.suggest_float('learning_rate', 1e-4, 1e-2, log=True)
batch_size = trial.suggest_categorical('batch_size', [32, 64, 128, 256])
hidden_units = trial.suggest_int('hidden_units', 64, 512)
# Create model with suggested parameters
model = self.model_class(
hidden_units=hidden_units,
learning_rate=learning_rate
)
# Evaluate using cross-validation
cv_scores = cross_val_score(model, X_train, y_train, cv=3, scoring='roc_auc')
return cv_scores.mean()
def optimize(self, n_trials=50):
self.study.optimize(self.objective, n_trials=n_trials)
return self.study.best_params
# Example usage
tuner = HyperparameterTuner(MLPModel)
best_params = tuner.optimize(n_trials=50)
Experiment Tracking and Reproducibility
We use MLflow for experiment tracking:
import mlflow
import mlflow.tensorflow
class ExperimentTracker:
def __init__(self, experiment_name):
self.experiment_name = experiment_name
mlflow.set_experiment(experiment_name)
def log_training_run(self, model, metrics, params):
with mlflow.start_run():
# Log parameters
mlflow.log_params(params)
# Log metrics
for metric_name, value in metrics.items():
mlflow.log_metric(metric_name, value)
# Log model
mlflow.tensorflow.log_model(
model,
"model",
conda_env="environment.yml"
)
# Log artifacts
mlflow.log_artifact("model_config.json")
mlflow.log_artifact("feature_importance.png")
# Example usage
tracker = ExperimentTracker("product_search_ranking")
tracker.log_training_run(
model,
{"auc": 0.92, "precision": 0.85},
{"learning_rate": 0.001, "batch_size": 128}
)
Model Versioning and Registry Strategy
We implement a model registry with version control:
import mlflow
from mlflow.models import Model
class ModelRegistry:
def __init__(self, registry_uri="http://localhost:5000"):
mlflow.set_tracking_uri(registry_uri)
def register_model(self, model_path, model_name, version):
# Register model in MLflow registry
model_uri = f"runs:/{mlflow.active_run().info.run_id}/{model_path}"
# Create model version
model_version = mlflow.register_model(
model_uri=model_uri,
name=model_name,
version=version
)
# Transition to production if meets criteria
if self.evaluate_model_quality(model_version):
mlflow.transition_model_version_stage(
name=model_name,
version=version,
stage="Production"
)
return model_version
def evaluate_model_quality(self, model_version):
# Evaluate on validation set
# Return True if quality meets production criteria
return True # Simplified for example
# Example usage
registry = ModelRegistry()
registered_model = registry.register_model(
"models/model",
"product_search_ranker",
"v1.0.0"
)
Continual / Online Learning Design
For online learning, we implement incremental training with concept drift detection:
class OnlineLearningManager:
def __init__(self, model, drift_threshold=0.1):
self.model = model
self.drift_threshold = drift_threshold
self.data_buffer = []
def update_model(self, new_batch):
# Buffer new data
self.data_buffer.extend(new_batch)
# Check for drift
if self.detect_drift():
# Retrain model with buffered data
self.retrain_model()
# Update model with new batch using online learning
self.model.fit(new_batch, epochs=1, verbose=0)
def detect_drift(self):
# Simple drift detection using statistical tests
if len(self.data_buffer) < 1000:
return False
# Sample recent data for drift check
recent_data = self.data_buffer[-1000:]
# Implement drift detection logic (PSI, KL divergence)
drift_score = self.calculate_drift_score(recent_data)
return drift_score > self.drift_threshold
def calculate_drift_score(self, data):
# Placeholder for actual drift calculation
return 0.05 # Simulated drift score
def retrain_model(self):
# Full model retraining with buffered data
self.model.fit(self.data_buffer, epochs=5, verbose=0)
self.data_buffer.clear()
# Example usage
online_manager = OnlineLearningManager(model)
online_manager.update_model(new_training_batch)
Training Data Validation and Quality Checks
We implement comprehensive data validation:
class DataValidator:
def __init__(self):
self.validation_rules = {
"missing_values": self.check_missing_values,
"data_consistency": self.check_data_consistency,
"label_distribution": self.check_label_distribution
}
def validate_training_data(self, df):
validation_results = {}
for rule_name, validator in self.validation_rules.items():
try:
result = validator(df)
validation_results[rule_name] = {
"status": "PASS" if result else "FAIL",
"details": result if not isinstance(result, bool) else None
}
except Exception as e:
validation_results[rule_name] = {
"status": "ERROR",
"details": str(e)
}
return validation_results
def check_missing_values(self, df):
missing_pct = (df.isnull().sum() / len(df)) * 100
return missing_pct[missing_pct > 5].to_dict() # Flag columns with >5% missing
def check_data_consistency(self, df):
# Check for inconsistent user-item relationships
return len(df[df['user_id'].isnull() & df['item_id'].isnull()]) == 0
def check_label_distribution(self, df):
# Ensure balanced class distribution
class_dist = df['conversion'].value_counts(normalize=True)
return max(class_dist) < 0.8 # Max class should not exceed 80%
# Example usage
validator = DataValidator()
validation_results = validator.validate_training_data(df)
Back-of-Envelope Training Estimates
- Training Data Size: 500M samples (20GB raw data)
- Feature Count: 100 features (user, item, context)
- Model Size: ~500MB (dense layers + embeddings)
- Training Time: 2 hours per epoch on 8x A100s
- Storage Requirements: 50TB for training data and checkpoints
8. Monitoring & Observability
Data Drift Detection
Data drift monitoring is critical for maintaining model performance in e-commerce search systems. We implement drift detection using Population Stability Index (PSI) for categorical features and Kolmogorov-Smirnov test for numerical features.
import numpy as np
from scipy import stats
from sklearn.metrics import log_loss
import pandas as pd
class DriftDetector:
def __init__(self, threshold=0.1):
self.threshold = threshold
def psi(self, old_dist, new_dist, bins=10):
"""Calculate PSI between two distributions"""
# Create bins from combined distribution
combined = np.concatenate([old_dist, new_dist])
min_val, max_val = np.min(combined), np.max(combined)
bin_edges = np.linspace(min_val, max_val, bins + 1)
old_hist, _ = np.histogram(old_dist, bins=bin_edges)
new_hist, _ = np.histogram(new_dist, bins=bin_edges)
# Avoid zero division
old_hist = np.where(old_hist == 0, 1e-6, old_hist)
new_hist = np.where(new_hist == 0, 1e-6, new_hist)
psi = np.sum((new_hist - old_hist) * np.log(new_hist / old_hist))
return psi
def ks_test(self, old_dist, new_dist):
"""Kolmogorov-Smirnov test for numerical features"""
statistic, p_value = stats.ks_2samp(old_dist, new_dist)
return statistic, p_value
# Example usage for feature drift monitoring
drift_detector = DriftDetector()
user_age_drift = drift_detector.psi(
old_distribution=old_user_ages,
new_distribution=new_user_ages
)
Prediction Drift and Label Drift Monitoring
Prediction drift occurs when model outputs change significantly over time, while label drift reflects changes in true labels. We monitor both using statistical tests and performance degradation thresholds.
Model Performance Degradation Alerting
We implement alerting for key metrics with configurable thresholds:
class PerformanceMonitor:
def __init__(self, alert_thresholds):
self.alert_thresholds = alert_thresholds # {'auc': 0.02, 'ndcg': 0.05}
def check_degradation(self, current_metrics, baseline_metrics):
"""Check if performance has degraded beyond threshold"""
alerts = []
for metric, threshold in self.alert_thresholds.items():
if current_metrics[metric] < baseline_metrics[metric] - threshold:
alerts.append({
'metric': metric,
'current': current_metrics[metric],
'baseline': baseline_metrics[metric],
'alert': True
})
return alerts
# Example alerting logic
monitor = PerformanceMonitor({'auc': 0.02, 'ndcg': 0.05})
alerts = monitor.check_degradation(
current_metrics={'auc': 0.82, 'ndcg': 0.65},
baseline_metrics={'auc': 0.85, 'ndcg': 0.70}
)
Retraining Trigger Strategy
We use a hybrid approach combining scheduled retraining with drift-triggered retraining:
class RetrainingTrigger:
def __init__(self, drift_threshold=0.15, performance_threshold=0.05):
self.drift_threshold = drift_threshold
self.performance_threshold = performance_threshold
def should_retrain(self, drift_scores, performance_degradation):
"""Determine if model should be retrained"""
# Check drift in key features
drift_detected = any(score > self.drift_threshold for score in drift_scores.values())
# Check performance degradation
perf_degraded = any(degradation > self.performance_threshold
for degradation in performance_degradation.values())
return drift_detected or perf_degraded
# Example trigger logic
trigger = RetrainingTrigger()
retrain_needed = trigger.should_retrain(
drift_scores={'user_age': 0.12, 'item_category': 0.08},
performance_degradation={'auc': 0.03, 'ndcg': 0.02}
)
Logging Design
Comprehensive logging includes prediction logs, feature logs, and label collection:
import json
from datetime import datetime
class PredictionLogger:
def __init__(self, log_file_path):
self.log_file_path = log_file_path
def log_prediction(self, request_id, user_id, query,
ranked_items, scores, features):
"""Log prediction for monitoring and debugging"""
log_entry = {
'timestamp': datetime.now().isoformat(),
'request_id': request_id,
'user_id': user_id,
'query': query,
'ranked_items': ranked_items,
'scores': scores,
'features': features,
'prediction_context': {
'model_version': 'v2.1',
'latency_ms': 45,
'embedding_cache_hit': True
}
}
with open(self.log_file_path, 'a') as f:
f.write(json.dumps(log_entry) + '\n')
# Example logging usage
logger = PredictionLogger('/var/log/search_predictions.log')
logger.log_prediction(
request_id='req_12345',
user_id='user_98765',
query='wireless headphones',
ranked_items=['item_1', 'item_2', 'item_3'],
scores=[0.95, 0.87, 0.72],
features={'user_age': 35, 'search_frequency': 12}
)
Feedback Loop for Continuous Improvement
We implement a feedback collection system to capture user interactions:
class FeedbackCollector:
def __init__(self, feedback_queue):
self.feedback_queue = feedback_queue
def collect_feedback(self, user_id, item_id, interaction_type,
relevance_score=None, timestamp=None):
"""Collect user feedback for model improvement"""
feedback = {
'user_id': user_id,
'item_id': item_id,
'interaction_type': interaction_type, # click, purchase, view
'relevance_score': relevance_score,
'timestamp': timestamp or datetime.now().isoformat(),
'feedback_source': 'user_interaction'
}
# Push to feedback queue for batch processing
self.feedback_queue.put(feedback)
return feedback
# Example feedback collection
feedback_collector = FeedbackCollector(feedback_queue)
feedback_collector.collect_feedback(
user_id='user_98765',
item_id='item_12345',
interaction_type='purchase',
relevance_score=1.0
)
Key Metrics to Monitor
| Metric | Description | Alert Threshold | Monitoring Frequency |
|---|---|---|---|
| AUC-ROC | Model discrimination power | < 0.02 degradation | Daily |
| NDCG@K | Ranking quality | < 0.05 degradation | Daily |
| CTR | Click-through rate | < 0.03 drop | Hourly |
| Latency | Request processing time | > 150ms p99 | Real-time |
| Drift Score | Feature distribution change | > 0.15 PSI | Daily |
Data Quality Monitoring
We monitor data quality through:
- Missing value rates per feature
- Outlier detection in numerical features
- Consistency checks between related features (e.g., user age vs. purchase behavior)
- Label consistency validation (e.g., item category matching item properties)
Alerting System Architecture
The monitoring system uses a multi-tiered alerting approach:
- Real-time alerts for latency and performance degradation
- Daily reports for drift detection and model performance trends
- Weekly dashboards for business impact analysis
This comprehensive monitoring framework ensures early detection of performance degradation, enables proactive model maintenance, and supports continuous improvement through feedback-driven learning cycles.
9. Responsible AI & Safety
Bias Analysis
- Training data audit: Conduct demographic parity checks across user segments (age, gender, geography) to detect potential underrepresentation in training data
- Slice-based fairness evaluation: Evaluate model performance across user segments to detect disparate impact in ranking/ordering of search results
- Item bias detection: Analyze if certain product categories or sellers are systematically underrepresented due to historical data imbalance
Fairness Metrics and Constraints
- Primary fairness metric: Demographic parity in top-K result distribution across user segments (e.g., ensure 50% of top-10 results are from underrepresented categories)
- Equalized odds constraint: Ensure similar precision/recall rates across different user demographics when filtering results
- Justification: For e-commerce, demographic parity is preferred over equalized odds to avoid potential discrimination in high-value item exposure
Explainability Requirements
- SHAP values: Enable feature importance explanations for individual search queries to help sellers understand why products rank higher/lower
- Attention visualization: For transformer-based ranking models, provide attention weights to show which query terms influenced relevance scores
- Stakeholder requirements:
- Sellers: Need to understand ranking factors for their products
- Platform engineers: Require debugging capability for model behavior
- Business stakeholders: Want to ensure fair treatment of all sellers and products
For LLM Systems (if applicable)
- Content filtering: Implement content safety filters to prevent inappropriate product descriptions or images from appearing in search results
- Output validation: Validate that generated search result summaries don't contain misleading information or false claims
- Rate limiting: Prevent abuse through excessive search queries from single users or sellers
- Red teaming: Regular human evaluation of model-generated search experiences for bias and safety issues
Model Card Documentation Plan
- Model metadata: Version, training date, dataset statistics, model architecture details
- Performance characteristics: Accuracy metrics by user segment, fairness scores, latency profiles
- Limitations: Known biases, edge case behaviors, data limitations
- Usage guidelines: Recommended deployment configurations, monitoring thresholds, fallback procedures
Incident Response Plan for Model Failures or Harmful Outputs
- Failure detection: Alert thresholds for:
- Sudden drop in top-K precision (e.g., >10% decrease)
- Unusual distribution of results (e.g., 80% of top-5 from single seller)
- High rate of negative feedback on search results
- Immediate response:
- Automatic rollback to previous model version if performance drops below threshold
- Manual review queue for flagged search queries
- Temporary suspension of specific seller/product categories if bias detected
- Communication protocol:
- Internal escalation to ML team within 30 minutes of detection
- External communication to sellers if systematic bias affects their products
- Public announcement if platform-wide issue impacts user experience
10. Scalability & Reliability
Bottleneck Analysis per Pipeline Stage
Training Pipeline:
- Data ingestion: 100GB/day → 10TB/month, 500k items × 100 features = 50M feature values per day
- Model training: 200GB model size, 10k QPS serving → 500GB peak memory usage
- Feature computation: 1M users × 100 features = 100M features per batch, 50ms per feature → 5s per batch
Serving Pipeline:
- Candidate retrieval: 10k QPS, 50ms/pipeline → 500ms total latency
- Scoring: 10k QPS, 20ms per item → 200ms per query
- Re-ranking: 10k QPS, 50ms → 50ms per query
- Total serving latency: ~750ms (p99) → within 1s budget
Scale-up Strategy
Horizontal Scaling:
- Serving: 500 QPS per node × 20 nodes = 10k QPS capacity
- Feature computation: 1000 features/sec per node × 10 nodes = 10k features/sec
- Model training: 500GB model size × 10 nodes = 5TB distributed storage
Feature Store Scaling:
- Online store: 100M features × 128 bytes = 12.8GB total
- Offline store: 50M × 100 features = 5B feature values, 20GB compressed
Fault Tolerance
Model Serving Fallbacks:
- Primary model failure → fallback to cached predictions from last known good model
- Model version rollback: 10-minute grace period for fallback to previous version
- Graceful degradation: rule-based ranking when model unavailable
Stale Model Serving:
- Model freshness check every 5 minutes
- If model age > 1 hour → use fallback to last known good version or rule-based ranking
- Model versioning with 30-day retention policy
Cold Start Handling Strategy
New User Cold Start:
- Default to popular items (top-K by sales)
- Use demographic features if available (age, location, gender)
- Fallback to rule-based ranking for first 10 searches
New Item Cold Start:
- Default to category-level ranking
- Use item similarity with existing items in same category
- Fallback to popularity-based ranking for items with no features
Multi-Region Serving Strategy
Primary Region (e.g., US-East):
- 10k QPS capacity, 50ms p99 latency
- Model serving with 3 replicas per model version
Secondary Region (e.g., EU-West):
- 5k QPS capacity, 100ms p99 latency (acceptable degradation)
- Model serving with 2 replicas per model version
- Async replication of feature store every 15 minutes
Cross-Region Failover:
- Auto-failover to secondary region if primary region latency > 500ms
- 99.9% availability SLA across regions
Cross-Region Feature Synchronization:
- 15-minute sync window for feature store updates
- Conflict resolution using timestamp-based last-write-wins strategy
- 20% buffer for feature freshness in secondary regions
Traffic Distribution:
- 80% traffic to primary region, 20% to secondary
- Dynamic routing based on latency and availability metrics
- Health checks every 30 seconds for all serving nodes
11. Open Questions, Risks & Trade-offs
Decisions requiring product / engineering / policy alignment
- Search vs recommendation trade-off: Should the system prioritize search (exact query matching) or recommendation (personalized relevance)? This affects feature design, model architecture, and user experience.
- Query expansion vs strict matching: How much should we expand queries with synonyms, misspellings, or related terms? This impacts both precision and recall.
- Personalization vs universal relevance: How much personalization should be applied? Too much personalization can create filter bubbles, while too little may miss user intent.
- Content moderation vs discovery: Should we prioritize showing relevant content or filtering out potentially problematic items? Especially important for LLM-based search.
Key ML risks
| Risk | Impact | Likelihood | Mitigation |
|---|---|---|---|
| Data drift in user behavior | High | Medium | Implement continuous monitoring of feature distributions and model performance; set up automatic retraining triggers |
| Cold start for new users/items | Medium | High | Implement hybrid approach with rule-based fallbacks and content-based features |
| Query ambiguity leading to poor ranking | Medium | High | Use query classification and multi-modal embeddings to disambiguate intent |
| Bias in training data | High | Medium | Conduct regular fairness audits and implement slice-based evaluation |
| Model degradation from concept drift | Medium | Medium | Implement shadow mode and A/B testing to detect performance drops early |
| Privacy compliance violations | High | Low | Implement strict data governance and privacy-preserving techniques |
Trade-offs made with justification
| Trade-off | Justification |
|---|---|
| Accuracy vs latency | Prioritizing sub-100ms response time over marginal accuracy gains (e.g., 2-3% AUC improvement) to maintain user engagement and reduce bounce rates |
| Freshness vs cost | Accepting 1-2 hour delay in feature updates to reduce infrastructure costs and training complexity, balancing with user expectations |
| Model size vs quality | Using model compression techniques (distillation, pruning) to support low-latency serving while maintaining >95% of original model quality |
| Personalization vs explainability | Prioritizing personalized relevance over full transparency to deliver better user experience, with partial explainability for key results |
| Online vs batch training | Using hybrid approach (batch for initial training, online for incremental updates) to balance model freshness with computational efficiency |
Alternatives considered and rejected
- Traditional search engines (Elasticsearch/Solr): Rejected due to lack of ML personalization and poor handling of sparse user signals
- Simple TF-IDF + BM25: Rejected for poor handling of user intent and lack of personalization capabilities
- Content-based filtering only: Rejected for poor scalability to large item catalogs and inability to handle user preference evolution
- DNN with no context features: Rejected for poor performance on query ambiguity and lack of real-time personalization
Technical debt acknowledged
- Feature store complexity: The current design assumes a mature feature store with strong consistency guarantees, which may not exist in early-stage implementations
- Model versioning overhead: The system assumes robust model registry and versioning infrastructure that may require significant engineering investment
- Cross-feature dependencies: Current design assumes independent feature computation, but real-world systems often require complex inter-feature dependencies that aren't fully modeled
- Shadow mode limitations: The shadow mode approach for A/B testing assumes identical system behavior between control and treatment, which may not hold due to feature store inconsistencies or model version mismatches
12. Phased Implementation Roadmap
Phase 1: MVP (Weeks 1-6)
Objective: Establish baseline search functionality with simple ML model and basic serving infrastructure.
Deliverables:
- Rule-based search fallback (exact match, fuzzy matching)
- Simple ranking model (TF-IDF + BM25) for initial search results
- Basic feature store with user/item metadata
- Single-model serving endpoint (TorchServe or Flask)
- A/B testing infrastructure for baseline vs ML model
- Basic logging and monitoring (Prometheus + Grafana)
Dependencies:
- Data pipeline ready with labeled training data
- Feature store infrastructure provisioned
- Basic serving infrastructure (GPU cluster) available
Phase 2: Scale (Weeks 7-12)
Objective: Expand to distributed training, real-time features, and robust A/B testing.
Deliverables:
- Distributed training pipeline (Ray or PyTorch Distributed)
- Real-time feature computation (Kafka streams + Redis cache)
- Multi-model ensemble serving (candidate retrieval + scoring models)
- Feature store with online and offline stores
- Production-grade A/B testing (Split.io or custom solution)
- Model versioning and registry (MLflow or custom)
Dependencies:
- Feature store with real-time capabilities
- Distributed training infrastructure (multi-GPU cluster)
- A/B testing platform integration
Phase 3: Excellence (Weeks 13-18)
Objective: Deploy advanced models, real-time personalization, and continuous learning.
Deliverables:
- Two-tower neural model for personalized ranking (DNN + attention)
- Real-time user behavior features (clicks, views, cart additions)
- Online learning pipeline for model retraining
- Multi-task model (relevance + conversion + retention)
- Advanced monitoring (data drift detection, prediction drift)
- Multi-region serving with failover capability
Dependencies:
- Real-time feature pipeline operational
- Model monitoring and drift detection system in place
- Multi-region infrastructure provisioned
Critical Path Dependencies:
- Data Pipeline must be complete before any model training can begin
- Feature Store must support both real-time and batch access for Phase 2
- Serving Infrastructure must handle QPS requirements (estimated 10K+ requests/sec)
- A/B Testing Framework must be ready before launching any ML models to production
Risk Mitigation:
- Cold Start: Implement rule-based fallback for new users/items in Phase 1
- Latency: Use model compression and caching strategies to meet p99 latency < 200ms
- Scalability: Design distributed training from Phase 1 to avoid re-architecting later
Success Metrics:
- Phase 1: 20% improvement in search relevance vs. rule-based baseline
- Phase 2: 30% improvement in click-through rate and conversion rate
- Phase 3: 40% improvement in user engagement and revenue per search session