Server layanan daring untuk boneka AI Riri Boneka berbasis ESP32-S3.
Satu server menyediakan tiga layanan sekaligus:
| Layanan | Isi |
|---|---|
| RAG data kampus | Menjawab pertanyaan tentang Universitas Catur Insan Cendekia dari dokumen, tanpa mengarang |
| Pencarian web | Data terkini lewat DuckDuckGo dengan penyaring wilayah Indonesia dan mode berita |
| Pemutar musik | Mencari lagu lewat YouTube Data API lalu menyiapkannya untuk diputar boneka |
| Endpoint | Fungsi |
|---|---|
GET /health |
Status server, kesiapan RAG, dan kesiapan musik |
GET /campus/query?q=... |
RAG data kampus |
GET /search?q=...®ion=id-id |
Pencarian web |
GET /music/resolve?song=...&artist=... |
Cari dan siapkan lagu |
GET /music/audio/<berkas>.mp3 |
Sajikan berkas lagu |
Permintaan musik memerlukan header autentikasi kunci dinamis dari firmware. Endpoint RAG dan pencarian sengaja terbuka supaya mudah diuji dari peramban.
Panduan langkah demi langkah lengkap ada di DEPLOY_CLOUDRUN.md.
Ringkasnya, setelah Google Cloud CLI terpasang dan penagihan proyek aktif:
gcloud run deploy riri-server `
--source . `
--region asia-southeast2 `
--allow-unauthenticated `
--memory 2Gi --cpu 2 --timeout 600 --no-cpu-throttling `
--set-env-vars "RIRI_SECRET_KEY=riri-boneka-2026,REQUIRE_AUTH=true"Ambil alamat layanannya:
gcloud run services describe riri-server --region asia-southeast2 --format="value(status.url)"Lalu isikan alamat itu ke firmware lewat idf.py menuconfig, menu
Riri Boneka, bagian URL server Riri.
Wilayah asia-southeast2 adalah Jakarta, yang paling dekat sehingga jawabannya
paling cepat sampai ke boneka.
Cloud Run punya kuota gratis bulanan yang jauh melebihi pemakaian satu boneka.
Dengan --min-instances=0 layanan berhenti total saat menganggur sehingga tidak
ada biaya berjalan, tetapi permintaan pertama setelah lama diam memerlukan waktu
bangun sekitar 20 sampai 40 detik. Firmware sudah membatasi waktu tunggunya, jadi
bila server belum bangun, Riri memakai data kampus lokal lebih dulu dan tidak
pernah diam menggantung.
copy .env.example .env
# isi YOUTUBE_API_KEY di dalam .env
docker compose up -d --buildServer tersedia di http://<ip-komputer>:8000. Redis ikut dijalankan otomatis.
Tanpa Docker:
pip install -r requirements.txt
# pasang ffmpeg lalu pastikan ada di PATH
python app.pyAlur disusun memakai LangGraph:
masuk -> router -> penulisan ulang kueri -> pencarian hibrida
-> pemeringkatan ulang -> penilaian kecukupan -> penyusunan jawaban
-> refleksi diri -> keluar
| Tahap | Peran |
|---|---|
| Router | Menentukan pertanyaan ini soal kampus atau umum |
| Penulisan ulang kueri | Memperluas singkatan prodi seperti TI dan DKV, lalu menyambungkan konteks pertanyaan sebelumnya dari memori |
| Pencarian hibrida | Menggabungkan pencarian vektor dan BM25 memakai Reciprocal Rank Fusion |
| Pemeringkatan ulang | Cross-encoder menilai ulang potongan, sifatnya wajib |
| Corrective RAG | Bila skor tertinggi di bawah ambang, pencarian diulang dengan kata kunci inti |
| Penyusunan jawaban | Menyusun jawaban hanya dari potongan yang lolos ambang |
| Refleksi diri | Menolak jawaban yang tidak memuat satu pun kata kunci pertanyaan |
Jawaban hanya disusun dari potongan dokumen yang benar-benar terambil. Bila skor
pemeringkat ulang di bawah RERANK_MIN_SCORE, server mengembalikan status
not_found, dan firmware memakai basis data kampus lokalnya sendiri. Refleksi
diri menambah satu lapis lagi dengan menolak jawaban yang tidak berhubungan
dengan pertanyaan.
Pertanyaan kampus banyak memuat nama dosen, singkatan prodi, dan angka semester. Kemiripan vektor sering meleset pada hal seperti itu, sedangkan BM25 kuat pada pencocokan kata persis. Menggabungkan keduanya membuat pertanyaan seperti "dosen Algoritma dan Pemrograman 2" tidak tertukar dengan "Algoritma dan Pemrograman".
Memakai AsyncDDGS sehingga permintaan tidak memblokir proses dan suara boneka
tidak putus-putus saat pencarian berjalan.
| Perilaku | Keterangan |
|---|---|
| Wilayah | region='id-id' untuk hasil Indonesia |
| Berita | news() dipakai otomatis saat kueri memuat kata seperti berita, kabar, atau terkini |
| Rentang waktu | timelimit diisi d, w, m, atau y sesuai frasa "hari ini", "minggu ini", "bulan ini", "tahun ini" |
| Singgahan | Hasil disimpan sepuluh menit di Redis, sehingga berita yang sama tidak ditembak berulang dan tidak kena batas laju |
| Batas bacaan | Hanya dua kalimat pertama yang dikirim ke perangkat, supaya boneka cepat mulai berbicara |
Bila REDIS_URL kosong, singgahan otomatis memakai memori proses sehingga
server tetap berjalan tanpa Redis.
Pencarian memakai YouTube Data API v3 dengan kategori Music dan wilayah ID,
sehingga rekaman penyanyi aslinya ditemukan, baik lagu internasional maupun lagu
populer Indonesia.
Berkas ditranskode menjadi MP3 mono 24 kHz sekitar 96 kbps, laju yang sama persis dengan keluaran codec boneka. Dengan begitu ESP32 hanya perlu mendekode, tanpa mencampur stereo ke mono dan tanpa mengubah laju cuplik. Beban CPU turun banyak dan kebutuhan jaringan hanya sekitar 12 KB per detik, sehingga suara tidak patah-patah.
| Variabel lingkungan | Bawaan | Keterangan |
|---|---|---|
RIRI_SECRET_KEY |
riri-boneka-2026 |
Harus sama dengan firmware |
YOUTUBE_API_KEY |
kosong | Kunci YouTube Data API v3 |
YOUTUBE_REGION |
ID |
Wilayah pencarian lagu |
REDIS_URL |
kosong | Kosong berarti singgahan memori proses |
CACHE_TTL_SEARCH |
600 |
Umur singgahan pencarian, dalam detik |
RERANK_MIN_SCORE |
0.15 |
Ambang kecukupan potongan |
TTS_MAX_SENTENCES |
2 |
Batas kalimat yang dibacakan dari hasil web |
REQUIRE_AUTH |
true |
Matikan hanya saat menguji |
Kunci YouTube bawaan tersimpan di dalam config.py atas permintaan pemilik
proyek. Kunci yang terlihat publik biasanya ditemukan perayap otomatis dalam
hitungan jam, lalu kuotanya dipakai orang lain sampai habis. Bila pencarian lagu
tiba-tiba berhenti bekerja, itulah penyebab yang paling mungkin.
Cara memperbaikinya: buat kunci baru di Google Cloud Console, hapus yang lama, lalu isi lewat variabel lingkungan yang selalu mengalahkan nilai bawaan:
gcloud run services update riri-server `
--region asia-southeast2 `
--update-env-vars "YOUTUBE_API_KEY=kunci-baru-anda"Taruh berkas baru di folder data/. Format yang dikenali: .pdf, .docx,
.html, .txt, .md, .json, dan .csv.
Berkas data/kampus_ucic.md dihasilkan dari main/campus_data.cc pada
repositori firmware, supaya server dan firmware memakai sumber data yang sama
persis. Jalankan ulang server setelah menambah dokumen agar indeksnya dibangun
ulang.
MIT.