Update README.md
Browse filesSo I built **CDN Cache Optimizer**.
It is an OpenEnv-compatible environment where an agent learns how to manage an edge CDN cache.
CDNs serve images, videos, scripts, documents, and application assets to users around the world.
A good cache policy can:
- reduce user latency
- reduce origin load
- save bandwidth
- improve reliability
- avoid unnecessary cache churn
A poor cache policy can do the opposite.
README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
---
|
| 2 |
-
title: CDN Cache Optimizer
|
| 3 |
emoji: 🌐
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: green
|
|
@@ -13,237 +13,143 @@ tags:
|
|
| 13 |
- hackathon
|
| 14 |
---
|
| 15 |
|
| 16 |
-
# CDN Cache Optimizer
|
| 17 |
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
|
| 20 |
---
|
| 21 |
|
| 22 |
-
##
|
|
|
|
|
|
|
| 23 |
|
| 24 |
-
|
| 25 |
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
|
| 32 |
---
|
| 33 |
|
| 34 |
-
##
|
| 35 |
|
| 36 |
-
|
| 37 |
|
| 38 |
-
|
| 39 |
-
- **Fine-tuned Agent**: preserves viral/previewed objects, avoids bulky cold admissions, and evicts low-value content under cache pressure.
|
| 40 |
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
-
|
| 44 |
-
pip install -r requirements.txt
|
| 45 |
-
python app.py
|
| 46 |
-
```
|
| 47 |
|
| 48 |
-
|
| 49 |
|
| 50 |
-
|
| 51 |
|
| 52 |
-
|
| 53 |
|
| 54 |
-
|
| 55 |
-
!python /content/colab_submission_script.py
|
| 56 |
-
```
|
| 57 |
|
| 58 |
-
|
| 59 |
|
| 60 |
-
-
|
| 61 |
-
- `policy.pt`
|
| 62 |
-
- `drift_report.json`
|
| 63 |
-
- `metrics.json`
|
| 64 |
|
| 65 |
-
##
|
| 66 |
|
| 67 |
-
|
| 68 |
|
| 69 |
-
|
| 70 |
-
- **Steady files**: consistent, cyclical demand.
|
| 71 |
-
- **Viral files**: bell-curve spikes that fade back to baseline.
|
| 72 |
-
- **Queue preview**: short lookahead signal similar to CDN prefetch telemetry.
|
| 73 |
|
| 74 |
-
|
| 75 |
|
| 76 |
-
|
| 77 |
|
| 78 |
-
|
| 79 |
-
R = w1 * Perf - w2 * Cost
|
| 80 |
-
```
|
| 81 |
|
| 82 |
-
|
|
|
|
|
|
|
|
|
|
| 83 |
|
| 84 |
-
|
| 85 |
|
| 86 |
-
|
| 87 |
|
| 88 |
-
|
| 89 |
-
- `fid`, `object_id`, `oid` -> `file_id`
|
| 90 |
-
- `bytes`, `size_bytes` -> `size_mb`
|
| 91 |
-
- `cache_hit`, `is_hit` -> `hit`
|
| 92 |
|
| 93 |
-
|
| 94 |
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
### Observation Space
|
| 98 |
-
| Field | Type | Description |
|
| 99 |
-
|-------|------|-------------|
|
| 100 |
-
| `step` | int | Current episode step |
|
| 101 |
-
| `cache_used_mb` | float | MB currently used |
|
| 102 |
-
| `cache_capacity_mb` | float | Total cache size |
|
| 103 |
-
| `cache_fill_ratio` | float | 0.0–1.0 fill level |
|
| 104 |
-
| `cached_files` | List[FileEntry] | All files in cache with metadata |
|
| 105 |
-
| `incoming_file_id` | str | File being requested |
|
| 106 |
-
| `incoming_file_size_mb` | float | Size of incoming file |
|
| 107 |
-
| `incoming_file_is_viral` | bool | Is this file currently viral? |
|
| 108 |
-
| `cache_hit` | bool | Is incoming file already cached? |
|
| 109 |
-
| `recent_hit_rate` | float | Rolling hit rate (last 20 steps) |
|
| 110 |
-
| `time_of_day` | float | Normalized 0.0–1.0 daily cycle |
|
| 111 |
-
| `queue_preview` | List[str] | Next 3 file IDs (prefetch hint) |
|
| 112 |
-
|
| 113 |
-
### FileEntry Fields
|
| 114 |
-
| Field | Type | Description |
|
| 115 |
-
|-------|------|-------------|
|
| 116 |
-
| `file_id` | str | Unique identifier |
|
| 117 |
-
| `size_mb` | float | File size in MB |
|
| 118 |
-
| `request_frequency` | float | Requests since cached |
|
| 119 |
-
| `is_viral` | bool | Currently viral |
|
| 120 |
-
| `last_accessed` | int | Step number of last access |
|
| 121 |
-
|
| 122 |
-
### Action Space
|
| 123 |
-
| Field | Type | Description |
|
| 124 |
-
|-------|------|-------------|
|
| 125 |
-
| `evict_file_id` | str \| null | File to evict (null = no eviction) |
|
| 126 |
-
|
| 127 |
-
### Reward Function
|
| 128 |
-
| Component | Range | Description |
|
| 129 |
-
|-----------|-------|-------------|
|
| 130 |
-
| `cache_hit_bonus` | +1.0 to +1.5 | Hit reward (viral hits = +1.5) |
|
| 131 |
-
| `bandwidth_saved` | +0.0 to +0.2 | Reward for bandwidth efficiency |
|
| 132 |
-
| `eviction_penalty` | -0.0 to -0.5 | Penalty for evicting popular files |
|
| 133 |
-
| `thrash_penalty` | 0.0 or -0.5 | Penalty for evicting same file twice |
|
| 134 |
-
| `wasted_capacity_penalty` | -0.0 to -0.3 | Penalty for leaving cache empty |
|
| 135 |
|
| 136 |
---
|
| 137 |
|
| 138 |
-
##
|
| 139 |
-
|
| 140 |
-
### Task 1: Steady Traffic Cache (Easy)
|
| 141 |
-
- **Cache**: 100MB | **Files**: 30 | **Steps**: 100
|
| 142 |
-
- No viral files — steady demand only
|
| 143 |
-
- Agent learns basic LRU-style eviction
|
| 144 |
-
- **Target hit rate**: ≥ 0.60 → score 1.0
|
| 145 |
-
- **Baseline score**: ~0.75
|
| 146 |
-
|
| 147 |
-
### Task 2: Mixed Traffic Cache (Medium)
|
| 148 |
-
- **Cache**: 80MB | **Files**: 50 | **Steps**: 150
|
| 149 |
-
- 20% viral files mixed with steady demand
|
| 150 |
-
- Agent must handle spikes and prioritize popular content
|
| 151 |
-
- **Score**: 70% hit rate + 30% bandwidth
|
| 152 |
-
- **Baseline score**: ~0.60
|
| 153 |
-
|
| 154 |
-
### Task 3: Constrained Cache with Viral Bursts (Hard)
|
| 155 |
-
- **Cache**: 50MB | **Files**: 80 | **Steps**: 200
|
| 156 |
-
- 35% viral files, tight capacity, large file sizes
|
| 157 |
-
- Agent must predict spikes, avoid thrashing
|
| 158 |
-
- **Score**: 50% hit rate + 25% bandwidth + 25% reward quality
|
| 159 |
-
- **Baseline score**: ~0.45
|
| 160 |
|
| 161 |
-
|
| 162 |
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
## GitHub Deployment
|
| 176 |
-
|
| 177 |
-
```bash
|
| 178 |
-
git add .
|
| 179 |
-
git commit -m "Prepare CDN Cache Optimizer hackathon submission"
|
| 180 |
-
git branch -M main
|
| 181 |
-
git remote add origin https://github.com/<username>/cdn-cache-optimizer.git
|
| 182 |
-
git push -u origin main
|
| 183 |
-
```
|
| 184 |
-
|
| 185 |
-
## 🚀 Setup & Usage
|
| 186 |
-
|
| 187 |
-
### Local Setup
|
| 188 |
-
```bash
|
| 189 |
-
git clone <repo>
|
| 190 |
-
cd cdn-cache-env
|
| 191 |
-
pip install -r requirements.txt
|
| 192 |
-
```
|
| 193 |
-
|
| 194 |
-
### Run API Server
|
| 195 |
-
```bash
|
| 196 |
-
uvicorn api.main:app --host 0.0.0.0 --port 7860
|
| 197 |
-
```
|
| 198 |
-
|
| 199 |
-
### Run Inference (Baseline Agent)
|
| 200 |
-
```bash
|
| 201 |
-
export API_BASE_URL="https://api.openai.com/v1"
|
| 202 |
-
export MODEL_NAME="gpt-4o-mini"
|
| 203 |
-
export HF_TOKEN="your_token_here"
|
| 204 |
-
|
| 205 |
-
python inference.py
|
| 206 |
-
```
|
| 207 |
-
|
| 208 |
-
### Docker
|
| 209 |
-
```bash
|
| 210 |
-
docker build -t cdn-cache-env .
|
| 211 |
-
docker run -p 7860:7860 cdn-cache-env
|
| 212 |
-
```
|
| 213 |
|
| 214 |
---
|
| 215 |
|
| 216 |
-
##
|
| 217 |
|
| 218 |
-
|
| 219 |
-
|--------|----------|-------------|
|
| 220 |
-
| GET | `/health` | Health check (returns 200) |
|
| 221 |
-
| GET | `/tasks` | List all tasks |
|
| 222 |
-
| POST | `/reset` | Start episode `{"task_id": "task_easy", "seed": 42}` |
|
| 223 |
-
| POST | `/step` | Take action `{"evict_file_id": "file_001" or null}` |
|
| 224 |
-
| GET | `/state` | Full environment state |
|
| 225 |
|
| 226 |
-
|
| 227 |
|
| 228 |
-
|
| 229 |
|
| 230 |
-
|
|
|
|
| 231 |
|
| 232 |
-
|
| 233 |
-
|------|----------|-------|
|
| 234 |
-
| Easy | ~0.72 | ~1.00 |
|
| 235 |
-
| Medium | ~0.61 | ~0.82 |
|
| 236 |
-
| Hard | ~0.48 | ~0.78 |
|
| 237 |
-
| **Overall** | | **~0.87** |
|
| 238 |
|
| 239 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 240 |
|
| 241 |
-
|
|
|
|
|
|
|
| 242 |
|
| 243 |
-
|
| 244 |
|
| 245 |
-
```
|
| 246 |
-
|
| 247 |
-
{"type": "STEP", "step": 0, "action": {...}, "reward": 1.0, ...}
|
| 248 |
-
{"type": "END", "total_reward": 87.3, "final_hit_rate": 0.72, "score": 1.0}
|
| 249 |
-
```
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Building a CDN Cache Optimizer with OpenEnv and RL
|
| 3 |
emoji: 🌐
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: green
|
|
|
|
| 13 |
- hackathon
|
| 14 |
---
|
| 15 |
|
| 16 |
+
# Building a CDN Cache Optimizer with OpenEnv and RL
|
| 17 |
|
| 18 |
+
For this hackathon, I wanted to build something that felt close to a real infrastructure problem.
|
| 19 |
+
|
| 20 |
+
A lot of reinforcement learning demos are fun, but they often feel disconnected from systems that engineers actually run in production. I wanted my project to sit closer to that world: networking, latency, logs, cost, traffic spikes, and reliability.
|
| 21 |
+
|
| 22 |
+
So I built **CDN Cache Optimizer**.
|
| 23 |
+
|
| 24 |
+
It is an OpenEnv-compatible environment where an agent learns how to manage an edge CDN cache.
|
| 25 |
+
|
| 26 |
+
The project is live here:
|
| 27 |
+
|
| 28 |
+
- GitHub: https://github.com/umar-sharif821/cdn-cache-env-improvedone
|
| 29 |
+
- Hugging Face Space: https://huggingface.co/spaces/umar-sharif821/cdn-cache-env-improvedone
|
| 30 |
|
| 31 |
---
|
| 32 |
|
| 33 |
+
## The Problem
|
| 34 |
+
|
| 35 |
+
A CDN edge server has limited storage.
|
| 36 |
|
| 37 |
+
Every time a file is requested, the system has to make a decision:
|
| 38 |
|
| 39 |
+
> Should this object stay in cache, should we ignore it, or should we evict something else to make room?
|
| 40 |
+
|
| 41 |
+
If the file is already cached, the user gets a fast edge response.
|
| 42 |
+
|
| 43 |
+
If the file is not cached, the request goes back to origin.
|
| 44 |
+
|
| 45 |
+
That is slower and more expensive.
|
| 46 |
+
|
| 47 |
+
At small scale, this looks simple.
|
| 48 |
+
|
| 49 |
+
At internet scale, it becomes a hard optimization problem.
|
| 50 |
|
| 51 |
---
|
| 52 |
|
| 53 |
+
## Why This Matters
|
| 54 |
|
| 55 |
+
CDNs serve images, videos, scripts, documents, and application assets to users around the world.
|
| 56 |
|
| 57 |
+
A good cache policy can:
|
|
|
|
| 58 |
|
| 59 |
+
- reduce user latency
|
| 60 |
+
- reduce origin load
|
| 61 |
+
- save bandwidth
|
| 62 |
+
- improve reliability
|
| 63 |
+
- avoid unnecessary cache churn
|
| 64 |
|
| 65 |
+
A poor cache policy can do the opposite.
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
+
It may evict useful files.
|
| 68 |
|
| 69 |
+
It may cache large files that are rarely requested.
|
| 70 |
|
| 71 |
+
It may miss viral traffic bursts.
|
| 72 |
|
| 73 |
+
It may keep sending users back to origin even when the edge cache could have served them.
|
|
|
|
|
|
|
| 74 |
|
| 75 |
+
This is why cache optimization is an interesting RL problem.
|
| 76 |
|
| 77 |
+
---
|
|
|
|
|
|
|
|
|
|
| 78 |
|
| 79 |
+
## Why Not Just Use LRU?
|
| 80 |
|
| 81 |
+
LRU is simple:
|
| 82 |
|
| 83 |
+
> Evict the least recently used file.
|
|
|
|
|
|
|
|
|
|
| 84 |
|
| 85 |
+
That is a strong baseline, and it works well in many cases.
|
| 86 |
|
| 87 |
+
But it has blind spots.
|
| 88 |
|
| 89 |
+
For example:
|
|
|
|
|
|
|
| 90 |
|
| 91 |
+
- A file may be old but about to become popular again.
|
| 92 |
+
- A file may be recently used once but not worth storing.
|
| 93 |
+
- A viral object may deserve protection even if it has not been in cache for long.
|
| 94 |
+
- A large file may consume too much cache space compared to its value.
|
| 95 |
|
| 96 |
+
That is where an agent can do better.
|
| 97 |
|
| 98 |
+
The agent does not just ask:
|
| 99 |
|
| 100 |
+
> What was used least recently?
|
|
|
|
|
|
|
|
|
|
| 101 |
|
| 102 |
+
It can ask:
|
| 103 |
|
| 104 |
+
> What is most valuable to keep right now?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
|
| 106 |
---
|
| 107 |
|
| 108 |
+
## Project Goal
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
|
| 110 |
+
The goal of this project is not just to train a model.
|
| 111 |
|
| 112 |
+
The goal is to build a complete benchmarkable environment around a realistic CDN caching problem.
|
| 113 |
+
|
| 114 |
+
That includes:
|
| 115 |
+
|
| 116 |
+
- an OpenEnv-style environment
|
| 117 |
+
- a baseline policy
|
| 118 |
+
- a fine-tuned agent policy
|
| 119 |
+
- a reward function grounded in latency and cost
|
| 120 |
+
- schema drift handling for CDN logs
|
| 121 |
+
- Colab reproducibility
|
| 122 |
+
- a live Hugging Face demo
|
| 123 |
+
- visual comparison between baseline and agent behavior
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
|
| 125 |
---
|
| 126 |
|
| 127 |
+
## Live Demo
|
| 128 |
|
| 129 |
+
The Hugging Face Space runs a Gradio app.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
|
| 131 |
+
The UI lets the judge choose a CDN task and run a benchmark.
|
| 132 |
|
| 133 |
+
It compares:
|
| 134 |
|
| 135 |
+
- **Baseline LRU**
|
| 136 |
+
- **Fine-tuned CDN agent**
|
| 137 |
|
| 138 |
+
The output shows:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
|
| 140 |
+
- total reward
|
| 141 |
+
- cache hit rate
|
| 142 |
+
- bandwidth saved
|
| 143 |
+
- hit-rate curve
|
| 144 |
+
- baseline-vs-agent comparison chart
|
| 145 |
+
|
| 146 |
+
Space:
|
| 147 |
|
| 148 |
+
https://huggingface.co/spaces/umar-sharif821/cdn-cache-env-improvedone
|
| 149 |
+
|
| 150 |
+
---
|
| 151 |
|
| 152 |
+

|
| 153 |
|
| 154 |
+
```markdown
|
| 155 |
+

|
|
|
|
|
|
|
|
|