Command Palette

Search for a command to run...

0

From Rules to Hybrid ML: SAG Auto-Tuning and Optimizer Practice

> SAG retrieval has 7 hyperparameters — manual tuning is not feasible. We solved this with a three-layer progressive optimization approach.

SAG retrieval has 7 hyperparameters — manual tuning is not feasible. We solved this with a three-layer progressive optimization approach.

1. SAG Auto-Tuning: Three-Layer Architecture

Layer 1: Rule-based Search (Base Layer)
│  Grid Search / Random Search
│  Pure program, no LLM required
│  Traverse parameter space → Evaluate → Output optimal
│
Layer 2: Bayesian Optimization (Advanced Layer)
│  Optuna Bayesian search
│  Adaptively adjust search direction based on historical evaluation results
│  ~50 trials to find near-optimal solution
│
Layer 3: LLM Agent (High-Level Layer)
   LLM analyzes tuning history → generates insights → proposes new parameter combinations
   "Last time vector_weight=0.6 caused a recall drop, possibly because..."
   → Generate new suggestion → Evaluate → Loop

Evaluation Metrics

def evaluate_config(config: dict, max_cases: int = 100) -> dict:
    """Run eval cases for a single parameter configuration and compute recall."""
    params = SAGParams.from_dict(config)
    hits = 0
    for case_id in case_ids:
        results = sag_retrieve(query, top_k=10, params=params)
        retrieved = {r.chunk_id for r in results}
        if retrieved & expected_ids:
            hits += 1
    return {"recall": hits / len(case_ids), "config": config, ...}

Tuning History Persistence

// reports/sag_tuning/history.jsonl
{"trial": 1, "config": {"vector_weight": 0.5, ...}, "recall": 0.72, "ts": "..."}
{"trial": 2, "config": {"vector_weight": 0.6, ...}, "recall": 0.68, "ts": "..."}
{"trial": 3, "config": {"structural_base": 0.7, ...}, "recall": 0.78, "ts": "..."}

2. TicketPilot Optimizer: From Rules to Hybrid ML

A concrete application scenario — automated customer service ticket classification (intent / severity / risk):

Initial State: Pure Rule-Based Classification
├─ intent: Keyword matching (8 intent classes)
├─ severity: Derived from risk flag count (LOW/MEDIUM/HIGH)
├─ risk: 5 keywords × 6 risk flags
└─ composite score: 0.624

Optimization Path:
├─ Phase 1: Rule Optimization
│   ├─ Expand risk keywords (21% → 50%+)
│   ├─ Direct severity classification (54% → 65%+)
│   ├─ Confidence threshold fixes
│   └─ Batch optimizer (multiple fixes per round)
│
├─ Phase 2: Lightweight ML
│   ├─ FastText hybrid classifier (intent 61% → 70%+)
│   ├─ External data augmentation (JDDC/COLDataset)
│   └─ NSGA-II multi-objective optimization
│
└─ Phase 3: LLM-Guided
    └─ LLM analyzes error patterns → generates rule variants

Hybrid Classifier Architecture

Input (user text)
    │
    ├─→ Rule Classifier (keyword matching)
    │   └─ confidence_score (based on matched keyword count/weight)
    │
    ├─→ FastText Classifier (subword n-gram)
    │   └─ probability (trained on 400 samples)
    │
    └─→ Ensemble
        ├─ rule_conf > 0.8 → use rule
        ├─ fasttext_prob > 0.7 → use fasttext
        └─ both uncertain → manual review

NSGA-II Multi-Objective Optimization

Simultaneously optimize F1 for 8 intents with no regression constraints:

class TicketPilotRuleOpt(ElementwiseProblem):
    # 8 objectives: 1-F1 for each intent (minimization)
    # Constraints: F1 for each intent ≥ baseline
    # Decision variables: keyword inclusion/exclusion per intent (0/1)
    
    # Results: Pareto front
    # Solution A: intent_1 F1=0.85, intent_2 F1=0.72
    # Solution B: intent_1 F1=0.80, intent_2 F1=0.78
    # → Manual trade-off selection