From fcb9706022396126898a3fce53080c9fc2cf1c42 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Wed, 7 May 2025 11:37:06 -0400 Subject: [PATCH] Improve Ollama tool use (#30120) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Screenshot 2025-05-07 at 9 37 39 AM Screenshot 2025-05-07 at 9 37 33 AM Release Notes: - Ollama models no longer require the supports_tools field in settings (defaults to false) --------- Co-authored-by: Antonio Scandurra --- crates/agent/src/profile_selector.rs | 65 ++++++++++--------- .../src/assistant_settings.rs | 2 +- crates/language_models/src/provider/ollama.rs | 12 ++-- crates/ollama/src/ollama.rs | 4 +- 4 files changed, 44 insertions(+), 39 deletions(-) diff --git a/crates/agent/src/profile_selector.rs b/crates/agent/src/profile_selector.rs index 9fed2cdd29..38b878aea0 100644 --- a/crates/agent/src/profile_selector.rs +++ b/crates/agent/src/profile_selector.rs @@ -156,46 +156,47 @@ impl Render for ProfileSelector { .default_model() .map_or(false, |default| default.model.supports_tools()); - let this = cx.entity().clone(); - let focus_handle = self.focus_handle.clone(); - - let trigger_button = if supports_tools { - Button::new("profile-selector-model", selected_profile) + if supports_tools { + let this = cx.entity().clone(); + let focus_handle = self.focus_handle.clone(); + let trigger_button = Button::new("profile-selector-model", selected_profile) .label_size(LabelSize::Small) .color(Color::Muted) .icon(IconName::ChevronDown) .icon_size(IconSize::XSmall) .icon_position(IconPosition::End) - .icon_color(Color::Muted) + .icon_color(Color::Muted); + + PopoverMenu::new("profile-selector") + .trigger_with_tooltip(trigger_button, { + let focus_handle = focus_handle.clone(); + move |window, cx| { + Tooltip::for_action_in( + "Toggle Profile Menu", + &ToggleProfileSelector, + &focus_handle, + window, + cx, + ) + } + }) + .anchor(if self.documentation_side == DocumentationSide::Left { + gpui::Corner::BottomRight + } else { + gpui::Corner::BottomLeft + }) + .with_handle(self.menu_handle.clone()) + .menu(move |window, cx| { + Some(this.update(cx, |this, cx| this.build_context_menu(window, cx))) + }) + .into_any_element() } else { - Button::new("tools-not-supported-button", "No Tools") + Button::new("tools-not-supported-button", "Tools Unsupported") .disabled(true) .label_size(LabelSize::Small) .color(Color::Muted) - .tooltip(Tooltip::text("The current model does not support tools.")) - }; - - PopoverMenu::new("profile-selector") - .trigger_with_tooltip(trigger_button, { - let focus_handle = focus_handle.clone(); - move |window, cx| { - Tooltip::for_action_in( - "Toggle Profile Menu", - &ToggleProfileSelector, - &focus_handle, - window, - cx, - ) - } - }) - .anchor(if self.documentation_side == DocumentationSide::Left { - gpui::Corner::BottomRight - } else { - gpui::Corner::BottomLeft - }) - .with_handle(self.menu_handle.clone()) - .menu(move |window, cx| { - Some(this.update(cx, |this, cx| this.build_context_menu(window, cx))) - }) + .tooltip(Tooltip::text("This model does not support tools.")) + .into_any_element() + } } } diff --git a/crates/assistant_settings/src/assistant_settings.rs b/crates/assistant_settings/src/assistant_settings.rs index 63cd689a4f..7cce692b26 100644 --- a/crates/assistant_settings/src/assistant_settings.rs +++ b/crates/assistant_settings/src/assistant_settings.rs @@ -366,7 +366,7 @@ impl AssistantSettingsContent { &model, None, None, - language_model.supports_tools(), + Some(language_model.supports_tools()), )), api_url, }); diff --git a/crates/language_models/src/provider/ollama.rs b/crates/language_models/src/provider/ollama.rs index 0273891c34..705f54f003 100644 --- a/crates/language_models/src/provider/ollama.rs +++ b/crates/language_models/src/provider/ollama.rs @@ -52,7 +52,7 @@ pub struct AvailableModel { /// The number of seconds to keep the connection open after the last request pub keep_alive: Option, /// Whether the model supports tools - pub supports_tools: bool, + pub supports_tools: Option, } pub struct OllamaLanguageModelProvider { @@ -93,8 +93,12 @@ impl State { async move { let name = model.name.as_str(); let capabilities = show_model(http_client.as_ref(), &api_url, name).await?; - let ollama_model = - ollama::Model::new(name, None, None, capabilities.supports_tools()); + let ollama_model = ollama::Model::new( + name, + None, + None, + Some(capabilities.supports_tools()), + ); Ok(ollama_model) } }); @@ -317,7 +321,7 @@ impl LanguageModel for OllamaLanguageModel { } fn supports_tools(&self) -> bool { - self.model.supports_tools + self.model.supports_tools.unwrap_or(false) } fn telemetry_id(&self) -> String { diff --git a/crates/ollama/src/ollama.rs b/crates/ollama/src/ollama.rs index 10436a3581..281c563454 100644 --- a/crates/ollama/src/ollama.rs +++ b/crates/ollama/src/ollama.rs @@ -37,7 +37,7 @@ pub struct Model { pub display_name: Option, pub max_tokens: usize, pub keep_alive: Option, - pub supports_tools: bool, + pub supports_tools: Option, } fn get_max_tokens(name: &str) -> usize { @@ -67,7 +67,7 @@ impl Model { name: &str, display_name: Option<&str>, max_tokens: Option, - supports_tools: bool, + supports_tools: Option, ) -> Self { Self { name: name.to_owned(),