14 minute read

Sejak 2017, saya memulai menggunakan R dan tak henti-hentinya mendapatkan momen AHA dengan cara menemukan libraries atau frameworks yang mengubah sejarah hidup saya. Lebay ya, hehe.

Belakangan ini, saya mendapatkan momen AHA kembali saat mengoprek ellmer di R. Keberadaan ellmer cukup banyak mengubah cara saya melakukan coding di R. Saya pribadi seperti merasa punya partner dalam membuat algoritma dan codes. Selain itu, saya sekarang suka membuat AI agents based on ellmer untuk beberapa tasks.

Sebagai contoh, saya membuat AI-powered data viz tools dengan framework seperti ini:

Pada tulisan ini, saya akan coba share beberapa functions di ellmer yang saya gunakan sehari-hari. Dari functions ini, rekan-rekan bisa berkreasi sedemikian sehingga pekerjaan sehari-hari bisa dilakukan dengan lebih cepat, tepat, dan akurat. Saya sudah mencobanya untuk suatu pekerjaan yang pada tahun lalu membutuhkan waktu 3-4 hari kerja tapi dengan bantuan ellmer bisa selesai kurang dari satu jam saja.

Oh iya, pastikan kalian sudah memiliki API Key dari salah satu AI provider ya. Saya pribadi menggunakan DeepSeek sebagai basis model saya.

Oke, kita mulai:

Membuat object AI

Jika rekan-rekan membaca tulisan saya terkait responden survey dan anggota DPR kemarin, object AI (selanjutnya akan saya sebut sebagai AI agent) dibuat berdasarkan persona tertentu. Persona ini yang disebut dengan system prompt. System prompt ini yang sebaiknya kita inject di awal kita membuat object AI.

si_prompt = glue::glue(
  "Kamu adalah asisten yang menjawab pertanyaan sesingkat mungkin."
)

model = "deepseek-chat"

chat = chat_deepseek(system_prompt = si_prompt,
                     model         = model)

Programming dengan ellmer

Agent bernama chat ini kemudian akan kita berikan informasi seperti ini:

chat$chat("Perkenalkan saya Roberto Hongo dan saya seorang pemain sepak bola asal Brazil.")
Halo, Roberto Hongo. Senang berkenalan dengan pemain sepak bola dari Brazil.

Kemudian kita akan tanya sebagai berikut:

chat$chat("Siapakah saya?")
Anda adalah Roberto Hongo, pemain sepak bola asal Brazil.

Agent telah mengenali saya.

Cloning an Agent

Misalkan kita hendak meng-cloning agent chat yang sudah diberikan informasi sebelumnya menjadi chat_2.

chat_2 = chat$clone()

Sekarang saya akan tanyakan kepada chat_2 hal sebagai berikut:

chat_2$chat("apa profesi saya??")
Pemain sepak bola.

Resetting an Agent

Misalkan saya ingin menghilangkan informasi (atau reset) dari chat_2, saya lakukan hal berikut ini:

chat_2$set_turns(list())
chat_2$chat("siapa saya?")
Saya tidak tahu siapa Anda.

Terlihat bahwa chat_2 sudah tak mengenali informasi sebelumnya.

Melihat History dari Agent

Kita bisa menggunakan function get_turns() untuk melihat history dari suatu agent.

chat$get_turns()
[[1]]
<Turn: user>
Perkenalkan saya Roberto Hongo dan saya seorang pemain sepak bola asal Brazil.

[[2]]
<Turn: assistant>
Halo, Roberto Hongo. Senang berkenalan dengan pemain sepak bola dari Brazil.

[[3]]
<Turn: user>
Siapakah saya?

[[4]]
<Turn: assistant>
Anda adalah Roberto Hongo, pemain sepak bola asal Brazil.
chat_2$get_turns()
[[1]]
<Turn: user>
siapa saya?

[[2]]
<Turn: assistant>
Saya tidak tahu siapa Anda.

Menambahkan Custom Functions pada Agent

Sebagai sebuah agent, sebenarnya chat sudah cukup powerful untuk menjawab dan memberikan assist. Namun ada saatnya kita perlu memperkaya agent dengan custom function.

Beberapa minggu yang lalu, saya membuat sistem RAG sederhana (videonya bisa dilihat di sini). Prinsip custom function ini yang dimanfaatkan sedemikian sehingga agent bisa membaca local source yang diberikan.

Nah, kali ini saya akan tunjukan satu custom function sederhana untuk mendapatkan informasi cuaca dari situs open weather. Karena secara default chat tidak memiliki informasi cuaca. Misalkan:

chat$chat("Bagaimana cuaca di Bandung saat ini?")
Saya tidak dapat mengakses informasi cuaca real-time. Untuk mengetahui kondisi 
terkini di Bandung, silakan cek sumber cuaca terpercaya atau aplikasi seperti 
BMKG.

Sekarang saya akan buatkan custom function untuk mendapatkan cuaca realtime sebagai berikut:

cuaca_kota = function(city){
  # tempel kota dan api key ke dalam link API
    api = paste0("http://api.openweathermap.org/data/2.5/weather?q=",
                 city,
                 "&appid=",
                 API_key,
                 "&units=metric")
    
    # baca data
    data = fromJSON(api)

    # kita akan buat datanya
    suhu      = data$main$temp
    humidity  = data$main$humidity
    feel_like = data$main$feels_like
    kota      = data$name
    pressure  = data$main$pressure
    wind_spd  = data$wind$speed
    kondisi   = data$weather$main
    kondisi_d = data$weather$description
    
    # kita buat outputnya
    output = data.frame(kota,kondisi,detail_kondisi = kondisi_d,
                        suhu,feel_like,
                        pressure,wind_spd,
                        humidity)

    return(output)
}

Kita coba dulu dengan memasukkan Bandung sebagai input:

cuaca_kota("Bandung") |> knitr::kable()
kota kondisi detail_kondisi suhu feel_like pressure wind_spd humidity
Bandung Clouds overcast clouds 25.03 25.91 1011 1.48 89

Function sudah bekerja, sekarang kita tinggal me-register-kan function tersebut as a tool kepada agent chat.

# membuat as a tool
get_cuaca = tool(
  cuaca_kota,
  name = "cuaca_kota",
  description = "Mendapatkan informasi cuaca real time dari suatu kota",
  arguments = list(
    city = type_string(
      "Nama kota",
      required = T
    )
  )
)

# register ke chat
chat$register_tool(get_cuaca)

Sekarang kita akan cek apakah chat bisa mengenali cuaca realtime di Bandung saat ini atau tidak.

chat$chat("Bagaimana cuaca di Bandung saat ini?")
Cuaca di Bandung saat ini:
- Suhu: 25°C (terasa seperti 26°C)
- Kondisi: Berawan tebal
- Kelembaban: 89%
- Angin: 1.48 m/s
- Tekanan: 1011 hPa

Kita coba dengan kota lainnya:

chat$chat("Carikan saya informasi cuaca di Bekasi!")
Cuaca di Bekasi:
- Suhu: 27°C (terasa seperti 29°C)
- Kondisi: Berawan tebal
- Kelembaban: 78%
- Angin: 2.31 m/s
- Tekanan: 1010 hPa

Membuat Tools Webscrape untuk Agent

Sebagaimana yang saya informasikan sebelumnya: agent memang pintar tapi belum tentu tahu hal-hal yang sifatnya real time. Oleh karena itu, kita harus memasukkan custom function.

Sebagai contoh saya akan tanyakan berita kepada agent:

chat$chat("Ada berita apa pada sore hari ini?")
Saya tidak memiliki akses untuk mencari berita terbaru. Untuk informasi berita 
terkini pada sore hari ini, silakan cek sumber berita terpercaya atau aplikasi 
berita online.

Kali ini saya akan membuat function yang berfungsi untuk mencari top 7 updated news dari situs detik.com.

cari_berita = function(){
  berita = url |> read_html() |> html_nodes("a") |> html_text()
  link   = url |> read_html() |> html_nodes("a") |> html_attr("href")

  data.frame(berita,link) |> 
    filter(grepl("news.detik.com/berita",link,fixed = T)) |> 
    mutate(berita = stringr::str_squish(berita)) |> 
    filter(stringr::str_length(berita) > 3) |> 
    head(7) |> 
    pull(berita)
}

Berbeda dengan function sebelumnya, cari_berita() tidak memiliki input sama sekali.

# membuat as a tool
get_detik = tool(
  cari_berita,
  name = "cari_berita",
  description = "Mendapatkan lima berita terupdate dari situs portal detik.com"
)

# register ke chat
chat$register_tool(get_detik)

Sekarang kita akan coba kepada agent:

chat$chat("Ada berita apa pada sore hari ini?")
Berita terbaru hari ini:
1. Prabowo undang tokoh Gerakan Nurani Bangsa ke Istana
2. Penculik kacab bank ajukan jadi justice collaborator
3. Kubu RK tuding cari sensasi soal tes DNA ulang
4. Eks Wamenaker Noel pakai peci saat diperiksa KPK
5. Warung di Ciputat diminta 'jatah preman'
6. Gerindra sebut spekulasi Sara Mundur terlalu jauh
7. Lisa Mariana menangis dan akui anaknya dari RK

Mari kita coba dengan pertanyaan lain:

chat$chat("apakah ada berita tentang korupsi sore hari ini?")
Ya, ada berita terkait korupsi:
- **Eks Wamenaker Noel pakai peci saat diperiksa KPK** (dari berita sebelumnya)
- **Penculik kacab bank ajukan jadi justice collaborator** - terkait kasus 
korupsi/kriminal perbankan

Berita terbaru lainnya lebih fokus pada politik dan infrastruktur.

Menarik ya hasilnya.

Conclusion

Dari paparan yang saya buat di atas, agent yang saya buat dengan ellmer berpotensi menjadi one stop solution untuk meningkatkan produktivitas tergantung seberapa kreatif kitanya.