Bedah Repositori Aider-Chat: Mengapa Repository-Map Berbasis Tree-sitter Mengalahkan RAG Tradisional
Ada satu ilusi yang sering menjebak para insinyur perangkat lunak ketika pertama kali mencoba mengawinkan Large Language Models (LLM) dengan basis kode berukuran raksasa: anggapan bahwa kode program bisa diperlakukan sama seperti tumpukan artikel Wikipedia.
Pendekatan umum yang sering diambil adalah membuat Retrieval-Augmented Generation (RAG) standar. File kode dipotong-potong menjadi pecahan 500 token, dikonversi menjadi vektor melalui model embedding, lalu disimpan di vector database. Ketika pengguna meminta fitur baru atau perbaikan bug, sistem mencari potongan kode yang memiliki kemiripan kosinus (cosine similarity) tertinggi dan menjejalkannya ke dalam prompt.
Hasilnya sering kali mengecewakan.
Kode program bukanlah teks bebas. Memotong fungsi di baris ke-40 hanya karena batas token telah tercapai sama saja dengan memotong jalur pipa rem mobil dan berharap mobil tetap bisa berhenti mulus. Kode memiliki hierarki, lexical scoping, graf pemanggilan (call graph), serta relasi dependensi yang ketat. Sekali relasi itu putus, LLM akan mulai berhalusinasi mengarang argumen fungsi atau mengimpor modul yang tidak pernah ada.
Paul Gauthier, pencipta open-source coding assistant terminal bernama Aider, memilih jalur yang sama sekali berbeda. Alih-alih mengandalkan pencarian vektor yang probabilistik dan rentan meleset, Aider membangun Repository Map (Repo-Map) menggunakan parser Abstract Syntax Tree (AST) deterministik berbasis Tree-sitter, yang dipadukan dengan algoritma graf PageRank.
Hasilnya adalah efisiensi token yang ekstrem, akurasi struktural tinggi, dan kemampuan memandu LLM bernavigasi di dalam monorepo tanpa tersesat. Mari kita bedah bagaimana arsitektur ini bekerja di balik layar.
1. Dosa Asal Naive Code RAG: Mengapa Potongan Vektor Gagal Memahami Software
Untuk memahami keunggulan Repo-Map milik Aider, kita perlu melihat mengapa RAG tradisional sering gagal saat diterapkan pada rekayasa perangkat lunak.
[ Pendekatan Naive RAG ]
Source Code(5.000 baris)
──> Arbitrary Chunking(500 token/chunk)
──> Vector Embeddings
──> Semantic Search
──> Potongan acak masuk konteks LLM(Kehilangan hierarki class & import)
[ Pendekatan Aider Repo-Map ]
Source Code(Monorepo)
──> Tree-sitter AST Parser
──> Ekstraksi Tag(Definisi & Referensi)
──> Directed Graph(PageRank)
──> Dynamic Token-Budgeted Map(Struktur utuh berdensitas tinggi)Ketika kita memecah file auth_service.py menjadi potongan-potongan teks acak, beberapa anomali fatal terjadi:
- Kehilangan Batas Ruang Lingkup (Scope Blindness): Deklarasi class berada di Chunk A, definisi metode inti berada di Chunk B, sementara decorator dan type hinting berada di Chunk C. LLM tidak lagi mengetahui apakah sebuah variabel bersifat privat, global, atau warisan dari parent class.
- Polusi Konteks (Context Noise): Pencarian kemiripan teks sering kali menarik sepuluh implementasi fungsi pembantu (helper utility) yang tidak relevan hanya karena memiliki kata kunci serupa seperti
format_user_data, alih-alih menarik definisi antarmuka (interface) utama yang sebenarnya dicari. - Pemborosan Anggaran Token: Menyuapkan 10 chunk kode mentah berukuran masing-masing 500 token menghabiskan 5.000 token hanya untuk memberikan gambaran parsial. Sebagian besar token tersebut terbuang untuk logika internal fungsi, padahal yang dibutuhkan LLM untuk memahami konteks hanyalah signature fungsi dan relasi antar-berkas.
2. Anatomi Tree-sitter: Membaca Kode Layaknya Kompiler
Tree-sitter adalah pustaka parser inkremental yang awalnya dikembangkan untuk editor teks Atom (dan kini menjadi tulang punggung Neovim serta GitHub Semantic). Berbeda dengan regex yang rapuh atau model embedding yang mengira-ngira makna teks, Tree-sitter membangun Abstract Syntax Tree (AST) konkret secara deterministik dalam hitungan milidetik.
Aider memanfaatkan Tree-sitter untuk membedah file sumber menjadi node-node tata bahasa (grammar nodes). Melalui query language bawaan Tree-sitter (yang berbasis S-expressions), Aider secara spesifik mengekstrak dua entitas penting dari setiap file:
Definitions (Definisi): Di mana sebuah class, method, function, atau variable dideklarasikan.
References (Referensi): Di mana sebuah identifier dipanggil, diinstansiasi, atau diwarisi oleh file lain.
Sebagai gambaran, perhatikan bagaimana Tree-sitter mengekstrak struktur dari kode Python sederhana berikut:
class PaymentProcessor:
def __init__(self, gateway: StripeGateway):
self.gateway = gateway
def charge(self, amount: float, user_id: str) -> bool:
return self.gateway.execute_transaction(user_id, amount)Alih-alih menyimpan seluruh badan fungsi charge, Aider mengekstrak struktur esensial (tags):
Definisi: class PaymentProcessor, def __init__, def charge
Referensi: StripeGateway, execute_transaction
Badan logika internal fungsi dipangkas, menyisakan kerangka ringkas yang mempertahankan tanda tangan tipe (type signatures) dan relasi panggilan.
3. Dari Node Menjadi Graf: Mengadaptasi PageRank untuk Kode Sumber
Mengekstrak seluruh tanda tangan fungsi dari proyek berisi ratusan ribu baris kode masih akan menghasilkan ribuan baris teks yang melebihi batas prompt. Di sinilah kejeniusan arsitektur Aider terlihat: Aider memperlakukan basis kode sebagai sebuah web jaringan sosial antar-simbol.
Membangun Directed Graph Simbol
Aider membangun graf berarah (directed graph) $G = (V, E)$ di mana: $V$ (Vertices/Nodes) adalah file atau simbol (definisi fungsi/kelas). $E$ (Edges) adalah relasi referensi atau impor antara simbol-simbol tersebut.Jika file order_controller.py memanggil PaymentProcessor.charge() yang didefinisikan di payment_service.py, maka terdapat edge berarah dari order_controller.py menuju payment_service.py.
[ order_controller.py ] ──(calls charge)──> [ payment_service.py ]
│ │
│ (imports) │ (instantiates)
▼ ▼
[ auth_middleware.py ] [ stripe_client.py ]Mengukur Kepentingan Simbol dengan PageRank
Sama seperti Google meranking halaman web berdasarkan seberapa banyak situs bereputasi lain yang menautkan link ke halaman tersebut, Aider menjalankan algoritma Personalized PageRank pada graf dependensi kode.File atau modul yang menjadi hub utama (seperti core entity, database client, atau base class yang diimpor oleh puluhan modul lain) akan mendapatkan skor sentralitas graf yang tinggi. Sebaliknya, modul utilitas pinggiran yang hanya dipanggil satu kali akan memiliki bobot rendah.
Ketika developer sedang membuka atau mengedit file tertentu (misalnya checkout_view.py), algoritma PageRank Aider akan dipersonalisasi (biased) dengan memberikan bobot awal lebih tinggi pada simpul file tersebut. Graf kemudian mengalirkan energi sentralitas ke file-file yang berada di sekitar lintasan pemanggilan (call path) terdekat.
4. Algoritma Dynamic Token Budgeting: Kepadatan Informasi Maksimal
Setelah semua node memiliki skor peringkat dependensi, Aider menyusun peta repositori (repo-map) secara bertahap sesuai batas alokasi token yang ditentukan pengguna (biasanya antara 1.024 hingga 4.096 token).
Proses seleksinya berjalan secara rekursif:
- Simpul dengan skor sentralitas tertinggi dimasukkan ke dalam peta beserta deklarasi hierarkinya.
- Jika kuota token masih tersisa, Aider menyertakan tanda tangan fungsi publik (public method signatures).
- Jika kuota semakin menipis, detail fungsi privat dipangkas menjadi sekadar nama kelas atau nama berkas saja.
- Proses berhenti tepat saat estimasi token mencapai batas aman yang ditentukan.
+-------------------------------------------------------------------+
| KONTEN REPO-MAP YANG DITERIMA LLM(Contoh ~350 Token) |
+-------------------------------------------------------------------+
| app/models/user.py: |
| │ class User(BaseModel): |
| │ id: UUID |
| │ email: str |
| │ is_active: bool |
| |
| app/services/billing.py: |
| │ class BillingService: |
| │ def __init__(self, db: DatabaseSession) |
| │ def process_invoice(self, user: User, amount: Decimal) -> bool|
| |
| app/controllers/checkout.py: |
| │ (File target aktif dalam sesi edit) |
+-------------------------------------------------------------------+Dengan format seringkas ini, LLM langsung memahami tipe data User, metode process_invoice milik BillingService, serta lokasi file masing-masing tanpa perlu membaca ribuan baris implementasi SQL atau logika penanganan error.
5. Komparasi Head-to-Head: Tree-sitter Repo-Map vs Vector RAG Tradisional
Berikut adalah perbandingan langsung antara kedua pendekatan dalam konteks pengembangan perangkat lunak nyata:
| Dimensi Evaluasi | Vector RAG Tradisional (Embedding) | Aider Repo-Map (Tree-sitter + PageRank) |
|---|---|---|
| Akurasi Ruang Lingkup | Rendah; rentan memotong blok sintaks di tengah jalan | Mutlak; berbasis parser AST resmi tiap bahasa |
| Konsumsi Token Prompt | Sangat boros (5.000 – 20.000+ token per query) | Sangat hemat (1.000 – 4.000 token padat struktur) |
| Biaya Komputasi Indeks | Mahal (API call embedding berulang setiap ada perubahan) | Nyaris gratis (Parsing CPU lokal dalam hitungan milidetik) |
| Kepekaan Dependensi | Buta dependensi; hanya mencocokkan kemiripan teks | Memahami relasi caller-callee dan pewarisan kelas |
| Dukungan Monorepo | Lambat dan menimbulkan banyak false-positive semantik | Berskala baik; PageRank menyaring file inti secara presisi |
| Risiko Halusinasi Impor | Tinggi (LLM sering salah menebak path modul) | Sangat rendah (Path modul dan tipe data tertera eksplisit) |
| Kebutuhan Infrastruktur | Butuh Vector DB eksternal, embedding pipeline | Cukup satu binary lokal tanpa dependensi database |
6. Implementasi Sederhana: Membangun Ekstraktor AST Sederhana dengan Python
Untuk melihat betapa elegannya ekstraksi AST ini, kita bisa membuat prototipe sederhana menggunakan pustaka tree-sitter-languages di Python. Script ini mendeteksi definisi fungsi dan pemanggilan fungsi dalam hitungan milidetik tanpa memanggil model bahasa apa pun.
import tree_sitter_languages
def extract_code_skeleton(source_code: str, language: str = "python") -> list[dict]:
parser = tree_sitter_languages.get_parser(language)
tree = parser.parse(bytes(source_code, "utf8"))
# Query Tree-sitter untuk menangkap definisi fungsi dan class
query_scm = """
(class_definition
name: (identifier) @class_name)
(function_definition
name: (identifier) @func_name
parameters: (parameters) @params)
"""
query = tree_sitter_languages.get_language(language).query(query_scm)
captures = query.captures(tree.root_node)
skeleton = []
for node, tag in captures:
line_no = node.start_point[0] + 1
text = node.text.decode("utf8")
skeleton.append({
"tag": tag,
"identifier": text,
"line": line_no
})
return skeleton
# Uji coba pada potongan kode
sample_python = """
class OrderManager:
def create_order(self, customer_id: int, items: list) -> dict:
validated = self._validate_stock(items)
return {"status": "success", "id": 101}
def _validate_stock(self, items: list) -> bool:
return True
"""
tags = extract_code_skeleton(sample_python)
for t in tags:
print(f"L{t['line']:02d} | [{t['tag']}] {t['identifier']}")Output yang dihasilkan langsung memetakan kerangka kerja tanpa menyertakan logika internal:
L02 | [class_name] OrderManager
L03 | [func_name] create_order
L03 | [params] (self, customer_id: int, items: list)
L07 | [func_name] _validate_stock
L07 | [params] (self, items: list)Ketika representasi ini dikirimkan bersama graf relasi antar-file, model penalaran (reasoning models) modern seperti Claude 3.7 Sonnet, DeepSeek V3/R1, atau GPT-4o dapat langsung menyimpulkan seluruh arsitektur proyek tanpa kebingungan.
7. Panduan Praktis Menggunakan Aider dengan API Gateway Berkinerja Tinggi
Menggunakan Aider di lingkungan kerja lokal sangat mudah, tetapi tantangan sebenarnya muncul pada lapisan model: bagaimana mengalirkan kode ke model penalaran terbaik tanpa terbentur kendala kuota, latensi lambat, atau kerumitan metode pembayaran kartu kredit luar negeri.
Di sinilah peran orkestrasi API menjadi krusial. Melalui gateway terpadu seperti AiStudio.id API Gateway, developer dapat menghubungkan Aider langsung ke berbagai model terkemuka (Claude 3.5/3.7 Sonnet, DeepSeek-V3, DeepSeek-R1, hingga OpenAI o3-mini) menggunakan satu antarmuka kompatibel OpenAI dengan penagihan lokal berbasis Rupiah.
Berikut adalah panduan langkah demi langkah untuk mengonfigurasi Aider dengan infrastruktur API Gateway:
[ Developer Terminal(Aider CLI) ]
│
│ (Tree-sitter Repo-Map + User Prompt)
▼
[ AiStudio.id API Gateway ] ──> Routing Pintar & Failover
│
┌─────────────┼─────────────┐
▼ ▼ ▼
[Claude 3.7] [DeepSeek R1] [GPT-4o]Langkah 1: Pasang Aider di Lingkungan Lokal
Pastikan Python 3.10+ sudah terpasang, lalu instal Aider:pip install aider-chatLangkah 2: Konfigurasi Endpoint AiStudio.id API Gateway
Buat file konfigurasi.aider.conf.yml pada direktori root proyek Anda atau atur environment variable terminal untuk mengarahkan lalu lintas API ke gateway:
# Set OpenAI Base URL ke AiStudio.id Gateway
export OPENAI_API_BASE="https://api.aistudio.id/v1"
export OPENAI_API_KEY="sk-aistudio-anda-yang-sebenarnya"Langkah 3: Jalankan Aider dengan Model Pilihan
Anda dapat langsung menjalankan Aider dengan menentukan model target yang paling optimal untuk pemrograman, misalnya DeepSeek-V3 atau Claude Sonnet:# Menjalankan Aider dengan repositori map aktif (default 1024 token budget)
aider --model openai/deepseek-chat --map-tokens 2048Saat pertama kali dijalankan, Aider akan memindai repositori Anda, mengindeks struktur kode menggunakan Tree-sitter, menghitung PageRank, dan menampilkan ukuran Repo-Map yang berhasil dipadatkan:
Creating repo map for 142 files...
Repo-map: 1.842 tokens(menghemat ~94% token dibandingkan pembacaan file mentah)
Model: openai/deepseek-chat via AiStudio.id Gateway
Aider v0.74.0 is ready.Kombinasi antara efisiensi Repo-Map lokal dan keandalan gateway API berlatensi rendah memastikan proses refactoring multi-file berjalan instan tanpa resiko kehabisan batas token konteks (context overflow).
8. Mengapa Monorepo Membutuhkan Deterministik AST, Bukan Pencarian Probabilistik
Ketika proyek tumbuh dari sepuluh berkas menjadi ribuan modul monorepo, kelemahan sistem berbasis pure vector search menjadi tidak dapat ditoleransi. Masalah utamanya berakar pada sifat probabilitas:
- Efek Homonim Kode (The Homonym Problem): Di monorepo skala besar, mungkin ada 30 fungsi berbeda yang bernama
validate(),save(), ataurender(). Embedding semantik sering gagal membedakanvalidate()milik modul otentikasi denganvalidate()milik modul formulir HTML. Sebaliknya, Tree-sitter mengisolasi namespace dan jalur impor secara absolut. - Kerapuhan Inkremental (Incremental Cost): Dalam repositori aktif dengan ratusan commit per hari, memperbarui indeks vektor membutuhkan proses chunking dan embedding ulang yang memakan waktu dan biaya. Parser Tree-sitter berjalan inkremental: saat Anda mengedit 10 baris kode, Tree-sitter hanya memperbarui sub-tree yang berubah dalam hitungan mikrodetik langsung di memori RAM komputer Anda.
- Pemberian Konteks Dua Arah (Bi-directional Context): LLM tidak hanya perlu tahu apa yang ada di dalam file yang sedang diedit, tetapi juga siapa yang memanggil file ini dari luar. Pendekatan graf PageRank Aider secara otomatis menarik informasi bahwa fungsi yang sedang diubah memiliki dependensi kritis di lima modul hulu (upstream modules), mencegah LLM menghasilkan kode yang merusak breaking changes.
9. Sinergi Deterministik dan Probabilistik: Standar Baru AI Coding Assistant
Arsitektur Repo-Map Aider memberikan pelajaran berharga bagi masa depan arsitektur aplikasi berbasis LLM: model probabilistik bekerja paling optimal jika disokong oleh struktur data deterministik.
Menyerahkan seluruh tugas navigasi kode kepada model embedding vektor adalah bentuk kemalasan arsitektur yang harus dibayar mahal dengan pemborosan token dan tingginya tingkat halusinasi.
Dengan menggabungkan kekuatan kompilator murni (Tree-sitter AST) untuk membedah fakta sintaksis, teori graf (PageRank) untuk menyaring relevansi arsitektural, dan LLM mutakhir sebagai mesin penalaran generatif, Aider membuktikan bahwa efisiensi dan presisi dapat dicapai secara bersamaan.
Bagi developer dan kreator teknologi, memahami pergeseran ini bukan sekadar urusan memilih alat bantu koding di terminal. Ini adalah cetak biru baru dalam mendesain sistem AI: jangan membebani model dengan tumpukan jerami informasi mentah jika kita bisa memberikannya peta navigasi yang ringkas, akurat, dan terstruktur sejak awal.
Catatan Penulis

> Sandra menulis seputar rekayasa prompt, efisiensi arsitektur AI, dan produk digital di AiStudio.id.