TEI 降级 bge-base:N97 上 CPU 从 94% 压回 80%
NAS 上用 TEI 做中文嵌入,批量任务一跑 CPU 就是 85–94%,别的容器被饿死、任务直接失败。
把模型从 bge-large 降到 bge-base,再留一个核给系统,TEI 峰值回到 70–80%。
代价写在最前面:维度从 1024 降到 768,已有向量库必须全量重建,新旧不能混用。
开始之前
要不要降这一档
只有一种情况该降:批量任务把 CPU 打到 90% 以上,同一台机器上别的容器开始超时或失败。降档换来的是稳定,不是速度。
CPU 还有余量就别动。bge-large 在近义去重、术语歧义这类细粒度区分上确实更准,降到 base 会丢掉这部分。
重灌向量的成本也要先算进去:文本越多越贵,而且中途新旧维度混在一起会直接报写入失败。
硬件与版本
实测机器是极空间 Z4 Pro,Intel N97,四核四线程、没有 AVX-512。四线程这个数字决定了后面每一个参数。
镜像用 ghcr.io/huggingface/text-embeddings-inference:cpu-1.9,模型 bge-base-zh-v1.5,输出 768 维。
先定好这几个值
下面命令和配置里出现的占位符,先想好各自换成什么:
| 占位符 | 换成什么 |
|---|---|
/path/to/tei-project | 放 docker-compose.yml 的目录 |
tei.example.com | 给这个服务用的域名;不走反代就把 traefik 那几行标签删掉 |
traefik-net | 反代所在的 docker 网络名 |
| 向量库集合名 | 实际的 collection / 表名,第四步要清空它 |
一、下载 bge-base 模型
在宿主机上进项目目录,两种方式选一种:
cd /path/to/tei-project
# 方式 A:git(需要 git-lfs)git lfs installgit clone https://huggingface.co/BAAI/bge-base-zh-v1.5 ./models/bge-base-zh-v1.5
# 方式 B:huggingface-cli(推荐,断点续传更稳)pip install -U "huggingface_hub[cli]"huggingface-cli download BAAI/bge-base-zh-v1.5 \ --local-dir ./models/bge-base-zh-v1.5 \ --local-dir-use-symlinks False国内拉得慢就先设镜像再走方式 B:
export HF_ENDPOINT=https://hf-mirror.com下载完确认这几个文件在:
ls -lh ./models/bge-base-zh-v1.5# 至少要有 config.json、model.safetensors(或 pytorch_model.bin)、tokenizer.json二、改 docker-compose.yml
只有模型路径、名称和性能参数变了,网络和标签结构不动:
services: tei-embedding: image: ghcr.io/huggingface/text-embeddings-inference:cpu-1.9 container_name: tei-embedding restart: unless-stopped volumes: - ./models/bge-base-zh-v1.5:/data/model:ro command: - --model-id - /data/model - --served-model-name - bge-base-zh-v1.5 - --port - "80" - --max-concurrent-requests - "48" - --max-client-batch-size - "16" - --max-batch-tokens - "4096" - --tokenization-workers - "2" environment: - RUST_LOG=warn - OMP_NUM_THREADS=3 - RAYON_NUM_THREADS=3 deploy: resources: limits: { cpus: '3.0', memory: 4G } reservations: { cpus: '1.0', memory: 1G } networks: - traefik-net labels: - "com.centurylinklabs.watchtower.enable=false" # 原来有 traefik 路由标签的话按需加回: # - "traefik.enable=true" # - "traefik.http.routers.tei.rule=Host(`tei.example.com`)" # - "traefik.http.services.tei.loadbalancer.server.port=80"
networks: traefik-net: external: true参数说明:N97 四核上怎么分
| 参数 | 值 | 为什么 |
|---|---|---|
OMP_NUM_THREADS / RAYON_NUM_THREADS | 3 | 限制计算线程,永远留一个核给系统和反代——这条是止住任务失败的关键 |
cpus | 3.0 | 硬上限,和上面的线程数呼应,两处都要写 |
max-concurrent-requests | 48 | base 更轻,能比 large 承受更高并发;超出直接返回 429,而不是排队到超时 |
max-batch-tokens | 4096 | bge 的上下文只有 512,批再大也用不上,而批越大单批延迟越高 |
memory | 4G | base 比 large 省内存,从 6G 降到 4G 够用 |
三、重启服务
docker compose pull # 可选,确保镜像最新docker compose up -ddocker logs -f tei-embedding # 看到 Ready / Starting HTTP server 就是起来了四、全量重建向量库
维度从 1024 变成 768,旧向量和新模型不兼容,这一步不能跳。
- 清空原向量库里这个模型产生的集合或表(Milvus / Qdrant / pgvector 按各自的方式操作)。
- 用新服务对全部历史文本重新生成向量并写回。
- 把库里的维度定义改成 768。
schema 里写死 1024 的话要先改 schema 再重灌,否则写入会报维度不匹配。
五、验证三件事
健康检查:
curl http://tei-embedding:80/health# 走反代: curl https://tei.example.com/health生成一条向量,确认维度是 768:
curl -s http://tei-embedding:80/embed \ -H 'Content-Type: application/json' \ -d '{"inputs":"痛苦往往源于见多识广后的欲望膨胀,能平静管理欲望的人才真正快乐。"}' \ | python3 -c "import sys,json;v=json.load(sys.stdin);print('dim =',len(v[0]))"# 期望: dim = 768盯一眼 CPU:
docker stats tei-embedding批量任务跑起来时应该稳定在 3 核以内,整机峰值 70–80%,不再打到 94%,别的容器也不会被饿死。三条都对上,到这里已经能用了。
可选:回滚到 large
volumes 和 --served-model-name 改回 bge-large-zh-v1.5,cpus 仍然保持 3.0,max-batch-tokens 降到 2048。
⚠️ 回滚同样要重灌向量库,维度回到 1024。换模型这件事没有单向的便宜路。
几个选择的理由
为什么是 base,不是 small 也不是 large
本场景是观点、金句、研报片段的主题级语义检索,不需要区分近义词。三档的取舍:
| 模型 | 维度 | 什么时候用 | 代价 |
|---|---|---|---|
| bge-small-zh-v1.5 | 512 | 文本普遍不到 200 字,而且 base 还嫌慢 | 主题级检索也开始丢细节 |
| bge-base-zh-v1.5 | 768 | 主题级语义检索,也就是本场景 | 近义词、术语歧义分不开 |
| bge-large-zh-v1.5 | 1024 | 需要近义去重、区分术语歧义 | N97 这种小主机上 CPU 常态打满 |
选中间那档是因为丢掉的正好是用不上的能力:本场景从来不需要判断两句话是不是近义。
为什么一定要留一个核
TEI 默认按可用核数开线程,四核机器上等于全占,系统和反代就没有 CPU 可用。表现不是「慢一点」,而是请求超时、容器被判不健康。
真正把任务失败止住的是留核这一步,换模型只是让同样的负载更轻。
高精度排序该用 reranker
以后要做金句去重这类需要细粒度区分的事,用独立的 reranker 做二次精排。不必为此让嵌入服务常态高负载——精排只作用在召回回来的少量候选上。
同一台 NAS 上服务多了以后还有一堆约定要守,那些写在在 NAS 上用 Coolify 部署自建服务:十条约定里。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!


