haematite_cli/serve/embed/
question.rs1use haem_frames::embedding::Kind;
10
11use super::{Answer, Embedded, Embedder};
12use crate::serve::storage::Failure;
13use crate::serve::storage::embedded::{Declaration, ModelName};
14
15pub trait Ask {
17 fn question(&self, text: &str) -> Result<Embedded, Failure>;
23}
24
25impl Ask for Embedder {
26 fn question(&self, text: &str) -> Result<Embedded, Failure> {
27 self.embed(Kind::Query, &[text.to_owned()])
28 }
29}
30
31pub fn question_for(
41 asker: &dyn Ask,
42 text: &str,
43 declaration: &Declaration,
44) -> Result<Vec<f32>, Failure> {
45 let embedded = asker.question(text)?;
46 let count = embedded.answers.len();
47 let model = ModelName {
48 name: embedded.model.name,
49 revision: embedded.model.revision,
50 manifest_sha256: embedded.model.manifest_sha256,
51 };
52 let mut answers = embedded.answers.into_iter();
53 let (Some(answer), None) = (answers.next(), answers.next()) else {
54 return Err(Failure::new(
55 "embed_vector_count",
56 format!("one question was sent and {count} vectors came back"),
57 ));
58 };
59 if model != declaration.model {
60 return Err(Failure::new(
61 "embed_model_mismatch",
62 format!(
63 "the question worker runs {}; the field is declared for {}",
64 model.name, declaration.model.name
65 ),
66 ));
67 }
68 let vector = match answer {
69 Answer::Vector(vector) => vector,
70 Answer::Windows(_) => {
73 return Err(Failure::new(
74 "embed_vector_count",
75 "the question worker answered windows for one question",
76 ));
77 }
78 Answer::Longer(longer) | Answer::OverCap(longer) => {
79 return Err(Failure::new(
80 "text_longer_than_model",
81 format!(
82 "the question is {} tokens; the model's limit is {}",
83 longer.tokens_total, longer.tokens_limit
84 ),
85 ));
86 }
87 };
88 let dimensions = declaration.dimensions.get();
89 if vector.len() != dimensions {
90 return Err(Failure::new(
91 "embed_vector_length",
92 format!(
93 "a question vector of {} members came back; {dimensions} are declared",
94 vector.len()
95 ),
96 ));
97 }
98 Ok(vector)
99}
100
101#[cfg(test)]
102#[path = "question_tests.rs"]
103mod tests;