semantic_operators/
locate.rs1use crate::{
3 Answer, AnswerValue, Boolean, BoxQuestion, Error, ErrorKind, Provider, Region, Request, Result,
4 ask,
5};
6use indexmap::IndexMap;
7
8#[derive(Clone, Debug)]
10pub struct LocateOptions {
11 pub where_: String,
13 pub min_presence: f64,
15 pub min_box_confidence: f64,
17}
18impl Default for LocateOptions {
19 fn default() -> Self {
20 Self {
21 where_: "the image".into(),
22 min_presence: 0.5,
23 min_box_confidence: 0.0,
24 }
25 }
26}
27#[derive(Clone, Debug)]
29pub struct Located {
30 pub found: Option<bool>,
32 pub region: Option<Region>,
34 pub presence: Answer<AnswerValue>,
36 pub box_answer: Answer<AnswerValue>,
38}
39
40pub async fn locate(
52 provider: &dyn Provider,
53 request: &Request,
54 target: &str,
55 options: LocateOptions,
56) -> Result<Located> {
57 if crate::question::is_blank(target) {
58 return Err(Error::new(
59 ErrorKind::InvalidArgument,
60 "target must be a non-empty description",
61 ));
62 }
63 let presence = Boolean::new(format!("Is there {target} in {}?", options.where_))?
64 .with_min_confidence(options.min_presence)?;
65 let region = BoxQuestion::new(format!("{target} in {}", options.where_))?
66 .with_min_confidence(options.min_box_confidence)?;
67 let questions = IndexMap::from([
68 ("present".into(), presence.into()),
69 ("box".into(), region.into()),
70 ]);
71 let request = request.with_questions(questions)?;
72 let mut answers = ask(provider, &request).await?;
73 let presence = answers
74 .shift_remove("present")
75 .ok_or_else(|| Error::new(ErrorKind::InvalidResponse, "missing presence answer"))?;
76 let box_answer = answers
77 .shift_remove("box")
78 .ok_or_else(|| Error::new(ErrorKind::InvalidResponse, "missing box answer"))?;
79 let found = match presence.value() {
80 Some(AnswerValue::Boolean(value)) => Some(*value),
81 _ => None,
82 };
83 let region = if found == Some(true) {
84 match box_answer.value() {
85 Some(AnswerValue::Box(region)) => Some(*region),
86 _ => None,
87 }
88 } else {
89 None
90 };
91 Ok(Located {
92 found,
93 region,
94 presence,
95 box_answer,
96 })
97}