Download index.html from fredmo/mlserving: direct link, hf CLI and curl.
- Browser
- Download file 38.6 kB
-
https://huggingface.co/spaces/fredmo/mlserving/resolve/main/index.html
- Command line
-
hf download hf://spaces/fredmo/mlserving/index.html
-
curl -L -o index.html https://huggingface.co/spaces/fredmo/mlserving/resolve/main/index.html
38.6 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>The MLOps Engineer's Interactive Architecture Builder</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet"> | |
| <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> | |
| <style> | |
| /* --- General Setup & Variables --- */ | |
| :root { | |
| --primary-color: #1E88E5; /* Blue */ | |
| --primary-dark: #1565C0; | |
| --secondary-color: #004d40; /* Dark Teal for contrast */ | |
| --genai-color: #6A1B9A; /* Purple for Gen AI */ | |
| --background-color: #f4f6f8; | |
| --card-bg-color: #ffffff; | |
| --text-color: #333; | |
| --heading-color: #212121; | |
| --subtle-text-color: #555; | |
| --border-color: #e0e0e0; | |
| --code-bg-color: #282c34; | |
| --code-text-color: #abb2bf; | |
| --shadow: 0 4px 12px rgba(0,0,0,0.1); | |
| --tile-hover-shadow: 0 6px 16px rgba(0,0,0,0.15); | |
| } | |
| body { | |
| font-family: 'Roboto', sans-serif; | |
| background-color: var(--background-color); | |
| color: var(--text-color); | |
| margin: 0; | |
| padding: 0; | |
| line-height: 1.6; | |
| } | |
| /* --- Layout & Containers --- */ | |
| .container { max-width: 1200px; margin: 0 auto; padding: 2rem; } | |
| header { text-align: center; margin-bottom: 2rem; } | |
| header h1 { color: var(--heading-color); font-weight: 700; font-size: 2.8rem; margin-bottom: 0.5rem; } | |
| header p { font-size: 1.1rem; color: var(--subtle-text-color); max-width: 800px; margin: 0 auto; } | |
| .main-section-title { | |
| font-size: 2.2rem; color: var(--heading-color); border-bottom: 3px solid var(--primary-color); | |
| padding-bottom: 0.75rem; margin-top: 3rem; margin-bottom: 2rem; display: flex; align-items: center; | |
| } | |
| .main-section-title .material-icons { font-size: 2.8rem; margin-right: 1rem; } | |
| /* --- Architecture Builder --- */ | |
| #architecture-builder { background-color: var(--card-bg-color); padding: 2rem; border-radius: 8px; box-shadow: var(--shadow); } | |
| .arch-type-selector { display: flex; gap: 1rem; margin-bottom: 2rem; border-bottom: 1px solid var(--border-color); padding-bottom: 1.5rem; } | |
| .arch-type-chip { padding: 0.8rem 1.5rem; border-radius: 8px; cursor: pointer; font-weight: 500; font-size: 1.1rem; border: 2px solid transparent; transition: all 0.2s ease; } | |
| .arch-type-chip.active.classic { background-color: #e3f2fd; border-color: var(--primary-color); color: var(--primary-dark); } | |
| .arch-type-chip.active.gen-ai { background-color: #f3e5f5; border-color: var(--genai-color); color: var(--genai-color); } | |
| .builder-fields { display: none; } | |
| .builder-fields.active { display: block; } | |
| .selection-group { margin-bottom: 1.5rem; transition: opacity 0.3s ease; } | |
| .selection-group.disabled { opacity: 0.5; pointer-events: none; } | |
| .selection-group h4 { margin-top: 0; margin-bottom: 1rem; font-size: 1.2rem; color: var(--secondary-color); } | |
| .selection-chips { display: flex; flex-wrap: wrap; gap: 0.75rem; } | |
| .chip { | |
| padding: 0.6rem 1.2rem; border: 2px solid var(--border-color); border-radius: 20px; | |
| cursor: pointer; transition: all 0.2s ease; font-weight: 500; background-color: #f9f9f9; | |
| } | |
| .chip:not(.disabled):hover { border-color: var(--primary-dark); background-color: #e3f2fd; } | |
| .chip.active { background-color: var(--primary-color); color: white; border-color: var(--primary-color); } | |
| .chip.disabled { opacity: 0.6; cursor: not-allowed; background-color: #f0f0f0; border-color: var(--border-color); color: #999; } | |
| #generate-btn { | |
| background-color: var(--secondary-color); color: white; border: none; padding: 0.8rem 2rem; font-size: 1.1rem; | |
| font-weight: 500; border-radius: 6px; cursor: pointer; transition: background-color 0.2s; | |
| display: block; margin-top: 2rem; width: 100%; | |
| } | |
| #generate-btn:hover { background-color: #00695C; } | |
| /* --- Architecture Diagram Output --- */ | |
| #architecture-diagram-output { | |
| display: none; margin-top: 2rem; background-color: #fdfdfd; border: 1px solid var(--border-color); | |
| padding: 2rem; border-radius: 8px; text-align: center; | |
| } | |
| .diagram-title { font-size: 1.5rem; font-weight: 500; margin-bottom: 2rem; } | |
| .diagram-stack { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; } | |
| .diagram-layer { | |
| background-color: var(--card-bg-color); border: 2px solid var(--primary-color); border-radius: 8px; | |
| padding: 1.5rem 2.5rem; width: 80%; max-width: 500px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); text-align: center; | |
| } | |
| .diagram-layer.gen-ai-layer { border-color: var(--genai-color); } | |
| .diagram-layer.gen-ai-layer h5 { color: var(--genai-color); } | |
| .diagram-layer h5 { margin: 0 0 0.5rem 0; color: var(--primary-dark); font-size: 1.2rem; font-weight: 700; } | |
| .diagram-layer p { margin: 0; font-size: 1rem; color: var(--subtle-text-color); } | |
| .diagram-arrow { font-family: 'Material Icons'; font-size: 2.5rem; color: var(--primary-color); line-height: 1; } | |
| .diagram-arrow.gen-ai-arrow { color: var(--genai-color); } | |
| .icon-img-placeholder { | |
| height: 32px; | |
| max-width: 120px; | |
| width: auto; | |
| margin-top: 10px; | |
| } | |
| /* --- Reference Tiles and Panels, Code & Details --- */ | |
| .tile-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1.5rem; margin-bottom: 2.5rem; } | |
| .tile { background-color: var(--card-bg-color); border: 2px solid var(--border-color); border-radius: 8px; padding: 1.5rem; text-align: center; cursor: pointer; transition: all 0.2s ease; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 150px; } | |
| .tile:hover { transform: translateY(-5px); box-shadow: var(--tile-hover-shadow); border-color: var(--primary-color); } | |
| .tile.active { border-color: var(--primary-color); box-shadow: var(--tile-hover-shadow); background-color: #f0f7ff; } | |
| .tile-icon-img { | |
| height: 48px; | |
| width: auto; | |
| max-width: 100%; | |
| margin-bottom: 1rem; | |
| } | |
| .tile h4 { margin: 0; font-size: 1.2rem; color: var(--heading-color); } | |
| .content-panel { display: none; background-color: var(--card-bg-color); border-radius: 8px; box-shadow: var(--shadow); padding: 2.5rem; margin-top: 1rem; } | |
| .content-panel.active { display: block; } | |
| .stack-layer { margin-bottom: 2.5rem; padding-bottom: 1.5rem; border-bottom: 1px solid var(--border-color); } | |
| .stack-layer:last-child { border-bottom: none; margin-bottom: 0; } | |
| .stack-layer h3 { font-size: 1.6rem; color: var(--secondary-color); margin-top: 0; display: flex; align-items: center; } | |
| .stack-layer h3 .material-icons { margin-right: 12px; font-size: 2rem; } | |
| details { border: 1px solid var(--border-color); border-radius: 6px; margin-bottom: 1rem; background-color: #f9fafb; } | |
| summary { cursor: pointer; padding: 1rem; font-weight: 500; font-size: 1.1rem; list-style: none; display: flex; align-items: center; justify-content: space-between; } | |
| pre { background-color: var(--code-bg-color); color: var(--code-text-color); padding: 1.5rem 1rem 1rem 1rem; border-radius: 6px; overflow-x: auto; font-size: 0.9em; position: relative; } | |
| code { font-family: 'Courier New', Courier, monospace; } | |
| .copy-btn { position: absolute; top: 10px; right: 10px; background-color: #4a505c; color: #fff; border: none; padding: 6px 10px; border-radius: 4px; cursor: pointer; opacity: 0.7; } | |
| pre:hover .copy-btn { opacity: 1; } | |
| .copy-btn.copied { background-color: var(--primary-dark); } | |
| .code-block-header { font-weight: bold; color: var(--subtle-text-color); margin-bottom: -0.5rem; margin-top: 1rem; } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <header> | |
| <h1>MLOps Architecture Builder & Cheatsheet</h1> | |
| <p>Design your custom model serving stack using the builder below, or explore detailed deployment guides for common frameworks.</p> | |
| </header> | |
| <main> | |
| <!-- ======================= My Architecture Builder ======================= --> | |
| <h2 class="main-section-title"><i class="material-icons">architecture</i>My Architecture</h2> | |
| <div id="architecture-builder"> | |
| <div class="arch-type-selector"> | |
| <div class="arch-type-chip active classic" data-type="classic">Classic ML</div> | |
| <div class="arch-type-chip gen-ai" data-type="gen-ai">Generative AI</div> | |
| </div> | |
| <!-- Classic Builder Fields --> | |
| <div id="classic-builder-fields" class="builder-fields active"> | |
| <div class="selection-group" data-group="framework"> | |
| <h4>1. ML Framework</h4> | |
| <div class="selection-chips"> | |
| <div class="chip" data-id="scikit-learn">Scikit-learn</div> | |
| <div class="chip" data-id="xgboost">XGBoost</div> | |
| <div class="chip" data-id="pytorch">PyTorch</div> | |
| <div class="chip" data-id="tensorflow">TensorFlow</div> | |
| <div class="chip" data-id="jax">JAX</div> | |
| <div class="chip" data-id="keras">Keras</div> | |
| </div> | |
| </div> | |
| <div class="selection-group" data-group="serving"> | |
| <h4>2. Serving Container</h4> | |
| <div class="selection-chips"> | |
| <div class="chip" data-id="kserve">Kubeflow KServe</div> | |
| <div class="chip" data-id="ray-serve">Ray Serve</div> | |
| <div class="chip" data-id="torchserve">TorchServe</div> | |
| <div class="chip" data-id="tf-serving">TF Serving</div> | |
| <div class="chip" data-id="triton">NVIDIA Triton</div> | |
| <div class="chip" data-id="custom">Custom Container (FastAPI)</div> | |
| </div> | |
| </div> | |
| <div class="selection-group" data-group="orchestration"> | |
| <h4>3. Orchestration / Platform</h4> | |
| <div class="selection-chips"> | |
| <div class="chip active" data-id="kubernetes">Kubernetes</div> | |
| <div class="chip" data-id="vertex-ai">Managed: Vertex AI</div> | |
| <div class="chip" data-id="sagemaker">Managed: SageMaker</div> | |
| </div> | |
| </div> | |
| <div class="selection-group" data-group="hardware"> | |
| <h4>4. Hardware</h4> | |
| <div class="selection-chips"> | |
| <div class="chip" data-id="vm">VMs (CPU)</div> | |
| <div class="chip" data-id="gpu">GPU</div> | |
| <div class="chip" data-id="tpu">TPU</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Gen AI Builder Fields --> | |
| <div id="genai-builder-fields" class="builder-fields"> | |
| <div class="selection-group" data-group="model-type"> | |
| <h4>0. Model Type</h4> | |
| <div class="selection-chips"> | |
| <div class="chip" data-id="llm">LLM</div> | |
| <div class="chip" data-id="vlm">Multimodal LLM (VLM)</div> | |
| <div class="chip" data-id="diffusion">Diffusion</div> | |
| </div> | |
| </div> | |
| <div class="selection-group" data-group="framework"> | |
| <h4>1. ML Framework</h4> | |
| <div class="selection-chips"> | |
| <div class="chip" data-id="pytorch">PyTorch</div> | |
| <div class="chip" data-id="tensorflow">TensorFlow</div> | |
| <div class="chip" data-id="jax">JAX</div> | |
| <div class="chip" data-id="keras">Keras</div> | |
| </div> | |
| </div> | |
| <div class="selection-group" data-group="serving"> | |
| <h4>2. Serving Container</h4> | |
| <div class="selection-chips"> | |
| <div class="chip" data-id="vllm">vLLM</div> | |
| <div class="chip" data-id="sglang">SGLang</div> | |
| <div class="chip" data-id="triton-trt-llm">NVIDIA Triton (TensorRT-LLM)</div> | |
| <div class="chip" data-id="custom">Custom Container (Diffusers, etc.)</div> | |
| </div> | |
| </div> | |
| <div class="selection-group" data-group="orchestration"> | |
| <h4>3. Orchestration / Platform</h4> | |
| <div class="selection-chips"> | |
| <div class="chip active" data-id="k8s-ray-kf">Kubernetes (KubeRay/Kubeflow)</div> | |
| <div class="chip" data-id="vertex-ai">Managed: Vertex AI</div> | |
| <div class="chip" data-id="sagemaker">Managed: SageMaker</div> | |
| </div> | |
| </div> | |
| <div class="selection-group" data-group="hardware"> | |
| <h4>4. Hardware</h4> | |
| <div class="selection-chips"> | |
| <div class="chip" data-id="gpu">GPU</div> | |
| <div class="chip" data-id="tpu">TPU</div> | |
| </div> | |
| </div> | |
| </div> | |
| <button id="generate-btn">Generate Architecture Diagram</button> | |
| </div> | |
| <div id="architecture-diagram-output"></div> | |
| <h2 class="main-section-title"><i class="material-icons">menu_book</i>Reference Guides</h2> | |
| <h3 class="main-section-title" style="font-size: 1.8rem; border-color: var(--primary-color);"><i class="material-icons" style="color: var(--primary-color);">model_training</i>Classic ML</h3> | |
| <div class="tile-container"> | |
| <div class="tile" data-target="classic-pytorch"><img src="pytorch.png" class="tile-icon-img" alt="PyTorch Icon"><h4>PyTorch</h4></div> | |
| <div class="tile" data-target="classic-tensorflow"><img src="tensorflow.png" class="tile-icon-img" alt="TensorFlow Icon"><h4>TensorFlow</h4></div> | |
| <div class="tile" data-target="classic-sklearn"><img src="scikit-learn.png" class="tile-icon-img" alt="Scikit-learn Icon"><h4>Scikit-learn</h4></div> | |
| <div class="tile" data-target="classic-xgboost"><img src="xgboost.png" class="tile-icon-img" alt="XGBoost Icon"><h4>XGBoost</h4></div> | |
| <div class="tile" data-target="classic-jax"><img src="jax.png" class="tile-icon-img" alt="JAX Icon"><h4>JAX</h4></div> | |
| </div> | |
| <h3 class="main-section-title" style="font-size: 1.8rem; border-color: var(--genai-color);"><i class="material-icons" style="color: var(--genai-color);">auto_awesome</i>Generative AI</h3> | |
| <div class="tile-container"> | |
| <div class="tile" data-target="genai-llm"><img src="llm.png" class="tile-icon-img" alt="LLM Icon"><h4>LLMs</h4></div> | |
| <div class="tile" data-target="genai-vlm"><img src="vlm.png" class="tile-icon-img" alt="VLM Icon"><h4>Multimodal (VLMs)</h4></div> | |
| <div class="tile" data-target="genai-diffusion"><img src="diffusion.png" class="tile-icon-img" alt="Diffusion Icon"><h4>Diffusion Models</h4></div> | |
| </div> | |
| <div class="content-container"> | |
| <!-- Classic ML Panels --> | |
| <div id="classic-pytorch" class="content-panel"> | |
| <div class="stack-layer"><h3><i class="material-icons">psychology</i>Model Layer</h3> | |
| <p>A simple feed-forward network defined in PyTorch. The model's `state_dict` is saved for deployment.</p> | |
| <p class="code-block-header">model_setup.py</p> | |
| <pre><code>import torch | |
| import torch.nn as nn | |
| class SimpleNet(nn.Module): | |
| def __init__(self): | |
| super(SimpleNet, self).__init__() | |
| self.linear = nn.Linear(10, 1) | |
| def forward(self, x): return self.linear(x) | |
| model = SimpleNet() | |
| torch.save(model.state_dict(), "pytorch_model.pth")</code></pre> | |
| </div> | |
| <div class="stack-layer"><h3><i class="material-icons">layers</i>Serving Stack Layer</h3> | |
| <p>Use a high-performance framework like FastAPI for a custom server. For dedicated solutions, TorchServe is the native choice, while Kubeflow KServe, Ray Serve, and NVIDIA Triton offer powerful, managed abstractions.</p> | |
| </div> | |
| <div class="stack-layer"><h3><i class="material-icons">cloud_queue</i>Orchestration Layer</h3> | |
| <p>Package the application with a multi-stage Dockerfile and define its runtime with Kubernetes Deployment, Service, and HPA objects. Managed platforms like Vertex AI abstract this away.</p> | |
| </div> | |
| <div class="stack-layer"><h3><i class="material-icons">memory</i>Hardware Layer</h3> | |
| <p><strong>CPUs:</strong> Suitable for small networks. <strong>GPUs:</strong> Essential for deep learning models. <strong>TPUs:</strong> Best for massive-scale inference on GCP.</p> | |
| </div> | |
| </div> | |
| <div id="classic-tensorflow" class="content-panel"> | |
| <div class="stack-layer"><h3><i class="material-icons">psychology</i>Model Layer</h3> | |
| <p>A simple Keras model saved in TensorFlow's `SavedModel` format, which bundles the architecture and weights.</p> | |
| <p class="code-block-header">model_setup.py</p> | |
| <pre><code>import tensorflow as tf | |
| model = tf.keras.Sequential([ | |
| tf.keras.layers.Dense(10, activation='relu', input_shape=(10,)), | |
| tf.keras.layers.Dense(1) | |
| ]) | |
| model.save("tf_saved_model")</code></pre> | |
| </div> | |
| <div class="stack-layer"><h3><i class="material-icons">layers</i>Serving Stack Layer</h3> | |
| <p>TF Serving and Kubeflow KServe offer native, high-performance support for the `SavedModel` format. NVIDIA Triton is also highly optimized for TF models. A custom FastAPI server is another flexible option.</p> | |
| </div> | |
| <div class="stack-layer"><h3><i class="material-icons">cloud_queue</i>Orchestration Layer</h3> | |
| <p>The Kubernetes configuration is very similar to other frameworks. Ensure your Dockerfile copies the entire `tf_saved_model` directory.</p> | |
| </div> | |
| <div class="stack-layer"><h3><i class="material-icons">memory</i>Hardware Layer</h3> | |
| <p><strong>CPUs:</strong> Good for smaller Keras models. <strong>GPUs:</strong> Highly recommended for deep learning models. <strong>TPUs:</strong> The premier choice for running TensorFlow models at scale on GCP.</p> | |
| </div> | |
| </div> | |
| <div id="classic-sklearn" class="content-panel"> | |
| <div class="stack-layer"><h3><i class="material-icons">psychology</i>Model Layer</h3> | |
| <p>A classic logistic regression model. Serialization is typically done with `joblib` for efficiency with NumPy structures.</p> | |
| <p class="code-block-header">model_setup.py</p> | |
| <pre><code>import joblib | |
| from sklearn.linear_model import LogisticRegression | |
| from sklearn.datasets import make_classification | |
| X, y = make_classification(n_features=4) | |
| model = LogisticRegression().fit(X, y) | |
| joblib.dump(model, "sklearn_model.joblib")</code></pre> | |
| </div> | |
| <div class="stack-layer"><h3><i class="material-icons">layers</i>Serving Stack Layer</h3> | |
| <p>FastAPI provides a simple and fast web server. Kubeflow KServe and Ray Serve also have native support for scikit-learn models. NVIDIA Triton is an option for CPU-optimized execution using its FIL backend.</p> | |
| </div> | |
| <div class="stack-layer"><h3><i class="material-icons">cloud_queue</i>Orchestration Layer</h3> | |
| <p>Standard Kubernetes setup. The Docker container will be lightweight as it only needs `scikit-learn`, `joblib`, and `fastapi` for a custom server.</p> | |
| </div> | |
| <div class="stack-layer"><h3><i class="material-icons">memory</i>Hardware Layer</h3> | |
| <p><strong>CPUs:</strong> Almost always sufficient. There is no GPU acceleration for standard scikit-learn algorithms.</p> | |
| </div> | |
| </div> | |
| <div id="classic-xgboost" class="content-panel"> | |
| <div class="stack-layer"><h3><i class="material-icons">psychology</i>Model Layer</h3><p>An XGBoost model saved in its native JSON or UBJ format, which is portable and efficient.</p></div> | |
| <div class="stack-layer"><h3><i class="material-icons">layers</i>Serving Stack Layer</h3><p>Kubeflow KServe, Ray Serve, NVIDIA Triton (with FIL backend), and custom FastAPI servers are all excellent choices.</p></div> | |
| <div class="stack-layer"><h3><i class="material-icons">cloud_queue</i>Orchestration Layer</h3><p>Standard Kubernetes setup. The Dockerfile should include the `xgboost` library.</p></div> | |
| <div class="stack-layer"><h3><i class="material-icons">memory</i>Hardware Layer</h3><p><strong>CPUs:</strong> Excellent performance. <strong>GPUs:</strong> XGBoost has optional GPU acceleration which can provide a significant speedup.</p></div> | |
| </div> | |
| <div id="classic-jax" class="content-panel"> | |
| <div class="stack-layer"><h3><i class="material-icons">psychology</i>Model Layer</h3><p>JAX models are often defined as pure functions with parameters handled separately. We save the parameters using a standard serialization library like Flax's `msgpack`.</p></div> | |
| <div class="stack-layer"><h3><i class="material-icons">layers</i>Serving Stack Layer</h3><p>Ray Serve is an excellent fit for JAX's functional paradigm. A custom FastAPI server is also straightforward. Kubeflow KServe and NVIDIA Triton require a custom container approach wrapping the JAX logic.</p></div> | |
| <div class="stack-layer"><h3><i class="material-icons">cloud_queue</i>Orchestration Layer</h3><p>The Dockerfile needs to install `jax` and `jaxlib` corresponding to the target hardware (CPU, GPU, or TPU).</p></div> | |
| <div class="stack-layer"><h3><i class="material-icons">memory</i>Hardware Layer</h3><p><strong>CPUs/GPUs/TPUs:</strong> JAX was designed for accelerators and excels on all of them due to its XLA-based compilation.</p></div> | |
| </div> | |
| <!-- Gen AI Panels --> | |
| <div id="genai-llm" class="content-panel"> | |
| <div class="stack-layer"><h3><i class="material-icons">psychology</i>Model Layer</h3><p>Large Language Models (e.g., Llama, Mistral) are based on the Transformer architecture. The key inference challenge is managing the <strong>KV Cache</strong>.</p></div> | |
| <div class="stack-layer"><h3><i class="material-icons">layers</i>Serving Stack Layer</h3><p>Specialized serving toolkits like <strong>vLLM</strong>, <strong>SGLang</strong>, or <strong>NVIDIA Triton</strong> with its TensorRT-LLM backend are required for efficient inference, handling complexities like continuous batching and paged attention.</p></div> | |
| <div class="stack-layer"><h3><i class="material-icons">cloud_queue</i>Orchestration Layer</h3><p>Kubernetes (often with KubeRay) is used to manage GPU resources and schedule serving pods. Managed services like Vertex AI and SageMaker also provide optimized runtimes for popular LLMs.</p></div> | |
| <div class="stack-layer"><h3><i class="material-icons">memory</i>Hardware Layer</h3><p><strong>GPUs:</strong> Essential. High-VRAM GPUs like NVIDIA A100 or H100 are required to fit the model weights and KV cache. <strong>TPUs:</strong> Viable for specific models, especially on GCP.</p></div> | |
| </div> | |
| <div id="genai-vlm" class="content-panel"> | |
| <div class="stack-layer"><h3><i class="material-icons">psychology</i>Model Layer</h3><p>Visual Large Models (e.g., LLaVA, IDEFICS) combine a vision encoder (like ViT) with an LLM to process images and text.</p></div> | |
| <div class="stack-layer"><h3><i class="material-icons">layers</i>Serving Stack Layer</h3><p>The stack must handle multi-modal inputs. Frameworks like <strong>vLLM</strong> and <strong>SGLang</strong> are adding native support for VLMs. A custom container is often needed to handle the specific image preprocessing logic.</p></div> | |
| <div class="stack-layer"><h3><i class="material-icons">cloud_queue</i>Orchestration Layer</h3><p>Similar to LLMs, requires robust orchestration to manage high-resource GPU pods and potentially large input payloads.</p></div> | |
| <div class="stack-layer"><h3><i class="material-icons">memory</i>Hardware Layer</h3><p><strong>GPUs:</strong> High-VRAM GPUs are mandatory due to the combined size of the vision encoder, LLM, and KV cache.</p></div> | |
| </div> | |
| <div id="genai-diffusion" class="content-panel"> | |
| <div class="stack-layer"><h3><i class="material-icons">psychology</i>Model Layer</h3><p>Diffusion models (e.g., Stable Diffusion) generate images through an iterative denoising process, making latency a key challenge.</p></div> | |
| <div class="stack-layer"><h3><i class="material-icons">layers</i>Serving Stack Layer</h3><p>Optimizations focus on reducing latency. Key tools include model compilers like <strong>TensorRT</strong> (often used with NVIDIA Triton), techniques like <strong>Latent Consistency Models (LCMs)</strong>, and libraries like <strong>Diffusers</strong>, typically wrapped in a custom FastAPI container.</p></div> | |
| <div class="stack-layer"><h3><i class="material-icons">cloud_queue</i>Orchestration Layer</h3><p>Kubernetes or managed platforms are used to serve the GPU-intensive workload. Autoscaling is critical to handle bursty traffic patterns.</p></div> | |
| <div class="stack-layer"><h3><i class="material-icons">memory</i>Hardware Layer</h3><p><strong>GPUs:</strong> High-end consumer or datacenter GPUs are needed for acceptable generation speeds. VRAM is the most critical resource, dictating max resolution and batch size.</p></div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| const builder = document.getElementById('architecture-builder'); | |
| const generateBtn = document.getElementById('generate-btn'); | |
| const diagramOutput = document.getElementById('architecture-diagram-output'); | |
| const archTypeSelector = builder.querySelector('.arch-type-selector'); | |
| const classicFields = document.getElementById('classic-builder-fields'); | |
| const genaiFields = document.getElementById('genai-builder-fields'); | |
| function updateChipStates() { | |
| const activeArchType = archTypeSelector.querySelector('.active').dataset.type; | |
| const activeBuilderFields = (activeArchType === 'classic') ? classicFields : genaiFields; | |
| if (activeArchType === 'classic') { | |
| const activeFramework = activeBuilderFields.querySelector('.selection-group[data-group="framework"] .chip.active'); | |
| const torchserveChip = activeBuilderFields.querySelector('.chip[data-id="torchserve"]'); | |
| const tfservingChip = activeBuilderFields.querySelector('.chip[data-id="tf-serving"]'); | |
| [torchserveChip, tfservingChip].forEach(c => c.classList.remove('disabled')); | |
| if (activeFramework) { | |
| const frameworkId = activeFramework.dataset.id; | |
| const nonTfTsFrameworks = ['scikit-learn', 'xgboost', 'jax']; | |
| if (frameworkId === 'pytorch') { | |
| tfservingChip.classList.add('disabled'); | |
| if(tfservingChip.classList.contains('active')) tfservingChip.classList.remove('active'); | |
| } else if (frameworkId === 'tensorflow') { | |
| torchserveChip.classList.add('disabled'); | |
| if(torchserveChip.classList.contains('active')) torchserveChip.classList.remove('active'); | |
| } else if (nonTfTsFrameworks.includes(frameworkId)) { | |
| [torchserveChip, tfservingChip].forEach(c => { | |
| c.classList.add('disabled'); | |
| if(c.classList.contains('active')) c.classList.remove('active'); | |
| }); | |
| } | |
| } | |
| } else { // Gen AI Logic | |
| const activeModelType = activeBuilderFields.querySelector('.selection-group[data-group="model-type"] .chip.active'); | |
| const vllmChip = activeBuilderFields.querySelector('.chip[data-id="vllm"]'); | |
| const sglangChip = activeBuilderFields.querySelector('.chip[data-id="sglang"]'); | |
| [vllmChip, sglangChip].forEach(c => c.classList.remove('disabled')); | |
| if (activeModelType && activeModelType.dataset.id === 'diffusion') { | |
| [vllmChip, sglangChip].forEach(c => { | |
| c.classList.add('disabled'); | |
| if(c.classList.contains('active')) c.classList.remove('active'); | |
| }); | |
| } | |
| } | |
| const activeOrchestration = activeBuilderFields.querySelector('.selection-group[data-group="orchestration"] .chip.active'); | |
| const servingGroup = activeBuilderFields.querySelector('.selection-group[data-group="serving"]'); | |
| if (activeOrchestration && (activeOrchestration.dataset.id === 'vertex-ai' || activeOrchestration.dataset.id === 'sagemaker')) { | |
| servingGroup.classList.add('disabled'); | |
| servingGroup.querySelector('.chip.active')?.classList.remove('active'); | |
| } else { | |
| servingGroup.classList.remove('disabled'); | |
| } | |
| } | |
| archTypeSelector.addEventListener('click', function(e){ | |
| if (!e.target.classList.contains('arch-type-chip')) return; | |
| archTypeSelector.querySelectorAll('.arch-type-chip').forEach(c => c.classList.remove('active')); | |
| e.target.classList.add('active'); | |
| const type = e.target.dataset.type; | |
| classicFields.classList.toggle('active', type === 'classic'); | |
| genaiFields.classList.toggle('active', type === 'gen-ai'); | |
| diagramOutput.style.display = 'none'; | |
| updateChipStates(); | |
| }); | |
| builder.addEventListener('click', function(e) { | |
| if (!e.target.classList.contains('chip') || e.target.classList.contains('disabled')) return; | |
| const chip = e.target; | |
| const group = chip.closest('.selection-group'); | |
| if (group.classList.contains('disabled')) return; | |
| group.querySelectorAll('.chip').forEach(c => c.classList.remove('active')); | |
| chip.classList.add('active'); | |
| updateChipStates(); | |
| }); | |
| generateBtn.addEventListener('click', function() { | |
| const activeArchType = archTypeSelector.querySelector('.active').dataset.type; | |
| const activeBuilderFields = document.querySelector('.builder-fields.active'); | |
| const selections = {}; | |
| let allSelected = true; | |
| const isManaged = activeBuilderFields.querySelector('.selection-group[data-group="orchestration"] .chip.active')?.dataset.id.includes('vertex') || | |
| activeBuilderFields.querySelector('.selection-group[data-group="orchestration"] .chip.active')?.dataset.id.includes('sagemaker'); | |
| activeBuilderFields.querySelectorAll('.selection-group').forEach(group => { | |
| const groupKey = group.dataset.group; | |
| if (isManaged && groupKey === 'serving') return; | |
| const activeChip = group.querySelector('.chip.active'); | |
| if (activeChip) { | |
| selections[groupKey] = { name: activeChip.innerText, id: activeChip.dataset.id }; | |
| } else { | |
| allSelected = false; | |
| } | |
| }); | |
| if (!allSelected) { | |
| alert('Please make a selection for each required layer.'); | |
| return; | |
| } | |
| let diagramHtml = `<h3 class="diagram-title">Your Custom ${activeArchType === 'gen-ai' ? 'Generative AI' : 'Classic ML'} Architecture</h3><div class="diagram-stack">`; | |
| const arrowClass = activeArchType === 'gen-ai' ? 'gen-ai-arrow' : ''; | |
| const layerClass = activeArchType === 'gen-ai' ? 'gen-ai-layer' : ''; | |
| function createImageTag(selection) { | |
| return `<img src="${selection.id}.png" alt="${selection.name} Icon" class="icon-img-placeholder">`; | |
| } | |
| if (activeArchType === 'gen-ai') { | |
| diagramHtml += `<div class="diagram-layer ${layerClass}"><h5>${selections['model-type'].name}</h5><p>Model Type</p>${createImageTag(selections['model-type'])}</div><div class="diagram-arrow ${arrowClass}">south</div>`; | |
| } | |
| diagramHtml += `<div class="diagram-layer ${layerClass}"><h5>${selections.framework.name}</h5><p>ML Framework</p>${createImageTag(selections.framework)}</div><div class="diagram-arrow ${arrowClass}">south</div>`; | |
| if (isManaged) { | |
| diagramHtml += `<div class="diagram-layer ${layerClass}"><h5>${selections.orchestration.name}</h5><p>Managed Platform</p>${createImageTag(selections.orchestration)}</div><div class="diagram-arrow ${arrowClass}">south</div>`; | |
| } else { | |
| diagramHtml += `<div class="diagram-layer ${layerClass}"><h5>${selections.serving.name}</h5><p>Serving Container</p>${createImageTag(selections.serving)}</div><div class="diagram-arrow ${arrowClass}">south</div>`; | |
| diagramHtml += `<div class="diagram-layer ${layerClass}"><h5>${selections.orchestration.name}</h5><p>Orchestration</p>${createImageTag(selections.orchestration)}</div><div class="diagram-arrow ${arrowClass}">south</div>`; | |
| } | |
| diagramHtml += `<div class="diagram-layer ${layerClass}"><h5>${selections.hardware.name}</h5><p>Hardware</p>${createImageTag(selections.hardware)}</div>`; | |
| diagramHtml += `</div>`; | |
| diagramOutput.innerHTML = diagramHtml; | |
| diagramOutput.style.display = 'block'; | |
| diagramOutput.scrollIntoView({ behavior: 'smooth', block: 'center' }); | |
| }); | |
| const tiles = document.querySelectorAll('.tile'); | |
| const contentPanels = document.querySelectorAll('.content-panel'); | |
| tiles.forEach(tile => tile.addEventListener('click', (e) => { | |
| const targetId = e.currentTarget.dataset.target; | |
| tiles.forEach(t => t.classList.remove('active')); | |
| e.currentTarget.classList.add('active'); | |
| contentPanels.forEach(p => p.classList.remove('active')); | |
| const panel = document.getElementById(targetId); | |
| if (panel) { | |
| panel.classList.add('active'); | |
| panel.scrollIntoView({ behavior: 'smooth', block: 'start' }); | |
| } | |
| })); | |
| document.querySelectorAll('pre code').forEach(codeBlock => { | |
| const pre = codeBlock.parentElement; | |
| if (!pre.querySelector('.copy-btn')) { | |
| const copyButton = document.createElement('button'); | |
| copyButton.innerText = 'Copy'; | |
| copyButton.className = 'copy-btn'; | |
| pre.appendChild(copyButton); | |
| copyButton.addEventListener('click', (e) => { | |
| e.stopPropagation(); | |
| navigator.clipboard.writeText(codeBlock.innerText).then(() => { | |
| copyButton.innerText = 'Copied!'; | |
| copyButton.classList.add('copied'); | |
| setTimeout(() => { copyButton.innerText = 'Copy'; copyButton.classList.remove('copied'); }, 2000); | |
| }); | |
| }); | |
| } | |
| }); | |
| updateChipStates(); | |
| }); | |
| </script> | |
| </body> | |
| </html> |