Skip to content

About

Sistem peramalan stok, deteksi risiko kadaluwarsa, dan AI procurement assistant untuk gudang obat vital. Final project bootcamp data (Data Engineer, Data Scientist, Data Analyst)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Smart Pharma Inventory Intelligence

Sistem peramalan stok, deteksi risiko kadaluwarsa, dan AI procurement assistant untuk gudang obat vital. Final project bootcamp data (Data Engineer, Data Scientist, Data Analyst), dikerjakan oleh 1 tim 3 orang sesuai peran masing-masing dengan project target 7 hari.

README ini mendokumentasikan arsitektur final, cara menjalankan, sumber data, serta keterbatasan.

Demo live: https://smart-pharma-inventory.streamlit.app/

1. Arsitektur Singkat

Fornas + simulasi stok 
    |
    v

BRONZE (MinIO)  -->  Data Quality (Great Expectations) 
    | 
    v 
SILVER (Postgres, cleaned + karantina baris rusak) 
    | 
    v 
GOLD (Postgres, star schema) 
    | 
    +--> Model forecasting demand (Prophet) --> gold.pred_demand_forecast +--> Model klasifikasi risiko kadaluwarsa (LogReg) --> gold.pred_expiry_risk 
    | 
    +--> Procurement Recommendation Generator (Gemini) --> gold.agent_recommendations 
    | 
    +--> Aplikasi Streamlit 
        |
        --> Data Scientist (forecast, risiko) 
        |
        --> Data Analyst (dashboard, rekomendasi, chatbot Q&A)

Seluruh pipeline (extract sampai training model dan recommendation generator) diorkestrasi lewat satu DAG Airflow ( dags/extract_to_bronze_dag.py ), jadwal tiap Minggu 23:00-23:45 per 15 menit. Aplikasi Streamlit terpisah, membaca gold layer secara langsung, tidak menjalankan model apa pun secara live (pola batch scoring, bukan live inference).

2. Ringkasan Sumber Data

Sumber Status Catatan
e-Fornas Kemkes (daftar obat esensial, 663 obat) Real Lihat catatan cara perolehan di bawah
e-Katalog LKPP (harga pengadaan) Dihapus dari scope Lihat catatan di bawah
Data pergerakan stok, batch, dan kadaluwarsa Simulasi Digenerate sendiri, tidak ada dataset publik yang sesuai skema project ini

Catatan soal cara perolehan data Fornas

Awalnya extractor Fornas didesain membaca file perhuruf (A-Z) hasil download manual dari e-fornas.kemenkes.go.id, karena situsnya cuma menyediakan unduhan per huruf, bukan satu file lengkap sekaligus. Semua file diunduh secara lengkap dari A - Z ( Daftar Obat.csv , 663 obat) yang disediakan sebagai bagian dari dataset project ini. Karena file itu berasal dari sumber resmi yang sama (Formularium Nasional) dan lebih lengkap, extractor diubah untuk membaca file itu langsung.

Catatan soal desain dim_obat (Gold layer)

dim_obat dibangun dari seluruh 663 obat Fornas. 20 obat yang juga dipakai di simulasi stok gudang di-enrich dengan kategori dan bentuk_ketersediaan (murni internal, dari desain generator simulasi sendiri, bukan dari Fornas, NULL untuk 643 obat lainnya). flag_vital bernilai True untuk semua baris karena basisnya dari daftar obat esensial nasional.

Catatan soal LKPP dihapus dari scope

Tiga jalur resmi sudah dicoba: API e-Katalog (ditolak robots.txt ), halaman unduh manual (isinya cuma manual PDF), dan portal data.lkpp.go.id (isinya statistik agregat, bukan harga per item). Karena ketiganya buntu dan tidak ada item Definition of Done yang bergantung langsung pada harga pengadaan, sumber ini dihapus dari scope MVP , bukan digantikan data sintetis. Dampaknya:

waste rate di dashboard dilaporkan dalam unit, bukan Rupiah , lihat bagian 6 di bawah.

3. Data Scientist: Model Forecasting Demand

Model: Prophet, satu model terpisah per kombinasi obat-gudang (80 kombinasi). yearly_seasonality=False (histori cuma sekitar 2 tahun, belum cukup dipercaya untuk pola tahunan), weekly_seasonality=True (demand memang didesain turun di akhir pekan).

Evaluasi (split berbasis waktu, 60 hari terakhir sebagai test, bukan acak):

MAPE MAE
Baseline (seasonal naive lag-7) 41.85% 7.14
Prophet 29.21% 4.84

Prophet membaik di 79 dari 80 kombinasi. Forecast produksi di-fit ulang pakai seluruh histori, horizon 30 hari ke depan (kira-kira di tengah siklus kedatangan batch 20-40 hari).
Kode: models/train_demand_forecast.py.

4. Data Scientist: Model Klasifikasi Risiko Kadaluwarsa

Label diturunkan sendiri dari histori batch (bandingkan total masuk vs keluar per batch terhadap tanggal kadaluwarsa), bukan disediakan di data mentah, supaya tidak terjadi data leakage. Perbandingan model (repeated stratified 5-fold x 5 repeat CV):

Model ROC-AUC
Dummy (baseline) 0.500
Model ROC-AUC
Logistic Regression (model final) 0.557
XGBoost 0.449
LightGBM 0.481

Catatan prediksi:

performa model ini memang lemah, mendekati tebakan acak. Fitur turunan lain (margin hari, posisi antrean FEFO) dan model berbasis pohon sudah dicoba dan tidak membantu (XGBoost/LightGBM malah overfitting, AUC di bawah baseline, karena data training cuma 168 baris jauh di bawah kapasitas model tersebut). Kesimpulan: outcome waste/habis di data simulasi ini kemungkinan besar didominasi variasi acak konsumsi harian (proses Poisson di generator), bukan pola batch yang bisa dipelajari. Dilaporkan sebagai keterbatasan, bukan disembunyikan.
Kode: models/train_expiry_risk.py .

5. AI Agent: Procurement Recommendation Generator

Membaca gold.pred_demand_forecast dan gold.pred_expiry_risk , memilih 15 batch risiko tertinggi per run, menentukan jenis tindakan ( redistribusi / diskon_cepat / prioritas_fefo ) lewat kode program berbasis angka aktual (bukan LLM), baru memanggil LLM untuk merangkai narasinya. Prinsip anti-halusinasi ini sesuai PRD section 5.1, LLM tidak pernah diminta menghitung ulang angka apa pun. Hasil disimpan append-only ke gold.agent_recommendations (bukan truncate+insert seperti dua tabel prediksi), karena tabel ini berfungsi sebagai audit trail riwayat rekomendasi dari waktu ke waktu, bukan snapshot kondisi terkini. Chatbot LLM AI API menggunakan Google Gemini API ( gemini-3.6-flash ), karena project ini tidak berbudget, Gemini API punya free tier resmi tanpa kartu kredit dengan limit cukup untuk kebutuhan project (DoD cuma minta minimal 1 rekomendasi per hari). Konsekuensinya, free tier Gemini punya rate limit ketat (5 request/menit), jadi agent ini punya jeda proaktif antar panggilan plus retry otomatis yang membaca retryDelay asli dari respons error Google, bukan asal tebak jeda.
Kode: agents/recommendation_agent/.

6. AI Agent: Q&A Chatbot

6.1 Pola function calling dengan fungsi terbatas

( get_expiring_batches , get_stock_level , get_top_risk_items ), sesuai keputusan keamanan untuk project ini, bukan text-to-SQL bebas yang berisiko menghasilkan query salah atau berbahaya. Chatbot dibatasi lewat system instruction supaya cuma menjawab topik stok, kadaluwarsa, dan risiko waste di sistem ini, menolak pertanyaan di luar topik itu.
Kode: agents/qa_agent/.

7. Data Analyst: Aplikasi Streamlit

Satu aplikasi, dua grup halaman (pakai st.navigation untuk grouping sidebar):

  • Data Scientist : Forecast Demand (chart Prophet per obat-gudang), Risiko Kadaluwarsa (distribusi skor model)

  • Data Analyst : Dashboard (KPI + filter gudang/tanggal), Rekomendasi (hasil agent), Tanya Jawab (chatbot)

Definisi dua KPI utama (didefinisikan sendiri, didokumentasikan supaya tidak dianggap standar industri baku):

  • Service level = persentase hari (dalam rentang tanggal yang difilter) di mana saldo stok berjalan (kumulatif masuk dikurangi keluar) masih di atas nol, per kombinasi obat-gudang. Proxy, karena data tidak mencatat permintaan yang eksplisit ditolak akibat stok habis.
  • Waste rate proyeksi = persentase unit (bukan Rupiah, karena data harga di luar scope, lihat bagian 2) dari sisa stok batch berjalan yang jatuh di kategori risiko Tinggi.

Kode: streamlit_app/

8. Cara Menjalankan (Development)

8.1 Pipeline Airflow (Docker Compose)

cp .env.example .env # isi .env: AIRFLOW_FERNET_KEY, GOLD_DATABASE_URL (Neon), GEMINI_API_KEY docker compose up -d --build

Build pertama kali lebih lama dari biasanya karena prophet butuh compile

cmdstan dari source (beberapa menit ekstra, bukan macet).

8.2 Aplikasi Streamlit (lokal)

pip install -r streamlit_app/requirements.txt streamlit run streamlit_app/app.py

Jalankan dari root repo (bukan dari dalam folder streamlit_app/ ), supaya .env dan folder agents/qa_agent/ yang dipakai halaman chatbot ketemu dengan benar.

9. Deployment

  • Database: Neon Postgres, hosted, satu database dipakai bersama untuk schema silver dan gold .
  • Orkestrasi: Airflow lokal (Docker Compose), jadwal tiap Minggu 23:00-23:45 per 15 menit.
  • Aplikasi Streamlit: Streamlit Community Cloud, main file path streamlit_app/app.py , secrets ( GOLD_DATABASE_URL , GEMINI_API_KEY , GEMINI_MODEL ) diisi flat di pengaturan Secrets (bukan dikelompokkan dalam section TOML), supaya juga terbaca lewat os.getenv() di kode agent.

10. Struktur Repo

Image

11. Keterbatasan Project (Ringkasan)

  • Data pergerakan stok, batch, dan harga bersifat simulasi, bukan data operasional nyata. Seluruh metrik bisnis (service level, waste rate) adalah proyeksi dari data simulasi, bukan klaim hasil nyata.
  • Model klasifikasi risiko kadaluwarsa lemah (AUC 0.557), didokumentasikan prediksi di bagian 4, bukan disembunyikan.
  • Data harga pengadaan (LKPP) tidak tersedia, waste rate dilaporkan dalam unit, bukan Rupiah.
  • Gemini API dan Plotly dipakai sebagai deviasi chatbot.

About

Sistem peramalan stok, deteksi risiko kadaluwarsa, dan AI procurement assistant untuk gudang obat vital. Final project bootcamp data (Data Engineer, Data Scientist, Data Analyst)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages