SevdanurGenc's picture
Upload 300 files
9438a57 verified
Raw History Blame Contribute Delete
9.35 kB
#!/usr/bin/env bash
# TestAjanı başlatıcı (macOS + Linux).
# Kullanım: ./scripts/start.sh [--rebuild] [--model MODEL] [--no-browser]
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
MODEL="${OLLAMA_MODEL:-qwen2.5-coder:7b}"
REBUILD=0
OPEN_BROWSER=1
APP_URL="http://localhost:8000"
while [ $# -gt 0 ]; do
case "$1" in
--rebuild) REBUILD=1 ;;
--model) MODEL="$2"; shift ;;
--no-browser) OPEN_BROWSER=0 ;;
-h|--help) sed -n '2,3p' "$0"; exit 0 ;;
*) echo "Bilinmeyen seçenek: $1"; exit 2 ;;
esac
shift
done
OS="$(uname -s)"
step() { printf '\n\033[1;34m==>\033[0m %s\n' "$1"; }
ok() { printf ' \033[32m✓\033[0m %s\n' "$1"; }
fail() { printf '\n\033[31mHATA:\033[0m %s\n' "$1"; exit 1; }
http_ok() { curl -fsS -m 3 -o /dev/null "$1" 2>/dev/null; }
# ---------------------------------------------------------------- 1. Docker kurulu mu?
step "Docker kontrol ediliyor"
if ! command -v docker >/dev/null 2>&1; then
if [ "$OS" = "Darwin" ]; then
echo " Docker Desktop kurulu değil."
if command -v brew >/dev/null 2>&1; then
read -r -p " Homebrew ile şimdi kurulsun mu? [E/h] " ans
if [[ ! "$ans" =~ ^[Hh] ]]; then
brew install --cask docker
else
fail "Docker Desktop'ı https://www.docker.com/products/docker-desktop/ adresinden kurup tekrar deneyin."
fi
else
fail "Docker Desktop'ı https://www.docker.com/products/docker-desktop/ adresinden kurup tekrar deneyin."
fi
else
fail "Docker kurulu değil. Kurulum: https://docs.docker.com/engine/install/ (hızlı yol: curl -fsSL https://get.docker.com | sh)"
fi
fi
ok "docker komutu bulundu"
# ---------------------------------------------------------------- 2. Docker çalışıyor mu?
if ! docker info >/dev/null 2>&1; then
if [ "$OS" = "Darwin" ]; then
echo " Docker Desktop başlatılıyor…"
open -a Docker || fail "Docker Desktop açılamadı. Uygulamalar klasöründen elle açın."
elif docker info 2>&1 | grep -qi "permission denied"; then
fail "Docker'a erişim izni yok. Şunu çalıştırıp oturumu kapatıp açın: sudo usermod -aG docker \$USER"
else
echo " Docker servisi başlatılıyor (sudo parolası istenebilir)…"
sudo systemctl start docker 2>/dev/null || true
fi
for _ in $(seq 1 60); do
docker info >/dev/null 2>&1 && break
sleep 3
done
docker info >/dev/null 2>&1 || fail "Docker 3 dakikada başlamadı. Docker'ı elle açıp tekrar deneyin."
fi
docker compose version >/dev/null 2>&1 || fail "'docker compose' bulunamadı. Docker'ı güncelleyin (Compose v2 gerekli)."
ok "Docker çalışıyor"
# ---------------------------------------------------------------- 3. Sandbox imajları
step "Kod çalıştırma ortamları (sandbox imajları)"
for lang in python node java ui; do
img="lta-sandbox-$lang"
# Dockerfile değiştiyse (ör. yeni kütüphane) imaj yeniden derlenir: özet imaj etiketinde tutulur
hash="$( (sha256sum "sandbox/docker/$lang.Dockerfile" 2>/dev/null || shasum -a 256 "sandbox/docker/$lang.Dockerfile") | cut -c1-16)"
have="$(docker image inspect "$img" --format '{{ index .Config.Labels "lta.hash" }}' 2>/dev/null || true)"
if [ "$REBUILD" = 1 ] || [ "$have" != "$hash" ]; then
echo " $img derleniyor (ilk seferde birkaç dakika sürer)…"
docker build -q --label "lta.hash=$hash" -f "sandbox/docker/$lang.Dockerfile" -t "$img" sandbox >/dev/null
fi
ok "$img"
done
# ---------------------------------------------------------------- 4. Ollama: yerel mi, konteyner mi?
step "Dil modeli sunucusu (Ollama)"
PROFILE_ARGS=()
if http_ok "http://localhost:11434/api/tags" && ! docker compose ps --services --status running 2>/dev/null | grep -qx ollama; then
export OLLAMA_URL="http://host.docker.internal:11434"
OLLAMA_MODE=host
ok "Bilgisayardaki Ollama kullanılacak"
else
export OLLAMA_URL="http://ollama:11434"
OLLAMA_MODE=docker
PROFILE_ARGS=(--profile ollama)
ok "Ollama konteynerde çalışacak"
if command -v nvidia-smi >/dev/null || [ "$(uname)" = "Darwin" ]; then
echo " [UYARI] Konteynerdeki Ollama ekran kartını (Mac'te Metal) genellikle kullanmaz; çok yavaş olur."
echo " Hız için Ollama'yı bilgisayara kurun: https://ollama.com/download — sonra yeniden başlatın."
fi
fi
export OLLAMA_MODEL="$MODEL"
# ---------------------------------------------------------------- 5. Uygulamayı başlat
step "Uygulama başlatılıyor"
EXPECTED="$(head -n1 VERSION 2>/dev/null | tr -d '[:space:]')"
# Başka bir klasörden (eski sürümden) başlatılmış ve 8000 portunu tutan uygulama konteynerini kaldır
docker ps -a --filter "publish=8000" --format '{{.ID}}|{{.Names}}|{{.Labels}}' 2>/dev/null | while IFS='|' read -r cid cname clabels; do
proj="$(printf '%s' "$clabels" | tr ',' '\n' | sed -n 's/^com\.docker\.compose\.project=//p')"
if [ -n "$cid" ] && [ "$proj" != "llm-test-agent" ]; then
echo " Eski uygulama konteyneri kaldırılıyor: $cname (proje: ${proj:-yok})"
docker rm -f "$cid" >/dev/null 2>&1 || true
fi
done
# Her başlatmada imaj güncellenir; değişiklik yoksa Docker önbelleği sayesinde birkaç saniye sürer
BUILD_ARGS=(--build)
if [ -z "$(docker compose images -q app 2>/dev/null)" ]; then
echo " Uygulama imajı derleniyor (ilk seferde birkaç dakika sürer)…"
fi
# Not: macOS'taki bash 3.2 boş dizileri "set -u" altında sorun sayar; bu yüzden ${a[@]+...} kalıbı
# NVIDIA kartı varsa uygulama konteynerine GPU izleme erişimi verilir (gerçek zamanlı GPU göstergesi için)
GPU_FILES=()
command -v nvidia-smi >/dev/null && GPU_FILES=(-f docker-compose.yml -f docker-compose.gpu.yml)
if ! docker compose ${GPU_FILES[@]+"${GPU_FILES[@]}"} ${PROFILE_ARGS[@]+"${PROFILE_ARGS[@]}"} up -d ${BUILD_ARGS[@]+"${BUILD_ARGS[@]}"}; then
[ ${#GPU_FILES[@]} -gt 0 ] || fail "docker compose up başarısız oldu. Ayrıntı: docker compose logs"
echo " [UYARI] Konteynere GPU erişimi verilemedi; GPU göstergesi yalnızca Ollama bilgisini gösterecek."
docker compose ${PROFILE_ARGS[@]+"${PROFILE_ARGS[@]}"} up -d ${BUILD_ARGS[@]+"${BUILD_ARGS[@]}"} || fail "docker compose up başarısız oldu."
fi
ok "Konteynerler ayakta"
# ---------------------------------------------------------------- 6. Model
step "Model: $MODEL"
for _ in $(seq 1 40); do http_ok "http://localhost:11434/api/tags" && break; sleep 2; done
if curl -fsS -m 5 "http://localhost:11434/api/tags" 2>/dev/null | grep -q "\"name\":\"$MODEL"; then
ok "Model zaten indirilmiş"
else
echo " Model indiriliyor (yalnızca ilk seferde; ~5 GB)…"
if [ "$OLLAMA_MODE" = host ]; then
ollama pull "$MODEL"
else
docker compose --profile ollama exec -T ollama ollama pull "$MODEL"
fi
ok "Model hazır"
fi
# ---------------------------------------------------------------- 7. Hazır olmasını bekle, tarayıcıyı aç
step "Arayüz hazırlanıyor"
# Hafif /api/ping kullanılır (Ollama'ya dokunmaz); eski sürümde ping yoksa /api/health'e uzun zaman aşımıyla bakılır.
app_version() {
local v
v="$(curl -fsS -m 5 "$1/api/ping" 2>/dev/null | sed -n 's/.*"version":"\([^"]*\)".*/\1/p')"
[ -n "$v" ] || v="$(curl -fsS -m 30 "$1/api/health" 2>/dev/null | sed -n 's/.*"version":"\([^"]*\)".*/\1/p')"
printf '%s' "$v"
}
wait_app() {
local v u
for _ in $(seq 1 60); do
for u in "http://localhost:8000" "http://127.0.0.1:8000"; do
v="$(app_version "$u")"
if [ -n "$v" ]; then APP_URL="$u"; RUNNING="$v"; return 0; fi
done
sleep 2
done
RUNNING=""; return 1
}
show_diag() {
printf '\n\033[33m---- docker compose ps ----\033[0m\n'; docker compose ps -a || true
printf '\033[33m---- docker compose logs app (son 60 satır) ----\033[0m\n'; docker compose logs app --tail 60 || true
}
wait_app || { show_diag; fail "Uygulama yanıt vermiyor. Yukarıdaki satırların ekran görüntüsünü paylaşın."; }
if [ -n "$EXPECTED" ] && [ "$RUNNING" != "$EXPECTED" ]; then
echo " Çalışan sürüm '${RUNNING}', beklenen '${EXPECTED}'. Uygulama önbelleksiz yeniden derleniyor…"
docker compose ${GPU_FILES[@]+"${GPU_FILES[@]}"} build --no-cache app || docker compose build --no-cache app
docker compose ${GPU_FILES[@]+"${GPU_FILES[@]}"} ${PROFILE_ARGS[@]+"${PROFILE_ARGS[@]}"} up -d --force-recreate app \
|| docker compose ${PROFILE_ARGS[@]+"${PROFILE_ARGS[@]}"} up -d --force-recreate app
wait_app || true
[ "$RUNNING" = "$EXPECTED" ] || { show_diag; fail "Uygulama hâlâ eski sürümde ('${RUNNING}'). 'docker ps' ile 8000 portunu kullanan konteyneri kontrol edin."; }
fi
if ! curl -fsS -m 30 "$APP_URL/api/health" 2>/dev/null | grep -q '"ollama":{"ok":true'; then
printf ' \033[33m!\033[0m Uygulama Ollama’ya ulaşamıyor (%s).\n' "$OLLAMA_URL"
echo " Ollama'yı yeniden başlatın; sürerse OLLAMA_HOST=0.0.0.0 ile başlatın (Linux: systemctl edit ollama)."
echo " Arayüz yine de açılıyor; Ollama düzelince üst çubuktaki durum yeşile döner."
fi
ok "Sürüm: $RUNNING"
ok "Hazır: $APP_URL"
if [ "$OPEN_BROWSER" = 1 ]; then
if [ "$OS" = "Darwin" ]; then open "$APP_URL/?v=$RUNNING"
elif command -v xdg-open >/dev/null 2>&1; then xdg-open "$APP_URL/?v=$RUNNING" >/dev/null 2>&1 &
fi
fi
echo
echo "Durdurmak için: ./scripts/stop.sh (veya Durdur kısayolu)"