Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

hyprask

CLI tool berbasis C++ yang menerapkan Retrieval-Augmented Generation (RAG) untuk menjawab pertanyaan seputar isi file konfigurasi Hyprland (window manager Linux berbasis Wayland), dengan jawaban yang wajib bersitasi ke path:line sumber aslinya di config kamu.

Prinsip inti: read-only (tidak pernah mengedit config), jawaban HANYA berdasarkan isi config yang beneran ada (bukan pengetahuan umum LLM), dan setiap klaim harus bisa ditelusuri balik ke baris config yang tepat.


Kenapa dibuat

Pengguna Hyprland yang konfigurasinya kompleks (banyak file, saling source, ratusan baris) sering kesulitan mencari pengaturan tertentu tanpa hafal struktur filenya. hyprask memungkinkan tanya pakai bahasa natural ("gimana cara buka terminal?") dan dapat jawaban akurat lengkap dengan sitasi presisi, tanpa perlu grep manual.


Cara kerja (pipeline RAG)

Fase indexing (dijalankan sekali/berkala, offline):

hyprland.conf --[parser]--> chunk --[embedding API]--> vector --[simpan]--> vector store

Fase query (tiap kali kamu tanya):

pertanyaan --[embed]--> vector --[cari mirip]--> top-k chunk --[+ LLM]--> jawaban bersitasi

Instalasi

Dependency

  • CMake >= 3.16
  • Compiler C++17 (g++/clang++)
  • libcurl (dev headers): sudo apt install libcurl4-openssl-dev

Semua dependency lain (toml++, nlohmann/json) sudah di-vendor di third_party/, tidak perlu package manager tambahan.

Build

mkdir build && cd build
cmake ..
cmake --build .

Binary hypraskcpp akan ada di folder build/. Nama binary bisa di-custom tanpa edit source:

cmake -DHYPRASK_APP_NAME='"namabaru"' ..

Setup awal

hypraskcpp init

Wizard bakal nanya lokasi hyprland.conf, provider embedding & LLM (base_url, model, nama env var API key), lalu otomatis nawarin lanjut parse dan index.

Sebelum jalanin, set API key sesuai yang diminta wizard:

export HYPRASK_EMBEDDING_API_KEY="sk-..."
export HYPRASK_LLM_API_KEY="sk-..."

Support provider apapun yang OpenAI-compatible — termasuk model lokal kayak Ollama (base_url = "http://localhost:11434/v1"), tanpa perlu ubah kode sama sekali.


Pemakaian

Tanya sekali (stateless)

hypraskcpp ask "gimana cara buka terminal?"
hypraskcpp ask "berapa top-k yang dipakai?" --no-llm   # cuma print hasil retrieval, skip LLM

Mode chat (inget histori percakapan)

hypraskcpp chat --session harian

Retrieval "sadar konteks" (gabung 1-2 pertanyaan terakhir + pertanyaan baru jadi query pencarian), replay histori lengkap kalau resume session lama, label warna beda buat You:/Assistant:.

hypraskcpp history                    # list semua session tersimpan
hypraskcpp history --session harian   # lihat isi 1 session (read-only)

Cek kesehatan setup

hypraskcpp status

Ngecek: config.toml valid, hyprland.conf bisa dibaca, API key ke-set, host embedding/LLM bisa dijangkau (HTTP CONNECT-ONLY, bukan ICMP — tanpa kena biaya API), chunks/vectors ada, staleness index vs config terbaru, jumlah session tersimpan.

Evaluasi kualitas retrieval

hypraskcpp eval dataset.json
hypraskcpp eval dataset.json --k 5   # override top_k, sekali pakai doang

Baca dataset Q&A ground-truth, hitung Hit Rate dan MRR (Mean Reciprocal Rank). Matching-nya range-aware: cocok kalau baris yang di-expected ada di dalam rentang [line, endLine] hasil retrieval — jadi 1 dataset yang sama valid dipakai baik strategi line maupun block.

Format dataset:

[
  { "question": "gimana cara buka terminal?", "expected": ["UserKeybinds.conf:23"] },
  { "question": "berapa resolusi monitor utama?", "expected": ["monitors.conf:3"] }
]

Strategi chunking

hypraskcpp parser              # lihat strategi aktif
hypraskcpp parser change       # toggle line <-> block, tersimpan ke config.toml
  • line — 1 baris config = 1 chunk, sitasi presisi 1 baris
  • block — baris dalam { } digabung jadi 1 chunk (konteks nested ikut kebawa, misal decoration { shadow {...} blur {...} } jadi 1 kesatuan), sitasi jadi rentang baris

Dua strategi hidup bersamaan di disk (chunks_line.json / chunks_block.json, vectors_line.json / vectors_block.json), tidak saling timpa. ask/chat/eval otomatis pakai file sesuai strategi yang lagi aktif.


Konfigurasi

~/.config/hypraskcpp/config.toml:

[paths]
hyprland_conf = "~/.config/hypr/hyprland.conf"

[embedding]
provider    = "openai"
model       = "text-embedding-3-small"
base_url    = "https://api.openai.com/v1"
api_key_env = "HYPRASK_EMBEDDING_API_KEY"

[llm]
provider    = "openai"
model       = "gpt-4o-mini"
base_url    = "https://api.openai.com/v1"
api_key_env = "HYPRASK_LLM_API_KEY"

[retriever]
top_k = 8

[chat]
history_turns = 5

[parser]
strategy = "line"

Semua field punya default kalau tidak diisi — config.toml boleh parsial.


Visualisasi (tree viewer)

web/tree_viewer.html — buka isi index dalam bentuk visual:

cd ~/.local/share/hypraskcpp
python3 -m http.server 8000
# buka http://localhost:8000/tree_viewer.html
  • Auto-detect chunks_line.json/chunks_block.json, tab switcher kalau dua-duanya ada
  • Mode List (tree berdasar source chain, expand/collapse per node atau semua sekaligus)
  • Mode True AST — diagram visual dengan pan/zoom, parse key = value jadi node nested per argumen, sub-blok (shadow {}, blur {}) jadi node terpisah yang bisa dibuka-tutup sendiri

Catatan: ini tree berdasarkan source chain (file mana nge-source file mana) dan struktur blok { }, bukan AST grammar penuh dari bahasa config Hyprland.


Arsitektur

include/
├── config/       app_identity, xdg_paths, config (baca/tulis TOML), config_wizard
├── parser/       source-chain resolver + chunker (strategi line & block)
├── embedding/     HTTP client ke endpoint /embeddings (OpenAI-compatible)
├── indexer/       orkestrasi batch -> embed -> simpan
├── store/         vector store: brute-force cosine similarity, JSON manual
├── retriever/      embed pertanyaan + panggil topK()
├── llm/           HTTP client ke endpoint /chat/completions
├── answer/        build_prompt (SYSTEM_PROMPT + Context + Question), render (CLI box UI)
├── chat/          REPL interaktif + histori
├── session/        simpan/baca histori percakapan (JSON per nama session)
├── status/         cek kesehatan setup
├── eval/          evaluasi retrieval otomatis (Hit Rate, MRR)
third_party/       toml++, nlohmann/json (vendored)
web/               tree_viewer.html

Keputusan desain

  • Vector store: JSON manual + brute-force cosine similarity, bukan SQLite/ChromaDB — cukup buat skala ratusan chunk, exact search (bukan approximate), tanpa dependency tambahan. Titik upgrade cuma di 1 fungsi (topK()) kalau suatu saat perlu ganti ke ANN library.
  • Embedding dense/semantic, bukan BM25/TF-IDF murni — user nanya pakai bahasa natural yang sering beda kata literal dari isi config (misal "terminal" vs "kitty" di config).
  • Provider-agnostic — base_url bebas dikonfigurasi, jadi jalan ke cloud API atau model lokal tanpa ubah kode.

Keterbatasan yang diketahui

  • Evaluasi baru mengukur kualitas retrieval (Hit Rate, MRR), belum ada pengukuran kualitas generation (faithfulness/halusinasi jawaban LLM).
  • Belum ada hybrid search (embedding + keyword/BM25).
  • top_k default (8) belum dioptimasi lewat eksperimen sistematis.
  • Read-only murni — tidak ada fitur edit config dari dalam app.

Lisensi & status

Project belajar C++ sekaligus draft riset RAG diterapkan ke domain file konfigurasi sistem (belum banyak diteliti dibanding domain dokumen naratif seperti PDF/artikel ilmiah).

About

CLI tool berbasis C++ yang menerapkan Retrieval-Augmented Generation (RAG) untuk menjawab pertanyaan seputar isi file konfigurasi Hyprland (window manager Linux berbasis Wayland), dengan jawaban yang wajib bersitasi ke path:line sumber aslinya di config lokal..

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages