viarl199020 commited on
Commit
ed62617
Β·
verified Β·
1 Parent(s): 9c8925e

Upload 5 files

Browse files
Files changed (4) hide show
  1. Dockerfile +48 -96
  2. README.md +15 -15
  3. download_model.py +19 -0
  4. start.sh +23 -53
Dockerfile CHANGED
@@ -1,108 +1,57 @@
1
  # ═══════════════════════════════════════════════════════════════════════════
2
- # OMNI-NEXUS Β· Worker BitNet b1.58 (ternario, 1.58 bits)
3
  # ═══════════════════════════════════════════════════════════════════════════
4
  #
5
- # POR QUÉ BITNET Y NO UN GGUF Q4 NORMAL
6
- # ─────────────────────────────────────
7
- # BitNet restringe cada peso a {-1, 0, +1}. Eso elimina las multiplicaciones
8
- # del matmul y las convierte en sumas y restas β€” que es exactamente donde una
9
- # CPU sin AVX potente deja de ser el cuello de botella.
 
 
10
  #
11
- # NΓΊmeros oficiales de bitnet.cpp en x86: 2.37x-6.17x mΓ‘s rΓ‘pido que fp16,
12
- # mΓ‘s 1.15x-2.1x extra con los kernels paralelos de enero 2026.
 
13
  #
14
- # El detalle que decide todo: el paper reporta que la ventaja es MAYOR en
15
- # escenarios con hilos limitados. Un Space tiene 2 vCPU. Es el peor caso para
16
- # un Q4 normal y el mejor caso relativo para BitNet.
17
- #
18
- # Modelo TamaΓ±o tok/s en 2 vCPU (estimado)
19
- # ─────────────────────────────────────────────────────────
20
- # Llama 3.2 3B Q4_K_M 2.0 GB 8-12
21
- # BitNet b1.58 2B i2_s 1.2 GB 18-30 ← este
22
- #
23
- # EL BUG QUE MATΓ“ TU "CEREBRO A"
24
- # ──────────────────────────────
25
- # Tu Dockerfile anterior documentaba que ggml-model-i2_s.gguf usa el tensor
26
- # type 36 (IQ4_NL_4_4), eliminado del llama.cpp oficial. Por eso tuviste que
27
- # recurrir a los binarios de ik_llama.cpp de Thireus.
28
- #
29
- # AquΓ­ no hay ese problema: compilamos bitnet.cpp, que es el framework OFICIAL
30
- # de Microsoft para i2_s. No depende de que un fork de terceros siga publicando
31
- # binarios, y trae las optimizaciones de enero 2026 que ik_llama no tiene.
32
  # ═══════════════════════════════════════════════════════════════════════════
33
 
34
- # ── Etapa 1: compilar bitnet.cpp ───────────────────────────────────────────
35
- FROM python:3.11-slim AS builder
36
 
37
  RUN apt-get update && apt-get install -y --no-install-recommends \
38
- build-essential cmake git ca-certificates \
39
- clang lld libomp-dev \
40
  && rm -rf /var/lib/apt/lists/*
41
 
42
- WORKDIR /build
43
-
44
- # --recursive es obligatorio: bitnet.cpp lleva llama.cpp como submΓ³dulo con
45
- # los kernels ternarios parcheados encima.
46
- RUN git clone --recursive --depth 1 https://github.com/microsoft/BitNet.git bitnet
47
-
48
- WORKDIR /build/bitnet
49
 
50
- RUN pip install --no-cache-dir -r requirements.txt || true
51
-
52
- # Se compila con clang porque los kernels TL1/TL2 de BitNet usan intrΓ­nsecos
53
- # que gcc no vectoriza igual de bien.
54
- #
55
- # EL BUG REAL: -DLLAMA_BUILD_SERVER=ON no existe como flag en el CMake de
56
- # BitNet.cpp (es una opciΓ³n del llama.cpp "vainilla", no del fork parcheado
57
- # que trae BitNet como submΓ³dulo). Como llama.cpp estΓ‘ incluido vΓ­a
58
- # add_subdirectory, CMake trata "server" como un target de EXAMPLES y los
59
- # examples estΓ‘n desactivados por defecto. Por eso "gmake: No rule to make
60
- # target 'llama-server'" β€” el target ni se generΓ³.
61
- # El flag correcto es -DLLAMA_BUILD_EXAMPLES=ON (asΓ­ lo hace el propio
62
- # setup_env.py oficial de Microsoft).
63
- #
64
- # AdemΓ‘s, "cmake --build" con target "llama-server" produce un binario
65
- # enlazado dinΓ‘micamente contra libllama.so y libggml*.so, ubicadas dentro
66
- # del Γ‘rbol de build. Copiar solo el binario al runtime (sin esas .so)
67
- # provoca en el arranque:
68
- # "llama-server: error while loading shared libraries: libllama.so:
69
- # cannot open shared object file: No such file or directory"
70
- # Por eso copiamos tambiΓ©n todas las .so generadas.
71
- RUN cmake -B build \
72
- -DCMAKE_BUILD_TYPE=Release \
73
- -DCMAKE_C_COMPILER=clang \
74
- -DCMAKE_CXX_COMPILER=clang++ \
75
- -DGGML_NATIVE=OFF \
76
- -DGGML_AVX2=ON \
77
- -DGGML_FMA=ON \
78
- -DLLAMA_BUILD_EXAMPLES=ON \
79
- && cmake --build build --config Release -j"$(nproc)" --target llama-server \
80
- && find build -name "llama-server" -type f -exec cp {} /build/llama-server \; \
81
- && find build -name "lib*.so*" -type f -exec cp {} /build/ \; \
82
- && chmod +x /build/llama-server \
83
- && echo "[BUILD] bitnet.cpp compilado"
84
-
85
- # ── Etapa 2: descargar el modelo ternario ──────────────────────────────────
86
  FROM python:3.11-slim AS fetcher
87
 
88
  RUN pip install --no-cache-dir huggingface_hub
89
 
90
- # Repo oficial de Microsoft, pΓΊblico y sin gating. Licencia MIT.
91
- # i2_s = cuantizaciΓ³n ternaria nativa de BitNet (~1.2 GB para 2.4B params).
92
- ARG MODEL_REPO="microsoft/bitnet-b1.58-2B-4T-gguf"
93
- ARG MODEL_FILE="ggml-model-i2_s.gguf"
 
 
94
  ENV MODEL_REPO=${MODEL_REPO}
95
  ENV MODEL_FILE=${MODEL_FILE}
96
 
97
- RUN mkdir -p /models && python3 -c "\
98
- import os, sys; \
99
- from huggingface_hub import hf_hub_download; \
100
- p = hf_hub_download(repo_id=os.environ['MODEL_REPO'], filename=os.environ['MODEL_FILE'], local_dir='/models'); \
101
- gb = os.path.getsize(p)/1024**3; \
102
- print(f'[FETCH] {p} ({gb:.2f} GB)', flush=True); \
103
- sys.exit(0 if gb > 0.5 else 1)"
104
 
105
- # ── Etapa 3: runtime ───────────────────────────────────────────────────────
106
  FROM python:3.11-slim AS runtime
107
 
108
  RUN apt-get update && apt-get install -y --no-install-recommends \
@@ -111,32 +60,35 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
111
 
112
  WORKDIR /app
113
 
114
- COPY --from=builder /build/llama-server /usr/local/bin/llama-server
115
- COPY --from=builder /build/*.so* /usr/local/lib/
116
  COPY --from=fetcher /models /models
117
 
118
- RUN chmod +x /usr/local/bin/llama-server && ldconfig
119
-
120
- # Necesario para que el loader dinΓ‘mico encuentre libllama.so, libggml*.so.
121
- ENV LD_LIBRARY_PATH=/usr/local/lib:${LD_LIBRARY_PATH}
 
 
 
 
 
122
 
123
  RUN pip install --no-cache-dir \
124
  fastapi==0.115.6 \
125
  "uvicorn[standard]==0.34.0" \
126
  httpx==0.28.1
127
 
128
- # ── ConfiguraciΓ³n ──────────────────────────────────────────────────────────
129
- # N_THREADS=2 : son 2 vCPU reales; mΓ‘s hilos solo generan contenciΓ³n de cachΓ©.
130
- # N_CTX=4096 : el KV cache se reserva entero al arrancar. Con la cuantizaciΓ³n
131
- # q8_0 de abajo ocupa la mitad que en f16.
132
  ENV N_CTX=4096
133
  ENV N_THREADS=2
134
  ENV LLAMA_PORT=8080
135
  ENV PORT=7860
136
  ENV WORKER_ID=A
137
  ENV WORKER_KIND=chat
138
- ENV MODEL_NAME="bitnet-b1.58-2b"
 
139
  ENV LLAMA_TIMEOUT=180.0
 
140
 
141
  COPY server.py start.sh ./
142
  RUN chmod +x start.sh
 
1
  # ═══════════════════════════════════════════════════════════════════════════
2
+ # OMNI-NEXUS Β· Worker de chat (reemplaza al de BitNet)
3
  # ═══════════════════════════════════════════════════════════════════════════
4
  #
5
+ # POR QUÉ YA NO SE USA BITNET
6
+ # ───────────────────────────
7
+ # bitnet.cpp NO incluye servidor HTTP. Su submΓ³dulo de llama.cpp solo compila
8
+ # `llama-cli`; el target `llama-server` no existe, de ahΓ­ el error
9
+ # "No rule to make target 'llama-server'" que salΓ­a siempre.
10
+ # Y `setup_env.py` morΓ­a con OOMKilled porque convierte el modelo con PyTorch
11
+ # durante el build, cosa que no cabe en la RAM del builder de HF.
12
  #
13
+ # Esta imagen usa los binarios OFICIALES precompilados de llama.cpp β€” la misma
14
+ # receta con la que tu Space `coder` ya arranca sin problemas. Cero compilaciΓ³n
15
+ # de C++, build de 3-5 minutos en vez de 25.
16
  #
17
+ # EL BUG DE libllama.so, RESUELTO
18
+ # ───────────────────────────────
19
+ # El zip oficial trae el binario Y sus librerΓ­as compartidas. Antes copiaba
20
+ # solo el binario y por eso fallaba con "libllama.so: cannot open shared
21
+ # object file". Ahora se copia el directorio COMPLETO y se registra con
22
+ # ldconfig.
 
 
 
 
 
 
 
 
 
 
 
 
23
  # ═══════════════════════════════════════════════════════════════════════════
24
 
25
+ FROM python:3.11-slim AS llama
 
26
 
27
  RUN apt-get update && apt-get install -y --no-install-recommends \
28
+ wget unzip ca-certificates \
 
29
  && rm -rf /var/lib/apt/lists/*
30
 
31
+ ARG LLAMA_RELEASE="b4585"
32
+ RUN wget -q -O /tmp/l.zip \
33
+ "https://github.com/ggml-org/llama.cpp/releases/download/${LLAMA_RELEASE}/llama-${LLAMA_RELEASE}-bin-ubuntu-x64.zip" \
34
+ && mkdir -p /llama && unzip -q /tmp/l.zip -d /llama \
35
+ && echo "[LLAMA] contenido descargado:" && find /llama -name "llama-server" -o -name "*.so*" | head -20
 
 
36
 
37
+ # ── Modelo ─────────────────────────────────────────────────────────────────
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  FROM python:3.11-slim AS fetcher
39
 
40
  RUN pip install --no-cache-dir huggingface_hub
41
 
42
+ # Llama 3.2 3B en Q4_K_M (~2 GB). En 2 vCPU da 8-12 tok/s.
43
+ # Para mΓ‘s velocidad y menos calidad, cambia a 1B (~0.8 GB, 20-30 tok/s):
44
+ # MODEL_REPO=bartowski/Llama-3.2-1B-Instruct-GGUF
45
+ # MODEL_FILE=Llama-3.2-1B-Instruct-Q4_K_M.gguf
46
+ ARG MODEL_REPO="bartowski/Llama-3.2-3B-Instruct-GGUF"
47
+ ARG MODEL_FILE="Llama-3.2-3B-Instruct-Q4_K_M.gguf"
48
  ENV MODEL_REPO=${MODEL_REPO}
49
  ENV MODEL_FILE=${MODEL_FILE}
50
 
51
+ COPY download_model.py /tmp/download_model.py
52
+ RUN mkdir -p /models && python3 /tmp/download_model.py
 
 
 
 
 
53
 
54
+ # ── Runtime ────────────────────────────────────────────────────────────────
55
  FROM python:3.11-slim AS runtime
56
 
57
  RUN apt-get update && apt-get install -y --no-install-recommends \
 
60
 
61
  WORKDIR /app
62
 
63
+ # Directorio COMPLETO, no solo el binario: asΓ­ vienen las .so que necesita.
64
+ COPY --from=llama /llama /opt/llama
65
  COPY --from=fetcher /models /models
66
 
67
+ # Localizar el binario donde sea que estΓ© dentro del zip, enlazarlo, y
68
+ # registrar sus librerΓ­as en el linker dinΓ‘mico.
69
+ RUN BIN="$(find /opt/llama -name 'llama-server' -type f | head -1)" \
70
+ && test -n "$BIN" || { echo "FATAL: llama-server no encontrado"; exit 1; } \
71
+ && chmod +x "$BIN" && ln -sf "$BIN" /usr/local/bin/llama-server \
72
+ && find /opt/llama -name "*.so*" -exec cp {} /usr/local/lib/ \; \
73
+ && ldconfig \
74
+ && echo "/usr/local/lib" > /etc/ld.so.conf.d/llama.conf && ldconfig \
75
+ && llama-server --version 2>&1 | head -3 || true
76
 
77
  RUN pip install --no-cache-dir \
78
  fastapi==0.115.6 \
79
  "uvicorn[standard]==0.34.0" \
80
  httpx==0.28.1
81
 
 
 
 
 
82
  ENV N_CTX=4096
83
  ENV N_THREADS=2
84
  ENV LLAMA_PORT=8080
85
  ENV PORT=7860
86
  ENV WORKER_ID=A
87
  ENV WORKER_KIND=chat
88
+ ENV MODEL_NAME="llama-3.2-3b"
89
+ ENV CHAT_TEMPLATE=llama3
90
  ENV LLAMA_TIMEOUT=180.0
91
+ ENV LD_LIBRARY_PATH="/usr/local/lib"
92
 
93
  COPY server.py start.sh ./
94
  RUN chmod +x start.sh
README.md CHANGED
@@ -1,6 +1,6 @@
1
  ---
2
- title: Omni-Nexus Worker A (BitNet)
3
- emoji: ⚑
4
  colorFrom: indigo
5
  colorTo: purple
6
  sdk: docker
@@ -8,18 +8,18 @@ app_port: 7860
8
  pinned: false
9
  ---
10
 
11
- # Omni-Nexus Β· Worker BitNet b1.58
12
 
13
- Nodo de inferencia ternario (1.58 bits) compatible con la API de OpenAI.
14
 
15
- Cada peso vale {-1, 0, +1}, lo que convierte las multiplicaciones del matmul
16
- en sumas. La ventaja crece en escenarios con pocos hilos β€” justo el caso de
17
- un Space con 2 vCPU.
18
 
19
- | | 3B Q4_K_M | BitNet b1.58 2B |
20
- |---|---|---|
21
- | TamaΓ±o | 2.0 GB | 1.2 GB |
22
- | tok/s en 2 vCPU | 8-12 | 18-30 |
 
23
 
24
  ## Uso
25
 
@@ -31,7 +31,7 @@ https://TU-USUARIO-ESTE-SPACE.hf.space/v1
31
 
32
  ## Variables
33
 
34
- | Variable | Valor | Nota |
35
- |---|---|---|
36
- | `WORKER_ID` | `A` | Identifica quiΓ©n respondiΓ³ |
37
- | `CHAT_TEMPLATE` | `llama3` | BitNet usa formato Llama 3, **no** ChatML |
 
1
  ---
2
+ title: Omni-Nexus Worker A
3
+ emoji: πŸ’¬
4
  colorFrom: indigo
5
  colorTo: purple
6
  sdk: docker
 
8
  pinned: false
9
  ---
10
 
11
+ # Omni-Nexus Β· Worker de chat
12
 
13
+ Llama 3.2 3B (Q4_K_M) servido con API compatible con OpenAI.
14
 
15
+ Usa los binarios **oficiales precompilados** de llama.cpp: build de 3-5 min,
16
+ sin compilar C++.
 
17
 
18
+ ## Por quΓ© ya no se usa BitNet
19
+
20
+ bitnet.cpp no incluye servidor HTTP β€” su submΓ³dulo solo compila `llama-cli`.
21
+ El target `llama-server` no existe. Y `setup_env.py` agota la RAM del builder
22
+ de HF al convertir el modelo. No es parcheable.
23
 
24
  ## Uso
25
 
 
31
 
32
  ## Variables
33
 
34
+ | Variable | Valor |
35
+ |---|---|
36
+ | `WORKER_ID` | `A` |
37
+ | `CHAT_TEMPLATE` | `llama3` |
download_model.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Descarga el modelo. En archivo aparte porque `python3 -c` con ';' no
2
+ admite try/except β€” Γ©se fue el SyntaxError del Space de embeddings."""
3
+ import os
4
+ import sys
5
+
6
+ from huggingface_hub import hf_hub_download
7
+
8
+ repo = os.environ["MODEL_REPO"]
9
+ fname = os.environ["MODEL_FILE"]
10
+
11
+ try:
12
+ path = hf_hub_download(repo_id=repo, filename=fname, local_dir="/models")
13
+ except Exception as exc:
14
+ print(f"[FETCH] FALLO al descargar {repo}/{fname}: {exc}", flush=True)
15
+ sys.exit(1)
16
+
17
+ gb = os.path.getsize(path) / 1024 ** 3
18
+ print(f"[FETCH] OK {path} ({gb:.2f} GB)", flush=True)
19
+ sys.exit(0 if gb > 0.3 else 1)
start.sh CHANGED
@@ -1,67 +1,37 @@
1
  #!/bin/bash
2
- # ═══════════════════════════════════════════════════════════════════════════
3
- # start.sh β€” Worker BitNet b1.58
4
- # ═══════════════════════════════════════════════════════════════════════════
5
  set -e
 
 
6
 
7
- N_CTX="${N_CTX:-4096}"
8
- N_THREADS="${N_THREADS:-2}"
9
- LLAMA_PORT="${LLAMA_PORT:-8080}"
10
- PORT="${PORT:-7860}"
11
- WORKER_ID="${WORKER_ID:-A}"
12
-
13
- echo "[START] ═══════════════════════════════════════════"
14
- echo "[START] Omni-Nexus Worker ${WORKER_ID} β€” BitNet b1.58"
15
- echo "[START] ═══════════════════════════════════════════"
16
 
17
  GGUF=$(find /models -name "*.gguf" -type f | head -1)
18
- if [ -z "$GGUF" ]; then
19
- echo "[START] FATAL: no hay .gguf en /models"; ls -lah /models 2>/dev/null; exit 1
 
 
 
 
 
 
 
20
  fi
21
- echo "[START] Modelo ternario: $(du -h "$GGUF" | cut -f1) β€” $GGUF"
22
- echo "[START] Hilos: ${N_THREADS} | Contexto: ${N_CTX}"
23
 
24
  LOG=/tmp/llama.log; : > "$LOG"
25
 
26
- # --cache-type-k/v q8_0: cuantiza el KV cache. Reduce a la mitad la RAM del
27
- # contexto con pΓ©rdida de calidad inapreciable. Es lo que permite tener
28
- # 4096 de contexto cΓ³modamente en vez de recortar a 2048.
29
- # --cont-batching: permite solapar prefill y generaciΓ³n entre peticiones.
30
- # --mlock: evita que el kernel mande los pesos a swap. Con 16 GB y un modelo
31
- # de 1.2 GB sobra memoria, asΓ­ que fijarlo en RAM es gratis y elimina
32
- # pausas aleatorias a mitad de generaciΓ³n.
33
- llama-server \
34
- --model "$GGUF" \
35
- --host 127.0.0.1 \
36
- --port "$LLAMA_PORT" \
37
- --ctx-size "$N_CTX" \
38
- --threads "$N_THREADS" \
39
- --n-gpu-layers 0 \
40
- --cache-type-k q8_0 \
41
- --cache-type-v q8_0 \
42
- --cont-batching \
43
- --parallel 1 \
44
- --mlock \
45
- 2>&1 | tee "$LOG" | sed 's/^/[BITNET] /' &
46
-
47
- PID=$!
48
- echo "[START] PID=$PID β€” cargando (BitNet carga rΓ‘pido: ~20-40s)"
49
 
50
- MAX=300; T=0
51
  while [ $T -lt $MAX ]; do
52
- if ! kill -0 $PID 2>/dev/null; then
53
- echo "[START] llama-server muriΓ³:"; tail -30 "$LOG" | sed 's/^/[CRASH] /'; exit 1
54
- fi
55
- if curl -sf "http://127.0.0.1:${LLAMA_PORT}/health" >/dev/null 2>&1; then
56
- echo "[START] Worker ${WORKER_ID} ONLINE en ${T}s"; break
57
- fi
58
- sleep 5; T=$((T+5))
59
- [ $((T % 30)) -eq 0 ] && echo "[START] ${T}/${MAX}s..."
60
  done
 
61
 
62
- if [ $T -ge $MAX ]; then
63
- echo "[START] FATAL: timeout"; tail -20 "$LOG" | sed 's/^/[TIMEOUT] /'; exit 1
64
- fi
65
-
66
- echo "[START] FastAPI en :${PORT}"
67
  exec uvicorn server:app --host 0.0.0.0 --port "$PORT" --workers 1 --log-level info
 
1
  #!/bin/bash
 
 
 
2
  set -e
3
+ N_CTX="${N_CTX:-4096}"; N_THREADS="${N_THREADS:-2}"
4
+ LLAMA_PORT="${LLAMA_PORT:-8080}"; PORT="${PORT:-7860}"; WORKER_ID="${WORKER_ID:-A}"
5
 
6
+ echo "[START] Omni-Nexus Worker ${WORKER_ID} (chat)"
 
 
 
 
 
 
 
 
7
 
8
  GGUF=$(find /models -name "*.gguf" -type f | head -1)
9
+ [ -z "$GGUF" ] && { echo "[START] FATAL: sin .gguf"; ls -lah /models; exit 1; }
10
+ echo "[START] Modelo: $(du -h "$GGUF" | cut -f1)"
11
+
12
+ # Verificación temprana: si faltan librerías, se ve AQUÍ y no a mitad del
13
+ # arranque con un mensaje crΓ­ptico.
14
+ if ! llama-server --version >/dev/null 2>&1; then
15
+ echo "[START] FATAL: llama-server no ejecuta. LibrerΓ­as:"
16
+ ldd "$(readlink -f "$(command -v llama-server)")" 2>&1 | grep -i "not found" || true
17
+ exit 1
18
  fi
19
+ echo "[START] llama-server OK"
 
20
 
21
  LOG=/tmp/llama.log; : > "$LOG"
22
 
23
+ llama-server --model "$GGUF" --host 127.0.0.1 --port "$LLAMA_PORT" \
24
+ --ctx-size "$N_CTX" --threads "$N_THREADS" --n-gpu-layers 0 \
25
+ --cache-type-k q8_0 --cache-type-v q8_0 \
26
+ --cont-batching --parallel 1 \
27
+ 2>&1 | tee "$LOG" | sed 's/^/[LLAMA] /' &
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
+ PID=$!; MAX=300; T=0
30
  while [ $T -lt $MAX ]; do
31
+ kill -0 $PID 2>/dev/null || { echo "[START] muriΓ³:"; tail -30 "$LOG"; exit 1; }
32
+ curl -sf "http://127.0.0.1:${LLAMA_PORT}/health" >/dev/null 2>&1 && { echo "[START] ONLINE en ${T}s"; break; }
33
+ sleep 5; T=$((T+5)); [ $((T % 30)) -eq 0 ] && echo "[START] ${T}/${MAX}s..."
 
 
 
 
 
34
  done
35
+ [ $T -ge $MAX ] && { echo "[START] FATAL: timeout"; tail -20 "$LOG"; exit 1; }
36
 
 
 
 
 
 
37
  exec uvicorn server:app --host 0.0.0.0 --port "$PORT" --workers 1 --log-level info