Metadata-Version: 2.5
Name: cokgine
Version: 0.3.0
Summary: Standalone Ollama-like LLM engine (MLX: Metal, CUDA; llama.cpp: all-core CPU) with built-in genetic AI
Author: Kridho Cokro
License-Expression: LicenseRef-Proprietary
Keywords: cuda,genetic-algorithm,gguf,llama.cpp,llm,metal,mlx,ollama
Requires-Python: <3.13,>=3.12
Requires-Dist: fastapi>=0.115
Requires-Dist: huggingface-hub>=0.33
Requires-Dist: mlx-lm<0.32,>=0.31
Requires-Dist: mlx>=0.31.2
Requires-Dist: rich>=13.9
Requires-Dist: typer>=0.12
Requires-Dist: uvicorn>=0.32
Provides-Extra: cpu
Requires-Dist: mlx[cpu]; extra == 'cpu'
Provides-Extra: cuda
Requires-Dist: mlx[cuda12]; extra == 'cuda'
Provides-Extra: native
Requires-Dist: jinja2>=3; extra == 'native'
Requires-Dist: llama-cpp-python>=0.3.30; extra == 'native'
Provides-Extra: vision
Requires-Dist: mlx-vlm>=0.3; extra == 'vision'
Description-Content-Type: text/markdown

# cokgine

Engine AI mandiri ala Ollama lintas platform (macOS Apple Silicon, Linux CUDA, Linux CPU) — load model LLM dari
HuggingFace dan jalankan in-process: [MLX](https://github.com/ml-explore/mlx) (Metal/CUDA) untuk model
`mlx-community/...`, atau llama.cpp via `llama-cpp-python` (CPU semua core, keluarga mesin yang sama dengan Ollama)
untuk model GGUF — plus evolusi prompt dengan algoritma genetika bawaan. Tanpa Ollama, tanpa server perantara.

```
┌─────────────┐   ┌───────────────────────────────────────────────────┐
│ CLI / REST  │──▶│ EngineService ──▶ AutoBackend ──┬─ MlxBackend      │
│ Open WebUI  │   │      │                          │  (mlx-lm)        │
│ Genetics    │───┘      │                          └─ NativeBackend  │
└─────────────┘   │      └──▶ FakeBackend (--fake)      (llama.cpp)    │
                  └───────────────────────────────────────────────────┘
```

Backend dipilih otomatis dari isi model: direktori berisi `*.gguf` → llama.cpp (semua core CPU, Metal di Mac),
selain itu → MLX seperti sebelumnya.

- **Lintas Platform** — macOS (Apple Silicon Metal), Linux (NVIDIA CUDA), Linux CPU multi-core (GGUF/llama.cpp), dan Linux CPU via MLX.
- **Cepat** — MLX memanfaatkan akselerasi GPU secara native (Metal di Mac, CUDA di Linux); Llama-3.2-1B berjalan ~50 tok/dtk di M4 Max. Di GPU-less, model `*-gguf` berjalan dengan semua core CPU.
- **REST kompatibel Ollama** — aplikasi eksternal tinggal ganti base URL ke `http://localhost:11435`.
- **Genetic AI bawaan** — algoritma genetika yang memakai inferensi engine sendiri sebagai mutator dan penilai fitness.

## Platform & Instalasi

Memerlukan [uv](https://docs.astral.sh/uv/) (direkomendasikan) atau Python 3.12.

| Platform | Akselerasi | Perintah Install | Catatan |
|---|---|---|---|
| **macOS (Apple Silicon)** | Metal (GPU) | `uv tool install cokgine` | M1/M2/M3/M4, macOS 13.5+ |
| **Linux (NVIDIA GPU)** | CUDA 12 (GPU) | `uv tool install "cokgine[cuda]"` | Driver ≥ 550.54, SM 7.5+ (T4+), glibc ≥ 2.35 |
| **Linux (VPS / Server)** | CPU — **semua core** (llama.cpp) | `uv tool install "cokgine[native]"` | Model `*-gguf`; build butuh `build-essential` + `cmake`; glibc ≥ 2.35 |
| **Linux (VPS, MLX lama)** | CPU — 1 core (single-thread by design MLX) | `uv tool install "cokgine[cpu]"` | Model `mlx-community/...`; hanya untuk uji coba kecil |

> **Catatan Shell:** Tanda kutip pada `"cokgine[cpu]"` dan `"cokgine[cuda]"` **wajib disertakan** agar kurung siku `[...]` tidak diinterpretasikan oleh shell (zsh/bash).

### Syarat Linux CUDA

- **NVIDIA Driver**: ≥ `550.54.14` (`nvidia-smi` untuk cek).
- **Compute Capability**: **SM 7.5+** (Turing/Ampere/Ada/Hopper: T4, RTX 20xx/30xx/40xx, A10, A100, H100; GPU lawas seperti V100/Pascal tidak didukung oleh MLX CUDA).
- **C-library**: glibc ≥ `2.35` (bawaan Ubuntu 22.04 LTS ke atas; periksa dengan `ldd --version`).

### Panduan Cloud GPU (RunPod / Vast.ai)

1. **Pilih Instance On-Demand (Bukan Serverless)**:
   Model LLM (mis. 17 GB untuk 30B) butuh dimuat ke memori. Instance serverless akan memicu reload cold-start yang lama setiap kali jeda request.
2. **Jalankan Server**:
   ```bash
   uv tool install "cokgine[cuda]"
   cokgine pull qwen3-coder-30b
   cokgine serve --host 0.0.0.0
   ```
3. **Keamanan Jaringan**: Server cokgine tidak memakai autentikasi (identik dengan default Ollama). Jangan expose port 11435 ke publik tanpa proteksi; gunakan private overlay network (Tailscale / WireGuard) atau reverse proxy dengan autentikasi.
4. **Batas Memori GPU**: Untuk GPU dengan VRAM 24–36 GB (mis. RTX 3090/4090), set:
   ```bash
   export COKGINE_MAX_LOADED=1
   ```
   agar LRU cache tidak menumpuk lebih dari satu model besar di VRAM.

### VPS CPU tanpa GPU (semua core)

Di VPS CPU-only ada dua jalur:

**1. GGUF / native (disarankan)** — pakai model berakhiran `-gguf`; mesin inferensinya llama.cpp,
keluarga yang sama dengan Ollama, jadi **semua vCPU terpakai** (di Mac CPU-mode terbukti 12,5/14
core untuk Llama-3.2-1B). Pasang sekali:

```bash
sudo apt-get update && sudo apt-get install -y build-essential cmake    # kompilasi llama.cpp, sekali saja
uv tool install "cokgine[native]" --force --refresh                     # build dari source, tunggu beberapa menit
cokgine pull llama3.2-1b-gguf                                           # ~0.8 GB, Q4_K_M
cokgine generate llama3.2-1b-gguf "What is the capital of France?"
```

Cek pemakaian core saat generate (target: ratusan persen, bukan ~100%):

```bash
top -H -p "$(pgrep -f 'cokgine serve')"     # atau: htop
```

Jumlah thread default = semua core; override dengan `export COKGINE_CPU_THREADS=8`.
Log saat load menampilkan `loaded … (gguf · llama.cpp · 16 threads)`.

Perkiraan RAM (quant default Q4_K_M): 1B ≈ 0.8 GB · 8B ≈ 5 GB · 14B ≈ 9 GB · 30B-A3B ≈ 19 GB.
Cek dulu: `free -h` — untuk 30B-A3B sediakan RAM ≥ 24 GB.

Bila kompilasi `llama-cpp-python` gagal di VPS, ada wheel prebuilt di index abetlen
(`--extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cpu`); catatan: wheel di sana
bisa tertinggal dari versi terbaru, cukup untuk model lama (Llama-3.2 / Qwen2.5), jalur kompilasi
tetap yang utama untuk Qwen3-Coder.

**2. MLX CPU (jalur lama)** — model `mlx-community/...` tetap bisa jalan (`cokgine[cpu]`), tetapi
MLX di CPU itu single-thread by design: hanya ~1 core yang terpakai, apa pun jumlah vCPU Anda.
Cocok hanya untuk uji coba/CI dengan model kecil; untuk penggunaan nyata gunakan jalur GGUF di atas.

### Instalasi dari Source (Pengembang)

Lihat [DEVELOPING.md](DEVELOPING.md):

```bash
uv sync
uv run cokgine --help
```

Model tersimpan di `~/.cokgine/models/` (ubah via `COKGINE_HOME`).

Ketik `cokgine` tanpa perintah untuk melihat backend aktif (`metal`, `cuda`, atau `cpu`), status server, model lokal, dan panduan perintah.

## Quickstart

```bash
# ambil model uji (~0.7 GB)
cokgine pull llama3.2-1b

# tanya langsung dari CLI
cokgine generate llama3.2-1b "What is the capital of France?"

# REPL interaktif
cokgine run llama3.2-1b

# jalankan server REST (port 11435)
cokgine serve
```

Di mesin tanpa GPU (VPS), pakai varian GGUF agar semua core CPU terpakai
(perlu `uv tool install "cokgine[native]"` — detail di bagian VPS):

```bash
cokgine pull llama3.2-1b-gguf
cokgine generate llama3.2-1b-gguf "What is the capital of France?"
```

Model 7–8B (butuh ~5 GB RAM untuk 4-bit):

```bash
cokgine pull llama3.1-8b        # mlx-community/Meta-Llama-3.1-8B-Instruct-4bit
cokgine pull qwen2.5-7b
cokgine pull qwen3-8b
```

Model coding 30B MoE (17 GB, cocok untuk agentic coding via Cline; set
`COKGINE_MAX_LOADED=1` di RAM 36 GB):

Model Coding & Technical ERP (SuiteScript, SuiteQL, APIs):

```bash
cokgine pull qwen2.5-coder-7b    # mlx-community/Qwen2.5-Coder-7B-Instruct-4bit (~4.5 GB)
cokgine pull qwen2.5-coder-14b   # mlx-community/Qwen2.5-Coder-14B-Instruct-4bit (~9 GB)
cokgine pull qwen3-coder-30b     # mlx-community/Qwen3-Coder-30B-A3B-Instruct-4bit (~17 GB, MoE)
```

Model Functional ERP & Alur Bisnis / Akuntansi:

```bash
cokgine pull qwen2.5-14b         # mlx-community/Qwen2.5-14B-Instruct-4bit (~9 GB)
cokgine pull deepseek-r1-14b     # mlx-community/DeepSeek-R1-Distill-Qwen-14B-4bit (~9 GB)
```

## Model apa pun dari HuggingFace

Tidak ada daftar model yang dikunci di kode. Semua repo `mlx-community/...`
(atau repo MLX apa pun) bisa ditarik langsung dengan repo id-nya:

```bash
cokgine pull mlx-community/Llama-3.1-8B-Instruct-4bit
```

Repo **GGUF** juga langsung didukung — cokgine mendeteksi file `*.gguf` di repo,
memilih satu quant, dan mengunduhnya saja (bukan seluruh repo):

```bash
cokgine pull unsloth/Qwen3-8B-GGUF            # otomatis pilih Q4_K_M
COKGINE_GGUF_QUANT=Q8_0 cokgine pull unsloth/Qwen3-8B-GGUF   # quant lain
```

Urutan preferensi quant default: `Q4_K_M` → `Q5_K_M` → `Q4_K_S` → `Q8_0` → `Q4_0`.
Model GGUF di-load lewat llama.cpp (semua core CPU) — lihat bagian VPS di atas.

Alias bawaan (MLX): `llama3.2-1b`, `llama3.1-8b`, `qwen2.5-7b`, `qwen2.5-14b`,
`qwen3-8b`, `qwen2.5-coder-7b`, `qwen2.5-coder-14b`, `qwen3-coder-30b`,
`deepseek-r1-14b`.
Alias GGUF (native, semua core CPU): `llama3.2-1b-gguf`, `llama3.1-8b-gguf`,
`qwen2.5-7b-gguf`, `qwen2.5-14b-gguf`, `qwen3-8b-gguf`, `qwen2.5-coder-7b-gguf`,
`qwen2.5-coder-14b-gguf`, `qwen3-coder-30b-gguf`, `deepseek-r1-14b-gguf`.

Buat alias pribadi sendiri — tersimpan di `~/.cokgine/aliases.json`, tanpa
mengubah kode:

```bash
cokgine alias add deepseek mlx-community/DeepSeek-R1-Distill-Qwen-7B-4bit
cokgine pull deepseek
cokgine alias list          # alias -> repo id, plus status sudah/belum ditarik
cokgine alias rm deepseek   # hapus alias; file model (jika ada) tetap utuh
```

`cokgine pull <nama> --alias <nama-baru>` juga menyimpan alias saat selesai
mengunduh.

## REST API (kompatibel Ollama)

Semua endpoint streaming memakai NDJSON — satu objek JSON per baris
(`Content-Type: application/x-ndjson`), sama seperti Ollama. Set `stream: false`
untuk satu respons buffered.

| Endpoint | Fungsi |
|---|---|
| `GET /` | heartbeat |
| `GET /api/version` | versi server |
| `POST /api/generate` | generate satu prompt |
| `POST /api/chat` | chat multi-turn dengan chat template |
| `GET /api/tags` | daftar model lokal |
| `POST /api/pull` | unduh model dari HuggingFace |
| `POST /api/show` | detail model |
| `DELETE /api/delete` | hapus model lokal |

```bash
curl --json '{"model":"llama3.2-1b","prompt":"Say OK","stream":false}' \
     http://localhost:11435/api/generate

curl -sN --json '{"model":"llama3.2-1b","messages":[{"role":"user","content":"Say OK"}]}' \
     http://localhost:11435/api/chat
```

Open WebUI: tambahkan koneksi OpenAI/Ollama ke `http://localhost:11435` — CORS terbuka.

### Options yang dikenali

`options` map Ollama diterjemahkan ke sampler MLX:

| Ollama | cokgine |
|---|---|
| `temperature`, `top_p`, `top_k` | sampler MLX |
| `repeat_penalty` | logits processor repetition penalty |
| `num_predict` | `max_tokens` (default 512; -1 → 8192) |
| `num_ctx` | `max_kv_size` (default 8192; **per-request** — tidak memicu reload) |
| `stop` | pemotongan stream sisi klien |
| `seed` | `mx.random.seed` |

Opsi lain diabaikan.

Di jalur GGUF/native, panjang konteks ditetapkan saat model di-load
(`COKGINE_MAX_NUM_CTX`, default 32768) dan tidak berubah per request; prompt
yang melebihi plafon di-truncate dari depan disertai warning.

### Model thinking (Qwen3, DeepSeek-R1, …)

Field `think` mengikuti semantik Ollama: `true` / `false`, atau level
(`"low"`, `"medium"`, `"high"`, `"max"`) yang diperlakukan sebagai "thinking on".
Soft switch `/think` dan `/no_think` pada pesan user terakhir juga dikenali —
`think` eksplisit selalu menang atas soft switch.

Chain-of-thought tidak pernah bercampur dengan jawaban: reasoning dikirim di
field tersendiri (`message.thinking` untuk `/api/chat`, `thinking` untuk
`/api/generate`) dan field itu dihilangkan bila kosong. Ini juga memperbaiki
tool calling, karena JSON `tool_calls` tidak lagi tercemar blok `<think>`.

```bash
# jawaban langsung, tanpa reasoning
curl --json '{"model":"qwen3-8b","think":false,"stream":false,"messages":[{"role":"user","content":"9.11 vs 9.9, mana yang lebih besar?"}]}' \
     http://localhost:11435/api/chat
```

Di CLI: `cokgine generate qwen3-8b "…" --no-think`. Di dalam REPL ada perintah
`/think` dan `/no_think`; reasoning dicetak redup agar terpisah dari jawaban.

### Perilaku error

Stream yang gagal di tengah jalan tidak lagi diam (HTTP 200 + body kosong).
Chunk terakhir berisi `{"error": "...", "done": true, "done_reason": "error"}`.
Sebelum stream dimulai, error dipetakan ke status HTTP yang benar: `404` model
tidak dikenal, `400` model incomplete atau payload tidak valid, `500` kegagalan
engine. Traceback lengkap tetap masuk log server.

Pull yang terputus juga tidak lagi meninggalkan model yang "terdaftar tapi
tidak bisa dimuat": setiap pull diverifikasi (MLX: terhadap
`model.safetensors.index.json`; GGUF: file utuh byte-per-byte, header `GGUF`
valid, part split lengkap), manifest hanya ditulis bila model lengkap, dan
`cokgine list` / `cokgine show` menandai model yang belum selesai beserta
perintah untuk melanjutkannya.

## Genetic AI

`cokgine evolve` menjalankan algoritma genetika di atas inferensi engine sendiri:
setiap individu adalah **prompt-genome** (system prompt + instruction template
dengan placeholder `{input}`), dievolusi lewat seleksi tournament, crossover,
mutasi string deterministik, dan mutasi berbantuan LLM (temperature 0.9).

```bash
cokgine evolve --config examples/evolve_capitals.json
cokgine evolve --task "answer in rhymes" --model llama3.2-1b
cokgine evolve --resume <RUN_ID>          # lanjut dari checkpoint
```

Contoh config:

```json
{
  "task": "answer world capital-city questions accurately and concisely",
  "samples": [
    { "input": "What is the capital of France?", "expected": "Paris" }
  ],
  "target_model": "llama3.2-1b",
  "fitness": { "strategy": "contains" },
  "population": 6,
  "generations": 5,
  "llm_mutation_rate": 0.3
}
```

Strategi fitness:

- `contains` / `exact` / `regex` — deterministik terhadap `expected`.
- `llm_judge` — engine menilai jawaban kandidatnya sendiri (rubrik bisa dikustom via `"rubric"`).

Checkpoint atomik per generasi tersimpan di `~/.cokgine/evolve/<run_id>/state.json`;
run bisa dilanjutkan dengan `--resume`. Seed RNG dikonfigurasi (`"seed": 42`) agar
run reproducible.

Seam arsitektur untuk masa depan: `WeightGenome` (evolusi bobot/LoRA) — parameter
`adapter` sudah mengalir dari options → cache key → `mlx_lm.load(adapter_path=...)`,
jadi evolusi adapter bisa ditambahkan tanpa menyentuh core.

## Mode tanpa GPU / demo

Seluruh stack (CLI, REST, evolve) bisa dijalankan tanpa model dan tanpa jaringan:

```bash
cokgine serve --fake
cokgine evolve --fake --config examples/evolve_capitals.json
# atau: export COKGINE_FAKE=1
```

## Memori (M-series 36 GB)

- LRU cache memuat maksimal 2 model sekaligus (`COKGINE_MAX_LOADED`); evict memanggil `gc.collect()` + `mx.clear_cache()`.
- `num_ctx` besar menaikkan pemakaian KV-cache per request — 8192 aman untuk model 8B-4bit.
- Untuk headroom lebih saat load 2 model 8B: `sudo sysctl iogpu.wired_limit_mb=28000`.

Lisensi: proprietary — semua hak dilindungi. Penggunaan kembali atau redistribusi
source code tidak diizinkan tanpa izin tertulis dari pemilik.
