gpt-oss ist ein Modell, das vom ChatGPT Betreiber OpenAI selbst trainiert wurde.

gpt-oss
Dieses Modell kommt mit 20b und 120b Parametern und steht unter Apache 2.0 Lizenz.
Es verspricht, eine neue lokale Erfahrung und ist für leistungsstarkes Reasoning, Agentenaufgaben und vielseitige Anwendungsfälle für Entwickler konzipiert.
20b
Das Modell mit 20b Parametern passt mit seinem ca. 13GB Umfang noch in den Speicher des Raspberry Pi 5 16GB, so dass ich den als Testplattform benutze. Nach beinah einer Viertelstunde kommt ein bestenfalls mittelmäßiges Ergebnis zurück.

120b
Das 120b Modell ist fünf mal so groß wie das 20b und kann ich nur auf meinem Desktop PC mit 128GB RAM testen. Nach fast genau 8 Minuten habe ich eine Antwort von sehr guter Qualität.
| Model | Hersteller | Parameter | Speicherverbrauch | Lizenz | Testsystem | Laufzeit | Antwortqualität |
|---|---|---|---|---|---|---|---|
| gpt-oss | OpenAI | 20b | 13GB | Apache 2.0 | Raspberry Pi 5 16GB | 14 Minuten 54,629214351s | mittelmäßig |
| gpt-oss | OpenAI | 120b | 65 GB | Apache 2.0 | Intel i9-10900K (20) @ 5.300GHz | 8 Minuten 0,491043453s | sehr gut |
| tinyllama | OpenSource | 1,1b | 637MB | Apache | Raspberry Pi 5B 8GB | 24.387617981s | Unsinnige Antwort. |
| phi | Microsoft | 2,8b | 1,6GB | MIT | Raspberry Pi 5B 8GB | 2 Minuten 39.691083496s | teilweise brauchbar |
| llava | Microsoft | 7,2b | 4,7GB | Apache | Raspberry Pi 5B 8GB | 1 Minute 25.629187111s | zufriedenstellend |
| llama3 | Meta | 8,0b | 4,7GB | META LLAMA 3 COMMUNITY LICENSE AGREEMENT | Raspberry Pi 5B 8GB | 3 Minuten 4.925977295s | gut |
| deepseek-v3 | Deepseek | 681,0b | 404GB | DEEPSEEK LICENSE AGREEMENT | Raspberry Pi 5B 8GB | – | – |
| deepseek-r1 | Deepseek | 7,6b | 4,7GB | MIT | Raspberry Pi 5B 8GB | 8 Minuten 23.00118112s | völlig unbrauchbar |
| gemma3 | 4,3b | 3,3GB | Gemma Terms of Use | Raspberry Pi 5B 8GB | 1 Minute 14.086309352s | unbrauchbar | |
| gemma3 | 12b | 8,1GB | Gemma Terms Of Use | Intel i9-10900K (20) @ 5.300GHz | 3 Minuten 34.5325445s | sehr gut | |
| gemma3 | 27b | 17GB | Gemma Terms of Use | Intel i9-10900K (20) @ 5.300GHz | 4 Minuten 41.199445574s | sehr gut | |
| phi4 | Microsoft | 14b | 9,1GB | MIT | Raspberry Pi 5B 16GB | 3 Minuten 17.342953352s | teilweise brauchbar |
| phi4:14b-Q8_0 | Microsoft | 14b | 17GB | MIT | Intel i9-10900K (20) @ 5.300GHz | 5 Minuten 42.156362295s | unbrauchbar |
| phi4:14b-fp16 | Microsoft | 14b | 29GB | MIT | Intel i9-10900K (20) @ 5.300GHz | 7 Minuten 34.78815032s | unsinnig |
| phi4:14b-q4_K_M | Micro | 14b | 9,1GB | MIT | Raspberry Pi 5B 16GB | 4 Minuten 44.654069613s | Thema verfehlt |
Zusatzaufgabe
Um die Programmierfähigkeit des 120b Modells zu testen, habe ich es gebeten, mir ein bash Script zu schreiben, dass alle im aktuellen Verzeichnis vorhandenen .bz2 Dateien mit pbzip2 entpackt und mit zstd neu komprimiert.
Nach 34 Minuten erhielt ich dieses Script
#!/usr/bin/env bash
#====================================================================
# bz2-to-zst.sh
#
# Convert every *.bz2 file in the current directory to *.zst
# using parallel pbzip2 for decompression and zstd for recompression.
#
# Usage:
# ./bz2-to-zst.sh [-d] [-l LEVEL] [-t THREADS] [FILE...]
#
# Options:
# -d Delete the original .bz2 file after a successful
# conversion (default: keep the original).
# -l LEVEL zstd compression level (0‑22). Default is 3.
# -t THREADS Number of threads for both pbzip2 and zstd.
# If omitted, both utilities use their own defaults.
# FILE... Specific .bz2 files to process (otherwise all *.bz2).
#
# Requirements:
# * pbzip2 (parallel bzip2 implementation)
# * zstd (Zstandard compressor)
#
# Author: ChatGPT (2025‑08‑10)
#====================================================================
set -euo pipefail # abort on errors, unset vars, and failed pipes
# ---------- default configuration ----------
delete_original=false
zstd_level=3
zstd_threads=
pbzip2_threads=
declare -a targets # will hold the list of files to process
# ---------- helper functions ----------
usage() {
cat <<EOF
Usage: $(basename "$0") [-d] [-l LEVEL] [-t THREADS] [FILE...]
-d Delete the original .bz2 after successful conversion.
-l LEVEL zstd compression level (0‑22). Default: $zstd_level
-t THREADS Number of threads for both pbzip2 and zstd (if omitted each
tool picks its own default).
FILE... One or more specific *.bz2 files to convert.
If omitted, all *.bz2 files in the current directory are used.
Examples:
$(basename "$0") # convert every *.bz2, keep originals
$(basename "$0") -d # convert and delete *.bz2 afterwards
$(basename "$0") -l 19 file1.bz2 file2.bz2
$(basename "$0") -t 8 # use 8 threads for both tools
EOF
exit 1
}
check_program() {
local prog=$1
if ! command -v "$prog" >/dev/null 2>&1; then
echo "Error: '$prog' not found in PATH." >&2
exit 1
fi
}
# ---------- parse arguments ----------
while (( $# )); do
case "$1" in
-d|--delete) delete_original=true; shift ;;
-l|--level) [[ -n ${2-} ]] || { echo "Missing argument for $1"; usage; }
zstd_level=$2; shift 2 ;;
-t|--threads) [[ -n ${2-} ]] || { echo "Missing argument for $1"; usage; }
zstd_threads=$2; pbzip2_threads=$2; shift 2 ;;
-h|--help) usage ;;
-*)
echo "Unknown option: $1"; usage ;;
*) targets+=("$1"); shift ;;
esac
done
# If no explicit file list was given, use a glob expansion.
if [[ ${#targets[@]} -eq 0 ]]; then
shopt -s nullglob # makes *.bz2 expand to an empty list instead of the pattern itself
for f in *.bz2; do
[[ -f $f ]] && targets+=("$f")
done
shopt -u nullglob
fi
# Bail out early if nothing to do.
if [[ ${#targets[@]} -eq 0 ]]; then
echo "No *.bz2 files found in the current directory."
exit 0
fi
# ---------- sanity checks ----------
check_program pbzip2
check_program zstd
# Verify that the chosen compression level is numeric and within zstd's range.
if ! [[ $zstd_level =~ ^[0-9]+$ ]] || (( zstd_level < 0 || zstd_level > 22 )); then
echo "Error: ZSTD level must be an integer between 0 and 22 (got '$zstd_level')." >&2
exit 1
fi
# ---------- conversion loop ----------
for src in "${targets[@]}"; do
# Guard against non‑existent files (maybe they were removed meanwhile)
if [[ ! -f $src ]]; then
echo "Skipping missing file: $src"
continue
fi
# Derive destination name: strip .bz2 (or .tbz2, .tbz) and add .zst
dst="${src%.*}.zst"
# If a .zst already exists, skip to avoid overwriting.
if [[ -e $dst ]]; then
echo "Target already exists, skipping: $dst"
continue
fi
echo "Converting: $src → $dst"
# Build command lines (add thread flags only if user supplied them)
pbzip2_cmd=(pbzip2 -dc) # -d = decompress, -c = write to stdout
[[ -n $pbzip2_threads ]] && pbzip2_cmd+=( -p "$pbzip2_threads" )
zstd_cmd=(zstd -q -$zstd_level -o "$dst" -) # - = read from stdin
[[ -n $zstd_threads ]] && zstd_cmd+=( -T "$zstd_threads" )
# Run the pipeline. Using `pipefail` + `set -e` means any failure aborts.
"${pbzip2_cmd[@]}" "$src" | "${zstd_cmd[@]}"
# If we reach this point the conversion succeeded.
if $delete_original; then
rm -f -- "$src"
echo "Deleted original: $src"
fi
done
echo "All done."
Das ist etwas umfangreicher als ich ursprünglich angefordert hatte. Aber der Aufruf ./bz2-to-zstd.sh *.bz2 tut, was er soll.

Wenn ich allerdings über die Kommandozeilen Parameter den Kompressionslevel auf 5 setzen und zstd alle Kerne des Rechners benutzen lassen will, kommt es zu einem Fehler im Skript. ./bz2-to-zstd.sh -l 5 -t 0 *.bz2

Es hat mich dann eine Weile Sucharbeit gekostet, um die insgesamt 3 Fehler zu finden
- Beim Parsen von –threads müssen separate Variabel für den pzib2 und den zstd Aufruf gesetzt werden.
- Beim Aufruf von zstd war ein überflüssiges Leerzeichen zwischen dem -t Parameter und dem Wert.
- Das Sript versuchte mehrere Dateien gleichzeitig zu konvertieren, was pbzip2 nicht zu lässt.
Hier also nochmal eine lauffähige Version des Scripts.
#!/usr/bin/env bash
#====================================================================
# bz2-to-zst.sh
#
# Convert every *.bz2 file in the current directory to *.zst
# using parallel pbzip2 for decompression and zstd for recompression.
#
# Usage:
# ./bz2-to-zst.sh [-d] [-l LEVEL] [-t THREADS] [FILE...]
#
# Options:
# -d Delete the original .bz2 file after a successful
# conversion (default: keep the original).
# -l LEVEL zstd compression level (0-22). Default is 3.
# -t THREADS Number of threads for both pbzip2 and zstd.
# If 0 is given: pbzip2 uses default autodetect (all cores),
# zstd uses -T0 (all cores).
# FILE... Specific .bz2 files to process (otherwise all *.bz2).
#
#====================================================================
set -euo pipefail # abort on errors, unset vars, and failed pipes
# ---------- default configuration ----------
delete_original=false
zstd_level=3
zstd_threads=
pbzip2_threads=
declare -a targets # will hold the list of files to process
# ---------- helper functions ----------
usage() {
cat <<EOF
Usage: $(basename "$0") [-d] [-l LEVEL] [-t THREADS] [FILE...]
-d Delete the original .bz2 after successful conversion.
-l LEVEL zstd compression level (0-22). Default: $zstd_level
-t THREADS Number of threads for both pbzip2 and zstd (if omitted each
tool picks its own default; 0 means "all cores").
FILE... One or more specific *.bz2 files to convert.
If omitted, all *.bz2 files in the current directory are used.
EOF
exit 1
}
check_program() {
local prog=$1
if ! command -v "$prog" >/dev/null 2>&1; then
echo "Error: '$prog' not found in PATH." >&2
exit 1
fi
}
# ---------- parse arguments ----------
while (( $# )); do
case "$1" in
-d|--delete) delete_original=true; shift ;;
-l|--level)
[[ -n ${2-} ]] || { echo "Missing argument for $1"; usage; }
zstd_level=$2; shift 2 ;;
-t|--threads)
[[ -n ${2-} ]] || { echo "Missing argument for $1"; usage; }
if [[ $2 -eq 0 ]]; then
zstd_threads=0 # zstd: alle Kerne
pbzip2_threads= # pbzip2: kein -p -> Autodetect
else
zstd_threads=$2
pbzip2_threads=$2
fi
shift 2 ;;
-h|--help) usage ;;
-*)
echo "Unknown option: $1"; usage ;;
*) targets+=("$1"); shift ;;
esac
done
# If no explicit file list was given, use a glob expansion.
if [[ ${#targets[@]} -eq 0 ]]; then
shopt -s nullglob
for f in *.bz2; do
[[ -f $f ]] && targets+=("$f")
done
shopt -u nullglob
fi
if [[ ${#targets[@]} -eq 0 ]]; then
echo "No *.bz2 files found in the current directory."
exit 0
fi
# ---------- sanity checks ----------
check_program pbzip2
check_program zstd
if ! [[ $zstd_level =~ ^[0-9]+$ ]] || (( zstd_level < 0 || zstd_level > 22 )); then
echo "Error: ZSTD level must be an integer between 0 and 22 (got '$zstd_level')." >&2
exit 1
fi
# ---------- conversion loop ----------
for src in "${targets[@]}"; do
if [[ ! -f $src ]]; then
echo "Skipping missing file: $src"
continue
fi
dst="${src%.*}.zst"
if [[ -e $dst ]]; then
echo "Target already exists, skipping: $dst"
continue
fi
echo "Converting: $src → $dst"
# Build command lines fresh in each loop
pbzip2_cmd=(pbzip2 -dc)
[[ -n $pbzip2_threads ]] && pbzip2_cmd+=(-p "$pbzip2_threads")
zstd_cmd=(zstd -q -$zstd_level -o "$dst" -)
[[ -n $zstd_threads ]] && zstd_cmd+=(-T"$zstd_threads")
# Debug
echo "DEBUG: pbzip2_cmd=${pbzip2_cmd[@]} src=$src zstd_cmd=${zstd_cmd[@]}"
# Run pipeline
"${pbzip2_cmd[@]}" "$src" | "${zstd_cmd[@]}"
if $delete_original; then
rm -f -- "$src"
echo "Deleted original: $src"
fi
done
echo "All done."

Diese Probleme hätte das Script nicht gehabt, hätte gpt-oss sich daran gehalten, nur die Konvertierungsschleife zu schreiben und den Parameterteil weggelassen.
Fazit
Der Vorreiter für LLM im Internet macht auf dem Raspberry Pi eher eine jämmerliche Figur.