langchain_rust/output_parsers/
boolean_parser.rs1use super::{
2 typed::{preview, string_output_parser, strip_reasoning},
3 OutputParserError, TypedOutputParser,
4};
5
6#[derive(Debug, Clone)]
12pub struct BooleanParser {
13 true_values: Vec<String>,
14 false_values: Vec<String>,
15}
16
17impl Default for BooleanParser {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22
23impl BooleanParser {
24 pub fn new() -> Self {
25 Self {
26 true_values: vec!["YES".into(), "TRUE".into()],
27 false_values: vec!["NO".into(), "FALSE".into()],
28 }
29 }
30
31 pub fn with_values<T, F>(mut self, true_values: T, false_values: F) -> Self
33 where
34 T: IntoIterator,
35 T::Item: Into<String>,
36 F: IntoIterator,
37 F::Item: Into<String>,
38 {
39 self.true_values = true_values
40 .into_iter()
41 .map(|v| v.into().to_uppercase())
42 .collect();
43 self.false_values = false_values
44 .into_iter()
45 .map(|v| v.into().to_uppercase())
46 .collect();
47 self
48 }
49}
50
51impl TypedOutputParser for BooleanParser {
52 type Output = bool;
53
54 fn format_instructions(&self) -> String {
55 format!(
56 "Answer with only `{}` or `{}`.",
57 self.true_values
58 .first()
59 .map(String::as_str)
60 .unwrap_or("YES"),
61 self.false_values
62 .first()
63 .map(String::as_str)
64 .unwrap_or("NO"),
65 )
66 }
67
68 fn parse_output(&self, text: &str) -> Result<bool, OutputParserError> {
69 let normalized = strip_reasoning(text)
70 .trim()
71 .trim_end_matches('.')
72 .trim_matches(|c| matches!(c, '\'' | '"' | '`'))
73 .trim()
74 .to_uppercase();
75 if self.true_values.contains(&normalized) {
76 Ok(true)
77 } else if self.false_values.contains(&normalized) {
78 Ok(false)
79 } else {
80 Err(OutputParserError::ParsingError(format!(
81 "expected one of {:?} or {:?}, got {}",
82 self.true_values,
83 self.false_values,
84 preview(text)
85 )))
86 }
87 }
88}
89
90string_output_parser!(BooleanParser, |value| value.to_string());