from sentence_transformers import CrossEncoder
# 原始HF格式的Qwen3-Reranker路径
src_model = "/PATH/models/Qwen/Qwen3-Reranker-4B-HF"
# 目标保存路径(sentence-transformers结构)
dst_model = "/PATH/models/Qwen/Qwen3-Reranker-4B"
# 加载HuggingFace格式模型
print(f"Loading HF model from {src_model} ...")
model = CrossEncoder(src_model)
# 保存为sentence-transformers结构
print(f"Saving as sentence-transformers CrossEncoder to {dst_model} ...")
model.save(dst_model)
print("✅ Done! You can now mount this folder to TEI and call /rerank")
2、缺少pad_token pad_token.py
from transformers import AutoTokenizer
import sys
import os
# 默认模型路径
default_model_path = "/PATH/models/Qwen/Qwen3-Reranker-4B"
# 获取模型路径,支持命令行传参,没传就用默认路径
if len(sys.argv) == 2:
model_path = sys.argv[1]
else:
model_path = default_model_path
print(f"未传入模型目录,使用默认路径: {model_path}")
if not os.path.isdir(model_path):
print(f"错误: 模型目录不存在: {model_path}")
sys.exit(1)
print(f"正在修复模型目录: {model_path}")
tokenizer = AutoTokenizer.from_pretrained(model_path)
# 如果没有 pad_token,则用 eos_token 作为 pad
if tokenizer.pad_token is None:
print(f"未检测到 pad_token,使用 eos_token 作为 pad_token: {tokenizer.eos_token}")
tokenizer.pad_token = tokenizer.eos_token
else:
print(f"已存在 pad_token: {tokenizer.pad_token}")
# 如果 pad_token_id 为空,则设置为 eos_token_id
if tokenizer.pad_token_id is None:
tokenizer.pad_token_id = tokenizer.eos_token_id
print(f"设置 pad_token_id = eos_token_id: {tokenizer.pad_token_id}")
else:
print(f"已存在 pad_token_id: {tokenizer.pad_token_id}")
# 保存修改
tokenizer.save_pretrained(model_path)
print("✅ 修复完成,已保存到模型目录。")
huggingface tei 还没说支持 qwen3-reranker,华为msi-tei就说支持了:https://www.hiascend.com/developer/ascendhub/detail/07a016975cc341f3a5ae131f2b52399d
之前部署qwen3-embedding 确实没啥问题,这次部署qwen3-reranker各种坑,我记录下处理的过程。
1、HF模型转换成ST模型 convert_to_st.py
from sentence_transformers import CrossEncoder # 原始HF格式的Qwen3-Reranker路径 src_model = "/PATH/models/Qwen/Qwen3-Reranker-4B-HF" # 目标保存路径(sentence-transformers结构) dst_model = "/PATH/models/Qwen/Qwen3-Reranker-4B" # 加载HuggingFace格式模型 print(f"Loading HF model from {src_model} ...") model = CrossEncoder(src_model) # 保存为sentence-transformers结构 print(f"Saving as sentence-transformers CrossEncoder to {dst_model} ...") model.save(dst_model) print("✅ Done! You can now mount this folder to TEI and call /rerank")2、缺少pad_token pad_token.py
from transformers import AutoTokenizer import sys import os # 默认模型路径 default_model_path = "/PATH/models/Qwen/Qwen3-Reranker-4B" # 获取模型路径,支持命令行传参,没传就用默认路径 if len(sys.argv) == 2: model_path = sys.argv[1] else: model_path = default_model_path print(f"未传入模型目录,使用默认路径: {model_path}") if not os.path.isdir(model_path): print(f"错误: 模型目录不存在: {model_path}") sys.exit(1) print(f"正在修复模型目录: {model_path}") tokenizer = AutoTokenizer.from_pretrained(model_path) # 如果没有 pad_token,则用 eos_token 作为 pad if tokenizer.pad_token is None: print(f"未检测到 pad_token,使用 eos_token 作为 pad_token: {tokenizer.eos_token}") tokenizer.pad_token = tokenizer.eos_token else: print(f"已存在 pad_token: {tokenizer.pad_token}") # 如果 pad_token_id 为空,则设置为 eos_token_id if tokenizer.pad_token_id is None: tokenizer.pad_token_id = tokenizer.eos_token_id print(f"设置 pad_token_id = eos_token_id: {tokenizer.pad_token_id}") else: print(f"已存在 pad_token_id: {tokenizer.pad_token_id}") # 保存修改 tokenizer.save_pretrained(model_path) print("✅ 修复完成,已保存到模型目录。")3、缺少 sentence_bert_config.json 文件
{ "pooling_mode_cls_token": false, "pooling_mode_mean_tokens": false, "pooling_mode_max_tokens": false, "pooling_mode_mean_sqrt_len_tokens": false, "pooling_mode_weightedmean_tokens": false, "pooling_mode_lasttoken": true, "word_embedding_dimension": 2560, "max_seq_length": 5120 }4、config.json 加入 "pad_token_id": 151643,
{ "architectures": [ "Qwen3ForSequenceClassification" ], "attention_bias": false, "attention_dropout": 0.0, "bos_token_id": 151643, "eos_token_id": 151645, "pad_token_id": 151643, "head_dim": 128, "hidden_act": "silu", "hidden_size": 2560, "id2label": { "0": "LABEL_0" }, "initializer_range": 0.02, "intermediate_size": 9728, "label2id": { "LABEL_0": 0 }, "layer_types": [ "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention", "full_attention" ], "max_position_embeddings": 40960, "max_window_layers": 36, "model_type": "qwen3", "num_attention_heads": 32, "num_hidden_layers": 36, "num_key_value_heads": 8, "rms_norm_eps": 1e-06, "rope_scaling": null, "rope_theta": 1000000, "sentence_transformers": { "activation_fn": "torch.nn.modules.activation.Sigmoid", "version": "5.1.0" }, "sliding_window": null, "tie_word_embeddings": true, "torch_dtype": "float32", "transformers_version": "4.53.3", "use_cache": true, "use_sliding_window": false, "vocab_size": 151669 }部署得比较粗糙,路径和参数调优自己改。
其他按照官方的启动就没什么问题了,华为官方说支持openai,看看有没有人说明下,怎么部署。
其他vllm-ascend部署方式,我这里有 https://www.hiascend.com/forum/thread-02115184822344490084-1-1.html