Add typed generation preferences
This commit is contained in:
131
src/app/view.rs
131
src/app/view.rs
@@ -3,6 +3,7 @@ use crate::database::{ProjectWithSessions, Session};
|
||||
use crate::model::{
|
||||
self, DownloadPhase, MODEL_CHOICES, ManagedArtifact, ManagedArtifactState, ModelChoice,
|
||||
};
|
||||
use crate::settings::REASONING_MODES;
|
||||
use iced::theme::{Palette, palette};
|
||||
use iced::widget::{
|
||||
Button, Space, Svg, button, checkbox, column, container, horizontal_rule, opaque, pick_list,
|
||||
@@ -299,17 +300,13 @@ impl App {
|
||||
self.preference_draft.dspark_enabled,
|
||||
)
|
||||
.on_toggle_maybe(dspark_toggle);
|
||||
let effective = self
|
||||
.preference_draft
|
||||
.generation()
|
||||
.ok()
|
||||
.map(|generation| generation.effective(self.preference_draft.model));
|
||||
|
||||
let mut content = column![
|
||||
row![
|
||||
icon(ICON_SETTINGS, 22),
|
||||
text("Preferences").size(24),
|
||||
Space::with_width(Length::Fill),
|
||||
text("⌘,").size(12),
|
||||
]
|
||||
.spacing(10)
|
||||
.align_y(Alignment::Center),
|
||||
Space::with_height(6),
|
||||
let mut fields = column![
|
||||
text("MODEL").size(11),
|
||||
pick_list(
|
||||
&MODEL_CHOICES[..],
|
||||
@@ -325,6 +322,75 @@ impl App {
|
||||
})
|
||||
.size(12),
|
||||
Space::with_height(8),
|
||||
text("CAPACITY").size(11),
|
||||
preference_input_row(
|
||||
"Context tokens",
|
||||
text_input("32768", &self.preference_draft.context_tokens)
|
||||
.on_input(Message::PreferenceContextChanged),
|
||||
),
|
||||
preference_input_row(
|
||||
"Maximum generated tokens",
|
||||
text_input("50000", &self.preference_draft.max_generated_tokens)
|
||||
.on_input(Message::PreferenceMaxTokensChanged),
|
||||
),
|
||||
text("System prompt").size(13),
|
||||
text_input(
|
||||
"You are a helpful assistant",
|
||||
&self.preference_draft.system_prompt,
|
||||
)
|
||||
.on_input(Message::PreferenceSystemPromptChanged)
|
||||
.padding(9),
|
||||
Space::with_height(8),
|
||||
text("SAMPLING AND REASONING").size(11),
|
||||
preference_input_row(
|
||||
"Temperature",
|
||||
text_input("DS4 default", &self.preference_draft.temperature)
|
||||
.on_input(Message::PreferenceTemperatureChanged),
|
||||
),
|
||||
preference_input_row(
|
||||
"Top-p",
|
||||
text_input("DS4 default", &self.preference_draft.top_p)
|
||||
.on_input(Message::PreferenceTopPChanged),
|
||||
),
|
||||
preference_input_row(
|
||||
"Min-p",
|
||||
text_input("DS4 default", &self.preference_draft.min_p)
|
||||
.on_input(Message::PreferenceMinPChanged),
|
||||
),
|
||||
preference_input_row(
|
||||
"Seed",
|
||||
text_input("Random", &self.preference_draft.seed)
|
||||
.on_input(Message::PreferenceSeedChanged),
|
||||
),
|
||||
row![
|
||||
text("Reasoning").size(13).width(Length::Fill),
|
||||
pick_list(
|
||||
&REASONING_MODES[..],
|
||||
Some(self.preference_draft.reasoning_mode),
|
||||
Message::PreferenceReasoningChanged,
|
||||
)
|
||||
.width(240),
|
||||
]
|
||||
.spacing(12)
|
||||
.align_y(Alignment::Center),
|
||||
text("Blank sampling values retain DS4's model-family defaults. Think Max needs at least 393216 context tokens.")
|
||||
.size(12),
|
||||
text(effective.map_or_else(
|
||||
|| "Effective settings will appear after valid values are entered.".to_owned(),
|
||||
|settings| format!(
|
||||
"Effective: {} context • {} max • temp {} • top-p {} • min-p {} • seed {} • {} • system prompt {}",
|
||||
settings.context_tokens,
|
||||
settings.max_generated_tokens,
|
||||
settings.temperature,
|
||||
settings.top_p,
|
||||
settings.min_p,
|
||||
settings.seed.map_or_else(|| "random".to_owned(), |seed| seed.to_string()),
|
||||
settings.reasoning_mode,
|
||||
if settings.system_prompt.is_empty() { "off" } else { "on" },
|
||||
),
|
||||
))
|
||||
.size(12),
|
||||
Space::with_height(8),
|
||||
text("INACTIVITY").size(11),
|
||||
row![
|
||||
text_input("10", &self.preference_draft.idle_timeout_minutes)
|
||||
@@ -340,23 +406,33 @@ impl App {
|
||||
.spacing(10);
|
||||
|
||||
if let Some(error) = &self.preference_error {
|
||||
content = content.push(text(error).style(iced::widget::text::danger));
|
||||
fields = fields.push(text(error).style(iced::widget::text::danger));
|
||||
}
|
||||
content = content.push(
|
||||
row![
|
||||
Space::with_width(Length::Fill),
|
||||
action_button("Cancel").on_press(Message::DismissPanel),
|
||||
action_button("Save").on_press(Message::SavePreferences),
|
||||
]
|
||||
.spacing(8),
|
||||
);
|
||||
let header = row![
|
||||
icon(ICON_SETTINGS, 22),
|
||||
text("Preferences").size(24),
|
||||
Space::with_width(Length::Fill),
|
||||
text("⌘,").size(12),
|
||||
]
|
||||
.spacing(10)
|
||||
.align_y(Alignment::Center);
|
||||
let footer = row![
|
||||
action_button("Reset DS4 defaults").on_press(Message::ResetPreferences),
|
||||
Space::with_width(Length::Fill),
|
||||
action_button("Cancel").on_press(Message::DismissPanel),
|
||||
action_button("Save").on_press(Message::SavePreferences),
|
||||
]
|
||||
.spacing(8);
|
||||
|
||||
let panel = container(content)
|
||||
let panel = container(column![header, scrollable(fields), footer].spacing(16))
|
||||
.padding(24)
|
||||
.width(520)
|
||||
.width(600)
|
||||
.height(Length::Fill)
|
||||
.max_height(660)
|
||||
.style(overview_style);
|
||||
opaque(
|
||||
container(panel)
|
||||
.padding(24)
|
||||
.center_x(Length::Fill)
|
||||
.center_y(Length::Fill)
|
||||
.style(|_| {
|
||||
@@ -541,6 +617,19 @@ fn model_artifact_row(artifact: &ManagedArtifact, busy: bool) -> Element<'static
|
||||
.into()
|
||||
}
|
||||
|
||||
fn preference_input_row<'a>(
|
||||
label: &'a str,
|
||||
input: iced::widget::TextInput<'a, Message>,
|
||||
) -> Element<'a, Message> {
|
||||
row![
|
||||
text(label).size(13).width(Length::Fill),
|
||||
input.width(240).padding(9),
|
||||
]
|
||||
.spacing(12)
|
||||
.align_y(Alignment::Center)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn download_status_bar(download: &ActiveDownload) -> Element<'_, Message> {
|
||||
let progress = &download.progress;
|
||||
let percent = progress.fraction() * 100.0;
|
||||
|
||||
Reference in New Issue
Block a user