Compare commits

..

3 Commits

5 changed files with 46 additions and 86 deletions

14
flake.lock generated
View File

@@ -70,11 +70,11 @@
"pre-commit-hooks": "pre-commit-hooks" "pre-commit-hooks": "pre-commit-hooks"
}, },
"locked": { "locked": {
"lastModified": 1774721317, "lastModified": 1777373577,
"narHash": "sha256-KS0ElyhZKdUFcfaxfwid3yi2Id3EP9i+dGL16/wx1T8=", "narHash": "sha256-K0sXr8tRA9L1FGE8Khl42NR+DmZOY9gNYCP8ljX7TAo=",
"ref": "main", "ref": "main",
"rev": "d0190cff6f2314cc1c727ff113aea20e086f4bcc", "rev": "faaa14a303dabc6309a52cc8e5eba86f9e29ccaf",
"revCount": 19103, "revCount": 19152,
"type": "git", "type": "git",
"url": "https://git.lix.systems/lix-project/lix" "url": "https://git.lix.systems/lix-project/lix"
}, },
@@ -178,11 +178,11 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1774386573, "lastModified": 1777268161,
"narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=", "narHash": "sha256-bxrdOn8SCOv8tN4JbTF/TXq7kjo9ag4M+C8yzzIRYbE=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "46db2e09e1d3f113a13c0d7b81e2f221c63b8ce9", "rev": "1c3fe55ad329cbcb28471bb30f05c9827f724c76",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -1,87 +1,67 @@
{ pkgs, ... }: { { pkgs, ... }: {
systemd.services.init-ollama-model = { systemd.services.init-ollama-model = {
description = "Initialize LLM models with extra context in Ollama Docker"; description = "Initialize LLM models with extra context in Ollama Docker";
after = [ "docker-ollama.service" ];
# On s'assure que Docker tourne avant de lancer ce script
after = [ "docker.service" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
script = '' script = ''
# Fonction de création asynchrone pour ne pas bloquer le démarrage # Wait for Ollama
( while ! ${pkgs.curl}/bin/curl -s http://localhost:11434/api/tags > /dev/null; do
echo "Starting asynchronous Ollama initialization..." sleep 2
done
# 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
create_model_if_missing() { create_model_if_missing() {
local model_name=$1 local model_name=$1
local base_model=$2 local base_model=$2
if ! ${pkgs.docker}/bin/docker exec ollama ollama list | grep -q "$model_name"; then
echo "$model_name not found, creating from $base_model..."
# Vérification robuste via l'API HTTP d'Ollama plutôt que docker exec (évite les conflits de tty) # We use a custom TEMPLATE block to strip the 'currentDate' function
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 # which is unsupported in Ollama 0.5.7 but present in Devstral's default manifest.
echo "$model_name not found, creating from $base_model..." ${pkgs.docker}/bin/docker exec ollama sh -c "cat <<EOF > /root/.ollama/$model_name.modelfile
# Utilisation d'un fichier temporaire sur l'hôte pour l'injecter proprement dans Docker
TMP_FILE=$(mktemp)
cat <<EOF > "$TMP_FILE"
FROM $base_model FROM $base_model
TEMPLATE """{{- if .System }} TEMPLATE \"\"\"{{- if .System }}
[SYSTEM_PROMPT] [SYSTEM_PROMPT]
{{ .System }} {{ .System }}
[/SYSTEM_PROMPT] [/SYSTEM_PROMPT]
{{- end }} {{- end }}
{{- range .Messages }} {{- range .Messages }}
{{- if eq .Role "user" }} {{- if eq .Role \"user\" }}
[INST] [INST]
{{ .Content }} {{ .Content }}
[/INST] [/INST]
{{- else if eq .Role "assistant" }} {{- else if eq .Role \"assistant\" }}
{{ .Content }} {{ .Content }}
{{- end }} {{- end }}
{{- end }}""" {{- end }}\"\"\"
PARAMETER num_ctx 131072 PARAMETER num_ctx 131072
PARAMETER num_predict 4096 PARAMETER num_predict 4096
PARAMETER num_keep 1024 PARAMETER num_keep 1024
PARAMETER repeat_penalty 1.1 PARAMETER repeat_penalty 1.1
PARAMETER top_k 40 PARAMETER top_k 40
PARAMETER stop "[INST]" PARAMETER stop \"[INST]\"
PARAMETER stop "[/INST]" PARAMETER stop \"[/INST]\"
PARAMETER stop "</s>" PARAMETER stop \"</s>\"
EOF EOF"
${pkgs.docker}/bin/docker exec ollama ollama create "$model_name" -f "/root/.ollama/$model_name.modelfile"
${pkgs.docker}/bin/docker exec ollama rm "/root/.ollama/$model_name.modelfile"
else
echo "$model_name already exists, skipping."
fi
}
# Copie et création dans le conteneur # Create Nemotron
${pkgs.docker}/bin/docker cp "$TMP_FILE" ollama:/tmp/model.modelfile create_model_if_missing "nemotron-3-nano:30b-128k" "nemotron-3-nano:30b"
${pkgs.docker}/bin/docker exec ollama ollama create "$model_name" -f /tmp/model.modelfile
${pkgs.docker}/bin/docker exec ollama rm /tmp/model.modelfile # Create Devstral
rm -f "$TMP_FILE" create_model_if_missing "devstral-small-2:24b-128k" "devstral-small-2:24b"
else
echo "$model_name already exists, skipping." # create_model_if_missing "qwen2.5-coder:32b-128k" "qwen2.5-coder:32b"
fi
} # create_model_if_missing "mistral-large-planner:123b" "mistral-large:123b-instruct-v2407-q4_K_S"
# 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"
) &
''; '';
serviceConfig = { serviceConfig = {
Type = "forking"; # Permet à systemd de savoir que le script passe en arrière-plan via '&' Type = "oneshot";
User = "root"; RemainAfterExit = true;
}; };
}; };
} }

View File

@@ -1,9 +0,0 @@
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IEdoTUQ4QSA3VG9Z
MVFPVFc2VVJ3d0h0dmtBUnI3WHl2SzUxTkRZbjFCaGloWmV3dnd3ClcxdnVPeGd6
SU4zR0Q0K1dtVjRRVHd0VW5XSFI0dVFpTjZnYk1DNjRxTVEKLT4gQzlgRy1ncmVh
c2UKeUozOWgyUytSTVF0NjY2STBEb2VadwotLS0gblI3bmJCUWxxU3QrYTEyVFBI
Snc4NC9rTkh0NnZYbUtxUE9hRWRkelpmMAq58fmH6cK13GeD7wGLxKmx10hmJeW4
b7KqnCD1ZP7uG85s32xzVRwRG8RrG4xZo5nR9Mrtg1CoTSFfUGeFnf5xveN+Ej0X
wDVB1LwC+Q==
-----END AGE ENCRYPTED FILE-----

View File

@@ -1,11 +0,0 @@
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IEdoTUQ4QSA5dzVG
WUNvT3NlRmcrWS81bzJqSWlTekVYaDFFTE10SkI2dEgzaGpxcUI4Cmk5Y0FGYTRZ
K0NGYzY3VUp4aS9ZZGRmWTgybDJFUURva2pZNmVOS3QxdEUKLT4gPnVRTCtldGMt
Z3JlYXNlCk04OTJZeFRNeDI5aGpMVTk1ZTE0Y2FMMnFEMjlJalJpMHRlaTE4ZWIx
d2lCRGQ5RHVjcktOMGJCb1VERlNWcTYKaSt0L1Z6dVJ0QWIyZkhsYzFEVjZSQWUr
ZWpwVlo1TmhoUFJZdkEvR0gxNlVhcXF2ZTRnCi0tLSBLcmM2MThNVkdWclpHUXRr
VTF6QVk2WUZlTXpZMVNLMlpBOFc3M1o5WjZzCs9xbPlIX+u5vRSQ/z9utu+I9S2c
02DOsIb1kzxzb1OK91b8Kh4JucQSq3qkyEvRucsNn5QW8hIHDnRuND6EbPyN7p4S
YB/F0dxSqgnq
-----END AGE ENCRYPTED FILE-----