# Full pipeline diagram (text) ``` ┌──────────────────────────────────────────────────────────────┐ │ STEP 1: DATA (raw Zindi CSVs → AfriE5 retrieval) │ │ │ │ Train.csv Val.csv Test.csv │ │ │ │ │ │ │ └───────┴────────┘ │ │ │ │ │ AfriE5 retrieval (McGill-NLP/AfriE5-Large-instruct) │ │ build_afrie5_k5.py --k=3,5,7 │ │ │ │ │ ┌────────┼────────┐ │ │ ▼ ▼ ▼ │ │ TV_k3.json TV_k5.json TV_k7.json │ │ (train+test, top-K passages per query) │ │ │ │ Fewshot demo prep (top-K similar Q,A from Train+Val) │ │ build_fewshot_train_k{3,4,5,7}.py + test counterparts │ │ │ │ │ ┌────────┼────────┐ │ │ ▼ ▼ ▼ │ │ k3_fewshot k5_fewshot k7_fewshot │ │ │ │ │ v8 prompt swap (replace v1 instruction with v8) │ │ build_v8_k5_fewshot.py │ │ │ │ │ ▼ │ │ k5_fewshot_v8.json │ └──────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────┐ │ STEP 2: TRAIN (13 LoRA adapters) — OPTIONAL for reviewer │ │ │ │ ⚠ Reviewer can SKIP this step — all 19 LoRA adapters │ │ are PRE-TRAINED and shipped in checkpoints// │ │ (~35 GB total, 1.8-2.1 GB per adapter). │ │ │ │ Training recipes (LlamaFactory + DeepSpeed ZeRO-3): │ │ Q3.5-27B base × K=3 v1 (3ep) → ck-1200, ck-1100 │ │ Q3.5-27B base × K=3 v1 (5ep) → ck-1200 │ │ Q3.5-27B base × K=4 v1 (3ep) → ck-1600 │ │ Q3.5-27B base × K=5 V8 (3ep) → ck-1500 │ │ Q3.5-27B base × K=7 v1 (3ep) → ck-1600, ck-1200 │ │ Q3.6-27B base × K=3 v1 (3ep RecA) → ck-1600 │ │ Q3.6-27B base × K=4 v1 (3ep) → ck-1400 │ │ Q3.6-27B base × K=5 v1 (3ep) → ck-1200, ck-1000 │ │ Q3.6-27B base × K=7 V8 (3ep) ⭐ → ck-1600 │ │ Q3-32B base × K=3 v1 (3ep) → ck-1400 │ │ Q3-32B base × K=5 v1 (3ep) → ck-1700 │ │ Q3-32B base × K=7 v1 (3ep) → ck-1600, ck-1200 │ │ + 3 NoFewshots SFT runs (same LoRA recipe, no demos): │ │ Q3.5-27B (5ep ck-2800) qwen35_27b_nofewshots_5ep...yaml │ │ Q3.6-27B (5ep ck-2600) qwen36_27b_nofewshots_5ep...yaml │ │ Q3-32B (4ep ck-6500) qwen3_32b_nofewshots_4ep...yaml │ │ │ │ LoRA: r=128, α=256, dropout=0.05, target=all │ │ LR=2e-4 cosine warmup 5%, bf16, gc=true │ │ eff_bs=64 (per_dev=2, ga=4, GPUs=8) │ │ Wall time: 13 × (~8-14h on 8× H100) sequential │ └──────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────┐ │ STEP 3: PREDICT (19 CSVs from 19 provided LoRA adapters) │ │ │ │ bash scripts/launch_all_predicts.sh │ │ (orchestrator runs all 19 in parallel/sequential) │ │ │ │ For each adapter in checkpoints//: │ │ vllm_predict_extra.py │ │ --base │ │ --adapter checkpoints/ │ │ --rag_test data/msrh_rag_test_k3_AfriE5_TV*.json │ │ --max_lora_rank 128 --max_new 512 │ │ --max_model_len 6144/8192/10240 (per K) --no_think │ │ --temperature 0.0 --best_of 1 │ │ │ │ │ jsonl_rowidx_to_csv.py → candidate_csvs/.csv │ │ │ │ Produces 19 prediction CSVs in candidate_csvs/ │ │ (the folder is empty in the shipped package — they │ │ are GENERATED here from provided checkpoints) │ └──────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────┐ │ STEP 4: ENSEMBLE (V2 medoid_ngram on 19 cands) │ │ │ │ build_ensemble.py │ │ │ │ For each Test row: │ │ 1. Collect 19 candidate answer texts │ │ 2. Compute pairwise ROUGE-1.F + ROUGE-2.F (171 pairs) │ │ 3. For each cand, sum similarity to all others │ │ 4. Pick candidate with HIGHEST sum (medoid) │ │ 5. Use its answer text │ │ │ │ │ ▼ │ │ go.csv │ │ (2618 rows × 4 target columns, all = same medoid pick) │ └──────────────────────────────────────────────────────────────┘ │ ▼ ┌────────────────────┐ │ Submit to Zindi │ │ Public LB 0.7388 │ │ Private LB Top 1🏆│ └────────────────────┘