[개발기] Mencari Percakapan Sebelumnya Terminal Agent Hanya dengan SQLite - Mengapa Harus Melakukan Analisis Morfologi Bahasa Korea?

116.126.***.***
11

Artikel ini adalah kisah pengembangan fitur seCall — alat CLI untuk mengumpulkan dan mencari sesi percakapan agen AI. Dibuat sebagai bagian dari proyek pengujian Vibe Coding, jadi saya tidak tahu dan tidak ingin tahu detail kodenya. Tidak perlu tahu. Malah jadi berantakan kalau tahu Namun saya menulis ini karena ingin menjelaskan teknologi yang digunakan dalam fitur-fitur yang diterapkan setelah melalui coba-coba, dan alasan pengenalan mereka.

Masalah: Ada Terlalu Banyak Percakapan AI

Puluhan percakapan menumpuk setiap hari. Momen seperti "Apa yang saya katakan tentang BM25 minggu lalu?" terjadi setiap hari. Tetapi Claude Code menyimpan di ~/.claude dalam JSONL, ChatGPT mengekspor ZIP, dan Codex di suatu tempat di bawah ~/.codex... semuanya tersebar dalam format berbeda. Dan percakapan bersifat FIFO sehingga percakapan lama dengan cepat tertarik ke atas dan sulit dicari (AI berbicara sangat panjang) Juga, setelah sesi terputus, sulit untuk menemukan sesi mana yang berisi percakapan sebelumnya. Jadi saya juga mencatat sesi terakhir di resume.md. 😇

Yang saya inginkan sederhana: Mengumpulkan semuanya di satu tempat, mencari dalam bahasa Korea, dan semoga ada terstruktur di suatu tempat sehingga saya dapat meninjau proyek di waktu luang.

Mengapa SQLite?

Ketika berbicara tentang mesin pencari, Elasticsearch terlintas terlebih dahulu, dan ada banyak alat open source yang menonjol seperti ChromaDB untuk VectorDB, tetapi saya pikir berlebihan untuk menjalankan layanan berbasis JVM untuk alat pribadi. Jadi saya memutuskan untuk tetap ringan. Saya bisa menggunakan PostgreSQL untuk membuat buku harian pribadi, tapi itu sangat berlebihan.

Alasan memilih SQLite:

  • Tidak ada yang perlu diinstal. Satu file adalah database (cukup untuk penggunaan pribadi)

  • Metadata dan indeks pencarian di satu tempat. Penyaringan agen, proyek, tanggal dan pencarian teks lengkap dalam satu kueri

  • FTS5, mesin pencari teks lengkap bawaan. Bahkan mendukung peringkat BM25

Tidak ada alasan untuk tidak menggunakannya.

Apa itu FTS5?

Full-Text Search 5 — ekstensi pencarian teks lengkap bawaan SQLite.

LIKE '%cari%' biasa harus memindai seluruh tabel, tetapi FTS5 membuat indeks terbalik terlebih dahulu. Ini mencatat berapa kali setiap kata muncul untuk setiap dokumen, dan saat pencarian hanya melihat indeks itu. Bahkan dari ribuan percakapan, hasilnya muncul dalam hitungan milidetik.

Selain itu, peringkat BM25 juga bawaan. Ini mengurutkan berdasarkan relevansi dengan mempertimbangkan berapa kali istilah pencarian muncul dalam dokumen dan seberapa jarang kata itu di antara semua dokumen. Ini adalah algoritma yang sama dengan yang digunakan oleh pencarian Google.

Masalah: FTS5 Tidak Memahami Bahasa Korea

Di sini saya menghadapi dinding. Sebelumnya, ketika mencoba reimplementasi QMD (skrip Python + menggunakan BM25 untuk mem-parse sesi Claude Code ke vault Obsidian — proyek serupa yang mungkin paling terkenal) ke versi Gemini, saya juga menyerah pada bagian ini. Saya berpikir apakah perlu belajar tokenizer sampai seperti itu dan menyerah, tetapi kebetulan guru Andrej Karpathy kami (anggota pendiri OpenAI -> kepala AI Tesla) melempar topik di wiki, jadi saya mencoba lagi dan itulah yang menyebabkan lahirnya seCall, proyek super populer dengan 50 bintang GitHub(?)

Tokenizer default FTS5 membagi kata berdasarkan spasi dan tanda baca. Ini cukup untuk bahasa Inggris tetapi tidak untuk bahasa Korea.

Masalahnya adalah

Jika disimpan sebagai "임베딩 모델을 최적화했습니다", FTS5 membaginya dengan gaya Inggris menjadi "임베딩" "모델을" "최적화했습니다", dan dalam keadaan ini jika saya mencari "모델", itu tidak cocok dengan "모델을". Hal yang sama berlaku untuk "최적화". Ketika diterapkan ke bahasa Korea (CJK sama), ini menjadi tidak berguna. Jadi bahasa Korea memerlukan analisis morfologi terpisah (proses memecah kata menjadi unit bermakna).

Dengan analisis morfologi, dibagi menjadi "임베딩" "모델" "최적화", jadi sekarang ketika saya mencari "모델", pencarian berhasil.

Solusi: Potong Dulu di Rust Sebelum Dimasukkan

Memasukkan analis bahasa Korea ke FTS5 itu sendiri akan memerlukan penulisan perpanjangan baru dalam bahasa C dengan cara apa pun, sehingga merepotkan. Sebaliknya, saya menggunakan metode yang lebih praktis:

  1. Saat menyimpan percakapan: Analisis morfologi bahasa Korea di Rust → sambungkan kata-kata yang dianalisis dengan spasi dan simpan ke FTS5

  2. Saat mencari: Istilah pencarian juga melewati analis morfologi yang sama sebelum kueri FTS5

Karena kedua sisi penyimpanan dan pencarian melewati analis yang sama, dari perspektif FTS5 hanya menangani kata-kata yang sudah diatur dengan rapi. Pola ini disebut Pre-Tokenization. Ini adalah cara untuk tokenisasi lebih awal di depan mesin pencari. (Jika Anda menerapkan konsep seperti layering, pipeline, alur kerja objek seperti ini, kualitas Vibe Coding menjadi lebih baik)

Analis Morfologi Bahasa Korea: Lindera

Dan pada lapisan yang benar-benar membutuhkan tokenizer, saya menjelajahi lautan open source. Saya memilih Lindera sebagai analis morfologi.

  • Kamus bahasa Korea berbasis MeCab (ko-dic) disertakan sepenuhnya dalam biner

  • Berfungsi segera tanpa unduhan tambahan atau layanan eksternal

  • Native Rust jadi build sekaligus selesai

Trade-off adalah ukuran biner meningkat ~80MB. Tetapi saya pikir tingkat ini dapat diterima dalam proyek pribadi. Sebagai alternatif, saya juga menyediakan Kiwi (analis khusus bahasa Korea) sebagai opsi. Saya kemudian mengetahui bahwa ada evaluasi bahwa kualitas analisis Kiwi lebih baik, jadi itu menjadi opsi. Sepertinya tidak ada perbedaan besar secara aktual.

Penyaringan Bagian Ucapan: Hanya Menyimpan Kata yang Bermakna

Jika saya mengindeks semua potongan yang dihasilkan oleh analis morfologi, pencarian menjadi tidak akurat.

"임베딩 모델을 최적화했습니다"

Semua morfologi → 임베딩 / 모델 / 을 / 최적화 / 하 / 았 / 습니다

"을", "하", "았", "습니다" tidak berguna untuk pencarian. Jadi saya memilih hanya bagian ucapan dengan makna untuk disimpan:

  • Kata benda (모델, 최적화, 검색, SQLite)

  • Kata kerja/Kata sifat (구현하다, 빠르다)

  • Bahasa asing (embedding, vector, BM25)

Partikel, akhiran, dan sufiks semuanya dibuang. Token satu karakter juga menjadi kebisingan sehingga dihapus.

Hasil: "임베딩" "모델" "최적화" — hanya inti yang diperlukan untuk pencarian yang tersisa. Untuk menghilangkan kebisingan sebanyak mungkin, saya melakukan layering dengan kata benda, kata kerja/kata sifat, dan bahasa asing. Ketika sampai ke vektor db, kualitas chunk pada akhirnya menjadi kualitas konteks. Anda harus mengurangi kebisingan sebanyak dan sejauh mungkin. (Dan tren yang lebih baru adalah memasukkan teks percakapan asli, dokumen RAG langsung ke DB dan melakukan layering dengan memisahkan, mengompresi, menata morfologi dari sana. Keuntungannya adalah Anda dapat mengubah algoritma dan mengindeks ulang terlepas dari berapa banyak kebisingan yang dihasilkan)

Mengapa Tidak Menggunakan sqlite-vec

Rencana awal adalah menyelesaikan FTS5 (pencarian teks) + sqlite-vec (pencarian vektor) semuanya dalam SQLite. (Semua orang melakukannya!) Tetapi sqlite-vec mengalami kesalahan kompilasi C di Mac saya. Karena masih versi alfa (0.1), kompatibilitas platform tidak stabil.

Pada akhirnya saya menyelesaikan bagian vektor dengan cara lain, tetapi jika ada yang tertarik, saya akan menjelaskan bagaimana saya menerapkan pencarian vektor untuk menemukan "percakapan dengan makna serupa" yang sulit dicari dengan pencocokan teks saja.

Inti dari semuanya adalah melakukan pencarian teks lengkap bahasa Korea pada satu SQLite tanpa layanan eksternal. Dengan menggunakan jalan pintas yang disebut Pre-Tokenization, saya dapat dengan rapi melewati masalah bahwa FTS5 tidak memahami bahasa Korea.

Teknologi

Peran

Alasan Pemilihan

SQLite FTS5

Pencarian teks lengkap + peringkat BM25

Zero infrastructure, DB file tunggal

Lindera (ko-dic)

Analisis morfologi bahasa Korea

Native Rust, tidak ada ketergantungan eksternal

Pre-Tokenization

Tambahkan dukungan bahasa Korea ke FTS5

Selesaikan secara praktis tanpa ekstensi C

Penyaringan Bagian Ucapan

Tingkatkan presisi pencarian

Hapus kebisingan partikel/akhiran

Posting ini ditulis tanpa Vibe. Silakan baca dengan tenang 😁 Mengembangkan agen tanpa rencana bukanlah pengembangan agen. Ini adalah kolaborasi dua orang tiga kaki antara pengetahuan domain kecerdasan manusia yang dibangun melalui pengalaman dan pekerjaan akurat yang tidak kenal lelah dari kecerdasan buatan yang melesat sembarangan.

로그인한 회원만 댓글 등록이 가능합니다.

개발한당

KR | ID | EN
  • IDR
  • KOR
8.35 -0.01

2026.07.10 KEB 하나은행 고시회차 1102회

다가오는 한인 행사일정

  • 등록 된 일정이 없어요!