From 57180914254c9b0c9f835d1e923d12db0b135c59 Mon Sep 17 00:00:00 2001 From: zhousha <736730048@qq.com> Date: Tue, 29 Sep 2026 16:01:24 +0800 Subject: [PATCH] Add BI-150 vLLM image and ModelHub release workflow --- .dockerignore | 2 + .gitea/workflows/docker-build-push.yml | 132 +++++++++++++++++++++++++ .gitea/workflows/task_info.env | 3 + Dockerfile | 4 + README.md | 64 ++++++++++++ 5 files changed, 205 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitea/workflows/docker-build-push.yml create mode 100644 .gitea/workflows/task_info.env create mode 100644 Dockerfile create mode 100644 README.md diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..4d9b1a2 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +** +!Dockerfile diff --git a/.gitea/workflows/docker-build-push.yml b/.gitea/workflows/docker-build-push.yml new file mode 100644 index 0000000..9c5c285 --- /dev/null +++ b/.gitea/workflows/docker-build-push.yml @@ -0,0 +1,132 @@ +name: Docker Build and Push + +on: + push: + tags: + - "v*" + +jobs: + docker: + runs-on: amd64-ubuntu-24.04 + + steps: + - name: Clone repository + run: | + git clone "${{ gitea.server_url }}/${{ gitea.repository }}.git" . + git checkout "${{ gitea.ref_name }}" + + - name: Set image metadata + run: | + IMAGE_NAME="$(echo "${{ gitea.repository }}" | tr '[:upper:]' '[:lower:]' | tr '_' '-')" + IMAGE="${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${{ gitea.ref_name }}" + + echo "IMAGE_NAME=${IMAGE_NAME}" >> "$GITEA_ENV" + echo "IMAGE=${IMAGE}" >> "$GITEA_ENV" + + - name: Load and Validate Task Info + run: | + set -a + . .gitea/workflows/task_info.env + set +a + + for name in FRAMEWORK GPU_TYPE TASK_TYPE; do + eval "value=\${${name}:-}" + if [ "$name" = "FRAMEWORK" ] && [ -z "$value" ]; then + echo "${name} is empty in .gitea/workflows/task_info.env" + exit 1 + fi + + echo "${name}=${value}" >> "$GITEA_ENV" + done + + - name: Validate Image Verify Metadata + run: | + if [ -z "${FIXED_TOKEN:-}" ]; then + echo "FIXED_TOKEN is not configured on runner" + exit 1 + fi + + if ! response="$(curl --silent --show-error --location --get 'https://modelhub.org.cn/adminApi/image-verify/validate' \ + --header "Xc-Token: ${FIXED_TOKEN}" \ + --data-urlencode "gpuType=${GPU_TYPE:-}" \ + --data-urlencode "taskType=${TASK_TYPE:-}")"; then + echo "failed to call image verify validate API" + exit 1 + fi + + VALIDATE_RESPONSE="$response" python3 - <<'PY' + import json + import os + import sys + + raw = os.environ.get("VALIDATE_RESPONSE", "") + try: + body = json.loads(raw) + except json.JSONDecodeError: + print("image verify validate API returned invalid JSON") + print(raw) + sys.exit(1) + + if body.get("code") == 0 and body.get("data") is True: + print("image verify metadata validation passed") + sys.exit(0) + + message = body.get("message") or "unknown error" + print(f"image verify metadata validation failed: {message}") + print(raw) + sys.exit(1) + PY + + - name: Login to Docker Registry + run: | + echo "$DOCKER_PASSWORD" | docker login "$DOCKER_REGISTRY" \ + -u "$DOCKER_USERNAME" \ + --password-stdin + + - name: Build Docker Image + run: | + docker build -t "$IMAGE" . + + - name: Push Docker Image + run: | + for attempt in 1 2 3; do + echo "Starting docker push attempt ${attempt}/3 for ${IMAGE}" + docker push "$IMAGE" & + PUSH_PID=$! + + while kill -0 "$PUSH_PID" 2>/dev/null; do + echo "docker push is still running at $(date -u '+%Y-%m-%dT%H:%M:%SZ')" + sleep 60 + done + + if wait "$PUSH_PID"; then + echo "docker push completed successfully" + exit 0 + fi + + echo "docker push failed on attempt ${attempt}/3" + sleep 30 + done + + echo "docker push failed after 3 attempts" + exit 1 + + - name: Notify Image Verify + run: | + if [ -z "${FIXED_TOKEN:-}" ]; then + echo "FIXED_TOKEN is not configured on runner" + exit 1 + fi + + curl --silent --show-error --fail-with-body --location --request POST 'https://modelhub.org.cn//adminApi/image-verify' \ + --header "Xc-Token: ${FIXED_TOKEN}" \ + --header 'Content-Type: application/json' \ + --data-raw "{ + \"framework\": \"${FRAMEWORK}\", + \"gpuType\": \"${GPU_TYPE}\", + \"imageUrl\": \"${IMAGE}\", + \"taskType\": \"${TASK_TYPE}\", + \"createBy\": \"${{ gitea.actor }}\", + \"repoUrl\": \"${{ gitea.server_url }}/${{ gitea.repository }}\", + \"tag\": \"${{ github.ref_name }}\" + }" diff --git a/.gitea/workflows/task_info.env b/.gitea/workflows/task_info.env new file mode 100644 index 0000000..632ab2c --- /dev/null +++ b/.gitea/workflows/task_info.env @@ -0,0 +1,3 @@ +FRAMEWORK=vllm +GPU_TYPE="Iluvatar_bi-150" +TASK_TYPE=text-generation diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e2f9023 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +FROM registry.iluvatar.com.cn:10443/customer/sz/vllm0.17.0-4.4.0-x86:v7 + +# Preserve the vendor runtime used in the validated BI-150 deployment. +CMD ["/bin/bash"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..9166127 --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +# Step-3.5-Flash 天垓150部署 + +基于用户已验证的天数镜像: +`registry.iluvatar.com.cn:10443/customer/sz/vllm0.17.0-4.4.0-x86:v7`。 +使用 16 张卡,TP=8、PP=2。镜像不包含模型权重。 + +## ModelHub 发布 + +CI 配置沿用 https://dev.modelhub.org.cn/4pdadmin/cicd_demo。 +推送 `v*` 标签后自动构建、推送镜像并提交审核。 +GPU 分类采用 demo 的 `Iluvatar_bi-150`,由平台接口校验。 +Runner 使用 amd64-ubuntu-24.04,需能访问并拉取上述天数基础镜像。 +推送凭据和审核令牌由 runner 提供,不写入仓库。 + +## 模型配置准备 + +模型目录:`/mnt/disk0/stepfun-ai/Step-3.5-Flash`。 +在用户原部署中,`num_hidden_layers=45`,但以下数组各有48项, +引发层数校验失败:`layer_types`、`rope_theta`、 +`partial_rotary_factors`、`swiglu_limits`、`swiglu_limits_shared`。 + +原部署的处理方式是先备份 config.json,再将这些数组保留前45项。 +该操作修改宿主机挂载的模型配置,并未修改容器镜像。 +本镜像不会自动修改外部模型文件;部署时使用已验证的45项配置。 +如果换用其他版本权重,应先核对配置和权重结构,不应盲目截断。 + +## 创建容器 + +将 STEP_IMAGE 设置为 CI 日志中实际推送成功的镜像地址,然后执行: + +```bash +docker run -dit -v /usr/src:/usr/src -v /lib/modules:/lib/modules -v /dev:/dev \ + -v /home:/home -v /mnt/disk0:/mnt/disk0 \ + --network=host --name=step3p5-flash --ipc=host --privileged --cap-add=ALL --pid=host \ + "${STEP_IMAGE:?请先设置CI产出的镜像地址}" /bin/bash +``` + +## 启动服务 + +```bash +docker exec -it step3p5-flash bash -c ' +export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 +vllm serve /mnt/disk0/stepfun-ai/Step-3.5-Flash \ + --served-model-name step3p5-flash \ + --host 0.0.0.0 --port 1237 \ + --tensor-parallel-size 8 \ + --pipeline-parallel-size 2 \ + --disable-cascade-attn \ + --trust-remote-code \ + --gpu-memory-utilization 0.92 \ + --max-model-len 8192' +``` + +原部署中 corex MoE 算子要求切分后的中间维度为32的倍数。 +1280/16=80不满足要求,1280/8=160满足要求,因此采用TP=8、PP=2。 +各流水线阶段的显存占用取决于实际层分配,不保证各卡相等。 + +## 验证 + +```bash +curl -sS http://127.0.0.1:1237/v1/chat/completions \ + -H 'Content-Type: application/json' \ + -d '{"model":"step3p5-flash","messages":[{"role":"user","content":"请介绍一下人工智能"}],"temperature":0.7,"top_p":0.9,"max_tokens":1024}' +```