Giskard: Testing dan Evaluasi Model ML plus Aplikasi LLM/RAG Biar Nggak Bocor di Produksi
Halo temen-temen, ketemu lagi sama aku Ruby Abdullah. Kali ini aku mau ngajak kalian kenalan sama satu tools yang menurutku wajib banget masuk ke toolbox kalian kalau kalian serius bikin model machine learning atau aplikasi berbasis LLM. Namanya Giskard. Ini library open source buat testing dan evaluasi model ML sekaligus aplikasi LLM/RAG. Jadi bukan cuma buat ngecek akurasi doang, tapi buat nyari bug-bug yang biasanya nggak kelihatan di metric standar. Bug kayak bias, hallucination, sampai masalah robustness.
Kenapa aku semangat banget bahas ini? Soalnya jujur aja, selama ini banyak dari kita yang cuma ngeliat model dari satu angka: akurasi. Model akurasinya 92 persen, mantap, deploy. Padahal di balik angka 92 persen itu bisa aja modelnya diam-diam diskriminatif ke kelompok tertentu, atau gampang banget dikadalin cuma dengan ganti satu kata di input. Nah Giskard hadir buat ngebongkar hal-hal semacam itu secara otomatis. Yuk kita bahas pelan-pelan dari nol sampai kalian bisa pakai sendiri.
Introduction
Giskard itu intinya adalah quality assurance platform buat AI models. Aku suka menyebutnya kayak "unit test tapi buat model". Kalau di software engineering biasa kita nulis test buat mastiin fungsi berjalan sesuai harapan, di Giskard kita nulis (atau generate otomatis) test buat mastiin model kita nggak punya kelemahan tersembunyi.
Ada beberapa masalah utama yang Giskard bantu deteksi. Yang pertama itu performance bias, yaitu ketika model performanya jelek banget di subset data tertentu meskipun secara keseluruhan kelihatan bagus. Kedua ada robustness issue, yaitu ketika model gampang berubah prediksinya cuma gara-gara perturbasi kecil di input, misalnya typo atau ganti huruf kapital. Ketiga ada unrobustness terhadap fitur yang harusnya nggak ngaruh. Keempat, khusus buat LLM, ada masalah hallucination, injeksi prompt, kebocoran informasi sensitif, dan output yang toxic atau bias.
Yang bikin Giskard beda dari sekadar nulis assert biasa adalah dia punya automatic scan. Jadi kalian tinggal kasih model sama dataset, terus Giskard yang muterin ratusan test berbasis heuristik dan machine learning buat nyari vulnerability. Hasilnya berupa report interaktif yang gampang dibaca. Dari situ kalian bisa langsung generate test suite yang bisa dijalanin ulang tiap kali model di-update. Ini penting banget buat CI/CD pipeline machine learning.
Buat konteks, Giskard mendukung banyak jenis model. Dari tabular (klasifikasi dan regresi), NLP, sampai LLM. Dia framework-agnostic, jadi mau kalian pakai scikit-learn, PyTorch, TensorFlow, HuggingFace, atau bahkan model custom yang kalian bungkus dalam fungsi Python biasa, semuanya bisa. Buat LLM dan RAG, Giskard punya modul khusus namanya RAGET yang bakal kita bahas di bagian advanced nanti.
Oke, sebelum masuk kode, aku mau tekankan satu hal. Giskard ini bukan pengganti evaluasi manual atau domain expertise kalian. Dia tools buat mempercepat dan memperluas cakupan testing kalian. Anggep aja dia asisten QA yang rajin banget nyoba segala macam skenario yang mungkin kalian lupa cek. Keputusan akhir tetap di tangan kalian. Sepakat ya? Lanjut.
Instalasi
Instalasi Giskard gampang banget, tinggal pakai pip. Aku saranin kalian bikin virtual environment dulu biar rapi dan nggak nabrak dependency project lain.
# Bikin virtual environment dulu (opsional tapi sangat disarankan)
python -m venv venv
source venv/bin/activate (Linux/Mac)
venv\Scripts\activate (Windows)
Instalasi Giskard versi dasar
pip install giskard
Kalau kalian mau pakai fitur LLM dan RAG evaluation (RAGET), kalian butuh install dengan extra dependency-nya. Ini karena modul LLM butuh beberapa library tambahan.
# pip install "giskard[llm]"
Setelah keinstall, kalian bisa cek versinya buat mastiin semuanya beres.
import giskard
print(giskard.version)
Buat fitur LLM, Giskard secara default pakai LiteLLM buat manggil model bahasa. Jadi kalian perlu set API key sesuai provider yang kalian pakai. Kalau pakai OpenAI misalnya, kalian set environment variable-nya dulu.
import os
Set API key buat provider LLM yang kalian pakai
os.environ["OPENAIAPIKEY"] = "sk-..." # ganti sama key kalian
Konfigurasi model default yang dipakai Giskard buat evaluasi LLM
import giskard
from giskard.llm.client.openai import OpenAIClient
giskard.llm.setllmmodel("gpt-4o-mini")
giskard.llm.setembeddingmodel("text-embedding-3-small")
Nah kalau environment kalian udah siap, kita bisa mulai bagian yang seru, yaitu makai Giskard buat model beneran. Aku bakal mulai dari kasus tabular klasik dulu biar konsepnya kebentuk, baru nanti naik ke LLM.
Basic Usage
Di bagian ini kita bakal latihan pakai dataset Titanic yang legendaris itu. Tujuannya sederhana: prediksi penumpang selamat atau nggak. Aku sengaja pilih dataset ini karena kalian pasti udah familiar dan gampang buat fokus ke konsep Giskard-nya, bukan ke domain data-nya.
Menyiapkan dan Melatih Model
Pertama, kita siapin data dan latih model sederhana pakai scikit-learn. Nggak ada yang aneh di sini, ini flow machine learning biasa yang kalian udah tahu.
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.linearmodel import LogisticRegression
from sklearn.modelselection import traintestsplit
Ambil dataset Titanic
url = "https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv"
df = pd.readcsv(url)
Pilih kolom yang mau dipakai
featurecols = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]
targetcol = "Survived"
df = df[featurecols + [targetcol]].copy()
Split data
X = df[featurecols]
y = df[targetcol]
Xtrain, Xtest, ytrain, ytest = traintestsplit(
X, y, testsize=0.2, randomstate=42, stratify=y
)
Bangun preprocessing + model dalam satu pipeline
numericfeatures = ["Age", "SibSp", "Parch", "Fare"]
categoricalfeatures = ["Pclass", "Sex", "Embarked"]
numerictransformer = Pipeline(steps=[
("imputer", SimpleImputer(strategy="median")),
("scaler", StandardScaler()),
])
categoricaltransformer = Pipeline(steps=[
("imputer", SimpleImputer(strategy="mostfrequent")),
("onehot", OneHotEncoder(handleunknown="ignore")),
])
preprocessor = ColumnTransformer(transformers=[
("num", numerictransformer, numericfeatures),
("cat", categoricaltransformer, categoricalfeatures),
])
model = Pipeline(steps=[
("preprocessor", preprocessor),
("classifier", LogisticRegression(maxiter=1000)),
])
model.fit(Xtrain, ytrain)
print("Akurasi test:", model.score(Xtest, ytest))
Sampai sini kalian punya model yang jalan. Kalau kita berhenti di sini, kita cuma tahu akurasinya. Tapi kita mau lebih dari itu. Kita mau tahu di mana model ini rapuh. Di sinilah Giskard masuk.
Membungkus Dataset dengan Giskard
Langkah pertama di Giskard adalah bungkus dataset kalian pakai objek giskard.Dataset. Ini penting karena Giskard butuh tahu mana kolom target dan mana kolom kategorikal biar bisa muterin test yang relevan.
import giskard
Gabungin fitur dan target buat dataset Giskard
rawtest = Xtest.copy()
rawtest[targetcol] = ytest
giskarddataset = giskard.Dataset(
df=rawtest,
target=targetcol, # kolom yang mau diprediksi
name="Titanic test set",
catcolumns=categoricalfeatures, # kolom kategorikal
)
print(giskarddataset)
Perhatikan bahwa aku masukin kolom target ke dalam dataframe-nya, terus aku kasih tahu Giskard nama kolomnya lewat parameter target. Ini biar Giskard bisa membandingkan prediksi model sama ground truth waktu ngejalanin scan.
Membungkus Model dengan Giskard
Setelah dataset, sekarang giliran model. Kita bungkus model pakai giskard.Model. Yang penting di sini adalah kita kasih fungsi prediksi, tipe model (klasifikasi atau regresi), nama fitur, dan daftar label kelasnya.
def predictfn(dfinput):
# Fungsi ini nerima dataframe mentah dan balikin probabilitas
return model.predict
proba(dfinput)
giskard
model = giskard.Model(
model=predictfn,
modeltype="classification",
name="Titanic survival classifier",
classificationlabels=[0, 1], # urutan sesuai output predictproba
featurenames=featurecols,
)
Validasi cepat: pastikan wrapper jalan bener
print(giskardmodel.predict(giskarddataset).raw[:5])
Ada dua pendekatan buat membungkus model. Yang pertama pakai fungsi prediksi seperti di atas, ini yang paling fleksibel dan aku paling sering pakai karena bisa dipakai buat model apa aja. Yang kedua kalian bisa langsung kasih objek model scikit-learn dan Giskard bakal otomatis detect, tapi cara fungsi ini lebih universal.
Satu tips penting dari aku: pastikan urutan classificationlabels sesuai persis dengan urutan kolom output dari predictproba. Kalau kebalik, hasil scan-nya bakal ngaco dan bikin kalian bingung sendiri.
Menjalankan Automatic Scan
Nah ini bagian favoritku. Dengan model dan dataset yang udah dibungkus, kita tinggal panggil satu fungsi buat muterin ratusan test otomatis.
# Jalanin scan otomatis buat nyari vulnerability
scanresults = giskard.scan(giskardmodel, giskarddataset)
Tampilkan report (di notebook langsung muncul interaktif)
display(scanresults)
Kalau di luar notebook, simpan ke HTML
scanresults.tohtml("titanicscanreport.html")
Scan ini bakal ngecek banyak hal sekaligus. Dia cek performance bias di berbagai slice data, misalnya apakah model performanya lebih jelek buat penumpang perempuan atau penumpang kelas tiga. Dia cek robustness dengan nambahin perturbasi ke input. Dia cek overconfidence dan underconfidence, yaitu kasus di mana model terlalu yakin padahal salah, atau ragu padahal seharusnya jelas. Dan masih banyak lagi.
Report yang dihasilkan itu interaktif dan ngasih tahu kalian persis di mana masalahnya, seberapa parah, plus contoh datanya. Jujur pertama kali aku jalanin ini di model produksi lama, aku kaget karena ada slice data yang performanya turun drastis padahal metric globalnya kelihatan sehat-sehat aja.
Generate Test Suite dari Hasil Scan
Setelah scan nemu masalah, Giskard bisa langsung ngubah temuan itu jadi test suite yang bisa dijalanin ulang. Ini keren banget buat regression testing.
# Ubah hasil scan jadi test suite otomatis
testsuite = scanresults.generatetestsuite("Titanic test suite")
Jalanin test suite
suiteresults = testsuite.run()
print(suiteresults)
Test suite ini isinya kumpulan test konkret dengan threshold tertentu. Misalnya "akurasi buat slice penumpang perempuan harus di atas 0.7" atau "prediksi harus stabil terhadap perubahan huruf kapital di kolom Sex". Tiap kali kalian retrain model, kalian tinggal jalanin suite ini lagi buat mastiin nggak ada regresi. Ini yang aku maksud tadi soal integrasi ke CI/CD.
Advanced Usage
Oke sekarang kita naik level. Bagian ini aku bagi dua. Pertama soal bikin custom test dan tuning scan buat tabular, kedua soal evaluasi LLM dan RAG pakai RAGET. Bagian LLM ini yang paling banyak ditanyain temen-temen ke aku belakangan ini, jadi aku bahas agak detail.
Menambahkan Custom Test ke Test Suite
Kadang test bawaan Giskard nggak cukup buat kebutuhan bisnis kalian yang spesifik. Untungnya kalian bisa nambahin custom test sendiri. Giskard punya banyak test siap pakai di modul giskard.testing, dan kalian juga bisa nulis fungsi test sendiri.
from giskard import testing, Suite
Bangun suite manual dengan test bawaan Giskard
customsuite = Suite(name="Custom Titanic Suite")
Test 1: akurasi minimum keseluruhan
customsuite.addtest(
testing.testaccuracy(
model=giskardmodel,
dataset=giskarddataset,
threshold=0.75,
)
)
Test 2: F1 score minimum
customsuite.addtest(
testing.testf1(
model=giskardmodel,
dataset=giskarddataset,
threshold=0.70,
)
)
results = customsuite.run()
print("Semua test lolos:", results.passed)
Kalau kalian butuh logika test yang bener-bener custom, kalian bisa pakai decorator @test.
from giskard import test, TestResult
@test(name="Prediksi tidak boleh semua sama")
def testpredictionvariety(model, dataset):
preds = model.predict(dataset).prediction
uniquepreds = set(preds)
passed = len(uniquepreds) > 1
return TestResult(
passed=passed,
metric=len(uniquepreds),
)
Tambahin ke suite
customsuite.addtest(
testpredictionvariety(model=giskardmodel, dataset=giskarddataset)
)
print(customsuite.run().passed)
Custom test kayak gini berguna banget buat encode aturan bisnis yang cuma kalian yang tahu. Contohnya di kasus fraud detection, kalian mungkin mau mastiin model nggak pernah kasih skor risiko sangat rendah ke transaksi di atas jumlah tertentu. Aturan begini nggak bakal ketangkep sama scan generik, jadi kalian harus tulis sendiri.
Evaluasi LLM dan RAG dengan RAGET
Sekarang kita masuk ke bagian LLM. Katakanlah kalian bikin aplikasi RAG (Retrieval Augmented Generation), misalnya chatbot yang jawab pertanyaan berdasarkan dokumen internal perusahaan. Gimana cara kalian tahu chatbot ini bener-bener bagus? Nge-test manual satu-satu itu capek dan nggak scalable. Di sinilah RAGET (RAG Evaluation Toolkit) dari Giskard bersinar.
RAGET punya dua kemampuan utama. Pertama, dia bisa generate test set otomatis dari knowledge base kalian. Jadi dia baca dokumen kalian, terus bikin pertanyaan-pertanyaan beserta jawaban referensinya. Kedua, dia bisa evaluasi jawaban aplikasi RAG kalian dan ngasih skor per komponen, biar kalian tahu bagian mana dari pipeline RAG yang bermasalah.
Pertama, kita generate test set dari knowledge base.
import pandas as pd
from giskard.rag import KnowledgeBase, generatetestset
Anggap kita punya dokumen-dokumen dalam bentuk dataframe
Tiap baris satu potongan (chunk) teks
documents = pd.DataFrame({
"text": [
"Giskard adalah library open source untuk testing model ML dan LLM.",
"RAGET adalah modul Giskard untuk mengevaluasi aplikasi RAG.",
"Automatic scan Giskard mendeteksi bias, robustness, dan hallucination.",
"Giskard mendukung model dari scikit-learn, PyTorch, dan HuggingFace.",
# ... idealnya ratusan sampai ribuan chunk dari dokumen asli kalian
]
})
Bangun knowledge base
knowledgebase = KnowledgeBase(documents)
Generate test set otomatis
testset = generatetestset(
knowledgebase,
numquestions=30, # jumlah pertanyaan yang mau digenerate
agentdescription="Chatbot yang menjawab pertanyaan tentang Giskard",
)
Simpan test set biar bisa dipakai ulang
testset.save("giskardragettestset.jsonl")
Lihat contoh pertanyaan yang digenerate
for sample in testset.topandas().head(3).itertuples():
print(sample)
Yang keren dari RAGET adalah dia generate berbagai tipe pertanyaan. Ada pertanyaan simpel, pertanyaan kompleks yang butuh reasoning, pertanyaan yang jawabannya tersebar di beberapa dokumen, pertanyaan situasional, dan lain-lain. Ini penting karena aplikasi RAG kalian harus tahan diuji dari berbagai sudut, bukan cuma pertanyaan gampang.
Setelah punya test set, kita evaluasi aplikasi RAG kita. Kita perlu kasih RAGET sebuah fungsi yang nerima pertanyaan dan balikin jawaban dari aplikasi RAG kita.
from giskard.rag import evaluate
def raganswerfn(question, history=None):
# Di sini kalian panggil aplikasi RAG kalian yang sebenarnya.
# Contoh sederhana: retrieval + generation.
# Ganti bagian ini dengan pipeline RAG kalian.
retrieved = retrieverelevantdocs(question) # fungsi retrieval kalian
answer = generateanswer(question, retrieved) # fungsi generation kalian
return answer
Jalanin evaluasi memakai test set yang tadi
report = evaluate(
raganswerfn,
testset=testset,
knowledgebase=knowledgebase,
)
Tampilkan report (interaktif di notebook)
display(report)
Simpan ke HTML
report.tohtml("ragetreport.html")
Lihat skor keseluruhan
print(report.correctness)
Report dari RAGET ini benar-benar informatif. Dia ngasih skor per komponen RAG, yaitu Generator (LLM yang bikin jawaban), Retriever (yang ngambil dokumen relevan), Rewriter (kalau ada), Router, dan Knowledge Base itu sendiri. Jadi misalnya skor kalian jelek, kalian bisa tahu apakah masalahnya di retrieval yang salah ngambil dokumen, atau di generator yang halusinasi meskipun dokumennya udah bener. Ini diagnostik yang jauh lebih berguna daripada cuma satu angka akurasi.
RAGET juga mengklasifikasikan pertanyaan berdasarkan topik dan tipe, jadi kalian bisa lihat aplikasi RAG kalian lemah di topik apa. Misalnya ternyata chatbot kalian jago jawab pertanyaan produk tapi lemah di pertanyaan kebijakan refund. Insight semacam ini emas banget buat prioritas perbaikan.
Menjalankan Scan LLM Langsung
Selain RAGET yang fokus ke RAG, Giskard juga punya scan buat LLM secara umum. Ini mirip konsepnya sama scan tabular tadi, tapi test-nya spesifik buat masalah LLM kayak prompt injection, hallucination, output berbahaya, dan bocornya informasi sensitif.
import giskard
import pandas as pd
def llmpredict(dfinput):
# Fungsi yang manggil LLM kalian buat tiap baris input
outputs = []
for question in dfinput["question"]:
answer = callyourllm(question) # ganti sama pemanggilan LLM kalian
outputs.append(answer)
return outputs
Bungkus sebagai model Giskard bertipe textgeneration
llmmodel = giskard.Model(
model=llmpredict,
modeltype="textgeneration",
name="Customer support assistant",
description="Asisten yang menjawab pertanyaan pelanggan tentang produk kami",
featurenames=["question"],
)
Dataset contoh berisi beberapa pertanyaan
llmdataset = giskard.Dataset(pd.DataFrame({
"question": [
"Bagaimana cara reset password saya?",
"Apa kebijakan pengembalian dana kalian?",
]
}))
Jalanin scan LLM
llmscan = giskard.scan(llmmodel, llmdataset)
llmscan.tohtml("llmscanreport.html")
Yang penting diingat di scan LLM: parameter description itu bukan sekadar dokumentasi. Giskard pakai deskripsi itu buat ngerti maksud dan batasan aplikasi kalian, terus generate test yang relevan. Jadi tulis deskripsi yang jelas dan spesifik. Kalau deskripsinya asal, test yang digenerate juga jadi kurang tajam.
Best Practices
Setelah cukup lama pakai Giskard di berbagai project, aku punya beberapa prinsip yang mau aku bagi ke temen-temen biar kalian nggak jatuh ke lubang yang sama kayak aku dulu.
Yang pertama, jangan cuma andelin metric global. Ini pesan utama dari seluruh tulisan ini. Akurasi 92 persen itu nggak ada artinya kalau 8 persen kesalahan itu terkonsentrasi di satu kelompok yang penting secara bisnis atau etika. Selalu jalanin scan buat lihat performa di berbagai slice data. Giskard bikin ini gampang, jadi nggak ada alasan buat nggak ngelakuinnya.
Yang kedua, jadikan test suite bagian dari pipeline kalian. Jangan cuma jalanin scan sekali pas develop terus lupa. Generate test suite dari hasil scan, simpan, dan jalanin ulang tiap kali model di-retrain atau data berubah. Aku biasanya taruh ini di step CI, jadi kalau ada regresi kelemahan yang tadinya udah diperbaiki, build-nya langsung gagal dan aku dapat notifikasi. Ini menyelamatkan aku dari banyak insiden produksi.
Yang ketiga, tulis deskripsi model yang jelas terutama buat LLM. Kayak yang aku bilang tadi, kualitas test yang digenerate sangat bergantung pada seberapa baik kalian mendeskripsikan apa yang model kalian lakukan dan apa batasannya. Luangkan waktu buat nulis deskripsi yang bener. Anggap kalian lagi jelasin ke QA engineer baru yang belum tahu apa-apa soal produk kalian.
Yang keempat, buat RAG, evaluasi per komponen, jangan cuma end-to-end. Kekuatan RAGET adalah dia bisa nunjukin komponen mana yang bermasalah. Manfaatkan itu. Kalau skor akhir jelek, jangan buru-buru ganti model LLM-nya. Cek dulu, jangan-jangan masalahnya di retriever yang salah ngambil dokumen. Sering kali fix di retrieval jauh lebih murah dan efektif daripada gonta-ganti LLM.
Yang kelima, mulai dengan test set kecil terus perbesar. Buat RAGET, generate test set dari knowledge base itu butuh pemanggilan LLM yang berbiaya. Mulai dengan jumlah pertanyaan kecil, misalnya 20 sampai 30, buat validasi setup kalian jalan. Setelah yakin, baru perbesar jadi ratusan buat evaluasi yang lebih menyeluruh. Ini hemat biaya dan waktu.
Yang keenam, review test yang digenerate secara manual. Giskard itu pinter, tapi bukan berarti sempurna. Sesekali test set yang digenerate bisa punya pertanyaan yang aneh atau jawaban referensi yang kurang tepat. Luangkan waktu buat baca sampel dari test set, terutama di awal. Domain expertise kalian tetap nggak tergantikan. Buang test yang nggak masuk akal dan perbaiki yang perlu.
Yang ketujuh, perhatikan biaya API kalau pakai fitur LLM. Scan LLM dan generasi test set RAGET itu ngirim banyak request ke provider LLM. Kalau kalian pakai model mahal kayak GPT-4 buat semua ini, tagihan bisa membengkak. Aku biasanya pakai model yang lebih murah kayak gpt-4o-mini buat evaluasi rutin, dan cadangin model besar buat kasus yang bener-bener butuh presisi tinggi.
Yang kedelapan, dokumentasikan temuan kalian. Tiap kali scan nemu vulnerability, catat apa temuannya dan apa keputusan kalian. Kadang kalian memutuskan sebuah "kelemahan" sebenarnya acceptable buat konteks bisnis kalian. Dokumentasikan alasannya, biar tim kalian nggak bingung di kemudian hari dan biar kalian sendiri nggak lupa kenapa dulu ambil keputusan itu.
Conclusion
Oke temen-temen, kita udah jalan cukup jauh dari instalasi sampai evaluasi RAG yang cukup dalam. Aku harap sekarang kalian punya gambaran utuh kenapa Giskard ini berharga banget buat siapa aja yang serius bawa model AI ke produksi.
Poin besar yang aku mau kalian bawa pulang: model yang kelihatan bagus di kertas belum tentu bagus di dunia nyata. Metric global bisa menipu. Giskard ngasih kalian cara sistematis buat ngebongkar kelemahan tersembunyi, baik itu bias, masalah robustness, maupun hallucination di aplikasi LLM. Dan yang lebih penting, dia bikin proses testing ini bisa diulang dan diotomasi, jadi kalian nggak cuma testing sekali terus lupa.
Buat langkah selanjutnya, aku saranin kalian langsung praktik. Ambil satu model yang udah kalian punya, bungkus pakai Giskard, terus jalanin scan. Aku hampir yakin kalian bakal nemu minimal satu hal yang bikin kalian mikir "wah untung ketauan sekarang". Setelah nyaman dengan tabular, coba naik ke evaluasi LLM dan RAGET kalau kalian lagi ngerjain aplikasi berbasis LLM.
Ingat, tujuan kita bukan bikin model yang keliatan sempurna di demo, tapi bikin model yang beneran bisa dipercaya waktu dipakai orang. Testing yang serius adalah bagian nggak terpisahkan dari itu. Giskard cuma tools, tapi tools yang tepat bisa ngubah cara kalian kerja jadi jauh lebih tenang dan profesional.
Segitu dulu dari aku. Kalau kalian nyoba dan nemu insight menarik, aku pengen banget denger ceritanya. Selamat ngoprek, dan sampai ketemu di tutorial berikutnya. Semangat terus belajarnya ya temen-temen!