Studi Kasus

Cara engineer Instagram Direct membangun arsitektur UI yang dibuat khusus untuk AI dengan Jetpack Compose dan mengurangi biaya token per sesi agen sebesar 33%

Waktu baca: 11 menit

Postingan blog ini ditulis berkolaborasi dengan tim Meta

Instagram Direct adalah salah satu platform inti di Instagram, yang menangani miliaran pesan pengguna setiap harinya. Selama bertahun-tahun melakukan iterasi, tim telah melakukan setiap pengoptimalan mikro yang mungkin dilakukan pada sistem Android View lama. Namun, mempertahankan dan memperluas platform lama yang sangat dioptimalkan akan menimbulkan utang teknis dan overhead engineering yang signifikan, terutama karena tim makin banyak mengadopsi UI deklaratif dan asisten coding AI. 

Penggunaan Jetpack Compose untuk Instagram Direct lebih dari sekadar modernisasi UI biasa. Tim ini membuat codebase UI yang dibuat khusus untuk AI yang 50% lebih kecil daripada penerapan aslinya, sekaligus mencapai pengurangan waktu eksekusi agen AI sebesar 35% , 32% lebih sedikit pertukaran engineer-agen, dan pengurangan biaya token sebesar 33% . Dalam kemitraan yang erat dengan Google, tim mengadopsi Jetpack Compose sambil mempertahankan standar performa yang tinggi. Melalui pengoptimalan performa, Meta dan Google meningkatkan kualitas Compose tidak hanya untuk Instagram, tetapi juga untuk ekosistem developer Android yang lebih luas.

Memodernisasi codebase dalam skala besar

AI telah dengan cepat menjadi pendamping harian bagi para engineer di industri ini, dan penerapannya pada codebase skala besar seperti Instagram telah menghasilkan peningkatan produktivitas yang nyata. Tim Instagram Direct menetapkan sasaran yang lebih ambisius. Daripada sekadar mengarahkan alat AI ke kode yang ada, tim mendesain ulang codebase dan arsitekturnya agar secara desain kompatibel dengan AI, sehingga melipatgandakan dampak AI jauh melampaui apa yang dapat diberikan oleh penyesuaian saja.

Tim Instagram Direct memilih Jetpack Compose sebagai komponen utama untuk membangun arsitektur UI yang dibuat khusus untuk AI. Sifat deklaratifnya memastikan kode ringkas, dapat diprediksi, dan secara struktural lebih mudah dipahami oleh model AI, dengan lebih sedikit efek samping, lebih sedikit status implisit, dan batas komponen yang lebih jelas.

Migrasi ke Jetpack Compose memerlukan perencanaan yang cermat. Ratusan juta orang mengirim pesan di Instagram setiap hari, sehingga migrasi harus dilakukan secara bertahap, lancar, tanpa mengganggu pengalaman pengguna, sementara tim merekonstruksi fondasi di baliknya. Untuk menggambarkan skala tantangannya: Setiap komponen UI dapat dirender dalam lebih dari 160 permutasi status yang berbeda, dan satu layar percakapan saja menangani lebih dari 200 jenis pesan yang berbeda.

Product Design 1.png

Saat memigrasikan codebase sebesar ini ke Compose, Anda mungkin tergoda untuk mengambil jalan pintas dan menyematkan komponen UI Compose di dalam hierarki tampilan yang ada. Sebagai langkah inkremental selama migrasi bertahap, hal ini sangat valid. Namun, dalam jangka panjang, mengintegrasikan Compose di dalam codebase berbasis View menimbulkan tantangan. Alat AI sering kali mengambil jalur yang paling mudah. Jika Anda mencampur kode UI deklaratif dan imperatif, AI kemungkinan akan menggabungkannya secara tidak benar, sehingga memunculkan bug halus, utang teknis, dan regresi performa. 

Membangun arsitektur UI yang dibuat khusus untuk AI

Pada skala Instagram, tingkat abstraksi arsitektur tidak dapat dihindari, dan itulah yang membuat aplikasi dapat dikelola seiring pertumbuhannya. Pertimbangkan pola umum, di mana setiap jenis item RecyclerView dimodelkan sebagai turunan dari class dasar RecyclerViewItem kustom yang mengekspos hook siklus proses biasa seperti onBind.

Contoh 1

class ChatItem(
  val features: FeatureFlagProvider
) : RecyclerViewItem<ComposeViewHolder, ChatUiState> {

  // Imperative context:
  // AI could often take the path of least resistance and generate a mutable
  // state here, dispatched outside the ChatUiState. This class survives
  // re-bindings and is shared across multiple items, ultimately leading to
  // unexpected, hard-to-reproduce bugs.
  var isPinned: Boolean = false

  override fun onBind(holder: ComposeViewHolder, uiState: ChatUiState) {
      // Imperative context
      val isPinnedChatsEnabled = features.isEnabled("pinned_chats_feature")

      // Declarative context
      holder.composeView.setContent {

        // Blending imperative and declarative contexts
        if (isPinnedChatsEnabled) {
          Button(onClick = { isPinned = !isPinned }) {
            Text(if (isPinned) "Unpin" else "Pin")
          }
        }
        
        ...
      }
  }
}


Dalam cuplikan di atas, ada dua masalah yang muncul. Pertama, tanda isPinnedChatsEnabled dibaca dalam kode imperatif, lalu diambil di dalam lambda Compose, yang merupakan coupling halus di seluruh paradigma. Kedua, isPinned ada sebagai kolom yang dapat diubah pada item itu sendiri, bukan di ChatUiState, sehingga tetap ada setelah RecyclerView mengikat ulang dan mendaur ulang di seluruh baris, yang menyebabkan kebocoran dan menghasilkan bug yang sulit direproduksi.

Meskipun kode dibersihkan dengan memberikan fungsi @Composable khusus untuk item, masalah yang sama tetap ada.

Contoh 2

class ChatItem(
  val features: FeatureFlagProvider
) : ComposeRecyclerViewItem<ChatUiState> {

  // Imperative context
  val isPinnedChatsEnabled = features.isEnabled("pinned_chats_feature")
  var isPinned: Boolean = false

  // Declarative context
  @Composable
  override fun Content(uiState: ChatUiState) {

 
    // Blending imperative and declarative contexts
    if (isPinnedChatsEnabled) {
      Button(onClick = { isPinned = !isPinned }) {
        Text(if (isPinned) "Unpin" else "Pin")
      }
    }

    ...
  }
}

Ini sengaja dibuat sebagai contoh sederhana, tetapi mengilustrasikan masalah yang lebih luas—semakin sedikit batas yang diberikan kepada AI, semakin rendah kualitas kode yang dihasilkan seiring waktu. Batasan dan keterampilan membantu, tetapi tidak cukup dengan sendirinya, karena saat AI mengalami hambatan, AI akan sering kali mencari cara untuk mengatasinya agar tidak terhambat.

Agar codebase kompatibel dengan AI, codebase harus mengikuti dua aturan praktis: 

  • Minimalkan dependensi pada konteks kustom. Makin banyak pengetahuan khusus codebase yang diperlukan agen AI untuk melakukan perubahan yang benar, makin rendah kualitas outputnya. Makin dekat codebase dengan praktik terbaik yang diketahui, makin baik hasil AI.
  • Codebase yang mengutamakan AI harus menerapkan batasnya sendiri. Menambal kesenjangan desain dengan keterampilan AI tidak dapat diskalakan, karena setiap keterampilan yang dimuat ke dalam konteks memerlukan token dan dapat menurunkan performa agen. Sebagai gantinya, arsitektur itu sendiri yang harus menanggung beban tersebut. Agen AI secara alami mengambil jalur yang paling mudah, sehingga desain harus membuat jalur tersebut mengarah ke kode yang benar dan berkualitas tinggi, sekaligus membuat keputusan desain yang buruk sulit dan mahal untuk diungkapkan.

Item daftar masih dapat direpresentasikan oleh abstraksinya sendiri, tetapi dalam hal ini semua kode Compose berada di konstruktor, sehingga tidak memiliki akses ke anggota atau status class, dan satu-satunya sumber argumennya adalah konstruktor. Hal ini membuatnya setara dengan fungsi @Composable biasa, sekaligus sesuai dengan arsitektur yang ada.

Contoh 3

class ChatItem(
  val features: FeatureFlagProvider,
  val onPin: (Boolean) -> Unit,
) : ComposeItem<ChatUiState>(

 
   // Compose UI
   content = { uiState: ChatUiState ->
    val isPinnedChatsEnabled = features.isEnabled("pinned_chats_feature")

    if (isPinnedChatsEnabled) {
      Button(onClick = { onPin(!uiState.isPinned) }) {
        Text(if (uiState.isPinned) "Unpin" else "Pin")
      }
    }
    
    ...
  },
)

Memigrasikan codebase dengan ukuran ini adalah tugas yang sangat besar. Selama ini, ratusan komponen UI yang membentuk sebagian besar UI Langsung harus berdampingan dengan komponen lama, dengan keduanya dipertahankan secara paralel. Alur kerja AI membantu memungkinkan migrasi paralel ini dengan mempercepat proses penulisan kode dalam jumlah besar. Pendekatan itulah yang memungkinkan tim Direct melakukan migrasi dalam waktu singkat, tanpa mengganggu tim lainnya, yang terus mengirimkan fitur yang meningkatkan pengalaman jutaan orang setiap hari.

Beberapa engineer menjalankan agen AI mereka sendiri terhadap pusat informasi bersama yang berisi keterampilan dan konvensi yang dapat digunakan kembali yang dibuat selama migrasi. Hal ini membuat alur kerja dan praktik terbaik tetap sinkron di seluruh tim, daripada setiap engineer harus menemukannya kembali. Dalam setiap platform, tim melakukan migrasi dalam tahap berikut:

  • Tulis semua kode Compose dengan AI.
  • Sempurnakan, tangani kasus ekstrem, dan tutup kesenjangan performa, hingga UI diluncurkan kepada pengguna sungguhan dalam pengujian publik.

Membagi pekerjaan menjadi dua tahap per layar memungkinkan satu engineer bergerak cepat di seluruh platform, menyelesaikan arsitektur dan kasus ekstrem yang rumit di awal. Dengan adanya dasar tersebut, orang lain dapat berfokus untuk menyiapkan UI agar siap produksi tanpa perlu berhenti untuk membuat keputusan teknis tersebut sendiri, sehingga keseluruhan migrasi berjalan cepat.

Hasil migrasi memvalidasi pendekatan tersebut. Untuk platform Instagram Direct yang dimigrasikan, Jetpack Compose memungkinkan tim mengurangi jumlah total kode UI sebesar 50%. Lebih sedikit kode yang perlu dibuat AI akan menghasilkan output berkualitas lebih tinggi dan biaya token yang lebih rendah per tugas. 

Quote-Pavlo-New.jpg

Analisis data internal codebase Android untuk Instagram Direct membandingkan sesi agen AI yang mengerjakan UI Compose dengan tugas yang sama menggunakan Android Views. Peningkatan efisiensi terlihat jelas di dua dimensi:

  • Per karakter kode yang dihasilkan: Compose memerlukan 32% lebih sedikit pertukaran antara engineer dan agen dan 35% lebih sedikit waktu eksekusi agen (waktu yang berlalu sejak agen mulai mengerjakan permintaan engineer hingga agen menampilkan respons).
  • Per sesi agen: Biaya token keseluruhan turun sebesar 33% dengan Compose dibandingkan dengan Views.

Kami melaporkan efisiensi output dan jumlah sesi umum karena keduanya merupakan hasil yang berguna secara independen. Angka waktu eksekusi dan pertukaran engineer-agen membandingkan penggunaan resource per unit output yang dihasilkan, sedangkan angka token membandingkan total biaya untuk sesi agen biasa.

Data tersebut juga mengungkapkan perbedaan yang konsisten dalam cara kedua framework menangani kode yang kompleks atau rentan. Meta melacak hal ini menggunakan skor risiko perubahan kode, yang mengevaluasi kualitas kode secara keseluruhan dan kemungkinan perubahan menyebabkan insiden produksi. Analisis ini mengukur efisiensi resource agen menggunakan gabungan konsumsi token, waktu eksekusi agen, dan interaksi engineer dengan agen. Seiring bertambahnya skor risiko file, sesi agen AI secara alami menjadi kurang efisien dalam penggunaan resource. 

Jika skor risiko kumulatif file berlipat ganda, UI yang diterapkan dengan Tampilan Android mengurangi efisiensi resource agen sebesar 30% (per karakter yang ditampilkan). Dalam keadaan yang sama, pengurangan oleh UI Jetpack Compose hanya 9%

Melalui kemitraan antara Google dan Meta, tim Instagram Direct memberikan perspektif baru dalam adopsi Compose — mendekatinya melalui lensa kesiapan AI codebase, bukan hanya penulisan ulang UI. Upaya ini mengungkapkan kekuatan Compose dalam berfungsi sebagai dasar untuk membangun codebase dan arsitektur yang mengutamakan AI, terutama saat diterapkan pada skala aplikasi seperti Instagram.

Pengoptimalan performa 

Instagram Direct adalah salah satu platform paling integral di aplikasi, dan orang-orang berharap platform ini terasa cepat dan responsif setiap saat. Mengadopsi Jetpack Compose secara efektif berarti menulis ulang UI secara substansial, dan tujuan utamanya adalah mempertahankan pengalaman berkualitas tinggi tanpa regresi.

Iterasi selama bertahun-tahun telah mendorong penerapan berbasis View lama di Instagram ke standar performa yang sangat tinggi, dan tim perlu memenuhi standar yang sama saat beralih ke framework UI yang sama sekali baru.

Instagram mengukur ratusan, bahkan ribuan, metrik performa.  Untuk adopsi Compose, tiga hal berikut adalah yang paling penting:

  • Waktu untuk berinteraksi - durasi waktu antara membuka layar hingga dapat menggunakannya.
  • Waktu untuk memuat sepenuhnya - jumlah waktu antara membuka layar hingga semua konten dimuat sepenuhnya (yaitu gambar).
  • Performa scroll - seberapa lancar layar di-scroll, tanpa frame yang terputus.

Metrik ini dilacak saat runtime dalam produksi, sehingga memungkinkan untuk menjalankan pengujian A/B yang membandingkan UI Compose yang dimigrasikan dengan UI lama dan mengevaluasi dampak performa dari upaya ini.

Cara umum untuk melakukan migrasi seperti ini adalah dengan memulai dari yang kecil, memindahkan beberapa komponen UI, mengumpulkan data, dan mempelajari perilakunya. Meskipun berguna, hasil awal ini hanya memberikan gambaran sebagian, sehingga memberikan negatif palsu terhadap adopsi Compose karena:

  • Tidak representatif — satu komponen UI yang dimigrasikan dapat memberikan data yang berguna tentang performa keseluruhannya di layar tertentu. Namun, komponen yang berbeda berperilaku berbeda karena alasan yang tidak dapat digeneralisasi, sehingga Anda tidak selalu dapat mengekstrapolasinya.
  • Biaya interoperabilitas — potongan kecil Compose di dalam codebase View yang besar akan membayar biaya penghubung yang tidak dapat diprediksi antara kedua sistem. Overhead tersebut mendistorsi pengukuran, sehingga hasil skala kecil awal tidak mencerminkan seperti apa migrasi penuh sebenarnya.

Hasilnya adalah migrasi kecil, meskipun berguna, tidak selalu mencerminkan dampak penuh Compose. Semakin banyak permukaan yang dimigrasikan secara menyeluruh tanpa gangguan penghubungan, semakin jelas dan baik gambar yang dihasilkan dari segi performa.

Layar inti di Instagram Direct dibangun di sekitar daftar panjang jenis item yang bervariasi, yang awalnya diterapkan dengan RecyclerView. Arsitektur ini mengandalkan abstraksi kustom untuk skalabilitas, tetapi tetap terikat pada siklus proses sistem berbasis View.

Diagram 1.png

Tugas utama tim adalah melakukan migrasi bertahap ratusan item daftar individual ke Compose dalam arsitektur berbasis RecyclerView yang ada, meluncurkannya dalam produksi dalam grup kecil independen di bawah pengujian A/B — semuanya tanpa perubahan yang terlihat pada pengalaman pesan pengguna.

Kelemahan terbesar dari penyiapan tersebut adalah adanya dependensi yang signifikan pada sistem View lama melalui arsitektur RecyclerView inti, bahkan setelah migrasi penuh setiap item daftar ke Compose. Sebagai langkah alami berikutnya, tim memutuskan untuk berinvestasi dalam mengganti arsitektur inti berbasis RecyclerView dengan alternatif native Compose — LazyColumn.

Artinya, komponen UI Compose harus diabstraksi dari framework yang melingkupinya sambil tetap kompatibel dengan RecyclerView dan LazyColumn secara bersamaan. Yang sama pentingnya adalah kemampuan untuk beralih di antara keduanya saat runtime melalui tanda fitur, untuk mengaktifkan pengujian A/B.

Diagram 2.png

Meskipun item Compose baru kompatibel secara native dengan LazyColumn dan dapat dihubungkan ke pohon komposisi yang tidak terganggu, API interop dibuat untuk memasukkannya ke dalam RecyclerView juga. Hal ini memungkinkan penyiapan LazyColumn di-roll out dalam pengujian A/B secara berdampingan dengan RecyclerView — menggunakan kembali item Compose yang sama dan meningkatkan performa, tanpa mengganggu tim lainnya yang sedang membangun dan menyempurnakan fitur.

Skala, kompleksitas, dan sensitivitas Instagram terhadap regresi terkecil sekalipun menimbulkan tantangan unik bagi Jetpack Compose. Untuk mengatasinya, diperlukan kemitraan yang berulang dan langsung. Dengan bekerja sama secara erat, para engineer Google dan Meta menganalisis metrik untuk menentukan dan mendesain kemampuan Compose baru agar memenuhi atau melampaui tolok ukur berbasis View. Sebagai hasil dari kemitraan ini, penambahan berikut pada Jetpack Compose menjadi perhatian: Komposisi yang dapat dijeda dengan LazyLayoutCacheWindows dan pelacakan visibilitas. 

Komposisi yang dapat dijeda dengan LazyLayoutCacheWindows

Komposisi yang dapat dijeda (diaktifkan secara default di Compose 1.10) memungkinkan item daftar lambat yang mahal dikomposisikan secara bertahap di seluruh frame untuk mencegah jank. Jika dipasangkan dengan LazyLayoutCacheWindow (ditambahkan di Compose 1.9), kombinasi ini akan meningkatkan kelancaran scroll secara signifikan. Dalam pengujian internal baru-baru ini di Meta, menggabungkan komposisi yang Dapat dijeda dengan satu viewport LazyLayoutCacheWindow mengurangi frame drop besar per menit (LFD/m) sekitar 13% dibandingkan dengan Compose standar. Cache Window sendiri menguranginya sekitar 8% terhadap dasar yang sama. LFDs/m adalah metrik internal yang digunakan Meta untuk melacak jeda yang terlihat saat men-scroll.

Quote-Fabio.jpg


Menggunakan LazyLayoutCacheWindow di aplikasi Anda akan menyiapkan dan mempertahankan item di luar layar dalam rentang berbasis piksel di sekitar area tampilan untuk memungkinkan gerakan cepat. Untuk memanfaatkan LazyLayoutCacheWindows di aplikasi, Anda dapat menggunakan Compose 1.13.0-alpha03 terbaru dan menyiapkannya seperti yang ditunjukkan dalam contoh di bawah:

val cacheWindow = LazyLayoutCacheWindow(ahead = 150.dp, behind = 100.dp)
// OR
val cacheWindow = LazyLayoutCacheWindow(aheadFraction = 0.5f, behindFraction = 0.3f)

LazyColumn(state = state, cacheWindow = cacheWindow) {
    ...
}

Ada dua cara untuk mengonfigurasi periode cache. Keduanya mendeskripsikan hal yang sama: seberapa banyak konten di luar layar yang harus tetap disusun, tetapi dalam unit yang berbeda.

  • Dp: panjang absolut tetap. ahead = 150.dp menyimpan 150 dp konten yang disusun melewati tepi yang terlihat, terlepas dari perangkat.
  • Float: fraksi area tampilan. aheadFraction = 0.5f menyimpan setengah layar yang disusun di depan, sehingga jumlah absolutnya diskalakan dengan tinggi layar yang mendukung berbagai faktor bentuk: lebih banyak di tablet atau perangkat foldable yang dibuka, lebih sedikit di ponsel ringkas. 

Tim Instagram menyempurnakan fraksi mengambang jendela cache secara khusus untuk struktur konten dan ukuran item Direct. Karena nilai ideal bervariasi bergantung pada parameter UI tertentu, menemukan keseimbangan yang tepat memerlukan beberapa eksperimen.

Pencatatan log tayangan iklan dengan onVisibilityChanged


API onVisibilityChanged (ditambahkan di Compose 1.9.0) adalah hasil utama lainnya dari kemitraan teknis antara Google dan Meta. Hal ini memberikan cara yang konsisten bagi permukaan Jetpack Compose skala besar untuk mengetahui kapan composable benar-benar terlihat di layar, menggantikan penerapan kustom yang dibuat secara manual yang digunakan pada masa lalu. Khusus dalam Instagram Direct, sinyal visibilitas ini digunakan di ratusan file untuk mendukung metrik kualitas produk yang bergantung pada apakah elemen UI benar-benar ditampilkan kepada orang atau tidak.

Performa startup

Penggunaan Jetpack Compose untuk Instagram Direct menghasilkan peningkatan performa yang tidak terduga di seluruh platform aplikasi lainnya. Runtime Jetpack Compose memiliki biaya pemanasan yang hanya Anda bayar satu kali, dan karena fitur pesan adalah platform dengan traffic tinggi yang sering dikunjungi di awal sesi pengguna, platform lain di Instagram yang mengandalkan Compose mengalami peningkatan performa yang signifikan.

Performa saat memulai UI Compose di dalam Instagram Direct itu sendiri dioptimalkan dengan menggunakan Profil Dasar Pengukuran, yang melakukan pra-kompilasi jalur kode aktif pada waktu penginstalan sehingga Compose dapat merender dengan cepat sejak peluncuran pertama.

Pelajaran dari migrasi Instagram Direct ke Jetpack Compose 

  • Jetpack Compose memberikan laba atas investasi secara langsung: Anda tidak perlu menggunakan alur kerja AI tingkat lanjut untuk mendapatkan manfaat dari Compose. Dengan pengurangan kode sekitar 50%, berarti lebih sedikit kode yang perlu dikelola, dan area permukaan untuk bug juga berkurang.
  • Merancang arsitektur yang dibuat khusus untuk AI menghasilkan pencapaian yang signifikan, termasuk pengurangan waktu eksekusi agen AI sebesar 35%, pengurangan pertukaran agen-engineer sebesar 32%, dan pengurangan biaya token sebesar 33%.
  • Meskipun ada banyak API interop dan dukungan untuk menggabungkan View dan Compose, usahakan untuk memigrasikan permukaan yang lebih besar daripada komponen kecil individual. Hal ini menjaga UI dalam hierarki komposisi tunggal yang tidak terganggu dan membuka semua pengoptimalan performa terbaik yang bersifat native Compose.
  • Pasangkan komposisi yang Dapat Dijeda dengan LazyLayoutCacheWindow: Memasangkan keduanya akan memberikan hasil yang lebih baik daripada hanya menggunakan jendela cache. Dengan hanya jendela cache, item berat masih dapat mencoba menyusun dalam satu proses, yang berpotensi melebihi anggaran frame.
  • Berkontribusi pada Compose itu sendiri. Meta telah berpartner dengan tim Jetpack Compose untuk mewujudkan masukan dan ide mereka dalam Compose. Dengan mengerjakan toolkit open source, kita semua akan mendapatkan manfaat saat perbaikan bug dan peningkatan performa dilakukan secara terpusat. Jadi, sampaikan masukan Anda.

Penggunaan Jetpack Compose memberikan peningkatan signifikan dalam pengembangan yang dibantu AI sekaligus menyederhanakan rekayasa UI sehari-hari di Instagram. Pendekatan deklaratif mengurangi boilerplate, mempermudah penalaran status, dan meningkatkan produktivitas developer secara keseluruhan. Tim engineering Instagram berharap dapat menghadirkan Compose ke lebih banyak platform di seluruh aplikasi, dan melanjutkan kolaborasi antara Google dan Meta untuk menghadirkan lebih banyak peningkatan bagi pengguna Instagram dan Jetpack Compose. 

Jika Anda belum mencoba Compose, yang kini dilengkapi bantuan AI, bermigrasi ke Jetpack Compose menjadi lebih mudah dari sebelumnya.

Ucapan Terima Kasih. Terima kasih kepada Michal Zielinski dan Matthew Du dari Meta, serta Andrei Shikov dan George Mount dari Google, atas upaya mereka dalam menghadirkan peningkatan performa pada Compose melalui kolaborasi antara Meta dan Google. Terima kasih juga kepada Gary Ye dari Meta yang telah membantu menghadirkan Compose ke Instagram Direct, dan kepada Gopal Juneja dari Meta yang telah mendukung upaya ini melalui data science.

Ditulis oleh:
Lanjutkan membaca