Consolidated local ollama model logic

This commit is contained in:
2026-04-07 15:44:17 +02:00
parent 9b2573ebb8
commit e737c51924
10 changed files with 1943 additions and 350 deletions
+1589
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -0,0 +1,3 @@
Kannst du mir ein Skript bauen, dass wenn ich den Namen der Tabelle in sql server habe,
du mir das T-SQL ausgibst was ich brauche, um select sourcedb.Tabelle col1, col2,... etc. INTO Tabelle col1, col2,... etc. zu erzeugen?
+45
View File
@@ -0,0 +1,45 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_OVERRIDE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
export ROOT_OVERRIDE
# shellcheck disable=SC1091
source "${ROOT_OVERRIDE}/scripts/common.sh"
init_log bootstrap-native
print_header "bootstrap-native: START"
need_cmd curl
need_cmd python
need_cmd ollama
load_env
check_for_legacy_docker_ollama
log "bootstrap-native: waiting for Ollama API at ${OLLAMA_URL}"
wait_for_ollama_api "$OLLAMA_URL" 120 || fail "Ollama API not reachable at ${OLLAMA_URL}" 40
ok "bootstrap-native: Ollama API reachable"
log "bootstrap-native: pulling base model ${BASE_MODEL}"
ollama pull "${BASE_MODEL}"
if [[ -n "${EXTRA_MODELS}" ]]; then
for m in ${EXTRA_MODELS}; do
log "bootstrap-native: pulling extra model ${m}"
ollama pull "$m"
done
fi
tmp="$(mktemp)"
trap 'rm -f "$tmp"' EXIT
render_modelfile "$tmp"
log "bootstrap-native: building expert model ${EXPERT_MODEL}"
ollama create "${EXPERT_MODEL}" -f "$tmp"
tags="$(fetch_tags)"
printf '%s' "$tags" | is_json || fail "/api/tags did not return valid JSON" 41
model_in_tags "$EXPERT_MODEL" "$tags" || fail "expert model missing after bootstrap: ${EXPERT_MODEL}" 42
ok "bootstrap-native: expert model available: ${EXPERT_MODEL}"
warmup_sqlai
print_footer "bootstrap-native: END status=OK log=${LOG_FILE}"
-68
View File
@@ -1,68 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cp -n "${ROOT}/.env.example" "${ROOT}/.env" || true
source "${ROOT}/.env"
ts(){ date -Is; }
log_dir="${ROOT}/logs"
mkdir -p "$log_dir"
log_file="${log_dir}/bootstrap-$(date -Iseconds).log"
exec > >(tee -a "$log_file") 2>&1
echo "[$(ts)] bootstrap: starting (ROOT=$ROOT)"
echo "[$(ts)] bootstrap: docker compose up -d"
docker compose -f "${ROOT}/docker-compose.yml" up -d
echo "[$(ts)] bootstrap: waiting for Ollama API at ${OLLAMA_URL} ..."
for i in {1..120}; do
if curl -sS "${OLLAMA_URL}/api/tags" >/dev/null 2>&1; then
echo "[$(ts)] bootstrap: Ollama API is up."
break
fi
if [[ $i -eq 120 ]]; then
echo "[$(ts)] bootstrap: ERROR: API did not come up in time."
exit 1
fi
sleep 1
done
echo "[$(ts)] bootstrap: pulling base model: ${BASE_MODEL}"
docker exec -it ollama ollama pull "${BASE_MODEL}"
if [[ -n "${EXTRA_MODELS:-}" ]]; then
for m in ${EXTRA_MODELS}; do
echo "[$(ts)] bootstrap: pulling extra model: $m"
docker exec -it ollama ollama pull "$m"
done
fi
echo "[$(ts)] bootstrap: building expert model: ${EXPERT_MODEL}"
tmp="$(mktemp)"
sed "s/\${BASE_MODEL}/${BASE_MODEL}/g" "${ROOT}/Modelfile" > "$tmp"
docker cp "$tmp" ollama:/tmp/Modelfile.jr-sql-expert
docker exec -it ollama ollama create "${EXPERT_MODEL}" -f /tmp/Modelfile.jr-sql-expert
rm -f "$tmp"
echo "[$(ts)] bootstrap: verifying model exists..."
docker exec -it ollama ollama list | grep -F "${EXPERT_MODEL}" >/dev/null && \
echo "[$(ts)] bootstrap: OK: ${EXPERT_MODEL} is available."
# Warmup
if [[ -x "${ROOT}/bin/sqlai" ]]; then
echo "[$(ts)] bootstrap: warmup: sending a short request (no-metrics)..."
"${ROOT}/bin/sqlai" ask --text "Warmup: reply with exactly 'OK'." --no-metrics || {
echo "[$(ts)] bootstrap: WARN: warmup failed (continuing)."
}
echo "[$(ts)] bootstrap: warmup: done"
else
echo "[$(ts)] bootstrap: WARN: ${ROOT}/bin/sqlai not executable; skipping warmup."
fi
echo "[$(ts)] bootstrap: done"
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
LOG_DIR="${ROOT}/logs"
mkdir -p "$LOG_DIR"
LOG_FILE="${LOG_DIR}/cleanup-docker-ollama-$(date -Iseconds).log"
exec > >(tee -a "$LOG_FILE") 2>&1
ts(){ date -Is; }
log(){ echo "[$(ts)] $*"; }
log "cleanup-docker-ollama: START ROOT=${ROOT}"
if ! command -v docker >/dev/null 2>&1; then
log "cleanup-docker-ollama: docker not installed; nothing to do"
exit 0
fi
if [[ -f "${ROOT}/docker-compose.yml" ]] && docker compose version >/dev/null 2>&1; then
log "cleanup-docker-ollama: docker compose down --remove-orphans"
docker compose -f "${ROOT}/docker-compose.yml" down --remove-orphans || true
fi
if docker ps -a --format '{{.Names}}' | grep -qx 'ollama'; then
log "cleanup-docker-ollama: removing container ollama"
docker rm -f ollama || true
else
log "cleanup-docker-ollama: container ollama not present"
fi
if docker images --format '{{.Repository}}:{{.Tag}}' | grep -qx 'ollama/ollama:latest'; then
log "cleanup-docker-ollama: removing image ollama/ollama:latest"
docker image rm -f ollama/ollama:latest || true
else
log "cleanup-docker-ollama: image ollama/ollama:latest not present"
fi
if [[ "${PURGE_OLLAMA_DOCKER_VOLUMES:-0}" == "1" ]]; then
mapfile -t volumes < <(docker volume ls --format '{{.Name}}' | grep -E 'ollama' || true)
if (( ${#volumes[@]} > 0 )); then
log "cleanup-docker-ollama: removing volumes: ${volumes[*]}"
docker volume rm "${volumes[@]}" || true
else
log "cleanup-docker-ollama: no ollama volumes found"
fi
else
log "cleanup-docker-ollama: keeping volumes (set PURGE_OLLAMA_DOCKER_VOLUMES=1 to remove them)"
fi
log "cleanup-docker-ollama: END log=${LOG_FILE}"
+149
View File
@@ -0,0 +1,149 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="${ROOT_OVERRIDE:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
ENV_FILE="${ENV_FILE:-${ROOT}/.env}"
MODFILE="${MODFILE:-${ROOT}/Modelfile}"
SQLAI_BIN="${SQLAI_BIN:-${ROOT}/bin/sqlai}"
LOG_FILE=""
_ts_prefix(){ date -Is; }
ts(){ _ts_prefix; }
log(){ echo "[$(ts)] $*"; }
ok(){ log "OK $*"; }
warn(){ log "WARN $*"; }
fail(){
local msg="$1"
local code="${2:-1}"
log "FAIL $msg"
exit "$code"
}
need_cmd(){
command -v "$1" >/dev/null 2>&1 || fail "missing command: $1" 10
}
init_log(){
local name="$1"
local log_dir="${ROOT}/logs"
mkdir -p "$log_dir"
LOG_FILE="${log_dir}/${name}-$(date -Iseconds).log"
export LOG_FILE
exec > >(tee -a "$LOG_FILE") 2>&1
}
load_env(){
if [[ ! -f "$ENV_FILE" && -f "${ROOT}/.env.example" ]]; then
cp -n "${ROOT}/.env.example" "$ENV_FILE" || true
fi
if [[ -f "$ENV_FILE" ]]; then
set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
fi
: "${OLLAMA_URL:=http://127.0.0.1:11434}"
: "${EXPERT_MODEL:=jr-sql-expert}"
: "${BASE_MODEL:=}"
: "${EXTRA_MODELS:=}"
export OLLAMA_URL EXPERT_MODEL BASE_MODEL EXTRA_MODELS
# The Ollama CLI honors OLLAMA_HOST.
export OLLAMA_HOST="$OLLAMA_URL"
}
is_json(){
python -c 'import json,sys; json.load(sys.stdin)' >/dev/null 2>&1
}
wait_for_ollama_api(){
local url="$1"
local max_wait="${2:-120}"
local i
for ((i=1; i<=max_wait; i++)); do
if curl -fsS "${url}/api/tags" >/dev/null 2>&1; then
return 0
fi
sleep 1
done
return 1
}
fetch_tags(){
curl -fsS "${OLLAMA_URL}/api/tags"
}
model_in_tags(){
local model="$1"
local tags="$2"
TAGS_JSON="$tags" python - "$model" <<'PY'
import json
import os
import sys
m = sys.argv[1]
obj = json.loads(os.environ['TAGS_JSON'])
names = {it.get('name') for it in obj.get('models', []) if it.get('name')}
ok = (
m in names or
f"{m}:latest" in names or
(m.endswith(':latest') and m[:-7] in names)
)
sys.exit(0 if ok else 1)
PY
}
render_modelfile(){
local out_file="$1"
[[ -f "$MODFILE" ]] || fail "Modelfile not found at $MODFILE" 20
[[ -n "$BASE_MODEL" ]] || fail "BASE_MODEL is empty" 21
python - "$MODFILE" "$out_file" "$BASE_MODEL" <<'PY'
from pathlib import Path
import sys
src = Path(sys.argv[1]).read_text(encoding='utf-8')
out = src.replace('${BASE_MODEL}', sys.argv[3])
Path(sys.argv[2]).write_text(out, encoding='utf-8')
PY
}
check_for_legacy_docker_ollama(){
if ! command -v docker >/dev/null 2>&1; then
return 0
fi
if docker ps --format '{{.Names}}' | grep -qx 'ollama'; then
fail "legacy docker container 'ollama' is still running; run cleanup-docker-ollama.sh first" 30
fi
if docker ps -a --format '{{.Names}}' | grep -qx 'ollama'; then
warn "legacy docker container 'ollama' still exists in stopped state; cleanup recommended"
fi
if docker images --format '{{.Repository}}:{{.Tag}}' | grep -qx 'ollama/ollama:latest'; then
warn "legacy docker image ollama/ollama:latest still exists; cleanup recommended"
fi
}
warmup_sqlai(){
if [[ -x "$SQLAI_BIN" ]]; then
log "warmup via ${SQLAI_BIN}"
"$SQLAI_BIN" ask --text "Warmup: reply with exactly 'OK'." --no-metrics || warn "warmup failed"
else
warn "${SQLAI_BIN} not executable; skipping warmup"
fi
}
print_header(){
echo "================================================================================"
log "$1 ROOT=$ROOT"
}
print_footer(){
log "$1"
echo "================================================================================"
}
+60
View File
@@ -0,0 +1,60 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_OVERRIDE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
export ROOT_OVERRIDE
# shellcheck disable=SC1091
source "${ROOT_OVERRIDE}/scripts/common.sh"
init_log selftest-native
print_header "selftest-native: START"
need_cmd curl
need_cmd python
need_cmd ollama
need_cmd grep
load_env
check_for_legacy_docker_ollama
[[ -x "$SQLAI_BIN" ]] || fail "bin/sqlai missing or not executable at ${SQLAI_BIN}" 60
log "selftest-native: waiting for Ollama API at ${OLLAMA_URL}"
wait_for_ollama_api "$OLLAMA_URL" 120 || fail "Ollama API not reachable at ${OLLAMA_URL}" 61
ok "selftest-native: Ollama API reachable"
tags="$(fetch_tags)"
[[ -n "$tags" ]] || fail "/api/tags returned empty body" 62
printf '%s' "$tags" | is_json || fail "/api/tags did not return valid JSON" 63
ok "selftest-native: /api/tags returned valid JSON"
if model_in_tags "$EXPERT_MODEL" "$tags"; then
ok "selftest-native: expert model present: ${EXPERT_MODEL}"
else
fail "expert model missing: ${EXPERT_MODEL}" 64
fi
if [[ -n "${BASE_MODEL}" ]]; then
if model_in_tags "$BASE_MODEL" "$tags"; then
ok "selftest-native: base model present: ${BASE_MODEL}"
else
fail "base model missing: ${BASE_MODEL}" 65
fi
fi
log "selftest-native: warmup request via sqlai"
set +e
"$SQLAI_BIN" ask --text "Warmup: reply with exactly 'OK'." --no-metrics
rc=$?
set -e
[[ "$rc" -eq 0 ]] || warn "warmup failed rc=${rc}"
log "selftest-native: real query via sqlai"
set +e
out="$("$SQLAI_BIN" ask --text "Give a concise checklist to troubleshoot parameter sniffing in SQL Server 2022. Keep it technical." --no-metrics 2>&1)"
rc=$?
set -e
[[ "$rc" -eq 0 ]] || fail "real query failed rc=${rc}" 66
[[ -n "${out//[[:space:]]/}" ]] || fail "real query returned empty output" 67
ok "selftest-native: real query returned non-empty output"
print_footer "selftest-native: END status=OK log=${LOG_FILE}"
-212
View File
@@ -1,212 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ENV_FILE="${ROOT}/.env"
ts(){ date -Is; }
log_dir="${ROOT}/logs"
mkdir -p "$log_dir"
log_file="${log_dir}/selftest-$(date -Iseconds).log"
exec > >(tee -a "$log_file") 2>&1
echo "================================================================================"
echo "[$(ts)] selftest: START ROOT=$ROOT"
# -------- helpers --------
fail() {
local msg="$1"
local code="${2:-1}"
echo "[$(ts)] selftest: FAIL code=$code msg=$msg"
echo "[$(ts)] selftest: END status=FAIL"
echo "================================================================================"
exit "$code"
}
warn() {
echo "[$(ts)] selftest: WARN $*"
}
ok() {
echo "[$(ts)] selftest: OK $*"
}
need_cmd() {
command -v "$1" >/dev/null 2>&1 || fail "missing command: $1" 10
}
# robust JSON check
is_json() {
# reads stdin
python -c 'import json,sys; json.load(sys.stdin)' >/dev/null 2>&1
}
# Extract model names from /api/tags JSON and check membership
model_in_tags() {
# args: modelname, tags_json_string
local model="$1"
local tags="$2"
printf '%s' "$tags" | python -c '
import json,sys
m=sys.argv[1]
obj=json.load(sys.stdin)
names=set()
for it in obj.get("models", []):
n=it.get("name")
if n: names.add(n)
ok = (m in names) or (m + ":latest" in names) or (m.endswith(":latest") and m[:-7] in names)
sys.exit(0 if ok else 1)
' "$model" >/dev/null 2>&1
}
# -------- preflight --------
need_cmd docker
need_cmd curl
need_cmd python
need_cmd grep
need_cmd sed
if [[ ! -f "$ENV_FILE" ]]; then
warn ".env not found, creating from .env.example"
cp -n "${ROOT}/.env.example" "${ROOT}/.env" || true
fi
# shellcheck disable=SC1090
source "${ROOT}/.env"
: "${OLLAMA_URL:=http://127.0.0.1:11434}"
: "${EXPERT_MODEL:=jr-sql-expert}"
: "${BASE_MODEL:=}"
ok "loaded env: OLLAMA_URL=$OLLAMA_URL EXPERT_MODEL=$EXPERT_MODEL BASE_MODEL=${BASE_MODEL:-<empty>}"
if [[ ! -x "${ROOT}/bin/sqlai" ]]; then
fail "bin/sqlai missing or not executable at ${ROOT}/bin/sqlai" 11
fi
# docker compose availability (plugin or legacy)
if docker compose version >/dev/null 2>&1; then
ok "docker compose available"
else
fail "docker compose not available (install docker compose plugin)" 12
fi
# container state
if docker ps --format '{{.Names}}' | grep -qx 'ollama'; then
ok "container 'ollama' is running"
else
warn "container 'ollama' not running; attempting 'docker compose up -d'"
docker compose -f "${ROOT}/docker-compose.yml" up -d || fail "docker compose up failed" 13
if ! docker ps --format '{{.Names}}' | grep -qx 'ollama'; then
fail "container 'ollama' still not running after compose up" 14
fi
ok "container 'ollama' is running after compose up"
fi
# API wait loop
ok "waiting for Ollama API at $OLLAMA_URL ..."
api_ok="0"
for i in {1..120}; do
if curl -sS "${OLLAMA_URL}/api/tags" >/dev/null 2>&1; then
api_ok="1"
break
fi
sleep 1
done
[[ "$api_ok" == "1" ]] || fail "Ollama API not reachable at $OLLAMA_URL after waiting" 20
ok "Ollama API reachable"
# Fetch /api/tags and validate JSON
tags="$(curl -sS "${OLLAMA_URL}/api/tags" || true)"
[[ -n "$tags" ]] || fail "/api/tags returned empty body" 21
if ! printf '%s' "$tags" | is_json; then
echo "[$(ts)] selftest: /api/tags RAW_BEGIN"
printf '%s\n' "$tags" | head -n 200
echo "[$(ts)] selftest: /api/tags RAW_END"
fail "/api/tags did not return JSON" 22
fi
ok "/api/tags returned valid JSON"
# Model availability checks
expert_present="0"
base_present="0"
if model_in_tags "$EXPERT_MODEL" "$tags"; then
expert_present="1"
ok "EXPERT_MODEL present: $EXPERT_MODEL"
else
warn "EXPERT_MODEL not present in tags: $EXPERT_MODEL"
fi
if [[ -n "${BASE_MODEL:-}" ]] && model_in_tags "$BASE_MODEL" "$tags"; then
base_present="1"
ok "BASE_MODEL present: $BASE_MODEL"
else
if [[ -n "${BASE_MODEL:-}" ]]; then
warn "BASE_MODEL not present in tags: $BASE_MODEL"
else
warn "BASE_MODEL empty in .env"
fi
fi
if [[ "$expert_present" != "1" && "$base_present" != "1" ]]; then
warn "No expert/base model found. Attempting to pull BASE_MODEL if set..."
if [[ -n "${BASE_MODEL:-}" ]]; then
docker exec -it ollama ollama pull "${BASE_MODEL}" || warn "ollama pull BASE_MODEL failed"
tags2="$(curl -sS "${OLLAMA_URL}/api/tags" || true)"
if printf '%s' "$tags2" | is_json && model_in_tags "$BASE_MODEL" "$tags2"; then
ok "BASE_MODEL now present after pull: $BASE_MODEL"
base_present="1"
else
fail "Neither EXPERT_MODEL nor BASE_MODEL available after attempted pull" 23
fi
else
fail "Neither EXPERT_MODEL nor BASE_MODEL available and BASE_MODEL is empty" 24
fi
fi
# Warmup request
ok "warmup request via sqlai (no-metrics)"
set +e
"${ROOT}/bin/sqlai" ask --text "Warmup: reply with exactly 'OK'." --no-metrics
rc=$?
set -e
if [[ "$rc" -ne 0 ]]; then
warn "warmup failed rc=$rc (continuing to real query)"
else
ok "warmup succeeded"
fi
# Real query (slightly longer)
ok "real query via sqlai (ask)"
set +e
out="$("${ROOT}/bin/sqlai" ask --text "Give a concise checklist to troubleshoot parameter sniffing in SQL Server 2022. Keep it technical." --no-metrics 2>&1)"
rc=$?
set -e
if [[ "$rc" -ne 0 ]]; then
echo "[$(ts)] selftest: sqlai output BEGIN"
printf '%s\n' "$out" | tail -n 200
echo "[$(ts)] selftest: sqlai output END"
fail "real query failed rc=$rc" 30
fi
# Basic sanity: must contain at least some non-empty text
if [[ -z "${out//[[:space:]]/}" ]]; then
fail "real query returned empty output" 31
fi
ok "real query returned non-empty output"
# Summary
echo "--------------------------------------------------------------------------------"
echo "[$(ts)] selftest: SUMMARY"
echo "[$(ts)] selftest: API=OK"
echo "[$(ts)] selftest: EXPERT_MODEL_PRESENT=$expert_present"
echo "[$(ts)] selftest: BASE_MODEL_PRESENT=$base_present"
echo "[$(ts)] selftest: LOG_FILE=$log_file"
echo "--------------------------------------------------------------------------------"
echo "[$(ts)] selftest: END status=OK"
echo "================================================================================"
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_OVERRIDE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
export ROOT_OVERRIDE
# shellcheck disable=SC1091
source "${ROOT_OVERRIDE}/scripts/common.sh"
init_log update-native
print_header "update-native: START"
need_cmd curl
need_cmd python
need_cmd ollama
load_env
check_for_legacy_docker_ollama
log "update-native: waiting for Ollama API at ${OLLAMA_URL}"
wait_for_ollama_api "$OLLAMA_URL" 120 || fail "Ollama API not reachable at ${OLLAMA_URL}" 50
ok "update-native: Ollama API reachable"
log "update-native: pulling base model ${BASE_MODEL}"
ollama pull "${BASE_MODEL}"
if [[ -n "${EXTRA_MODELS}" ]]; then
for m in ${EXTRA_MODELS}; do
log "update-native: pulling extra model ${m}"
ollama pull "$m"
done
fi
tmp="$(mktemp)"
trap 'rm -f "$tmp"' EXIT
render_modelfile "$tmp"
log "update-native: rebuilding expert model ${EXPERT_MODEL}"
ollama create "${EXPERT_MODEL}" -f "$tmp"
tags="$(fetch_tags)"
printf '%s' "$tags" | is_json || fail "/api/tags did not return valid JSON" 51
model_in_tags "$BASE_MODEL" "$tags" || fail "base model missing after update: ${BASE_MODEL}" 52
model_in_tags "$EXPERT_MODEL" "$tags" || fail "expert model missing after update: ${EXPERT_MODEL}" 53
ok "update-native: base and expert models are available"
warmup_sqlai
print_footer "update-native: END status=OK log=${LOG_FILE}"
-70
View File
@@ -1,70 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ROOT}/.env"
ts(){ date -Is; }
log_dir="${ROOT}/logs"
mkdir -p "$log_dir"
log_file="${log_dir}/update-$(date -Iseconds).log"
exec > >(tee -a "$log_file") 2>&1
echo "[$(ts)] update: starting (ROOT=$ROOT)"
echo "[$(ts)] update: pulling docker image(s)"
docker compose -f "${ROOT}/docker-compose.yml" pull
echo "[$(ts)] update: restarting services"
docker compose -f "${ROOT}/docker-compose.yml" up -d
echo "[$(ts)] update: waiting for Ollama API at ${OLLAMA_URL} ..."
for i in {1..120}; do
if curl -sS "${OLLAMA_URL}/api/tags" >/dev/null 2>&1; then
echo "[$(ts)] update: Ollama API is up."
break
fi
if [[ $i -eq 120 ]]; then
echo "[$(ts)] update: ERROR: API did not come up in time."
exit 1
fi
sleep 1
done
echo "[$(ts)] update: pulling base model: ${BASE_MODEL}"
docker exec -it ollama ollama pull "${BASE_MODEL}"
if [[ -n "${EXTRA_MODELS:-}" ]]; then
for m in ${EXTRA_MODELS}; do
echo "[$(ts)] update: pulling extra model: $m"
docker exec -it ollama ollama pull "$m"
done
fi
echo "[$(ts)] update: rebuilding expert model: ${EXPERT_MODEL}"
tmp="$(mktemp)"
sed "s/\${BASE_MODEL}/${BASE_MODEL}/g" "${ROOT}/Modelfile" > "$tmp"
docker cp "$tmp" ollama:/tmp/Modelfile.jr-sql-expert
docker exec -it ollama ollama create "${EXPERT_MODEL}" -f /tmp/Modelfile.jr-sql-expert
rm -f "$tmp"
echo "[$(ts)] update: verifying model exists..."
docker exec -it ollama ollama list | grep -F "${EXPERT_MODEL}" >/dev/null && \
echo "[$(ts)] update: OK: ${EXPERT_MODEL} is available."
# Warmup (loads model + GPU kernels, reduces first real query latency)
if [[ -x "${ROOT}/bin/sqlai" ]]; then
echo "[$(ts)] update: warmup: sending a short request (no-metrics)..."
"${ROOT}/bin/sqlai" ask --text "Warmup: reply with exactly 'OK'." --no-metrics || {
echo "[$(ts)] update: WARN: warmup failed (continuing)."
}
echo "[$(ts)] update: warmup: done"
else
echo "[$(ts)] update: WARN: ${ROOT}/bin/sqlai not executable; skipping warmup."
fi
echo "[$(ts)] update: complete"