1use crate::prelude::*;
2
3#[derive(Clone, PartialEq, Deserialize, Serialize)]
4#[cfg_attr(feature = "ts_rs", derive(TS))]
5pub struct ChatbotConfiguration {
6 pub id: Uuid,
7 pub created_at: DateTime<Utc>,
8 pub updated_at: DateTime<Utc>,
9 pub deleted_at: Option<DateTime<Utc>>,
10 pub course_id: Uuid,
11 pub enabled_to_students: bool,
12 pub chatbot_name: String,
13 pub prompt: String,
14 pub initial_message: String,
15 pub weekly_tokens_per_user: i32,
16 pub daily_tokens_per_user: i32,
17 pub temperature: f32,
18 pub top_p: f32,
19 pub frequency_penalty: f32,
20 pub presence_penalty: f32,
21 pub response_max_tokens: i32,
22 pub use_azure_search: bool,
23 pub maintain_azure_search_index: bool,
24 pub hide_citations: bool,
25 pub use_semantic_reranking: bool,
26 pub default_chatbot: bool,
27}
28
29impl Default for ChatbotConfiguration {
30 fn default() -> Self {
31 Self {
32 id: Uuid::nil(),
33 created_at: Default::default(),
34 updated_at: Default::default(),
35 deleted_at: None,
36 course_id: Default::default(),
37 enabled_to_students: false,
38 chatbot_name: Default::default(),
39 prompt: Default::default(),
40 initial_message: Default::default(),
41 weekly_tokens_per_user: 20000 * 5,
42 daily_tokens_per_user: 20000,
43 temperature: 0.7,
44 top_p: 1.0,
45 frequency_penalty: Default::default(),
46 presence_penalty: Default::default(),
47 response_max_tokens: 500,
48 use_azure_search: false,
49 maintain_azure_search_index: false,
50 hide_citations: false,
51 use_semantic_reranking: false,
52 default_chatbot: false,
53 }
54 }
55}
56
57#[derive(Clone, PartialEq, Deserialize, Serialize)]
58#[cfg_attr(feature = "ts_rs", derive(TS))]
59pub struct NewChatbotConf {
60 pub course_id: Uuid,
61 pub enabled_to_students: bool,
62 pub chatbot_name: String,
63 pub prompt: String,
64 pub initial_message: String,
65 pub weekly_tokens_per_user: i32,
66 pub daily_tokens_per_user: i32,
67 pub temperature: f32,
68 pub top_p: f32,
69 pub frequency_penalty: f32,
70 pub presence_penalty: f32,
71 pub response_max_tokens: i32,
72 pub use_azure_search: bool,
73 pub maintain_azure_search_index: bool,
74 pub hide_citations: bool,
75 pub use_semantic_reranking: bool,
76 pub default_chatbot: bool,
77}
78
79impl Default for NewChatbotConf {
80 fn default() -> Self {
81 let chatbot_conf: ChatbotConfiguration = ChatbotConfiguration::default();
82 Self {
83 course_id: chatbot_conf.course_id,
84 enabled_to_students: chatbot_conf.enabled_to_students,
85 chatbot_name: chatbot_conf.chatbot_name,
86 prompt: chatbot_conf.prompt,
87 initial_message: chatbot_conf.initial_message,
88 weekly_tokens_per_user: chatbot_conf.weekly_tokens_per_user,
89 daily_tokens_per_user: chatbot_conf.daily_tokens_per_user,
90 temperature: chatbot_conf.temperature,
91 top_p: chatbot_conf.top_p,
92 frequency_penalty: chatbot_conf.frequency_penalty,
93 presence_penalty: chatbot_conf.presence_penalty,
94 response_max_tokens: chatbot_conf.response_max_tokens,
95 use_azure_search: chatbot_conf.use_azure_search,
96 maintain_azure_search_index: chatbot_conf.maintain_azure_search_index,
97 hide_citations: chatbot_conf.hide_citations,
98 use_semantic_reranking: chatbot_conf.use_semantic_reranking,
99 default_chatbot: chatbot_conf.default_chatbot,
100 }
101 }
102}
103
104pub async fn get_by_id(conn: &mut PgConnection, id: Uuid) -> ModelResult<ChatbotConfiguration> {
105 let res = sqlx::query_as!(
106 ChatbotConfiguration,
107 r#"
108SELECT * FROM chatbot_configurations
109WHERE id = $1
110AND deleted_at IS NULL
111 "#,
112 id
113 )
114 .fetch_one(conn)
115 .await?;
116 Ok(res)
117}
118
119pub async fn insert(
120 conn: &mut PgConnection,
121 input: NewChatbotConf,
122) -> ModelResult<ChatbotConfiguration> {
123 let res = sqlx::query_as!(
124 ChatbotConfiguration,
125 r#"
126INSERT INTO chatbot_configurations (
127 course_id,
128 enabled_to_students,
129 chatbot_name,
130 prompt,
131 initial_message,
132 weekly_tokens_per_user,
133 daily_tokens_per_user,
134 temperature,
135 top_p,
136 frequency_penalty,
137 presence_penalty,
138 response_max_tokens
139 )
140VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
141RETURNING *
142 "#,
143 input.course_id,
144 input.enabled_to_students,
145 input.chatbot_name,
146 input.prompt,
147 input.initial_message,
148 input.weekly_tokens_per_user,
149 input.daily_tokens_per_user,
150 input.temperature,
151 input.top_p,
152 input.frequency_penalty,
153 input.presence_penalty,
154 input.response_max_tokens
155 )
156 .fetch_one(conn)
157 .await?;
158 Ok(res)
159}
160
161pub async fn edit(
162 conn: &mut PgConnection,
163 input: NewChatbotConf,
164 chatbot_configuration_id: Uuid,
165) -> ModelResult<ChatbotConfiguration> {
166 let res = sqlx::query_as!(
167 ChatbotConfiguration,
168 r#"
169UPDATE chatbot_configurations AS cc
170SET
171 enabled_to_students = $1,
172 chatbot_name = $2,
173 prompt = $3,
174 initial_message = $4,
175 weekly_tokens_per_user = $5,
176 daily_tokens_per_user = $6,
177 temperature = $7,
178 top_p = $8,
179 frequency_penalty = $9,
180 presence_penalty = $10,
181 response_max_tokens = $11,
182 use_azure_search = $12,
183 maintain_azure_search_index = $13,
184 hide_citations = $14,
185 use_semantic_reranking = $15,
186 default_chatbot = $16
187WHERE cc.id = $17
188RETURNING *"#,
189 input.enabled_to_students,
190 input.chatbot_name,
191 input.prompt,
192 input.initial_message,
193 input.weekly_tokens_per_user,
194 input.daily_tokens_per_user,
195 input.temperature,
196 input.top_p,
197 input.frequency_penalty,
198 input.presence_penalty,
199 input.response_max_tokens,
200 input.use_azure_search,
201 input.maintain_azure_search_index,
202 input.hide_citations,
203 input.use_semantic_reranking,
204 input.default_chatbot,
205 chatbot_configuration_id
206 )
207 .fetch_one(conn)
208 .await?;
209 Ok(res)
210}
211
212pub async fn delete(conn: &mut PgConnection, chatbot_configuration_id: Uuid) -> ModelResult<()> {
213 sqlx::query!(
214 r#"
215UPDATE chatbot_configurations
216SET deleted_at = now()
217WHERE id = $1
218AND deleted_at IS NULL
219 "#,
220 chatbot_configuration_id
221 )
222 .execute(conn)
223 .await?;
224 Ok(())
225}
226
227pub async fn get_for_course(
228 conn: &mut PgConnection,
229 course_id: Uuid,
230) -> ModelResult<Vec<ChatbotConfiguration>> {
231 let res = sqlx::query_as!(
232 ChatbotConfiguration,
233 r#"
234SELECT * FROM
235chatbot_configurations
236WHERE course_id = $1
237AND deleted_at IS NULL
238"#,
239 course_id
240 )
241 .fetch_all(conn)
242 .await?;
243 Ok(res)
244}
245
246pub async fn get_enabled_nondefault_for_course(
247 conn: &mut PgConnection,
248 course_id: Uuid,
249) -> ModelResult<Vec<ChatbotConfiguration>> {
250 let res = sqlx::query_as!(
251 ChatbotConfiguration,
252 r#"
253SELECT * FROM
254chatbot_configurations
255WHERE course_id = $1
256AND default_chatbot IS false
257AND enabled_to_students IS true
258AND deleted_at IS NULL
259"#,
260 course_id
261 )
262 .fetch_all(conn)
263 .await?;
264 Ok(res)
265}
266
267pub async fn get_for_azure_search_maintenance(
268 conn: &mut PgConnection,
269) -> ModelResult<Vec<ChatbotConfiguration>> {
270 let res = sqlx::query_as!(
271 ChatbotConfiguration,
272 r#"
273SELECT * FROM
274chatbot_configurations
275WHERE maintain_azure_search_index = true
276AND deleted_at IS NULL
277"#,
278 )
279 .fetch_all(conn)
280 .await?;
281 Ok(res)
282}
283
284pub async fn remove_default_chatbot_from_course(
285 conn: &mut PgConnection,
286 course_id: Uuid,
287) -> ModelResult<()> {
288 sqlx::query!(
289 r#"
290UPDATE chatbot_configurations
291SET default_chatbot = false
292WHERE course_id = $1
293AND default_chatbot = true
294AND deleted_at IS NULL
295"#,
296 course_id,
297 )
298 .execute(conn)
299 .await?;
300 Ok(())
301}
302
303pub async fn set_default_chatbot_for_course(
304 conn: &mut PgConnection,
305 chatbot_configuration_id: Uuid,
306) -> ModelResult<ChatbotConfiguration> {
307 let res = sqlx::query_as!(
308 ChatbotConfiguration,
309 r#"
310UPDATE chatbot_configurations
311SET default_chatbot = true
312WHERE id = $1
313RETURNING *
314"#,
315 chatbot_configuration_id,
316 )
317 .fetch_one(conn)
318 .await?;
319 Ok(res)
320}