1use derive_builder::Builder;
9
10use crate::{Embedding, SparseEmbedding, document::Document, util::debug_long_utf8};
11
12#[derive(Clone, Default, Builder, PartialEq)]
20#[builder(setter(into))]
21pub struct Query<STATE: QueryState> {
22 original: String,
23 #[builder(default = "self.original.clone().unwrap_or_default()")]
24 current: String,
25 #[builder(default = STATE::default())]
26 state: STATE,
27 #[builder(default)]
28 transformation_history: Vec<TransformationEvent>,
29
30 #[builder(default)]
32 pub embedding: Option<Embedding>,
33
34 #[builder(default)]
35 pub sparse_embedding: Option<SparseEmbedding>,
36
37 #[builder(default)]
41 pub documents: Vec<Document>,
42}
43
44impl<STATE: std::fmt::Debug + QueryState> std::fmt::Debug for Query<STATE> {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 f.debug_struct("Query")
47 .field(
48 "original",
49 &debug_long_utf8(&self.original, 100).lines().take(1),
50 )
51 .field(
52 "current",
53 &debug_long_utf8(&self.current, 100).lines().take(1),
54 )
55 .field("state", &self.state)
56 .field("num_transformations", &self.transformation_history.len())
57 .field("embedding", &self.embedding.is_some())
58 .field("num_documents", &self.documents.len())
59 .finish()
60 }
61}
62
63impl<STATE: Clone + QueryState> Query<STATE> {
64 pub fn builder() -> QueryBuilder<STATE> {
65 QueryBuilder::default().clone()
66 }
67
68 pub fn original(&self) -> &str {
70 &self.original
71 }
72
73 pub fn current(&self) -> &str {
75 &self.current
76 }
77
78 fn transition_to<NEWSTATE: QueryState>(self, new_state: NEWSTATE) -> Query<NEWSTATE> {
79 Query {
80 state: new_state,
81 original: self.original,
82 current: self.current,
83 transformation_history: self.transformation_history,
84 embedding: self.embedding,
85 sparse_embedding: self.sparse_embedding,
86 documents: self.documents,
87 }
88 }
89
90 #[allow(dead_code)]
91 pub fn history(&self) -> &Vec<TransformationEvent> {
92 &self.transformation_history
93 }
94
95 pub fn documents(&self) -> &[Document] {
97 &self.documents
98 }
99
100 pub fn documents_mut(&mut self) -> &mut Vec<Document> {
102 &mut self.documents
103 }
104}
105
106impl<STATE: Clone + CanRetrieve> Query<STATE> {
107 pub fn retrieved_documents(mut self, documents: Vec<Document>) -> Query<states::Retrieved> {
109 self.documents.extend(documents.clone());
110 self.transformation_history
111 .push(TransformationEvent::Retrieved {
112 before: self.current.clone(),
113 after: self.current.clone(),
114 documents,
115 });
116
117 let state = states::Retrieved;
118
119 self.transition_to(state)
120 }
121}
122
123impl Query<states::Pending> {
124 pub fn new(query: impl Into<String>) -> Self {
125 Self {
126 original: query.into(),
127 ..Default::default()
128 }
129 }
130
131 pub fn transformed_query(&mut self, new_query: impl Into<String>) {
133 let new_query = new_query.into();
134
135 self.transformation_history
136 .push(TransformationEvent::Transformed {
137 before: self.current.clone(),
138 after: new_query.clone(),
139 });
140
141 self.current = new_query;
142 }
143}
144
145impl Query<states::Retrieved> {
146 pub fn new() -> Self {
147 Self::default()
148 }
149
150 pub fn transformed_response(&mut self, new_response: impl Into<String>) {
152 let new_response = new_response.into();
153
154 self.transformation_history
155 .push(TransformationEvent::Transformed {
156 before: self.current.clone(),
157 after: new_response.clone(),
158 });
159
160 self.current = new_response;
161 }
162
163 #[must_use]
165 pub fn answered(mut self, answer: impl Into<String>) -> Query<states::Answered> {
166 self.current = answer.into();
167 let state = states::Answered;
168 self.transition_to(state)
169 }
170}
171
172impl Query<states::Answered> {
173 pub fn new() -> Self {
174 Self::default()
175 }
176
177 pub fn answer(&self) -> &str {
179 &self.current
180 }
181}
182
183pub trait QueryState: Send + Sync + Default {}
185pub trait CanRetrieve: QueryState {}
187
188pub mod states {
190 use super::{CanRetrieve, QueryState};
191
192 #[derive(Debug, Default, Clone, PartialEq)]
193 pub struct Pending;
195
196 #[derive(Debug, Default, Clone, PartialEq)]
197 pub struct Retrieved;
199
200 #[derive(Debug, Default, Clone, PartialEq)]
201 pub struct Answered;
203
204 impl QueryState for Pending {}
205 impl QueryState for Retrieved {}
206 impl QueryState for Answered {}
207
208 impl CanRetrieve for Pending {}
209 impl CanRetrieve for Retrieved {}
210}
211
212impl<T: AsRef<str>> From<T> for Query<states::Pending> {
213 fn from(original: T) -> Self {
214 Self {
215 original: original.as_ref().to_string(),
216 current: original.as_ref().to_string(),
217 state: states::Pending,
218 ..Default::default()
219 }
220 }
221}
222
223#[derive(Clone, PartialEq)]
224pub enum TransformationEvent {
226 Transformed {
227 before: String,
228 after: String,
229 },
230 Retrieved {
231 before: String,
232 after: String,
233 documents: Vec<Document>,
234 },
235}
236
237impl TransformationEvent {
238 pub fn is_retrieval(&self) -> bool {
240 matches!(self, TransformationEvent::Retrieved { .. })
241 }
242
243 pub fn is_transformation(&self) -> bool {
245 matches!(self, TransformationEvent::Transformed { .. })
246 }
247
248 pub fn before(&self) -> &str {
250 match self {
251 TransformationEvent::Transformed { before, .. }
252 | TransformationEvent::Retrieved { before, .. } => before,
253 }
254 }
255
256 pub fn after(&self) -> &str {
258 match self {
259 TransformationEvent::Transformed { after, .. }
260 | TransformationEvent::Retrieved { after, .. } => after,
261 }
262 }
263
264 pub fn documents(&self) -> Option<&[Document]> {
266 match self {
267 TransformationEvent::Retrieved { documents, .. } => Some(documents),
268 TransformationEvent::Transformed { .. } => None,
269 }
270 }
271}
272
273impl std::fmt::Debug for TransformationEvent {
274 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275 match self {
276 TransformationEvent::Transformed { before, after } => {
277 write!(
278 f,
279 "Transformed: {} -> {}",
280 debug_long_utf8(before, 100),
281 debug_long_utf8(after, 100)
282 )
283 }
284 TransformationEvent::Retrieved {
285 before,
286 after,
287 documents,
288 } => {
289 write!(
290 f,
291 "Retrieved: {} -> {}\nDocuments: {:?}",
292 debug_long_utf8(before, 100),
293 debug_long_utf8(after, 100),
294 documents.len()
295 )
296 }
297 }
298 }
299}
300
301#[cfg(test)]
302mod tests {
303 use super::*;
304
305 #[test]
306 fn test_query_initial_state() {
307 let query = Query::<states::Pending>::from("test query");
308 assert_eq!(query.original(), "test query");
309 assert_eq!(query.current(), "test query");
310 assert_eq!(query.history().len(), 0);
311 }
312
313 #[test]
314 fn test_query_transformed_query() {
315 let mut query = Query::<states::Pending>::from("test query");
316 query.transformed_query("new query");
317 assert_eq!(query.current(), "new query");
318 assert_eq!(query.history().len(), 1);
319 if let TransformationEvent::Transformed { before, after } = &query.history()[0] {
320 assert_eq!(before, "test query");
321 assert_eq!(after, "new query");
322 } else {
323 panic!("Unexpected event in history");
324 }
325 }
326
327 #[test]
328 fn test_query_retrieved_documents() {
329 let query = Query::<states::Pending>::from("test query");
330 let documents: Vec<Document> = vec!["doc1".into(), "doc2".into()];
331 let query = query.retrieved_documents(documents.clone());
332 assert_eq!(query.documents(), &documents);
333 assert_eq!(query.history().len(), 1);
334 if let TransformationEvent::Retrieved {
335 before,
336 after,
337 documents: retrieved_docs,
338 } = &query.history()[0]
339 {
340 assert_eq!(before, "test query");
341 assert_eq!(after, "test query");
342 assert_eq!(retrieved_docs, &documents);
343 } else {
344 panic!("Unexpected event in history");
345 }
346 }
347
348 #[test]
349 fn test_query_transformed_response() {
350 let query = Query::<states::Pending>::from("test query");
351 let documents = vec!["doc1".into(), "doc2".into()];
352 let mut query = query.retrieved_documents(documents.clone());
353 query.transformed_response("new response");
354
355 assert_eq!(query.current(), "new response");
356 assert_eq!(query.history().len(), 2);
357 assert_eq!(query.documents(), &documents);
358 assert_eq!(query.original, "test query");
359 if let TransformationEvent::Transformed { before, after } = &query.history()[1] {
360 assert_eq!(before, "test query");
361 assert_eq!(after, "new response");
362 } else {
363 panic!("Unexpected event in history");
364 }
365 }
366
367 #[test]
368 fn test_query_answered() {
369 let query = Query::<states::Pending>::from("test query");
370 let documents = vec!["doc1".into(), "doc2".into()];
371 let query = query.retrieved_documents(documents);
372 let query = query.answered("the answer");
373
374 assert_eq!(query.answer(), "the answer");
375 }
376}