2026-01-01 02:25:25 -05:00
|
|
|
{ pkgs, ... }: {
|
|
|
|
|
systemd.services.init-ollama-model = {
|
|
|
|
|
description = "Initialize LLM models with extra context in Ollama Docker";
|
2026-05-10 16:56:09 -04:00
|
|
|
|
|
|
|
|
# On s'assure que Docker tourne avant de lancer ce script
|
|
|
|
|
after = [ "docker.service" ];
|
2026-01-01 02:25:25 -05:00
|
|
|
wantedBy = [ "multi-user.target" ];
|
2026-05-10 16:56:09 -04:00
|
|
|
|
2026-01-01 02:25:25 -05:00
|
|
|
script = ''
|
2026-05-10 16:56:09 -04:00
|
|
|
# Fonction de création asynchrone pour ne pas bloquer le démarrage
|
|
|
|
|
(
|
|
|
|
|
echo "Starting asynchronous Ollama initialization..."
|
|
|
|
|
|
|
|
|
|
# Attente d'Ollama (maximum 120 secondes pour éviter une boucle infinie)
|
|
|
|
|
TIMEOUT=60
|
|
|
|
|
COUNT=0
|
|
|
|
|
while ! ${pkgs.curl}/bin/curl -s -f http://127.0.0.1:11434/api/tags > /dev/null; do
|
|
|
|
|
if [ $COUNT -ge $TIMEOUT ]; then
|
|
|
|
|
echo "Ollama did not become ready in time. Exiting."
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
echo "Waiting for Ollama API to be reachable..."
|
|
|
|
|
sleep 5
|
|
|
|
|
COUNT=$((COUNT + 5))
|
|
|
|
|
done
|
2026-01-01 01:36:58 -05:00
|
|
|
|
2026-05-10 16:56:09 -04:00
|
|
|
create_model_if_missing() {
|
|
|
|
|
local model_name=$1
|
|
|
|
|
local base_model=$2
|
2026-04-30 21:54:47 -04:00
|
|
|
|
2026-05-10 16:56:09 -04:00
|
|
|
# Vérification robuste via l'API HTTP d'Ollama plutôt que docker exec (évite les conflits de tty)
|
|
|
|
|
if ! ${pkgs.curl}/bin/curl -s http://127.0.0.1:11434/api/tags | ${pkgs.jq}/bin/jq -e ".models[] | select(.name == \"$model_name\")" > /dev/null; then
|
|
|
|
|
echo "$model_name not found, creating from $base_model..."
|
|
|
|
|
|
|
|
|
|
# Utilisation d'un fichier temporaire sur l'hôte pour l'injecter proprement dans Docker
|
|
|
|
|
TMP_FILE=$(mktemp)
|
|
|
|
|
cat <<EOF > "$TMP_FILE"
|
2026-01-01 02:25:25 -05:00
|
|
|
FROM $base_model
|
2026-05-10 16:56:09 -04:00
|
|
|
TEMPLATE """{{- if .System }}
|
2026-04-30 21:54:47 -04:00
|
|
|
[SYSTEM_PROMPT]
|
|
|
|
|
{{ .System }}
|
|
|
|
|
[/SYSTEM_PROMPT]
|
|
|
|
|
{{- end }}
|
|
|
|
|
{{- range .Messages }}
|
2026-05-10 16:56:09 -04:00
|
|
|
{{- if eq .Role "user" }}
|
2026-04-30 21:54:47 -04:00
|
|
|
[INST]
|
|
|
|
|
{{ .Content }}
|
|
|
|
|
[/INST]
|
2026-05-10 16:56:09 -04:00
|
|
|
{{- else if eq .Role "assistant" }}
|
2026-04-30 21:54:47 -04:00
|
|
|
{{ .Content }}
|
|
|
|
|
{{- end }}
|
2026-05-10 16:56:09 -04:00
|
|
|
{{- end }}"""
|
2026-01-01 02:25:25 -05:00
|
|
|
PARAMETER num_ctx 131072
|
|
|
|
|
PARAMETER num_predict 4096
|
|
|
|
|
PARAMETER num_keep 1024
|
|
|
|
|
PARAMETER repeat_penalty 1.1
|
|
|
|
|
PARAMETER top_k 40
|
2026-05-10 16:56:09 -04:00
|
|
|
PARAMETER stop "[INST]"
|
|
|
|
|
PARAMETER stop "[/INST]"
|
|
|
|
|
PARAMETER stop "</s>"
|
|
|
|
|
EOF
|
2026-01-01 01:36:58 -05:00
|
|
|
|
2026-05-10 16:56:09 -04:00
|
|
|
# Copie et création dans le conteneur
|
|
|
|
|
${pkgs.docker}/bin/docker cp "$TMP_FILE" ollama:/tmp/model.modelfile
|
|
|
|
|
${pkgs.docker}/bin/docker exec ollama ollama create "$model_name" -f /tmp/model.modelfile
|
|
|
|
|
${pkgs.docker}/bin/docker exec ollama rm /tmp/model.modelfile
|
|
|
|
|
rm -f "$TMP_FILE"
|
|
|
|
|
else
|
|
|
|
|
echo "$model_name already exists, skipping."
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Create Nemotron
|
|
|
|
|
create_model_if_missing "nemotron-3-nano:30b-128k" "nemotron-3-nano:30b"
|
|
|
|
|
|
|
|
|
|
# Create Devstral
|
|
|
|
|
create_model_if_missing "devstral-small-2:24b-128k" "devstral-small-2:24b"
|
|
|
|
|
|
|
|
|
|
) &
|
2026-01-01 02:25:25 -05:00
|
|
|
'';
|
2026-05-10 16:56:09 -04:00
|
|
|
|
2026-01-01 02:25:25 -05:00
|
|
|
serviceConfig = {
|
2026-05-10 16:56:09 -04:00
|
|
|
Type = "forking"; # Permet à systemd de savoir que le script passe en arrière-plan via '&'
|
|
|
|
|
User = "root";
|
2026-01-01 02:25:25 -05:00
|
|
|
};
|
2026-01-01 01:36:58 -05:00
|
|
|
};
|
2026-01-01 02:25:25 -05:00
|
|
|
}
|