feat: more preferences
This commit is contained in:
199
src/database.rs
199
src/database.rs
@@ -5,7 +5,11 @@ use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::schema::{preferences, projects, sessions};
|
||||
use crate::settings::{ExecutionPreferences, GenerationPreferences, ReasoningMode};
|
||||
use crate::settings::{
|
||||
DiagnosticPreferences, ExecutionPreferences, GenerationPreferences, ReasoningMode,
|
||||
RuntimePreferences, SpeculativePreferences, SsdPreferences, SteeringPreferences,
|
||||
StreamingCacheBudget,
|
||||
};
|
||||
|
||||
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations");
|
||||
|
||||
@@ -30,6 +34,23 @@ pub struct AppPreferences {
|
||||
pub prefill_chunk: Option<i32>,
|
||||
pub quality: bool,
|
||||
pub warm_weights: bool,
|
||||
pub mtp_draft_tokens: i32,
|
||||
pub mtp_margin: f32,
|
||||
pub glm_mtp: bool,
|
||||
pub glm_mtp_timing: bool,
|
||||
pub dspark_confidence_threshold: Option<f32>,
|
||||
pub dspark_strict: bool,
|
||||
pub ssd_streaming: bool,
|
||||
pub ssd_streaming_cold: bool,
|
||||
pub ssd_cache_experts: Option<i64>,
|
||||
pub ssd_cache_gib: Option<i64>,
|
||||
pub ssd_full_layers: Option<i32>,
|
||||
pub ssd_preload_experts: Option<i32>,
|
||||
pub directional_steering_file: Option<String>,
|
||||
pub directional_steering_ffn: Option<f32>,
|
||||
pub directional_steering_attn: Option<f32>,
|
||||
pub simulated_used_memory_gib: Option<i64>,
|
||||
pub expert_profile_path: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for AppPreferences {
|
||||
@@ -52,6 +73,23 @@ impl Default for AppPreferences {
|
||||
prefill_chunk: None,
|
||||
quality: false,
|
||||
warm_weights: false,
|
||||
mtp_draft_tokens: 1,
|
||||
mtp_margin: 3.0,
|
||||
glm_mtp: false,
|
||||
glm_mtp_timing: false,
|
||||
dspark_confidence_threshold: None,
|
||||
dspark_strict: false,
|
||||
ssd_streaming: false,
|
||||
ssd_streaming_cold: false,
|
||||
ssd_cache_experts: None,
|
||||
ssd_cache_gib: None,
|
||||
ssd_full_layers: None,
|
||||
ssd_preload_experts: None,
|
||||
directional_steering_file: None,
|
||||
directional_steering_ffn: None,
|
||||
directional_steering_attn: None,
|
||||
simulated_used_memory_gib: None,
|
||||
expert_profile_path: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,6 +137,65 @@ impl AppPreferences {
|
||||
warm_weights: self.warm_weights,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn speculative(&self) -> SpeculativePreferences {
|
||||
SpeculativePreferences {
|
||||
mtp_draft_tokens: self.mtp_draft_tokens,
|
||||
mtp_margin: self.mtp_margin,
|
||||
glm_mtp: self.glm_mtp,
|
||||
glm_mtp_timing: self.glm_mtp_timing,
|
||||
dspark_enabled: self.dspark_enabled,
|
||||
dspark_confidence_threshold: self.dspark_confidence_threshold,
|
||||
dspark_strict: self.dspark_strict,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn runtime(&self) -> Result<RuntimePreferences, String> {
|
||||
let cache = match (self.ssd_cache_experts, self.ssd_cache_gib) {
|
||||
(None, None) => None,
|
||||
(Some(experts), None) => Some(StreamingCacheBudget::Experts(
|
||||
u32::try_from(experts).map_err(|_| "Saved SSD expert count is invalid.")?,
|
||||
)),
|
||||
(None, Some(gib)) => Some(StreamingCacheBudget::Gib(
|
||||
u64::try_from(gib).map_err(|_| "Saved SSD cache budget is invalid.")?,
|
||||
)),
|
||||
(Some(_), Some(_)) => {
|
||||
return Err("Saved SSD cache budget has both count and GiB values.".into());
|
||||
}
|
||||
};
|
||||
Ok(RuntimePreferences {
|
||||
execution: self.execution()?,
|
||||
speculative: self.speculative(),
|
||||
ssd: SsdPreferences {
|
||||
enabled: self.ssd_streaming,
|
||||
cold: self.ssd_streaming_cold,
|
||||
cache,
|
||||
full_layers: self
|
||||
.ssd_full_layers
|
||||
.map(u32::try_from)
|
||||
.transpose()
|
||||
.map_err(|_| "Saved SSD full-layer count is invalid.")?,
|
||||
preload_experts: self
|
||||
.ssd_preload_experts
|
||||
.map(u32::try_from)
|
||||
.transpose()
|
||||
.map_err(|_| "Saved SSD preload count is invalid.")?,
|
||||
},
|
||||
steering: SteeringPreferences {
|
||||
file: self.directional_steering_file.clone(),
|
||||
ffn_scale: self.directional_steering_ffn,
|
||||
attention_scale: self.directional_steering_attn,
|
||||
},
|
||||
diagnostics: DiagnosticPreferences {
|
||||
simulated_used_memory_gib: self
|
||||
.simulated_used_memory_gib
|
||||
.map(u64::try_from)
|
||||
.transpose()
|
||||
.map_err(|_| "Saved simulated memory is invalid.")?,
|
||||
expert_profile_path: self.expert_profile_path.clone(),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(AsChangeset)]
|
||||
@@ -120,6 +217,23 @@ struct PreferenceChanges<'a> {
|
||||
prefill_chunk: Option<i32>,
|
||||
quality: bool,
|
||||
warm_weights: bool,
|
||||
mtp_draft_tokens: i32,
|
||||
mtp_margin: f32,
|
||||
glm_mtp: bool,
|
||||
glm_mtp_timing: bool,
|
||||
dspark_confidence_threshold: Option<f32>,
|
||||
dspark_strict: bool,
|
||||
ssd_streaming: bool,
|
||||
ssd_streaming_cold: bool,
|
||||
ssd_cache_experts: Option<i64>,
|
||||
ssd_cache_gib: Option<i64>,
|
||||
ssd_full_layers: Option<i32>,
|
||||
ssd_preload_experts: Option<i32>,
|
||||
directional_steering_file: Option<&'a str>,
|
||||
directional_steering_ffn: Option<f32>,
|
||||
directional_steering_attn: Option<f32>,
|
||||
simulated_used_memory_gib: Option<i64>,
|
||||
expert_profile_path: Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Identifiable, Queryable, Selectable)]
|
||||
@@ -220,20 +334,29 @@ impl Database {
|
||||
pub fn update_preferences(
|
||||
&mut self,
|
||||
selected_model: &str,
|
||||
dspark_enabled: bool,
|
||||
idle_timeout_minutes: i32,
|
||||
generation: &GenerationPreferences,
|
||||
execution: &ExecutionPreferences,
|
||||
runtime: &RuntimePreferences,
|
||||
) -> Result<AppPreferences, String> {
|
||||
generation.validate()?;
|
||||
let model = crate::model::ModelChoice::from_id(selected_model)
|
||||
.ok_or_else(|| format!("Unsupported model: {selected_model}"))?;
|
||||
execution.validate(model)?;
|
||||
runtime.engine_settings(model)?;
|
||||
let execution = &runtime.execution;
|
||||
let speculative = &runtime.speculative;
|
||||
let (ssd_cache_experts, ssd_cache_gib) = match runtime.ssd.cache {
|
||||
None => (None, None),
|
||||
Some(StreamingCacheBudget::Experts(experts)) => (Some(i64::from(experts)), None),
|
||||
Some(StreamingCacheBudget::Gib(gib)) => (
|
||||
None,
|
||||
Some(i64::try_from(gib).map_err(|_| "SSD cache budget is too large.")?),
|
||||
),
|
||||
};
|
||||
let seed = generation.seed.map(|seed| seed.to_string());
|
||||
diesel::update(preferences::table.find(1))
|
||||
.set(PreferenceChanges {
|
||||
selected_model,
|
||||
dspark_enabled,
|
||||
dspark_enabled: speculative.dspark_enabled,
|
||||
idle_timeout_minutes,
|
||||
context_tokens: generation.context_tokens,
|
||||
max_generated_tokens: generation.max_generated_tokens,
|
||||
@@ -248,6 +371,26 @@ impl Database {
|
||||
prefill_chunk: execution.prefill_chunk.map(|value| value as i32),
|
||||
quality: execution.quality,
|
||||
warm_weights: execution.warm_weights,
|
||||
mtp_draft_tokens: speculative.mtp_draft_tokens,
|
||||
mtp_margin: speculative.mtp_margin,
|
||||
glm_mtp: speculative.glm_mtp,
|
||||
glm_mtp_timing: speculative.glm_mtp_timing,
|
||||
dspark_confidence_threshold: speculative.dspark_confidence_threshold,
|
||||
dspark_strict: speculative.dspark_strict,
|
||||
ssd_streaming: runtime.ssd.enabled,
|
||||
ssd_streaming_cold: runtime.ssd.cold,
|
||||
ssd_cache_experts,
|
||||
ssd_cache_gib,
|
||||
ssd_full_layers: runtime.ssd.full_layers.map(|value| value as i32),
|
||||
ssd_preload_experts: runtime.ssd.preload_experts.map(|value| value as i32),
|
||||
directional_steering_file: runtime.steering.file.as_deref(),
|
||||
directional_steering_ffn: runtime.steering.ffn_scale,
|
||||
directional_steering_attn: runtime.steering.attention_scale,
|
||||
simulated_used_memory_gib: runtime
|
||||
.diagnostics
|
||||
.simulated_used_memory_gib
|
||||
.map(|value| value as i64),
|
||||
expert_profile_path: runtime.diagnostics.expert_profile_path.as_deref(),
|
||||
})
|
||||
.returning(AppPreferences::as_returning())
|
||||
.get_result(&mut self.connection)
|
||||
@@ -308,15 +451,26 @@ mod tests {
|
||||
assert!(!preferences.dspark_enabled);
|
||||
assert_eq!(preferences.idle_timeout_minutes, 10);
|
||||
let generation = GenerationPreferences::default();
|
||||
let execution = ExecutionPreferences::default();
|
||||
let runtime = RuntimePreferences::default();
|
||||
assert!(
|
||||
database
|
||||
.update_preferences("glm-5.2", true, 30, &generation, &execution)
|
||||
.update_preferences(
|
||||
"glm-5.2",
|
||||
30,
|
||||
&generation,
|
||||
&RuntimePreferences {
|
||||
speculative: SpeculativePreferences {
|
||||
dspark_enabled: true,
|
||||
..runtime.speculative.clone()
|
||||
},
|
||||
..runtime.clone()
|
||||
}
|
||||
)
|
||||
.is_err()
|
||||
);
|
||||
assert!(
|
||||
database
|
||||
.update_preferences("deepseek-v4-flash", false, 0, &generation, &execution)
|
||||
.update_preferences("deepseek-v4-flash", 0, &generation, &runtime,)
|
||||
.is_err()
|
||||
);
|
||||
let generation = GenerationPreferences {
|
||||
@@ -328,10 +482,33 @@ mod tests {
|
||||
let execution = ExecutionPreferences {
|
||||
cpu_threads: Some(8),
|
||||
quality: true,
|
||||
..execution
|
||||
..runtime.execution
|
||||
};
|
||||
let speculative = SpeculativePreferences {
|
||||
glm_mtp: true,
|
||||
glm_mtp_timing: true,
|
||||
mtp_draft_tokens: 4,
|
||||
mtp_margin: 2.5,
|
||||
..runtime.speculative
|
||||
};
|
||||
let runtime = RuntimePreferences {
|
||||
execution,
|
||||
speculative,
|
||||
ssd: SsdPreferences {
|
||||
enabled: true,
|
||||
cache: Some(StreamingCacheBudget::Gib(64)),
|
||||
full_layers: Some(0),
|
||||
preload_experts: Some(32),
|
||||
..SsdPreferences::default()
|
||||
},
|
||||
diagnostics: DiagnosticPreferences {
|
||||
simulated_used_memory_gib: Some(8),
|
||||
expert_profile_path: Some("/tmp/experts.json".into()),
|
||||
},
|
||||
..RuntimePreferences::default()
|
||||
};
|
||||
database
|
||||
.update_preferences("glm-5.2", false, 30, &generation, &execution)
|
||||
.update_preferences("glm-5.2", 30, &generation, &runtime)
|
||||
.unwrap();
|
||||
|
||||
let project = database.create_project("DS4", "/tmp/ds4").unwrap();
|
||||
@@ -354,7 +531,7 @@ mod tests {
|
||||
assert_eq!(preferences.selected_model, "glm-5.2");
|
||||
assert_eq!(preferences.idle_timeout_minutes, 30);
|
||||
assert_eq!(preferences.generation().unwrap(), generation);
|
||||
assert_eq!(preferences.execution().unwrap(), execution);
|
||||
assert_eq!(preferences.runtime().unwrap(), runtime);
|
||||
drop(reopened);
|
||||
fs::remove_file(path).unwrap();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user