Reflect token limit errors and warnings in the assistant panel Send button style (#15529)
When used token count is below 80%, the Send button is displayed as usual: no tooltip, regular style:  When it exceeds 80% but below the `max_tokens` threshold, the button starts to show as a warning, with the corresponding tooltip:  When it is over the `max_token` threshold, the button starts to show as an error, with another tooltip:  The buttons are not blocked in any case, in case the token calculation is wrong, to allow using the assistant panel nonetheless. Release Notes: - N/A
This commit is contained in:
parent
380a19fcf2
commit
a31dba9fc1
1 changed files with 82 additions and 13 deletions
|
@ -58,6 +58,7 @@ use std::{
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
use terminal_view::{terminal_panel::TerminalPanel, TerminalView};
|
use terminal_view::{terminal_panel::TerminalPanel, TerminalView};
|
||||||
|
use ui::TintColor;
|
||||||
use ui::{
|
use ui::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
utils::{format_distance_from_now, DateTimeType},
|
utils::{format_distance_from_now, DateTimeType},
|
||||||
|
@ -2320,8 +2321,34 @@ impl ContextEditor {
|
||||||
},
|
},
|
||||||
None => "Send",
|
None => "Send",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let (style, tooltip) = match token_state(&self.context, cx) {
|
||||||
|
Some(TokenState::NoTokensLeft { .. }) => (
|
||||||
|
ButtonStyle::Tinted(TintColor::Negative),
|
||||||
|
Some(Tooltip::text("Token limit reached", cx)),
|
||||||
|
),
|
||||||
|
Some(TokenState::HasMoreTokens {
|
||||||
|
over_warn_threshold,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
let (style, tooltip) = if over_warn_threshold {
|
||||||
|
(
|
||||||
|
ButtonStyle::Tinted(TintColor::Warning),
|
||||||
|
Some(Tooltip::text("Token limit is close to exhaustion", cx)),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(ButtonStyle::Filled, None)
|
||||||
|
};
|
||||||
|
(style, tooltip)
|
||||||
|
}
|
||||||
|
None => (ButtonStyle::Filled, None),
|
||||||
|
};
|
||||||
|
|
||||||
ButtonLike::new("send_button")
|
ButtonLike::new("send_button")
|
||||||
.style(ButtonStyle::Filled)
|
.style(style)
|
||||||
|
.when_some(tooltip, |button, tooltip| {
|
||||||
|
button.tooltip(move |_| tooltip.clone())
|
||||||
|
})
|
||||||
.layer(ElevationIndex::ModalSurface)
|
.layer(ElevationIndex::ModalSurface)
|
||||||
.children(
|
.children(
|
||||||
KeyBinding::for_action_in(&Assist, &focus_handle, cx)
|
KeyBinding::for_action_in(&Assist, &focus_handle, cx)
|
||||||
|
@ -2726,25 +2753,30 @@ impl ContextEditorToolbarItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_remaining_tokens(&self, cx: &mut ViewContext<Self>) -> Option<impl IntoElement> {
|
fn render_remaining_tokens(&self, cx: &mut ViewContext<Self>) -> Option<impl IntoElement> {
|
||||||
let model = LanguageModelRegistry::read_global(cx).active_model()?;
|
|
||||||
let context = &self
|
let context = &self
|
||||||
.active_context_editor
|
.active_context_editor
|
||||||
.as_ref()?
|
.as_ref()?
|
||||||
.upgrade()?
|
.upgrade()?
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.context;
|
.context;
|
||||||
let token_count = context.read(cx).token_count()?;
|
let (token_count_color, token_count, max_token_count) = match token_state(context, cx)? {
|
||||||
let max_token_count = model.max_token_count();
|
TokenState::NoTokensLeft {
|
||||||
|
max_token_count,
|
||||||
let remaining_tokens = max_token_count as isize - token_count as isize;
|
token_count,
|
||||||
let token_count_color = if remaining_tokens <= 0 {
|
} => (Color::Error, token_count, max_token_count),
|
||||||
Color::Error
|
TokenState::HasMoreTokens {
|
||||||
} else if token_count as f32 / max_token_count as f32 >= 0.8 {
|
max_token_count,
|
||||||
Color::Warning
|
token_count,
|
||||||
} else {
|
over_warn_threshold,
|
||||||
Color::Muted
|
} => {
|
||||||
|
let color = if over_warn_threshold {
|
||||||
|
Color::Warning
|
||||||
|
} else {
|
||||||
|
Color::Muted
|
||||||
|
};
|
||||||
|
(color, token_count, max_token_count)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
h_flex()
|
h_flex()
|
||||||
.gap_0p5()
|
.gap_0p5()
|
||||||
|
@ -3077,3 +3109,40 @@ fn slash_command_error_block_renderer(message: String) -> RenderBlock {
|
||||||
.into_any()
|
.into_any()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum TokenState {
|
||||||
|
NoTokensLeft {
|
||||||
|
max_token_count: usize,
|
||||||
|
token_count: usize,
|
||||||
|
},
|
||||||
|
HasMoreTokens {
|
||||||
|
max_token_count: usize,
|
||||||
|
token_count: usize,
|
||||||
|
over_warn_threshold: bool,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fn token_state(context: &Model<Context>, cx: &AppContext) -> Option<TokenState> {
|
||||||
|
const WARNING_TOKEN_THRESHOLD: f32 = 0.8;
|
||||||
|
|
||||||
|
let model = LanguageModelRegistry::read_global(cx).active_model()?;
|
||||||
|
let token_count = context.read(cx).token_count()?;
|
||||||
|
let max_token_count = model.max_token_count();
|
||||||
|
|
||||||
|
let remaining_tokens = max_token_count as isize - token_count as isize;
|
||||||
|
let token_state = if remaining_tokens <= 0 {
|
||||||
|
TokenState::NoTokensLeft {
|
||||||
|
max_token_count,
|
||||||
|
token_count,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let over_warn_threshold =
|
||||||
|
token_count as f32 / max_token_count as f32 >= WARNING_TOKEN_THRESHOLD;
|
||||||
|
TokenState::HasMoreTokens {
|
||||||
|
max_token_count,
|
||||||
|
token_count,
|
||||||
|
over_warn_threshold,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some(token_state)
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue