Skip to content

Commit 8d33666

Browse files
Merge pull request #14 from XyLearningProgramming/bugfix/model-download
Bugfix/model download
2 parents c617756 + 359a365 commit 8d33666

File tree

7 files changed

+104
-84
lines changed

7 files changed

+104
-84
lines changed

.github/actions/helm-deploy/action.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ inputs:
2424
description: 'Kubernetes namespace'
2525
required: true
2626
default: 'backend'
27+
helm_set_files:
28+
description: 'Comma-separated --set-file args, e.g. "configMapData.download=scripts/download.sh"'
29+
required: false
30+
default: ''
2731
github_token:
2832
description: 'GitHub token for Helm installation'
2933
required: true
@@ -92,11 +96,23 @@ runs:
9296
${{ steps.parse_env.outputs.helm_env_values }}
9397
EOF
9498
99+
# Build --set-file flags from comma-separated input
100+
SET_FILE_FLAGS=""
101+
if [ -n "${{ inputs.helm_set_files }}" ]; then
102+
IFS=',' read -ra PAIRS <<< "${{ inputs.helm_set_files }}"
103+
for pair in "${PAIRS[@]}"; do
104+
pair="${pair#"${pair%%[![:space:]]*}"}"
105+
pair="${pair%"${pair##*[![:space:]]}"}"
106+
[ -n "$pair" ] && SET_FILE_FLAGS="$SET_FILE_FLAGS --set-file $pair"
107+
done
108+
fi
109+
95110
# Deploy using Helm (values file won't be logged due to file redirection)
96111
helm upgrade --install slm-server ./deploy/helm \
97112
--namespace ${{ inputs.namespace }} \
98113
--create-namespace \
99114
--values "$temp_values" \
115+
$SET_FILE_FLAGS \
100116
--wait \
101117
--timeout 10m
102118

.github/workflows/cd.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,6 @@ jobs:
8383
helm_values_env: ${{ secrets.HELM_VALUES_ENV }}
8484
helm_values_persistence_hostpath: ${{ secrets.HELM_VALUES_PERSISTENCE_HOSTPATH }}
8585
helm_values_persistence_nodename: ${{ secrets.HELM_VALUES_PERSISTENCE_NODENAME }}
86+
helm_set_files: 'configMapData.download=scripts/download.sh'
8687
namespace: ${{ env.NAMESPACE }}
8788
github_token: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/deploy.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@ jobs:
2929
helm_values_env: ${{ secrets.HELM_VALUES_ENV }}
3030
helm_values_persistence_hostpath: ${{ secrets.HELM_VALUES_PERSISTENCE_HOSTPATH }}
3131
helm_values_persistence_nodename: ${{ secrets.HELM_VALUES_PERSISTENCE_NODENAME }}
32+
helm_set_files: 'configMapData.download=scripts/download.sh'
3233
namespace: ${{ env.NAMESPACE }}
3334
github_token: ${{ secrets.GITHUB_TOKEN }}
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
{{- if .Values.configMapData }}
12
apiVersion: v1
23
kind: ConfigMap
34
metadata:
45
name: {{ include "slm-server.fullname" . }}-scripts
56
labels:
67
{{- include "slm-server.labels" . | nindent 4 }}
78
data:
8-
download.sh: |-
9-
{{- .Files.Get "scripts/download.sh" | nindent 4 }}
9+
{{- range $key, $val := .Values.configMapData }}
10+
{{ $key }}: |
11+
{{- $val | nindent 4 }}
12+
{{- end }}
13+
{{- end }}

deploy/helm/templates/deployment.yaml

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,10 @@ spec:
1919
affinity:
2020
{{- toYaml . | nindent 8 }}
2121
{{- end }}
22+
{{- if .Values.initContainers }}
2223
initContainers:
23-
- name: download-model
24-
image: busybox:1.28
25-
command: ["sh", "-c", "/scripts/download.sh"]
26-
volumeMounts:
27-
- name: models-storage
28-
mountPath: {{ .Values.persistence.mountPath }}
29-
- name: scripts
30-
mountPath: /scripts
24+
{{- tpl (toYaml .Values.initContainers) . | nindent 8 }}
25+
{{- end }}
3126
containers:
3227
- name: {{ .Chart.Name }}
3328
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
@@ -67,20 +62,13 @@ spec:
6762
{{- end }}
6863
resources:
6964
{{- toYaml .Values.resources | nindent 12 }}
65+
{{- if .Values.volumeMounts }}
7066
volumeMounts:
71-
- name: models-storage
72-
mountPath: {{ .Values.persistence.mountPath }}
73-
volumes:
74-
- name: models-storage
75-
{{- if .Values.persistence.enabled }}
76-
persistentVolumeClaim:
77-
claimName: {{ include "slm-server.fullname" . }}
78-
{{- else }}
79-
emptyDir: {}
67+
{{- tpl (toYaml .Values.volumeMounts) . | nindent 12 }}
8068
{{- end }}
81-
- name: scripts
82-
configMap:
83-
name: {{ include "slm-server.fullname" . }}-scripts
84-
defaultMode: 0755
69+
{{- if .Values.volumes }}
70+
volumes:
71+
{{- tpl (toYaml .Values.volumes) . | nindent 8 }}
72+
{{- end }}
8573
strategy:
8674
{{- toYaml .Values.strategy | nindent 4 }}

deploy/helm/values.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,5 +128,35 @@ probes:
128128
successThreshold: 1
129129
failureThreshold: 5
130130

131+
# Content is injected at deploy time via: --set-file configMapData.download=scripts/download.sh
132+
configMapData: {}
133+
134+
# Volumes and volumeMounts rendered via tpl so template expressions work.
135+
volumes:
136+
- name: models-storage
137+
persistentVolumeClaim:
138+
claimName: '{{ include "slm-server.fullname" . }}'
139+
- name: scripts
140+
configMap:
141+
name: '{{ include "slm-server.fullname" . }}-scripts'
142+
defaultMode: 0755
143+
items:
144+
- key: download
145+
path: download.sh
146+
147+
volumeMounts:
148+
- name: models-storage
149+
mountPath: /app/models
150+
151+
initContainers:
152+
- name: download-model
153+
image: curlimages/curl:latest
154+
command: ["sh", "-c", "MODEL_DIR=/app/models sh /scripts/download.sh"]
155+
volumeMounts:
156+
- name: models-storage
157+
mountPath: /app/models
158+
- name: scripts
159+
mountPath: /scripts
160+
131161
strategy:
132162
type: Recreate

scripts/download.sh

Lines changed: 41 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,45 @@
1-
#!/bin/bash
1+
#!/bin/sh
2+
#
3+
# Download model files for slm-server.
4+
#
5+
# When run inside the init container, MODEL_DIR is set by the caller
6+
# (the Helm-rendered configmap). For local use it defaults to
7+
# ../models relative to this script.
28

3-
set -ex
9+
set -e
410

5-
# Get the absolute path of the directory where the script is located
6-
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)
7-
8-
# Original (official Qwen repo, Q8_0 only):
9-
# https://huggingface.co/Qwen/Qwen3-0.6B-GGUF -> Qwen3-0.6B-Q8_0.gguf
10-
# Switched to second-state community repo for Q4_K_M quantization.
11-
# See README.md "Model Choice" section for rationale.
12-
REPO_URL="https://huggingface.co/second-state/Qwen3-0.6B-GGUF"
13-
# Set model directory relative to the script's location
14-
MODEL_DIR="$SCRIPT_DIR/../models"
15-
16-
# Create the directory if it doesn't exist
11+
MODEL_DIR="${MODEL_DIR:-$(cd -- "$(dirname "$0")" && pwd)/../models}"
1712
mkdir -p "$MODEL_DIR"
1813

19-
# --- Files to download ---
20-
FILES_TO_DOWNLOAD=(
21-
"Qwen3-0.6B-Q4_K_M.gguf"
22-
# Previous default: "Qwen3-0.6B-Q8_0.gguf" (805 MB, from Qwen/Qwen3-0.6B-GGUF)
23-
)
24-
25-
echo "Downloading Qwen3-0.6B-GGUF model and params files..."
26-
27-
for file in "${FILES_TO_DOWNLOAD[@]}"; do
28-
if [ -f "$MODEL_DIR/$file" ]; then
29-
echo "$file already exists, skipping download."
30-
else
31-
echo "Downloading $file..."
32-
wget -P "$MODEL_DIR" "$REPO_URL/resolve/main/$file" || {
33-
echo "Failed to download $file with wget, trying curl..."
34-
curl -L -o "$MODEL_DIR/$file" "$REPO_URL/resolve/main/$file"
35-
}
36-
fi
37-
done
38-
39-
# --- Embedding model: all-MiniLM-L6-v2 (ONNX, quantized UINT8 for AVX2) ---
40-
EMBEDDING_REPO_URL="https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2"
41-
EMBEDDING_MODEL_DIR="$MODEL_DIR/all-MiniLM-L6-v2"
42-
43-
mkdir -p "$EMBEDDING_MODEL_DIR/onnx"
44-
45-
EMBEDDING_FILES=(
46-
"onnx/model_quint8_avx2.onnx"
47-
"tokenizer.json"
48-
)
49-
50-
echo "Downloading all-MiniLM-L6-v2 ONNX embedding model..."
51-
52-
for file in "${EMBEDDING_FILES[@]}"; do
53-
dest="$EMBEDDING_MODEL_DIR/$file"
54-
if [ -f "$dest" ]; then
55-
echo "$file already exists, skipping download."
56-
else
57-
echo "Downloading $file..."
58-
wget -O "$dest" "$EMBEDDING_REPO_URL/resolve/main/$file" || {
59-
echo "Failed to download $file with wget, trying curl..."
60-
curl -L -o "$dest" "$EMBEDDING_REPO_URL/resolve/main/$file"
61-
}
62-
fi
63-
done
64-
65-
echo "Download process complete! Files are in $MODEL_DIR"
14+
# --- Chat LLM: Qwen3-0.6B (Q4_K_M quantisation from second-state) ---
15+
GGUF_REPO="https://huggingface.co/second-state/Qwen3-0.6B-GGUF"
16+
GGUF_FILE="Qwen3-0.6B-Q4_K_M.gguf"
17+
18+
if [ -f "$MODEL_DIR/$GGUF_FILE" ]; then
19+
echo "$GGUF_FILE already exists, skipping."
20+
else
21+
echo "Downloading $GGUF_FILE ..."
22+
curl -fSL -o "$MODEL_DIR/$GGUF_FILE" "$GGUF_REPO/resolve/main/$GGUF_FILE"
23+
fi
24+
25+
# --- Embedding: all-MiniLM-L6-v2 (ONNX, quantized UINT8 for AVX2) ---
26+
EMBED_REPO="https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2"
27+
EMBED_DIR="$MODEL_DIR/all-MiniLM-L6-v2"
28+
mkdir -p "$EMBED_DIR/onnx"
29+
30+
if [ -f "$EMBED_DIR/tokenizer.json" ]; then
31+
echo "tokenizer.json already exists, skipping."
32+
else
33+
echo "Downloading tokenizer.json ..."
34+
curl -fSL -o "$EMBED_DIR/tokenizer.json" "$EMBED_REPO/resolve/main/tokenizer.json"
35+
fi
36+
37+
ONNX_FILE="model_quint8_avx2.onnx"
38+
if [ -f "$EMBED_DIR/onnx/$ONNX_FILE" ]; then
39+
echo "$ONNX_FILE already exists, skipping."
40+
else
41+
echo "Downloading $ONNX_FILE ..."
42+
curl -fSL -o "$EMBED_DIR/onnx/$ONNX_FILE" "$EMBED_REPO/resolve/main/onnx/$ONNX_FILE"
43+
fi
44+
45+
echo "Download complete. Files are in $MODEL_DIR"

0 commit comments

Comments
 (0)