# A. Judul
**Blueprint Redesign Implementasi PoC Task 2: Asynchronous Neo4j Vector Knowledge Graph**

# B. Tanggal
19 April 2026

# B1. Status Dokumen
**Transisi (Redesign Tahap-1 / Bukan acuan final)**  
Dokumen ini merekam evolusi arsitektur menuju desain akhir. Acuan implementasi aktif saat ini adalah `Markdown/redesign_2_PoC_implementation.md`.

# C. Ringkasan Pemahaman
Dokumen ini merupakan arsitektur revisi dari purwarupa (Proof of Concept) migrasi My-SRE Knowledge Graph. Pipeline ini bertanggung jawab membaca PDF akademis, mengekstraksi 5 pilar informasi (Background, Method, Gap, Objective, Futurework) menggunakan LLM, melakukan vektorisasi 768-D, dan memasukkannya ke Neo4j. Pada versi *redesign* ini, terjadi perombakan mendasar dari sisi konkurensi (pemisahan fase Sinkron vs Asinkron), penyaringan threshold kemiripan (KNN), sanitasi teks, serta penguncian Idempotensi untuk mengatasi kerentanan kuota API Gemini dan batas penyimpanan (storage) Edge pada Neo4j AuraDB Free tier.

# D. Penjelasan Perbedaan Redesign vs PoC Lama

| Aspek | PoC Lama | Redesign (Versi Baru) | Dampak Signifikan |
| :--- | :--- | :--- | :--- |
| **Alur Eksekusi** | Sepenuhnya sekuensial (Sinkron). User harus menunggu pembuatan Node sekaligus Edge Summary selesai per PDF. | Antrean Multi-Threading (Asinkron). Node dibuat instan di _Main Thread_, Edge dirajut di _Background Worker Thread_. | Terbebas dari _UI Timeout_. Ingesti file massif jauh lebih cepat (hanya membuat Node). |
| **Pencarian Vektor** | Murni `Top-K` KNN. Selalu memaksa 5 jurnal terdekat untuk ditarik relasinya. | Ditambah pelindung `Cut-off Threshold` (misal Cosine > 0.85). | _False Positive_ (contoh: Lele vs AI) hilang total. Edge hanya tercipta jika relevan. |
| **Arah Garis Graf** | Dua arah terpisah (Bidirectional: `A->B` dan `B->A`). | Searah dikunci secara alfabetis (_Lexicographical ID Sorting_). | Hemat Kuota Neo4j Edge dan API LLM Token hingga 50% absolut! |
| **Idempotensi File** | Skrip tetap memakai memori ekstraksi meski Node ternyata sudah ada di database. | Valuasi `MATCH Exist` via Hash. Kalau file ada, lewati (Skip) PyMuPDF dan Gemini. | Pencegahan kebocoran beban biaya API (_Cost Drain_) pada saat _re-run_ kegagalan. |
| **Kualitas Teks Input** | Teks PDF mentah dikirim bulat-bulat ke Ekstraktor termasuk "Daftar Pustaka". | Dilakukan sanitasi berbasis _String Split / RegEx_ (memenggal bagian References). | Hilangnya _LLM Hallucination_ di pilar Future-Work akibat membaca teks sitasi. |

# E. Asumsi dan Spesifikasi
*   **Database Graf:** Neo4j AuraDB (lisensi *Free Plan*, limitasi 50k node/175k edge, v5.x).
*   **AI Engine (Parsing & Summary):** Ekosistem Gemini (`gemini-2.5`).
*   **AI Vector Embedding:** Ekosistem Gemini (`text-embedding-004` -> 768 Dimensi).
*   **Ekstraktor Dokumen:** `PyMuPDF` (Sanitasi RegEx).
*   **Lingkungan Eksekusi:** CLI Terminal menggunakan arsitektur Orchestrator dalam 1 File Tunggal yang menampung `Main Thread` (untuk ingest) dan `Worker Thread/Queue` (untuk Edge).
*   **Ambang Batas KNN Similarity:** Minimum threshold > 0.80 (skor cosine perlu dituning pada rentang 0.75-0.85 saat ujicoba).

# F. Decision Log (Log Keputusan)
1. **[DEC-01] Async Orchestrator:** Disepakati menggunakan implementasi `queue.Queue` berlapis `threading.Thread` atau `asyncio` bawaan Python. Skrip di terminal tetap berjalan dan menunggu dengan `queue.join()` setelah iterasi *upload* PDF selesai, namun diproses menyamping.
2. **[DEC-02] Lexicographical Merge:** Setiap garis `[SIMILAR_METHOD]` dan kawan-kawan dari PDF `A` ke `B` akan dirotasi: `Source = min(A,B)` dan `Target = max(A,B)`. Kueri selalu dibaca dengan `MATCH (n1)-[r]-(n2)` tanpa arah panah.
3. **[DEC-03] Pre-LLM Sanitation:** Melakukan *Regex match* yang mencari variasi kalimat *"REFERENCES", "DAFTAR PUSTAKA", "BIBLIOGRAPHY"* dengan *font size* besar, atau cukup *split string* akhir jurnal. Semuanya dipotong *off-board*.

---

# G. Penjelasan Cara Kerja Arsitektur End-to-End
Sistem bergerak dalam 1 *script orchestrator* yang memiliki dua tungku proses yang hidup berdampingan.
Tungku pertama **(Main Thread / Ingestion)** berjalan mensurvei folder `Literature/`. Tiap menemukan PDF, ia membangkitkan `MD5 Hash`. Hash ini ditanyakan langsung ke Neo4j. Jika sudah jadi anggota, `SKIP`. Jika baru, ia membuka PyMuPDF, memotong *Daftar Pustaka*, dan mengirim sari dokumen ke Gemini Extractor. Gemini mencetak ulang bentuk JSON, lalu diubah ke Vektor numerik, lalu ditanam jadi `Merk/Node Baru` di Neo4j. Terakhir, ID Node yang baru masuk didorong *(Push)* ke Antrean Pesan in-memory (`Task Queue`). Selesai, main thread lanjut ke dokumen dua.

Tungku kedua **(Background Worker Thread)** yang selama ini menganggur menanti di terminal yang sama, terbangun karena ada pesan ID masuk ke *Queue*. Ia langsung menyelinap menembak fungsi kueri *Vector Search KNN* Neo4j. Dengan filter ketat (Score > 0.85), ia memanggil kandidat lama. Jurnal *Lele* akan dicoret otomatis. Jurnal valid (skor >0.85) diambil. Worker membereskan arah panahnya (A vs B alfabetis) sehingga menghindari *duplicate loop*, mengirim 1 sesi API tunggal ke Gemini (Summary mengapa mereka mirip), lalu memasang garis MERGE Edge di Neo4j.

# H. Diagram Alur End-to-End (AWS Architectural Style)

```mermaid
flowchart TD
    %% AWS Style Custom Diagram
    classDef awsOrange fill:#FF9900,stroke:#232F3E,stroke-width:2px,color:#fff,rx:5,ry:5
    classDef awsNavy fill:#232F3E,stroke:#FF9900,stroke-width:2px,color:#fff,rx:5,ry:5
    classDef awsBlue fill:#EEF6FF,stroke:#0071C5,stroke-width:2px,color:#0071C5,rx:5,ry:5
    classDef awsGreen fill:#eaffea,stroke:#1e8900,stroke-width:2px,color:#1e8900,rx:5,ry:5
    classDef awsGray fill:#f4f4f4,stroke:#666,stroke-width:2px,color:#333
    
    subgraph S_Local ["💻 Local Machine (Python CLI Orchestrator)"]
        direction TB
        PDF["📄 PDF Folder (Literature)"]:::awsGray
        
        subgraph S_Ingest ["Main Thread (Node Ingestion - Fast Sync)"]
            HashCheck["🔎 MD5 Hash Check (Neo4j Exist?)"]:::awsBlue
            PyMuPDF["🛠️ PyMuPDF (Cut References)"]:::awsBlue
            Extract["🧠 Gemini LLM (Extract 5 Pillars)"]:::awsOrange
            Embedde7r["🔢 Gemini Embedder (768-D Vector)"]:::awsOrange
            NodeDB["💾 MERGE Node (AuraDB)"]:::awsNavy
            Queue["📬 Internal Memory Queue (Push ID)"]:::awsGray
        end
        
        subgraph S_Worker ["Worker Thread (Edge Generation - Slow Async)"]
            KNN["🔎 Vector Search (KNN Top-K + Threshold)"]:::awsBlue
            Sort["🔀 Lexicographical Sort (Avoid Duplicate)"]:::awsGray
            Summarize["🧠 Gemini LLM (Edge Summary Bulk)"]:::awsOrange
            EdgeDB["💾 MERGE Edge (AuraDB)"]:::awsNavy
        end
    end

    %% Flow Relationships Ingestion
    PDF -->|1. Upload Read| HashCheck
    HashCheck -->|2. New Node Passed| PyMuPDF
    PyMuPDF -->|3. Clean Text| Extract
    Extract -->|4. JSON 5 Pillars| Embedder
    Embedder -->|5. 5x Arrays| NodeDB
    NodeDB -->|6. Fire Event| Queue
    
    %% Bypass Flow Idempotent
    HashCheck -->|Exist Skip| Queue
    
    %% Flow Relationships Worker
    Queue -->|7. Pop New Node ID| KNN
    KNN -->|8. Raw Matched Vectors| Sort
    Sort -->|9. Directed Unique Pair| Summarize
    Summarize -->|10. Edge Reasoning Strings| EdgeDB
```

# I. Penjelasan Diagram
1. **S_Ingest (Biru Tua/Navy-Orange):** Adalah urutan utama di mana PDF difilter (Skip Duplicate), disanitasi, dipompa lewat Gemini untuk ditarik saripatinya dan di-_embed_, serta diamankan ke dalam basis data. Jalur ini cepat dan menjadi urutan prioritas di mata *User CLI*.
2. **Queue (Abu-abu):** Jembatan penghubung antara dunia cepat (Node) dan dunia lambat (Edge). Menyimpan variabel `node_id` yang butuh dicarikan saudaranya.
3. **S_Worker (Biru/Orange):** Sebuah antrean latar yang melakukan tiga Filter Ketat agar sistem tak jebol: `Threshold ≥ 0.85` (Mencegah Halusinasi Kesamaan), `Lexicographical Sort` (Mencegah Boros Memori Arrow), lalu dirapikan dan ditulis ke dalam relasi Graf secara damai di luar pandangan pemblokiran tampilan pengguna (*Non-Blocking*).

# J. Struktur Repositori PoC
```text
poc-task2-neo4j-vector/
├── Literature/              # Target folder file .pdf pengujian
├── Markdown/                # Catatan dokumentasi 
│   ├── redesign_PoC_Implementation.md
│   └── (arsip log lama)
├── .env                     # API Key
├── requirements.txt         # neo4j, google-genai, pymupdf
├── setup_indexes.py         # Tetap / Modifikasi tuning indexing (Cosine 768-D)
├── orchestrator_ingest.py   # SINGLE FILE (Replaces embed_and_ingest.py) berisikan Main+Worker!
├── query_similarity.py      # Console CLI khusus testing output tanpa UI visual.
└── README.md
```

# K. Desain Skrip (Versi Redesign untuk `orchestrator_ingest.py`)
File ini akan menggunakan `queue.Queue()` dan modul `threading` standar Python CLI. Di dalam file ini akan ada:
1. `class KnowledgeGraphCore:` -> Inisiasi *Driver Neo4j* & Gemini Client.
2. `def process_sync_pdf(filepath):` -> Mengandung *Idempotent check*, Ekstraksi Teks, *Regex Sanitization*, Ekspansi Gemini JSON, Embedding 768D, dan Cypher `MERGE Node`. Melempar _return_ `article_id` ke *Queue*.
3. `def worker_edge_generator(q):` -> Looping tiada henti memakan antrean dari *Queue*. Begitu mendapat `article_id`, ia melancarkan kueri `CALL db.index.vector.queryNodes` bersyarat (*score filter*), mengurutkan abjad untuk panah ganda, mengumpulkan string ringkasan LLM, lalu me-*Merge Edge*.
4. `def main():` -> Meng-_spawn_ 1 Background Thread. Me-loop isi folder `Literature/*.pdf`, mengirimnya ke `process_sync_pdf()`. Seusai seluruh loop, memanggil `q.join()` untuk menunggu proses *Worker* selesai membersihkan sisa antrean.

# L. Execution Tasks (Task Tabel)
Berikut unit eksekusi perbaikan yang dapat dikonsumsi oleh *Agent AI Code* maupun Insinyur Manusia:

| ✅ | ID | Task Name (Perintah / Action) | Indikator Selesai (Verification) |
| :---: | :---: | --- | --- |
| [x] | **RD-01** | **Setup Project & Depedencies Baru** <br> Pastikan folder struktur (`Literature/`) eksis dan `neo4j`, `google-genai`, `pymupdf` bersih ter-_install_ dalam kerangka _env_. | _Import_ tes berjalan lancar tanpa _Missing Module Error_. |
| [x] | **RD-02** | **AuraDB Vector Index Prep** <br> Update atau jalankan `setup_indexes.py` dari kode lama yang menyimpan index komponen `cosine` berdimensi `768`. | AuraDB GUI menampakkan status ke 5 Index Vektor (Background, Method, Gap, dsb) berlabel *ONLINE*. |
| [x] | **RD-03** | **Anti-Idempotent Helper (Hash Generator)** <br> Tulis fungsi `get_md5_hash(filepath)` dan `check_node_exists(hash, neo4j_driver)` di dalam file skrip utama. | Skrip berhasil melewatkan _(print "File X skipped")_ ketika menemukan Hash yang sama. |
| [x] | **RD-04** | **PDF Reference Sanitizer** <br> Re-tulis fungsi ekstraktor `PyMuPDF`. Sisipkan validasi `.split('REFERENCES')[0]` atau pencari RegEx sebelum mengirim *string* mentah. | Terminal log menampilkan Teks *clean* dan menghilangkan subuah literatur yang berada di pojok akhir jurnal. |
| [x] | **RD-05** | **Sync LLM Pipeline (Extrac & Embed)** <br> Susun logic yang menyuntik API Gemini 2.5 Structured JSON, lantas mengubah isinya ke array 768-D. | Terminal log berteriak _"Embed array 768 sukses terbentuk"_. API Gemini dipanggil dalam keadaan aman. |
| [x] | **RD-06** | **Neo4j Node Injection (Main Thread)** <br> Tulis cypher MERGE untuk menetapkan property `.hash`, `.title`, lima teks pilar, dan lima vektor properti di AuraDB. Lempar ID nya. | Terdapat _Query Nodes_ berhasil dicatat menggunakan `article_id` ke AuraDB tanpa membuat koneksi graf relasi (yatim piatu). |
| [x] | **RD-07** | **Membangun Main Thread & Queue Orchestrator** <br> Ganti arsitektur dasar menjadi arsitektur multi-thread via Python `queue.Queue()`. Jadikan task *Upload* (Task 03 - 06) masuk di Main, lalu push ID ke Queue. | Skrip ter-_print_ "Memproses Node A, masuk ke antrean!". |
| [x] | **RD-08** | **Worker Edge: KNN Threshold Filter** <br> Dalam fungsi sisi worker `worker_edge_generator`, rubah kueri lawas menjadi kueri pencarian Vektor yang dipersenjatai filter `WHERE score >= 0.82` (atau 0.85). | Log tak pernah menarik Jurnal bertopik perikanan di dalam kumpulan node berbasis ilmu komputer AI. |
| [x] | **RD-09** | **Worker Edge: Lexicographical Node Merge** <br> Skrip memilah `min(ID_1, ID_2)` versus `max()`. Kemudian menata kueri cypher `MERGE (NodeMin)-[r]->(NodeMax)`. | Penciptaan panah hanya berarah dari huruf A->Z, Neo4j terhindari dari panah silang ganda untuk sepasang Node id yang kongruen. |
| [x] | **RD-10** | **Worker Edge: Bulk Gemini Summary & Injection** <br> Lempar _prompt bulk_ (jika bisa) untuk mencari *why similarities matter*, lalu *MERGE SET* bobot edge dan kalimat narasi ke dalam edge Neo4j yang dikunci task sebelumnya. | Aplikasi Console/UI AuraDB memunculkan anak panah garis di mana _Score_ > 0.80 menempel dengan mulus. |
| [x] | **RD-11** | **Testing E2E Terminal (Query Similary Script)** <br> Kembangkan alat baca `query_similarity.py` agar mengesampingkan garis panah `()` - `[r]` - `()` (_undirected_ fetch) walau secara fisik mereka berpanah pada disk Aura. | *Output* log dapat mengejar kueri pertanyaan pengguna dan membalikkan informasi kedekatan node secara seutuhnya lintas jurnal murni asimetrik visibel. |
