use async_trait::async_trait;
use futures_util::Stream;
use std::pin::Pin;
use super::base::{BaseOutputParser, OutputParserError, OutputParserResult};
use crate::runnables::{Runnable, RunnableConfig};
pub struct CommaSeparatedListOutputParser;
impl CommaSeparatedListOutputParser {
pub fn new() -> Self {
Self
}
}
impl Default for CommaSeparatedListOutputParser {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl BaseOutputParser<Vec<String>> for CommaSeparatedListOutputParser {
async fn parse(&self, text: &str) -> OutputParserResult<Vec<String>> {
let text = text.trim();
if text.is_empty() {
return Ok(Vec::new());
}
let items: Vec<String> = text
.split(',')
.flat_map(|item| item.split(','))
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect();
Ok(items)
}
fn get_format_instructions(&self) -> String {
"请用逗号分隔的列表形式输出,例如:项目1, 项目2, 项目3".to_string()
}
}
#[async_trait]
impl Runnable<String, Vec<String>> for CommaSeparatedListOutputParser {
type Error = OutputParserError;
async fn invoke(
&self,
input: String,
_config: Option<RunnableConfig>,
) -> Result<Vec<String>, Self::Error> {
self.parse(&input).await
}
async fn stream(
&self,
input: String,
_config: Option<RunnableConfig>,
) -> Result<Pin<Box<dyn Stream<Item = Result<Vec<String>, Self::Error>> + Send>>, Self::Error>
{
let result = self.parse(&input).await?;
let stream = futures_util::stream::once(async move { Ok(result) });
Ok(Box::pin(stream))
}
}