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.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir