1. 引言:为什么选择离线部署

在当今AI技术快速发展的时代,许多企业面临着数据安全与合规性的严格要求,特别是在金融、医疗和政府等领域,离线部署AI模型成为刚需。本文将详细介绍如何利用Xinference框架在完全离线的环境中部署四种核心AI能力:文本嵌入(Embedding)、重排序(Reranker)、语音识别(STT)和语音合成(TTS)。

2. 方案概述

离线部署方案具有以下特点:

  • ​​全流程离线​​:服务部署完全脱离互联网;

  • ​​一键式部署​​:通过脚本自动化完成复杂配置;

  • ​​资源可控​​:精确分配GPU资源,避免冲突;

  • ​​模型灵活管理​​:支持按需插拔不同模型。

3. 准备工作

3.1 资源下载(联网机器)

首先需要在可联网的机器上准备所需资源:

?
1
2
3
4
5
6
7
8
9
10
11
拉取Xinference官方镜像
docker pull xprobe/xinference:latest
 
# 保存为离线包
docker save xprobe/xinference:latest -o xinference-image.tar
 
# 下载所需模型(登录魔塔,根据需求搜索模型,搜索后点击目标模型,右侧下载模型)
modelscope download --model maidalun/bce-embedding-base_v1
modelscope download --model maidalun/bce-reranker-base_v1
modelscope download --model iic/CosyVoice-300M
modelscope download --model iic/SenseVoiceSmall

模型会默认下载到/root/.cache/modelscope/hub/models/路径下:

?
1
2
3
4
├── iic/CosyVoice-300M
├── iic/SenseVoiceSmall
├── maidalun/bce-embedding-base_v1
└── maidalun/bce-reranker-base_v1

3.2 离线包目录结构规划

?
1
2
3
4
5
6
7
8
9
10
11
model_services/
├── docker/
│   ├── images/xinference-image.tar
│   └── docker-compose.yaml
├── models/
│   ├── bce-embedding-base_v1
│   ├── bce-reranker-base_v1
│   ├── CosyVoice-300M
│   └── SenseVoiceSmall
├── config.ini
└── install.sh 

3.2.1. 配置文件(config.ini)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[XINFERENCE]
# 指定Xinference服务可用的GPU设备ID(逗号分隔多个ID,如"0,1")
# 注意:实际GPU编号需与服务器物理设备一致,可通过`nvidia-smi -L`查看
XINFERENCE_GPUS="0,1" 
# 模型挂载路径
MODELS_VOLUMES_DIRECTORY=/data/docker_models
 
[EMBEDDING]
# 是否启用嵌入模型自动安装(true/true)
EMBEDDING_INSTALL_ENABLE=true
# 嵌入模型运行时绑定的GPU设备编号
# 必须存在于XINFERENCE_GPUS定义的可用设备列表中
# 示例:若XINFERENCE_GPUS="1",则此处只能填1
EMBEDDING_GPU=0
 
[RERANKER]
# 是否启用重排序模型自动安装(true/true)
RERANKER_INSTALL_ENABLE=true
# 重排序模型绑定的GPU设备编号
# 需与XINFERENCE_GPUS定义的设备一致
RERANKER_GPU=0
 
[TTS]
# 是否启用语音合成(TTS)模型安装(true/true)
TTS_INSTALL_ENABLE=true
# TTS模型绑定的GPU设备编号
# 若与嵌入模型共用GPU,需确保总显存不超限
TTS_GPU=0
 
[STT]
# 是否启用语音识别(STT)模型安装(true/true)
STT_INSTALL_ENABLE=true
# STT模型绑定的GPU设备编号
# 语音识别通常需要更多显存,建议独占GPU
STT_GPU=1

关键配置说明​​:

  • GPU分配策略:语音识别模型通常需要更多显存,建议独占GPU

  • 模型路径:确保容器内外的路径映射正确

  • 启用标志:可灵活控制哪些模型需要加载

3.2.2. Docker编排文件(docker-compose.yaml)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
version: "3.3"
 
services:
   xinference:
     image: xprobe/xinference:latest
     container_name: xinference
     restart: unless-stopped
     command: ["xinference-local", "-H", "0.0.0.0"]  # 启动命令
     ports:
       - "9997:9997"  # 默认API端口
     healthcheck:
       test: ["CMD", "curl", "-f", "http://localhost:9997"]
       interval: 10s
       timeout: 5s
       retries: 10
       start_period: 30s
     environment:
       - XINFERENCE_GPUS=${XINFERENCE_GPUS:-"0"}  # 从环境变量读取GPU ID,默认使用GPU 0
     volumes:
       - ${MODELS_VOLUMES_DIRECTORY}:/root/.xinference/models  # 模型数据持久化
     deploy:
       resources:
         reservations:
           devices:
             - driver: nvidia
               capabilities: [gpu]
               device_ids: ["0,1"]  

3.2.3. 自动化部署脚本

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#! /bin/bash
#-----------------------------------------------------------
# 模型安装配置脚本
# 1.加载config.ini配置文件
# 2.拷贝模型文件到模型挂载路径
# 3.解压xinference镜像并运行xinference容器
# 4.加载模型
# 5.查看模型状态
#-----------------------------------------------------------
 
# 加载config.ini配置文件
while IFS= '=' read -r key value || [[ -n "$key" ]]; do
     # 修剪 key 和 value 的首尾空格和换行符
     key=$( echo "$key" | tr -d '\r\n' | xargs )
     value=$( echo "$value" | tr -d '\r\n' | xargs )
     # 跳过空行、注释行(以#开头)或段标记(如[section])
     if [[ "$key" = "" || "$key" =~ ^ # || "$key" =~ ^\[.*\] ]]; then
         continue
     fi
     export "$key=$value"
done < config.ini
 
# 创建并验证目标目录
if [ ! -d "${MODELS_VOLUMES_DIRECTORY}" ]; then
     echo "创建模型目录: ${MODELS_VOLUMES_DIRECTORY}"
     mkdir -p "${MODELS_VOLUMES_DIRECTORY}" || {
     echo "错误:无法创建目录 ${MODELS_VOLUMES_DIRECTORY}"
         exit 1
     }
fi
 
# 拷贝模型文件到模型挂载路径
#cp -r models/* ${MODELS_VOLUMES_DIRECTORY}
 
# 解压xinference容器镜像
#docker load < docker/images/xinference-image.tar
 
# 运行xinference容器
docker-compose -f . /docker/docker-compose .yaml up -d
while true ; do
   status=$(docker inspect -- format = '{{.State.Health.Status}}' xinference)
   if [ "$status" = "healthy" ]; then
     break
   fi
   echo "等待Xinference健康状态... 当前状态: $status"
   sleep 10
done
 
echo "加载模型"
 
# 函数:检查模型是否已注册
function is_model_registered() {
     local model_name= "$1"
     docker exec xinference xinference list | grep -q "$model_name"
}
 
if [[ "${EMBEDDING_INSTALL_ENABLE}" = "true" ]] ; then
     MODEL_NAME= "bce-embedding-base_v1"
     MODEL_TYPE= "embedding"
 
     if ! is_model_registered "$MODEL_NAME" ; then
         echo "启动嵌入模型: ${MODEL_NAME}"
         docker exec xinference xinference launch \
             --model-name "$MODEL_NAME" \
             --model- type "$MODEL_TYPE" \
         --model-path "/root/.xinference/models/${MODEL_NAME}" \
             --gpu-idx "$EMBEDDING_GPU"
     fi
 
fi
 
if [[ "${RERANKER_INSTALL_ENABLE}" = "true" ]] ; then
     MODEL_NAME= "bce-reranker-base_v1"
     MODEL_TYPE= "rerank"
 
     if ! is_model_registered "$MODEL_NAME" ; then
         echo "加载重排序模型: ${MODEL_NAME}"
         docker exec xinference xinference launch \
             --model-name "$MODEL_NAME" \
             --model- type "$MODEL_TYPE" \
         --model-path "/root/.xinference/models/${MODEL_NAME}" \
             --gpu-idx "$RERANKER_GPU"
     fi
fi
 
if [[ "${TTS_INSTALL_ENABLE}" = "true" ]] ; then
     MODEL_NAME= "CosyVoice-300M"
     MODEL_TYPE= "audio"
 
     if ! is_model_registered "$MODEL_NAME" ; then
         echo "加载TTS模型: ${MODEL_NAME}"
         docker exec xinference xinference launch \
             --model-name "$MODEL_NAME" \
             --model- type "$MODEL_TYPE" \
         --model-path "/root/.xinference/models/${MODEL_NAME}" \
             --gpu-idx "$TTS_GPU"
     fi
fi
 
if [[ "${STT_INSTALL_ENABLE}" = "true" ]]; then
     MODEL_NAME= "SenseVoiceSmall"
     MODEL_TYPE= "audio"
 
     if ! is_model_registered "$MODEL_NAME" ; then
         echo "加载STT模型: ${MODEL_NAME}"
         docker exec xinference xinference launch \
             --model-name "$MODEL_NAME" \
             --model- type "$MODEL_TYPE" \
         --model-path "/root/.xinference/models/${MODEL_NAME}" \
             --gpu-idx "$STT_GPU"
     fi
     
fi
 
echo "查看模型状态"
docker exec xinference xinference list
 
echo "完成模型注册"

3.2.4 压缩离线包

?
1
tar -czvf model_services. tar .gz model_services

4. 离线服务器部署步骤

4.1 前提条件

确保服务器已安装配置好docker、docker-compose并配置好nvidia-container-runtime。

4.2 传输资源包​​

?
1
scp model_services. tar .gz user@offline-server: /data/

4.3 解压资源

?
1
tar -xzvf model_services. tar .gz -C /data/

4.4 ​​修改配置​​

根据实际服务器GPU情况调整config.ini中的设备分配。

注意: xinference上加载的模型并不支持配置显存。

​​执行部署​​:

?
1
2
3
cd /data/model_services
chmod +x install .sh
. /install .sh

脚本执行日志:

5. 服务验证与测试

5.1 基础检查

?
1
2
3
4
5
# 检查容器状态
docker ps | grep xinference
 
# 查看模型列表
docker exec xinference xinference list

5.2 API接口测试

文本嵌入测试​​:

?
1
2
3
curl -X POST "http://localhost:9997/v1/embeddings" \
   -H "Content-Type: application/json" \
   -d '{"model": "bce-embedding-base_v1", "input": "测试文本"}'

5.3 xinference图形化界面测试

点击语音识别模型行Actions按钮,测试语音识别:

6、总结

通过本文介绍的方案,企业可以在完全离线的环境中快速部署一套功能完整的AI能力平台。该方案不仅保证了数据的安全性,还通过灵活的配置满足了不同场景的需求。Xinference框架的轻量级特性使其成为离线部署的理想选择,而我们的自动化脚本则大大降低了部署复杂度。

未来,随着模型技术的进步,我们可以通过同样的方式无缝升级模型版本,持续提升业务系统的AI能力,而无需改变整体架构。

原创作者: zhangmingcheng 转载于: https://www.cnblogs.com/zhangmingcheng/p/18989096
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐