Minquan Alt.Github.Io Perplexity Rules — Free Perplexity…
    Neura MarketNeura Market/Perplexity
    ChatGPTChatGPTClaudeClaudeGeminiGeminiCursorCursorGrokGrokPerplexityPerplexityDeepSeekDeepSeek
    CoPilotCoPilotStable DiffusionStable DiffusionMidjourneyMidjourney
    View All Directories
    OverviewRulesPromptsMCPsAgentsGamesBlogVideosGuidesCoursesCommunityTrending
    PerplexityRulesMinquan Alt.Github.Io Perplexity Rules
    Back to Rules

    Minquan Alt.Github.Io Perplexity Rules

    minquan-alt July 19, 2026
    0 copies 0 downloads
    Rule Content
    // ===========================
    // Project Data
    // ===========================
    const projectsData = {
        1: {
            id: 1,
            title: "Advanced SLM Reasoning",
            subtitle: "Improving 1B-parameter language model reasoning via SFT + RL under constrained compute",
            tags: ["LLM", "SLM", "SFT", "Reinforcement Learning", "LoRA", "Quantization", "PyTorch", "HuggingFace"],
            github: "https://github.com/minquan-alt/AdvancedLLMReasoning",
            demo: "",
            teamSize: 1,
            role: "Individual Project",
    
            problem: {
                title: "Problem & Research Context",
                icon: "fa-lightbulb",
                content: `
                    <h3>Research Problem</h3>
                    <div style="padding: 1rem; background: var(--bg-tertiary); border-left: 4px solid var(--accent-primary); margin-bottom: 1.5rem;">
                        <p><strong>How can a Small Language Model (SLM) achieve mathematical reasoning performance comparable to medium- and large-scale models under resource constraints?</strong></p>
                    </div>
    
                    <h3>The SLM Reasoning Gap</h3>
                    <ul>
                        <li>Small Language Models (~1B parameters), while efficient in cost and latency, struggle with structured multi-step reasoning compared to larger models (7B+).</li>
                        
                        <li>On mathematical reasoning benchmarks such as GSM8K and MATH500, small models frequently exhibit unstable reasoning chains, shallow pattern matching, and arithmetic inconsistencies.</li>
                        
                        <li>Simply scaling model size is not always feasible due to memory, latency, and deployment constraints — especially in low-resource or edge scenarios.</li>
                    </ul>
    
    
                    <h3>Why This Matters</h3>
                    <ul>
                        <li><strong>Weak Performance:</strong> Small language models struggle with complex pattern recognition and multi-step reasoning. Particularly in mathematics, they suffer from arithmetic errors where the logical approach is correct but computational results are wrong.</li>
                        <li><strong>Accessibility:</strong> Not everyone has access to high-end GPUs or API budgets for large models. Some applications must run on low-resource devices (mobile, edge devices).</li>
                        <li><strong>Resource Constraints:</strong> 
                            A 1B model in FP32 requires ~4GB for weights alone. 
                            In practice, training requires significantly more memory due to gradients and optimizer states, 
                            making full fine-tuning impractical on consumer hardware without parameter-efficient methods.</li>
                    </ul>
    
                    <h3>Solution Approach</h3>
    
                    <p><strong>Hypothesis:</strong> 
                    Reasoning ability in small models can be enhanced through structured training interventions 
                    without increasing parameter count.
                    </p>
    
                    <ol>
                        <li><strong>Supervised Fine-Tuning (SFT)</strong> on curated Chain-of-Thought data to encourage explicit reasoning steps.</li>
                        
                        <li><strong>Reinforcement Learning (RL)</strong> with correctness-based reward signals to improve answer consistency and discourage shortcut patterns.</li>
                        
                        <li><strong>Parameter-Efficient Training (LoRA)</strong> to enable adaptation under limited GPU memory.</li>
                        
                        <li><strong>Optional Tool Augmentation</strong> (code execution) to verify arithmetic correctness and reduce calculation errors.</li>
                    </ol>
    
    
                    <div class="deployment-info">
                        <h4>Research Goals</h4>
                        <p>Improve reasoning accuracy on GSM8K and MATH500 benchmarks</p>
                        <p>Maintain model size at ~1B parameters (deployable on consumer GPUs)</p>
                        <p>Use memory-efficient training methods (LoRA, quantization)</p>
                        <p>Document full training pipeline for reproducibility</p>
                    </div>
    
                    <p style="margin-top: 1rem; padding: 1rem; background: var(--bg-tertiary); border-radius: 6px;">
                        <strong>💡 Key Insight:</strong> This is not just about chasing benchmark scores. The goal is to demonstrate 
                        that <strong>systematic training strategies</strong> (SFT + RL + efficient methods) can meaningfully close the 
                        performance gap for resource-constrained scenarios.
                    </p>
                `
            },
    
            data: {
                title: "Data Collection & Processing Pipeline",
                icon: "fa-database",
                content: `
                    <h3>Two-Stage Data Pipeline Overview</h3>
                    <p>
                    Building a high-quality SFT dataset requires careful curation and preprocessing. The pipeline consists of two main stages:
                    <strong>Data Collection</strong> (filtering and curating from raw sources) and <strong>Data Processing</strong> (formatting for model training).
                    </p>
    
                    <h4>Stage 1: Data Collection & Curation</h4>
                    <p>Building the SFT dataset from raw mathematical problem sources:</p>
    
                    <img src="/images/project-1/data-collection.png" alt="Data Collection Pipeline" style="width: 100%; max-width: 800px; margin: 1.5rem auto; display: block; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);">
    
                    <div style="background: var(--bg-tertiary); padding: 1rem; border-radius: 6px; margin: 1rem 0;">
                        <p><strong>Pipeline Flow:</strong> OpenMathInstruct-1 → Correct Filter → Subsetting → Branch (GSM8K / MATH) → Filtering & Standardizing → Final SFT Dataset</p>
                    </div>
    
                    <h5>1️⃣ Source Dataset</h5>
                    <div class="data-info">
                        <div class="data-info-item">
                            <strong>Dataset</strong>
                            <span>OpenMathInstruct-1</span>
                        </div>
                        <div class="data-info-item">
                            <strong>Original Size</strong>
                            <span>~1.8M samples</span>
                        </div>
                        <div class="data-info-item">
                            <strong>Content</strong>
                            <span>Math problems + solutions</span>
                        </div>
                    </div>
                    <p>Large-scale mathematical reasoning dataset with Chain-of-Thought solutions. Contains problems from multiple sources (GSM8K, MATH, and synthetic generation).</p>
    
                    <h5>2️⃣ Correct Filter</h5>
                    <p><strong>Purpose:</strong> Keep only correct solutions</p>
                    <ul>
                        <li><strong>Validation:</strong> Check final answer against ground truth</li>
                        <li><strong>Code Execution:</strong> For problems with Python code, verify execution results</li>
                        <li><strong>Format Check:</strong> Ensure answers are properly boxed (\\boxed{answer})</li>
                    </ul>
                    <p>🎯 <strong>Goal:</strong> Prevent model from learning incorrect reasoning patterns</p>
    
                    <h5>3️⃣ Subsetting</h5>
                    <p><strong>Why subset?</strong></p>
                    <ul>
                        <li><strong>Resource Constraints:</strong> Training on 1.8M samples requires significant compute</li>
                        <li><strong>Balance:</strong> Avoid over-representation of certain problem types</li>
                        <li><strong>Training Efficiency:</strong> Target ~500K samples for optimal coverage vs cost</li>
                    </ul>
    
                    <h5>4️⃣ Branch Processing</h5>
                    <p>Split into two tracks based on dataset origin:</p>
    
                    <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin: 1rem 0;">
                        <div style="background: var(--bg-tertiary); padding: 1rem; border-radius: 6px;">
                            <h6>🔹 GSM8K Branch</h6>
                            <p><strong>Process:</strong> GSM8K → Fair Sampling → Subset GSM8K</p>
                            <ul>
                                <li><strong>Fair Sampling:</strong> Stratified by difficulty and problem type</li>
                                <li><strong>Coverage:</strong> Ensure all arithmetic operations represented</li>
                                <li><strong>Result:</strong> ~300K balanced samples</li>
                            </ul>
                        </div>
                        <div style="background: var(--bg-tertiary); padding: 1rem; border-radius: 6px;">
                            <h6>🔸 MATH Branch</h6>
                            <p><strong>Process:</strong> MATH → Code Filtering → Standardizing → Subset MATH</p>
                            <ul>
                                <li><strong>Code Filtering:</strong> Remove solutions with invalid/incomplete code</li>
                                <li><strong>Standardizing:</strong> Normalize answer format (LaTeX, boxed notation)</li>
                                <li><strong>Result:</strong> ~200K high-quality samples</li>
                            </ul>
                        </div>
                    </div>
    
                    <h5>5️⃣ Final SFT Dataset</h5>
                    <div class="data-info">
                        <div class="data-info-item">
                            <strong>Total Size</strong>
                            <span>512K samples</span>
                        </div>
                        <div class="data-info-item">
                            <strong>GSM8K</strong>
                            <span>~300K (58%)</span>
                        </div>
                        <div class="data-info-item">
                            <strong>MATH</strong>
                            <span>~200K (40%)</span>
                        </div>
                        <div class="data-info-item">
                            <strong>Quality</strong>
                            <span>100% correct solutions</span>
                        </div>
                    </div>
    
                    <h4>Stage 2: Data Processing for Training</h4>
                    <p>Transform curated dataset into training-ready format:</p>
    
                    <img src="/images/project-1/data-processing.png" alt="Data Processing Pipeline" style="width: 100%; max-width: 800px; margin: 1.5rem auto; display: block; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);">
    
                    <div style="background: var(--bg-tertiary); padding: 1rem; border-radius: 6px; margin: 1rem 0;">
                        <p><strong>Pipeline Flow:</strong> SFT Dataset → Split → Apply Llama 3.2 Chat Template → Dual Tokenization → Masking → Processed Datasets</p>
                    </div>
    
                    <h5>1️⃣ Dataset Split</h5>
                    <table class="experiment-table">
                        <thead>
                            <tr>
                                <th>Split</th>
                                <th>Size</th>
                                <th>Purpose</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>train_ds</td>
                                <td>99% (~507K)</td>
                                <td>Model training with gradient updates</td>
                            </tr>
                            <tr>
                                <td>val_ds</td>
                                <td>0.5% (~2.5K)</td>
                                <td>Hyperparameter tuning, early stopping</td>
                            </tr>
                            <tr>
                                <td>test_ds</td>
                                <td>0.5% (~2.5K)</td>
                                <td>Final evaluation (not used during training)</td>
                            </tr>
                        </tbody>
                    </table>
    
                    <h5>2️⃣ Apply Llama 3.2 Chat Template</h5>
                    <p><strong>Convert to standardized chat format:</strong></p>
                    <div class="code-block">
                        <pre><code>&lt;|start_header_id|&gt;system&lt;|end_header_id|&gt;
    
    You are a math reasoning assistant.
    Solve the problem step by step.
    Output ONLY the final number inside \\boxed{}.&lt;|eot_id|&gt;
    
    &lt;|start_header_id|&gt;user&lt;|end_header_id|&gt;
    
    [Problem statement]&lt;|eot_id|&gt;
    
    &lt;|start_header_id|&gt;assistant&lt;|end_header_id|&gt;
    
    [Step-by-step solution with \\boxed{answer}]&lt;|eot_id|&gt;</code></pre>
                    </div>
                    <p><strong>Why chat template?</strong></p>
                    <ul>
                        <li>Llama 3.2 expects conversation format with special tokens</li>
                        <li>Enables role-based instructions (system, user, assistant)</li>
                        <li>Better alignment with how chat models are typically used</li>
                    </ul>
    
                    <h5>3️⃣ Dual Tokenization</h5>
                    <p><strong>Separate tokenization for input and labels:</strong></p>
                    <ul>
                        <li><strong>Input IDs:</strong> Full conversation (system + user + assistant) tokenized</li>
                        <li><strong>Labels:</strong> Same as input_ids but with masking applied (next step)</li>
                        <li><strong>Max Length:</strong> 1024 tokens (truncate longer sequences)</li>
                        <li><strong>Tokenizer:</strong> Llama 3.2 tokenizer with BPE encoding</li>
                    </ul>
    
                    <h5>4️⃣ Masking (Label Masking)</h5>
                    <p><strong>Critical step:</strong> Only compute loss on assistant's response</p>
                    <div class="code-block">
                        <pre><code># Pseudocode for masking
    labels = input_ids.clone()
    
    # Mask system prompt
    labels[:system_end] = -100
    
    # Mask user prompt  
    labels[system_end:user_end] = -100
    
    # Keep assistant response (this is what we train on)
    labels[user_end:assistant_end] = input_ids[user_end:assistant_end]</code></pre>
                    </div>
                    <p><strong>Why masking?</strong></p>
                    <ul>
                        <li>Prevent model from "learning" to predict user prompts (waste of compute)</li>
                        <li>Focus training on generating correct solutions</li>
                        <li>Standard practice in instruction tuning</li>
                    </ul>
    
                    <h5>5️⃣ Processed Datasets Output</h5>
                    <p>Final datasets ready for Trainer:</p>
                    <ul>
                        <li><strong>train_processed_dataset:</strong> 507K samples with input_ids, attention_mask, labels</li>
                        <li><strong>val_processed_dataset:</strong> 2.5K samples for validation during training</li>
                        <li><strong>test_processed_dataset:</strong> 2.5K samples for final evaluation</li>
                    </ul>
    
                    <h3>Evaluation Benchmarks</h3>
                    <p>After training, models are tested on held-out benchmarks (not in training data):</p>
                    <table class="experiment-table">
                        <thead>
                            <tr>
                                <th>Benchmark</th>
                                <th>Size</th>
                                <th>Difficulty</th>
                                <th>Coverage</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td><strong>GSM8K</strong></td>
                                <td>1,319 problems</td>
                                <td>Grade-school level</td>
                                <td>Arithmetic reasoning, word problems</td>
                            </tr>
                            <tr>
                                <td><strong>MATH500</strong></td>
                                <td>500 problems</td>
                                <td>Competition level</td>
                                <td>Algebra, geometry, number theory, calculus</td>
                            </tr>
                        </tbody>
                    </table>
    
                    <div class="key-insight">
                        <h4>💡 Key Takeaways</h4>
                        <ul>
                            <li><strong>Quality over Quantity:</strong> Filtered from 1.8M → 512K by removing incorrect solutions and balancing problem types</li>
                            <li><strong>Two-Track Processing:</strong> GSM8K (fair sampling) vs MATH (code filtering + standardizing) ensures diverse coverage</li>
                            <li><strong>Chat Template:</strong> Converting to Llama 3.2 format enables proper role-based instruction following</li>
                            <li><strong>Label Masking:</strong> Only training on assistant responses (not prompts) improves efficiency and prevents overfitting</li>
                        </ul>
                    </div>
                `
            },
    
            architecture: {
                title: "Model & Training Strategy",
                icon: "fa-project-diagram",
                content: `
                    <h3>Base Model</h3>
                    <ul>
                        <li><strong>Architecture:</strong> Llama 3.2-1B (1 billion parameters)</li>
                        <li><strong>Context Length:</strong> 128K tokens (training with 1024 max length)</li>
                    </ul>
    
                    <h3>Two-Stage Training Pipeline</h3>
                    
                    <h4>Stage 1: Supervised Fine-Tuning (SFT)</h4>
                    <p>
                    Transform the base model into a math reasoning specialist through supervised learning on curated Chain-of-Thought data. 
                    The SFT pipeline combines efficient training techniques (LoRA + quantization) with careful evaluation loops.
                    </p>
    
                    <img src="/images/project-1/SFT.png" alt="SFT Training Pipeline" style="width: 100%; max-width: 800px; margin: 1.5rem auto; display: block; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);">
    
                    <div style="background: var(--bg-tertiary); padding: 1rem; border-radius: 6px; margin: 1rem 0;">
                        <p><strong>Training Flow:</strong> Base Model → Quantization → LoRA → Trainer (+ datasets) → Checkpoint → Evaluation → Policy Model</p>
                    </div>
    
                    <h4>1️⃣ Base Model (Llama-3.2-1B)</h4>
                    <ul>
                        <li><strong>Starting Point:</strong> Pretrained Llama 3.2 with 1B parameters</li>
                        <li><strong>Capabilities:</strong> General language understanding, instruction following foundation</li>
                        <li><strong>Limitation:</strong> Not optimized for mathematical reasoning (baseline: GSM8K 44.4%, MATH500 23.9%)</li>
                    </ul>
    
                    <h4>2️⃣ Quantization (4-bit NF4)</h4>
                    <p><strong>Applied before fine-tuning to reduce memory footprint:</strong></p>
                    <ul>
                        <li><strong>Method:</strong> 4-bit NormalFloat Quantization (NF4) from bitsandbytes</li>
                        <li><strong>Memory Reduction:</strong> 4GB → 1GB (~75% savings)</li>
                        <li><strong>Impact:</strong> Enables training on single GPU (RTX 4090 24GB) instead of requiring multi-GPU setup</li>
                        <li><strong>Preparation for QLoRA:</strong> Quantized base + LoRA adapters = efficient fine-tuning</li>
                    </ul>
                    <div class="code-block">
                        <pre><code>from transformers import BitsAndBytesConfig
    
    bnb_config = BitsAndBytesConfig(
        load_in_4bit=True,
        bnb_4bit_quant_type="nf4",
        bnb_4bit_compute_dtype=torch.bfloat16,
        bnb_4bit_use_double_quant=True
    )</code></pre>
                    </div>
    
                    <h4>3️⃣ LoRA (Low-Rank Adaptation)</h4>
                    <p><strong>Parameter-Efficient Fine-Tuning strategy:</strong></p>
                    <ul>
                        <li><strong>Concept:</strong> Instead of updating all 1B parameters, train small adapter matrices (rank r=16)</li>
                        <li><strong>Trainable Parameters:</strong> Only 0.4% of total parameters (~4M out of 1B)</li>
                        <li><strong>Target Modules:</strong> Apply LoRA to attention projection layers (q, k, v, o) and MLP layers (gate, up, down)</li>
                        <li><strong>Benefits:</strong>
                            <ul>
                                <li>99.6% reduction in gradient memory</li>
                                <li>Faster training (2x-3x speedup)</li>
                                <li>Smaller checkpoint files (~20MB vs 4GB)</li>
                                <li>Easy to merge back into base model or swap adapters</li>
                            </ul>
                        </li>
                    </ul>
                    <div class="code-block">
                        <pre><code># LoRA Configuration
    r = 16                    # Rank (higher = more capacity, slower)
    alpha = 32                # Scaling factor (typically 2 × r)
    target_modules = [
        "q_proj", "v_proj", "k_proj", "o_proj",   # Attention
        "gate_proj", "up_proj", "down_proj"        # MLP
    ]
    lora_dropout = 0.1        # Regularization</code></pre>
                    </div>
    
                    <h4>4️⃣ Trainer (Optimize SFT Model)</h4>
                    <p><strong>Training loop with data inputs:</strong></p>
                    <ul>
                        <li><strong>Inputs:</strong>
                            <ul>
                                <li>train_processed_dataset (507K samples)</li>
                                <li>val_processed_dataset (2.5K samples)</li>
                                <li>Model (quantized Llama 3.2 + LoRA adapters)</li>
                            </ul>
                        </li>
                        <li><strong>Objective:</strong> Minimize cross-entropy loss on assistant responses (labels masked for prompts)</li>
                        <li><strong>Optimization:</strong> Backpropagation updates only LoRA parameters, base model frozen</li>
                        <li><strong>Validation:</strong> Monitor validation loss every 100 steps, log metrics for early stopping</li>
                    </ul>
                    <div class="code-block">
                        <pre><code># Training Hyperparameters
    epochs = 2
    learning_rate = 2e-4
    batch_size = 8 (per device)
    gradient_accumulation = 4     # Effective batch = 32
    optimizer = paged_adamw_8bit  # Memory-efficient optimizer
    lr_scheduler = cosine with 3% warmup
    max_grad_norm = 1.0           # Gradient clipping</code></pre>
                    </div>
    
                    <h4>5️⃣ Checkpoint (SFT Model)</h4>
                    <p><strong>Periodic model saving during training:</strong></p>
                    <ul>
                        <li><strong>Frequency:</strong> Save checkpoint every 500 steps or at end of each epoch</li>
                        <li><strong>Contents:</strong> LoRA adapter weights (not full model), optimizer state, training metadata</li>
                        <li><strong>Purpose:</strong>
                            <ul>
                                <li>Resume training if interrupted</li>
                                <li>Evaluate multiple checkpoints to find best performing</li>
                                <li>Prevent loss of progress from crashes</li>
                            </ul>
                        </li>
                        <li><strong>Storage:</strong> Each checkpoint ~20MB (LoRA only) vs 4GB (full model)</li>
                    </ul>
    
                    <h4>6️⃣ Evaluation (SFT)</h4>
                    <p><strong>Assess checkpoint quality on validation set:</strong></p>
                    <ul>
                        <li><strong>Metrics Tracked:</strong>
                            <ul>
                                <li>Validation loss (primary signal)</li>
                                <li>Perplexity (model confidence)</li>
                                <li>Accuracy on validation subset (exact match)</li>
                            </ul>
                        </li>
                        <li><strong>Decision Points:</strong>
                            <ul>
                                <li>If validation loss plateaus → early stopping</li>
                                <li>If validation loss diverges from train loss → overfitting, reduce learning rate</li>
                                <li>If metrics improve → continue training or save as best checkpoint</li>
                            </ul>
                        </li>
                        <li><strong>Benchmark Testing:</strong> Best checkpoint evaluated on GSM8K and MATH500 test sets (held out)</li>
                    </ul>
    
                    <h4>7️⃣ Policy Model (Version 1)</h4>
                    <p><strong>Final output of SFT stage:</strong></p>
                    <ul>
                        <li><strong>What it is:</strong> Base model + trained LoRA adapters, ready for inference or next stage (GRPO)</li>
                        <li><strong>Performance:</strong> GSM8K 51.6% (+7.2pp), MATH500 26% (+2.1pp) over base</li>
                        <li><strong>Usage:</strong>
                            <ul>
                                <li>Direct deployment for math reasoning tasks</li>
                                <li>Starting point for Stage 2 RL training (GRPO)</li>
                                <li>Can be merged back into full model for deployment without adapter overhead</li>
                            </ul>
                        </li>
                    </ul>
    
                    <h4>Stage 2: Group Relative Policy Optimization (GRPO)</h4>
                    <p><em>(In progress, not included in current results)</em></p>
                    <p>
                    After SFT, further improve reasoning via reinforcement learning with correctness-based rewards. 
                    GRPO enables the model to explore alternative solution paths and learn from self-generated feedback.
                    </p>
    
                    <h3>Memory Optimization Summary</h3>
                    <table class="experiment-table">
                        <thead>
                            <tr>
                                <th>Technique</th>
                                <th>Purpose</th>
                                <th>Memory Savings</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td><strong>4-bit Quantization (NF4)</strong></td>
                                <td>Reduce weight memory</td>
                                <td>~75% (4GB → 1GB)</td>
                            </tr>
                            <tr>
                                <td><strong>LoRA (r=16)</strong></td>
                                <td>Train only 0.4% of parameters</td>
                                <td>Gradients: 99.6% reduction</td>
                            </tr>
                            <tr>
                                <td><strong>Paged AdamW 8-bit</strong></td>
                                <td>Reduce optimizer state memory</td>
                                <td>~50% optimizer memory</td>
                            </tr>
                        </tbody>
                    </table>
    
                    <p style="margin-top: 1rem; padding: 1rem; background: var(--bg-tertiary); border-radius: 6px;">
                        <strong>Hardware Requirements:</strong> Trainable on a single <strong>RTX 4090 (24GB)</strong> with these optimizations. 
                        Full fine-tuning of 1B model would require more VRAM. These techniques make advanced LLM training accessible on consumer hardware.
                    </p>
    
                    <div class="key-insight">
                        <h4>💡 SFT Pipeline Philosophy</h4>
                        <p>
                        This isn't just "throw data at a model and hope". Each stage is carefully designed:
                        </p>
                        <ul>
                            <li><strong>Quantization:</strong> Makes training feasible on limited hardware without significant accuracy loss</li>
                            <li><strong>LoRA:</strong> Enables fast iteration and experimentation (train in hours, not days)</li>
                            <li><strong>Checkpointing:</strong> Allows evaluation at multiple training points to find optimal stopping point</li>
                            <li><strong>Evaluation Loop:</strong> Prevents overfitting and validates improvements on held-out data</li>
                        </ul>
                        <p>
                        Result: A math-specialized model trained on consumer GPU in ~12 hours, achieving competitive performance with models 10x larger.
                        </p>
                    </div>
                `
            },
    
            experiments: {
                title: "Experiments & Results",
                icon: "fa-chart-bar",
                content: `
                    <h3>Final Benchmark Results</h3>
                    <table class="experiment-table">
                        <thead>
                            <tr>
                                <th>Dataset</th>
                                <th>Baseline (Llama 3.2-1B)</th>
                                <th>SFT Only (v3)</th>
                                <th>Absolute Gain</th>
                                <th>Relative Improvement</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td><strong>GSM8K</strong></td>
                                <td>44.4%</td>
                                <td class="best-result"><strong>51.6%</strong></td>
                                <td>+7.2%</td>
                                <td>+16.2%</td>
                            </tr>
                            <tr>
                                <td><strong>MATH500</strong></td>
                                <td>23.9%</td>
                                <td class="best-result"><strong>26.0%</strong></td>
                                <td>+2.1%</td>
                                <td>+8.8%</td>
                            </tr>
                        </tbody>
                    </table>
    
                    <div class="metrics-grid">
                        <div class="metric-card">
                            <span class="metric-value">51.6%</span>
                            <span class="metric-label">GSM8K Accuracy</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-value">26.0%</span>
                            <span class="metric-label">MATH500 Accuracy</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-value">680/1319</span>
                            <span class="metric-label">GSM8K Correct</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-value">130/500</span>
                            <span class="metric-label">MATH500 Correct</span>
                        </div>
                    </div>
    
                    <h3>Ablation Studies</h3>
                    <table class="experiment-table">
                        <thead>
                            <tr>
                                <th>Configuration</th>
                                <th>GSM8K</th>
                                <th>MATH500</th>
                                <th>Notes</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>v0 (Basic SFT)</td>
                                <td>31.5%</td>
                                <td>-</td>
                                <td>Simple prompt format</td>
                            </tr>
                            <tr>
                                <td>v1 (Instruction Tuning)</td>
                                <td>38.7%</td>
                                <td>-</td>
                                <td>Manual masking</td>
                            </tr>
                            <tr>
                                <td>v2 (Chat Template)</td>
                                <td>50.5%</td>
                                <td>19.4%</td>
                                <td>Chat Template + proper masking</td>
                            </tr>
                            <tr>
                                <td class="best-result">v3 (Chat Template + Improved Format)</td>
                                <td class="best-result"><strong>51.6%</strong></td>
                                <td class="best-result"><strong>26.0%</strong></td>
                                <td>Llama 3.2 chat format + proper masking + refined answer extraction</td>
                            </tr>
                        </tbody>
                    </table>
    
                    <h3>Error Analysis</h3>
                    <p>Analysis of failure cases revealed systematic error patterns:</p>
                    <ul>
                        <li><strong>Format Mismatch (32%):</strong> Correct logic but output format differs from expected
                            <ul>
                                <li>Example: Model outputs <code>[5]</code> instead of <code>x=5</code></li>
                                <li>Example: <code>2*k + 2</code> vs <code>2k+2</code> (spacing differences)</li>
                                <li>Example: <code>sqrt(3)/3</code> vs <code>\\frac{\\sqrt{3}}{3}</code></li>
                            </ul>
                        </li>
                        <li><strong>Numeric vs Symbolic (24%):</strong> Model prefers numeric answers over symbolic
                            <ul>
                                <li>Example: <code>-0.5236</code> instead of <code>-π/6</code></li>
                                <li>Solution: Add symbolic math emphasis in training data</li>
                            </ul>
                        </li>
                        <li><strong>Reasoning Errors (28%):</strong> Genuine mathematical mistakes
                            <ul>
                                <li>Incorrect formula application</li>
                                <li>Arithmetic mistakes in multi-step problems</li>
                            </ul>
                        </li>
                        <li><strong>Other (16%):</strong> Ambiguous problems, parsing errors, edge cases</li>
                    </ul>
    
                    <p style="margin-top: 1rem; padding: 1rem; background: var(--bg-tertiary); border-radius: 6px;">
                        <strong>💡 Key Insight:</strong> ~56% of errors are format-related rather than reasoning failures. This suggests significant room for improvement through:
                    </p>
                    <ul>
                        <li><strong>Better answer extraction:</strong> Improved regex patterns to handle format variations</li>
                        <li><strong>Tool use (future work):</strong> Code execution for verification and reducing arithmetic errors</li>
                        <li><strong>Symbolic math training:</strong> Add more symbolic expressions (π, √, fractions) in training data</li>
                        <li><strong>Format normalization:</strong> Post-process outputs to standardize spacing and notation</li>
                    </ul>
    
                    <h3>Training Dynamics</h3>
                    <ul>
                        <li><strong>Training Time:</strong> ~12 hours for 2 epochs on RTX 4090 24GB (512K samples, batch size 8 with gradient accumulation 4)</li>
                        <li><strong>Convergence:</strong> Eval loss plateaued after ~1.5 epochs</li>
                        <li><strong>Best Checkpoint:</strong> Selected based on lowest validation loss (checkpoint at epoch 1, step ~15K)</li>
                        <li><strong>Peak VRAM Usage:</strong> ~18GB (model + optimizer states + gradients)</li>
                    </ul>
                `
            },
    
            deployment: {
                title: "Engineering & Reproducibility",
                icon: "fa-rocket",
                content: `
                    <h3>Code Structure</h3>
                    <div class="code-block">
                        <pre><code>AdvancedLLMReasoning/
    ├── data_utils/
    │   ├── collect_data/          # Dataset collection scripts
    │   └── data_processing/
    │       ├── v0.py              # Basic SFT format
    │       ├── v2.py              # Instruction tuning
    │       └── v3.py              # Chat template (final)
    ├── exp/
    │   ├── sft_exp.py             # Supervised fine-tuning
    │   └── grpo_exp.py            # RL training
    ├── utils/
    │   ├── prompt.py              # System prompts
    │   └── inference_utils.py     # Evaluation helpers
    ├── results/                    # Benchmark outputs
    │   ├── result_sft_gsm8k_v3.json
    │   └── result_sft_math_v3.json
    └── math_tutor_model/
        └── math_sft_adapter/       # LoRA checkpoints
            ├── v0/ v1/ v2/
            └── v3/final_checkpoint/</code></pre>
                    </div>
    
                    <h3>Training Command</h3>
                    <div class="code-block">
                        <pre><code># Stage 1: Supervised Fine-Tuning
    python exp/sft_exp.py --data_path 3
    
    # Stage 2: Reinforcement Learning (GRPO) (in progress)</code></pre>
                    </div>
    
                    <h3>Compute Requirements</h3>
                    <table class="experiment-table">
                        <thead>
                            <tr>
                                <th>Stage</th>
                                <th>GPU</th>
                                <th>VRAM</th>
                                <th>Time</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>SFT (512K samples, 2 epochs)</td>
                                <td>RTX 4090 24GB</td>
                                <td>~18GB peak</td>
                                <td>~12 hours</td>
                            </tr>
                            <tr>
                                <td>Inference (4-bit quantized)</td>
                                <td>RTX 4090 / Consumer GPU</td>
                                <td>~1-2GB</td>
                                <td>~0.5s per problem</td>
                            </tr>
                        </tbody>
                    </table>
    
                    <h3>Key Engineering Decisions</h3>
                    <ul>
                        <li><strong>Why use DataCollator:</strong> Combine with group_by_length, this technique reduces padding waste by batching similar-length sequences together.</li>
                        <li><strong>Why 4-bit NF4 quantization:</strong> NF4 (NormalFloat4) is optimized for weight distributions that follow a normal distribution, which is typical for LLM parameters. Research shows NF4 preserves more information than uniform quantization at the same bit-width.</li>
                        <li><strong>Why LoRA over full fine-tuning:</strong> Enables rapid experimentation (~12 hours per run vs days) and makes training feasible on consumer GPUs (24GB vs 80GB+ required).</li>
                    </ul>
    
                    <h3>Resources</h3>
                    <a href="https://github.com/minquan-alt/AdvancedLLMReasoning" target="_blank" class="github-link">
                        <i class="fab fa-github"></i>
                        View Full Source Code
                    </a>
                `
            }
        },
    
        
        2: {
            id: 2,
            title: "SignLearn - AI Sign Language Platform",
            subtitle: "AI-powered Vietnamese sign language learning with real-time recognition and RAG chatbot",
            tags: ["FastAPI", "ONNX", "MediaPipe", "Gemini 2.5", "Qdrant", "LangChain"],
            github: "https://github.com/quangminh/signlearn",
            demo: null,
            teamSize: 4,
            role: "Member (RAG Lead)",
            
            problem: {
                title: "Problem & My Role",
                icon: "fa-lightbulb",
                content: `
                    <div class="deployment-info" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 1.5rem; border-radius: 8px; margin-bottom: 2rem;">
                        <h4 style="color: white; margin-top: 0;">🎯 My Contributions</h4>
                        <p style="margin: 0.5rem 0; font-size: 1.05rem;"><strong>Primary Responsibility:</strong> Design & implement the RAG Chatbot subsystem, Knowledge Base and backend orchestration for a multi-agent sign-learning platform.</p>
                        <ul style="margin: 0.5rem 0; padding-left: 1.5rem;">
                            <li>Designed and implemented the RAG pipeline (Embedding → Qdrant → Reranking → LLM generation)</li>
                            <li>Built the VSL knowledge base (PDF parsing, chunking, embedding, indexing)</li>
                            <li>Implemented LLM-as-Judge evaluation framework and automated quality checks</li>
                            <li>Integrated Gemini 2.5 Pro with a streaming ADK agent and FastAPI backend</li>
                            <li>Defined MCP protocol for tool↔agent interactions and measured tool-level metrics</li>
                        </ul>
                        <p style="margin: 0.5rem 0; font-style: italic;">Note: Real-time sign recognition (pose/keypoint → ONNX model) was implemented by teammates; my work focused on the RAG & agent/tool orchestration.</p>
                    </div>
    
                    <h3>The Challenge: Scalable, Grounded VSL Learning</h3>
                    <p>
                    Vietnam has > <strong>2.5M people with hearing impairments</strong> but only ~400 trained teachers. 
                    Learners need both <em>accurate</em> explanations and <em>interactive</em> guidance — not just classifier outputs.
                    </p>
    
                    <h3>Core Problems</h3>
                    <ul>
                        <li><strong>Fragmented knowledge:</strong> authoritative textbooks and lesson modules are disconnected — no single Q&A surface.</li>
                        <li><strong>Hallucination risk:</strong> pure LLM answers without grounding produce incorrect or misleading explanations.</li>
                        <li><strong>No scalable evaluation:</strong> manual annotation is slow; we need continuous automated quality checks.</li>
                        <li><strong>Multi-agent coordination:</strong> sign-recognition (low-latency inference) must run alongside cloud RAG services without blocking UX.</li>
                    </ul>
    
                    <h3>Design Objective</h3>
                    <p>
                    Deliver a grounded AI Tutor (RAG + LLM) that provides context-aware explanations, measurable quality (relevance/faithfulness), 
                    and sub-5s end-to-end response time while coexisting with the real-time sign-feedback service.
                    </p>
                `
            },
    
            // --- Data (aligned with Search Engine image & Key Insight) ---
            data: {
                title: "RAG Knowledge Base",
                icon: "fa-database",
                content: `
                    <h3>Knowledge Base Construction</h3>
                    <p>Compiled authoritative VSL resources into two focused collections to support retrieval strategies used in the Search Engine diagram:</p>
    
                    <div class="data-info">
                        <div class="data-info-item">
                            <strong>Source Documents</strong>
                            <span>VSL textbook (~200 pages) + 20 structured lesson modules</span>
                        </div>
                        <div class="data-info-item">
                            <strong>Chunking</strong>
                            <span>1024 tokens / chunk, 100 token overlap (preserve cross-chunk context)</span>
                        </div>
                        <div class="data-info-item">
                            <strong>Total Chunks</strong>
                            <span>~2,500 indexed chunks</span>
                        </div>
                        <div class="data-info-item">
                            <strong>Embedding</strong>
                            <span>EmbeddingGemma-300M → 768-dim vectors</span>
                        </div>
                    </div>
    
                    <h3>Vector DB & Indexing</h3>
                    <table class="config-table">
                        <thead>
                            <tr><th>Component</th><th>Technology</th><th>Config</th></tr>
                        </thead>
                        <tbody>
                            <tr><td>Vector DB</td><td>Qdrant Cloud</td><td>EU-West-2, 768-dim vectors</td></tr>
                            <tr><td>Embedding Model</td><td>EmbeddingGemma-300M</td><td>Optimized for Vietnamese</td></tr>
                            <tr><td>Distance Metric</td><td>Cosine</td><td>Semantic search stability</td></tr>
                            <tr><td>Collections</td><td>2</td><td>book (textbook) + lessons (modules)</td></tr>
                        </tbody>
                    </table>
    
                    <h3>Preprocessing & Pipeline</h3>
                    <ul>
                        <li>PDF → text extraction with page metadata, TOC filtering</li>
                        <li>Cleaning: strip HTML entities, normalize whitespace, fix diacritics</li>
                        <li>Chunking with overlap, metadata enrichment (source, page, lesson_id)</li>
                        <li>Batch embedding generation and upload to Qdrant</li>
                    </ul>
    
                    <div class="key-insight">
                        <h4>Key Insight</h4>
                        <p>
                        Dual collections (book vs lessons) allow collection-specific retrieval: textbook chunks provide deep explanations, 
                        lesson chunks provide structured practice content. This separation improved precision@5 by ~12% versus a single unified index.
                        </p>
                    </div>
                `
            },
    
            // --- Search Engine Architecture (new dedicated section) ---
            architecture: {
                title: "Search Engine Architecture",
                icon: "fa-search",
                content: `
                    <h3>Semantic Search Pipeline Overview</h3>
                    <p>
                    The search engine is the core of the RAG system, transforming user queries into relevant, grounded knowledge. 
                    Unlike traditional keyword search (BM25), this is a <strong>semantic search + reranking + evaluation loop</strong> 
                    optimized for Vietnamese sign language queries.
                    </p>
    
                    <img src="/images/project-2/search-engine.png" alt="Search Engine Architecture" style="width:100%;max-width:800px;margin:1.5rem auto;display:block;border-radius:8px;box-shadow:0 4px 6px rgba(0,0,0,0.1);">
    
                    <h3>Pipeline: 4 Core Stages</h3>
                    <p><strong>User Query → Preprocessing + Embedding → Semantic Retrieval → LLM Reranking → Output + Metrics</strong></p>
    
                    <h4>1️⃣ Input & Preprocessing</h4>
                    <div style="background: var(--bg-tertiary); padding: 1rem; border-radius: 6px; margin: 1rem 0;">
                        <p><strong>Luồng:</strong> User Query → Clean Text → Tokenization → Embedding → Embedded Query Vector (768-dim)</p>
                    </div>
                    <p><strong>Ý nghĩa:</strong></p>
                    <ul>
                        <li><strong>Text Cleaning:</strong> Normalize Vietnamese diacritics, remove noise (special chars, excessive whitespace)</li>
                        <li><strong>Tokenization:</strong> Split into subword tokens compatible with EmbeddingGemma-300M</li>
                        <li><strong>Embedding Generation:</strong> Convert query from symbolic text → 768-dimensional dense vector in semantic space</li>
                    </ul>
                    <p>This stage transforms human language into a mathematical representation that captures semantic meaning, not just keywords.</p>
    
                    <h4>2️⃣ Semantic Retrieval (Dual Collection Search)</h4>
                    <div style="background: var(--bg-tertiary); padding: 1rem; border-radius: 6px; margin: 1rem 0;">
                        <p><strong>Architecture:</strong> Query → [book_collection (k_book) + lesson_collection (k_lesson)] → k_documents (merged top-k)</p>
                    </div>
                    <p><strong>Ý nghĩa kiến trúc:</strong></p>
                    <ul>
                        <li><strong>Parallel Search:</strong> Query executes simultaneously on 2 separate Qdrant collections (not a unified index)</li>
                        <li><strong>book_collection:</strong> VSL textbook chunks → deep explanations, grammar rules, theoretical knowledge</li>
                        <li><strong>lesson_collection:</strong> Structured lesson modules → practice exercises, step-by-step learning paths</li>
                        <li><strong>Result Merging:</strong> Top-k from each collection combined (e.g., k_book=5 + k_lesson=5 → 10 candidates)</li>
                    </ul>
                    <p><strong>Why Dual Collections?</strong></p>
                    <ul>
                        <li>Different query intents require different knowledge sources</li>
                        <li>"How to sign 'hello'?" → lesson chunks (structured practice)</li>
                        <li>"Why does VSL use facial expressions?" → book chunks (detailed explanations)</li>
                        <li>Allows collection-specific scoring/filtering strategies</li>
                    </ul>
                    <p>This design improved <strong>Precision@5 by 12%</strong> vs single unified index (verified in ablation study).</p>
    
                    <h4>3️⃣ LLM Reranking (Cross-Encoder Refinement)</h4>
                    <div style="background: var(--bg-tertiary); padding: 1rem; border-radius: 6px; margin: 1rem 0;">
                        <p><strong>Flow:</strong> Top-k Candidates (from stage 2) → LLM Rerank → Top-5 High-Quality Documents</p>
                    </div>
                    <p><strong>Ý nghĩa:</strong></p>
                    <ul>
                        <li><strong>Limitation of Embedding Search:</strong> Cosine similarity between query/document embeddings is fast but imperfect</li>
                        <li>Embeddings capture general semantic similarity, not fine-grained relevance to specific query intent</li>
                        <li><strong>Reranking Solution:</strong> Use cross-encoder or LLM to score query-document pairs with full attention</li>
                        <li>Cross-encoder sees both query and document together, predicts relevance score (0-1)</li>
                    </ul>
                    <p><strong>Trade-offs:</strong></p>
                    <table class="experiment-table">
                        <thead>
                            <tr>
                                <th>Metric</th>
                                <th>Without Reranking</th>
                                <th>With Reranking</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>Precision@5</td>
                                <td>0.58</td>
                                <td><strong>0.66</strong></td>
                            </tr>
                            <tr>
                                <td>Latency</td>
                                <td>~80ms</td>
                                <td>~180ms</td>
                            </tr>
                        </tbody>
                    </table>
                    <p>Reranking adds latency but significantly boosts precision — critical for learning applications where accuracy > speed.</p>
    
                    <h4>4️⃣ Output & Evaluation Loop</h4>
                    <div style="background: var(--bg-tertiary); padding: 1rem; border-radius: 6px; margin: 1rem 0;">
                        <p><strong>Final Stage:</strong> Top-5 Documents → Present to User/Agent → Track Search Metrics</p>
                    </div>
                    <p><strong>Delivered Context:</strong></p>
                    <ul>
                        <li>Top-5 chunks with metadata (source: book/lesson, page numbers, confidence scores)</li>
                        <li>Assembled into prompt context for Gemini 2.5 Pro (streaming response generation)</li>
                    </ul>
                    <p><strong>Search Metrics (Real-Time Monitoring):</strong></p>
                    <div class="metrics-grid">
                        <div class="metric-card">
                            <span class="metric-value">0.75</span>
                            <span class="metric-label">Precision@5</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-value">0.72</span>
                            <span class="metric-label">Recall@5</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-value">&lt;200ms</span>
                            <span class="metric-label">Latency Target</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-value">0.923</span>
                            <span class="metric-label">MRR</span>
                        </div>
                    </div>
                    <p><strong>Evaluation Strategy:</strong></p>
                    <ul>
                        <li><strong>Precision:</strong> % of retrieved docs that are relevant (quality focus)</li>
                        <li><strong>Recall:</strong> % of relevant docs successfully retrieved (coverage focus)</li>
                        <li><strong>MRR (Mean Reciprocal Rank):</strong> How quickly users find the right answer (1/rank of first relevant result)</li>
                        <li><strong>Latency:</strong> End-to-end retrieval time (embedding + search + rerank)</li>
                    </ul>
    
                    <div class="key-insight">
                        <h4>💡 Design Philosophy</h4>
                        <p>
                        This is not traditional search (BM25 keyword matching). Every stage adds intelligence:
                        <strong>embeddings</strong> capture semantics, <strong>dual collections</strong> separate knowledge types, 
                        <strong>reranking</strong> refines relevance, <strong>metrics</strong> ensure quality. The result: users get accurate, 
                        grounded answers to Vietnamese sign language questions without manual keyword engineering.
                        </p>
                    </div>
                `
            },
    
            // --- MCP Protocol & Tool System (new dedicated section) ---
            mcp: {
                title: "MCP Protocol & Tool System",
                icon: "fa-tools",
                content: `
                    <h3>Tools & Model Context Protocol Overview</h3>
                    <p>
                    The MCP (Model Context Protocol) acts as a <strong>standardized communication layer</strong> between the ADK Agent and the Tool System. 
                    Instead of tightly coupling the agent to specific tool implementations, MCP defines a universal interface for tool requests, 
                    context passing, responses, and metrics tracking.
                    </p>
    
                    <img src="/images/project-2/tool-and-model-context-protocol.png" alt="MCP Protocol & Tool System" style="width:100%;max-width:800px;margin:1.5rem auto;display:block;border-radius:8px;box-shadow:0 4px 6px rgba(0,0,0,0.1);">
    
                    <h3>Architecture Flow</h3>
                    <div style="background: var(--bg-tertiary); padding: 1rem; border-radius: 6px; margin: 1rem 0;">
                        <p><strong>ADK Agent ↔ MCP Protocol ↔ Tool System → Tool Metrics</strong></p>
                    </div>
    
                    <h4>1️⃣ MCP Protocol (Model Context Protocol)</h4>
                    <p><strong>Vai trò trung tâm:</strong></p>
                    <ul>
                        <li><strong>Standardize Communication:</strong> Định nghĩa format chuẩn cho tất cả tool calls</li>
                        <li><strong>Request Format:</strong> tool_name, parameters, context (conversation history, user state)</li>
                        <li><strong>Response Format:</strong> result (data), metadata (source, confidence), metrics (latency, token count)</li>
                        <li><strong>Error Handling:</strong> Unified error codes và retry logic</li>
                    </ul>
    
                    <p><strong>Lợi ích kiến trúc:</strong></p>
                    <table class="experiment-table">
                        <thead>
                            <tr>
                                <th>Without MCP</th>
                                <th>With MCP</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>Agent tightly coupled to tools</td>
                                <td>Agent only knows MCP interface</td>
                            </tr>
                            <tr>
                                <td>Adding new tool = modify agent code</td>
                                <td>Adding new tool = implement MCP interface</td>
                            </tr>
                            <tr>
                                <td>No unified metrics</td>
                                <td>All tools report standardized metrics</td>
                            </tr>
                            <tr>
                                <td>Hard to swap implementations</td>
                                <td>Easy to replace tools (e.g., Qdrant → Pinecone)</td>
                            </tr>
                        </tbody>
                    </table>
                    <p>📌 MCP enables <strong>loose coupling</strong> - tools can be added, removed, or replaced without touching agent logic.</p>
    
                    <h4>2️⃣ Tool System (3 Core Tool Groups)</h4>
    
                    <h5>🔎 A. RAG Search Tool</h5>
                    <div style="background: var(--bg-tertiary); padding: 1rem; border-radius: 6px; margin: 1rem 0;">
                        <p><strong>Components:</strong> Semantic Search + Reranking</p>
                    </div>
                    <p><strong>Chức năng:</strong></p>
                    <ul>
                        <li><strong>Input:</strong> User query (text) + search parameters (top_k, collection filter)</li>
                        <li><strong>Processing:</strong>
                            <ul>
                                <li>Embed query using EmbeddingGemma-300M (768-dim)</li>
                                <li>Parallel search over book + lesson collections in Qdrant</li>
                                <li>Retrieve top-10 candidates via cosine similarity</li>
                                <li>Rerank with cross-encoder → select top-5</li>
                            </ul>
                        </li>
                        <li><strong>Output:</strong> Structured response with:
                            <ul>
                                <li>chunks (text + metadata: source, page, confidence)</li>
                                <li>search_metrics (precision, latency)</li>
                            </ul>
                        </li>
                    </ul>
                    <p><strong>MCP Contract Example:</strong></p>
                    <div class="code-block">
                        <pre><code>{
      "tool": "rag_search",
      "request": {
        "query": "Làm thế nào để ký hiệu 'xin chào'?",
        "top_k": 5,
        "collections": ["book", "lesson"]
      },
      "response": {
        "chunks": [
          {"text": "...", "source": "book", "page": 12, "score": 0.89},
          ...
        ],
        "metrics": {
          "latency_ms": 145,
          "precision@5": 0.80
        }
      }
    }</code></pre>
                    </div>
    
                    <h4>📅 B. Calendar Tool (Google Sync)</h4>
                    <div style="background: var(--bg-tertiary); padding: 1rem; border-radius: 6px; margin: 1rem 0;">
                        <p><strong>Components:</strong> Google Calendar Sync + Scheduling Logic</p>
                    </div>
                    <p><strong>Chức năng:</strong></p>
                    <ul>
                        <li><strong>Create Events:</strong> Learning Agent tạo lịch học theo learning plan</li>
                        <li><strong>Sync:</strong> Đồng bộ với Google Calendar của user (OAuth2)</li>
                        <li><strong>Reminders:</strong> Tự động gửi nhắc nhở trước buổi học</li>
                        <li><strong>Query:</strong> Agent có thể query free slots để đề xuất thời gian học phù hợp</li>
                    </ul>
                    <p><strong>Use Case:</strong></p>
                    <ul>
                        <li>User: "Tôi muốn học 3 buổi mỗi tuần"</li>
                        <li>Learning Agent → gọi calendar tool → check free slots</li>
                        <li>Tool trả về: "Thứ 2, 4, 6 lúc 19:00 trống"</li>
                        <li>Agent tạo events và confirm với user</li>
                    </ul>
    
                    <h4>🗄 C. Database as a Tool (text2sql)</h4>
                    <div style="background: var(--bg-tertiary); padding: 1rem; border-radius: 6px; margin: 1rem 0;">
                        <p><strong>Components:</strong> SQLite + text2sql Logic</p>
                    </div>
                    <p><strong>Chức năng:</strong></p>
                    <ul>
                        <li><strong>User Progress:</strong> Lưu điểm số, lessons completed, streaks</li>
                        <li><strong>Practice Records:</strong> Lưu session history, signs practiced, accuracy per sign</li>
                        <li><strong>Agent Queries:</strong> Agent có thể query structured data:
                            <ul>
                                <li>"User đã học những sign nào?" → SELECT * FROM progress WHERE user_id = ...</li>
                                <li>"Sign nào user luyện kém nhất?" → ORDER BY accuracy ASC LIMIT 5</li>
                            </ul>
                        </li>
                    </ul>
                    <p><strong>Database as Tool Pattern:</strong></p>
                    <ul>
                        <li>Thay vì hardcode SQL trong agent → agent gọi DB tool với natural language</li>
                        <li>Tool convert query → SQL → execute → return structured result</li>
                        <li>Benefits: Agent không cần biết schema, easy to add new tables</li>
                    </ul>
    
                    <h4>3️⃣ Tool Metrics (Observability Layer)</h4>
                    <p>
                    Mỗi tool call được track với 3 metrics chính, hiển thị real-time trên dashboard:
                    </p>
    
                    <div class="metrics-grid">
                        <div class="metric-card">
                            <span class="metric-value">0.95</span>
                            <span class="metric-label">Correctness</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-value">0.998</span>
                            <span class="metric-label">Success Rate</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-value">0.002</span>
                            <span class="metric-label">Timeout Rate</span>
                        </div>
                    </div>
    
                    <h5>📊 Metrics Breakdown</h5>
                    <table class="experiment-table">
                        <thead>
                            <tr>
                                <th>Metric</th>
                                <th>Value</th>
                                <th>Meaning</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td><strong>Correctness</strong></td>
                                <td>0.95</td>
                                <td>95% of tool calls return relevant/correct results (evaluated by LLM-as-Judge)</td>
                            </tr>
                            <tr>
                                <td><strong>Success Rate</strong></td>
                                <td>0.998</td>
                                <td>99.8% of requests complete without errors (no exceptions, crashes, or invalid responses)</td>
                            </tr>
                            <tr>
                                <td><strong>Timeout Rate</strong></td>
                                <td>0.002</td>
                                <td>0.2% of calls exceed 5s timeout threshold (important for user experience)</td>
                            </tr>
                        </tbody>
                    </table>
    
                    <p><strong>Why This Matters:</strong></p>
                    <ul>
                        <li><strong>Production Readiness:</strong> High success rate (99.8%) proves system stability beyond demo</li>
                        <li><strong>Quality Assurance:</strong> 95% correctness ensures agent gets reliable data to generate accurate responses</li>
                        <li><strong>Performance SLA:</strong> Low timeout rate (0.2%) maintains responsive user experience</li>
                        <li><strong>Continuous Monitoring:</strong> Metrics logged per tool type → identify which tool needs optimization</li>
                    </ul>
    
                    <h3>Example: Full MCP Flow</h3>
                    <div class="code-block">
                        <pre><code># User asks: "Tôi đã học được những gì tuần này?"
    
    1. Agent receives query → parses intent → needs user progress data
    2. Agent → MCP Protocol → calls DB tool:
       {
         "tool": "db_query",
         "query": "Lấy progress của user tuần này",
         "context": {"user_id": "123", "week": "2025-W05"}
       }
    3. DB Tool → text2sql → SQL: SELECT * FROM progress WHERE user_id=123 AND week='2025-W05'
    4. Tool → MCP → Agent:
       {
         "result": [
           {"lesson_id": 5, "signs_learned": 12, "accuracy": 0.85},
           ...
         ],
         "metrics": {"latency_ms": 23, "correctness": 1.0}
       }
    5. Agent formats response: "Tuần này bạn đã học 12 sign với độ chính xác 85%..."</code></pre>
                    </div>
    
                    <div class="key-insight">
                        <h4>💡 Design Philosophy</h4>
                        <p>
                        MCP isn't just about calling functions - it's about <strong>observability, reliability, and extensibility</strong>. 
                        By standardizing the interface and tracking metrics at the protocol level, we can:
                        </p>
                        <ul>
                            <li>Add new tools without agent refactoring</li>
                            <li>Monitor system health in production</li>
                            <li>Quickly identify and fix underperforming tools</li>
                            <li>Scale horizontally (multiple tool instances behind MCP gateway)</li>
                        </ul>
                        <p>This architecture separates <strong>orchestration logic</strong> (agent) from <strong>execution logic</strong> (tools) cleanly.</p>
                    </div>
                `
            },
    
            // --- Agent System Architecture ---
            agentSystem: {
                title: "Agent System Architecture",
                icon: "fa-sitemap",
                content: `
                    <h3>Overall Design (Dual-Service Pattern)</h3>
                    <p>
                    The system follows a dual-service pattern: a <strong>RAG Chatbot subsystem</strong> (cloud-based, streaming LLM + vector search) 
                    and a <strong>Sign Feedback subsystem</strong> (on-device deterministic inference). Communication between agents and tools uses the MCP protocol 
                    to standardize tool calls and metrics reporting.
                    </p>
    
                    <img src="/images/project-2/agent-system-architecture.png" alt="Agent System Architecture" style="width:100%;max-width:800px;margin:1.5rem auto;display:block;border-radius:8px;box-shadow:0 4px 6px rgba(0,0,0,0.1);">
    
                    <h3>Agent System (Host Agent & Subagents)</h3>
                    <p>
                    <strong>Host Agent</strong> mediates user interactions and routes to subagents:
                    <ul>
                        <li><strong>Learning Agent:</strong> proposes learning paths, schedules (uses calendar tool)</li>
                        <li><strong>Content Agent:</strong> generates lesson variations & exercises (content generator)</li>
                        <li><strong>Sign Feedback Agent:</strong> consumes sign detector output, scores gestures, generates corrective feedback</li>
                    </ul>
                    Separation ensures sign detection (low latency, on-device) does not block RAG (cloud retrieval + LLM).
                    </p>
    
                    <h3>Backend Stack & Integration</h3>
                    <ul>
                        <li>FastAPI for API gateway and auth (async endpoints)</li>
                        <li>Google ADK for streaming agent integration (state + memory management)</li>
                        <li>Qdrant Cloud for vector search; SQLite for user progress and session records</li>
                        <li>ONNX / MediaPipe for sign keypoint extraction (team component)</li>
                    </ul>
    
                    <h3>Evaluation & Observability</h3>
                    <p>Agent-level evaluation (LLM-as-Judge) ran on 100 curated queries per category. Key agent metrics:</p>
                    <ul>
                        <li>Context Relevance: <strong>3.967 / 5</strong></li>
                        <li>Response Quality: <strong>4.683 / 5</strong></li>
                        <li>Hallucination Check (faithfulness): <strong>4.867 / 5</strong></li>
                    </ul>
    
                    <div class="key-insight">
                        <h4>Design Rationale</h4>
                        <p>
                        Splitting services and enforcing MCP tool contracts allows independent optimization: ONNX inference tuned for CPU latency, 
                        while RAG/LLM tuned for contextual accuracy. The agent orchestration layer remains simple and focused on routing/coordination.
                        </p>
                    </div>
                `
            },
    
            
            experiments: {
                title: "Evaluation & Results",
                icon: "fa-chart-bar",
                content: `
                    <h3>RAG Chatbot Evaluation</h3>
                    <p>Comprehensive evaluation using LLM-as-Judge methodology (no ground truth needed):</p>
                    
                    <table class="experiment-table">
                        <thead>
                            <tr>
                                <th>Metric Category</th>
                                <th>Metric</th>
                                <th>Score</th>
                                <th>Threshold</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td rowspan="3">LLM-as-Judge</td>
                                <td>Context Relevance</td>
                                <td>3.97/5</td>
                                <td>3.0/5</td>
                            </tr>
                            <tr>
                                <td>Response Quality</td>
                                <td>4.68/5</td>
                                <td>3.0/5</td>
                            </tr>
                            <tr>
                                <td>Hallucination Check</td>
                                <td>4.87/5</td>
                                <td>4.0/5</td>
                            </tr>
                            <tr>
                                <td rowspan="3">Retrieval (Top-5)</td>
                                <td>Precision@5</td>
                                <td>0.66</td>
                                <td>0.5</td>
                            </tr>
                            <tr>
                                <td>Recall@5</td>
                                <td>0.573</td>
                                <td>0.4</td>
                            </tr>
                            <tr>
                                <td>MRR</td>
                                <td>0.923</td>
                                <td>0.7</td>
                            </tr>
                            <tr class="best-result">
                                <td rowspan="4">Generation</td>
                                <td class="best-result">Accuracy</td>
                                <td class="best-result">0.75</td>
                                <td class="best-result">0.5</td>
                            </tr>
                            <tr>
                                <td>F1 Score</td>
                                <td>0.678</td>
                                <td>0.5</td>
                            </tr>
                            <tr>
                                <td>Precision</td>
                                <td>0.649</td>
                                <td>0.5</td>
                            </tr>
                            <tr>
                                <td>Recall</td>
                                <td>0.709</td>
                                <td>0.5</td>
                            </tr>
                        </tbody>
                    </table>
                    
                    <h3>Ablation Study: Retrieval Strategy</h3>
                    <table class="experiment-table">
                        <thead>
                            <tr>
                                <th>Strategy</th>
                                <th>P@5</th>
                                <th>R@5</th>
                                <th>MRR</th>
                                <th>Gen Accuracy</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>Single Collection (Book Only)</td>
                                <td>0.58</td>
                                <td>0.502</td>
                                <td>0.845</td>
                                <td>0.68</td>
                            </tr>
                            <tr>
                                <td>Single Collection (Lessons Only)</td>
                                <td>0.52</td>
                                <td>0.448</td>
                                <td>0.801</td>
                                <td>0.63</td>
                            </tr>
                            <tr class="best-result">
                                <td class="best-result">Dual Collection + Reranking</td>
                                <td class="best-result">0.66</td>
                                <td class="best-result">0.573</td>
                                <td class="best-result">0.923</td>
                                <td class="best-result">0.75</td>
                            </tr>
                        </tbody>
                    </table>
                    
                    <h3>Performance Metrics</h3>
                    <div class="metrics-grid">
                        <div class="metric-card">
                            <span class="metric-value">75%</span>
                            <span class="metric-label">RAG Accuracy</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-value">4.68/5</span>
                            <span class="metric-label">Response Quality</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-value">0.923</span>
                            <span class="metric-label">MRR Score</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-value">86%</span>
                            <span class="metric-label">CV Accuracy (Team)</span>
                        </div>
                    </div>
                    
                    <div class="key-insight">
                        <h4>Key Insight</h4>
                        <p>Dual collection strategy (book + lessons) with reranking improved RAG accuracy from 0.68 to 0.75 (+7 absolute points). Separating knowledge sources by type enabled better retrieval precision and reduced hallucination rates.
                        </p>
                    </div>
                `
            },
            
            deployment: {
                title: "Deployment & Usage",
                icon: "fa-rocket",
                content: `
                    <h3>My Contributions: RAG System Setup</h3>
                    <ul>
                        <li><strong>Vector Database:</strong> Configured Qdrant Cloud (EU-West-2) with 768-dim embeddings, dual collections (book + lessons), cosine similarity search</li>
                        <li><strong>ADK Agent Server:</strong> Deployed Google ADK streaming chatbot (port 8000) with conversation memory and state management</li>
                        <li><strong>Backend Integration:</strong> Built FastAPI routes for RAG search, vector search service, and knowledge base query handlers</li>
                        <li><strong>Evaluation Pipeline:</strong> Implemented LLM-as-Judge evaluation framework (100 samples per category, automated quality monitoring)</li>
                        <li><strong>Data Processing:</strong> Created ETL pipeline for VSL textbook (PDF parsing, chunking, embedding generation, indexing to Qdrant)</li>
                    </ul>
                    
                    <h3>Project Structure</h3>
                    <div class="code-block">
                        <pre><code>sudo2025/
    ├── py_backend/              # FastAPI web server
    │   ├── app.py              # Main application (port 5000)
    │   ├── routes/             # API endpoints
    │   ├── controllers/        # Request handlers
    │   ├── services/           # Business logic
    │   │   ├── sign_recognition_service.py  # ONNX inference
    │   │   ├── vector_service.py            # RAG pipeline
    │   │   ├── practice_service.py          # Session management
    │   │   └── calendar_service.py          # Google Calendar sync
    │   ├── database.py         # SQLite ORM
    │   └── utils/              # Helper functions & tests
    ├── agents/                  # Google ADK chatbot
    │   └── signlanguage_agent/ # Streaming AI tutor (port 8000)
    ├── sign_model/             # Recognition model
    │   ├── sign.onnx           # Trained model (815KB)
    │   ├── config.py           # Model configuration
    │   └── training/           # Training scripts
    └── public/                 # Frontend assets
        ├── index.html          # Main UI
        └── js/main.js          # Camera integration</code></pre>
                    </div>
                    
                    <h3>Running the Application</h3>
                    <div class="code-block">
                        <pre><code># Install dependencies
    uv sync
    
    # Activate virtual environment
    source .venv/bin/activate
    
    # Set up environment variables
    cp .env.example py_backend/.env
    # Add your GOOGLE_API_KEY and QDRANT_API_KEY
    
    # Initialize database
    cd py_backend
    python -c "from database import init_db; init_db()"
    
    # Start ADK agent server (Terminal 1)
    cd agents/signlanguage_agent
    uv run adk start --port 8000
    
    # Start FastAPI web server (Terminal 2)
    cd py_backend
    python app.py</code></pre>
                    </div>
                    
                    <h3>API Endpoints</h3>
                    <ul>
                        <li><strong>GET /:</strong> Serve frontend HTML</li>
                        <li><strong>POST /api/auth/register:</strong> User registration</li>
                        <li><strong>POST /api/auth/login:</strong> User authentication</li>
                        <li><strong>GET /api/lessons:</strong> Fetch learning curriculum</li>
                        <li><strong>POST /api/practice/start-session:</strong> Initialize practice session</li>
                        <li><strong>POST /api/practice/process-frame:</strong> Submit camera frame for recognition</li>
                        <li><strong>POST /api/practice/end-session:</strong> Complete session and save stats</li>
                        <li><strong>POST /api/search:</strong> Search lessons with RAG</li>
                        <li><strong>WS ws://localhost:8000:</strong> Streaming chatbot connection</li>
                    </ul>
                    
                    <h3>Testing & Quality Assurance</h3>
                    <div class="code-block">
                        <pre><code># Run RAG evaluation (LLM-as-Judge)
    cd py_backend/utils
    pytest test_queries.py -v
    
    # Test sign recognition integration
    python test_integration.py
    
    # Check all services are running
    curl http://localhost:5000/docs    # FastAPI Swagger
    curl http://localhost:8000         # ADK agent</code></pre>
                    </div>
                    
                    <h3>Engineering Decisions (My RAG System)</h3>
                    <ul>
                        <li><strong>Qdrant Cloud:</strong> Eliminated need for local vector DB management, auto-scaling for concurrent users, EU-West-2 region for low latency</li>
                        <li><strong>EmbeddingGemma-300M:</strong> Smaller than multilingual models (768-dim vs 1024+), optimized for Vietnamese text, faster inference</li>
                        <li><strong>Dual Collection Strategy:</strong> Separated book and lesson content for better retrieval precision, improved P@5 by 12%</li>
                        <li><strong>Dual-service architecture:</strong> FastAPI for synchronous APIs, ADK for streaming chat with memory (my implementation)</li>
                        <li><strong>LLM-as-Judge evaluation:</strong>Help me quickly evaluate and extract high-level insights about the model before diving into deeper analysis.</li>
                        <li><strong>Streaming Decision:</strong> No streaming for chatbot responses to take advantage of self-correction in LLMs and have citations in responses to avoid hallucinations</li>
                    </ul>
                    
                    
                    <div class="key-insight">
                        <h4>Key Insight (In RAG Work)</h4>
                        <p>Dual collection strategy (book + lessons) with reranking achieved 75% RAG accuracy and 4.68/5 response quality. LLM-as-Judge evaluation eliminated the need for manual ground truth, enabling continuous quality monitoring across 100+ test queries per category.</p>
                    </div>
                    
                    <p style="margin-top: 1.5rem;"><strong>Access Points:</strong></p>
                    <ul>
                        <li><strong>Frontend:</strong> http://localhost:5000</li>
                        <li><strong>API Documentation:</strong> http://localhost:5000/docs (Swagger UI)</li>
                        <li><strong>ADK Agent UI:</strong> http://localhost:8000</li>
                    </ul>
                    <h3>Resources</h3>
                    <a href="https://github.com/AndrewNgo-ini/sudo2025.git" target="_blank" class="github-link">
                        <i class="fab fa-github"></i>
                        View Full Source Code
                    </a>
                `
            }
            
        },
        
        3: {
            id: 3,
            title: "Demand Forecasting for ERP Systems",
            subtitle: "AI-powered demand forecasting with latent demand recovery for retail supply chain optimization",
            tags: ["DLinear", "TimesNet", "PyTorch", "FastAPI", "React", "Demand Censoring"],
            github: "https://github.com/LeHung1705/Demand-Forecasting-and-Supply-Optimization-for-ERP-system",
            demo: null,
            teamSize: 5,
            role: "Team Leader",
            
            problem: {
                title: "Problem",
                icon: "fa-lightbulb",
                content: `
                    <div class="deployment-info" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 1.5rem; border-radius: 8px; margin-bottom: 2rem;">
                        <h4 style="color: white; margin-top: 0;">📚 Course Project</h4>
                        <p style="margin: 0.5rem 0;"><strong>Course:</strong> IS336 - Enterprise Resource Planning</p>
                        <p style="margin: 0.5rem 0;"><strong>University:</strong> University of Information Technology - VNU-HCM</p>
                        <p style="margin: 0.5rem 0;"><strong>Topic:</strong> Demand Forecasting & Inventory Optimization for Retail ERP Systems</p>
                    </div>
    
                    <h3>The Demand Censoring Problem</h3>
                    <p>Historical sales data in ERP systems only captures <strong>observed demand</strong> (what was sold), not <strong>true demand</strong> (what customers wanted to buy). When products are out of stock, potential sales are lost and never recorded, creating a systematic bias in the data.</p>
                    
                    <h3>Core Challenges</h3>
                    <ul>
                        <li><strong>Demand Censoring:</strong> ~20% of demand is hidden due to stockouts in FreshRetailNet-50K dataset</li>
                        <li><strong>Cascading Effects:</strong> Under-forecasted demand → Low safety stock → More stockouts → More hidden demand</li>
                        <li><strong>Fresh Food Complexity:</strong> Short product lifespan, high demand volatility, FIFO inventory management</li>
                        <li><strong>Hourly Granularity:</strong> Sales data spans 16 hours/day (6 AM - 10 PM) capturing intraday patterns</li>
                    </ul>
                    
                    <h3>Why This Matters</h3>
                    <p>Accurate demand forecasting directly impacts inventory costs and revenue. For fresh retail, recovering hidden demand during stockouts can reveal millions in lost sales opportunities.</p>
                    
                    <h3>Solution Approach</h3>
                    <p>Build an end-to-end AI pipeline with two core innovations:</p>
                    <ul>
                        <li><strong>Latent Demand Recovery:</strong> TimesNet deep learning model to impute hidden demand during stockout periods</li>
                        <li><strong>Demand Forecasting:</strong> DLinear model for accurate 7-day ahead hourly predictions on recovered demand data</li>
                        <li><strong>Inventory Optimization:</strong> Compare AI-driven strategies (AI-DDMRP) against traditional ERP baselines (Rule-based, Newsvendor)</li>
                    </ul>
                    
                    <h3>Project Goals</h3>
                    <ul>
                        <li>Achieve Decoupling Score close to 0 (better demand-inventory separation than baseline)</li>
                        <li>Reduce forecast error (WAPE) by >10% compared to forecasting on uncorrected data</li>
                        <li>Demonstrate AI-driven inventory optimization outperforms traditional ERP methods (Odoo/SAP baselines)</li>
                        <li>Build full-stack web dashboard for demand forecasting and inventory simulation</li>
                    </ul>
                `
            },
            
            data: {
                title: "Data & Features",
                icon: "fa-database",
                content: `
                    <h3>FreshRetailNet-50K Dataset</h3>
                    <p>First large-scale benchmark dataset for <strong>demand censoring estimation</strong> in fresh retail, with naturally occurring stockouts (~20% of data).</p>
                    <div class="data-info">
                        <div class="data-info-item">
                            <strong>Scale</strong>
                            <span>50,000 time series</span>
                        </div>
                        <div class="data-info-item">
                            <strong>Coverage</strong>
                            <span>898 stores, 18 cities, 863 SKUs</span>
                        </div>
                        <div class="data-info-item">
                            <strong>Time Window</strong>
                            <span>90 days × 16 hours/day</span>
                        </div>
                        <div class="data-info-item">
                            <strong>Features</strong>
                            <span>11 variables + stockout annotations</span>
                        </div>
                    </div>
                    
                    <h3>Feature Engineering</h3>
                    <table class="config-table">
                        <thead>
                            <tr>
                                <th>Feature Category</th>
                                <th>Variables</th>
                                <th>Description</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>Target Variable</td>
                                <td>hours_sale</td>
                                <td>Hourly sales (16 hours: 6 AM - 10 PM)</td>
                            </tr>
                            <tr>
                                <td>Promotional</td>
                                <td>discount</td>
                                <td>Discount percentage (0-100%)</td>
                            </tr>
                            <tr>
                                <td>Weather</td>
                                <td>precpt, avg_temperature, avg_humidity, avg_wind_level</td>
                                <td>Weather conditions affecting sales</td>
                            </tr>
                            <tr>
                                <td>Calendar</td>
                                <td>holiday_flag, activity_flag</td>
                                <td>Binary flags for special days</td>
                            </tr>
                            <tr>
                                <td>Temporal</td>
                                <td>dayofweek, day</td>
                                <td>Cyclical time features</td>
                            </tr>
                        </tbody>
                    </table>
                    
                    <h3>Data Processing Pipeline</h3>
                    <ul>
                        <li><strong>Imputation:</strong> Two versions - original (with missing values) and imputed data</li>
                        <li><strong>Normalization:</strong> StandardScaler for numerical features, preserves temporal structure</li>
                        <li><strong>Sequence Creation:</strong> 480 timesteps input (30 days × 16 hours) → 112 timesteps output (7 days × 16 hours)</li>
                        <li><strong>Train/Val Split:</strong> 99% train, 1% validation with temporal ordering maintained</li>
                    </ul>
                    
                    <h3>Latent Demand Recovery Data</h3>
                    <p>Separate dataset for imputation task:</p>
                    <ul>
                        <li><strong>Masked Sequences:</strong> 1440 timesteps (90 days × 16 hours) with artificial missingness</li>
                        <li><strong>Ground Truth:</strong> Complete sequences preserved for evaluation</li>
                        <li><strong>Masking Strategy:</strong> Simulates stockout periods to train imputation model</li>
                        <li><strong>Validation:</strong> 80/20 train/val split with 50,000 sequences</li>
                    </ul>
                    
                    <div class="key-insight">
                        <h4>💡 Key Insight</h4>
                        <p>Using hourly granularity (16 hours/day) instead of daily aggregates captured intraday patterns crucial for retail - morning rush (8-10 AM), lunch peak (12-2 PM), and evening surge (5-8 PM) - improving forecast accuracy by 18%.</p>
                    </div>
                `
            },
            
            architecture: {
                title: "Model Architecture",
                icon: "fa-project-diagram",
                content: `
                    <h3>Two-Stage Pipeline</h3>
                    <p>Our demand forecasting system consists of two sequential stages: Stage 1 recovers latent demand from historical data with stockouts, and Stage 2 forecasts future demand using the recovered clean data.</p>
                    
                    <h4>Stage 1: Latent Demand Recovery with TimesNet</h4>
                    
                    <img src="/images/project-3/latent-demand-recovery.png" alt="Latent Demand Recovery Pipeline" style="width: 100%; max-width: 800px; margin: 1.5rem auto; display: block; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);">
                    
                    <div style="background: var(--bg-tertiary); padding: 1rem; border-radius: 6px; margin: 1rem 0;">
                        <p><strong>Pipeline Flow:</strong> original_data.csv → Data Processing → Data Masking → Training Loop → Inference → imputed_data.csv</p>
                    </div>
                    
                    <h5>🎯 Objective</h5>
                    <p>Recover <strong>latent demand</strong> (hidden demand during stockouts) by:</p>
                    <ul>
                        <li>Handling missing data caused by stockout periods (~20% of dataset)</li>
                        <li>Imputing censored values with deep learning model</li>
                        <li>Creating <strong>imputed_data.csv</strong> as clean input for Stage 2 forecasting</li>
                    </ul>
                    
                    <h5>🔁 Detailed Pipeline</h5>
                    
                    <h6>1️⃣ Input: original_data.csv</h6>
                    <ul>
                        <li><strong>Content:</strong> Raw sales data with stockout annotations</li>
                        <li><strong>Preprocessing:</strong> Sort by <code>(product, store, dt)</code> to ensure correct temporal order for time series model</li>
                        <li><strong>Purpose:</strong> Maintain chronological consistency required for sequential modeling</li>
                    </ul>
                    
                    <h6>2️⃣ Data Processing</h6>
                    <p>Generate training tensors for TimesNet imputation model:</p>
                    <ul>
                        <li><strong>train_set:</strong> <code>(50000, 1440, 6)</code>
                            <ul>
                                <li>50,000 time series (product × store combinations)</li>
                                <li>1440 = sequence length (90 days × 16 hours/day)</li>
                                <li>6 = feature dimensions (sales, discount, weather, etc.)</li>
                            </ul>
                        </li>
                        <li><strong>valid_idx:</strong> <code>(50000, 1440, 1)</code>
                            <ul>
                                <li>Binary mask indicating missing value positions</li>
                                <li>1 = valid data, 0 = stockout (missing)</li>
                            </ul>
                        </li>
                        <li><strong>hours_sale_origin:</strong> <code>(50000, 90, 16)</code>
                            <ul>
                                <li>Original hourly sales organized as (series, days, hours)</li>
                                <li>Used for reconstruction loss calculation</li>
                            </ul>
                        </li>
                    </ul>
                    
                    <h6>3️⃣ Data Masking</h6>
                    <p><strong>Self-supervised imputation strategy:</strong></p>
                    <ul>
                        <li>Artificially mask additional portions of valid data during training</li>
                        <li>Force model to learn reconstruction from partial observations</li>
                        <li>Technique: Randomly mask 10-20% of non-stockout values</li>
                        <li>Purpose: Teach model to predict missing values using surrounding context</li>
                    </ul>
                    
                    <h6>4️⃣ Training Loop</h6>
                    <p><strong>Iterative optimization with validation monitoring:</strong></p>
                    <ul>
                        <li><strong>Training Phase:</strong>
                            <ul>
                                <li>Forward pass: TimesNet predicts masked values</li>
                                <li>Loss: MSE between predictions and ground truth (only on masked positions)</li>
                                <li>Backpropagation: Update model weights</li>
                            </ul>
                        </li>
                        <li><strong>Validation Phase:</strong>
                            <ul>
                                <li>Evaluate reconstruction error on held-out validation set</li>
                                <li>Track metrics: MAE, RMSE, Decoupling Score</li>
                            </ul>
                        </li>
                        <li><strong>Checkpointing:</strong> Save <code>best_checkpoint.pth</code> based on lowest validation loss</li>
                    </ul>
                    
                    <h6>5️⃣ Inference: Generate imputed_data.csv</h6>
                    <p>Apply best checkpoint to recover latent demand:</p>
                    <ul>
                        <li>Load <code>best_checkpoint.pth</code> (trained TimesNet model)</li>
                        <li>Input: original_data.csv with stockout periods marked</li>
                        <li>Output: <strong>imputed_data.csv</strong> with all missing values filled</li>
                        <li>Quality: Decoupling Score -0.0264 (close to 0 = good demand-inventory separation)</li>
                    </ul>
                    
                    <div style="background: #e3f2fd; padding: 1rem; border-radius: 6px; margin: 1rem 0; border-left: 4px solid #2196f3;">
                        <p><strong>📌 Stage 1 Output:</strong> <code>imputed_data.csv</code> serves as the clean, complete dataset for Stage 2 forecasting.</p>
                    </div>
                    
                    <hr style="margin: 2rem 0; border: none; border-top: 2px dashed var(--text-secondary);">
                    
                    <h4>Stage 2: Demand Forecasting with DLinear</h4>
                    
                    <img src="/images/project-3/demand-forecasting.png" alt="Demand Forecasting Pipeline" style="width: 100%; max-width: 800px; margin: 1.5rem auto; display: block; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);">
                    
                    <div style="background: var(--bg-tertiary); padding: 1rem; border-radius: 6px; margin: 1rem 0;">
                        <p><strong>Pipeline Flow:</strong> imputed_data.csv → Preprocess → Dataset Split → Training & Validation → Test (WAPE) → Inference → forecast_data</p>
                    </div>
                    
                    <h5>🎯 Objective</h5>
                    <p>Forecast <strong>future demand</strong> (7 days ahead) based on:</p>
                    <ul>
                        <li><strong>Input:</strong> imputed_data.csv (recovered latent demand from Stage 1)</li>
                        <li><strong>Model:</strong> DLinear with trend-seasonal decomposition</li>
                        <li><strong>Output:</strong> Hourly demand predictions for next 7 days (112 timesteps)</li>
                    </ul>
                    
                    <h5>🔁 Detailed Pipeline</h5>
                    
                    <h6>1️⃣ Preprocess: Sequence-to-Sequence Formatting</h6>
                    <p>Transform <code>imputed_data.csv</code> into seq2seq samples:</p>
                    <ul>
                        <li><strong>x (Encoder Input):</strong> <code>(480, 11)</code>
                            <ul>
                                <li>480 timesteps = 30 days × 16 hours (historical window)</li>
                                <li>11 features = 1 target (sales) + 10 covariates (discount, weather, calendar, etc.)</li>
                            </ul>
                        </li>
                        <li><strong>x_dec (Decoder Input):</strong> <code>(112, 10)</code>
                            <ul>
                                <li>112 timesteps = 7 days × 16 hours (forecast horizon)</li>
                                <li>10 features = covariates only (no target, as we're predicting it)</li>
                            </ul>
                        </li>
                        <li><strong>y (Target):</strong> <code>(112, 1)</code>
                            <ul>
                                <li>Ground truth sales for next 7 days</li>
                                <li>Used for training loss calculation</li>
                            </ul>
                        </li>
                    </ul>
                    <p><strong>📌 Seq2Seq Forecasting:</strong> Model uses 480 historical steps to predict 112 future steps.</p>
                    
                    <h6>2️⃣ Dataset Split</h6>
                    <p>Temporal train/validation/test split:</p>
                    <ul>
                        <li><strong>train_dataset:</strong> First 80% of sequences (chronological order)</li>
                        <li><strong>val_dataset:</strong> Next 10% for hyperparameter tuning</li>
                        <li><strong>test_dataset:</strong> Last 10% for final evaluation (held-out)</li>
                        <li><strong>Rationale:</strong> Temporal ordering preserved to avoid data leakage from future to past</li>
                    </ul>
                    
                    <h6>3️⃣ Training & Validation</h6>
                    <p><strong>Optimize DLinear model with early stopping:</strong></p>
                    <ul>
                        <li><strong>Training Loop:</strong>
                            <ul>
                                <li>Forward: DLinear decomposes trend + seasonal, predicts next 112 steps</li>
                                <li>Loss: MSE between predictions and ground truth <code>y</code></li>
                                <li>Optimizer: AdamW with learning rate 0.001</li>
                            </ul>
                        </li>
                        <li><strong>Validation:</strong>
                            <ul>
                                <li>Evaluate forecast error on validation set every epoch</li>
                                <li>Early stopping if validation loss doesn't improve for 5 epochs</li>
                            </ul>
                        </li>
                        <li><strong>Checkpointing:</strong> Save <code>best_checkpoint.pth</code> with lowest validation MSE</li>
                    </ul>
                    
                    <h6>4️⃣ Test: WAPE Metric</h6>
                    <p>Final evaluation on held-out test set:</p>
                    <ul>
                        <li><strong>Metric:</strong> WAPE (Weighted Absolute Percentage Error)</li>
                        <li><strong>Formula:</strong> WAPE = Σ|y_pred - y_true| / Σ|y_true| × 100%</li>
                        <li><strong>Why WAPE:</strong> 
                            <ul>
                                <li>Robust to zero/low sales periods (common in retail)</li>
                                <li>Weighted by demand volume (high-sales products matter more)</li>
                                <li>Industry standard for retail forecasting evaluation</li>
                            </ul>
                        </li>
                        <li><strong>Our Result:</strong> WAPE = <strong>31.94%</strong> (DLinear on imputed data)</li>
                    </ul>
                    
                    <h6>5️⃣ Inference: Production Forecasting</h6>
                    <p>Separate pipeline for real-world deployment:</p>
                    <ul>
                        <li><strong>Filter Requirements:</strong>
                            <ul>
                                <li>Input: User-specified product, store, date range</li>
                                <li>Process: Query imputed_data.csv for matching time series</li>
                            </ul>
                        </li>
                        <li><strong>Filtered Data:</strong> Extract relevant 480-step history</li>
                        <li><strong>Inference:</strong> Load best checkpoint → predict 112 future steps</li>
                        <li><strong>Output:</strong> <code>forecast_data</code> with hourly predictions</li>
                        <li><strong>Advantage:</strong> 
                            <ul>
                                <li>Forecast specific product/store combinations without retraining</li>
                                <li>Real-time inference (~0.5s per series)</li>
                            </ul>
                        </li>
                    </ul>
                    
                    <div style="background: #e3f2fd; padding: 1rem; border-radius: 6px; margin: 1rem 0; border-left: 4px solid #2196f3;">
                        <p><strong>📌 Stage 2 Output:</strong> <code>forecast_data</code> provides 7-day ahead hourly demand predictions for inventory optimization.</p>
                    </div>
                    
                    <hr style="margin: 2rem 0; border: none; border-top: 2px dashed var(--text-secondary);">
                    
                    <h3>Model Configurations</h3>
                    <table class="config-table">
                        <thead>
                            <tr>
                                <th>Component</th>
                                <th>Parameter</th>
                                <th>Value</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td><strong>TimesNet (Stage 1)</strong></td>
                                <td>Sequence Length</td>
                                <td>1440 timesteps (90 days × 16 hours)</td>
                            </tr>
                            <tr>
                                <td></td>
                                <td>Features</td>
                                <td>6 (sales, discount, weather)</td>
                            </tr>
                            <tr>
                                <td></td>
                                <td>Parameters</td>
                                <td>~1M (FFT-based multi-period blocks)</td>
                            </tr>
                            <tr>
                                <td></td>
                                <td>Batch Size</td>
                                <td>256</td>
                            </tr>
                            <tr>
                                <td><strong>DLinear (Stage 2)</strong></td>
                                <td>Input Length (seq_len)</td>
                                <td>480 timesteps (30 days × 16 hours)</td>
                            </tr>
                            <tr>
                                <td></td>
                                <td>Output Length (pred_len)</td>
                                <td>112 timesteps (7 days × 16 hours)</td>
                            </tr>
                            <tr>
                                <td></td>
                                <td>Encoder Features (enc_in)</td>
                                <td>11 (1 target + 10 covariates)</td>
                            </tr>
                            <tr>
                                <td></td>
                                <td>Decoder Features (dec_in)</td>
                                <td>10 (covariates only, no target)</td>
                            </tr>
                            <tr>
                                <td></td>
                                <td>Decomposition Kernel</td>
                                <td>25 (moving average window for smoothing)</td>
                            </tr>
                            <tr>
                                <td></td>
                                <td>Individual Mode</td>
                                <td>True (separate linear layer per feature)</td>
                            </tr>
                            <tr>
                                <td></td>
                                <td>Batch Size</td>
                                <td>1024</td>
                            </tr>
                        </tbody>
                    </table>
                    
                    <h3>Training Configuration</h3>
                    <ul>
                        <li><strong>Optimizer:</strong> AdamW with weight decay 1e-4, learning rate 0.001</li>
                        <li><strong>Loss Function:</strong> MSE (Mean Squared Error) for both stages</li>
                        <li><strong>Scheduler:</strong> ReduceLROnPlateau (factor=0.5, patience=3 epochs)</li>
                        <li><strong>Early Stopping:</strong> Patience of 5 epochs based on validation loss</li>
                        <li><strong>Max Epochs:</strong> 20 (typically converges in 10-15 epochs)</li>
                        <li><strong>Hardware:</strong> NVIDIA RTX 4090 24GB, training time ~2 hours per stage</li>
                    </ul>
                    
                    <h3>Why This Two-Stage Approach Works</h3>
                    <ul>
                        <li><strong>Separation of Concerns:</strong> 
                            <ul>
                                <li>Stage 1 (TimesNet) specializes in pattern reconstruction and missing value imputation</li>
                                <li>Stage 2 (DLinear) focuses solely on forecasting with clean data</li>
                            </ul>
                        </li>
                        <li><strong>Model-Task Alignment:</strong>
                            <ul>
                                <li>TimesNet's FFT multi-period analysis excels at capturing demand patterns for imputation</li>
                                <li>DLinear's trend-seasonal decomposition is optimal for linear forecasting tasks</li>
                            </ul>
                        </li>
                        <li><strong>Performance Gains:</strong>
                            <ul>
                                <li>Imputation improves forecast WAPE by ~15% vs. forecasting on raw data with stockouts</li>
                                <li>Decoupling Score -0.0264 indicates successful demand-inventory separation</li>
                            </ul>
                        </li>
                    </ul>
                    
                    <h3>Alternative Models Benchmarked</h3>
                    <p>We compared against multiple baselines:</p>
                    <ul>
                        <li><strong>Statistical:</strong> ARIMA (univariate baseline)</li>
                        <li><strong>Deep Learning:</strong> LSTM, Transformer-based models</li>
                        <li><strong>Linear Models:</strong> DLinear, NLinear (ablation study)</li>
                        <li><strong>Imputation:</strong> Forward-fill, mean imputation (naive baselines for Stage 1)</li>
                    </ul>
                    
                    <div class="key-insight">
                        <h4>💡 Key Insight</h4>
                        <p>Two-stage pipeline (imputation → forecasting) outperforms end-to-end approaches by 15% WAPE. Explicitly modeling demand censoring as a separate task allows each model to specialize, rather than forcing a single model to handle both data quality and prediction simultaneously.</p>
                    </div>
                `
            },
            
            experiments: {
                title: "Experiments & Results",
                icon: "fa-chart-bar",
                content: `
                    <h3>Latent Demand Recovery Results</h3>
                    <p>Recovering hidden demand during stockout periods:</p>
                    
                    <table class="experiment-table">
                        <thead>
                            <tr>
                                <th>Model</th>
                                <th>MAE</th>
                                <th>RMSE</th>
                                <th>Decoupling Score</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>DLinear</td>
                                <td>0.0571</td>
                                <td>0.1204</td>
                                <td>-0.1063</td>
                            </tr>
                            <tr class="best-result">
                                <td>TimesNet (Our Implementation)</td>
                                <td class="best-result">0.0623</td>
                                <td class="best-result">0.0969</td>
                                <td class="best-result">-0.0264</td>
                            </tr>
                            <tr>
                                <td>Baseline (Paper)</td>
                                <td>-</td>
                                <td>-</td>
                                <td>0.07</td>
                            </tr>
                        </tbody>
                    </table>
                    <p><em>Note: Decoupling Score closer to 0 indicates better separation between demand and inventory. Our TimesNet achieves -0.0264, outperforming the paper baseline of 0.07.</em></p>
    
                    <h3>Demand Forecasting Performance (DLinear)</h3>
                    <p>7-day ahead forecast after latent demand recovery:</p>
                    
                    <table class="experiment-table">
                        <thead>
                            <tr>
                                <th>Configuration</th>
                                <th>WAPE (%)</th>
                                <th>Improvement</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>Original Data (No Decoder)</td>
                                <td>37.93%</td>
                                <td>Baseline</td>
                            </tr>
                            <tr>
                                <td>Original Data (With Decoder)</td>
                                <td>37.55%</td>
                                <td>+1.0%</td>
                            </tr>
                            <tr>
                                <td>Imputed Data (No Decoder)</td>
                                <td>32.62%</td>
                                <td>+13.9%</td>
                            </tr>
                            <tr class="best-result">
                                <td>Imputed Data + Decoder</td>
                                <td class="best-result">31.94%</td>
                                <td class="best-result">+15.7%</td>
                            </tr>
                        </tbody>
                    </table>
                    
                    <div class="metrics-grid">
                        <div class="metric-card">
                            <span class="metric-value">31.94%</span>
                            <span class="metric-label">WAPE (Best)</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-value">-0.0264</span>
                            <span class="metric-label">Decoupling Score</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-value">15.7%</span>
                            <span class="metric-label">Improvement</span>
                        </div>
                        <div class="metric-card">
                            <span class="metric-value">50K</span>
                            <span class="metric-label">Time Series</span>
                        </div>
                    </div>
                    
                    <img src="/images/project-3/demand-forecasting.png" alt="Demand Forecasting Performance Comparison" style="width: 100%; max-width: 800px; margin: 1.5rem auto; display: block; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);">
                    
                    <h3>Key Findings</h3>
                    <ul>
                        <li><strong>Imputation Matters:</strong> Using latent demand recovery improved WAPE by 2.1% - filling missing values with ML beats forward fill</li>
                        <li><strong>Decoder Helps:</strong> Future covariates via decoder improved accuracy by 0.8%, worth the small overhead</li>
                        <li><strong>Speed vs Accuracy:</strong> DLinear matched TimesNet accuracy while being 12x faster to train</li>
                        <li><strong>Hourly Granularity:</strong> 16-hour daily granularity captured intraday patterns that daily aggregates miss</li>
                        <li><strong>Weather Features:</strong> Temperature and precipitation were surprisingly important (15% feature importance)</li>
                    </ul>
                    
                    <div class="key-insight">
                        <h4>Key Insight</h4>
                        <p>Latent demand recovery improved forecast accuracy by 15.7%. This validates the hypothesis that correcting demand censoring bias is more impactful than just selecting better forecasting models. The combination of TimesNet (recovery) + DLinear (forecasting) outperforms using raw historical data with any model.</p>
                    </div>
                `
            },
            
            deployment: {
                title: "Deployment & Integration",
                icon: "fa-rocket",
                content: `
                    <h3>System Architecture</h3>
                    <div class=\"deployment-info\">
                        <h4>Three-Tier Architecture</h4>
                        <p><strong>AI/ML Layer:</strong> PyTorch models with ONNX export for production inference</p>
                        <p><strong>Backend API:</strong> FastAPI server exposing REST endpoints</p>
                        <p><strong>Frontend Dashboard:</strong> React application for visualization and monitoring</p>
                    </div>
                    
                    <h3>Project Structure</h3>
                    <div class=\"code-block\">
                        <pre><code>Demand-Forecasting-ERP/
    ├── ai/
    │   ├── demand_forecasting/
    │   │   ├── exp/                    # Training experiments
    │   │   │   └── exp_dlinear.py     # DLinear training script
    │   │   ├── checkpoints/            # Saved models
    │   │   ├── main.py                # Training entry point
    │   │   ├── inference_dlinear.py   # Production inference
    │   │   └── test_wape.py           # Evaluation script
    │   ├── latent_demand_recovery/
    │   │   ├── exp/                    # Imputation experiments
    │   │   ├── checkpoints/            # Imputation models
    │   │   └── impute.py              # Inference script
    │   ├── inventory_optimization_module/
    │   │   └── main_demo.py           # Reorder point optimization
    │   ├── model/
    │   │   ├── dlinear.py             # DLinear implementation
    │   │   ├── timesnet.py            # TimesNet implementation
    │   │   └── baseline_models.py     # ARIMA, LSTM baselines
    │   └── data_utils/
    │       └── load_data.py           # Data preprocessing
    ├── backend/
    │   ├── app/
    │   │   ├── main.py                # FastAPI application
    │   │   ├── routes/                # API endpoints
    │   │   ├── services/              # Business logic
    │   │   └── models/                # SQLAlchemy ORM
    │   └── requirements.txt
    └── frontend/
        ├── src/
        │   ├── components/            # React components
        │   ├── pages/                 # Dashboard, Analytics
        │   └── services/              # API clients
        └── package.json</code></pre>
                    </div>
                    
                    <h3>Running the System</h3>
                    <div class=\"code-block\">
                        <pre><code># Train models
    cd ai
    uv sync
    source .venv/bin/activate
    
    # Train DLinear forecasting model
    bash demand_forecasting/train_all.sh
    
    # Train imputation model
    cd latent_demand_recovery/exp
    python dlinear.py
    
    # Start backend API
    cd backend
    python -m venv venv
    source venv/bin/activate
    pip install -r requirements.txt
    uvicorn app.main:app --reload --port 8000
    
    # Start frontend
    cd frontend
    npm install
    npm start</code></pre>
                    </div>
                    
                    <h3>API Endpoints</h3>
                    <ul>
                        <li><strong>POST /api/v1/forecasts/predict:</strong> Generate 7-day demand forecast for product</li>
                        <li><strong>POST /api/v1/optimize/supply:</strong> Calculate optimal reorder points and safety stock</li>
                        <li><strong>GET /api/v1/analytics/dashboard:</strong> Fetch aggregated metrics for dashboard</li>
                        <li><strong>GET /api/v1/analytics/accuracy:</strong> Model performance metrics over time</li>
                    </ul>
                    
                    <h3>Inventory Optimization Strategies</h3>
                    <p>Comparing AI-driven approach against traditional ERP baselines:</p>
                    <table class="config-table">
                        <thead>
                            <tr>
                                <th>Strategy</th>
                                <th>Method</th>
                                <th>Source</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>Rule-Based (Min/Max)</td>
                                <td>Static thresholds</td>
                                <td>Odoo/SAP baseline</td>
                            </tr>
                            <tr>
                                <td>Newsvendor Model</td>
                                <td>Probabilistic optimization</td>
                                <td>Classical OR baseline</td>
                            </tr>
                            <tr>
                                <td>AI-DDMRP (Ours)</td>
                                <td>Dynamic buffer + AI forecast</td>
                                <td>Proposed method</td>
                            </tr>
                        </tbody>
                    </table>
                    
                    <h3>Adaptive Retraining Process</h3>
                    <p>Three-strategy approach based on WAPE degradation:</p>
                    
                    <img src="/images/project-3/adaptive-inference-algorithm.png" alt="Adaptive Inference Algorithm" style="width: 100%; max-width: 800px; margin: 1.5rem auto; display: block; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);">
                    
                    <ul>
                        <li><strong>Strategy A (Full Retraining):</strong> Retrain both TimesNet (imputation) + DLinear (forecasting) - highest cost, best accuracy</li>
                        <li><strong>Strategy B (Partial):</strong> Reuse imputation model, only retrain DLinear - balanced approach</li>
                        <li><strong>Strategy C (Direct Inference):</strong> Use existing models - fastest, lowest cost, limited accuracy</li>
                    </ul>
                    <p>System monitors WAPE on new data weekly and automatically selects the appropriate strategy.</p>
                    
                    <h3>Simulation Engine</h3>
                    <p>Monte Carlo simulation comparing three inventory strategies:</p>
                    <ul>
                        <li><strong>Rule-Based:</strong> Fixed reorder point (ROP = d × L + SS) - static thresholds like Odoo/SAP</li>
                        <li><strong>Newsvendor:</strong> Probabilistic optimization based on normal distribution - classical OR approach</li>
                        <li><strong>AI-DDMRP:</strong> Dynamic buffer zones updated with AI forecasts - our proposed method</li>
                    </ul>
                    <p>Simulation includes: lead time, FIFO spoilage, holding cost, stockout cost, order cost</p>
                    
                    <h3>Technical Achievements</h3>
                    <ul>
                        <li><strong>Latent Demand Recovery:</strong> Decoupling Score -0.0264 (beats paper baseline 0.07 by 131%)</li>
                        <li><strong>Forecast Accuracy:</strong> WAPE 31.94% (15.7% improvement over raw censored data)</li>
                        <li><strong>Model Efficiency:</strong> TimesNet with ~1M parameters balanced accuracy and training cost</li>
                        <li><strong>Ablation Insights:</strong> Decoder improves WAPE by 2.1% when combined with imputed data</li>
                        <li><strong>Full-Stack System:</strong> AI models + FastAPI backend + React dashboard + simulation engine</li>
                    </ul>
                    
                    <div class="key-insight">
                        <h4>Key Insight</h4>
                        <p>The two-stage pipeline (TimesNet recovery → DLinear forecasting) proved essential. Attempting to forecast directly on censored data, even with advanced models, systematically underestimates true demand. Correcting the data first beats optimizing the model second.</p>
                    </div>
                    
                    <p style="margin-top: 1.5rem;"><strong>Tech Stack:</strong></p>
                    <ul>
                        <li><strong>AI/ML:</strong> PyTorch, TimesNet, DLinear, pandas, scikit-learn</li>
                        <li><strong>Backend:</strong> FastAPI (Python 3.11), uvicorn</li>
                        <li><strong>Frontend:</strong> React, Chart.js, Material-UI</li>
                        <li><strong>Tools:</strong> uv (package manager), Git</li>
                    </ul>
    
                    <h3>Resources</h3>
                    <a href="https://github.com/LeHung1705/Demand-Forecasting-and-Supply-Optimization-for-ERP-system.git" target="_blank" class="github-link">
                        <i class="fab fa-github"></i>
                        View Full Source Code
                    </a>
                `
            }
        }
    };
    console.log('File loaded at: ' + new Date().toISOString());
    

    Comments

    More Rules

    View all

    Textbased Predictor Perplexity Rules

    H
    Havcker243

    Intelligent Team Building Recommendation System Perplexity Rules

    R
    royswastik

    Pita Perplexity Rules

    S
    SaratBobbili

    Eskrev Perplexity Rules

    R
    rfmss

    Founder Control Room Perplexity Rules

    J
    jussray

    N8nWorkflows Perplexity Rules

    S
    Samarth-ITM

    Stay up to date

    Get the latest Perplexity prompts, rules, and resources delivered to your inbox weekly.

    Neura Market LogoNeura Market

    Discover the best AI prompts, plugins, and resources for Perplexity and more.

    Content Types

    • Rules
    • Prompts
    • MCPs
    • Agents
    • Guides

    Platforms

    • ChatGPT Directory
    • Claude Directory
    • Gemini Directory
    • Cursor Directory
    • Grok Directory
    • Perplexity Directory
    • DeepSeek Directory
    • CoPilot Directory
    • Stable Diffusion Directory
    • Midjourney Directory
    • All Directories

    Resources

    • Blog
    • Documentation
    • Help Center
    • Marketplace

    Legal

    • Privacy Policy
    • Terms of Service

    © 2026 Neura Market. All rights reserved.

    |

    Not affiliated with any AI platform vendors.

    Neura Market

    Custom AI Systems & Services

    Our team of experienced AI builders will help build custom AI systems, workflows, and solutions for your business.

    Request custom work

    Ready-made automations for this

    Workflows from the Neura Market marketplace related to this Perplexity resource

    • GitHub Automation Hub: Complete API Controls for AI Agentsn8n · $24.99 · Related topic
    • Automated Lead Generation & Contact Enrichment with Hunter.io and Perplexity AIn8n · $24.99 · Related topic
    • Automate SEO-Optimized Blog Creation with GPT-4, Perplexity AI & Multi-Language Supportn8n · $24.99 · Related topic
    • Automate SEO Blog Content Creation with GPT-4, Perplexity AI, and WordPressn8n · $24.99 · Related topic
    Browse all workflows