Files

138 lines
5.1 KiB
YAML
Raw Permalink Normal View History

# clef-flash: a decision model, not a chat model.
#
# It reads a `state` plus a schema of typed `questions` and returns one probability
# per allowed option in a single prefill pass. There is no decoding, no sampling and
# no free-form text. The public route is /v1/systemone, and its request and response
# shapes are Clef's own: no `messages`, no `choices`.
#
# Why not SGLang: Clef support landed in SGLang v0.5.22, which upstream publishes only
# on CUDA 13. CUDA 13 dropped Volta kernels and every card here is a Tesla V100
# (compute capability 7.0), so SGLang aborts with "no kernel image is available for
# execution on the device". SGLang also states sm75 as its floor regardless.
#
# So this runs the implementation the model ships: joint_schema_model.py, which has
# load_release_model, encode_record, collate_records and systemone. The weights are
# 17.75 GiB of BF16, and fp16 costs the same bytes per parameter. On one 32 GiB card
# that leaves room for a 32k state, which is why this is one GPU and not two: with
# device_map over two cards the embedding table and the tensors indexing into it land
# on different devices, and the forward pass dies with
# "indices should be either on cpu or on the same device as the indexed tensor".
#
# Known gap: the image cannot be pushed to the registry. Cloudflare fronts
# forgejo.riotpiao.com and answers 413 Payload Too Large for any layer above 100 MB,
# and the torch base alone is 7.58 GB. So this mounts app.py from a ConfigMap and pip
# installs on every start. A cold start therefore needs PyPI reachable, and takes
# about four minutes. Build the image in-cluster, or unproxy the registry host, before
# treating this as production.
apiVersion: apps/v1
kind: Deployment
metadata:
name: clef-serve
namespace: llm-serving
labels:
app: clef-serve
app.kubernetes.io/part-of: llm-serving
spec:
# Parked at 0 to free the only V100 that was not serving anything, so candle-vllm can
# run its Phase 0 on one card. All four cards were allocated (coder 2, reasoning 1,
# this 1) and a new GPU workload had nowhere to land.
#
# This is the only GPU consumer in the namespace that is not vLLM, which is why it is
# the first card released: the standing instruction is to keep the vLLM pods healthy
# until candle-vllm answers, and this pod is not one of them.
#
# It was serving nothing. The last 30 log lines at park time were 30/30 kubelet
# /health probes and no inference request since start (2026-10-30T06:23:40Z). Nothing
# in git selects this service. Restore it once the rollout leaves a card free:
# 30B-A3B takes 1, Coder-Next TP=2 takes 2, so card 4 is this one.
replicas: 0
# Recreate, not RollingUpdate. Every GPU card is allocated, so a rolling update leaves
# the new pod Pending forever waiting for a card the old pod still holds.
strategy:
type: Recreate
selector:
matchLabels:
app: clef-serve
template:
metadata:
labels:
app: clef-serve
app.kubernetes.io/part-of: llm-serving
spec:
runtimeClassName: nvidia
nodeSelector:
kubernetes.io/hostname: worker-1
containers:
- name: clef
image: pytorch/pytorch:2.8.0-cuda12.8-cudnn9-runtime
command: ["/bin/bash","-lc"]
args:
- |
set -e
pip install --no-cache-dir transformers==5.10.2 accelerate fastapi 'uvicorn[standard]' pillow safetensors sentencepiece protobuf
exec uvicorn app:create_app --factory --host 0.0.0.0 --port 8080
workingDir: /app
env:
- name: PYTHONUNBUFFERED
value: "1"
- name: MODEL_PATH
value: /mnt/models/clef-flash
# V100 has no bf16, and the release weights are bf16. fp16 is the same width.
- name: DTYPE
value: float16
# The state is truncated at this length without warning, so raise it only with
# spare VRAM: 17.75 GiB of weights plus 128 KiB of KV per token.
- name: MAX_LEN
value: "32768"
ports:
- containerPort: 8080
# A cold start pip-installs and loads 17.75 GiB, measured at about four minutes.
startupProbe:
httpGet:
path: /health
port: 8080
failureThreshold: 120
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8080
periodSeconds: 10
resources:
requests:
cpu: "4"
memory: 12Gi
nvidia.com/gpu: "1"
limits:
cpu: "8"
memory: 40Gi
nvidia.com/gpu: "1"
volumeMounts:
- name: app
mountPath: /app
- name: models
mountPath: /mnt/models
readOnly: true
volumes:
- name: app
configMap:
name: clef-serve-app
- name: models
persistentVolumeClaim:
claimName: llm-models
---
apiVersion: v1
kind: Service
metadata:
name: clef-serve
namespace: llm-serving
labels:
app.kubernetes.io/part-of: llm-serving
spec:
selector:
app: clef-serve
ports:
- name: http
port: 80
targetPort: 8080