Apa Itu Jev? Mengenal Model System One dari TypeSafe AI

Jev adalah model AI yang tidak menulis teks, melainkan mengembalikan pilihan, level, atau ya/tidak beserta probabilitasnya. Lewat banyak diagram, termasuk yang bisa diikuti langkah demi langkah, pelajari bedanya dengan ChatGPT dan cara menggunakannya di Python.

Jev adalah model AI buatan TypeSafe AI.

Berbeda dengan ChatGPT, Jev tidak menulis teks. Untuk keputusan seperti "Tiket ini untuk tim mana?" atau "Apakah ini mendesak?", Jev mengembalikan jawaban dalam bentuk yang kamu tentukan sebelumnya, lengkap dengan probabilitas (angka dari 0 sampai 1; makin dekat ke 1, makin besar kemungkinannya).

Video berbahasa Inggris dari Riley Brown, "JEV: How It Works and What You Can Build", yang menjelaskan cara kerja Jev dan apa saja yang bisa kamu bangun dengannya.

Untuk memakainya, kamu mengirim input yang akan dinilai (disebut state, misalnya isi tiket) beserta pertanyaanmu melalui API (antarmuka yang dipakai program untuk memanggil fitur layanan eksternal).

Setelah jawabannya kembali, kodemu sendiri yang sepenuhnya menentukan langkah berikutnya.

Dengan bantuan diagram, halaman ini membahas bedanya Jev dengan ChatGPT, tiga tipe pertanyaannya, cara memanggilnya dari Python, dan cara membuat percabangan berdasarkan confidence. Bagian akhirnya mengulas tugas yang sebaiknya tidak diserahkan ke Jev, serta cara kerja Jev di balik layar.

Apa yang dikirim ke Jev, apa yang kembali, dan siapa yang memutuskan sisanya
ChoiceTim mana?ScoreSeberapa marah?NoulMendesak?Evaluasiterhadap stateEvaluasiterhadap stateEvaluasiterhadap statechoice+ probabilitasscore+ probabilitasnoul(prob. ya)Kode mengirimke timKode mengurutkansesuai prioritasKode meneruskanke manusiaJev mengevaluasi paralel
Dalam satu request, ketiga pertanyaan dievaluasi terhadap state yang sama, dan masing-masing mendapat jawabannya sendiri.

Jev mengerjakan semua bagian kecuali kolom paling kanan. Kolom itu adalah kodemu sendiri, yang kamu tulis dengan pernyataan if.

Apa itu Jev? Model System One yang mengembalikan keputusan, bukan teks

TypeSafe menyebut jenis model ini model System One (model AI yang dengan cepat mengembalikan keputusan dalam tipe yang sudah ditentukan, sehingga bisa langsung dipakai oleh software).

Posisi Jev di antara model AI
Model AI yang membaca bahasa alami
Model yang menghasilkan teks (LLM)
  • Chatbot seperti ChatGPT dan model penalaran
  • Yang dikembalikan: teks, kode, dan penjelasan alur berpikir
  • Bentuk jawabannya baru jelas setelah dibaca
Model yang mengembalikan keputusan (model System One)
  • Yang dikembalikan: opsi, level, atau ya/tidak yang sudah ditentukan, beserta probabilitas
  • Tidak menulis teks, kode, atau penjelasan
Jev (TypeSafe AI)
  • Nama model di API: jev-latest
  • Input hanya teks (tanpa gambar, audio, atau video)
Kedua jenis model sama-sama bisa membaca bahasa alami. Bedanya ada pada apakah model mengembalikan teks atau keputusan. Jev, yang ada di kotak terdalam paling bawah, adalah model System One pertama.

jev-latest adalah alias (nama yang menunjuk ke versi tertentu) yang selalu mengarah ke versi terbaru. Begitu versi baru dirilis, alias ini ikut pindah ke versi tersebut.

Apa bedanya Jev dengan ChatGPT (LLM)?

Mari bandingkan keduanya lewat satu tugas yang sama: mengarahkan setiap tiket dukungan yang masuk ke salah satu dari tiga tim.

Kalau kamu bertanya ke LLM (large language model: model AI yang menghasilkan teks kata demi kata) seperti ChatGPT tentang tim mana yang sebaiknya menangani sebuah tiket, jawabannya akan berupa teks.

Kalau jawabannya berubah dari "dukungan teknis" menjadi "tim teknis", pengecekan seperti if answer == "technical" tidak lagi cocok.

Bahkan jika kamu memakai fitur yang membatasi output ke format JSON, kodemu tetap harus memvalidasi isinya.

Karena Jev sudah menerima daftar kandidat sejak awal, choice yang dikembalikan pasti salah satu dari kandidat tersebut.

Saat TypeSafe mengklaim "0% halusinasi" (menghasilkan konten keliru yang terdengar meyakinkan), yang dimaksud adalah soal format: kamu tidak akan pernah mendapat jawaban di luar daftar kandidat.

Klaim itu tidak menjamin kandidat yang dipilih benar.

Berikut perbandingan keduanya dari lima aspek. Baris terakhir membahas biaya, yang dihitung berdasarkan jumlah token (satuan yang dipakai model AI untuk memecah teks saat memprosesnya).

AspekLLM seperti ChatGPTJev
Yang dikembalikanTeks yang dihasilkanOpsi/level tetap + probabilitas
Menulis teks/kodeBisaTidak bisa
Unggul dalamTeks, kode, penalaran panjangKlasifikasi, skor, ya/tidak
Saat pertanyaan ditambahWaktu tunggu bertambahHampir sama (paralel)
Yang ditagihToken input dan outputHanya token input

Choice, Score, atau Noul: tipe pertanyaan mana yang sebaiknya dipakai?

Saat bertanya ke Jev, yang pertama perlu kamu putuskan bukanlah cara merangkai pertanyaan, melainkan bentuk jawabannya.

Ada tiga tipe pertanyaan: Choice (memilih satu dari beberapa kandidat yang tidak berurutan), Score (menempatkan sesuatu pada skala dengan level berurutan), dan Noul (menjawab ya atau tidak).

Selain jawabannya, Choice dan Score juga mengembalikan confidence, yaitu angka dari 0 sampai 1 yang menunjukkan seberapa terpusat probabilitasnya pada satu kandidat atau level. Makin dekat ke 1, makin yakin model pada satu jawaban.

Noul adalah satu-satunya tipe tanpa confidence.

Kalau masih ragu, lihat untuk apa kodemu memakai jawabannya: Choice untuk mengarahkan, Score untuk dibandingkan dengan ambang batas, dan Noul untuk satu pernyataan if.

Pada Choice, criteria (dasar penilaian) adalah dict yang memetakan nama kandidat ke penjelasannya.

Pakai penjelasan itu untuk mempertegas batas antarkandidat, misalnya "masalah pembayaran masuk ke billing, bug integrasi masuk ke technical."

Pada Score, criteria adalah list penjelasan level yang diurutkan dari rendah ke tinggi, dengan nomor level mulai dari 0.

score yang dikembalikan adalah jumlah dari setiap nomor level dikali probabilitasnya.

Probabilitas tiap level Score dan score yang dihasilkan
00.200.400.600.8010Level 00.57Level 10.43Level 2
Score-nya adalah 0 × 0.0 + 1 × 0.57 + 2 × 0.43 = 1.43. Nilai ini berada di antara level 1 dan level 2, dan lebih dekat ke level 1.

Score ini kemudian dibandingkan dengan ambang batas di kodemu, misalnya "tangani dulu semua yang nilainya 1.5 ke atas."

Noul 0.5 tidak berarti "sedang"

Nilai Noul adalah probabilitas bahwa jawabannya ya. Kalau pertanyaan "Apakah orang ini mahir Python?" menghasilkan 0.5, itu bukan berarti kemampuannya di tingkat menengah, melainkan peluangnya 50:50.

Untuk mengukur tingkat atau derajat, pakai Score.

Memakai Jev: mengarahkan tiket dukungan ke tim dengan Python SDK

Mari ikuti contoh dari quickstart resmi untuk mengarahkan sebuah tiket ke salah satu dari tiga tim.

Dengan SDK (library yang menyediakan semua yang dibutuhkan untuk memanggil suatu layanan), kamu tidak perlu menyusun request atau menulis logika retry sendiri.

SDK ini membutuhkan Python 3.10 atau versi yang lebih baru, dan TypeSafeClient() membaca key dari variabel lingkungan TYPESAFE_API_KEY.

Cara mengatur variabel lingkungan dibahas di Variabel lingkungan di Linux, sedangkan cara menangani key ada di API key dan webhook.

Apa yang dikirim dan dikembalikan dalam satu panggilan
stateisi tiketquestionsdiberi namamodeldefault: jev-latestJev membacadan menilaianswerssatu per pertanyaanmodelversi yang dipakaiusagetoken terpakai
Kirim tiga item di sebelah kiri, dan kamu akan menerima tiga item di sebelah kanan. Nama yang kamu berikan untuk setiap pertanyaan menjadi key untuk mengambil jawabannya dari answers.

Kode mengikuti dokumentasi resmi

Kode dan response di sini diambil dari contoh di dokumentasi resmi, bukan dari hasil saya menjalankannya sendiri. Isi tiket dan instructions yang berbahasa Inggris juga saya salin apa adanya dari contoh tersebut.

Memanggil Jev dengan Python SDK

pip install typesafe-sdk
export TYPESAFE_API_KEY="api-key-kamu"   # untuk shell macOS / Linux
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient

client = TypeSafeClient()  # membaca TYPESAFE_API_KEY dan memakai jev-latest

# Input yang dinilai (state): tiket dukungan yang masuk
# (sudah 3 hari integrasi Stripe terus gagal sehingga penjualan hilang, dan pelanggan butuh bantuan segera)
ticket = "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. I'm losing sales. Please help ASAP."

response = client.system_one(
    state=ticket,
    questions={
        # Tim mana: dict yang memetakan nama kandidat ke penjelasannya
        "department": Choice(
            instructions="Which team should handle this",
            criteria={
                "billing": "Payment or subscription issues",
                "technical": "Bugs or integration problems",
                "sales": "Pricing or account questions",
            },
        ),
        # Seberapa kesal: level dari terendah ke tertinggi
        "frustration": Score(
            instructions="How frustrated the customer appears",
            criteria=[
                "Calm, just stating facts",
                "Frustrated but civil",
                "Very angry, strong language",
            ],
        ),
        # Apakah mendesak: ya atau tidak
        "is_urgent": Noul(
            instructions="The message conveys urgency or time-sensitivity",
        ),
    },
)

print(response.answers["department"].choice)  # technical
print(response.answers["frustration"].score)  # 1.0
print(response.answers["is_urgent"].noul)     # 1.0

questions adalah dict yang memetakan nama pertanyaan ke definisi pertanyaannya, dan setiap jawaban diambil dari response.answers dengan nama yang sama. Nilai di komentar berasal dari response di quickstart resmi.

Hasilnya: timnya technical, tingkat kekesalannya ada di level 1 ("Frustrated but civil"), dan tiket ini hampir pasti mendesak.

Cocok dengan "for 3 days" dan "ASAP" di tiketnya, bukan?

Memanggil Jev langsung lewat HTTP

Kamu juga bisa memanggil Jev langsung lewat HTTP tanpa SDK (dasar-dasar API dibahas di Apa itu API?).

Hanya ada satu endpoint (URL yang menerima request), dan key dikirim di header Authorization.

curl -X POST https://api.typesafe.ai/v1/systemone \
  -H "Authorization: Bearer $TYPESAFE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "state": "Hi, I have been trying to connect my Stripe account for 3 days ...",
    "model": "jev-latest",
    "questions": {
      "department": {
        "type": "choice",
        "instructions": "Which team should handle this",
        "criteria": {
          "billing": "Payment or subscription issues",
          "technical": "Bugs or integration problems",
          "sales": "Pricing or account questions"
        }
      }
    }
  }'

Kalau lewat HTTP, model wajib diisi, dan tipe setiap pertanyaan ditentukan dengan field type.

Membaca response

Berikut contoh JSON yang dikembalikan. Di sini hanya jawaban department yang ditampilkan.

{
  "answers": {
    "department": {
      "type": "choice",
      "choice": "technical",
      "confidence": 0.78,
      "probabilities": {
        "technical": 0.85,
        "sales": 0.0,
        "billing": 0.15
      }
    }
  },
  "usage": {
    "input_tokens": 392,
    "output_tokens": 65
  }
}
Struktur bersarang JSON response
Seluruh response
answers: satu jawaban per nama pertanyaan
department (jawaban Choice)
  • choice: kandidat yang dipilih → technical
  • probabilities: satu per kandidat (totalnya 1)
  • confidence: seberapa terpusat probabilitasnya → 0.78
usage
  • input_tokens / output_tokens: jumlah token yang terpakai
Kotak terluar mewakili seluruh response, sedangkan jawabannya sendiri ada di kotak bernama sesuai pertanyaan, di dalam answers.

usage berisi jumlah token yang menjadi dasar penagihan.

Kalau memakai SDK, kamu bisa mengambil kandidat yang dipilih dari JSON ini lewat response.answers["department"].choice.

Empat angka dalam jawaban department
00.200.400.600.8010.85technical0.15billing0sales0.78confidence
Nilai-nilai ini berasal dari contoh response di quickstart resmi. Tiga batang di kiri adalah probabilitas tiap kandidat, dengan total 1. Batang confidence di paling kanan bukan probabilitas, melainkan angka yang merangkum seberapa terpusat ketiga probabilitas tadi.

Kandidat teratas, technical, bernilai 0.85, tetapi confidence hanya 0.78. Confidence bernilai 0 saat probabilitas tersebar merata ke semua kandidat, dan 1 saat semuanya terkumpul di satu kandidat.

Untuk tiga kandidat, demo resmi memperkirakannya dengan rumus "(3 × probabilitas teratas − 1) ÷ 2", dan hasilnya memang cocok: (3 × 0.85 − 1) ÷ 2 ≈ 0.78.

Pakai confidence untuk memutuskan: otomatis, konfirmasi, atau serahkan ke manusia

Dokumentasi resmi menyarankan agar kamu memakai ambang batas (nilai yang menentukan kapan pemrosesan pindah dari satu jalur ke jalur lain) untuk membagi confidence menjadi tiga rentang.

Jalankan otomatis saat nilainya tinggi, minta konfirmasi pengguna saat nilainya di tengah, dan serahkan ke manusia saat nilainya rendah.

Ambang batas yang tepat berbeda-beda untuk setiap aksi. Contoh di dokumentasi resmi memakai kasus voice banking, yaitu layanan yang memungkinkan pengguna mengelola rekening lewat suara.

Kalau confidence-nya sama-sama 0.7, saldo langsung dibacakan, tetapi persetujuan transfer dikonfirmasi dulu ke pengguna. Makin besar kerugian yang bisa ditimbulkan sebuah aksi, makin tinggi ambang batas yang sebaiknya kamu pasang.

Anggap 0.6 dan 0.85 sebagai titik awal, lalu sesuaikan sambil membandingkan hasilnya dengan datamu sendiri.

action = response.answers["intent"]  # Choice: check_balance / approve_transfer / other

if action.confidence < 0.6:
    # Apa pun aksinya, jangan jalankan kalau model ragu
    route_to_support_agent(account_id)

elif action.choice == "check_balance":
    # Kalau salah, pengguna cukup menanyakan saldo lagi
    show_balance(account_id)

elif action.choice == "approve_transfer":
    if action.confidence > 0.85:
        approve_transfer(account_id)  # uang berpindah, jadi ambang batasnya lebih tinggi
    else:
        ask_user_to_confirm("Apakah kamu ingin menyetujui transfer ini?")

else:
    # dinilai sebagai other
    route_to_support_agent(account_id)

if pertama menetapkan batas bawah confidence, lalu cabang elif sesudahnya menerapkan ambang batas untuk tiap aksi, sehingga pengecekannya berlapis dua.

Karena if dan elif menguji kondisi secara berurutan dari atas ke bawah, mudah dilihat baris mana yang mencegah kerugian apa.

Kunci versi model setelah ambang batas ditetapkan

jev-latest ikut pindah setiap kali ada versi baru yang dirilis, sehingga input yang sama bisa saja mulai menghasilkan jawaban dan confidence yang berbeda.

Setelah ambang batasmu disetel, isi model dengan nama model yang mencantumkan nomor versi, dan baru pindah ke versi baru setelah kamu mengujinya.

Kapan Jev cocok dan kapan tidak: kelemahan dan akurasi untuk bahasa selain Inggris

Karena tidak bisa menulis teks, Jev bukan pengganti LLM.

Keunggulannya adalah memutuskan dengan cepat dan murah ke mana sesuatu harus diarahkan, sebelum LLM atau manusia turun tangan.

Memasangkan Jev dengan LLM: tentukan jalurnya lebih dulu

Dalam contoh resmi, Jev menilai maksud sebuah pesan dengan Choice dan seberapa sulit pesan itu ditangani dengan Score sekaligus, lalu menentukan ke mana pesan itu dikirim.

Jev memilih jalur di depan, pihak lain yang menulis balasan
PesanpelangganJev: maksuddan kesulitanPertanyaanstatus pesananPertanyaanprodukconfidencedi bawah 0.5Kode membalasdari DBLLM khususmenulis balasanPetugasmenangani
LLM yang mahal hanya dipanggil untuk pesan yang benar-benar membutuhkannya. Jev tidak menggantikan LLM; perannya adalah titik pemeriksaan yang berada di depan LLM.

Kelemahan Jev dan cara mengatasinya

TypeSafe memublikasikan daftar tugas yang sulit bagi Jev. Tiga di antaranya yang paling mungkin kamu temui dalam pemrosesan sehari-hari adalah menghitung jumlah, membandingkan tanggal, dan aritmetika.

Ketiganya bisa dihindari dengan menyerahkan penilaiannya saja ke Jev dan mengerjakan perhitungannya di kode.

Hindari tiga kelemahan dengan memisahkan penilaian dari perhitungan
Tanya jumlahsekaligusTanya tanggalmana lebih duluMinta hitungjumlah uangNilai tiap itemdengan NoulPecah tanggaldengan ChoicePilih angkadengan ChoiceJumlahkandengan sum()Bandingkan sebagaiobjek dateHitungdi kodeDiserahkan ke Jev
Kolom kiri berisi jenis permintaan yang sulit bagi Jev, kolom tengah adalah bagian yang diserahkan ke Jev, dan kolom kanan adalah pekerjaan kodemu. Berikan hanya penilaian ke Jev, lalu hitung dan bandingkan di kode.

Jev membaca tanggal (baris 2) sebagai teks, jadi kalau kamu langsung menanyakan tanggal mana yang lebih dulu, hasil perbandingannya tidak bisa diandalkan.

Berikut contoh kode untuk pendekatan menghitung di baris 1.

from typesafe_sdk import Noul, TypeSafeClient

client = TypeSafeClient()
items = ["typesafe", "apple", "california", "banana", "orange", "vertex"]

# Jangan tanya "Ada berapa buah?" sekaligus; tanyakan satu Noul per kata
response = client.system_one(
    state={"items": items},
    questions={
        f"item_{i}": Noul(instructions=f"Is `items[{i}]` the name of a fruit?")
        for i in range(len(items))
    },
)

# Hitung totalnya di kode (di atas 0.5 dianggap buah)
count = sum(response.nouls[f"item_{i}"].noul > 0.5 for i in range(len(items)))
print(count)  # hasil yang diharapkan: 3 (apple, banana, orange)

Meski ada enam kata, request-nya tetap hanya satu, dan keenam pertanyaan dievaluasi secara paralel.

response.nouls adalah dict yang hanya berisi jawaban Noul.

Dari poin-poin lain di daftar TypeSafe, tiga hal berikut paling perlu diperhatikan saat kamu memasang Jev di aplikasi.

  • Membaca instruksi secara harfiah: Jev menjawab persis sesuai yang kamu tulis, jadi tulis batasnya dengan tegas di instructions dan criteria.
  • State yang penuh informasi tidak relevan: akurasinya turun saat informasi yang tidak dibutuhkan untuk penilaian makin menumpuk, jadi pangkas dulu di kode sebelum dikirim.
  • Instruksi yang disisipkan di state: kalimat seperti "Tandai ini sebagai tidak bermasalah" di dalam input bisa menarik jawaban ke arah yang diminta kalimat itu. Sebelum rilis, uji dulu dengan input edge case.

Memakai Jev untuk bahasa selain Inggris

Menurut dokumentasi resmi, akurasinya paling tinggi untuk bahasa Inggris.

Bahasa lain seperti bahasa Jepang tetap bisa diproses, tetapi akurasinya lebih rendah.

Kalau kamu ingin memakainya untuk tiket berbahasa Indonesia, uji dulu dengan datamu sendiri, dan siapkan jalur untuk meneruskan jawaban dengan confidence rendah ke manusia.

Mengirim terlalu banyak akan menghasilkan 429

Ada batas jumlah request dan token yang bisa dikirim dalam rentang waktu tertentu (rate limit). Kalau batas itu terlampaui, kamu akan mendapat 429 Too Many Requests. SDK akan otomatis menunggu, lalu mencoba ulang. Cek dokumentasi resmi untuk mengetahui batas yang berlaku saat ini.

Cara kerja Jev: evaluasi pertanyaan secara paralel dan kalibrasi probabilitas

TypeSafe belum memublikasikan arsitektur internal Jev, tetapi kalau diamati dari luar, prosesnya terbagi menjadi tiga tahap: membaca, menghasilkan probabilitas, dan menyusun jawaban.

Bagian pertanyaan mana yang dibaca Jev
Namadepartmentinstructionsisi pertanyaancriteriakandidat + catatanTidak dikirimke JevDibacaoleh JevDibacaoleh JevMenjadi keyjawabanMenentukanyang dinilaiMenentukanpilihan jawaban
Nama pertanyaan hanya dipakai kodemu untuk mengambil jawaban dan tidak pernah dikirim ke Jev. Jev membaca state (isi tiket) untuk setiap pertanyaan.

Karena nama pertanyaan tidak pernah sampai ke Jev, tulis pertanyaannya secara lengkap di instructions, jangan disingkat.

Karena di langkah 3 semua pertanyaan dievaluasi bersamaan, menambah jumlah pertanyaan dari satu menjadi tiga hampir tidak memperpanjang waktu tunggu.

Apa yang terjadi di dalam satu pertanyaan Choice
state +3 kandidattechnical0.85billing0.15sales0.003 probabilitas(total = 1)choicetechnicalconfidence0.78Probabilitas per kandidat
Ini contoh department dari quickstart resmi. Dengan cara yang sama, Score menghasilkan probabilitas untuk setiap level, sedangkan Noul menghasilkan probabilitas jawaban ya.

Kandidat dengan probabilitas tertinggi menjadi choice, sedangkan seberapa terpusat probabilitasnya pada satu kandidat menjadi confidence.

RLCD: melatih probabilitas agar sesuai dengan seberapa sering jawabannya benar

Jev dilatih dengan metode bernama RLCD (reinforcement learning for calibrated decisions, atau pembelajaran penguatan untuk keputusan yang terkalibrasi).

Tujuannya adalah membuat probabilitas yang dikeluarkan Jev sesuai dengan seberapa sering jawabannya benar. Sifat ini disebut kalibrasi.

Probabilitas model terkalibrasi vs jumlah jawaban yang benar
100 jawabandi 0.9100 jawabandi 0.6100 jawabandi 0.2Sekitar 90benarSekitar 60benarSekitar 20benar1 dari 10salah4 dari 10salah8 dari 10salah
Angka-angka ini hanya ilustrasi untuk menggambarkan kalibrasi. Makin rendah probabilitasnya, makin banyak jawaban yang ternyata salah. Karena itu, kamu bisa menangani jawaban secara berbeda sesuai probabilitasnya.

Karena probabilitas mencerminkan seberapa sering jawabannya benar, kamu bisa menarik garis berdasarkan angka yang konkret, misalnya "biarkan Jev menangani sendiri yang 0.9, dan minta manusia memeriksa yang 0.6."

Ringkasan

Jev adalah model System One: kamu memberinya state dan pertanyaan, lalu Jev mengembalikan keputusan beserta probabilitasnya dalam tipe Choice, Score, atau Noul. Karena semua pertanyaan dievaluasi secara paralel, mengirim beberapa pertanyaan sekaligus hampir tidak menambah waktu tunggu.

Saat memasangnya di aplikasi, ingat dua hal berikut.

Pertama, pakai ambang batas untuk membagi confidence yang dikembalikan menjadi beberapa rentang, lalu biarkan kodemu sendiri yang memutuskan mana yang dijalankan otomatis, mana yang perlu dikonfirmasi, dan mana yang diserahkan ke manusia.

Kedua, kerjakan penghitungan jumlah, perbandingan tanggal, dan aritmetika di kodemu.