根本原因是默认float32加载大模型致显存溢出;应改用float16、禁用padding预分配、分批处理;相似度不准因归一化重复或模型不一致;部署需单例加载、启用fast tokenizer;windows下慎用torch.compile,优先onnx+cpu推理。

模型加载慢、显存爆掉,model.encode() 卡住不动
根本原因不是代码写错了,而是默认用 torch.float32 加载 500MB+ 的模型(比如 sentence-transformers/all-MiniLM-L6-v2),显存吃满后触发 CPU 回退或 OOM。别急着换显卡,先改加载方式。
- 强制用
torch.float16:加参数device='cuda',torch_dtype=torch.float16(注意不是fp16=True,那个只影响推理,不缩模型权重) - 禁用 tokenizer 的 padding 预分配:传
tokenizer_kwargs={'padding': False, 'truncation': True},否则 batch 大时内存翻倍 - 小批量处理:别一次性
encode(list_of_10000_texts),拆成每批 64 或 128 条,用batch_size=64参数控制
搜索结果不准,cos_sim() 返回的相似度全在 0.8 以上
不是模型不行,是文本预处理和向量归一化没对齐。Sentence-Transformers 的 encode() 默认已做 L2 归一化,但很多人自己算余弦相似度时又手动归一,导致数值失真。
- 直接用库里的
util.cos_sim(),别手写np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)) - query 和 doc 必须用同一个模型 encode,别 query 用
all-MiniLM-L6-v2,doc 用multi-qa-MiniLM-L6-dot-v1—— 向量空间不兼容,相似度无意义 - 中文文本务必确认 tokenizer 是否支持:比如
all-MiniLM-L6-v2是多语言但非中文特化,遇到“微信”“支付宝”这类词嵌入偏弱,可换paraphrase-multilingual-MiniLM-L12-v2
Docker 部署后 API 响应延迟高,curl 测出来首字节要 2s+
核心瓶颈常在模型首次加载 —— 每个请求都走一遍 SentenceTransformer(...),而不是复用实例。FastAPI/Flask 里别把 model 当局部变量。
- 全局单例加载:在模块顶层 or
app.on_event("startup")里初始化 model,确保只 load 一次 - 关闭 tokenizer 的 slow tokenizers:加
use_fast=True到 model 初始化参数,否则 Hugging Face 的 slow tokenizer 会拖慢首条请求 300ms+ - 验证是否真缓存:启动后立刻发一条请求,再
time curl http://localhost:8000/search?q=test,第二次响应应 ≤200ms;如果还是慢,检查是否误写了model = SentenceTransformer(...)在 route 函数里
Windows 下 torch.compile() 报错或无效
torch.compile() 在 Windows 上目前仅支持 CUDA 12.1+ 且需 nightly 版本 PyTorch,生产环境别硬上。更稳的提速方案是提前编译推理图 + 关闭梯度。
立即学习“Python免费学习笔记(深入)”;
- 部署前加
model.eval()和torch.no_grad()(后者必须显式写,不能只靠 eval) - 用
torch.jit.script(model)编译(注意:只支持部分模型结构,all-MiniLM-L6-v2可行;若报错就跳过) - Windows 用户优先用
onnxruntime:导出 ONNX 后用 CPU 推理,比原生 torch 快 1.5–2x,且无平台兼容问题
最易被忽略的是:模型路径含中文或空格时,SentenceTransformer() 在 Windows 下可能静默失败,日志里也不报错 —— 改用绝对路径并确保全是 ASCII 字符。










