Initial commit: local SQL expert AI (Ollama + CLI + prompts + systemd timer)
This commit is contained in:
11
.env.example
Normal file
11
.env.example
Normal file
@@ -0,0 +1,11 @@
|
||||
# Base model to pull and use for the expert model
|
||||
BASE_MODEL=qwen2.5-coder:14b
|
||||
|
||||
# Optional: space-separated list of extra models to pull
|
||||
EXTRA_MODELS=sqlcoder
|
||||
|
||||
# Name of your custom expert model (built from Modelfile)
|
||||
EXPERT_MODEL=jr-sql-expert
|
||||
|
||||
# Ollama API endpoint (host network)
|
||||
OLLAMA_URL=http://127.0.0.1:11434
|
||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
logs/*.log
|
||||
.env
|
||||
.DS_Store
|
||||
*.swp
|
||||
31
Modelfile
Normal file
31
Modelfile
Normal file
@@ -0,0 +1,31 @@
|
||||
# NOTE: scripts will replace ${BASE_MODEL} with your .env BASE_MODEL.
|
||||
FROM ${BASE_MODEL}
|
||||
|
||||
SYSTEM """
|
||||
Du bist ein sehr erfahrener Microsoft SQL Server 2022 Engineer (T-SQL, Query Optimizer, Indexing, Execution Plans, Stored Procedures, Views, Schema-Design, Collations/UTF-8).
|
||||
Du arbeitest offline und machst KEINE Annahmen über reale Daten. Keine Verbindungen, keine Ausführung – nur Analyse.
|
||||
|
||||
Allgemeine Regeln:
|
||||
- Antworte präzise, technisch, ohne Marketing.
|
||||
- Wenn Informationen fehlen: liste exakt auf, was fehlt, und gib trotzdem best-effort Analyse.
|
||||
- Wenn du Snippets vorschlägst: immer konkret (T-SQL/DDL) und kommentiert.
|
||||
- Wenn du mehrere Optionen gibst: nenne Vor-/Nachteile und wann welche Option sinnvoll ist.
|
||||
|
||||
Für Query Plans:
|
||||
- Erkläre Hotspots (Top Operatoren), Kardinalitätsschätzungen, Warnungen, Spills, SARGability,
|
||||
fehlende Indizes (vorsichtig!), Join-Strategien, Parameter Sniffing, Stats, Memory Grants.
|
||||
|
||||
Für UTF-8 Migration:
|
||||
- Erkläre Vorgehen über UTF-8-enabled Collations (_UTF8).
|
||||
- Risiken: Vergleiche/Sortierung, Indexgrößen, Abhängigkeiten (FK/Index/Computed/Triggers),
|
||||
Teststrategie, Cutover, Rollback.
|
||||
|
||||
Antwort-Struktur (immer):
|
||||
1) Kurzfazit (3–6 Bulletpoints)
|
||||
2) Detailanalyse (mit konkreten Snippets)
|
||||
3) Risiken & Checks (Checkliste)
|
||||
4) Nächste Schritte
|
||||
"""
|
||||
|
||||
PARAMETER temperature 0.1
|
||||
PARAMETER top_p 0.9
|
||||
84
README.md
Normal file
84
README.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# jr-sql-ai (Terminal-first SQL Server Expert KI, lokal)
|
||||
|
||||
Ziel: Lokale Expert-KI für **SQL Server 2022** (T-SQL, Views, Stored Procedures, Execution Plans, UTF-8 Migration),
|
||||
aufrufbar **vom Terminal**, ohne direkte DB-Verbindung (nur Copy & Paste / Dateien).
|
||||
|
||||
## Features
|
||||
- **Einfacher Tech-Stack:** Docker + Ollama + Bash + curl + python
|
||||
- **Host Networking:** nutzt den Host-Netzwerkstack (Routing/DNS wie Host; ideal wenn nur `br0` zuverlässig ist)
|
||||
- **Auto-Updates:** Runtime + Models via `systemd --user` Timer
|
||||
- **Viele Logs:** jede Ausführung schreibt detaillierte Logs unter `./logs/`
|
||||
|
||||
## Voraussetzungen (Arch Linux)
|
||||
- docker + docker compose
|
||||
- curl
|
||||
- python (für JSON-Quoting/Parsing)
|
||||
|
||||
## Quickstart
|
||||
```bash
|
||||
cp .env.example .env
|
||||
./scripts/bootstrap.sh
|
||||
echo "SELECT 1;" | ./bin/sqlai analyze-tsql
|
||||
```
|
||||
|
||||
## Verwendung (Copy & Paste)
|
||||
### T-SQL
|
||||
```bash
|
||||
cat query.sql | ./bin/sqlai analyze-tsql
|
||||
```
|
||||
|
||||
### Stored Procedure
|
||||
```bash
|
||||
cat dbo.usp_Something.sql | ./bin/sqlai analyze-proc
|
||||
```
|
||||
|
||||
### View
|
||||
```bash
|
||||
cat dbo.vw_Something.sql | ./bin/sqlai analyze-view
|
||||
```
|
||||
|
||||
### Execution Plan
|
||||
- Unterstützt Showplan XML oder Text.
|
||||
```bash
|
||||
./bin/sqlai analyze-plan --file showplan.xml
|
||||
```
|
||||
|
||||
### UTF-8 Migration Plan
|
||||
```bash
|
||||
cat schema_snippet.sql | ./bin/sqlai utf8-migration
|
||||
```
|
||||
|
||||
## Prompt Library (Templates)
|
||||
Unter `./prompts/` findest du Copy&Paste-Templates:
|
||||
- `prompts/tsql_review.md`
|
||||
- `prompts/plan_review.md`
|
||||
- `prompts/utf8_migration_runbook.md`
|
||||
- `prompts/indexing_checklist.md`
|
||||
- `prompts/sniffing_stats_playbook.md`
|
||||
- `prompts/proc_refactor_template.md`
|
||||
- `prompts/view_analysis_template.md`
|
||||
|
||||
## Logs
|
||||
- CLI Logs: `./logs/sqlai-YYYY-MM-DD.log`
|
||||
- Bootstrap Logs: `./logs/bootstrap-YYYY-MM-DDTHH:MM:SS.log`
|
||||
- Update Logs: `./logs/update-YYYY-MM-DDTHH:MM:SS.log`
|
||||
|
||||
Die Logs enthalten:
|
||||
- Input-Bytes, Mode, Model
|
||||
- Roh-Metriken aus Ollama (Token Counts, Durations)
|
||||
- Fehler inkl. curl exit codes
|
||||
|
||||
## Auto-Updates aktivieren (systemd --user)
|
||||
```bash
|
||||
mkdir -p ~/.config/systemd/user
|
||||
cp systemd/user/* ~/.config/systemd/user/
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable --now jr-sql-ai-update.timer
|
||||
systemctl --user list-timers | grep jr-sql-ai
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
- **API nicht erreichbar**: Prüfe `docker ps` und ob Port 11434 lokal erreichbar ist (Host-Netz).
|
||||
- **Langsam/OOM**: setze `BASE_MODEL` kleiner (z.B. 7b) und re-run `./scripts/update.sh`.
|
||||
- **Model fehlt**: `./scripts/update.sh` ausführen und prüfen ob `ollama list` im Container das Model zeigt:
|
||||
`docker exec -it ollama ollama list`
|
||||
130
bin/sqlai
Executable file
130
bin/sqlai
Executable file
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
ENV_FILE="${ROOT}/.env"
|
||||
[[ -f "$ENV_FILE" ]] && source "$ENV_FILE"
|
||||
|
||||
: "${OLLAMA_URL:=http://127.0.0.1:11434}"
|
||||
: "${EXPERT_MODEL:=jr-sql-expert}"
|
||||
|
||||
ts() { date -Is; }
|
||||
|
||||
log_dir="${ROOT}/logs"
|
||||
mkdir -p "$log_dir"
|
||||
log_file="${log_dir}/sqlai-$(date -I).log"
|
||||
|
||||
# log everything (stdout+stderr)
|
||||
exec > >(tee -a "$log_file") 2>&1
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage:
|
||||
sqlai <mode> [--file path]
|
||||
Modes:
|
||||
analyze-tsql
|
||||
analyze-proc
|
||||
analyze-view
|
||||
analyze-plan
|
||||
utf8-migration
|
||||
|
||||
Examples:
|
||||
cat query.sql | sqlai analyze-tsql
|
||||
sqlai analyze-plan --file showplan.xml
|
||||
EOF
|
||||
}
|
||||
|
||||
mode="${1:-}"
|
||||
[[ -z "$mode" ]] && { usage; exit 1; }
|
||||
shift || true
|
||||
|
||||
file=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--file) file="$2"; shift 2;;
|
||||
*) echo "[$(ts)] ERROR: Unknown arg: $1"; usage; exit 2;;
|
||||
esac
|
||||
done
|
||||
|
||||
input=""
|
||||
if [[ -n "$file" ]]; then
|
||||
if [[ ! -f "$file" ]]; then
|
||||
echo "[$(ts)] ERROR: file not found: $file"
|
||||
exit 3
|
||||
fi
|
||||
input="$(cat "$file")"
|
||||
else
|
||||
input="$(cat)"
|
||||
fi
|
||||
|
||||
if [[ -z "${input//[[:space:]]/}" ]]; then
|
||||
echo "[$(ts)] ERROR: empty input"
|
||||
exit 4
|
||||
fi
|
||||
|
||||
case "$mode" in
|
||||
analyze-tsql)
|
||||
instruction="Analysiere das folgende T-SQL (SQL Server 2022). Finde Performance-Probleme, SARGability, Indizes, Statistiken, Parameter Sniffing Risiken und gib konkrete Verbesserungen."
|
||||
;;
|
||||
analyze-proc)
|
||||
instruction="Analysiere die folgende Stored Procedure (SQL Server 2022). Finde Performance-/Correctness-Risiken, Transaktions-/Locking-Themen, Parameter Sniffing, fehlende Indizes. Gib konkrete Refactorings."
|
||||
;;
|
||||
analyze-view)
|
||||
instruction="Analysiere die folgende View (SQL Server 2022). Prüfe SARGability, Expand/Inlining-Effekte, mögliche Indexing-Optionen (z.B. indexed view falls sinnvoll) und Plan-Auswirkungen."
|
||||
;;
|
||||
analyze-plan)
|
||||
instruction="Analysiere den folgenden SQL Server Execution Plan (XML Showplan oder Text). Identifiziere teure Operatoren, Spills, Warnungen, Kardinalitätsfehler, fehlende Indizes und gib konkrete Fixes."
|
||||
;;
|
||||
utf8-migration)
|
||||
instruction="Erstelle einen Migrationsplan, um Tabellen/Spalten auf UTF-8 umzustellen (UTF-8 enabled collations mit _UTF8). Berücksichtige Abhängigkeiten (FK/PK/Indexes/Computed/Triggers), Risiken und gib eine Schritt-für-Schritt Checkliste."
|
||||
;;
|
||||
*)
|
||||
echo "[$(ts)] ERROR: unknown mode: $mode"
|
||||
usage
|
||||
exit 5
|
||||
;;
|
||||
esac
|
||||
|
||||
prompt=$(cat <<EOF
|
||||
${instruction}
|
||||
|
||||
---BEGIN INPUT---
|
||||
${input}
|
||||
---END INPUT---
|
||||
EOF
|
||||
)
|
||||
|
||||
echo "[$(ts)] sqlai: MODE=$mode MODEL=$EXPERT_MODEL OLLAMA_URL=$OLLAMA_URL"
|
||||
echo "[$(ts)] sqlai: INPUT_BYTES=$(printf "%s" "$input" | wc -c)"
|
||||
|
||||
payload="$(python - <<'PY'
|
||||
import json, os, sys
|
||||
model=os.environ.get("EXPERT_MODEL","jr-sql-expert")
|
||||
prompt=sys.stdin.read()
|
||||
print(json.dumps({"model": model, "prompt": prompt, "stream": False}, ensure_ascii=False))
|
||||
PY
|
||||
<<<"$prompt")"
|
||||
|
||||
echo "[$(ts)] sqlai: sending request..."
|
||||
resp="$(curl -sS -X POST "${OLLAMA_URL}/api/generate" -H 'Content-Type: application/json' --data-binary "$payload")" || {
|
||||
rc=$?
|
||||
echo "[$(ts)] sqlai: ERROR: curl failed rc=$rc"
|
||||
exit 10
|
||||
}
|
||||
|
||||
python - <<'PY'
|
||||
import json,sys
|
||||
obj=json.loads(sys.stdin.read())
|
||||
print("\n" + (obj.get("response","").rstrip()) + "\n")
|
||||
md = {
|
||||
"total_duration": obj.get("total_duration"),
|
||||
"load_duration": obj.get("load_duration"),
|
||||
"prompt_eval_count": obj.get("prompt_eval_count"),
|
||||
"prompt_eval_duration": obj.get("prompt_eval_duration"),
|
||||
"eval_count": obj.get("eval_count"),
|
||||
"eval_duration": obj.get("eval_duration"),
|
||||
}
|
||||
print("METRICS=" + json.dumps(md, ensure_ascii=False))
|
||||
PY <<<"$resp"
|
||||
|
||||
echo "[$(ts)] sqlai: done"
|
||||
18
docker-compose.yml
Normal file
18
docker-compose.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
services:
|
||||
ollama:
|
||||
image: ollama/ollama:latest
|
||||
container_name: ollama
|
||||
restart: unless-stopped
|
||||
|
||||
# Uses the host network stack (routing/DNS identical to the host, incl. br0)
|
||||
network_mode: "host"
|
||||
|
||||
volumes:
|
||||
- ollama:/root/.ollama
|
||||
|
||||
environment:
|
||||
# Keep model in memory a bit (optional)
|
||||
OLLAMA_KEEP_ALIVE: "10m"
|
||||
|
||||
volumes:
|
||||
ollama:
|
||||
0
logs/.gitkeep
Normal file
0
logs/.gitkeep
Normal file
25
prompts/indexing_checklist.md
Normal file
25
prompts/indexing_checklist.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Indexing Checklist (SQL Server 2022)
|
||||
|
||||
## Vor dem Index
|
||||
- Welche Query/Workload? (Top N Abfragen)
|
||||
- Welche Filter/Join-Spalten?
|
||||
- Sort/Group By/Distinct? (ORDER BY, GROUP BY)
|
||||
- Häufige Lookups? (Key Lookup / RID Lookup)
|
||||
- Schreiblast hoch? (Index-Overhead)
|
||||
|
||||
## Plausible Index-Regeln
|
||||
- Key Columns: erst Equality predicates, dann Range, dann Join keys
|
||||
- Include Columns: nur für benötigte SELECT-Spalten (Covering)
|
||||
- Filtered Index: wenn Predicate stabil/selektiv (z.B. Status='Active')
|
||||
- Datentypen sauber (keine impliziten Konvertierungen)
|
||||
- Stats: nach großen Loads/Änderungen aktualisieren (gezielt)
|
||||
|
||||
## Validierung
|
||||
- Plan vorher/nachher
|
||||
- Reads/CPU/Duration
|
||||
- Index usage (DMVs) nur als Hinweis, nicht alleinige Wahrheit
|
||||
- Regression Tests / Parameter Sets
|
||||
|
||||
---BEGIN INPUT---
|
||||
<PASTE HERE>
|
||||
---END INPUT---
|
||||
27
prompts/plan_review.md
Normal file
27
prompts/plan_review.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Execution Plan Review Template (Showplan XML/Text)
|
||||
|
||||
## Kontext (optional)
|
||||
- Query text (falls verfügbar)
|
||||
- Parameterwerte bei Capture
|
||||
- CPU/Duration/Reads/Rowcount bei Capture
|
||||
- Server settings: MAXDOP, Cost Threshold for Parallelism (falls bekannt)
|
||||
|
||||
## Aufgabe
|
||||
1) Kurzfazit
|
||||
2) Hotspots:
|
||||
- Top Operatoren nach Kosten
|
||||
- Spills (Sort/Hash), Warnings
|
||||
- Memory Grant: zu hoch/zu niedrig
|
||||
- Parallelism (CXPACKET/CXCONSUMER Kontext)
|
||||
3) Kardinalität:
|
||||
- wo weicht Estimated vs Actual ab? (wenn Actual vorhanden)
|
||||
- Stats/Histogramm Hinweise
|
||||
4) Fixes:
|
||||
- Query Rewrite
|
||||
- Index/Stats Empfehlungen
|
||||
- Parameter Sniffing Mitigation
|
||||
5) Checkliste für Validierung
|
||||
|
||||
---BEGIN PLAN---
|
||||
<PASTE HERE>
|
||||
---END PLAN---
|
||||
22
prompts/proc_refactor_template.md
Normal file
22
prompts/proc_refactor_template.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Stored Procedure Review / Refactor Template
|
||||
|
||||
## Kontext (optional)
|
||||
- Aufrufmuster (Parameter, typische Werte):
|
||||
- Isolation Level / Transactions:
|
||||
- Deadlocks/Blocking bekannt? (ja/nein + Hinweise)
|
||||
- Ziel: Latenz, Throughput, Stabilität, Plan-Stabilität
|
||||
|
||||
## Aufgabe
|
||||
1) Kurzfazit
|
||||
2) Detailanalyse
|
||||
- Parameter Sniffing
|
||||
- Temp tables vs table variables
|
||||
- Row-by-row (Cursor, WHILE), UDFs, RBAR
|
||||
- TRY/CATCH + Fehlerbehandlung
|
||||
- Transaktionsumfang (zu groß?), Lock Escalation, Timeouts
|
||||
3) Konkrete Refactorings (mit T-SQL)
|
||||
4) Risiken/Checks/Next steps
|
||||
|
||||
---BEGIN PROC---
|
||||
<PASTE HERE>
|
||||
---END PROC---
|
||||
30
prompts/sniffing_stats_playbook.md
Normal file
30
prompts/sniffing_stats_playbook.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Parameter Sniffing & Statistics Playbook
|
||||
|
||||
## Symptome
|
||||
- Laufzeit stark schwankend je nach Parameter
|
||||
- Plan ist "gut" für einen Wert, "schlecht" für andere
|
||||
- Große Estimated vs Actual Abweichungen
|
||||
- Memory grants/spills je nach Parameter
|
||||
|
||||
## Diagnose (ohne DB-Zugriff: theoretisch/plan-basiert)
|
||||
- Welche Prädikate sind parameterabhängig?
|
||||
- Gibt es Skew (ein Wert sehr häufig/selten)?
|
||||
- OR-Logik / optional filters (@p IS NULL OR col=@p)?
|
||||
- Implizite Konvertierungen?
|
||||
|
||||
## Gegenmaßnahmen (geordnet von "leicht" zu "hart")
|
||||
1) Query rewrite (SARGability, Splitting optional filters)
|
||||
2) OPTION(RECOMPILE) selektiv
|
||||
3) OPTIMIZE FOR (oder OPTIMIZE FOR UNKNOWN) bewusst
|
||||
4) Zwei Queries / IF branches für stark unterschiedliche Pfade
|
||||
5) Plan guides / forced plan (nur in Ausnahmefällen)
|
||||
6) Stats: update + ggf. filtered stats (wenn passend)
|
||||
|
||||
## Checkliste
|
||||
- Welche Parameter-Sets testen (min/max/typisch)
|
||||
- Regression: CPU/Reads/Duration
|
||||
- Concurrency/Blocking beachten
|
||||
|
||||
---BEGIN INPUT---
|
||||
<PASTE HERE>
|
||||
---END INPUT---
|
||||
29
prompts/tsql_review.md
Normal file
29
prompts/tsql_review.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# T-SQL Review Template (Copy & Paste)
|
||||
|
||||
> Zweck: schnelle, präzise Analyse einer Abfrage.
|
||||
> Eingabe: T-SQL + (optional) Parameterwerte + (optional) Tabelleninfos.
|
||||
|
||||
## Kontext (optional)
|
||||
- SQL Server Version: 2022
|
||||
- DB Kompatibilitätslevel: ?
|
||||
- Tabellenvolumen grob (Rows): ?
|
||||
- Häufigkeit/Latency Ziel: ?
|
||||
- Parameterwerte (typisch & worst-case): ?
|
||||
|
||||
## Aufgabe
|
||||
Analysiere das T-SQL und liefere:
|
||||
1) **Kurzfazit** (3–6 Bulletpoints)
|
||||
2) **Detailanalyse**:
|
||||
- SARGability (LIKE, Funktionen auf Spalten, CAST/CONVERT, Datentyp-Mismatches)
|
||||
- Joins/Predicates (Reihenfolge, Join Typen)
|
||||
- Kardinalität/Stats (wo schätzt der Optimizer falsch)
|
||||
- Parameter Sniffing Risiko + konkrete Mitigation (z.B. OPTION(RECOMPILE) gezielt, OPTIMIZE FOR, plan guides nur wenn nötig)
|
||||
3) **Konkrete Verbesserungen**:
|
||||
- rewrite (mit kommentiertem SQL)
|
||||
- Index-Vorschläge (nur wenn plausibel; include columns; Filtered Index falls geeignet)
|
||||
4) **Checks**:
|
||||
- welche Messwerte/Plan-Indikatoren prüfen
|
||||
|
||||
---BEGIN T-SQL---
|
||||
<PASTE HERE>
|
||||
---END T-SQL---
|
||||
27
prompts/utf8_migration_runbook.md
Normal file
27
prompts/utf8_migration_runbook.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# UTF-8 Migration Runbook (SQL Server 2022)
|
||||
|
||||
## Ziel
|
||||
Tabellen/Spalten auf UTF-8 umstellen durch Verwendung von UTF-8-enabled Collations (`*_UTF8`).
|
||||
|
||||
## Input (paste)
|
||||
- Aktuelles Schema (CREATE TABLE oder relevante Spalten)
|
||||
- Aktuelle Collations
|
||||
- Abhängigkeiten (FKs, Indexes, Computed Columns, Triggers)
|
||||
- App assumptions (Sortierung, Vergleiche, Case sensitivity)
|
||||
|
||||
---BEGIN INPUT---
|
||||
<PASTE HERE>
|
||||
---END INPUT---
|
||||
|
||||
## Erwartete Ausgabe
|
||||
1) Kurzfazit
|
||||
2) Schritt-für-Schritt Plan (staging -> validate -> cutover -> rollback)
|
||||
3) DDL Snippets:
|
||||
- neue Collation setzen
|
||||
- Rebuild Indizes/Constraints
|
||||
4) Risiken:
|
||||
- Sort-/Compare-Verhalten kann sich ändern
|
||||
- mögliche Indexgrößenänderung
|
||||
- computed columns / persisted computed columns
|
||||
5) Teststrategie:
|
||||
- Vergleichssuites, Known tricky strings, roundtrip tests
|
||||
23
prompts/view_analysis_template.md
Normal file
23
prompts/view_analysis_template.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# View Analysis Template
|
||||
|
||||
## Kontext (optional)
|
||||
- Wird die View häufig gejoint/weitergefiltert?
|
||||
- Erwartete Selectivity / typische Filter?
|
||||
- Indexed view überhaupt erlaubt/gewünscht? (Schema binding etc.)
|
||||
|
||||
## Aufgabe
|
||||
1) Kurzfazit
|
||||
2) Detailanalyse:
|
||||
- Expand/Inlining Effekte
|
||||
- SARGability und Pushdown von Predicates
|
||||
- Aggregationen/Distinct/Union
|
||||
- Risiken bei Scalar UDFs / Non-deterministic Funktionen
|
||||
3) Verbesserungen:
|
||||
- alternative Definition
|
||||
- Hinweise zu Indizes auf Basistabellen
|
||||
- falls relevant: indexed view Voraussetzungen (nur als Option)
|
||||
4) Risiken/Checks
|
||||
|
||||
---BEGIN VIEW---
|
||||
<PASTE HERE>
|
||||
---END VIEW---
|
||||
49
scripts/bootstrap.sh
Executable file
49
scripts/bootstrap.sh
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/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..90}; 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 90 ]]; 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 exec -i ollama ollama create "${EXPERT_MODEL}" -f - < "$tmp"
|
||||
rm -f "$tmp"
|
||||
|
||||
echo "[$(ts)] bootstrap: done"
|
||||
echo "[$(ts)] bootstrap: test:"
|
||||
echo " echo "SELECT 1;" | ${ROOT}/bin/sqlai analyze-tsql"
|
||||
48
scripts/update.sh
Executable file
48
scripts/update.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/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..90}; 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 90 ]]; 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 exec -i ollama ollama create "${EXPERT_MODEL}" -f - < "$tmp"
|
||||
rm -f "$tmp"
|
||||
|
||||
echo "[$(ts)] update: complete"
|
||||
7
systemd/user/jr-sql-ai-update.service
Normal file
7
systemd/user/jr-sql-ai-update.service
Normal file
@@ -0,0 +1,7 @@
|
||||
[Unit]
|
||||
Description=Update Ollama runtime + models (jr-sql-ai)
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
WorkingDirectory=%h/jr-sql-ai
|
||||
ExecStart=%h/jr-sql-ai/scripts/update.sh
|
||||
9
systemd/user/jr-sql-ai-update.timer
Normal file
9
systemd/user/jr-sql-ai-update.timer
Normal file
@@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=Daily update timer for jr-sql-ai
|
||||
|
||||
[Timer]
|
||||
OnCalendar=daily
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
Reference in New Issue
Block a user