LocalAI ile Yerel Kod Tamamlama Sunucusu: VS Code ve Neovim Entegrasyonu
Kendi sunucunda çalışan, internet bağlantısı gerektirmeyen, tamamen kontrol altındaki bir yapay zeka kod tamamlama sistemi kurmak artık hayal değil. LocalAI projesi, OpenAI API’siyle uyumlu bir arayüz sunarak mevcut editör eklentilerinin neredeyse sıfır değişiklikle yerel modellere bağlanmasına imkan tanıyor. Bu yazıda bir Linux sunucusunda LocalAI kurarak VS Code ve Neovim’i bu sunucuya bağlayacağız. Şirket içi kod tabanı üzerinde çalışan, dışarıya bir satır veri sızdırmayan bir kurulum hedefliyoruz.
Neden Yerel Kod Tamamlama?
GitHub Copilot veya benzeri bulut tabanlı araçlar kodunuzu uzak sunuculara gönderiyor. Açık kaynak projelerde bu çoğunlukla sorun teşkil etmez, ancak kurumsal ortamda, gizlilik politikalarının sıkı olduğu ya da air-gap ağlarda çalışırken bu kabul edilemez bir durum.
Yerel çözümün pratik avantajları:
- Veri gizliliği: Kod satırı dışarı çıkmıyor
- Gecikme kontrolü: Ağ bağlantısına bağımlılık yok, LAN üzerinden ms seviyesinde yanıt
- Model seçimi: Farklı görevler için farklı modeller yüklenebiliyor
- Maliyet: Aylık abonelik yok, donanım bir kez alınıyor
- Özelleştirme: Kendi fine-tune modellerinizi kullanabiliyorsunuz
Dezavantajları da görmezden gelmemek gerekiyor: İyi bir GPU olmadan büyük modeller yavaş çalışıyor, kurulum ve bakım size kalıyor, model güncellemelerini kendiniz takip etmeniz gerekiyor.
Donanım ve Sistem Gereksinimleri
Bu kurulum için kullandığım test ortamı:
- Ubuntu 22.04 LTS
- AMD Ryzen 9 5900X
- 64 GB RAM
- NVIDIA RTX 3090 (24 GB VRAM)
GPU olmadan da çalışıyor ama CPU ile 7B modellerde bile kayda değer gecikme yaşıyorsunuz. Minimum önerim 16 GB RAM ve eğer GPU varsa 8 GB VRAM. Kod tamamlama için özel eğitilmiş modeller (StarCoder, DeepSeek Coder, CodeLlama gibi) genel amaçlı modellere göre daha küçük boyutlarda bile iyi sonuç veriyor.
LocalAI Kurulumu
LocalAI’yi Docker ile kurmak en temiz yol. Sistemi kirletmiyor, bağımlılık çakışması yaratmıyor, gerektiğinde kolayca sürüm değiştiriyorsunuz.
Önce Docker’ın kurulu olduğunu doğrulayın:
docker --version
docker compose version
GPU desteği için NVIDIA Container Toolkit gerekli:
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list |
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' |
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
Şimdi LocalAI için bir çalışma dizini oluşturup yapılandıralım:
mkdir -p /opt/localai/{models,config}
cd /opt/localai
docker-compose.yml dosyasını oluşturuyoruz:
cat > /opt/localai/docker-compose.yml << 'EOF'
version: "3.9"
services:
localai:
image: localai/localai:latest-aio-gpu-nvidia-cuda-12
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- ./models:/build/models
- ./config:/build/config
environment:
- THREADS=8
- CONTEXT_SIZE=4096
- DEBUG=false
- GALLERIES=[{"name":"model-gallery","url":"github:go-skynet/model-gallery/index.yaml"}]
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/readyz"]
interval: 30s
timeout: 10s
retries: 5
EOF
GPU kullanmıyorsanız image satırını localai/localai:latest-aio-cpu olarak değiştirin ve deploy bloğunu tamamen kaldırın.
Servisi başlatalım:
cd /opt/localai
docker compose up -d
docker compose logs -f
İlk başlatmada birkaç dakika bekleyin. Hazır olduğunda şu komutla kontrol edin:
curl http://localhost:8080/readyz
# Yanıt: {"status":"ok"}
Kod Tamamlama Modeli İndirme
LocalAI’nin model galerisi üzerinden model indirmek oldukça pratik. Kod tamamlama için CodeLlama 7B ile başlayalım, ardından daha güçlü alternatiflere geçeriz.
# Mevcut galerideki modelleri listele
curl http://localhost:8080/models/available | python3 -m json.tool | grep -i "code"
# CodeLlama 7B modelini indir
curl -X POST http://localhost:8080/models/apply
-H "Content-Type: application/json"
-d '{"id": "codellama-7b-instruct"}' | python3 -m json.tool
Model indirme işlemini takip etmek için:
curl http://localhost:8080/models/jobs | python3 -m json.tool
Model indirildikten sonra test edelim:
curl http://localhost:8080/v1/completions
-H "Content-Type: application/json"
-d '{
"model": "codellama-7b-instruct",
"prompt": "def fibonacci(n):",
"max_tokens": 150,
"temperature": 0.1,
"stop": ["def ", "class "]
}' | python3 -m json.tool
Düzgün bir Python fonksiyon gövdesi döndürüyorsa kurulum çalışıyor demektir.
Özel Model Yapılandırması
LocalAI’de modeller YAML dosyalarıyla yapılandırılıyor. Kod tamamlama için özelleştirilmiş bir yapılandırma oluşturalım:
cat > /opt/localai/config/codellama-completion.yaml << 'EOF'
name: codellama-completion
backend: llama
model: codellama-7b-instruct.Q4_K_M.gguf
context_size: 4096
threads: 8
f16: true
mmap: true
parameters:
temperature: 0.1
top_p: 0.95
top_k: 40
repeat_penalty: 1.1
stop:
- "```"
- "###"
- "<|endoftext|>"
template:
completion: |
Complete the following code:
{{.Input}}
chat_message: |
<s>[INST] {{.Text}} [/INST]
EOF
Yapılandırmayı yüklemek için servisi yeniden başlatın:
docker compose restart localai
VS Code Entegrasyonu
VS Code tarafında birkaç farklı eklenti seçeneği var. Continue eklentisi hem sohbet hem de kod tamamlama özelliği sunduğu için tercih ediyorum. Tabby eklentisi ise sadece inline tamamlama odaklı ve daha hafif.
Continue Eklentisi ile Kurulum
VS Code’da Extensions panelini açın (Ctrl+Shift+X), “Continue” arayın ve yükleyin. Yayıncısı “Continue Dev” olmalı.
Eklenti yüklendikten sonra yapılandırma dosyasını açın. Linux’ta genellikle ~/.continue/config.json konumunda:
mkdir -p ~/.continue
cat > ~/.continue/config.json << 'EOF'
{
"models": [
{
"title": "LocalAI CodeLlama",
"provider": "openai",
"model": "codellama-completion",
"apiBase": "http://YOUR_SERVER_IP:8080/v1",
"apiKey": "localai-no-auth-needed",
"completionOptions": {
"temperature": 0.1,
"maxTokens": 512
}
}
],
"tabAutocompleteModel": {
"title": "LocalAI Autocomplete",
"provider": "openai",
"model": "codellama-completion",
"apiBase": "http://YOUR_SERVER_IP:8080/v1",
"apiKey": "localai-no-auth-needed"
},
"tabAutocompleteOptions": {
"useCopyBuffer": false,
"maxPromptTokens": 1024,
"debounceDelay": 500
},
"allowAnonymousTelemetry": false
}
EOF
YOUR_SERVER_IP kısmını LocalAI sunucunuzun IP adresiyle değiştirin. Aynı makinede çalışıyorsa localhost kullanın.
VS Code’u yeniden başlatın. Sağ alt köşede Continue ikonunun yeşil olduğunu görmelisiniz. Herhangi bir .py, .js veya .go dosyası açıp yazmaya başladığınızda birkaç saniyelik gecikme sonrası tamamlama önerileri görünecek.
Tabby Eklentisi ile Alternatif Kurulum
Tabby daha minimal bir deneyim sunuyor, sadece inline tamamlama istiyor:
Tabby eklentisini kurun: “TabbyML.vscode-tabby” eklentisini Extensions’dan yükleyin.
# VS Code ayarlarına eklenecek (settings.json)
cat >> ~/.config/Code/User/settings.json << 'EOF'
{
"tabby.api.endpoint": "http://YOUR_SERVER_IP:8080/v1",
"tabby.api.token": "dummy-token",
"tabby.inlineCompletion.triggerMode": "automatic"
}
EOF
Ancak Tabby eklentisi kendi sunucu formatını bekliyor, OpenAI uyumlu endpoint için hafif bir proxy yazmanız gerekebilir. Bu yüzden Continue tercih edilebilir başlangıç için.
Neovim Entegrasyonu
Neovim tarafında iki popüler seçenek var: coc.nvim ile coc-openai veya nvim-cmp tabanlı özel bir kurulum. Lua tabanlı modern Neovim konfigürasyonu için gen.nvim veya doğrudan copilot.lua fork’larını kullanmak mümkün. Ben avante.nvim ve cmp-ai kombinasyonunu tercih ediyorum.
Temel Kurulum: cmp-ai ile nvim-cmp
Önce lazy.nvim ile gerekli eklentileri kuralım. ~/.config/nvim/lua/plugins/ai.lua dosyasını oluşturun:
-- ~/.config/nvim/lua/plugins/ai.lua
return {
{
"tzachar/cmp-ai",
dependencies = { "hrsh7th/nvim-cmp" },
config = function()
local cmp_ai = require("cmp_ai.config")
cmp_ai:setup({
max_lines = 1000,
provider = "OpenAI",
provider_options = {
model = "codellama-completion",
base_url = "http://YOUR_SERVER_IP:8080/v1/completions",
api_key = "localai-dummy-key",
max_tokens = 256,
temperature = 0.1,
stop = { "nn", "```" },
},
notify = true,
notify_callback = function(msg)
vim.notify(msg, vim.log.levels.INFO)
end,
run_on_every_keystroke = false,
ignored_file_types = {
TelescopePrompt = true,
NvimTree = true,
},
})
end,
},
{
"hrsh7th/nvim-cmp",
opts = function(_, opts)
local cmp = require("cmp")
opts.sources = opts.sources or {}
table.insert(opts.sources, {
name = "cmp_ai",
priority = 100,
keyword_length = 3,
})
-- AI tamamlamayı manuel tetiklemek için
opts.mapping = vim.tbl_extend("force", opts.mapping or {}, {
["<C-x><C-o>"] = cmp.mapping.complete({
config = {
sources = { { name = "cmp_ai" } },
},
}),
})
return opts
end,
},
}
Model.nvim ile Daha Esnek Yaklaşım
Daha fazla kontrol istiyorsanız doğrudan HTTP çağrısı yapan bir Lua modülü yazabilirsiniz:
-- ~/.config/nvim/lua/localai.lua
local M = {}
local config = {
endpoint = "http://YOUR_SERVER_IP:8080/v1/completions",
model = "codellama-completion",
max_tokens = 256,
temperature = 0.1,
}
function M.complete_at_cursor()
local bufnr = vim.api.nvim_get_current_buf()
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, row, false)
local current_line = vim.api.nvim_buf_get_lines(bufnr, row - 1, row, false)[1]
local prefix = current_line:sub(1, col)
table.insert(lines, prefix)
local context = table.concat(lines, "n")
local payload = vim.json.encode({
model = config.model,
prompt = context,
max_tokens = config.max_tokens,
temperature = config.temperature,
stop = { "nn" },
})
local cmd = string.format(
"curl -s -X POST '%s' -H 'Content-Type: application/json' -d '%s'",
config.endpoint,
payload:gsub("'", "'\''")
)
vim.fn.jobstart(cmd, {
stdout_buffered = true,
on_stdout = function(_, data)
if data and data[1] and data[1] ~= "" then
local ok, result = pcall(vim.json.decode, table.concat(data, ""))
if ok and result.choices and result.choices[1] then
local completion = result.choices[1].text
if completion and completion ~= "" then
local insert_lines = vim.split(completion, "n")
vim.api.nvim_put(insert_lines, "c", true, true)
end
end
end
end,
})
end
-- Keybinding
vim.keymap.set("n", "<leader>ai", M.complete_at_cursor, {
desc = "LocalAI: Cursor konumunda tamamla",
silent = true,
})
return M
init.lua veya init.vim dosyanıza ekleyin:
require("localai")
Bu modül ai tuş kombinasyonuyla cursor konumunda kod tamamlama istiyor ve sonucu buffer’a yapıştırıyor.
Sunucu Tarafında Güvenlik ve Proxy Yapılandırması
LocalAI’yi doğrudan açık bırakmak yerine Nginx reverse proxy arkasına almak ve basit token doğrulaması eklemek daha güvenli:
cat > /etc/nginx/sites-available/localai << 'EOF'
server {
listen 443 ssl;
server_name localai.internal.company.com;
ssl_certificate /etc/ssl/certs/internal.crt;
ssl_certificate_key /etc/ssl/private/internal.key;
# Yalnızca belirli IP'lere izin ver
allow 10.0.0.0/8;
allow 192.168.0.0/16;
deny all;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
# Büyük yanıtlar için buffer ayarları
proxy_buffering off;
proxy_cache off;
}
}
EOF
ln -s /etc/nginx/sites-available/localai /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
Performans Tuning
Gerçek kullanımda yanıt süresi çok önemli. Editörde yazan biri 2-3 saniyeden fazla beklemeye tahammül etmiyor. Birkaç pratik ayar:
GPU bellek optimizasyonu için docker-compose.yml ortam değişkenlerine ekleyin:
# GPU VRAM kullanımını optimize et
environment:
- GPU_LAYERS=35 # 7B model için, VRAM'e göre ayarla
- BATCH_SIZE=512
- CONTEXT_SIZE=2048 # Kod tamamlama için 4096'ya gerek yok
- PARALLEL=2 # Eş zamanlı istek sayısı
- F16=true # Half precision, hem hız hem VRAM tasarrufu
Yanıt süresi ölçümü için basit bir test scripti:
#!/bin/bash
# /opt/localai/benchmark.sh
ENDPOINT="http://localhost:8080/v1/completions"
MODEL="codellama-completion"
ITERATIONS=5
echo "LocalAI Benchmark - $MODEL"
echo "================================"
total_time=0
for i in $(seq 1 $ITERATIONS); do
start=$(date +%s%N)
curl -s -X POST "$ENDPOINT"
-H "Content-Type: application/json"
-d "{
"model": "$MODEL",
"prompt": "def calculate_fibonacci(n: int) -> int:",
"max_tokens": 100,
"temperature": 0.1
}" > /dev/null
end=$(date +%s%N)
elapsed=$(( (end - start) / 1000000 ))
echo "Iterasyon $i: ${elapsed}ms"
total_time=$((total_time + elapsed))
done
avg=$((total_time / ITERATIONS))
echo "================================"
echo "Ortalama yanit suresi: ${avg}ms"
chmod +x /opt/localai/benchmark.sh
/opt/localai/benchmark.sh
RTX 3090 ile CodeLlama 7B için 100 token’da ortalama 800-1200ms bekliyorum. Bu editör kullanımı için kabul edilebilir bir süre.
Gerçek Dünya Senaryosu: Takım Kullanımı
Beş kişilik bir backend geliştirici ekibini düşünün. Hepsi aynı LocalAI sunucusuna bağlanıyor, proje spesifik Python kodları üzerinde çalışıyor. Bu durumda tek model yeterli olmayabilir; farklı dillerde çalışanlar için farklı modeller açık tutabilirsiniz.
Birden fazla modeli aynı anda yönetmek için:
# Mevcut yüklü modelleri listele
curl http://localhost:8080/v1/models | python3 -m json.tool
# Model yükleme durumunu kontrol et
curl http://localhost:8080/v1/models | python3 -c "
import json, sys
models = json.load(sys.stdin)
for m in models.get('data', []):
print(f"Model: {m['id']} - Olusturulma: {m.get('created', 'N/A')}")
"
Yük dengeleme için birden fazla LocalAI örneği çalıştırıp Nginx upstream ile dağıtabilirsiniz:
# Nginx upstream konfigürasyonu
upstream localai_backend {
server 127.0.0.1:8080 weight=1;
server 127.0.0.1:8081 weight=1;
keepalive 32;
}
Sorun Giderme
Model yüklenmiyor: /opt/localai/models dizininde .gguf dosyasının varlığını kontrol edin, dosya izinlerini doğrulayın (chown -R 1000:1000 /opt/localai/models).
CUDA bulunamıyor: docker run --rm --gpus all nvidia/cuda:12.0-base nvidia-smi komutuyla container içinde GPU erişimini test edin.
VS Code eklentisi bağlanamıyor: Güvenlik duvarının 8080 portuna izin verdiğini kontrol edin: ufw allow from 10.0.0.0/8 to any port 8080.
Yavaş yanıtlar: PARALLEL değerini düşürün, tek istek işlenirken daha hızlı yanıt alırsınız. CONTEXT_SIZE değerini de düşürmek VRAM tasarrufu sağlar.
Neovim’de curl hatası: vim.fn.jobstart yerine plenary.nvim kütüphanesinin curl modülünü kullanmak daha güvenilir async HTTP işlemi sağlar.
Sonuç
LocalAI ile yerel kod tamamlama sunucusu kurmak başta karmaşık görünebilir ama bir kez oturduğunda oldukça stabil çalışıyor. Docker tabanlı kurulum güncelleme ve geri alma işlemlerini kolaylaştırıyor. VS Code tarafında Continue eklentisi en pürüzsüz deneyimi sunuyor; Neovim için ise cmp-ai veya tamamen özel Lua modülü yazma seçenekleri var.
En önemli nokta model seçimi: Genel amaçlı bir LLM yerine kodlamaya özelleştirilmiş modeller (CodeLlama, DeepSeek Coder, StarCoder2) kullanmak hem hız hem kalite açısından ciddi fark yaratıyor. 7B parametreli bir model orta seviye GPU’da rahatça çalışıyor ve günlük kod tamamlama için yeterince iyi öneriler üretiyor.
Kurulumu tamamladıktan sonra öneri kalitesini değerlendirmek için bir iki hafta gerçek projede kullanın, sonra ihtiyaca göre model boyutunu veya yapılandırmayı ayarlayın. Veri gizliliği gerektiren ortamlarda bu tür yerel kurulumlar artık ciddi bir alternatif, sadece hobi projesi değil.
