fix: ensure_default_models 每次启动重新检查模型文件存在性
This commit is contained in:
@@ -148,82 +148,87 @@ impl ModelManager {
|
||||
}
|
||||
|
||||
/// 初始化默认模型清单(首次启动或清单缺失时)
|
||||
/// 每次启动都重新检查文件存在性,更新 downloaded 状态(符号链接可能后建)
|
||||
pub fn ensure_default_models(&mut self) -> Result<()> {
|
||||
if !self.registry.models.is_empty() {
|
||||
return Ok(());
|
||||
// 首次:注册表为空,填充默认清单
|
||||
if self.registry.models.is_empty() {
|
||||
let defaults = vec![
|
||||
ModelInfo {
|
||||
id: "qwen2.5-0.5b-q4_k_m".to_string(),
|
||||
kind: ModelKind::Llm,
|
||||
name: "Qwen2.5 0.5B Q4 (推荐默认)".to_string(),
|
||||
version: "0.5b".to_string(),
|
||||
size: 469 * 1024 * 1024,
|
||||
memory_required: 1024 * 1024 * 1024,
|
||||
recommended_tier: "4G 内存档可用".to_string(),
|
||||
url: "https://hf-mirror.com/Qwen/Qwen2.5-0.5B-Instruct-GGUF/resolve/main/qwen2.5-0.5b-instruct-q4_k_m.gguf".to_string(),
|
||||
sha256: String::new(),
|
||||
filename: "qwen2.5-0.5b-q4_k_m.gguf".to_string(),
|
||||
},
|
||||
ModelInfo {
|
||||
id: "gemma3-1b-q4_k_m".to_string(),
|
||||
kind: ModelKind::Llm,
|
||||
name: "Gemma3 1B Q4 (可选档)".to_string(),
|
||||
version: "1b".to_string(),
|
||||
size: 800 * 1024 * 1024,
|
||||
memory_required: 2 * 1024 * 1024 * 1024,
|
||||
recommended_tier: "建议 8G 以上".to_string(),
|
||||
url: "https://hf-mirror.com/google/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-q4_k_m.gguf".to_string(),
|
||||
sha256: String::new(),
|
||||
filename: "gemma3-1b-q4_k_m.gguf".to_string(),
|
||||
},
|
||||
ModelInfo {
|
||||
id: "whisper-tiny".to_string(),
|
||||
kind: ModelKind::Asr,
|
||||
name: "Whisper Tiny (中文)".to_string(),
|
||||
version: "tiny".to_string(),
|
||||
size: 75 * 1024 * 1024,
|
||||
memory_required: 200 * 1024 * 1024,
|
||||
recommended_tier: "4G 内存档可用".to_string(),
|
||||
url: "https://hf-mirror.com/ggerganov/whisper.cpp/resolve/main/ggml-tiny.bin".to_string(),
|
||||
sha256: String::new(),
|
||||
filename: "ggml-tiny.bin".to_string(),
|
||||
},
|
||||
ModelInfo {
|
||||
id: "piper-zh-huayan".to_string(),
|
||||
kind: ModelKind::Tts,
|
||||
name: "Piper zh_CN huayan (中文女声)".to_string(),
|
||||
version: "medium".to_string(),
|
||||
size: 63 * 1024 * 1024,
|
||||
memory_required: 150 * 1024 * 1024,
|
||||
recommended_tier: "4G 内存档可用".to_string(),
|
||||
url: "https://hf-mirror.com/rhasspy/piper-voices/resolve/main/zh/zh_CN/huayan/medium/zh_CN-huayan-medium.onnx".to_string(),
|
||||
sha256: String::new(),
|
||||
filename: "zh_CN-huayan-medium.onnx".to_string(),
|
||||
},
|
||||
];
|
||||
|
||||
for info in defaults {
|
||||
self.registry.models.push(LocalModelEntry {
|
||||
info,
|
||||
downloaded: false,
|
||||
download_progress: 0,
|
||||
});
|
||||
}
|
||||
|
||||
// 设置默认 active 模型
|
||||
if !self.registry.active.contains_key(&ModelKind::Llm) {
|
||||
self.registry.active.insert(ModelKind::Llm, "qwen2.5-0.5b-q4_k_m".to_string());
|
||||
}
|
||||
if !self.registry.active.contains_key(&ModelKind::Asr) {
|
||||
self.registry.active.insert(ModelKind::Asr, "whisper-tiny".to_string());
|
||||
}
|
||||
if !self.registry.active.contains_key(&ModelKind::Tts) {
|
||||
self.registry.active.insert(ModelKind::Tts, "piper-zh-huayan".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
// Spike 推荐的默认模型清单
|
||||
let defaults = vec![
|
||||
ModelInfo {
|
||||
id: "qwen2.5-0.5b-q4_k_m".to_string(),
|
||||
kind: ModelKind::Llm,
|
||||
name: "Qwen2.5 0.5B Q4 (推荐默认)".to_string(),
|
||||
version: "0.5b".to_string(),
|
||||
size: 469 * 1024 * 1024,
|
||||
memory_required: 1024 * 1024 * 1024,
|
||||
recommended_tier: "4G 内存档可用".to_string(),
|
||||
url: "https://hf-mirror.com/Qwen/Qwen2.5-0.5B-Instruct-GGUF/resolve/main/qwen2.5-0.5b-instruct-q4_k_m.gguf".to_string(),
|
||||
sha256: String::new(), // 实际部署时填充
|
||||
filename: "qwen2.5-0.5b-q4_k_m.gguf".to_string(),
|
||||
},
|
||||
ModelInfo {
|
||||
id: "gemma3-1b-q4_k_m".to_string(),
|
||||
kind: ModelKind::Llm,
|
||||
name: "Gemma3 1B Q4 (可选档)".to_string(),
|
||||
version: "1b".to_string(),
|
||||
size: 800 * 1024 * 1024,
|
||||
memory_required: 2 * 1024 * 1024 * 1024,
|
||||
recommended_tier: "建议 8G 以上".to_string(),
|
||||
url: "https://hf-mirror.com/google/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-q4_k_m.gguf".to_string(),
|
||||
sha256: String::new(),
|
||||
filename: "gemma3-1b-q4_k_m.gguf".to_string(),
|
||||
},
|
||||
ModelInfo {
|
||||
id: "whisper-tiny".to_string(),
|
||||
kind: ModelKind::Asr,
|
||||
name: "Whisper Tiny (中文)".to_string(),
|
||||
version: "tiny".to_string(),
|
||||
size: 75 * 1024 * 1024,
|
||||
memory_required: 200 * 1024 * 1024,
|
||||
recommended_tier: "4G 内存档可用".to_string(),
|
||||
url: "https://hf-mirror.com/ggerganov/whisper.cpp/resolve/main/ggml-tiny.bin".to_string(),
|
||||
sha256: String::new(),
|
||||
filename: "ggml-tiny.bin".to_string(),
|
||||
},
|
||||
ModelInfo {
|
||||
id: "piper-zh-huayan".to_string(),
|
||||
kind: ModelKind::Tts,
|
||||
name: "Piper zh_CN huayan (中文女声)".to_string(),
|
||||
version: "medium".to_string(),
|
||||
size: 63 * 1024 * 1024,
|
||||
memory_required: 150 * 1024 * 1024,
|
||||
recommended_tier: "4G 内存档可用".to_string(),
|
||||
url: "https://hf-mirror.com/rhasspy/piper-voices/resolve/main/zh/zh_CN/huayan/medium/zh_CN-huayan-medium.onnx".to_string(),
|
||||
sha256: String::new(),
|
||||
filename: "zh_CN-huayan-medium.onnx".to_string(),
|
||||
},
|
||||
];
|
||||
|
||||
for info in defaults {
|
||||
let filename = info.filename.clone();
|
||||
let downloaded = self.store_dir.join(info.kind.dir_name()).join(&filename).exists();
|
||||
self.registry.models.push(LocalModelEntry {
|
||||
info,
|
||||
downloaded,
|
||||
download_progress: if downloaded { 100 } else { 0 },
|
||||
});
|
||||
}
|
||||
|
||||
// 设置默认 active 模型
|
||||
if !self.registry.active.contains_key(&ModelKind::Llm) {
|
||||
self.registry.active.insert(ModelKind::Llm, "qwen2.5-0.5b-q4_k_m".to_string());
|
||||
}
|
||||
if !self.registry.active.contains_key(&ModelKind::Asr) {
|
||||
self.registry.active.insert(ModelKind::Asr, "whisper-tiny".to_string());
|
||||
}
|
||||
if !self.registry.active.contains_key(&ModelKind::Tts) {
|
||||
self.registry.active.insert(ModelKind::Tts, "piper-zh-huayan".to_string());
|
||||
// 每次启动都重新检查文件存在性(符号链接可能后建,或文件被手动删除)
|
||||
for entry in &mut self.registry.models {
|
||||
let path = self.store_dir.join(entry.info.kind.dir_name()).join(&entry.info.filename);
|
||||
let exists = path.exists();
|
||||
entry.downloaded = exists;
|
||||
entry.download_progress = if exists { 100 } else { 0 };
|
||||
}
|
||||
|
||||
self.save_registry()?;
|
||||
|
||||
Reference in New Issue
Block a user