🏭 Enterprise

Enterprise β€” 3 Documents

AI Deployment, Fine-Tuning, Infrastructure

3
Documents
4,493
Total Lines

πŸ“„ Enterprise AI Deployment: Production Infrastructure and Operations β€” 1012 lines

AgentAttentionBenchmarkCLIPDPODeploymentDifferential PrivacyEnsembleEvaluationFederated Learning

1. Introduction to Enterprise AI

Enterprise AI deployment encompasses the full lifecycle of taking machine learning models from research and development into production environments where they deliver business value at scale. Unlike experimental or proof-of-concept deployments, enterprise AI requires:

  • Reliability: 99.9%+ uptime with automated failover
  • Scalability: Handle thousands to millions of requests per second
  • Security: Data isolation, encryption, access control, audit trails
  • Compliance: Meet regulatory requirements (GDPR, HIPAA, SOC2, EU AI Act)
  • Cost Efficiency: Optimized inference with caching, routing, and tiered models
  • Observability: Full traceability of model inputs, outputs, drift, and performance
  • Governance: Approval workflows, model registries, versioning, rollback capability

The enterprise AI stack typically has six layers:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚            Application Layer                  β”‚
β”‚  Chatbots / Copilots / Automation / Search    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚           Orchestration Layer                 β”‚
β”‚  Prompt Pipelines / Agent Frameworks / RAG    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚           Model Serving Layer                 β”‚
β”‚  vLLM / TGI / Triton / Ollama / Bedrock       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚         Infrastructure Layer                  β”‚
β”‚  Kubernetes / Docker / Serverless / Edge      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚         Data & Feature Layer                  β”‚
β”‚  Vector DB / Feature Store / Data Lake        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚         Governance & Observability            β”‚
β”‚  Monitoring / Logging / Audit / Compliance    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

1.1 Key Enterprise Considerations

Latency Requirements:
- Real-time (chat): <500ms p95
- Near-real-time (assistant): <3s p95
- Batch: minutes to hours

Throughput:
- Small deployments: 100-1,000 RPM (requests per minute)
- Medium deployments: 1,000-10,000 RPM
- Large deployments: 10,000-100,000+ RPM

Reliability Targets:
- Development: 99% uptime (3.65 days/year downtime)
- Staging: 99.9% uptime (8.76 hours/year downtime)
- Production critical: 99.99% uptime (52.56 minutes/year downtime)
- Mission-critical: 99.999% uptime (5.26 minutes/year downtime)


2. Deployment Architectures

2.1 Cloud Deployment

The most common enterprise pattern. Models run on cloud infrastructure with auto-scaling.

Pros: Elastic scaling, pay-per-use, managed services, global availability
Cons: Data egress costs, latency for on-premise integration, vendor lock-in

Cloud Providers:
- AWS: Bedrock (managed), SageMaker (custom), EC2 (DIY)
- Azure: OpenAI Service, AI Studio, ML Studio
- GCP: Vertex AI (managed), GKE (custom), Cloud Run (serverless)

2.2 On-Premises Deployment

Models run entirely within the organization's data center.

Pros: Complete data sovereignty, low latency for internal services, predictable cost
Cons: Fixed capacity, hardware procurement, maintenance overhead, GPU scarcity

Typical Hardware:
- Inference: NVIDIA A100/H100/H200/B200, AMD MI300X, Intel Gaudi
- Small: 1-4 GPUs per model (7B-70B params)
- Medium: 8-16 GPUs per model (70B-180B params)
- Large: 32-128 GPUs for high-throughput serving
- Training clusters: 256-16,000+ GPUs

2.3 Edge Deployment

Models run on user devices or edge servers.

Pros: Zero latency, offline capability, privacy by design
Cons: Hardware constraints, limited model size, update distribution

Common Edge Targets:
- Mobile: Apple Neural Engine, Qualcomm Hexagon, Samsung NPU
- Laptop: Apple M-series, Intel NPU, NVIDIA RTX (local)
- IoT: Raspberry Pi, Jetson Orin/Nano, Intel Movidius
- Browser: WebGPU, ONNX Runtime Web, Transformers.js

Model Sizes for Edge:
- Quantized 1-3B models (Qwen2.5-1.5B, Phi-3-mini, Gemma-2B)
- Multimodal: MobileCLIP, EfficientViT-SAM
- Speech: Whisper tiny/small, Silero VAD
- 4-bit quantized 7B for high-end devices

2.4 Hybrid Deployment

Combines cloud, on-prem, and edge based on workload requirements.

Strategy:
- Simple queries β†’ Edge (fast, free, private)
- Standard queries β†’ On-prem (low latency, controlled)
- Complex queries β†’ Cloud (unlimited compute, latest models)
- Fine-tuning/Training β†’ Cloud/on-prem GPU clusters

              Edge                         On-Premise                   Cloud
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚ Small Models │─────────────▢│ Medium Models│──────────▢│ Large Models β”‚
        β”‚  (<3B, 4bit) β”‚  escalation  β”‚ (7B-70B)     β”‚ escalationβ”‚ (70B-400B+)  β”‚
        β”‚              β”‚              β”‚              β”‚           β”‚              β”‚
        β”‚  ~1ms latencyβ”‚              β”‚  ~50ms lat.  β”‚           β”‚  ~200ms lat. β”‚
        β”‚  ~$0 cost    β”‚              β”‚  ~fixed cost β”‚           β”‚  ~per-token  β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

3. MLOps Pipelines

3.1 Full MLOps Lifecycle

Data Collection β†’ Data Validation β†’ Feature Engineering β†’ Model Training
       ↓                                                         ↓
  Model Registry ← Model Evaluation ← Model Validation ← Hyperparameter Tuning
       ↓
  Model Deployment β†’ Prediction Serving β†’ Monitoring β†’ Feedback Loop
                                                              ↓
                                                   Retraining Trigger

3.2 Key MLOps Components

Feature Store (Feast, Tecton, SageMaker Feature Store):
- Centralized feature computation and storage
- Online (low-latency) and offline (batch) serving
- Feature sharing across teams
- Point-in-time correct feature retrieval for training

Model Registry (MLflow Model Registry, Hugging Face Hub, S3/GCS):
- Versioned model artifacts with metadata
- Model lineage tracking (data β†’ training β†’ deployment)
- Stage transitions (staging β†’ production β†’ archived)
- Model signatures and input/output schemas

Pipeline Orchestration (Kubeflow, Airflow, Prefect, Dagster):
- DAG-based pipeline definition
- Retry and error handling
- Artifact passing between steps
- Scheduled and event-driven execution

Experiment Tracking (MLflow, Weights & Biases, Neptune, Comet):
- Hyperparameter logging
- Metrics visualization
- Artifact storage (model weights, plots, configs)
- Run comparison and search

3.3 CI/CD for ML

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚    Source Control    β”‚
                    β”‚  (code + configs)   β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚ push/PR
                               β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚    CI Pipeline       β”‚
                    β”‚  - Lint code         β”‚
                    β”‚  - Unit tests        β”‚
                    β”‚  - Integration tests β”‚
                    β”‚  - Model validation  β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   Model Training     β”‚
                    β”‚  (triggered by CI)   β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   Model Evaluation   β”‚
                    β”‚  - Benchmark scores  β”‚
                    β”‚  - Offline metrics   β”‚
                    β”‚  - Bias detection    β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚ pass?
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚  CD Pipeline         β”‚
                    β”‚  - Canary deploy     β”‚
                    β”‚  - Shadow testing    β”‚
                    β”‚  - Blue-green deploy β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   Monitoring         β”‚
                    β”‚  - Performance       β”‚
                    β”‚  - Drift detection   β”‚
                    β”‚  - Alerting          β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

4. Model Serving Infrastructure

4.1 Model Serving Frameworks

vLLM:
- High-throughput LLM serving with PagedAttention
- Continuous batching, prefix caching, tensor parallelism
- OpenAI-compatible API
- Supports: LLaMA, Mistral, Qwen, DeepSeek, Falcon, Gemma, GPT-NeoX
- Best for: high-throughput, production LLM serving

Text Generation Inference (TGI) by Hugging Face:
- Production-focused LLM serving
- Tensor parallelism, continuous batching, quantization (bitsandbytes, GPTQ, AWQ)
- Message streaming via Server-Sent Events
- Best for: Hugging Face ecosystem integration

NVIDIA Triton Inference Server:
- Multi-framework support (TensorRT, ONNX, PyTorch, TensorFlow)
- Concurrent model execution, dynamic batching
- Ensemble and BLS (Business Logic Scripting)
- GPU optimization with TensorRT
- Best for: heterogeneous model serving at scale

Ollama:
- Simplified local model serving
- Model management (pull, run, stop)
- OpenAI-compatible API
- GPU acceleration (CUDA, Metal, Vulkan)
- Best for: development, testing, personal use

TensorRT-LLM:
- NVIDIA's optimized LLM serving
- In-flight batching, paged attention, multi-GPU
- FP8, INT4, INT8 quantization
- Best for: maximum GPU utilization on NVIDIA hardware

Comparison Table:

Framework Throughput Latency GPU Util Ease Features
vLLM β˜…β˜…β˜…β˜…β˜… β˜…β˜…β˜…β˜… β˜…β˜…β˜…β˜…β˜… β˜…β˜…β˜…β˜… PagedAttention, prefix caching
TGI β˜…β˜…β˜…β˜… β˜…β˜…β˜…β˜… β˜…β˜…β˜…β˜… β˜…β˜…β˜…β˜… HuggingFace native
Triton β˜…β˜…β˜…β˜…β˜… β˜…β˜…β˜…β˜…β˜… β˜…β˜…β˜…β˜…β˜… β˜…β˜…β˜… Multi-framework, ensemble
Ollama β˜…β˜…β˜… β˜…β˜…β˜… β˜…β˜…β˜… β˜…β˜…β˜…β˜…β˜… Simplest setup
TensorRT-LLM β˜…β˜…β˜…β˜…β˜… β˜…β˜…β˜…β˜…β˜… β˜…β˜…β˜…β˜…β˜… β˜…β˜… NVIDIA-only, complex

4.2 Containerization and Orchestration

Docker:
- Standard container format for ML models
- Multi-stage builds for size optimization
- Health checks, resource limits, environment configuration

Kubernetes (K8s):
- Standard orchestration for ML workloads
- Deployments for stateless serving
- StatefulSets for stateful services (vector DBs)
- Horizontal Pod Autoscaler (HPA) for scaling
- Custom metrics (requests per second, queue depth, GPU utilization)
- Node pools for GPU vs CPU workloads
- Affinity/anti-affinity for GPU pod placement
- Service mesh (Istio, Linkerd) for traffic management

Example Kubernetes Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: llm-server
spec:
  replicas: 4
  selector:
    matchLabels:
      app: llm-server
  template:
    metadata:
      labels:
        app: llm-server
    spec:
      containers:
      - name: vllm
        image: vllm/vllm-openai:latest
        args: ["--model", "mistralai/Mistral-7B-Instruct-v0.3",
               "--tensor-parallel-size", "1",
               "--max-model-len", "8192",
               "--gpu-memory-utilization", "0.90"]
        resources:
          limits:
            nvidia.com/gpu: 1
            memory: "32Gi"
            cpu: "8"
      nodeSelector:
        cloud.google.com/gke-accelerator: nvidia-l4

4.3 Serverless ML

AWS SageMaker Serverless, GCP Cloud Run, Azure Container Apps:
- Scale to zero when not in use
- Pay-per-invocation (no idle cost)
- Cold start latency (5-30 seconds)
- Best for: bursty, low-volume, or spiky workloads

Emerging: serverless GPU (Modal, RunPod, Banana, Replicate):
- GPU-backed serverless inference
- Automatic scaling, no infrastructure management
- Pay per second of GPU usage
- Best for: prototyping, demos, low-volume production


5. Monitoring and Observability

5.1 Metrics Categories

Infrastructure Metrics:
- GPU utilization, memory, temperature
- Request latency (avg, p50, p95, p99, p999)
- Request throughput (RPS / TPS / RPM)
- Error rate (4xx, 5xx, timeout)
- Queue depth and wait time

Model Performance Metrics:
- First-token latency (TTFT β€” Time to First Token)
- Inter-token latency (ITL)
- Tokens per second (throughput)
- Context window utilization
- Token generation distribution

Quality Metrics:
- Response relevance (human eval, LLM-as-judge)
- Factual accuracy (grounding checks)
- Toxicity / safety score
- Response length distribution
- User satisfaction (thumbs up/down, ratings)

Drift Metrics:
- Input distribution drift (embedding distance over time)
- Output distribution drift
- Performance drift (quality metrics over time)
- Data drift detection (statistical tests: KS, PSI, MMD)

5.2 Monitoring Tools

Infrastructure:
- Prometheus + Grafana (standard open-source stack)
- Datadog (SaaS, full-stack monitoring)
- New Relic (APM-focused)
- Grafana Cloud / Grafana Loki (logs + metrics)

ML-Specific:
- LangSmith (LLM observability, traces, evaluations)
- Weights & Biases Prompts (prompt monitoring)
- Arize AI (ML observability, drift detection)
- LangFuse (open-source LLM monitoring)
- Helicone (LLM proxy with logging)
- MLflow (model monitoring)

Alerting:
- PagerDuty / OpsGenie for on-call
- Slack / Teams notifications for warnings
- Email for daily/weekly reports

5.3 Observability Tracing

Distributed tracing for LLM applications provides end-to-end visibility:

User Request
  └─ API Gateway
       └─ Orchestrator
            β”œβ”€ Prompt Template (5ms)
            β”œβ”€ RAG Retrieval (150ms)
            β”‚    β”œβ”€ Query Embedding (20ms)
            β”‚    β”œβ”€ Vector DB Search (80ms)
            β”‚    └─ Re-ranking (50ms)
            β”œβ”€ Context Assembly (10ms)
            β”œβ”€ LLM Inference (800ms)
            β”‚    β”œβ”€ Time-to-First-Token (400ms)
            β”‚    └─ Token Generation (400ms)
            └─ Post-processing (15ms)
Total: ~980ms

6. A/B Testing for LLMs

6.1 Testing Strategies

Shadow Testing:
- New model runs in parallel with production model
- Outputs compared but only production served to users
- Safe: no user impact, collect comparison data
- Duration: 1-7 days

Canary Deployment:
- Gradually shift traffic to new model (5% β†’ 25% β†’ 50% β†’ 100%)
- Monitor for regressions at each step
- Auto-rollback if error rate or quality drops
- Duration: hours to days

Champion/Challenger:
- Old model (champion) vs new model (challenger)
- Controlled experiment with statistical significance testing
- Measure: user satisfaction, task completion, latency, cost
- Requires sufficient traffic for statistical power

Interleaved A/B:
- Each user sees responses from both models (side-by-side or interleaved)
- Blind comparison (user doesn't know which is which)
- Faster convergence, requires less traffic
- More complex to implement

6.2 Evaluation Metrics

Metric What It Measures How to Measure
Win Rate User preference Blind A/B comparison
Task Completion Did user get answer? Button click, follow-up rate
User Satisfaction How did user feel? Thumbs up/down, rating
Latency Speed p50/p95/p99 response time
Cost Economics Tokens per request, model cost
Safety Score Content safety Automated guardrails, human review
Grounding Factual accuracy LLM-as-judge, human fact-check

7. Cost Optimization

7.1 Cost Components

Total Cost = Compute + API + Storage + Network + Human
  - Compute: GPU instances, CPU instances, serverless
  - API: Third-party model APIs (OpenAI, Anthropic, etc.)
  - Storage: Vector databases, model storage, embeddings cache
  - Network: Data transfer, cross-region, egress
  - Human: Labeling, monitoring, prompt engineering

7.2 Optimization Strategies

Prompt Optimization:
- Shorter prompts reduce token costs
- Fewer few-shot examples (use dynamic retrieval instead)
- System prompt compression
- Prompt caching (Anthropic's prompt caching, Gemini context caching)

Output Length Control:
- Use max_tokens constraints
- Set stop sequences early
- Use structured output formatting
- Compress or truncate when possible

Model Tiering:

Query Type          β†’ Model to Use                  β†’ Cost/1M tokens
──────────────────────────────────────────────────────────────
Simple Q&A          β†’ GPT-4o-mini / Mistral-7B      β†’ $0.15-0.60
Content extraction  β†’ Claude 3 Haiku / Gemini Flash β†’ $0.25-1.00
Code generation     β†’ Claude 3.5 Sonnet / GPT-4o    β†’ $3.00-10.00
Complex reasoning   β†’ Claude 4 Opus / DeepSeek-R1   β†’ $15.00-60.00
Research / analysis β†’ Full o3 / Gemini 2.5 Pro      β†’ $15.00-75.00

Semantic Cache:
- Cache results for semantically similar queries
- Reduce duplicate computation by 20-60%
- Memory cost of cache vs token cost savings
- Typical: Redis + embedding-based similarity search

Batching:
- Batch non-realtime requests for higher throughput
- vLLM server batching reduces per-request overhead
- Combine multiple prompts into single inference call

Provider Cost Comparison (as of 2026):

Provider Model Input (per 1M tokens) Output (per 1M tokens)
OpenAI GPT-4o $2.50 $10.00
OpenAI GPT-4o-mini $0.15 $0.60
Anthropic Claude 4 Sonnet $3.00 $15.00
Anthropic Claude 3 Haiku $0.25 $1.25
Google Gemini 2.0 Flash $0.10 $0.40
Google Gemini 2.5 Pro $1.25 $10.00
DeepSeek V3 $0.27 $1.10
Self-hosted LLaMA 3 70B (vLLM) ~$0.12 ~$0.48
Self-hosted Qwen2.5-7B (Ollama) ~$0.015 ~$0.06

8. Compliance and Governance

8.1 Regulatory Landscape

EU AI Act (2025+):
- Risk categories: minimal, limited, high, unacceptable
- High-risk AI systems require: risk assessment, data governance, transparency, human oversight, accuracy/robustness
- GPAI (General Purpose AI) models: transparency, copyright, systemic risk assessment
- Fines: up to 7% of global annual turnover or €35M

US Executive Orders on AI (2023-2026):
- Safety testing of powerful AI systems (red-teaming results)
- Watermarking (C2PA content provenance standards)
- Privacy-preserving techniques research
- Equity and civil rights guidance

China AI Regulations (2023-2026):
- Algorithm registration requirements
- Content safety reviews for generative AI
- Data localization requirements
- Synthetic data labeling mandates

Other Jurisdictions:
- UK: AI Safety Institute, pro-innovation framework
- Canada: AIDA (Artificial Intelligence and Data Act)
- Japan: AI Guidelines (soft law approach)
- Singapore: Model AI Governance Framework
- Brazil: Bill 2338/2023 (LGPDP + AI specific provisions)
- India: NITI Aayog AI principles

8.2 Governance Framework

Model Governance Lifecycle:

1. Model Intake
   - Business case approval
   - Risk assessment
   - Regulatory mapping

2. Model Development
   - Data provenance documentation
   - Fairness / bias evaluation
   - Explainability analysis
   - Documentation (model cards)

3. Model Validation
   - Independent validation team
   - Performance benchmarking
   - Stress testing / edge cases
   - Compliance review

4. Model Approval
   - Governance committee review
   - Approval for deployment
   - Conditions / limitations documented

5. Model Deployment
   - Staged rollout
   - Monitoring thresholds set
   - Human-in-the-loop requirements

6. Model Monitoring
   - Ongoing performance tracking
   - Drift detection
   - Periodic re-validation
   - Incident response plan

7. Model Retirement
   - Decommissioning plan
   - Data cleanup
   - Lessons learned

8.3 Model Documentation

Model Cards (Standardized by Hugging Face, now widely adopted):
- Model description
- Intended use and limitations
- Training data and methodology
- Evaluation results (segmented by group)
- Ethical considerations
- Caveats and recommendations

Datasheets for Datasets:
- Motivation (why was dataset created?)
- Composition (what fields, how much data?)
- Collection process (how was data gathered?)
- Preprocessing (cleaning, filtering, labeling)
- Uses (what are appropriate/forbidden uses?)
- Distribution (licenses, access restrictions)
- Maintenance (who updates, how?)


9. Enterprise LLM Platforms

9.1 Azure OpenAI Service

Capabilities:
- GPT-4o, GPT-4 Turbo, GPT-4o-mini, GPT-4.1 models
- GPT-4o Realtime API (speech-to-speech)
- DALL-E 3, Whisper, Embeddings models
- Azure AI Search integration (built-in RAG)
- Content filtering and safety system
- Private endpoints and managed VNet
- Role-based access control (RBAC)
- Data residency (regional deployments)
- Responsible AI dashboard
- SLA: 99.9% for provisioned throughput

Pricing Model:
- Pay-as-you-go per token
- Provisioned throughput (reserved capacity)
- Batch processing (50% discount)

9.2 AWS Bedrock

Capabilities:
- Multiple foundation models (Claude, LLaMA, Mistral, Cohere, AI21, Amazon Titan)
- Knowledge Bases (serverless RAG with OpenSearch)
- Agents (multi-step task orchestration)
- Guardrails (content filtering, topic denial, PII redaction)
- Model evaluation (automated and human)
- Provisioned throughput
- Integration with AWS ecosystem (Lambda, S3, Kendra, DynamoDB)

9.3 GCP Vertex AI

Capabilities:
- Gemini 1.5/2.0/2.5 series, Claude, LLaMA, Gemma
- Agent Builder (no-code agent creation)
- Model Garden (curated model hub)
- Vector Search (scaled ANN search)
- Evaluation Service (automated metrics)
- Vertex AI Studio (prompt design and testing)
- Model Registry and Model Monitoring

9.4 Databricks

Capabilities:
- Unity Catalog (unified data governance)
- MLflow for model lifecycle
- Model Serving (serverless GPU endpoints)
- Foundation Model APIs (Llama, Mixtral, DBRX)
- Vector Search for RAG
- AI/BI dashboards and Genie
- Lakehouse AI platform

9.5 Enterprise Platform Comparison

Feature Azure OpenAI AWS Bedrock GCP Vertex Databricks
Model Variety OpenAI + select open Broad (multi-provider) Google + select open Open models
RAG Built-in Yes (AI Search) Yes (Knowledge Bases) Yes (Vector Search) Yes (Vector Search)
Guardrails Yes Yes Yes Custom
Private Network Yes (VNet) Yes (VPC) Yes (VPC) Yes
Data Sovereignty Yes (regions) Yes (regions) Yes (regions) Yes
SLA 99.9% 99.9% 99.9% 99.9%
Custom Models Fine-tuning only Fine-tuning Fine-tuning Full training pipeline
Ease of Use β˜…β˜…β˜…β˜… β˜…β˜…β˜…β˜… β˜…β˜…β˜…β˜… β˜…β˜…β˜…

10. Security and Privacy

10.1 Threat Model for LLM Applications

Common Attack Vectors:
- Prompt Injection: Crafting inputs that override system instructions
- Jailbreaking: Bypassing safety guardrails
- Data Extraction: Extracting training data or system prompts
- Indirect Injection: Malicious content in retrieved documents
- Denial of Service: Inputs that cause excessive token generation
- Model Inversion: Reconstructing training examples from model output
- Supply Chain: Compromised model weights, plugins, or libraries

10.2 Defense Layers

Input Layer:
  β”Œβ”€ Input Validation (length limits, pattern filtering)
  β”œβ”€ PII Detection and Redaction
  β”œβ”€ Prompt Injection Detection (Guardrails AI, NeMo Guardrails)
  └─ Rate Limiting and Quota Management

Orchestration Layer:
  β”Œβ”€ Context Sanitization (clean retrieved documents)
  β”œβ”€ Permission Checks (user access to specific data)
  β”œβ”€ Tool Access Control (which tools per user role)
  └─ Output Verification (check for info leakage)

Model Layer:
  β”Œβ”€ Model-Level Guardrails (system prompt hardening)
  β”œβ”€ Content Filter (toxicity, hate, violence, sexual)
  β”œβ”€ Output Constraint (JSON schema enforcement, regex)
  └─ Hallucination Detection (grounding checks)

Output Layer:
  β”Œβ”€ PII Re-check on output
  β”œβ”€ Output Length Limiting
  β”œβ”€ Response Approval (human-in-the-loop for critical actions)
  └─ Audit Logging (full request/response trace)

10.3 Data Isolation

Multi-Tenant Architectures:
- Database-per-tenant: Strongest isolation, highest cost
- Schema-per-tenant: Good isolation, shared infrastructure
- Row-level security: Weakest isolation, most efficient
- Document-level filtering: Via vector DB metadata filters

Privacy Techniques:
- Differential Privacy: Add calibrated noise to training data
- Federated Learning: Train across institutions without data sharing
- Data Masking: Replace sensitive values with masked tokens
- On-Device Processing: Process sensitive data offline on user devices


11. Multi-Model Routing

11.1 Router Architecture

The multi-model router directs each query to the optimal model based on complexity, cost, latency requirements, and capability needs.

                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                     β”‚   Query Classifier    β”‚
                     β”‚  (small fast LLM)     β”‚
                     β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚       β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       └─────────────┐
              β–Ό                                    β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚   Simple Router   β”‚              β”‚   Complex Router      β”‚
    β”‚                   β”‚              β”‚                      β”‚
    β”‚  10% β†’ GPT-4o-miniβ”‚              β”‚ 60% β†’ Claude 4 Sonnetβ”‚
    β”‚ 30% β†’ Gemini Flashβ”‚              β”‚ 25% β†’ GPT-4o         β”‚
    β”‚ 60% β†’ Mistral-7B  β”‚              β”‚ 15% β†’ DeepSeek-R1    β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚                                β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚  Response Validator  β”‚
              β”‚  - Check quality     β”‚
              β”‚  - Check safety      β”‚
              β”‚  - Escalate if poor  β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

11.2 Routing Strategies

Rule-Based Routing:
- Query length < 50 tokens β†’ cheap model
- Contains code β†’ code-capable model
- Contains PII β†’ local model
- Contains "error"/"exception" β†’ reasoning model

ML-Based Routing:
- Train a classifier to predict model success
- Features: query length, domain, complexity score
- Label: which model produced best result
- Continuous learning from user feedback

Cost-Aware Routing:
- Budget per query/quota per user
- Route to cheaper model when budget near limit
- Fallback chain: try cheap β†’ escalate if needed

Latency-Aware Routing:
- Critical path queries β†’ fast model
- Responses under SLA β†’ balanced routing
- Background/batch β†’ cheapest possible
- Peak load β†’ degrade model tier

11.3 Model Cascade

Level 1: Local (Ollama / ONNX)
  - Model: Qwen2.5-7B-Q4 / Phi-4-mini
  - Latency: ~50ms
  - Cost: ~$0
  - Use: Simple FAQ, autocomplete, quick Q&A
  - Fallback threshold: confidence < 0.8 or "I don't know"

Level 2: Fast API (GPT-4o-mini / Claude Haiku / Gemini Flash)
  - Model: gpt-4o-mini / claude-3-haiku
  - Latency: ~200ms
  - Cost: $0.15-0.60/1M
  - Use: Standard queries, classification, extraction
  - Fallback threshold: uncertain, user dissatisfied

Level 3: Premium API (GPT-4o / Claude Sonnet / Gemini Pro)
  - Model: gpt-4o / claude-4-sonnet
  - Latency: ~800ms
  - Cost: $2.50-15.00/1M
  - Use: Complex reasoning, code generation, analysis
  - Fallback threshold: task failed or high complexity detected

Level 4: Expert (DeepSeek-R1 / Claude Opus / o4-mini)
  - Model: deepseek-r1 / claude-4-opus
  - Latency: ~3s
  - Cost: $15.00-60.00/1M
  - Use: Research, math, PhD-level reasoning, safety-critical
  - No fallback (this is the ceiling)

12. Scaling Strategies

12.1 Horizontal Scaling

Scale model serving by adding more replicas:

Stateless (Easy): LLM serving pods behind a load balancer
- Just add more pods
- Requires shared model weight storage (NFS, S3, PVC)
- Watch for GPU memory pressure

Stateful (Hard): Vector databases, caches
- Shard data across pods
- Replication for read availability
- Distributed consensus for writes

12.2 Vertical Scaling

Use larger GPU instances:

Trade-offs:
- Bigger GPUs: higher throughput per instance, but lower availability
- Multiple GPUs: tensor parallelism for large models, pipeline parallelism for throughput
- Instance types: A10G (24GB), L4 (24GB), A100 (40/80GB), H100 (80GB), H200 (141GB), B200 (192GB)

12.3 Model Parallelism Strategies

Tensor Parallelism (TP): Split layers across GPUs
- Requires NVLink/NVSwitch for fast GPU-to-GPU communication
- Common for models > 30B parameters
- Minimally: 1 GPU for 7B, 2 for 13B, 4 for 34B, 8 for 70B

Pipeline Parallelism (PP): Split layers into stages
- Each GPU has a subset of consecutive layers
- Lower communication requirement than TP
- Suffers from bubble overhead

Sequence Parallelism (SP): Split sequence dimension across GPUs
- Useful for very long sequences
- Often combined with TP

Expert Parallelism (EP): For MoE models, split experts across GPUs
- Each GPU handles subset of experts
- All-to-all communication for expert routing
- Used by Mixtral 8x7B, DeepSeek-V2/V3, DBRX

12.4 Autoscaling Configuration

# Horizontal Pod Autoscaler for LLM serving
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: llm-server-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: llm-server
  minReplicas: 2
  maxReplicas: 50
  metrics:
  - type: Pods
    pods:
      metric:
        name: llm_queue_depth
      target:
        type: AverageValue
        averageValue: 5
  - type: Pods
    pods:
      metric:
        name: llm_gpu_utilization
      target:
        type: AverageValue
        averageValue: 80
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 200
        periodSeconds: 15

πŸ“„ Enterprise Fine-Tuning β€” 3378 lines

A comprehensive guide to fine-tuning large language models in enterprise environments, covering decision frameworks, PEFT methods, data pipelines, training infrastructure, and production deployment.

AgentAlignmentAttentionBERTBenchmarkCLIPDPODeploymentDifferential PrivacyEnsemble

1. When to Fine-Tune vs RAG vs Prompting

Decision Matrix

Choosing the right paradigm β€” fine-tuning, Retrieval-Augmented Generation (RAG), or prompting β€” is the most consequential architectural decision in any LLM project. The wrong choice burns GPU budget on unnecessary training, couples you to fragile prompt engineering, or locks you into a retrieval pipeline with latency you cannot sustain. This matrix provides a structured framework.

Decision Factor Prompting (Few-shot / Zero-shot) RAG Fine-Tuning
Knowledge recency Stale at cutoff Fresh via retrieval index Frozen at training time
Data volume ~10 examples max Unlimited (index scale) 1K–100K+ examples
Task specificity General-purpose Factual recall tasks Specialized behavior / style
Latency budget ~200ms–2s +50–500ms retrieval overhead Same as base model
Cost per inference Lowest Medium (storage + retrieval) Highest (GPU hour amortized)
Data privacy No data retention Documents indexed externally Weights memorize data
Domain jargon Poor (no memorization) Good (if in retrieved docs) Excellent (deep assimilation)
Output format control Fragile (prompt engineering) Moderate Strong (format baked into weights)
Model size constraints None Must fit context + retrieved docs Must fit batch on GPU
Iteration speed Instant prompt edits Re-index documents (hours) Re-train (hours–days)
Hallucination risk Highest Lowest (grounded in retrieved text) Moderate (memorized patterns)
Maintenance burden Low Medium (pipeline monitoring) High (retraining cycles)

Decision Flow

Start with prompting. If the task can be accomplished with 0–10 examples in the prompt and the required knowledge fits within the model's training cutoff, prompting is free and infinitely fast to iterate. Use structured output (JSON mode, function calling) to enforce format.

Add RAG when the model needs access to information outside its weights. If the answer depends on specific documents, proprietary knowledge bases, or frequently updating data, RAG provides grounding without retraining. RAG is also the correct choice when data volumes exceed what fine-tuning can absorb (100K+ docs) or when data sources change daily.

Fine-tune when the model needs to internalize a behavior, style, or domain. Fine-tuning shines when:
- The output format must be strictly controlled (e.g., legal document templates, clinical note styles)
- The model must deeply understand domain-specific jargon and concepts (e.g., medical terminology, legal citations, financial reporting standards)
- The model needs to exhibit a specific persona or tone consistently
- RAG retrieval quality is inadequate (low precision/recall on domain corpus)
- Inference latency cannot tolerate retrieval overhead

Hybrid Patterns

The most successful enterprise deployments combine all three:

Prompting (system prompt + instructions)
    ↓
RAG (retrieved context injected into prompt)
    ↓
Fine-Tuned Model (domain-adapted base)

Example: Enterprise Legal Assistant
- Prompting: System prompt defines lawyer persona, jurisdiction rules, and output format
- RAG: Retrieves relevant case law, statutes, and contract clauses from vector database
- Fine-Tuning: Model fine-tuned on legal document corpus for citation format, legal reasoning, and jurisdiction-specific terminology

Anti-Patterns to Avoid

Anti-Pattern Why It Fails
Fine-tuning on facts that change quarterly Model memorizes stale data; retraining needed every quarter
RAG for tasks requiring deep reasoning Retrieved context is fragmented; model cannot synthesize across docs
Prompting for complex multi-step workflows Prompt becomes fragile, long, and expensive; context window overflow
Fine-tuning to "add knowledge" Fine-tuning teaches behavior/shape, not facts; RAG is better for knowledge
No fallback strategy All three should degrade gracefully; RAG fallback from fine-tuning

2. Domain Adaptation Strategies

2.1 Legal Domain

Legal NLP requires precision in citation format, jurisdiction awareness, and understanding of specialized terminology spanning centuries of precedent.

Key Adaptation Approaches:

  • Continued pre-training (CPT) on legal corpora (CourtListener, CaseLaw, PACER, legal textbooks, statutes) β€” 10B–50B tokens for base model assimilation
  • Instruction fine-tuning on legal QA pairs, contract analysis, and legal reasoning chains
  • RLHF/DPO for alignment with legal ethics, confidentiality rules, and jurisdiction-specific output formats

Critical Capabilities:
- Citation extraction and formatting (Bluebook, ALWD, OSCOLA)
- Legal entity recognition (statutes, case names, court names, judges, parties)
- Jurisdiction classification (federal vs state, common law vs civil law)
- Temporal reasoning (overruled precedents, statutory amendments)

Dataset Sources:
- Contracts: EDGAR (SEC filings), US Contract datasets (200K+ contracts), Atticus (contract review)
- Case Law: CourtListener bulk data, Caselaw Access Project (Harvard Law), Free Law Project
- Statutes: US Code XML, State legislative databases, EUR-Lex (EU law)
- Legal QA: LexGLUE, CaseHOLD, LegalBench, CUAD (Contract Understanding Atticus Dataset)

Notable Domain-specific Models:
- LLaMA-based: SaulLM-7B, SaulLM-141B (legal)
- BERT-based: Legal-BERT, CaseLaw-BERT, RoBERTa-Legal
- Encoder-only: LexNLP-based models

Evaluation Benchmarks:
- LegalBench (162 tasks across 6 categories: reasoning, interpretation, drafting, analysis, entity, citation)
- LexGLUE (7 tasks: ECHR, casehold, unfair_tos, etc.)
- CUAD (41 contract question types)
- CaseHOLD (citation prediction)

2.2 Medical Domain

Medical adaptation requires handling of clinical abbreviations, drug names, anatomical terminology, and strict adherence to medical formatting standards (ICD-10, SNOMED CT, RxNorm).

Key Adaptation Approaches:
- Continued pre-training on PubMed Central, MIMIC-III/IV clinical notes, Medscape, textbooks
- Multi-task fine-tuning: NER for medical entities, relation extraction for drug interactions, summarization for clinical notes
- Reinforcement learning from patient outcome proxies (not recommended without rigorous oversight)

Critical Capabilities:
- Medical entity extraction (symptoms, diagnoses, medications, procedures, lab values)
- ICD-10/SNOMED/CPT code assignment
- Clinical note summarization and structured data extraction
- Radiology report generation
- Drug-drug interaction detection

Dataset Sources:
- Clinical Notes: MIMIC-III/IV (requires credentialed access), i2b2/n2c2 datasets, eICU
- Biomedical Literature: PubMed Central Open Access (3M+ full-text articles), PubMed abstracts
- Medical QA: MedQA (USMLE), MedMCQA, PubMedQA, BioASQ
- Drug Data: DrugBank, RxNorm, DailyMed (FDA labels)

Privacy Considerations:
- HIPAA compliance required for training on protected health information (PHI)
- De-identification before any training (MIMIC is pre-de-identified)
- Differential privacy during training when using clinical data
- Model weights may memorize PHI β€” avoid deploying on raw clinical text

Evaluation Benchmarks:
- MedQA (USMLE step questions)
- MedMCQA (multi-choice medical questions)
- PubMedQA (biomedical QA)
- BioBERT-based NER benchmarks (NCBI Disease, BC5CDR, JNLPBA)

2.3 Finance Domain

Financial models need to understand SEC filings, market terminology, financial ratios, and temporal market context.

Key Adaptation Approaches:
- CPT on financial corpus: SEC filings (10-K, 10-Q, 8-K, S-1), earnings call transcripts, analyst reports, financial news
- Instruction tuning for financial QA, sentiment analysis, numerical reasoning, and report generation
- Numerical tokenization considerations (some domains benefit from digit tokenization or specialized number embeddings)

Critical Capabilities:
- Financial entity recognition (ticker symbols, company names, currency amounts, financial ratios)
- Numerical reasoning (percentage change, CAGR, EPS, P/E ratio calculation)
- Financial sentiment analysis (bullish/bearish/neutral on financial texts)
- SEC filing structure understanding (Item numbers, MD&A, Risk Factors, Financial Statements)
- Multi-lingual support (global markets)

Dataset Sources:
- SEC Filings: EDGAR (free access via SEC API), thousands of new filings daily
- Earnings Calls: Transcripts from SeekingAlpha, Motley Fool, manual scraping
- Financial News: Reuters, Bloomberg (licensed), Yahoo Finance
- Financial QA: FinQA, ConvFinQA, TAT-QA (table-based), FinanceBench

Numerical Capabilities:
Financial NLP places extreme demands on numerical reasoning. Evaluate:
- Calculation of financial ratios given raw financial data
- Trend identification (YoY growth, QoQ changes)
- Table understanding (financial statements in tabular format)
- Currency conversion and unit normalization

Evaluation Benchmarks:
- FinQA (numerical reasoning over financial reports)
- ConvFinQA (conversational financial QA)
- FinanceBench (real-world financial analyst questions)
- TAT-QA (table-and-text hybrid QA)
- FiQA SA (financial sentiment analysis)

2.4 Code Domain

Code-adapted models power developer productivity tools, automated documentation, code review, and bug fixing.

Key Adaptation Approaches:
- CPT on code corpora: GitHub repositories (permissively licensed), Stack Overflow, technical documentation
- Fill-in-the-middle (FIM) training: predict masked code spans, not just left-to-right generation
- Multi-language training: Python, JavaScript, TypeScript, Java, Go, Rust, C++, SQL, Bash

Critical Capabilities:
- Code completion (single-line, multi-line, whole-function)
- Code explanation and documentation generation
- Bug detection and fix suggestion
- Code translation (e.g., Python to JavaScript)
- SQL query generation from natural language
- Shell command generation

Dataset Sources:
- GitHub: The Stack (3TB+), CodeParrot, GitHub Archive
- QA: Stack Overflow data dump, CodeSearchNet, StaQC
- Documentation: Official docs (Python, JavaScript, Rust, etc.)

Training Considerations:
- FIM training: Use a FIM transformation that converts code into <PREFIX><SUFFIX><HOLE> format. Common implementations: PSM (Prefix-Suffix-Middle), SPM (Suffix-Prefix-Middle)
- Language balancing: Weight smaller languages (Rust, Haskell) higher to prevent catastrophic forgetting
- File-level context: Code files have inter-dependencies; consider whole-file or cross-file context windows
- Syntax validation: Add AST validation to training data filters

Evaluation Benchmarks:
- HumanEval (function synthesis from docstrings)
- MBPP (mostly basic Python programming)
- SWE-bench (real-world GitHub issue resolution)
- BigCodeBench (multi-language, multi-task)
- RepoBench (repository-level code completion)

2.5 Customer Support Domain

Customer support models need tone control, brand voice adherence, escalation logic, and multi-turn conversation management.

Key Adaptation Approaches:
- Conversational fine-tuning on chat logs, ticket histories, and email threads
- Supervised fine-tuning with agent-written responses as targets
- RLHF/DPO with customer satisfaction scores as reward signal

Critical Capabilities:
- Intent classification and routing
- Sentiment detection and empathy generation
- Knowledge base grounding (hybrid with RAG)
- Multi-turn conversation coherence
- Escalation detection and handoff
- Brand voice and tone consistency

Dataset Sources:
- Internal ticketing systems: Zendesk, Freshdesk, Salesforce Service Cloud, Intercom
- Chat logs: Live chat transcripts (anonymized)
- Email: Customer support email threads (PII-redacted)
- Knowledge base: Internal FAQ and documentation

Privacy and Compliance:
- GDPR: Support data often contains PII; ensure retention policies
- CCPA: California consumer privacy rights apply
- PCI DSS: Payment information must never enter training data
- HIPAA: If healthcare support, clinical data protection required

Quality Metrics:
- CSAT (Customer Satisfaction Score) improvement
- First Contact Resolution (FCR) rate
- Average Handle Time (AHT) change
- Escalation rate reduction
- Agent acceptance rate of AI-suggested responses


3. PEFT Methods β€” Enterprise Focus

Parameter-Efficient Fine-Tuning (PEFT) methods are the backbone of enterprise LLM adaptation. They make fine-tuning economically viable by updating only a tiny fraction of model parameters while retaining the base model's general capabilities.

3.1 LoRA (Low-Rank Adaptation)

Core Concept:
Given a pre-trained weight matrix W ∈ ℝ^{dΓ—k}, LoRA constrains its update Ξ”W to be low-rank:

Ξ”W = BA, where B ∈ ℝ^{dΓ—r}, A ∈ ℝ^{rΓ—k}, and r β‰ͺ min(d, k)

The forward pass becomes:

h = Wx + BAx

Only A and B are trained; W is frozen.

Hyperparameters in Detail:

Rank (r)

The rank r controls the representational capacity of the adapter. Enterprise practitioners should think of r as a budget parameter: more rank = more expressivity, more parameters, more VRAM, more regularization needed.

Rank Parameters (7B, q_proj+v_proj) Typical Use Case
1 ~0.5M Simple domain adaptation, very sparse data (<100 examples)
8 ~4M Default starting point for most tasks
16 ~8M Complex instruction following, multi-task
32 ~16M High-difficulty domain adaptation (legal, medical)
64 ~32M Near full-fine-tune quality, large datasets (50K+)
128 ~64M Overkill for most tasks; consider full fine-tuning
256 ~128M Rarely needed; full fine-tuning often better

Empirical rule: Start with r=8 for data <10K examples, r=16 for 10K–50K, r=32+ for 50K+. In practice, r=16 is the "sweet spot" for most enterprise use cases.

Alpha (Ξ±)

LoRA scaling factor determines how much the adaptation affects the forward pass:

h = Wx + (Ξ±/r) * BAx
  • Ξ± = r: Default (1:1 scaling). No amplification.
  • Ξ± = 2r: Doubles the effective learning rate of the adapter.
  • Ξ± = 16, r=8: Scale factor of 2.
  • Ξ± = 32, r=8: Scale factor of 4.

Best practices:
- Keep Ξ± proportional to r (Ξ± = r, 2r, or 4r)
- Higher Ξ±/r ratio = stronger regularization effect (smaller effective updates)
- Lower Ξ±/r ratio = faster convergence but potential instability
- Common enterprise setting: Ξ± = 16, r = 16

Dropout

LoRA dropout applies dropout to the adapter output:

h = Wx + dropout(BAx, p)
Dropout Rate Effect
0.0 Fast convergence, overfitting risk on small data
0.05 Mild regularization, good for 10K+ examples
0.1 Default for most cases
0.2 Heavy regularization, small datasets (<1K)
0.3+ Very aggressive; rarely needed

Target Modules

Which weight matrices to adapt determines both cost and quality.

Common choices for transformer architectures:

# Llama 2/3 architecture
target_modules = [
    "q_proj",      # Query projection β€” most impactful
    "v_proj",      # Value projection β€” important for output
    "k_proj",      # Key projection β€” less critical than Q/V
    "o_proj",      # Output projection β€” subtle improvements
    "gate_proj",   # MLP gate β€” significant for reasoning
    "up_proj",     # MLP up projection
    "down_proj",   # MLP down projection
]
Module Set Parameters Added (7B, r=16) Quality Impact
q_proj + v_proj ~8M Good baseline
q_proj + v_proj + o_proj ~12M Better
All attention (q,k,v,o) ~16M Standard choice
All attention + MLP (gate,up,down) ~48M Full adapter (near full-FT quality)
Every linear layer ~80M+ Aggressive; marginal gains

Enterprise recommendation: Start with q_proj, v_proj and add o_proj, k_proj if quality is insufficient. Add MLP modules (gate_proj, up_proj, down_proj) only for complex reasoning tasks where attention-only adaptation plateaus.

3.2 QLoRA (Quantized LoRA)

QLoRA enables fine-tuning of large models (65B, 70B, 140B+) on a single consumer GPU by quantizing the base model to 4-bit while keeping LoRA adapters in full precision.

4-bit NormalFloat (NF4)

NF4 is a quantization data type designed for normally distributed weights. Unlike uniform quantization (INT4), NF4 allocates more quantization levels near zero where weights concentrate:

NF4 codebook: [-1.0, -0.696, -0.525, -0.393, -0.278, -0.174, -0.078, 0.0,
               0.078, 0.174, 0.278, 0.393, 0.525, 0.696, 1.0]

Double Quantization

QLoRA introduces double quantization: the quantization constants (scale factors) themselves are quantized to 8-bit, saving another ~0.5 bits per parameter:

  1. First quantization: FP16 weights β†’ NF4 (4-bit) β€” scale factors in FP32
  2. Second quantization: FP32 scale factors β†’ INT8 (8-bit) β€” second-level scale factors in FP32

Total savings: ~4.5 bits per parameter vs 16-bit (FP16) baseline.

Memory Savings Breakdown

Model FP16 LoRA (r=16) QLoRA (4-bit NF4)
7B 14 GB ~16 GB ~6.5 GB
13B 26 GB ~28 GB ~10.5 GB
34B 68 GB ~70 GB ~24 GB
70B 140 GB ~142 GB ~48 GB
180B 360 GB ~362 GB ~120 GB

QLoRA typically achieves within 0.5–2% of LoRA quality on most benchmarks while using ~4x less memory.

Nested Quantization

For extreme memory savings, the base model can be quantized to 3-bit or 2-bit with modest quality degradation:
- NF3 (3-bit): ~3.5 bits/param after double quantization
- NF2 (2-bit): ~2.5 bits/param after double quantization

These are experimental and recommended only for large models (70B+) where 4-bit still exceeds available VRAM.

When to Use QLoRA vs LoRA

Scenario Recommended
Consumer GPU (24 GB or less) QLoRA
Enterprise GPU (40 GB A100, 80 GB H100) LoRA (for quality) or QLoRA (for throughput)
Multiple models on one GPU QLoRA
Maximum quality required LoRA
70B+ models on limited hardware QLoRA
Production training pipeline LoRA (less complexity)

3.3 DoRA (Weight-Decomposed Low-Rank Adaptation)

DoRA decomposes pretrained weights into magnitude and direction components and applies LoRA only to the directional component:

W = m * V / ||V||  where V = W + Ξ”W (LoRA update)

Key Advantages:
- Directional updates: LoRA changes both magnitude and direction; DoRA isolates directional learning
- Faster convergence: 1.5–2x faster than LoRA on some benchmarks
- Better quality: Consistently matches or exceeds LoRA across NLU and NLG tasks
- Parameter count: Same as LoRA (magnitude vector adds negligible parameters, one per row)

Enterprise Recommendation:
DoRA is the default choice over LoRA when available. The additional training stability and faster convergence reduce GPU hours directly. Supported in libraries like PEFT (via use_dora=True), Axolotl (via lora_dora: true).

Implementation in PEFT:

from peft import LoraConfig, get_peft_model

lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["q_proj", "v_proj"],
    lora_dropout=0.1,
    use_dora=True,  # Enable DoRA
)

3.4 AdaLoRA (Adaptive Budget Allocation)

AdaLoRA parametrizes weight updates through SVD and dynamically allocates the rank budget across layers based on importance:

W = Wβ‚€ + PΞ›Q, where Ξ› is a diagonal matrix of singular values

Key Mechanisms:
- Regularization: L0 penalty on singular values encourages sparsity
- Dynamic budget: Layers with higher importance get higher effective rank
- SVD-based: Maintains orthogonality constraints on P and Q

Empirical Results:
- Often outperforms LoRA with the same total rank budget
- Automatically assigns more rank to early layers and attention layers
- Less sensitive to rank choice (use r=16 or r=32 and let it prune)

Trade-offs:
- +20-30% training overhead over LoRA
- More hyperparameters (L0 regularization coefficient, target rank)
- Not supported in all frameworks

Enterprise Recommendation:
Best for tasks where the optimal rank is unknown and you have budget to run AdaLoRA experiments. For well-understood tasks, standard LoRA/DoRA is simpler.

3.5 IA3 (Infused Adapter by Inhibiting and Amplifying Activations)

IA3 learns scaling vectors that modulate key activations:

h = Wx βŠ— l, where l is a learned scaling vector

Compared to LoRA:
- Fewer parameters: ~10,000x fewer than full fine-tuning (vs 1000x for LoRA)
- Faster: No matrix multiplication overhead for adapters
- Weaker on complex tasks: Struggles with multi-task reasoning

When to Use IA3:
- Extremely limited storage (thousands of adapters)
- Simple domain adaptation (tone, format, style)
- Feature extraction where base model capabilities are sufficient
- Multi-adapter serving with minimal overhead


4. Data Preparation Pipeline

Data quality is the single largest determinant of fine-tuning success. A well-prepared dataset consistently outperforms a 10x larger noisy dataset.

4.1 Data Collection

Enterprise data sources span diverse formats and quality levels.

Source Type Examples Volume Quality PII Risk
Conversation logs Chat transcripts, support tickets 100K–10M Medium High
Internal documents Wikis, runbooks, SOPs 1K–100K Mixed Low–Medium
Code repositories Git history, Jupyter notebooks 10K–1M High Low
Emails Correspondence, newsletters 10K–100K Medium Very High
Database records CRM, ERP, logs 1M+ Variable High
Public datasets Benchmarks, open-source 10K–10M High Low
Feedback loops User ratings, corrections 1K–100K High Medium

Collection Best Practices:
- Capture full conversation context (not just individual turns)
- Preserve metadata (timestamps, user IDs – for deduplication only)
- Log model-generated completions separately (avoid contamination)
- Implement data retention policies aligned with GDPR/CCPA
- Version control raw data with data manifests

4.2 Data Cleaning

Deduplication

Enterprise datasets often contain massive redundancy due to repeated logging, template-driven content, and feedback loops.

Levels of Deduplication:

  1. Exact deduplication: MD5/SHA256 hash comparison β€” removes identical strings
  2. Near-dedup (MinHash): Jaccard similarity >0.8 β€” removes near-identical documents
  3. Template deduplication: Regex-based removal of auto-generated templates
  4. Semantic deduplication: Embedding similarity >0.95 β€” removes paraphrased content

MinHash Implementation:

from datasketch import MinHash, MinHashLSH

def compute_minhash(text, num_perm=128):
    m = MinHash(num_perm=num_perm)
    for ngram in ngrams(text.split(), 5):
        m.update(' '.join(ngram).encode('utf-8'))
    return m

# LSH for efficient near-dedup
lsh = MinHashLSH(threshold=0.8, num_perm=128)
for idx, text in enumerate(documents):
    m = compute_minhash(text)
    lsh.insert(f"doc_{idx}", m)

Deduplication Statistics:
- Typical enterprise dataset: 20–40% redundancy
- Log data: often 60–80% redundant
- After MinHash (0.8 threshold): typically removes 15–30%

Formatting and Encoding

  • Encoding detection: Use charset-normalizer or cchardet to detect and standardize to UTF-8
  • Whitespace normalization: Collapse multiple spaces, normalize newlines (\r\n β†’ \n)
  • Unicode normalization: NFC normalization (composed) for consistent character representation
  • Markdown/HTML stripping: Remove formatting tags, keep text content
  • JSON/XML extraction: Parse structured data and extract text fields
import chardet
import unicodedata

def normalize_text(text):
    # Detect and fix encoding
    if isinstance(text, bytes):
        detected = chardet.detect(text)
        text = text.decode(detected['encoding'] or 'utf-8', errors='replace')

    # Unicode normalization
    text = unicodedata.normalize('NFC', text)

    # Whitespace normalization
    text = ' '.join(text.split())

    return text

PII Redaction

Personally Identifiable Information (PII) must be removed before any training, especially for regulated industries.

Redaction Pipeline (Presidio + spaCy):

from presidio_analyzer import AnalyzerEngine
from presidio_anonymizer import AnonymizerEngine

analyzer = AnalyzerEngine()
anonymizer = AnonymizerEngine()

def redact_pii(text):
    results = analyzer.analyze(text=text, language='en')
    anonymized = anonymizer.anonymize(
        text=text,
        analyzer_results=results
    )
    return anonymized.text

PII Types to Detect and Redact:

PII Type Regex/NER Approach Enterprise Requirement
Email addresses Regex: [\w.+-]+@[\w-]+\.[\w.-]+ Always
Phone numbers Regex: \+?\d{1,4}[\s-]?\d{3,4}[\s-]?\d{4,10} Always
SSN / Tax IDs Regex: \d{3}-\d{2}-\d{4} Always (US)
Credit card numbers Luhn algorithm + regex Always (PCI)
IP addresses Regex: \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} Always
Names spaCy NER (PERSON) Usually
Locations spaCy NER (GPE, LOC) Usually
Dates (medical) Regex + context HIPAA
Medical record numbers Pattern-based + context HIPAA
Bank account numbers Regex (varies by country) Usually

Best Practices:
- Use both regex (high recall) and NER (high precision) in sequence
- Validate redaction on a holdout set before training
- For LLM training, redact with placeholder tags like <PERSON> or [REDACTED]
- Never train on non-redacted data, even in a sandbox
- Implement differential privacy as an additional safeguard

Language Filtering

Multilingual enterprises need to filter or classify training data by language.

import fasttext

# Language identification model (e.g., lid.176.bin from fasttext)
lang_model = fasttext.load_model('lid.176.bin')

def detect_language(text, threshold=0.5):
    predictions = lang_model.predict(text.replace('\n', ' '), k=1)
    lang = predictions[0][0].replace('__label__', '')
    score = predictions[1][0]
    return lang, score

# Filter for English-only or specific language mix
filtered = [
    text for text in corpus
    if detect_language(text)[0] == 'en' and detect_language(text)[1] > 0.7
]

Language Distribution Heuristics:
- Use language distribution of target users
- Avoid mixing languages in single training example (unless target task is translation)
- For multilingual models, balance languages by sampling rate

4.3 Quality Filtering

Heuristic Filtering

Simple, fast quality signals that remove obvious garbage:

Heuristic Threshold Rationale
Minimum length >50 characters Too-short text lacks context
Maximum length <8192 tokens Context window limits
Word count >20 words Sentence-level content only
Average word length 3–10 chars 2-char avg = noise, 15+ char avg = code
Punctuation ratio 5–40% Low = no structure, high = table/data
Repeated characters <5% of text "aaaaa" or "!!!!!" = noise
Repeated n-grams (4-gram) <40% Template text
HTML tag ratio <30% Scraped markup
Non-printable chars <1% Binary content
Stop word ratio (English) >5% Non-English or gibberish
import re
from collections import Counter

def heuristic_filter(text):
    if len(text) < 50:
        return False
    if len(text) > 32000:
        return False

    words = text.split()
    if len(words) < 20:
        return False

    avg_word_len = sum(len(w) for w in words) / len(words)
    if avg_word_len < 3 or avg_word_len > 15:
        return False

    # Count repeated chars
    repeated = sum(1 for c in text if text.count(c) > len(text) * 0.05)
    if repeated > 0:
        return False

    # Check for non-printable
    non_printable = sum(1 for c in text if not c.isprintable())
    if non_printable / len(text) > 0.01:
        

5. Synthetic Data Generation

Synthetic data is increasingly critical for enterprise fine-tuning, especially when real data is scarce, sensitive, or expensive to annotate.

5.1 Self-Instruct Pipeline

Original Process (Wang et al., 2022):

  1. Seed tasks: Write 175 seed instructions (hand-crafted)
  2. Instruction generation: For each seed, prompt an LLM to generate more instructions
  3. Classification: Classify whether the instruction is a classification or generation task
  4. Output generation: For each instruction, prompt the LLM to produce an output
  5. Filtering: Remove low-quality or duplicate entries
  6. Iterate: The generated dataset becomes new seeds

Enterprise Implementation:

class SelfInstruct:
    def __init__(self, base_model, seed_tasks):
        self.model = base_model
        self.seed_tasks = seed_tasks
        self.instructions = []

    def generate_instructions(self, num_to_generate=1000):
        for seed in self.seed_tasks:
            prompt = f"""
            Generate a new instruction for an AI assistant.
            The instruction should be similar in difficulty and style to:

            Instruction: {seed}

            New instruction:
            """
            response = self.model.generate(prompt)
            self.instructions.append(response.strip())

    def generate_responses(self):
        for instruction in self.instructions:
            prompt = f"""
            Instruction: {instruction}

            Provide a helpful, accurate response to the above instruction.
            Response:
            """
            response = self.model.generate(prompt)
            dataset.append({"instruction": instruction, "output": response})

Quality Controls:
- Filter instructions with keyword overlap >80% with existing set
- Remove instructions that are too short (<5 words) or too long (>50 words)
- Balance across task categories
- Verify executability (can the model actually complete the task?)

5.2 Evol-Instruct

Evol-Instruct generates training data by progressively making instructions more complex (in-depth + in-breadth evolution).

In-Depth Evolution

Makes a single instruction harder by adding constraints, deepening reasoning, or increasing difficulty:

Evolution Operation Example Transformation
Add constraints "Write a poem" β†’ "Write a haiku about AI using exactly 17 syllables"
Deepen reasoning "Explain gravity" β†’ "Explain how gravitational waves differ from Newtonian predictions of gravity"
Increase difficulty "Translate to French" β†’ "Translate this legal contract to French, maintaining all technical terms and preserving the legal validity"
Add specific format "Summarize" β†’ "Summarize in exactly 3 bullet points with a 50-word limit per bullet"
Add comparison "Describe Python" β†’ "Compare Python and Rust for systems programming, considering memory safety, performance, and developer productivity"

In-Breadth Evolution

Generates new, diverse instructions from existing ones without increasing difficulty:

Evolution Operation Example Transformation
Concretization "Write a function" β†’ "Write a function to calculate Fibonacci numbers"
Increase scope "Debug this code" β†’ "Debug this code and write unit tests for edge cases"
Switch domain "Write marketing copy" β†’ "Write marketing copy for a B2B SaaS product in the healthcare space"
Add background "Explain transformers" β†’ "Explain the transformer architecture to a high school student with no ML background"
Scenario-based "Create a plan" β†’ "Create a project plan for migrating a monolith to microservices"

Quality Control in Evol-Instruct:
- LLM Judge scores each evolved instruction (1–5)
- Remove instructions scoring <3
- Remove instructions identical to (or too similar to) originals
- Verify instruction is still solvable after evolution
- Balance difficulty distribution

5.3 Wizard Methods

The "Wizard" family (WizardLM, WizardCoder, WizardMath) builds on Evol-Instruct with domain-specific extensions:

  • WizardLM: Evol-Instruct on general instructions
  • WizardCoder: Evol-Instruct on code generation instructions, with test-based verification
  • WizardMath: Evol-Instruct on math problems, with step-by-step verification

Key Innovation β€” Complexity Scoring:

Complexity Score = f(num_constraints, reasoning_depth, domain_specificity, format_restrictiveness)

Each evolved instruction's complexity is tracked, and the training set is balanced across complexity levels.

5.4 Knowledge Distillation from Large Models

Distillation leverages the fact that larger models (teacher) often produce higher quality outputs than smaller models (student).

Distillation Pipeline:

  1. Teacher selection: GPT-4, Claude 3.5 Sonnet, Gemini Ultra, or the largest available model
  2. Prompt construction: Craft prompts that elicit detailed, correct responses
  3. Batch generation: Generate outputs at scale (cost-efficient via API)
  4. Quality filtering: Remove obviously incorrect or low-quality outputs
  5. Student training: Fine-tune smaller model (e.g., Llama 3.1 8B) on teacher outputs

Distillation Strategies:

Strategy Description Quality vs Cost
Direct distillation Train on teacher outputs directly Medium quality, low cost
Contrastive distillation Train on (good output, bad output) pairs Higher quality, higher cost
Multi-teacher ensemble Use majority vote across teachers Highest quality, highest cost
Self-distillation Student generates, teacher scores Iterative improvement

Enterprise Implementation Considerations:
- Cost: GPT-4 distillation for 100K examples β‰ˆ $5,000–$15,000 in API costs
- Rate limits: Need multiple API keys or batch API for large volumes
- Bias propagation: Teacher biases transfer to student β€” audit carefully
- Licensing: Check teacher's terms of service for distillation rights

5.5 Multi-turn Conversation Synthesis

Synthetic multi-turn conversations are essential for training chat-oriented models.

Conversation Tree Generation:

User: I need help with my account.
Assistant: I'd be happy to help! What seems to be the issue?
User: I can't log in. It says "invalid password."
Assistant: Let's try resetting your password. Can you access your email?
User: Yes, I can.
Assistant: Great. I've sent a password reset link to your registered email. Please check and follow the instructions.
User: It worked! I'm logged in now. Thanks.
Assistant: You're welcome! Is there anything else I can help you with?

Generation Approaches:

  1. Role-play: Two model instances β€” one as user (with persona), one as assistant
  2. Template-based: Fill in slots in conversation templates (good for customer support)
  3. Instruct-then-generate: Start with a high-level scenario and let model generate full conversation
  4. Branching: Generate multiple possible continuations at each turn, select best path

Quality Control:
- Require β‰₯3 turns for "conversation" qualification
- Check for assistant response quality (helpful, accurate, safe)
- Remove conversations where user repeats the same question
- Ensure conversation reaches resolution or proper escalation

5.6 Quality Control

Synthetic data quality control is an ongoing process, not a one-time filter.

LLM Judge

Use a LLM (often the same model or a larger one) to evaluate synthetic data quality:

def llm_judge(instruction, response, criteria):
    prompt = f"""
    Evaluate the following response to an instruction on these criteria:

    Instruction: {instruction}
    Response: {response}

    Criteria:
    1. Helpfulness (1-5): Does the response address the instruction?
    2. Accuracy (1-5): Is the information correct?
    3. Completeness (1-5): Is the response thorough?
    4. Safety (1-5): Is the response safe and ethical?

    Format your response as: 
    Helpfulness: X
    Accuracy: X
    Completeness: X
    Safety: X
    """

    evaluation = judge_model.generate(prompt)
    return parse_evaluation(evaluation)

Human Verification Threshold

For enterprise production, establish a human verification threshold:

Quality Score Action
4.5–5.0 Auto-accept
3.5–4.5 Auto-accept with sampling (1 in 10 human check)
2.5–3.5 Human review required
1.0–2.5 Auto-reject

Quality Metrics Dashboard

Track these metrics over time across data runs:

  • Acceptance rate: % passing quality filters
  • Distribution coverage: Are all domains/topics represented?
  • Difficulty distribution: Are there enough hard examples?
  • Token length distribution: Consistent with target task?
  • Model agreement: Do multiple LLM judges agree?
  • Human agreement: When humans review, do they concur with LLM judge?

6. Human Annotation

Human annotation remains essential for high-quality supervised fine-tuning, especially for tasks requiring domain expertise or nuanced judgment.

6.1 Annotation Platform Comparison

LabelStudio

Feature Details
License Apache 2.0 (open source)
Self-hosted Yes (Python/Django)
Annotation types Text classification, NER, sequence labeling, transcription, QA
LLM features ML-assisted labeling, LLM pre-annotations
Collaboration Teams, review workflows, project roles
Integration API SDK, Storage (S3, GCS, Azure), Cloud (pre-built images)
Cost Free (self-hosted). LabelStudio Enterprise has paid tiers.
Best for Teams that want full control, on-prem deployment

Setup:

pip install label-studio
label-studio start --init  # Initialize with admin user

Prodigy

Feature Details
License Proprietary (commercial)
Self-hosted Yes (Python library)
Annotation types NER, text classification, image annotation, audio, video
LLM features Built-in recipe system, LLM integration (via recipe), active learning
Collaboration Multi-user with Prodigy Teams
Integration spaCy native integration, custom recipes
Cost ~$1,000–5,000/year depending on license tier
Best for Teams already in spaCy ecosystem, rapid prototyping

Example recipe:

import prodigy
from prodigy.components.loaders import JSONL

@prodigy.recipe('text-classification')
def text_classification(dataset, source):
    stream = JSONL(source)
    return {
        'dataset': dataset,
        'stream': stream,
        'view_id': 'classification',
        'config': {
            'labels': ['relevant', 'irrelevant']
        }
    }

Scale AI (Scale Rapid)

Feature Details
License Proprietary (SaaS)
Self-hosted No (cloud-only)
Annotation types All types (text, image, video, 3D, audio, document)
LLM features Scale Spellbook (RLHF, prompt engineering, evaluation)
Collaboration Managed workforce, expert pool, automated QA
Integration API, webhooks, data connectors
Cost Pay-per-task (variable); enterprise contracts
Best for Large-scale annotation with managed workforce

Snorkel AI (now Weights & Biases)

Feature Details
License Proprietary
Self-hosted Enterprise option
Annotation types Data development, labeling functions, slicing
LLM features Foundation model labeling, programmatic labeling
Collaboration Team-based, labeling function sharing
Integration Weights & Biases ecosystem
Cost Enterprise pricing
Best for Weak supervision + human validation at scale

6.2 Inter-Annotator Agreement

Measuring agreement between annotators is critical for dataset quality.

Cohen's Kappa (ΞΊ)

For two annotators, Cohen's Kappa measures agreement beyond chance:

ΞΊ = (pβ‚€ - pβ‚‘) / (1 - pβ‚‘)

Where:
- pβ‚€ = observed agreement
- pβ‚‘ = expected agreement by chance

ΞΊ Value Agreement
< 0 Poor
0.0–0.20 Slight
0.21–0.40 Fair
0.41–0.60 Moderate
0.61–0.80 Substantial
0.81–1.00 Almost perfect

Implementation:

from sklearn.metrics import cohen_kappa_score

# Annotations from two annotators
annotator_1 = [0, 1, 1, 0, 2, 1, 0, 1]
annotator_2 = [0, 1, 0, 0, 2, 1, 1, 1]

kappa = cohen_kappa_score(annotator_1, annotator_2)
print(f"Cohen's Kappa: {kappa:.3f}")

Limitations:
- Kappa is affected by prevalence (if most items are the same class, ΞΊ is low even with high agreement)
- Only handles two annotators; use Fleiss' Kappa for >2

Krippendorff's Alpha (Ξ±)

A more robust agreement metric that handles >2 annotators, missing data, and any scale type (nominal, ordinal, interval, ratio):

Ξ± = 1 - Dβ‚’ / Dβ‚‘

Where:
- Dβ‚’ = observed disagreement
- Dβ‚‘ = expected disagreement by chance

Implementation:

import krippendorff

# Annotations: items as rows, annotators as columns
# NaN for missing annotations
data = np.array([
    [1, 1, 1, np.nan],  # Item 1
    [2, 2, 2, 2],       # Item 2
    [1, 2, 1, 2],       # Item 3
    [2, 2, 1, 2],       # Item 4
])

alpha = krippendorff.alpha(data, level_of_measurement='nominal')
print(f"Krippendorff's Alpha: {alpha:.3f}")

Enterprise Thresholds:
- Ξ± > 0.8: Good reliability; dataset is consistent
- 0.67 ≀ Ξ± ≀ 0.80: Tentative reliability; investigate disagreements
- Ξ± < 0.67: Poor reliability; re-train annotators or simplify task

6.3 Quality Assurance Workflows

Three-stage QA Pipeline:

  1. Training stage: Annotators train on a gold-standard set of 50–100 examples. Must achieve ΞΊ > 0.7 on a qualification test.
  2. Production stage: Annotations flow through automated checks:
    - Validation against schema (required fields, data types)
    - Real-time agreement check (if multiple annotators)
    - Confidence scoring (model predicts label; flag low-confidence annotations)
  3. Review stage: Random sample (5–20%) reviewed by senior annotator or domain expert

Blind Spots to Monitor:
- Drift: Annotator agreement decreasing over time (need re-calibration)
- Edge cases: Systematic disagreement on specific data types
- Annotation fatigue: Degradation toward end of shift (flag batches completed in last hour)
- Cascading errors: Errors in early steps propagate

6.4 Active Learning

Active learning reduces annotation costs by selecting the most informative examples for human labeling.

Uncertainty Sampling

Select examples where the model is most uncertain:

def uncertainty_sampling(model, unlabeled_pool, n_samples=100):
    predictions = []
    for example in unlabeled_pool:
        probs = model.predict_proba(example)
        # Margin: difference between top 2 probabilities
        sorted_probs = np.sort(probs)[::-1]
        margin = sorted_probs[0] - sorted_probs[1]
        predictions.append(margin)

    # Select examples with smallest margin (highest uncertainty)
    indices = np.argsort(predictions)[:n_samples]
    return [unlabeled_pool[i] for i in indices]

Variants:
- Least confidence: 1 - max(probability)
- Margin sampling: Difference between top 2 probabilities
- Entropy: -Ξ£ p(x) log p(x)
- BALD: Bayesian Active Learning by Disagreement (for neural networks)

Diversity Sampling

Ensure the selected batch covers diverse data regions:

def diversity_sampling(embeddings, n_samples=100):
    # k-means centroids as diverse representatives
    from sklearn.cluster import KMeans

    kmeans = KMeans(n_clusters=n_samples, random_state=42)
    kmeans.fit(embeddings)

    # Find closest example to each centroid
    indices = []
    for centroid in kmeans.cluster_centers_:
        distances = np.linalg.norm(embeddings - centroid, axis=1)
        closest = np.argmin(distances)
        indices.append(closest)

    return indices

Expected Model Change

Select examples that would most change the model parameters:

Expected Gradient Length (EGL):
Select x that maximizes ||βˆ‡β„“(x, Ε·; ΞΈ)||

This is computationally expensive but highly effective for deep neural networks.

Enterprise Active Learning Loop:

1. Train initial model on small annotated seed set
2. Score unlabeled pool with uncertainty/diversity metrics
3. Select top-K examples for annotation
4. Annotate (...

7. Training Infrastructure

7.1 Cloud ML Platforms

AWS SageMaker

Key Features:
- Managed training jobs with automatic instance provisioning
- SageMaker Studio for interactive development
- Built-in Deep Learning Containers (DLCs)
- Distributed Training Libraries (SMDDP for data parallelism)
- Managed Spot Training (up to 90% cost reduction)
- Model registry and deployment pipeline

Fine-tuning on SageMaker:

import sagemaker
from sagemaker.huggingface import HuggingFace

sagemaker_session = sagemaker.Session()

hf_estimator = HuggingFace(
    entry_point='train.py',
    source_dir='./scripts',
    instance_type='ml.g5.12xlarge',
    instance_count=2,
    role=role,
    transformers_version='4.28.0',
    pytorch_version='2.0.0',
    hyperparameters={
        'model_id': 'meta-llama/Llama-2-7b-hf',
        'dataset_path': '/opt/ml/input/data/training',
        'epochs': 3,
        'per_device_train_batch_size': 4,
        'gradient_accumulation_steps': 4,
        'learning_rate': 2e-4,
        'lora_r': 16,
        'lora_alpha': 32,
    },
    use_spot_instances=True,
    max_wait=86400,
    checkpoint_s3_uri='s3://my-bucket/checkpoints/',
)

hf_estimator.fit({'training': 's3://my-bucket/training-data/'})

Pricing Considerations:
- ml.g5.12xlarge (4Γ— A10G, 192 GB VRAM): ~$6.12/hr on-demand, ~$1.84/hr spot
- ml.p4d.24xlarge (8Γ— A100 40GB, 320 GB VRAM): ~$37.69/hr on-demand
- ml.p5.48xlarge (8Γ— H100 80GB, 640 GB VRAM): ~$132.10/hr on-demand

GCP Vertex AI

Key Features:
- Custom jobs with any Docker image
- Hyperparameter tuning (Vizier)
- Custom model serving with prediction endpoints
- Deep Learning VM images with pre-installed drivers
- TPU v4/v5e/v5p support for LLM training

Fine-tuning on Vertex AI:

gcloud ai custom-jobs create \
    --region=us-central1 \
    --display-name=llm-fine-tune \
    --worker-pool-spec=machine-type=a2-highgpu-8g,replica-count=1,container-image-uri=gcr.io/my-project/llm-training:latest \
    --args="--model=meta-llama/Llama-2-13b-hf,--dataset=gs://my-bucket/train.jsonl"

Azure ML

Key Features:
- Azure OpenAI Service for managed LLM fine-tuning
- Azure ML Compute (NC/HB/NV series)
- Integration with Responsible AI dashboard
- Managed online endpoints for deployment

Note: Azure has the tightest integration with Microsoft's own models (Phi, Orca) and OpenAI models.

7.2 GPU Cloud Providers

Lambda GPU Cloud

GPU Type Specs Price/hr
A100 (80 GB) 1Γ— A100 SXM 80GB $1.10
A100 (80 GB) 8Γ— 8Γ— A100 SXM 80GB $7.60
H100 (80 GB) 8Γ— 8Γ— H100 SXM 80GB $13.60
H200 (141 GB) 8Γ— 8Γ— H200 SXM 141GB $18.20

Pros: Reliable, predictable pricing, good support
Cons: Limited GPU variety, mostly NVIDIA only

RunPod

GPU Type Specs Price/hr
RTX 4090 (24 GB) 1Γ— RTX 4090 $0.34
A100 (80 GB) 1Γ— A100 SXM $0.99
A100 8Γ— (80 GB) 8Γ— A100 SXM $7.29
H100 8Γ— (80 GB) 8Γ— H100 SXM $11.99
H200 8Γ— (141 GB) 8Γ— H200 SXM $15.99

Pros: Cheapest spot pricing, wide GPU selection, serverless GPU option
Cons: Network performance varies, no guaranteed availability

Vast.ai

Pros: Cheapest prices (p2p marketplace for GPU), enormous variety
Cons: Inconsistent hardware quality, no support, security concerns

CoreWeave

Pros: Premium networking (InfiniBand), purpose-built for LLM training, great for multi-node
Cons: Minimum commitments, less accessible for small projects

JarvisLabs

Pros: Good for single-GPU fine-tuning, RTX 4090s cheap
Cons: Limited multi-node options

7.3 On-Premises Infrastructure

NVIDIA DGX Systems

System GPUs VRAM Price
DGX H100 8Γ— H100 80GB 640 GB ~$300K
DGX B200 8Γ— B200 180GB 1.4 TB ~$500K
DGX A100 8Γ— A100 80GB 640 GB ~$200K (used)

Dell PowerEdge with NVIDIA GPUs

  • PowerEdge R760xa (4Γ— H100/NVIDIA L40S)
  • PowerEdge XE9680 (8Γ— H100)
  • PowerEdge R750xa (4Γ— A100)

Supermicro

  • AS-4125GS-TNRT (8Γ— H100/H200)
  • SYS-421GU-TNXR (4Γ— H100)
  • SYS-420GP-TNR (8Γ— A100)

On-premise Considerations:
- Power: H100 SXM runs at 700W per GPU; 8Γ— H100 system = ~7–10 kW
- Cooling: Liquid cooling recommended for H100 clusters
- Networking: InfiniBand NDR400 (400 Gbps) for multi-node training
- Rack space: DGX H100 is 6U; expect 10+ racks for a full cluster
- Maintenance: Driver updates, hardware failures, cooling system upkeep

7.4 Spot / Preemptible Instances

Spot instances can reduce GPU costs by 60–90% but introduce interruption risk.

Mitigation Strategies:

Strategy Description Overhead
Checkpointing Save checkpoints every N steps (frequent) Storage cost, ~30s per save
Spot-to-ondemand fallback Switch to on-demand when spot is reclaimed Higher cost on last attempt
Multi-region Spread across regions for more spot capacity Data transfer costs
Model sharding If one GPU is reclaimed, stop all (FSDP/ZeRO) Wasted compute on remaining
Short training jobs Keep training time < 1 hour per run Overhead of frequent restarts

Spot pricing (example, AWS us-east-1):
| Instance | On-Demand/hr | Spot/hr (avg) |
|---|---|---|
| g5.12xlarge (4Γ— A10G) | $6.12 | $1.84 |
| p4d.24xlarge (8Γ— A100) | $37.69 | $11.30 |
| p5.48xlarge (8Γ— H100) | $132.10 | $39.63 |

7.5 Multi-GPU Training Strategies

DeepSpeed (ZeRO)

ZeRO (Zero Redundancy Optimizer) partitions optimizer states, gradients, and parameters across GPUs.

ZeRO Stages:

Stage Partitions Memory Savings Comm Overhead Best For
ZeRO-1 Optimizer states only ~4x Low Small models, small GPU count
ZeRO-2 Optimizer states + gradients ~8x Medium Most 7B–13B fine-tuning
ZeRO-3 Optimizer states + gradients + params ~16x~Nd High Large models (30B+), memory-bound
ZeRO-3 + offload CPU/NVMe offloading of params Near-infinite Very High Models too large for GPU memory

ZeRO Configuration:

{
  "zero_optimization": {
    "stage": 2,
    "allgather_partitions": true,
    "allgather_bucket_size": 500000000,
    "reduce_scatter": true,
    "reduce_bucket_size": 500000000,
    "overlap_comm": true,
    "contiguous_gradients": true
  }
}

ZeRO-3 with CPU Offload:

{
  "zero_optimization": {
    "stage": 3,
    "offload_optimizer": {
      "device": "cpu",
      "pin_memory": true
    },
    "offload_param": {
      "device": "cpu",
      "pin_memory": true
    },
    "overlap_comm": true,
    "contiguous_gradients": true,
    "sub_group_size": 100000000000,
    "stage3_max_live_parameters": 1000000000,
    "stage3_max_reuse_distance": 1000000000,
    "stage3_gather_16bit_weights_on_model_save": true
  }
}

FSDP (Fully Sharded Data Parallelism)

FSDP is PyTorch's native sharded training, conceptually similar to ZeRO-3.

from torch.distributed.fsdp import (
    FullyShardedDataParallel as FSDP,
    ShardingStrategy,
    MixedPrecision,
)
from torch.distributed.fsdp.wrap import transformer_auto_wrap_policy

fsdp_config = {
    "sharding_strategy": ShardingStrategy.FULL_SHARD,  # FULL_SHARD, HYBRID_SHARD, NO_SHARD
    "mixed_precision": MixedPrecision(
        param_dtype=torch.bfloat16,
        reduce_dtype=torch.float32,
        buffer_dtype=torch.bfloat16,
    ),
    "auto_wrap_policy": transformer_auto_wrap_policy,
    "backward_prefetch": BackwardPrefetch.BACKWARD_PRE,
    "limit_all_gathers": True,
    "use_orig_params": True,
}

FSDP vs DeepSpeed ZeRO:

Feature FSDP DeepSpeed ZeRO
Framework Native PyTorch Microsoft DeepSpeed
ZeRO stage FULL_SHARD = ZeRO-3 ZeRO 1/2/3
HYBRID_SHARD Yes Yes (ZeRO-3++)
CPU offload Yes Yes (optimizer + params)
NVMe offload No Yes
Overlap comm Limited Advanced
Ease of use Easier (less config) More config, more control
Performance Good Often better tuned
Community Growing Mature

Tensor Parallelism

Splits individual layers across GPUs (within a node for fast interconnects):

Large Matrix Multiplication:
Wx = [W₁; Wβ‚‚; ...; Wβ‚™] x β†’...

8. Tools

8.1 Axolotl

Axolotl is the most popular configuration-driven LLM fine-tuning framework. It supports almost all open-source models and PEFT methods.

YAML Configuration:

base_model: meta-llama/Llama-2-7b-hf
model_type: LlamaForCausalLM
tokenizer_type: LlamaTokenizer

load_in_8bit: false
load_in_4bit: true
strict: false

datasets:
  - path: ./data/train.jsonl
    ds_type: json
    type: sharegpt
    conversation: llama-2

dataset_prepared_path: ./processed_data
val_set_size: 0.1
output_dir: ./lora-out

sequence_len: 2048
sample_packing: false

lora_r: 16
lora_alpha: 32
lora_dropout: 0.05
lora_target_modules:
  - q_proj
  - v_proj
  - k_proj
  - o_proj
  - gate_proj
  - up_proj
  - down_proj

lora_modules_to_save:
  - embed_tokens
  - lm_head

train_on_inputs: false
group_by_length: false
bf16: auto
fp16: false
tf32: false

gradient_checkpointing: true
early_stopping_patience: 3
gradient_accumulation_steps: 4
per_device_train_batch_size: 4
per_device_eval_batch_size: 4
num_epochs: 3
optimizer: adamw_torch
lr_scheduler: cosine
learning_rate: 2e-4
warmup_ratio: 0.03

deepspeed: ./deepspeed_config.json  # Optional
fsdp: false

Supported Models:
- Llama 1/2/3/3.1
- Mistral, Mixtral
- Qwen 1/2/2.5
- Gemma 1/2
- Falcon
- Phi 1/2/3
- DeepSeek, DeepSeek-V2
- Yi, Yi-1.5
- DBRX
- Command-R
- And many more

Dataset Formats Supported: Alpaca, ShareGPT, ChatML, messages, raw text, JSONL, Parquet

Training Entry:

# Single GPU
accelerate launch -m axolotl.cli.train config.yml

# Multi-GPU
deepspeed --num_gpus 8 train.py --config config.yml

8.2 Unsloth

Unsloth optimizes memory and speed for LoRA/QLoRA training through custom CUDA kernels and optimized gradient checkpointing.

Key Optimizations:
- Custom attention kernels: 2x faster than vanilla implementation
- Optimized gradient checkpointing: Selective checkpointing reduces memory by 50% with minimal speed loss
- 4-bit optimizations: Faster NF4 quantization and dequantization
- Memory tracking: Built-in memory usage reporting

Memory Reductions:

Model Standard QLoRA Unsloth QLoRA Savings
Llama 3 8B ~16 GB ~12 GB 25%
Mistral 7B ~14 GB ~10 GB 29%
Gemma 7B ~14 GB ~11 GB 21%
Llama 3 70B ~72 GB ~56 GB 22%

Usage:

from unsloth import FastLanguageModel
import torch

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name="meta-llama/Llama-2-7b-hf",
    max_seq_length=2048,
    dtype=torch.bfloat16,
    load_in_4bit=True,
)

model = FastLanguageModel.get_peft_model(
    model,
    r=16,
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
    lora_alpha=16,
    lora_dropout=0,
    bias="none",
    use_gradient_checkpointing="unsloth",  # Enable Unsloth's optimized checkpointing
    random_state=42,
    use_rslora=False,
    loftq_config=None,
)

# Standard HuggingFace trainer interface
from transformers import TrainingArguments
from trl import SFTTrainer

trainer = SFTTrainer(
    model=model,
    tokenizer=tokenizer,
    train_dataset=dataset,
    args=TrainingArguments(
        output_dir="./output",
        per_device_train_batch_size=2,
        gradient_accumulation_steps=4,
        warmup_steps=5,
        max_steps=100,
        learning_rate=2e-4,
        fp16=not torch.cuda.is_bf16_supported(),
        bf16=torch.cuda.is_bf16_supported(),
        logging_steps=1,
        optim="adamw_8bit",
        weight_decay=0.01,
        lr_scheduler_type="linear",
        seed=3407,
    ),
)
trainer.train()

8.3 TRL (Transformer Reinforcement Learning)

TRL provides trainers for various alignment methods.

SFTTrainer (Supervised Fine-Tuning)

from trl import SFTTrainer

trainer = SFTTrainer(
    model=model,
    tokenizer=tokenizer,
    train_dataset=dataset,
    dataset_text_field="text",
    max_seq_length=2048,
    args=TrainingArguments(
        output_dir="./sft-output",
        per_device_train_batch_size=4,
        gradient_accumulation_steps=4,
        learning_rate=2e-4,
        num_train_epochs=3,
        fp16=True,
        logging_steps=10,
    ),
)
trainer.train()

Packing: TRL supports packing multiple short sequences into one training example to improve throughput:

SFTTrainer(..., packing=True)

DPOTrainer (Direct Preference Optimization)

DPO eliminates the need for a separate reward model by directly optimizing the policy on preference pairs:

from trl import DPOTrainer

dpo_trainer = DPOTrainer(
    model=model,
    ref_model=ref_model,
    tokenizer=tokenizer,
    train_dataset=preference_dataset,
    args=TrainingArguments(
        output_dir="./dpo-output",
        per_device_train_batch_size=4,
        gradient_accumulation_steps=4,
        learning_rate=1e-6,
        max_steps=1000,
        fp16=True,
    ),
    beta=0.1,  # KL penalty coefficient
)
dpo_trainer.train()

Dataset Format (DPO):

{
  "prompt": "Explain quantum computing",
  "chosen": "Quantum computing leverages quantum mechanical phenomena..."...

9. Hyperparameter Tuning

9.1 Learning Rate

Learning rate is the most impactful hyperparameter in fine-tuning.

Scheduling Strategies:

Schedule Description Best For
Cosine LR decreases following cosine curve from max to min General purpose, smooth convergence
Linear Linear decay to 0 Short training runs, simple tasks
Constant Fixed LR throughout training Very short runs, minimal adaptation
Constant with warmup Linear warmup then constant Stable training with aggressive LR
Cosine with restarts Cyclical cosine annealing Escaping local minima, multi-task
Inverse square root LR ∝ 1/√t Very long training runs

Recommended Defaults:

Setting Value
Learning rate (LoRA, 7B) 2e-4
Learning rate (LoRA, 13B) 1e-4
Learning rate (LoRA, 70B) 5e-5
Learning rate (Full FT, 7B) 1e-5
Learning rate (Full FT, 13B) 5e-6
Learning rate (Full FT, 70B) 2e-6
Warmup ratio 0.03 (3% of total steps)
Schedule Cosine

LR Range Guidelines:

LoRA:    1e-5 to 5e-4 (sweet spot: 1e-4 to 2e-4)
Full FT: 5e-6 to 5e-5 (sweet spot: 1e-5)
DPO:     1e-7 to 1e-6 (sweet spot: 5e-7)

9.2 Batch Size

Terminology:

  • Per-device batch size: Samples per GPU per step
  • Gradient accumulation steps: Accumulate gradients over N steps before applying update
  • Effective batch size: Per-device Γ— GPUs Γ— gradient accumulation steps

Calculations:

Effective batch size = per_device_train_batch_size Γ— num_gpus Γ— gradient_accumulation_steps

Example:

per_device_train_batch_size: 4
gradient_accumulation_steps: 8
num_gpus: 8
# Effective: 4 Γ— 8 Γ— 8 = 256 samples per update

Batch Size Guidelines:

Model Size Min Batch Recommended Max Batch
7B 32 128 1024
13B 16 64 512
34B 8 32 256
70B 4 16 128
180B 2 8 64

Effects of Batch Size:
- Too small: Noisy gradients, unstable training, poor generalization
- Too large: Smooth gradients, but wall-clock time per epoch increases; may converge to sharp minima

Scaling Laws (Batch Size):
- Double batch size β†’ halve learning rate for similar training dynamics
- Maximum useful batch size β‰ˆ 0.1 Γ— dataset size (for most tasks)

9.3 Epoch Count vs Tokens Seen

The number of training epochs depends on dataset size and the amount of repetition desired.

Dataset Size Typical Epochs Total Tokens Seen (7B model, 100M dataset)
1K examples 10–20 200M–400M tokens
10K examples 5–10 500M–1B tokens
100K examples 2–5 2B–5B tokens
1M+ examples 1–3 10B–30B tokens

Rule of Thumb: Train until validation loss plateaus. For LoRA, this is typically 1–5 epochs. For full fine-tuning, 1–3 epochs is usually sufficient and more can cause overfitting.

Token Budget Monitoring:

total_tokens = 0
for epoch in range(num_epochs):
    for batch in dataloader:
        total_tokens += batch['input_ids'].numel()

# Monitor tokens seen vs model size
tokens_per_param_ratio = total_tokens / model_params
# Good: 20–200 tokens per parameter (LoRA)
# Good: 100–500 tokens per parameter (full FT)

9.4 LoRA Rank

See Section 3.1 for detailed rank recommendations.

Tuning Approach:
1. Start with r=8 or r=16
2. Monitor validation loss β€” if underfitting, double the rank
3. If overfitting (train loss << val loss), halve the rank or increase dropout
4. For very large datasets (100K+), consider r=32 or r=64

Rank Scaling:

Compute budget β‰ˆ O(r Γ— (d + k)) where d, k are weight matrix dimensions
Doubling rank β†’ ~2x parameter count, ~2x compute, ~1.1–1.3x quality

9.5 LoRA Alpha Scaling

Alpha controls the magnitude of the adapter update:

  • Ξ± = r (default): Unit scaling
  • Ξ± = 2r: Stronger adapter influence
  • Ξ± = r/2: Weaker adapter influence

Tuning Alpha:
- If model is not adapting enough (similar to base): increase Ξ±/r ratio
- If training is unstable: decrease Ξ±/r ratio
- If catastrophic forgetting: decrease Ξ±/r ratio
- Common range: Ξ± = 8 to 128, r = 4 to 64

9.6 Target Modules Selection

See Section 3.1 for target module recommendations.

Module Selection Strategy:
1. Start with q_proj, v_proj
2. Evaluate: if quality is insufficient, add k_proj, o_proj
3. If still insufficient, add MLP: gate_proj, up_proj, down_proj
4. Monitor: each doubling of modules roughly doubles parameter count

Module Impact by Architecture:

Architecture Most Impactful Modules Additional Modules
Llama/Mistral q_proj, v_proj, gate_proj o_proj, k_proj, up_proj, down_proj
GPT-NeoX query, value, dense_h_to_4h attention.output, dense_4h_to_h
Falcon query, value, dense attention_output, dense_4h_to_h
CodeGen qkv_proj, out_proj fc_in, fc_out
BLOOM query_key_value, dense dense_h_to_4h, dense_4h_to_h

9.7 Weight Decay

Weight decay acts as L2 regularization on the adapter weights.

Setting Effect
0.0 No regularization (fast training, risky for small data)
0.01 Light regularization (default for most tasks)
0.1 Strong regularization (small datasets, overfitting)
1.0 Very strong (rarely used)

Recommendation: 0.01 for LoRA fine-tuning with 1K+ examples. Increase to 0.1 for <500 examples.

9.8 AdamW Betas and Epsilon

Default AdamW Parameters:

optimizer = torch.optim.AdamW(
    model.parameters(),
    lr=2e-4,
    betas=(0.9, 0.999),  # Default: (0.9, 0.999)
    eps=1e-8,             # Default: 1e-8
    weight_decay=0.01,
)

When to Tune Betas:
- Spiky loss: Increase Ξ²β‚‚ to 0.9999 (smoother but slower adaptation)
- Slow convergence: Decrease β₁ to 0.85 (more weight on recent gradients)
- Small batch training: Consider β₁=0.95, Ξ²β‚‚=0.999 (more stable)

When to Tune Epsilon:
- Training instability: Increase Ξ΅ to 1e-7 or 1e-6
- Mixed precision issues: Ξ΅ = 1e-4 or 1e-5 for fp16 training
- Convergence plateaus: Ξ΅ = 1e-8 is usually fine

9.9 LoRA Dropout

See Section 3.1 for dropout recommendations.

Tuning Dropout Together with Rank:

Low rank + low dropout:     Under-parameterized, might underfit
Low rank + high dropout:    Too constrained, won't learn
High rank + low dropout:    Overfit risk
High rank + high dropout:   Good for small data

10. Training Stability

10.1 Loss Spikes

Loss spikes during training can derail fine-tuning. Common causes and solutions:

Cause Symptom Fix
Data quality issue Isolated spike in one batch Detect and remove bad data point
Learning rate too high Gradual rise after initial drop Reduce LR, increase warmup
Batch with outlier length Spike on long sequences Gradient clipping, sort by length
Numerical instability Loss β†’ NaN or Inf Use bf16 instead of fp16, increase epsilon
Optimizer state corruption Spikes at resume Clear optimizer state on resume
Data ordering bias Periodic spikes Shuffle data before each epoch
LoRA rank too high Oscillating loss Reduce rank or increase dropout

Gradient Clipping:

# In TrainingArguments
args = TrainingArguments(
    max_grad_norm=1.0,  # Default: clip gradients to max L2 norm of 1.0
)

Detection and Recovery:

def detect_loss_spike(loss_history, threshold=3.0, window=10):
    if len(loss_history) < window * 2:
        return False

    recent = loss_history[-window:]
    prior = loss_history[-window*2:-window]

    recent_mean = np.mean(recent)
    prior_mean = np.mean(prior)
    prior_std = np.std(prior)

    # Flag if recent mean > prior mean + threshold * prior std
    if recent_mean > prior_mean + threshold * prior_std:
        return True
    return False

When Spikes Occur:
1. Pause training (if automated)
2. Examine the last batch β€” bad data point?
3. Reduce LR by 0.5x or 0.3x and restart from previous checkpoint
4. If persistent: Switch to bf16, increase gradient accumulation, reduce batch size

10.2 Loss Curves Interpretation

Ideal Loss Curve:

Loss
β”‚  \          
β”‚   \         
β”‚    \___     
β”‚        \    
β”‚         \___
β”‚             \__
└─────────────────→ Steps

Common Patterns:

Pattern 1: Healthy training
- Loss drops smoothly, no spikes
- Train and val loss converge
- Val loss eventually plateaus

Pattern 2: Overfitting

Train: \___ (low)
Val:   \___/ (higher, diverging)

Fix: Reduce epochs, increase dropout, add weight decay, reduce rank

Pattern 3: Underfitting

Train: \__________ (still high, still decreasing)
Val:   \__________ (plateau)

Fix: Increase epochs, increase LR, increase rank, reduce dropout

Pattern 4: Learning rate too high

Train: \/\/\/\/\/ (oscillating)

Fix: Reduce LR, increase warmup

Pattern 5: Data quality issues

Train: \___/\___/\ (periodic spikes)

Fix: Remove outlier data, shuffle, gradient clipping

Pattern 6: Catastrophic forgetting

Train: \__  (low on new task)
Benchmark: /β€Ύβ€Ύ (dropping on original task)

Fix: Reduce LR, use replay data, reduce epochs

10.3 Evaluation During Training

Regular evaluation prevents wasted training and enables early stopping.

Evaluation Types:

Type Frequency Metric Cost
Per-step loss Every step Cross-entropy loss None
Perplexity Every N steps (e.g., 100) exp(loss) on eval set ~1 minute
Downstream eval Every N steps (e.g., 500) Task-specific (F1, EM, etc.) 5–30 minutes
Generative eval Every N epochs Human eval, LLM-as-judge 10–60 minutes

Implementation:

from transformers import TrainerCallback

class EvalCallback(TrainerCallback):
    def __init__(self, eval_dataset, tokenizer, every_n_steps=100):
        self.eval_dataset = eval_dataset
        self.tokenizer = tokenizer
        self.every_n_steps = every_n_steps

    def on_step_end(self, args, state, control, **kwargs):
        if state.global_step % self.every_n_steps == 0:
            # Compute perplexity
            model = kwargs['model']
            eval_loader = DataLoader(self.eval_dataset, batch_size=4)

            total_loss = 0
            for batch in eval_loader:
                outputs = model(**batch)
                total_loss += outputs.loss.item()

            avg_loss = total_loss / len(eval_loader)
            perplexity = np.exp(avg_loss)

            self.log({"eval/perplexity": perplexity, "step": state.global_step})

10.4 Checkpointing Strategies

Checkpoint Frequency:

Strategy Frequency Storage Cost Recovery
By step Every N steps (e.g., 100) N Γ— model_size/hour Fine-grained
By epoch Every epoch epoch_count Γ— model_size Coarse
Best N When val loss improves N Γ— model_size Best quality
Time-based Every N hours N Γ— model_size/hour Time-budget aligned

Recommended Enterprise Strategy:

Save every 500 steps (by step)
Keep last 3 checkpoints (disk space management)
Save best checkpoint (by validation loss)
args = TrainingArguments(
    save_strategy="steps",
    save_steps=500,
    save_total_limit=3,  # Keep only 3 most recent
    load_best_model_at_end=True,
    metric_for_best_model="eval_loss",
    greater_is_better=False,
)

Checkpoint Structure:

checkpoint-500/
β”œβ”€β”€ adapter_config.json    # LoRA config
β”œβ”€β”€ adapter_model.safetensors  # LoRA weights
β”œβ”€β”€ training_args.bin      # Training arguments snapshot
β”œβ”€β”€ optimizer.pt           # Optimizer state (for resume)
β”œβ”€β”€ scheduler.pt           # LR scheduler state
β”œβ”€β”€ trainer_state.json     # Step, epoch, best metric
β”œβ”€β”€ rng_state.pth          # Random state for reproducibility
└── scaling.pt             # QLoRA scaling factors (if applicable)

10.5 Resuming from Checkpoint

# Resume training
trainer.train(resume_from_checkpoint=True)
# Or from specific checkpoint:
trainer.train(resume_from_checkpoint="./checkpoint-500")

# The trainer will:
# 1. Load model weights
# 2. Load optimizer and scheduler state
# 3. Skip already-processed data
# 4. Continue from save step

Issues When Resuming:
- Dataset shuffle: Will shuffle differently unless you set a seed for each run
- Data loading: If dataset changed, resume may skip wrong indices
- Optimizer state: Load optimizer.pt to avoid starting from fresh momentum
- LR scheduler: LR will jump if not properly restored
- Mixed precision: Loss scaler state must be restored for fp16


11. Evaluation

11.1 Holdout Sets Creation

Temporal Split (Recommended for Enterprise):

# Sort by timestamp, use oldest 80% for train, newest 10% for val, newest 10% for test
dataset_sorted = sorted(dataset, key=lambda x: x['timestamp'])
n = len(dataset_sorted)
train = dataset_sorted[:int(n*0.8)]
val = dataset_sorted[int(n*0.8):int(n*0.9)]
test = dataset_sorted[int(n*0.9):]

Stratified Split:

from sklearn.model_selection import StratifiedShuffleSplit

sss = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=42)
for train_idx, test_idx in sss.split(X, strata):
    train = [dataset[i] for i in train_idx]
    test = [dataset[i] for i in test_idx]

Cross-Validation (for small datasets):

from sklearn.model_selection import KFold

kf = KFold(n_splits=5, shuffle=True, random_state=42)
fold_metrics = []

for fold, (train_idx, val_idx) in enumerate(kf.split(dataset)):
    train_data = [dataset[i] for i in train_idx]
    val_data = [dataset[i] for i in val_idx]

    # Train on fold
    metrics = train_and_evaluate(train_data, val_data)
    fold_metrics.append(metrics)

mean_metrics = {k: np.mean([m[k] for m in fold_metrics]) for k in fold_metrics[0]}

11.2 Domain-Specific Metrics

General Metrics:
- Perplexity
- Accuracy
- F1 Score
- BLEU (generation)
- ROUGE (summarization)
- METEOR
- BERTScore

Legal Domain:
- Citation accuracy (% of citations correctly formatted)
- Statute relevance (precision/recall of cited statutes)
- Legal reasoning coherence (expert rating, 1–5)
- Hallucination rate of legal facts

Medical Domain:
- ICD-10 code assignment accuracy
- Drug name accuracy (% correctly named)
- Clinical note completeness (expert checklist)
- Safety flag rate (incorrect medical advice)
- HIPAA compliance (PII presence in generated text)

Finance Domain:
- Numerical calculation accuracy (% correct)
- Financial ratio calculation error
- Sentiment alignment with ground truth (finance-specific sentiment)
- SEC filing format compliance

Code Domain:
- Pass@k (functional correctness)
- Syntax error rate
- Test coverage of generated code
- Code style compliance (PEP8, etc.)
- Security vulnerability rate (SAST scan)

Customer Support:
- CSAT score prediction (agreement with actual CSAT)
- First Contact Resolution accuracy
- Intent classification accuracy
- Escalation prediction precision/recall
- Brand voice compliance (expert rating)

11.3 Human Evaluation Protocol

Protocol Design:

  1. Sample selection: Random sample of 100–500 generations per model variant
  2. Blinding: Remove model identifiers, shuffle outputs
  3. Evaluators: 3+ domain experts per sample
  4. Criteria: Task-specific rubric (1–5 scale per criterion)
  5. Calibration: Gold-standard examples with known scores
  6. Quality control: Inter-annotator agreement monitoring

Sample Rubric (Legal Domain):

Criteria                   1 (Poor)    3 (Good)    5 (Excellent)
Accuracy of legal facts    >3 errors   0-1 errors  Perfect
Citation format            None cited  Partial     Complete & correct
Reasoning quality          Illogical   Sound       Compelling
Helpfulness               Unhelpful   Somewhat    Highly actionable
Safety (no hallucination)  Hallucinates Minor issues  No issues

Typical Enterprise Human Eval Cost:

100 samples Γ— 3 evaluators Γ— 5 minutes each Γ— $50/hr = ~$125
1,000 samples Γ— 3 evaluators Γ— 5 min Γ— $50/hr = ~$1,250

11.4 A/B Testing

Online A/B Testing for LLM Deployment:

  1. Traffic split: 50% control (baseline), 50% treatment (fine-tuned model)
  2. Metric collection: User engagement, task completion, latency, feedback ratings
  3. Statistical significance: Chi-squared test, t-test, or Bayesian A/B test
  4. Minimum sample size:
n = (Z_Ξ±/2 + Z_Ξ²)Β² Γ— (p₁(1-p₁) + pβ‚‚(1-pβ‚‚)) / (pβ‚‚ - p₁)Β²
Example: 5% improvement, 80% power, 95% confidence β†’ ~3,000 samples per variant

Implementation:

from scipy import stats

def ab_test(control_outcomes, treatment_outcomes):
    """Two-proportion z-test"""
    n_control = len(control_outcomes)
    n_treatment = len(treatment_outcomes)

    p_control = sum(control_outcomes) / n_control
    p_treatment = sum(treatment_outcomes) / n_treatment

    p_pool = (sum(control_outcomes) + sum(treatment_outcomes)) / (n_control + n_treatment)

    se = np.sqrt(p_pool * (1 - p_pool) * (1/n_control + 1/n_treatment))
    z = (p_treatment - p_control) / se

    p_value = 2 * (1 - stats.norm.cdf(abs(z)))

    return {
        'control_rate': p_control,
        'treatment_rate': p_treatment,
        'lift': (p_treatment - p_control) / p_control,
        'p_value': p_value,
        'significant': p_value < 0.05,
    }

11.5 Regression Testing

Maintain a regression test suite to catch quality regressions when updating models:

REGRESSION_TESTS = [
    {
        "name": "citation_format",
        "input": "What is the holding in Miranda v. Arizona?",
        "expected_pattern": r"\d+ U\.S\. \d+",  # Must cite US Reports
        "metric": "regex_match",
    },
    {
        "name": "no_pii_leak",
        "input": "Summarize this patient: John Doe, SSN 123-45-6789",
        "expected_pattern": r"(?i)(?:\[REDACTED\]|<PERSON>|<SSN>)",
        "metric": "regex_match",
    },
    {
        "name": "code_compiles",
        "input": "Write a Python function to sort a list",
        "metric": "code_compiles",
    },
]

Regression Suite Pipeline:
1. Run suite against baseline model β†’ store ...

12. Deployment

12.1 Merging LoRA Adapters into Base Model

For production deployment, merging LoRA weights into the base model eliminates adapter loading overhead:

from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

# Load base model
base_model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-7b-hf",
    torch_dtype=torch.bfloat16,
    device_map="auto",
)

# Load LoRA adapter
lora_model = PeftModel.from_pretrained(base_model, "./lora-checkpoint-500")

# Merge weights into base model
merged_model = lora_model.merge_and_unload()

# Save merged model
merged_model.save_pretrained("./merged-model")
tokenizer.save_pretrained("./merged-model")

Storage Comparison:

Format 7B Base 7B + LoRA (r=16) 7B Merged
FP16 14 GB 14 GB + 16 MB 14 GB
4-bit 4 GB 4 GB + 16 MB 4 GB

When to Merge vs Keep Separate:

Scenario Merge Keep Separate
Single adapter deployment βœ“
Multiple adapter routing βœ“
Maximum inference throughput βœ“
Quick adapter switching βœ“
GPU memory constrained βœ“ (one forward pass)
Hot-swapping βœ“

12.2 Serving Multiple Adapters

vLLM LoRA Adapter Routing

vLLM supports serving multiple LoRA adapters simultaneously with dynamic routing:

from vllm import LLM, SamplingParams

# Initialize with base model + max LoRA config
llm = LLM(
    model="meta-llama/Llama-2-7b-hf",
    enable_lora=True,
    max_loras=8,           # Max concurrent adapters
    max_lora_rank=64,      # Max rank among all adapters
    # LoRA modules used across all adapters
    lora_extra_vocab_size=256,
)

# Load adapters
llm.load_lora(
    "legal-v1",
    lora_path="./adapters/legal-v1",
)
llm.load_lora(
    "medical-v1",
    lora_path="./adapters/medical-v1",
)

# Route requests to specific adapter
prompts = [
    ("What is the holding in Marbury v. Madison?", "legal-v1"),
    ("Diagnose based on these symptoms...", "medical-v1"),
]

sampling_params = SamplingParams(temperature=0.1, max_tokens=512)

# vLLM automatically routes each prompt to its specified adapter
outputs = llm.generate(
    [p[0] for p in prompts],
    sampling_params,
    lora_request=[p[1] for p in prompts],  # Per-prompt adapter routing
)

vLLM Adapter Hot-Swapping:

# Start vLLM server with LoRA support
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-2-7b-hf \
    --enable-lora \
    --max-loras 8 \
    --max-lora-rank 64

# Hot-swap: update an adapter without restarting
curl http://localhost:8000/v1/load_lora_adapter \
    -H "Content-Type: application/json" \
    -d '{"lora_name": "legal-v2", "lora_path": "./adapters/legal-v2"}'

# Then route traffic to new adapter
curl http://localhost:8000/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "legal-v2",
        "messages": [{"role": "user", "content": "Explain contract law"}]
    }'

Tensor Parallelism with LoRA

When using tensor parallelism (model parallelism across GPUs), LoRA adapters must be sharded consistently with the base model:

from vllm import LLM

llm = LLM(
    model="meta-llama/Llama-2-70b-hf",
    tensor_parallel_size=4,  # 4 GPUs
    enable_lora=True,
    max_loras=4,
)

Key Considerations for TP + LoRA:
- LoRA weights are sharded across GPUs along with base weights
- Each GPU holds 1/TP_size of each adapter
- Adapter loading/unloading must happen on all GPUs

12.3 Adapter Versioning

Versioning Schema:

adapters/
β”œβ”€β”€ legal-v1.0.0/  # Major.Minor.Patch
β”‚   β”œβ”€β”€ adapter_config.json
β”‚   └── adapter_model.safetensors
β”œβ”€β”€ legal-v1.1.0/
β”‚   β”œβ”€β”€ adapter_config.json
β”‚   └── adapter_model.safetensors
β”œβ”€β”€ legal-v2.0.0/
β”‚   β”œβ”€β”€ adapter_config.json
β”‚   └── adapter_model.safetensors
└── manifest.json

Manifest Example:

{
  "adapters": [
    {
      "name": "legal-v1.0.0",
      "base_model": "meta-llama/Llama-2-7b-hf",
      "created": "2024-06-01T10:00:00Z",
      "dataset": "legal-corpus-v1",
      "metrics": {"f1": 0.92, "exact_match": 0.87},
      "status": "deprecated",
      "checksum": "sha256:abc123..."
    },
    {
      "name": "legal-v1.1.0",
      "base_model": "meta-llama/Llama-2-7b-hf",
      "created": "2024-06-15T14:30:00Z",
      "dataset": "legal-corpus-v2",
      "metrics": {"f1": 0.94, "exact_match": 0.89},
      "status": "active",
      "checksum": "sha256:def456..."
    }
  ]
}

12.4 Model Registry

Enterprise Model Registry (using MLflow example):

import mlflow

mlflow.set_tracking_uri("http://mlflow-server:5000")

with mlflow.start_run(run_name="llama-7b-legal-v2"):
    # Log parameters
    mlflow.log_params({
        "base_model": "meta-llama/Llama-2-7b-hf",
        "lora_r": 16,
        "lora_alpha": 32,
        "learning_rate": 2e-4,
        "batch_size": 128,
        "dataset": "legal-corpus-v2",
        "num_epochs": 3,
    })

    # Log metrics
    mlflow.log_metrics({
        "eval_loss": 0.85,
        "eval_accuracy": 0.94,
        "eval_f1": 0.92,
    })

    # Log model
    mlflow.transformers.log_model(
        transformers_model={"model": merged_model, "tokenizer": tokenizer},
        artifact_path="model",
        registered_model_name="llama-7b-legal",
    )

# Transition model stage
from mlflow.tracking import MlflowClient
client = MlflowClient()

client.transition_model_version_stage(
    name="llama-7b-legal",
    version=2,
    stage="Staging",  # Options: None, Staging, Production, Archived
)

12.5 Canary Deployments

Canary Deployment Strategy for LLM Adapters:

Phase 1: Internal (5% traffic, dev team only)
   ↓ (monitor for

πŸ“„ AI Infrastructure: Compute, Storage, and Networking β€” 103 lines

AttentionDeploymentFine-tuningGPTGPUInferenceLLMPPOQuantizationRAG

1. Introduction

AI infrastructure is the physical and virtual foundation for training and deploying ML models. It encompasses GPUs, storage systems, networking, and orchestration software. As models grow to trillion-plus parameters, infrastructure design becomes a critical competitive advantage.


2. GPU Architecture

2.1 Current Generation (2025-2026)

GPU Memory BW FP8 TFLOPS Interconnect Power
H100 SXM 80GB HBM3 3.35 TB/s 1,979 NVLink 4 (900 GB/s) 700W
H200 141GB HBM3e 4.8 TB/s 1,979 NVLink 4 700W
B200 192GB HBM3e 8 TB/s 4,500 NVLink 5 (1.8 TB/s) 1,000W
MI300X (AMD) 192GB HBM3 5.3 TB/s 1,307 Infinity Fabric 750W

2.2 Bottleneck: Memory Bandwidth

For inference, the bottleneck is memory bandwidth (loading model weights) not compute (matrix multiplication). This is why:
- Quantization helps (less data to load)
- Batch processing helps (amortize loading cost)
- Speculative decoding helps (fewer generations)


3. Training Infrastructure

3.1 Cluster Design

Scale GPUs Model Size Training Time Example
Single 1-8 <7B Hours Fine-tuning
Small 8-64 7-70B Days LLaMA 70B
Medium 64-1024 70-400B Weeks GPT-4, Claude
Large 1024-16384 400B-1T+ Months Frontier models
Frontier 16K-100K+ >1T Months Next-gen systems

3.2 Parallelism Strategies

Strategy Split Communication Best For
Data Parallel (DP) Data across GPUs Gradient sync Small models, large data
Tensor Parallel (TP) Layers across GPUs High (NVLink) Large models, single node
Pipeline Parallel (PP) Layer groups Moderate Cross-node scaling
Expert Parallel (EP) MoE experts All-to-all Mixture of Experts
Sequence Parallel (SP) Sequence dimension High Long sequences
FSDP (Fully Sharded DP) Params + optimizer states Moderate Training efficiency

4. Inference Infrastructure

4.1 Serving Comparison (see: [05-Enterprise/01-Enterprise-AI-Deployment.md] Β§4)

  • vLLM: Best throughput (PagedAttention)
  • TGI: Best Hugging Face integration
  • Triton: Best multi-framework support
  • TensorRT-LLM: Best NVIDIA-optimized performance

4.2 Inference Hardware

  • Cloud GPUs: A10G (24GB), L4 (24GB), L40S (48GB), A100 (80GB), H100 (80GB)
  • Edge/Custom: Apple M-series Neural Engine, Google TPU v5p, AWS Trainium2
  • Inference ASICs: Groq LPU, Cerebras Wafer-Scale, d-Matrix

5. Storage for AI

Tier Type Example Speed Cost/GB
Hot NVMe SSD 8x Samsung PM9A3 20 GB/s ~$0.10
Warm Object storage S3, GCS 1-10 GB/s ~$0.02
Cold Tape/Archive Glacier, Azure Archive Minutes ~$0.001
ML Cache Distributed cache Alluxio, JuiceFS Varies Varies

6. Networking

Interconnect Speed Topology Latency
NVLink 4 900 GB/s (GPU-GPU) Fully connected <1Β΅s
NVLink 5 1.8 TB/s (GPU-GPU) Fully connected <1Β΅s
InfiniBand NDR 400 400 Gb/s (Node-Node) Fat tree 1-2Β΅s
InfiniBand XDR 800 Gb/s (Node-Node) Fat tree 1-2Β΅s
RoCE v2 200-400 Gb/s Various 3-5Β΅s
Ethernet 100-800 Gb/s Various 5-50Β΅s

AI Library of Alexandria β€” Enterprise Β· 3 Docs Β· 4,493 Lines

Home Β· June 2026