Skip to main content

synaptic_parsers/
list_parser.rs

1use async_trait::async_trait;
2use synaptic_core::{RunnableConfig, SynapticError};
3use synaptic_runnables::Runnable;
4
5use crate::FormatInstructions;
6
7/// Separator used to split the input into a list.
8#[derive(Debug, Clone)]
9pub enum ListSeparator {
10    Newline,
11    Comma,
12    Custom(String),
13}
14
15/// Parses a string into a list of strings by splitting on the configured separator.
16pub struct ListOutputParser {
17    separator: ListSeparator,
18}
19
20impl ListOutputParser {
21    pub fn new(separator: ListSeparator) -> Self {
22        Self { separator }
23    }
24
25    /// Creates a parser that splits on newlines (default).
26    pub fn newline() -> Self {
27        Self::new(ListSeparator::Newline)
28    }
29
30    /// Creates a parser that splits on commas.
31    pub fn comma() -> Self {
32        Self::new(ListSeparator::Comma)
33    }
34}
35
36impl Default for ListOutputParser {
37    fn default() -> Self {
38        Self::newline()
39    }
40}
41
42impl FormatInstructions for ListOutputParser {
43    fn get_format_instructions(&self) -> String {
44        let sep_desc = match &self.separator {
45            ListSeparator::Newline => "newlines",
46            ListSeparator::Comma => "commas",
47            ListSeparator::Custom(s) => s.as_str(),
48        };
49        format!("Your response should be a list of items separated by {sep_desc}.")
50    }
51}
52
53#[async_trait]
54impl Runnable<String, Vec<String>> for ListOutputParser {
55    async fn invoke(
56        &self,
57        input: String,
58        _config: &RunnableConfig,
59    ) -> Result<Vec<String>, SynapticError> {
60        let sep = match &self.separator {
61            ListSeparator::Newline => "\n",
62            ListSeparator::Comma => ",",
63            ListSeparator::Custom(s) => s.as_str(),
64        };
65
66        let items: Vec<String> = input
67            .split(sep)
68            .map(|s| s.trim().to_string())
69            .filter(|s| !s.is_empty())
70            .collect();
71
72        Ok(items)
73    }
74}