添加 rerank 和 embedding模型支持,并且添加 onnx 模型

This commit is contained in:
273265088@qq.com
2026-03-24 16:18:39 +08:00
parent 77b244e53e
commit b8d8732c3d
28 changed files with 2130 additions and 158 deletions
+299 -2
View File
@@ -15,6 +15,8 @@ pub mod qwen2_5vl;
pub mod qwen3;
pub mod qwen3_5;
pub mod qwen3_asr;
pub mod qwen3_embedding;
pub mod qwen3_reranker;
pub mod qwen3vl;
pub mod rmbg2_0;
pub mod voxcpm;
@@ -33,10 +35,18 @@ use crate::models::{
hunyuan_ocr::generate::HunyuanOCRGenerateModel, minicpm4::generate::MiniCPMGenerateModel,
paddleocr_vl::generate::PaddleOCRVLGenerateModel, qwen2_5vl::generate::Qwen2_5VLGenerateModel,
qwen3::generate::Qwen3GenerateModel, qwen3_5::generate::Qwen3_5GenerateModel,
qwen3_asr::generate::Qwen3AsrGenerateModel, qwen3vl::generate::Qwen3VLGenerateModel,
qwen3_asr::generate::Qwen3AsrGenerateModel, qwen3_embedding::generate::Qwen3EmbeddingModel,
qwen3_reranker::generate::Qwen3RerankerModel, qwen3vl::generate::Qwen3VLGenerateModel,
rmbg2_0::generate::RMBG2_0Model, voxcpm::generate::VoxCPMGenerate,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ModelArtifactFormat {
Safetensors,
Gguf,
Onnx,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, clap::ValueEnum)]
pub enum WhichModel {
#[value(name = "minicpm4-0.5b", hide = true)]
@@ -47,6 +57,18 @@ pub enum WhichModel {
Qwen2_5vl7B,
#[value(name = "qwen3-0.6b", hide = true)]
Qwen3_0_6B,
#[value(name = "qwen3-embedding-0.6b", hide = true)]
Qwen3Embedding0_6B,
#[value(name = "qwen3-embedding-4b", hide = true)]
Qwen3Embedding4B,
#[value(name = "qwen3-embedding-8b", hide = true)]
Qwen3Embedding8B,
#[value(name = "qwen3-reranker-0.6b", hide = true)]
Qwen3Reranker0_6B,
#[value(name = "qwen3-reranker-4b", hide = true)]
Qwen3Reranker4B,
#[value(name = "qwen3-reranker-8b", hide = true)]
Qwen3Reranker8B,
#[value(name = "qwen3.5-0.8b", hide = true)]
Qwen3_5_0_8B,
#[value(name = "qwen3.5-2b", hide = true)]
@@ -55,8 +77,35 @@ pub enum WhichModel {
Qwen3_5_4B,
#[value(name = "qwen3.5-9b", hide = true)]
Qwen3_5_9B,
#[value(
name = "qwen3.5-9b-claude-4.6-opus-reasoning-distilled-v2",
hide = true
)]
Qwen3_5_9BClaude46OpusReasoningDistilledV2,
#[value(name = "qwen3.5-gguf", hide = true)]
Qwen3_5Gguf,
#[value(
name = "qwen3.5-4b-claude-4.6-opus-reasoning-distilled-v2-gguf",
hide = true
)]
Qwen3_5_4BClaude46OpusReasoningDistilledV2Gguf,
#[value(
name = "qwen3.5-9b-claude-4.6-opus-reasoning-distilled-v2-gguf",
hide = true
)]
Qwen3_5_9BClaude46OpusReasoningDistilledV2Gguf,
#[value(name = "qwen3.5-0.8b-unsloth-gguf", hide = true)]
Qwen3_5_0_8BUnslothGguf,
#[value(name = "qwen3.5-2b-unsloth-gguf", hide = true)]
Qwen3_5_2BUnslothGguf,
#[value(name = "qwen3.5-4b-unsloth-gguf", hide = true)]
Qwen3_5_4BUnslothGguf,
#[value(name = "qwen3.5-0.8b-lmstudio-gguf", hide = true)]
Qwen3_5_0_8BLmstudioGguf,
#[value(name = "qwen3.5-2b-lmstudio-gguf", hide = true)]
Qwen3_5_2BLmstudioGguf,
#[value(name = "qwen3.5-4b-lmstudio-gguf", hide = true)]
Qwen3_5_4BLmstudioGguf,
#[value(name = "qwen3asr-0.6b", hide = true)]
Qwen3ASR0_6B,
#[value(name = "qwen3asr-1.7b", hide = true)]
@@ -93,7 +142,165 @@ pub enum WhichModel {
GlmOCR,
}
pub const LISTED_MODELS: &[WhichModel] = &[
WhichModel::MiniCPM4_0_5B,
WhichModel::Qwen2_5vl3B,
WhichModel::Qwen2_5vl7B,
WhichModel::Qwen3_0_6B,
WhichModel::Qwen3Embedding0_6B,
WhichModel::Qwen3Embedding4B,
WhichModel::Qwen3Embedding8B,
WhichModel::Qwen3Reranker0_6B,
WhichModel::Qwen3Reranker4B,
WhichModel::Qwen3Reranker8B,
WhichModel::Qwen3_5_0_8B,
WhichModel::Qwen3_5_2B,
WhichModel::Qwen3_5_4B,
WhichModel::Qwen3_5_9B,
WhichModel::Qwen3_5_9BClaude46OpusReasoningDistilledV2,
WhichModel::Qwen3_5_4BClaude46OpusReasoningDistilledV2Gguf,
WhichModel::Qwen3_5_9BClaude46OpusReasoningDistilledV2Gguf,
WhichModel::Qwen3_5_0_8BUnslothGguf,
WhichModel::Qwen3_5_2BUnslothGguf,
WhichModel::Qwen3_5_4BUnslothGguf,
WhichModel::Qwen3_5_0_8BLmstudioGguf,
WhichModel::Qwen3_5_2BLmstudioGguf,
WhichModel::Qwen3_5_4BLmstudioGguf,
WhichModel::Qwen3ASR0_6B,
WhichModel::Qwen3ASR1_7B,
WhichModel::Qwen3vl2B,
WhichModel::Qwen3vl4B,
WhichModel::Qwen3vl8B,
WhichModel::Qwen3vl32B,
WhichModel::DeepSeekOCR,
WhichModel::DeepSeekOCR2,
WhichModel::HunyuanOCR,
WhichModel::PaddleOCRVL,
WhichModel::PaddleOCRVL1_5,
WhichModel::RMBG2_0,
WhichModel::VoxCPM,
WhichModel::VoxCPM1_5,
WhichModel::GlmASRNano2512,
WhichModel::FunASRNano2512,
WhichModel::GlmOCR,
];
impl WhichModel {
pub fn artifact_format(self) -> ModelArtifactFormat {
match self {
WhichModel::Qwen3_5Gguf
| WhichModel::Qwen3_5_4BClaude46OpusReasoningDistilledV2Gguf
| WhichModel::Qwen3_5_9BClaude46OpusReasoningDistilledV2Gguf
| WhichModel::Qwen3_5_0_8BUnslothGguf
| WhichModel::Qwen3_5_2BUnslothGguf
| WhichModel::Qwen3_5_4BUnslothGguf
| WhichModel::Qwen3_5_0_8BLmstudioGguf
| WhichModel::Qwen3_5_2BLmstudioGguf
| WhichModel::Qwen3_5_4BLmstudioGguf => ModelArtifactFormat::Gguf,
_ => ModelArtifactFormat::Safetensors,
}
}
pub fn is_download_managed(self) -> bool {
!matches!(
self.artifact_format(),
ModelArtifactFormat::Gguf | ModelArtifactFormat::Onnx
)
}
pub fn openai_model_id(self) -> &'static str {
match self {
WhichModel::MiniCPM4_0_5B => "minicpm4-0.5b",
WhichModel::Qwen2_5vl3B => "qwen2.5vl-3b",
WhichModel::Qwen2_5vl7B => "qwen2.5vl-7b",
WhichModel::Qwen3_0_6B => "qwen3-0.6b",
WhichModel::Qwen3Embedding0_6B => "qwen3-embedding-0.6b",
WhichModel::Qwen3Embedding4B => "qwen3-embedding-4b",
WhichModel::Qwen3Embedding8B => "qwen3-embedding-8b",
WhichModel::Qwen3Reranker0_6B => "qwen3-reranker-0.6b",
WhichModel::Qwen3Reranker4B => "qwen3-reranker-4b",
WhichModel::Qwen3Reranker8B => "qwen3-reranker-8b",
WhichModel::Qwen3_5_0_8B => "qwen3.5-0.8b",
WhichModel::Qwen3_5_2B => "qwen3.5-2b",
WhichModel::Qwen3_5_4B => "qwen3.5-4b",
WhichModel::Qwen3_5_9B => "qwen3.5-9b",
WhichModel::Qwen3_5_9BClaude46OpusReasoningDistilledV2 => {
"qwen3.5-9b-claude-4.6-opus-reasoning-distilled-v2"
}
WhichModel::Qwen3_5Gguf => "qwen3.5-gguf",
WhichModel::Qwen3_5_4BClaude46OpusReasoningDistilledV2Gguf => {
"qwen3.5-4b-claude-4.6-opus-reasoning-distilled-v2-gguf"
}
WhichModel::Qwen3_5_9BClaude46OpusReasoningDistilledV2Gguf => {
"qwen3.5-9b-claude-4.6-opus-reasoning-distilled-v2-gguf"
}
WhichModel::Qwen3_5_0_8BUnslothGguf => "qwen3.5-0.8b-unsloth-gguf",
WhichModel::Qwen3_5_2BUnslothGguf => "qwen3.5-2b-unsloth-gguf",
WhichModel::Qwen3_5_4BUnslothGguf => "qwen3.5-4b-unsloth-gguf",
WhichModel::Qwen3_5_0_8BLmstudioGguf => "qwen3.5-0.8b-lmstudio-gguf",
WhichModel::Qwen3_5_2BLmstudioGguf => "qwen3.5-2b-lmstudio-gguf",
WhichModel::Qwen3_5_4BLmstudioGguf => "qwen3.5-4b-lmstudio-gguf",
WhichModel::Qwen3ASR0_6B => "qwen3asr-0.6b",
WhichModel::Qwen3ASR1_7B => "qwen3asr-1.7b",
WhichModel::Qwen3vl2B => "qwen3vl-2b",
WhichModel::Qwen3vl4B => "qwen3vl-4b",
WhichModel::Qwen3vl8B => "qwen3vl-8b",
WhichModel::Qwen3vl32B => "qwen3vl-32b",
WhichModel::DeepSeekOCR => "deepseek-ocr",
WhichModel::DeepSeekOCR2 => "deepseek-ocr2",
WhichModel::HunyuanOCR => "hunyuan-ocr",
WhichModel::PaddleOCRVL => "paddleocr-vl",
WhichModel::PaddleOCRVL1_5 => "paddleocr-vl1.5",
WhichModel::RMBG2_0 => "rmbg2.0",
WhichModel::VoxCPM => "voxcpm",
WhichModel::VoxCPM1_5 => "voxcpm1.5",
WhichModel::GlmASRNano2512 => "glm-asr-nano-2512",
WhichModel::FunASRNano2512 => "fun-asr-nano-2512",
WhichModel::GlmOCR => "glm-ocr",
}
}
pub fn owner(self) -> &'static str {
match self {
WhichModel::MiniCPM4_0_5B => "OpenBMB",
WhichModel::Qwen2_5vl3B | WhichModel::Qwen2_5vl7B => "Qwen",
WhichModel::Qwen3_0_6B
| WhichModel::Qwen3Embedding0_6B
| WhichModel::Qwen3Embedding4B
| WhichModel::Qwen3Embedding8B
| WhichModel::Qwen3Reranker0_6B
| WhichModel::Qwen3Reranker4B
| WhichModel::Qwen3Reranker8B
| WhichModel::Qwen3ASR0_6B
| WhichModel::Qwen3ASR1_7B => "Qwen",
WhichModel::Qwen3vl2B
| WhichModel::Qwen3vl4B
| WhichModel::Qwen3vl8B
| WhichModel::Qwen3vl32B
| WhichModel::Qwen3_5Gguf => "Qwen",
WhichModel::Qwen3_5_0_8B
| WhichModel::Qwen3_5_2B
| WhichModel::Qwen3_5_4B
| WhichModel::Qwen3_5_9B => "Qwen",
WhichModel::Qwen3_5_0_8BUnslothGguf
| WhichModel::Qwen3_5_2BUnslothGguf
| WhichModel::Qwen3_5_4BUnslothGguf => "unsloth",
WhichModel::Qwen3_5_0_8BLmstudioGguf
| WhichModel::Qwen3_5_2BLmstudioGguf
| WhichModel::Qwen3_5_4BLmstudioGguf => "lmstudio-community",
WhichModel::Qwen3_5_9BClaude46OpusReasoningDistilledV2
| WhichModel::Qwen3_5_4BClaude46OpusReasoningDistilledV2Gguf
| WhichModel::Qwen3_5_9BClaude46OpusReasoningDistilledV2Gguf => "Jackrong",
WhichModel::DeepSeekOCR | WhichModel::DeepSeekOCR2 => "deepseek-ai",
WhichModel::HunyuanOCR => "Tencent-Hunyuan",
WhichModel::PaddleOCRVL | WhichModel::PaddleOCRVL1_5 => "PaddlePaddle",
WhichModel::RMBG2_0 => "AI-ModelScope",
WhichModel::VoxCPM | WhichModel::VoxCPM1_5 => "OpenBMB",
WhichModel::GlmASRNano2512 | WhichModel::GlmOCR => "ZhipuAI",
WhichModel::FunASRNano2512 => "FunAudioLLM",
}
}
/// Get the ModelScope model ID for this model variant
pub fn model_id(self) -> &'static str {
match self {
@@ -101,11 +308,32 @@ impl WhichModel {
WhichModel::Qwen2_5vl3B => "Qwen/Qwen2.5-VL-3B-Instruct",
WhichModel::Qwen2_5vl7B => "Qwen/Qwen2.5-VL-7B-Instruct",
WhichModel::Qwen3_0_6B => "Qwen/Qwen3-0.6B",
WhichModel::Qwen3Embedding0_6B => "Qwen/Qwen3-Embedding-0.6B",
WhichModel::Qwen3Embedding4B => "Qwen/Qwen3-Embedding-4B",
WhichModel::Qwen3Embedding8B => "Qwen/Qwen3-Embedding-8B",
WhichModel::Qwen3Reranker0_6B => "Qwen/Qwen3-Reranker-0.6B",
WhichModel::Qwen3Reranker4B => "Qwen/Qwen3-Reranker-4B",
WhichModel::Qwen3Reranker8B => "Qwen/Qwen3-Reranker-8B",
WhichModel::Qwen3_5_0_8B => "Qwen/Qwen3.5-0.8B",
WhichModel::Qwen3_5_2B => "Qwen/Qwen3.5-2B",
WhichModel::Qwen3_5_4B => "Qwen/Qwen3.5-4B",
WhichModel::Qwen3_5_9B => "Qwen/Qwen3.5-9B",
WhichModel::Qwen3_5_9BClaude46OpusReasoningDistilledV2 => {
"Jackrong/Qwen3.5-9B-Claude-4.6-Opus-Reasoning-Distilled-v2"
}
WhichModel::Qwen3_5Gguf => "GGUF",
WhichModel::Qwen3_5_4BClaude46OpusReasoningDistilledV2Gguf => {
"Jackrong/Qwen3.5-4B-Claude-4.6-Opus-Reasoning-Distilled-v2-GGUF"
}
WhichModel::Qwen3_5_9BClaude46OpusReasoningDistilledV2Gguf => {
"Jackrong/Qwen3.5-9B-Claude-4.6-Opus-Reasoning-Distilled-v2-GGUF"
}
WhichModel::Qwen3_5_0_8BUnslothGguf => "unsloth/Qwen3.5-0.8B-GGUF",
WhichModel::Qwen3_5_2BUnslothGguf => "unsloth/Qwen3.5-2B-GGUF",
WhichModel::Qwen3_5_4BUnslothGguf => "unsloth/Qwen3.5-4B-GGUF",
WhichModel::Qwen3_5_0_8BLmstudioGguf => "lmstudio-community/Qwen3.5-0.8B-GGUF",
WhichModel::Qwen3_5_2BLmstudioGguf => "lmstudio-community/Qwen3.5-2B-GGUF",
WhichModel::Qwen3_5_4BLmstudioGguf => "lmstudio-community/Qwen3.5-4B-GGUF",
WhichModel::Qwen3ASR0_6B => "Qwen/Qwen3-ASR-0.6B",
WhichModel::Qwen3ASR1_7B => "Qwen/Qwen3-ASR-1.7B",
WhichModel::Qwen3vl2B => "Qwen/Qwen3-VL-2B-Instruct",
@@ -131,6 +359,12 @@ impl WhichModel {
match self {
// LLM models
WhichModel::MiniCPM4_0_5B | WhichModel::Qwen3_0_6B => "llm",
WhichModel::Qwen3Embedding0_6B
| WhichModel::Qwen3Embedding4B
| WhichModel::Qwen3Embedding8B => "embedding",
WhichModel::Qwen3Reranker0_6B
| WhichModel::Qwen3Reranker4B
| WhichModel::Qwen3Reranker8B => "reranker",
WhichModel::Qwen2_5vl3B
| WhichModel::Qwen2_5vl7B
| WhichModel::Qwen3vl2B
@@ -141,7 +375,16 @@ impl WhichModel {
| WhichModel::Qwen3_5_2B
| WhichModel::Qwen3_5_4B
| WhichModel::Qwen3_5_9B
| WhichModel::Qwen3_5_9BClaude46OpusReasoningDistilledV2
| WhichModel::Qwen3_5Gguf => "vlm",
WhichModel::Qwen3_5_4BClaude46OpusReasoningDistilledV2Gguf
| WhichModel::Qwen3_5_9BClaude46OpusReasoningDistilledV2Gguf
| WhichModel::Qwen3_5_0_8BUnslothGguf
| WhichModel::Qwen3_5_2BUnslothGguf
| WhichModel::Qwen3_5_4BUnslothGguf
| WhichModel::Qwen3_5_0_8BLmstudioGguf
| WhichModel::Qwen3_5_2BLmstudioGguf
| WhichModel::Qwen3_5_4BLmstudioGguf => "vlm",
// OCR models
WhichModel::DeepSeekOCR
| WhichModel::DeepSeekOCR2
@@ -179,6 +422,8 @@ pub enum ModelInstance<'a> {
MiniCPM4(MiniCPMGenerateModel<'a>),
Qwen2_5VL(Qwen2_5VLGenerateModel<'a>),
Qwen3(Qwen3GenerateModel<'a>),
Qwen3Embedding(Qwen3EmbeddingModel),
Qwen3Reranker(Qwen3RerankerModel),
Qwen3_5(Qwen3_5GenerateModel<'a>),
Qwen3ASR(Qwen3AsrGenerateModel<'a>),
Qwen3VL(Box<Qwen3VLGenerateModel<'a>>),
@@ -198,6 +443,12 @@ impl<'a> GenerateModel for ModelInstance<'a> {
ModelInstance::MiniCPM4(model) => model.generate(mes),
ModelInstance::Qwen2_5VL(model) => model.generate(mes),
ModelInstance::Qwen3(model) => model.generate(mes),
ModelInstance::Qwen3Embedding(_) => {
Err(anyhow!("embedding model does not support chat completions"))
}
ModelInstance::Qwen3Reranker(_) => {
Err(anyhow!("reranker model does not support chat completions"))
}
ModelInstance::Qwen3_5(model) => model.generate(mes),
ModelInstance::Qwen3ASR(model) => model.generate(mes),
ModelInstance::Qwen3VL(model) => model.generate(mes),
@@ -227,6 +478,12 @@ impl<'a> GenerateModel for ModelInstance<'a> {
ModelInstance::MiniCPM4(model) => model.generate_stream(mes),
ModelInstance::Qwen2_5VL(model) => model.generate_stream(mes),
ModelInstance::Qwen3(model) => model.generate_stream(mes),
ModelInstance::Qwen3Embedding(_) => Err(anyhow!(
"embedding model does not support streaming chat completions"
)),
ModelInstance::Qwen3Reranker(_) => Err(anyhow!(
"reranker model does not support streaming chat completions"
)),
ModelInstance::Qwen3_5(model) => model.generate_stream(mes),
ModelInstance::Qwen3VL(model) => model.generate_stream(mes),
ModelInstance::Qwen3ASR(model) => model.generate_stream(mes),
@@ -242,6 +499,22 @@ impl<'a> GenerateModel for ModelInstance<'a> {
}
}
impl<'a> ModelInstance<'a> {
pub fn embedding(&mut self, input: &[String]) -> Result<Vec<Vec<f32>>> {
match self {
ModelInstance::Qwen3Embedding(model) => model.embed(input),
_ => Err(anyhow!("current model does not support embeddings")),
}
}
pub fn rerank(&mut self, query: &str, documents: &[String]) -> Result<Vec<f32>> {
match self {
ModelInstance::Qwen3Reranker(model) => model.rerank(query, documents),
_ => Err(anyhow!("current model does not support reranking")),
}
}
}
pub fn load_model<'a>(
model_type: WhichModel,
path: &str,
@@ -265,6 +538,18 @@ pub fn load_model<'a>(
let model = Qwen3GenerateModel::init(path, None, None)?;
ModelInstance::Qwen3(model)
}
WhichModel::Qwen3Embedding0_6B
| WhichModel::Qwen3Embedding4B
| WhichModel::Qwen3Embedding8B => {
let model = Qwen3EmbeddingModel::init(path, None, None)?;
ModelInstance::Qwen3Embedding(model)
}
WhichModel::Qwen3Reranker0_6B
| WhichModel::Qwen3Reranker4B
| WhichModel::Qwen3Reranker8B => {
let model = Qwen3RerankerModel::init(path, None, None)?;
ModelInstance::Qwen3Reranker(model)
}
WhichModel::Qwen3_5_0_8B => {
let model = Qwen3_5GenerateModel::init(path, None, None)?;
ModelInstance::Qwen3_5(model)
@@ -281,7 +566,19 @@ pub fn load_model<'a>(
let model = Qwen3_5GenerateModel::init(path, None, None)?;
ModelInstance::Qwen3_5(model)
}
WhichModel::Qwen3_5Gguf => {
WhichModel::Qwen3_5_9BClaude46OpusReasoningDistilledV2 => {
let model = Qwen3_5GenerateModel::init(path, None, None)?;
ModelInstance::Qwen3_5(model)
}
WhichModel::Qwen3_5Gguf
| WhichModel::Qwen3_5_4BClaude46OpusReasoningDistilledV2Gguf
| WhichModel::Qwen3_5_9BClaude46OpusReasoningDistilledV2Gguf
| WhichModel::Qwen3_5_0_8BUnslothGguf
| WhichModel::Qwen3_5_2BUnslothGguf
| WhichModel::Qwen3_5_4BUnslothGguf
| WhichModel::Qwen3_5_0_8BLmstudioGguf
| WhichModel::Qwen3_5_2BLmstudioGguf
| WhichModel::Qwen3_5_4BLmstudioGguf => {
if gguf.is_none() {
return Err(anyhow!("Qwen3_5Gguf gguf model path is required"));
}