Ollama ile Kod İnceleme ve Otomatik Yorum Yazma
Geçen ay bir meslektaşım bana “ya bu code review işini otomatize edemez miyiz, her PR’a aynı yorumları yazıyorum” dedi. Haklıydı. Büyük ekiplerde code review hem zaman alıyor hem de tutarsız kalıyor: kimi reviewer çok sıkı, kimi çok gevşek, bazı standartlar hiç uygulanmıyor. Ollama ile yerel çalışan bir LLM kurduğumuzda bu sürecin ciddi bir kısmını otomatize edebildik. Bugün bu kurulumu, kullandığımız script’leri ve gerçek hayatta karşılaştığımız durumları paylaşacağım.
Neden Yerel LLM, Neden Ollama?
Bulut tabanlı alternatiflere (ChatGPT API, Claude API) kıyasla Ollama’nın temel avantajı açık: kodunuz dışarı çıkmıyor. Özellikle kurumsal ortamlarda, finans ya da sağlık sektöründe çalışıyorsanız kaynak kodunuzu üçüncü parti servislere göndermek ciddi bir compliance sorunu. Ollama bu problemi temelden çözüyor.
Bunun yanı sıra maliyet meselesi var. API çağrısı başına ödeme yapılan modellerde, yoğun bir geliştirme sürecinde fatura beklenmedik büyüyor. Kendi sunucunuzda çalışan bir model için sadece elektrik ve donanım maliyetini düşünürsünüz.
Kurulum için Ollama’yı indirip başlatmak yeterli:
# Linux kurulum
curl -fsSL https://ollama.ai/install.sh | sh
# Servisi başlat
systemctl enable ollama
systemctl start ollama
# Kod inceleme için uygun modelleri indir
ollama pull codellama:13b
ollama pull deepseek-coder:6.7b
ollama pull llama3.1:8b
# Model listesini kontrol et
ollama list
Kod inceleme için codellama ve deepseek-coder modellerini özellikle öneriyorum. Genel amaçlı modeller de çalışır ama bu modeller kod yapısını daha iyi anlıyor, daha isabetli yorumlar üretiyor.
Temel API Kullanımı
Ollama’nın REST API’si son derece sade. Bir curl komutuyla model ile konuşabilirsiniz:
# Basit bir kod parçasını incele
curl -s http://localhost:11434/api/generate
-H "Content-Type: application/json"
-d '{
"model": "codellama:13b",
"prompt": "Aşağıdaki Python kodunu incele ve sorunları listele:nndef get_user(id):n conn = psycopg2.connect("host=localhost dbname=mydb")n cur = conn.cursor()n cur.execute("SELECT * FROM users WHERE id = " + str(id))n return cur.fetchone()",
"stream": false
}' | jq -r '.response'
Bu kadar basit. Ama tabii gerçek kullanımda bunu bir script’e sarmanız gerekiyor.
Git Hook ile Otomatik Kod İnceleme
En pratik kullanım senaryolarından biri: commit öncesinde ya da PR açılırken otomatik code review tetiklemek. Bunun için bir pre-push hook yazalım.
#!/bin/bash
# .git/hooks/pre-push
# Çalıştırma izni: chmod +x .git/hooks/pre-push
OLLAMA_URL="http://localhost:11434/api/generate"
MODEL="codellama:13b"
REVIEW_LOG="/tmp/code_review_$(date +%Y%m%d_%H%M%S).txt"
# Son commit'teki değişen dosyaları al
CHANGED_FILES=$(git diff HEAD~1 HEAD --name-only --diff-filter=AM | grep -E '.(py|js|ts|go|java)$')
if [ -z "$CHANGED_FILES" ]; then
echo "İncelenecek kod dosyası bulunamadı, devam ediliyor."
exit 0
fi
echo "Kod incelemesi başlatılıyor..."
echo "Sonuçlar: $REVIEW_LOG"
for FILE in $CHANGED_FILES; do
if [ ! -f "$FILE" ]; then
continue
fi
FILE_CONTENT=$(cat "$FILE")
PROMPT="Sen bir kıdemli yazılım mühendisisin. Aşağıdaki kodu incele ve şu başlıklar altında değerlendirme yap:
1. Güvenlik açıkları (SQL injection, XSS, credential exposure vb.)
2. Performans sorunları
3. Hata yönetimi eksiklikleri
4. Kod kalitesi ve okunabilirlik
5. En iyi pratiklerden sapmalar
Dosya: $FILE
Kod:
```
$FILE_CONTENT
```
Sadece gerçek sorunları listele. Sorun yoksa kısaca belirt."
RESPONSE=$(curl -s "$OLLAMA_URL"
-H "Content-Type: application/json"
-d "$(jq -n
--arg model "$MODEL"
--arg prompt "$PROMPT"
'{model: $model, prompt: $prompt, stream: false}')"
| jq -r '.response')
echo "=== $FILE ===" >> "$REVIEW_LOG"
echo "$RESPONSE" >> "$REVIEW_LOG"
echo "" >> "$REVIEW_LOG"
done
echo "İnceleme tamamlandı. Detaylar: $REVIEW_LOG"
cat "$REVIEW_LOG"
Bu hook, her git push öncesinde değişen dosyaları alıp Ollama’ya gönderiyor ve sonuçları hem ekrana basıyor hem de dosyaya kaydediyor.
Python ile Daha Gelişmiş Bir Code Review Aracı
Hook yeterli değil, daha yapılandırılmış bir araç istiyorsanız Python ile şöyle bir şey yazabilirsiniz:
#!/usr/bin/env python3
# code_reviewer.py
import subprocess
import requests
import json
import sys
import argparse
from pathlib import Path
OLLAMA_URL = "http://localhost:11434/api/generate"
DEFAULT_MODEL = "codellama:13b"
REVIEW_PROMPT_TEMPLATE = """Sen deneyimli bir kod inceleyicisin. Aşağıdaki {language} kodunu analiz et.
Şu kriterlere göre değerlendir:
- Güvenlik: SQL injection, XSS, hardcoded credentials, vb.
- Performans: N+1 sorguları, gereksiz döngüler, bellek sızıntıları
- Hata yönetimi: Exception handling, edge case'ler
- Okunabilirlik: Değişken isimleri, fonksiyon uzunluğu, karmaşıklık
- Test edilebilirlik: Bağımlılıklar, side effects
Dosya: {filename}
{code}
Çıktını şu formatta ver:
## Kritik Sorunlar
[varsa listele, yoksa "Yok"]
## Uyarılar
[varsa listele, yoksa "Yok"]
## Öneriler
[varsa listele, yoksa "Yok"]
## Genel Değerlendirme
[1-2 cümle özet]"""
def get_language(filename: str) -> str:
ext_map = {
'.py': 'python', '.js': 'javascript', '.ts': 'typescript',
'.go': 'go', '.java': 'java', '.rb': 'ruby',
'.php': 'php', '.cs': 'csharp', '.cpp': 'cpp', '.rs': 'rust'
}
ext = Path(filename).suffix.lower()
return ext_map.get(ext, 'text')
def review_file(filepath: str, model: str = DEFAULT_MODEL) -> dict:
with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
code = f.read()
if len(code) > 8000:
print(f"Uyarı: {filepath} büyük ({len(code)} karakter), kırpılıyor...")
code = code[:8000] + "n... [dosya kırpıldı]"
language = get_language(filepath)
prompt = REVIEW_PROMPT_TEMPLATE.format(
language=language,
filename=filepath,
code=code
)
response = requests.post(OLLAMA_URL, json={
"model": model,
"prompt": prompt,
"stream": False,
"options": {
"temperature": 0.1,
"num_ctx": 4096
}
}, timeout=120)
result = response.json()
return {
"file": filepath,
"language": language,
"review": result.get("response", "Yanıt alınamadı"),
"model": model
}
def main():
parser = argparse.ArgumentParser(description='Ollama ile kod inceleme aracı')
parser.add_argument('files', nargs='+', help='İncelenecek dosyalar')
parser.add_argument('--model', default=DEFAULT_MODEL, help='Kullanılacak model')
parser.add_argument('--output', help='Çıktı dosyası (markdown)')
args = parser.parse_args()
results = []
for filepath in args.files:
if not Path(filepath).exists():
print(f"Dosya bulunamadı: {filepath}")
continue
print(f"İnceleniyor: {filepath}")
result = review_file(filepath, args.model)
results.append(result)
print(result['review'])
print("-" * 60)
if args.output:
with open(args.output, 'w') as f:
f.write("# Kod İnceleme Raporunn")
for r in results:
f.write(f"## {r['file']}n")
f.write(f"*Model: {r['model']} | Dil: {r['language']}*nn")
f.write(r['review'])
f.write("nn---nn")
print(f"nRapor kaydedildi: {args.output}")
if __name__ == "__main__":
main()
Kullanımı şöyle:
# Tek dosya inceleme
python3 code_reviewer.py src/auth.py
# Birden fazla dosya
python3 code_reviewer.py src/*.py --output review_report.md
# Farklı model ile
python3 code_reviewer.py app.js --model deepseek-coder:6.7b
# Git'teki değişen dosyaları incele
git diff --name-only HEAD~1 | xargs python3 code_reviewer.py --output pr_review.md
Otomatik Yorum Yazma: Docstring ve JSDoc Üretimi
Code review’un ötesinde, mevcut koda otomatik yorum ve dokümantasyon eklemek de Ollama ile yapılabilir. Özellikle legacy kod tabanlarında bu inanılmaz zaman kazandırıyor.
#!/bin/bash
# add_docstrings.sh - Python fonksiyonlarına otomatik docstring ekler
OLLAMA_URL="http://localhost:11434/api/generate"
MODEL="codellama:13b"
INPUT_FILE="$1"
OUTPUT_FILE="${INPUT_FILE%.py}_documented.py"
if [ -z "$INPUT_FILE" ]; then
echo "Kullanım: $0 <python_dosyası>"
exit 1
fi
FILE_CONTENT=$(cat "$INPUT_FILE")
PROMPT="Aşağıdaki Python kodundaki her fonksiyon ve sınıf için Google style docstring ekle.
Mevcut kodu değiştirme, sadece docstring'leri ekle.
Türkçe yorum yazma, İngilizce docstring kullan.
Sonuç olarak sadece kodu döndür, açıklama ekleme.
$FILE_CONTENT"
echo "Dokümantasyon oluşturuluyor: $INPUT_FILE"
curl -s "$OLLAMA_URL"
-H "Content-Type: application/json"
-d "$(jq -n
--arg model "$MODEL"
--arg prompt "$PROMPT"
'{model: $model, prompt: $prompt, stream: false, options: {temperature: 0.1}}')"
| jq -r '.response' > "$OUTPUT_FILE"
echo "Tamamlandı: $OUTPUT_FILE"
echo "Fark kontrolü için: diff $INPUT_FILE $OUTPUT_FILE"
CI/CD Pipeline’a Entegrasyon
GitLab CI örneği üzerinden gösterelim. Bu pipeline, her merge request’te otomatik code review çalıştırıp sonuçları artifact olarak saklıyor:
# .gitlab-ci.yml
stages:
- test
- code-review
variables:
OLLAMA_URL: "http://ollama-service:11434"
REVIEW_MODEL: "codellama:13b"
code-review:
stage: code-review
image: python:3.11-slim
before_script:
- pip install requests
- apt-get update -qq && apt-get install -y -qq jq git
script:
- |
# Değişen dosyaları bul
CHANGED=$(git diff --name-only origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME...HEAD
| grep -E '.(py|js|ts|go)$' || true)
if [ -z "$CHANGED" ]; then
echo "İncelenecek kod değişikliği yok."
exit 0
fi
# Model hazır mı kontrol et
curl -sf "$OLLAMA_URL/api/tags" > /dev/null || {
echo "Ollama servisi erişilemiyor, inceleme atlanıyor."
exit 0
}
echo "$CHANGED" | xargs python3 scripts/code_reviewer.py
--model "$REVIEW_MODEL"
--output review_report.md
artifacts:
paths:
- review_report.md
expire_in: 30 days
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
allow_failure: true
Önemli not: allow_failure: true koymayı unutmayın. Code review aracı çöktüğünde deployment’ı bloke etmemeli. Bu araç yardımcıdır, geçit bekçisi değil.
Modelfile ile Özelleştirilmiş Review Modeli
Ollama’nın güzel özelliklerinden biri kendi sistem prompt’unuzla özelleştirilmiş model oluşturabilmek. Şirketin kod standartlarını buraya ekleyebilirsiniz:
# Modelfile oluştur
cat > Modelfile.codereview << 'EOF'
FROM codellama:13b
SYSTEM """
Sen şirketimizin kod inceleme standardlarını bilen kıdemli bir yazılım mühendisisin.
Kod incelerken şu kurallara uy:
- PEP8 standartlarına uyum kontrol et (Python için)
- Fonksiyonlar 30 satırı geçmemeli
- Magic number kullanımını işaretle
- Her public API'nin docstring'i olmalı
- try/except bloklarında bare except kullanımını eleştir
- Loglama için print() yerine logging modülü kullanılmalı
- Veritabanı işlemlerinde bağlantı havuzu kullanımını kontrol et
- Hardcoded URL, IP veya credential varsa kritik sorun olarak işaretle
Türkçe yanıt ver. Kısa ve net ol, gereksiz övgü yapma.
"""
PARAMETER temperature 0.1
PARAMETER num_ctx 4096
EOF
# Modeli oluştur
ollama create company-reviewer -f Modelfile.codereview
# Test et
ollama run company-reviewer "def connect(): conn = psycopg2.connect('host=prod-db password=123456')"
Bu yaklaşımla farklı ekipler için farklı reviewer profilleri oluşturabilirsiniz: backend ekibi için ayrı, frontend ekibi için ayrı.
Gerçek Hayat Senaryosu: SQL Injection Tespiti
Bir gün ekibimizden biri legacy bir PHP projesinde code review yapıyordu. Yüzlerce dosya, binlerce satır kod. Elle geçmek günler alacaktı. Ollama ile şöyle bir tarama yaptık:
#!/bin/bash
# security_scan.sh - SQL injection ve güvenlik açığı taraması
OLLAMA_URL="http://localhost:11434/api/generate"
MODEL="codellama:13b"
TARGET_DIR="${1:-.}"
FINDINGS_FILE="security_findings_$(date +%Y%m%d).md"
echo "# Güvenlik Tarama Raporu" > "$FINDINGS_FILE"
echo "Tarih: $(date)" >> "$FINDINGS_FILE"
echo "Dizin: $TARGET_DIR" >> "$FINDINGS_FILE"
echo "" >> "$FINDINGS_FILE"
find "$TARGET_DIR" -name "*.php" -o -name "*.py" -o -name "*.js" | while read -r FILE; do
FILE_CONTENT=$(head -c 5000 "$FILE")
RESPONSE=$(curl -s "$OLLAMA_URL/api/generate"
-H "Content-Type: application/json"
-d "$(jq -n
--arg model "$MODEL"
--arg code "$FILE_CONTENT"
--arg file "$FILE"
'{
model: $model,
prompt: ("Sadece güvenlik açıkları varsa yanıt ver. Yoksa sadece OK yaz.nDosya: " + $file + "n```n" + $code + "n```"),
stream: false,
options: {temperature: 0.1}
}')"
| jq -r '.response')
if [ "$RESPONSE" != "OK" ] && [ "${#RESPONSE}" -gt 5 ]; then
echo "## $FILE" >> "$FINDINGS_FILE"
echo "$RESPONSE" >> "$FINDINGS_FILE"
echo "" >> "$FINDINGS_FILE"
echo "UYARI: $FILE"
else
echo "Temiz: $FILE"
fi
done
echo "Tarama tamamlandı. Rapor: $FINDINGS_FILE"
Bu script bizim için 200 dosyayı yaklaşık 40 dakikada taradı. Sonuçların %80’i isabetliydi, birkaç false positive vardı ama kritik 3 SQL injection açığını doğru tespit etti. Elle yapılsaydı bu iş günler alırdı.
Performans ve Optimizasyon İpuçları
Pratikte karşılaştığım birkaç önemli nokta:
- Model seçimi:
codellama:7bdaha hızlı amacodellama:13bçok daha isabetli. Sunucunuzun RAM’i 16GB’ın üzerindeyse 13B modelini tercih edin. - Sıcaklık (temperature): Kod inceleme için
0.1değerini kullanın. Yüksek temperature yaratıcılık için iyidir ama kod analizi için tutarsızlık yaratır. - Bağlam penceresi: Büyük dosyaları gönderirken
num_ctxdeğerini artırın, ama dikkatli olun. 8192 bağlam penceresi için modelin çok daha fazla VRAM kullandığını unutmayın. - Paralel çalışma: Çok dosya tarıyorsanız
xargs -P 4ile paralel çalıştırabilirsiniz ama bu GPU belleğini zorlayabilir. - Dosya boyutu: 500 satırı geçen dosyaları bölmeyi düşünün. Büyük dosyalar bağlamın sonunda kalan kısmı model unutabiliyor.
Model’in yanıt süreleri GPU’ya göre dramatik değişiyor. RTX 3090 gibi bir kartla 13B model saniyeler içinde yanıt verirken, CPU üzerinde aynı iş dakikalar alabilir. CI/CD’ye entegre edecekseniz GPU’lu bir runner kullanmanızı şiddetle tavsiye ederim.
Sonuç
Ollama tabanlı kod inceleme sistemi kurulumu göründüğünden kolay. Temel kurulumdan şirket standartlarına özelleştirilmiş modele, git hook’tan CI/CD entegrasyonuna kadar uzanan bu araç seti, özellikle büyük kod tabanlarında ve güvenlik taramalarında ciddi zaman kazandırıyor.
Şunu açıkça söylemek gerekir: bu araç insan code review’ının yerini almaz ve almamalı. Mimari kararlar, iş mantığı uygunluğu, takım konvansiyonlarına uyum gibi konularda hala insan gözetimi şart. Ama tekrarlayan güvenlik kontrolleri, stil denetimleri ve dokümantasyon eksikliklerini tespit etmekte gerçekten işe yarıyor.
Kodunuzu buluta göndermeden, sıfır maliyet ve tam kontrol ile bu altyapıyı kendi sunucunuzda çalıştırabilmek ise ayrı bir özgürlük. Özellikle veri gizliliği hassasiyeti olan ortamlarda bu fark gerçekten önemli oluyor.
