@@ -249,33 +249,7 @@ impl LanguageModelProvider for OllamaLanguageModelProvider {
}
// Override with available models from settings
- for setting_model in &OllamaLanguageModelProvider::settings(cx).available_models {
- let setting_base = setting_model.name.split(':').next().unwrap();
- if let Some(model) = models
- .values_mut()
- .find(|m| m.name.split(':').next().unwrap() == setting_base)
- {
- model.max_tokens = setting_model.max_tokens;
- model.display_name = setting_model.display_name.clone();
- model.keep_alive = setting_model.keep_alive.clone();
- model.supports_tools = setting_model.supports_tools;
- model.supports_vision = setting_model.supports_images;
- model.supports_thinking = setting_model.supports_thinking;
- } else {
- models.insert(
- setting_model.name.clone(),
- ollama::Model {
- name: setting_model.name.clone(),
- display_name: setting_model.display_name.clone(),
- max_tokens: setting_model.max_tokens,
- keep_alive: setting_model.keep_alive.clone(),
- supports_tools: setting_model.supports_tools,
- supports_vision: setting_model.supports_images,
- supports_thinking: setting_model.supports_thinking,
- },
- );
- }
- }
+ merge_settings_into_models(&mut models, &settings.available_models);
let mut models = models
.into_values()
@@ -921,6 +895,35 @@ impl Render for ConfigurationView {
}
}
+fn merge_settings_into_models(
+ models: &mut HashMap<String, ollama::Model>,
+ available_models: &[AvailableModel],
+) {
+ for setting_model in available_models {
+ if let Some(model) = models.get_mut(&setting_model.name) {
+ model.max_tokens = setting_model.max_tokens;
+ model.display_name = setting_model.display_name.clone();
+ model.keep_alive = setting_model.keep_alive.clone();
+ model.supports_tools = setting_model.supports_tools;
+ model.supports_vision = setting_model.supports_images;
+ model.supports_thinking = setting_model.supports_thinking;
+ } else {
+ models.insert(
+ setting_model.name.clone(),
+ ollama::Model {
+ name: setting_model.name.clone(),
+ display_name: setting_model.display_name.clone(),
+ max_tokens: setting_model.max_tokens,
+ keep_alive: setting_model.keep_alive.clone(),
+ supports_tools: setting_model.supports_tools,
+ supports_vision: setting_model.supports_images,
+ supports_thinking: setting_model.supports_thinking,
+ },
+ );
+ }
+ }
+}
+
fn tool_into_ollama(tool: LanguageModelRequestTool) -> ollama::OllamaTool {
ollama::OllamaTool::Function {
function: OllamaFunctionTool {
@@ -930,3 +933,83 @@ fn tool_into_ollama(tool: LanguageModelRequestTool) -> ollama::OllamaTool {
},
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_merge_settings_preserves_display_names_for_similar_models() {
+ // Regression test for https://github.com/zed-industries/zed/issues/43646
+ // When multiple models share the same base name (e.g., qwen2.5-coder:1.5b and qwen2.5-coder:3b),
+ // each model should get its own display_name from settings, not a random one.
+
+ let mut models: HashMap<String, ollama::Model> = HashMap::new();
+ models.insert(
+ "qwen2.5-coder:1.5b".to_string(),
+ ollama::Model {
+ name: "qwen2.5-coder:1.5b".to_string(),
+ display_name: None,
+ max_tokens: 4096,
+ keep_alive: None,
+ supports_tools: None,
+ supports_vision: None,
+ supports_thinking: None,
+ },
+ );
+ models.insert(
+ "qwen2.5-coder:3b".to_string(),
+ ollama::Model {
+ name: "qwen2.5-coder:3b".to_string(),
+ display_name: None,
+ max_tokens: 4096,
+ keep_alive: None,
+ supports_tools: None,
+ supports_vision: None,
+ supports_thinking: None,
+ },
+ );
+
+ let available_models = vec![
+ AvailableModel {
+ name: "qwen2.5-coder:1.5b".to_string(),
+ display_name: Some("QWEN2.5 Coder 1.5B".to_string()),
+ max_tokens: 5000,
+ keep_alive: None,
+ supports_tools: Some(true),
+ supports_images: None,
+ supports_thinking: None,
+ },
+ AvailableModel {
+ name: "qwen2.5-coder:3b".to_string(),
+ display_name: Some("QWEN2.5 Coder 3B".to_string()),
+ max_tokens: 6000,
+ keep_alive: None,
+ supports_tools: Some(true),
+ supports_images: None,
+ supports_thinking: None,
+ },
+ ];
+
+ merge_settings_into_models(&mut models, &available_models);
+
+ let model_1_5b = models
+ .get("qwen2.5-coder:1.5b")
+ .expect("1.5b model missing");
+ let model_3b = models.get("qwen2.5-coder:3b").expect("3b model missing");
+
+ assert_eq!(
+ model_1_5b.display_name,
+ Some("QWEN2.5 Coder 1.5B".to_string()),
+ "1.5b model should have its own display_name"
+ );
+ assert_eq!(model_1_5b.max_tokens, 5000);
+
+ assert_eq!(
+ model_3b.display_name,
+ Some("QWEN2.5 Coder 3B".to_string()),
+ "3b model should have its own display_name"
+ );
+ assert_eq!(model_3b.max_tokens, 6000);
+ }
+}