Optimasi biayaPanduan
Bahasa alami ke perintah shell dengan API LLM: JSON dan biaya
Skrip Python yang meminta satu perintah shell sebagai JSON dari model murah, menolak atau menandai permintaan yang tidak jelas, tidak pernah menjalankan apa pun, dan menghitung harga 1.000 permintaan.

Di halaman ini
Minta model untuk satu objek JSON dengan tiga field (type, command, explanation), batasi jawaban hingga beberapa ratus token, dan cetak perintahnya alih-alih menjalankannya. Dilihat dari token, permintaan seperti itu sebagian besar berupa prompt dengan jawaban pendek yang mudah diprediksi: dengan asumsi di bawah, 1.000 di antaranya berbiaya $0.012 pada DeepSeek-V4-Flash.
Misalkan Anda menambahkan kotak "jelaskan apa yang Anda inginkan" ke CLI internal. Seseorang mengetik cari file yang lebih besar dari 100 MB di folder home saya, dan Anda ingin mendapat satu baris yang bisa mereka baca, periksa, dan tempel. Muncul dua pertanyaan: bagaimana mencegah model menebak atau melakukan sesuatu yang berbahaya, dan berapa biayanya ketika seratus orang menggunakannya sepanjang hari?
Tugas yang sempit: mengapa jawabannya pendek#
Pada 9 November 2026 sebuah kanal Telegram menceritakan ulang model card dale-0.8b, model terbuka yang melakukan tepat satu pekerjaan ini. Menurut model card di Hugging Face (diperiksa 10 November 2026), dale-0.8b adalah fine-tune penuh Qwen3.5-0.8B di bawah Apache-2.0 yang mengubah permintaan berbahasa Spanyol atau Inggris menjadi satu perintah bash Linux. Penulisnya, Manuel García, melaporkan 79,4% (374 dari 471 kasus) pada test set miliknya sendiri, dibandingkan 62,8% untuk basis Qwen3.5-9B dan untuk Gemma 4 E4B-it tanpa fine-tuning. Itu angka yang dilaporkan sendiri pada test set satu orang, jadi anggap sebagai satu titik data, bukan peringkat.
Yang berguna bagi kita adalah bentuk tugasnya, bukan modelnya. Model card tersebut menjelaskan system prompt tetap, satu baris konteks (OS, distro, package manager, tools) plus permintaan, thinking dimatikan, dan balasan dibatasi 200 token. Batas itu adalah salah satu dari dua tuas biaya: ketika jawabannya satu objek JSON pendek, sisi output menjadi pendek dan mudah diprediksi karena dibatasi. Tuas lainnya adalah prompt. Berapa porsi tagihan dari masing-masing sisi ditunjukkan tabel di bawah; porsinya berbeda antar model.
Anda tidak perlu model 0.8B untuk itu. Format yang sama berfungsi pada model API apa pun, dan itulah yang dibangun di sisa artikel ini.

Format balasan: command, refuse, atau unsure#
Triknya adalah model selalu punya cara sah untuk berkata "tidak". Balasannya adalah satu objek:
{"type": "command | refuse | unsure", "command": "...", "explanation": "..."}command: satu perintah bash, plus penjelasan satu kalimat tentang apa yang dilakukannya.refuse: permintaan bersifat destruktif atau tidak ada hubungannya dengan shell. Tanpa perintah.unsure: permintaan terlalu kabur ("bersihkan disk saya"). Penjelasannya berisi pertanyaan klarifikasi.
Tanpa unsure, permintaan yang kabur memaksa model menebak, dan rm hasil tebakan adalah yang akan Anda ingat. Format pada model card memiliki tiga tipe yang sama; kami memakai ulang idenya, bukan modelnya.
Cocokkan pasangan
Cocokkan setiap tipe balasan dengan yang harus dilakukan skrip
Ketuk item di kiri, lalu pasangannya
- commandTampilkan perintah dan penjelasannya; orang tersebut menyalin dan menjalankannya sendiri
- refuseCetak penjelasannya dan tidak menawarkan apa pun untuk dijalankan
- unsureCetak pertanyaannya dan biarkan pengguna mengungkapkan ulang
Skripnya#
Satu file, paket openai, key di variabel lingkungan. Base URL dan id model lengkap berasal dari dokumentasi CheapTokens; id pendek tidak diterima, jadi gunakan deepseek-.
import json
import os
import sys
from openai import OpenAI
client = OpenAI(
base_url='https://api.cheaptokens.dev/v1',
api_key=os.environ['CHEAPTOKENS_API_KEY'],
)
MODEL = 'deepseek-ai/DeepSeek-V4-Flash-0731'
SYSTEM = '''You turn a request into ONE Linux bash command.
Reply with a single JSON object and nothing else:
{"type": "command" | "refuse" | "unsure", "command": "<one command, or empty>", "explanation": "<one short sentence>"}
Use "refuse" when the request is destructive or not about the shell.
Use "unsure" when it is too vague, and put a clarifying question in "explanation".'''
CONTEXT = 'os: Ubuntu 24.04; package manager: apt; tools: git, curl, jq'
def parse(text):
start = text.find('{')
if start == -1:
return None
try:
obj, _ = json.JSONDecoder().raw_decode(text[start:])
except json.JSONDecodeError:
return None
if not isinstance(obj, dict) or obj.get('type') not in ('command', 'refuse', 'unsure'):
return None
return obj
def ask(request):
resp = client.chat.completions.create(
model=MODEL,
max_tokens=200,
temperature=0,
messages=[
{'role': 'system', 'content': SYSTEM},
{'role': 'user', 'content': f'Context: {CONTEXT}\nRequest: {request}'},
],
)
return parse(resp.choices[0].message.content), resp.usage
if __name__ == '__main__':
result, usage = ask(' '.join(sys.argv[1:]))
if result is None:
print('Could not read the reply as JSON. Try again.')
elif result['type'] == 'command':
print(result['explanation'])
print('\n ' + result['command'] + '\n')
print('Read it, then copy it yourself. This script never runs it.')
else:
print(f"[{result['type']}] {result['explanation']}")
print(f'tokens: {usage.prompt_tokens} in, {usage.completion_tokens} out')Jalankan sebagai python shellhelp.. Tiga pilihan penting di sini:
- Tidak ada
subprocessdi mana pun. Perintahnya adalah teks di layar. Menjalankannya adalah keputusan Anda, setelah Anda membacanya. max_tokens=200, sama dengan batas pada model card. Satu objek JSON mudah muat; jawaban yang bertele-tele terpotong di 200 token alih-alih terus berjalan dengan biaya Anda. Batas ini berlaku untuk seluruh balasan, jadi jika model menuliskan penalarannya, itu bisa memakan batas tersebut. Jika suatu balasan berakhir denganfinish_reasonsama denganlength, naikkan batasnya sedikit. Selengkapnya di memotong token output dengan max_tokens.- Format diminta di prompt, lalu di-parse secara defensif.
raw_decodemelewati code fence yang nyasar atau kalimat sebelum{. Jika ingin lebih jauh, lihat JSON valid dari API yang kompatibel dengan OpenAI dan perbaikan untuk json.JSONDecodeError pada balasan.
Sebelum menjalankan apa pun, pastikan urutan langkahnya jelas:
Urutkan
Susun langkah-langkah skrip dalam urutan yang benar
Seret item atau gunakan panah
- Bangun prompt: teks sistem tetap, satu baris konteks, permintaan
- Panggil API dengan max_tokens kecil
- Parse JSON dan periksa bahwa type adalah salah satu dari tiga
- Tampilkan perintah dan tunggu orang tersebut menjalankannya
Berapa biaya 1.000 permintaan#
Baris terakhir skrip mencetak usage. Itu angka sebenarnya, dan Anda sebaiknya membaca angka Anda sendiri. Sampai Anda memilikinya, gunakan asumsi: prompt sekitar 400 token input (prompt polos di skrip kira-kira 150 token menurut hitungan kasar; sisanya ruang untuk tiga atau empat pasangan contoh permintaan-dan-balasan yang kemungkinan akan Anda tambahkan), dan balasan JSON sekitar 60 token output.
Untuk 1.000 permintaan itu berarti 400 × 1.000 = 400.000 token input dan 60 × 1.000 = 60.000 token output. Tabel memberi harga tepat untuk itu bagi setiap model di katalog, dengan kolom OpenRouter di sebelahnya; angkanya berasal dari harga langsung, jadi tetap terkini.
| Model | Input $/1Jt | Output $/1Jt | Per permintaan | 1.000 permintaan | OpenRouter, 1.000 permintaan |
|---|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.00001 | $0.0104 | $0.0184 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.000012 | $0.012 | $0.0364 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.000029 | $0.029 | $0.348 |
400 token input dan 60 token output per permintaan. Harga per 1 juta token adalah harga saat ini dan berubah seiring tarif kami; kolom OpenRouter menunjukkan harga referensi untuk beban kerja yang sama.
Secara total, dengan input dan output dihitung bersama, DeepSeek-V4-Flash lebih murah daripada OpenRouter untuk beban kerja ini. Dilihat dari token, permintaannya hampir seluruhnya input dan balasannya pendek, tetapi kedua sisi ditagih, jadi pangkas prompt dan jawaban sama-sama. Harga per model ada di halaman harga, dan modelnya sendiri dijelaskan di halaman DeepSeek: konteks 380K, hingga 32.768 token output, satu harga di jam berapa pun.
Cara cepat merasakan proporsinya:
Cek cepat
Bagian permintaan mana yang dibatasi max_tokens=200?
Tampilkan jawaban
Jawaban: Balasannya
max_tokens hanya membatasi balasan; prompt ditagih apa adanya, jadi pangkas secara terpisah.
Ingin 100.000 permintaan sebulan? Kalikan dengan 100: 40.000.000 input dan 6.000.000 token output. Masukkan kedua angka itu ke ::cost dengan cara yang sama dan baca barisnya.
Uji pada permintaan Anda sendiri#
Angka 79,4% pada model card tidak mengatakan apa pun tentang prompt Anda, OS Anda, atau pilihan kata pengguna Anda. Tulis 20 permintaan nyata beserta perintah yang akan Anda terima dan bandingkan, persis seperti di menguji prompt pada eval set kecil. Sertakan beberapa yang seharusnya ditolak atau ditandai unsure oleh skrip, seperti "hapus semuanya" atau "buat komputer saya lebih cepat".
Ketika ada yang salah, gejalanya biasanya menunjukkan perbaikannya:
Could not read the reply as JSON: cetak teks mentahnya sekali. Awalan seperti "Sure!" sudah ditangani; balasan yang terpotong oleh batas tidak, jadi periksafinish_reason.401atau404: key, base URL, atau id model salah. Daftarnya ada di API 401 atau 404: key, base URL, id model.- Perintah yang cocok untuk sistem lain: baris konteks penyebabnya. Jaga tetap akurat (OS, package manager, tools); biayanya beberapa lusin token dan mencegah
aptyang salah di mesin Fedora.
Tugas sama, model berbeda? Ganti MODEL dengan id GLM atau MiniMax dari dokumentasi, pertahankan prompt, dan bandingkan jumlah token yang dicetak skrip dengan tabel di atas.



