# Artifact Plan: Optimasi Ekstrim "Bilingual Mega-Sentence" & Pipeline Concurrency

## 1. Judul
**Blueprint Optimasi Kinerja Tinggi: Integrasi Tenacity, ThreadPool, dan The GIL Trap Evasion**

## 2. Tanggal
Minggu, 10 Mei 2026

## 3. Deskripsi
Dokumen ini merupakan cetak biru (*blueprint*) teknis untuk mengoptimalkan kinerja *ingestion pipeline* ("Small-to-Big Retrieval") pada `backend-sre-(Knowledge Extractor)`. Berdasarkan evaluasi beban (*bottlenecks*), waktu eksekusi dokumen sebelumnya tertahan oleh latensi *I/O-bound* (kuota API/sleep) dan jebakan antrean *CPU-bound* (*The GIL Trap*). Cetak biru ini mengusulkan implementasi teknik *Bounded Concurrency*, pengelompokan (*Batching*), dan manajemen pemulihan mundur (*Exponential Backoff*) menggunakan pustaka `tenacity`.

## 4. Metodologi
Pendekatan optimasi ini menggabungkan teknik asinkronisasi I/O dan pembatasan beban API (*Rate Limiting Guard*):
1.  **Tenacity Exponential Backoff:** Mengganti mekanisme `time.sleep()` kotor yang statis dengan mekanisme punggah/mundur eksponensial cerdas dari *library* `tenacity`. Ini diterapkan pada API Embedding (Alibaba DashScope) dan ekstraksi Pilar (OpenRouter).
2.  **API Batching Concurrency (Micro-Scale):** Menggunakan `ThreadPoolExecutor` di dalam `SemanticRetriever._embed_batch` untuk menembakkan potongan permintaan *embedding* secara serentak, bukan serial.
3.  **Pipeline Paralel Berjenjang (Macro-Scale):** Mengubah *loop* utama dokumen di `ingestion.py` untuk mendelegasikan proses *I/O* (Retrieval & LLM) ke sekumpulan benang (*Thread Pool*), namun tetap mengeksekusi ekstraksi Markdown (CPU-Bound, `pymupdf4llm`) secara serial agar tidak memicu rebutan sumber daya yang berujung kelumpuhan CPU.
4.  **Bounded Semaphore Guard:** Membatasi *concurrency* pada API Alibaba menggunakan pengunci global (Semaphore) agar lonjakan benang paralel (*Thread Storm*) tidak memicu hukuman penolakan beruntun (*Rate Limit Exceeded* - HTTP 429).

## 5. Keputusan (Decision Log)
1.  **Paralelisasi LLM & Embedding (Ya):** Memaksimalkan kemampuan asinkronisasi koneksi internet. Karena fungsi ini merupakan hambatan (*bottleneck*) dominan I/O, `ThreadPoolExecutor` sangat dianjurkan.
2.  **Paralelisasi Parsing PDF (Ditolak):** Pembongkaran PDF menjadi Markdown akan tetap dipertahankan pada proses *synchronous main thread*. Python GIL (Global Interpreter Lock) mencegah optimalisasi multithread murni pada eksekusi komputasi (*CPU-bound*), yang malah memperlambat sistem.
3.  **Implementasi Library Tenacity (Ya):** Penjadwalan ulang otomatis tanpa memblokir seluruh jaring antrean (*queue*) wajib diterapkan. Library `tenacity` memastikan algoritma eksponensial dengan komponen *Jitter* menstabilkan permintaan serentak yang gagal di API.

## 6. Alur Diagram
```mermaid
flowchart TD
    subgraph MainThread ["Main Thread (Sequential CPU-Bound)"]
        A[Daftar 10 File PDF] --> B[Ekstrak Markdown via pymupdf4llm]
        B --> C[Pembentukan Chunk Spasial]
        C --> D[Penyimpanan ke Supabase]
    end

    subgraph IOBound ["ThreadPoolExecutor (Parallel I/O-Bound)"]
        D -->|Serahkan Payload| E{"Bounded Semaphore (Max 5)"}
        E --> F[Semantic Retriever - Alibaba API]
        
        subgraph TenacityRetry ["Tenacity Retry + Parallel Batch"]
            F --> F1[Batch 1: 10 teks]
            F --> F2[Batch 2: 10 teks]
            F --> F3[Batch 3: 10 teks]
        end
        
        F1 --> G[Pencarian Top-K dan Deduplikasi]
        F2 --> G
        F3 --> G
        G --> H[OpenRouter LLM Pilar Extraction]
        H -->|Tenacity Retry| I[Injeksi ke Neo4j]
    end
```

## 7. Struktur Folder (Tree)
Pembaruan ini akan terfokus pada skrip yang melayani ekstraksi serta komunikasi LLM/API:
```text
/home/daegir/Documents/PERCOBAAN/backend-sre-(Knowledge Extractor)/
├── requirements.txt             # (TARGET: Tambah 'tenacity')
├── app/
│   └── services/
│       ├── ingestion.py                 # (TARGET: Tenacity & ThreadPool)
│       └── parser/
│           └── semantic_retriever.py    # (TARGET: Parallel Batch & Tenacity)
└── Markdown/
    └── small-to-big-retrieval/
        ├── Plan/
        │   └── optimization-concurrency-plan.md  # File dokumen ini
        └── Log-Execution/               # Untuk pelaporan eksekusi
```

## 8. Asumsi & Scope
*   **Scope In:**
    *   Penambahan modul `tenacity` pada `requirements.txt`.
    *   Pembungkus (*wrapper*) dekorator `@retry` pada fungsi LLM.
    *   Pengelompokan paralel 10-teks menggunakan mekanisme `BoundedSemaphore` pada Alibaba *text-embedding-v3*.
*   **Out of Scope:**
    *   Perubahan basis kode logika sistem Chunk.
    *   Model Embedding Loka (SentenceTransformers).
*   **Asumsi Tsunami Rate Limit:** Tanpa `BoundedSemaphore`, penembakan paralel massal pasti akan mengembalikan Error 429. Semaphore melindungi dari kemungkinan tersebut dengan membatasi *requests-per-second*.

## 9. Konsep Tabel Metriks
Penerapan *Tenacity* dan Eksekutor Paralel diukur berdasarkan pengurangan durasi pemrosesan (eksponensial menurun):

| Metrik | Kondisi Awal (Sequential + Static Sleep) | Target Ekspektasi | Status Perbandingan |
| :--- | :--- | :--- | :--- |
| **Parsing PDF** | Rata-rata 10 - 25 detik / Dokumen | Rata-rata 10 - 25 detik / Dokumen | Konstan (Dibatasi secara *Synchronous*) |
| **Retrieval Embedding** | ~60 - 80 detik / Dokumen | ~5 - 15 detik / Dokumen | Akselerasi Tinggi (Efek Paralel-Batch) |
| **Total Waktu per Dokumen**| 80 - 150 detik | < 45 detik | Memenuhi Syarat SLA |

## 10. Konsep Logika (Lapis Pertahanan & Paralelisasi)
1.  **Global Bounded Semaphore**: Dibuat sebagai benteng untuk mencegah lebih dari *N* jumlah *request* terlempar ke API Alibaba pada detik yang sama di dalam proses `_embed_batch`.
2.  **ThreadPoolExecutor di Main Ingestion**: Mengekstrak *logic* di dalam iterasi *array* PDF menjadi tugas (*task*) yang diajukan (`executor.submit`) sehingga *retrieval* Dokumen-2 dapat berjalan saat Dokumen-1 masih menunggu *respons* LLM.
3.  **Tenacity Decorator**:
    ```python
    @retry(wait=wait_exponential_jitter(initial=1, max=10), stop=stop_after_attempt(5))
    ```
    Diterapkan pada: `embed_text()`, `extract_pillars_with_llm()`, dan `generate_edge_reasoning()`. Jika gagal, fungsi tidak menghentikan keseluruhan sistem melainkan mundur dan mengulang sesuai *jitter* (memberikan selang acak waktu agar *request* paralel tak memadat bersamaan).

## 11. Langkah Implementasi
1.  Melakukan pendaftaran `tenacity` ke dalam `requirements.txt` dan lingkungan virtual (*virtual environment*).
2.  Modifikasi `semantic_retriever.py` dengan penambahan *thread pool* untuk *sub-array batch embedding* dengan penjaga *BoundedSemaphore* statis.
3.  Pembaruan pada `ingestion.py` melalui penggantian perulangan (*loop*) PDF murni menjadi pengaju tugas (*Task Submitter*) paralel dengan `ThreadPoolExecutor`.
4.  Substitusi dari sistem *Retry* manual (kalang *for-try-except-sleep*) dengan pembungkus *decorator* canggih dari `tenacity`.
5.  Uji coba pada beban penuh di mana seluruh file secara bersamaan diekstrak dan didorong ke *Cloud*.

## 12. Tabel Eksekusi Task

| Check Box | Fase | Task | Detail Task | Deskripsi | Acceptance Criteria |
| :---: | :---: | :---: | :--- | :--- | :--- |
| [x] | 1 - Dependensi | Pasang `tenacity` | Update `requirements.txt` | Menambahkan modul pustaka *exponential backoff*. | Pustaka `tenacity` berhasil dipasang via pip. |
| [x] | 2 - Refaktor Modul Eksternal | Pembaruan `semantic_retriever.py` | Terapkan *ThreadPoolExecutor* & *Tenacity* | Memecah fungsi `_embed_batch` untuk melempar permintaan paralel dengan penjagaan *BoundedSemaphore* (Max 5 pekerja). Gunakan `@retry`. | Proses *embedding* memproses sub-paket bersamaan. Eksepsi ditangkap dan diulang menggunakan Jitter. |
| [x] | 3 - Refaktor Sistem Inti | Bersihkan `ingestion.py` | Ganti *Manual Retry* dengan *Tenacity* | Hapuskan semua konstruksi perulangan `time.sleep` di fungsi ekstraksi LLM. Terapkan *decorator* `@retry`. | Kodeprogram menjadi lebih ringkas dan solid dengan bantuan `wait_exponential_jitter`. |
| [x] | 4 - Refaktor Logika Utama | Pembaruan Kalang *Main Thread* | Gunakan Pemrosesan Berbasis-*Task* Asinkron | Biarkan *Parsing PDF* berjalan di *Main Thread* agar *GIL Python* aman. Sisanya (Retriever, LLM) dibebankan pada `ThreadPoolExecutor`. | Semua PDF akan melewati *Parsing* sekensial, tapi akan bertumpuk memproses LLM secara paralel. |
| [ ] | 5 - Validasi Mutlak | Pengujian Performa | Eksekusi `python app/services/ingestion.py` | Melakukan pemrosesan 10 PDF dengan arsitektur baru. Pantau apakah durasi pemrosesan menurun sesuai yang ditargetkan (< 45 detik). | Berjalan tanpa galat (*Crash/429 Too Many Requests*). Matriks *Industrial-Grade* menunjukkan latensi *Retrieval* susut signifikan. |
| [ ] | 6 - Dokumentasi | Laporan Akhir Log | Buat pelaporan optimasi | Simpan catatan dari waktu, *token*, dan jumlah antrean sebelum & sesudah pada folder *Log-Execution*. | Sebuah laporan validitas yang merangkum keberhasilan implementasi `tenacity` telah diciptakan. |