ragrig_gpui/model/
settings.rs1#[derive(Clone, Debug, PartialEq)]
9pub struct ChatSettings {
10 pub model: String,
12 pub temperature: f64,
14 pub max_tokens: usize,
16 pub system_prompt: String,
18 pub stream: bool,
20}
21
22impl Default for ChatSettings {
23 fn default() -> Self {
24 Self {
25 model: "deepseek-chat".to_owned(),
26 temperature: 0.2,
27 max_tokens: 2048,
28 system_prompt: "Answer from the indexed corpus and cite sources.".to_owned(),
29 stream: true,
30 }
31 }
32}
33
34impl ChatSettings {
35 pub const MODELS: &'static [(&'static str, &'static str)] = &[
40 ("deepseek-chat", "DeepSeek Chat"),
41 ("qwen3:8b", "Qwen3 8B (Ollama)"),
42 ("gpt-oss:20b", "GPT-OSS 20B (Ollama)"),
43 ];
44
45 pub fn validate(&self) -> Result<(), String> {
47 if self.model.trim().is_empty() {
48 return Err("choose a chat model".to_owned());
49 }
50 if !self.temperature.is_finite() || !(0.0..=2.0).contains(&self.temperature) {
51 return Err("temperature must be between 0 and 2".to_owned());
52 }
53 if self.max_tokens == 0 {
54 return Err("max tokens must be at least 1".to_owned());
55 }
56 Ok(())
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn defaults_are_valid() {
66 assert_eq!(ChatSettings::default().validate(), Ok(()));
67 }
68
69 #[test]
70 fn invalid_values_are_rejected() {
71 let mut settings = ChatSettings {
72 model: " ".to_owned(),
73 ..Default::default()
74 };
75 assert_eq!(settings.validate(), Err("choose a chat model".to_owned()));
76
77 settings = ChatSettings {
78 temperature: 2.5,
79 ..Default::default()
80 };
81 assert_eq!(
82 settings.validate(),
83 Err("temperature must be between 0 and 2".to_owned())
84 );
85
86 settings = ChatSettings {
87 max_tokens: 0,
88 ..Default::default()
89 };
90 assert_eq!(
91 settings.validate(),
92 Err("max tokens must be at least 1".to_owned())
93 );
94 }
95
96 #[test]
97 fn the_default_model_is_in_the_offered_list() {
98 assert!(
99 ChatSettings::MODELS
100 .iter()
101 .any(|(id, _)| *id == ChatSettings::default().model)
102 );
103 }
104}