2024-08-06 07:56:13 +08:00
|
|
|
use appflowy_plugin::error::PluginError;
|
2024-08-12 15:43:17 +08:00
|
|
|
|
2024-08-06 07:56:13 +08:00
|
|
|
use flowy_ai_pub::cloud::QuestionStreamValue;
|
|
|
|
use flowy_error::FlowyError;
|
|
|
|
use futures::{ready, Stream};
|
|
|
|
use pin_project::pin_project;
|
2024-08-12 15:43:17 +08:00
|
|
|
use serde_json::Value;
|
2024-08-06 07:56:13 +08:00
|
|
|
use std::pin::Pin;
|
|
|
|
use std::task::{Context, Poll};
|
2024-08-12 15:43:17 +08:00
|
|
|
use tracing::error;
|
|
|
|
|
|
|
|
pub const STEAM_METADATA_KEY: &str = "0";
|
|
|
|
pub const STEAM_ANSWER_KEY: &str = "1";
|
2024-08-06 07:56:13 +08:00
|
|
|
|
|
|
|
#[pin_project]
|
2024-08-12 15:43:17 +08:00
|
|
|
pub struct QuestionStream {
|
|
|
|
stream: Pin<Box<dyn Stream<Item = Result<Value, PluginError>> + Send>>,
|
2024-08-06 07:56:13 +08:00
|
|
|
buffer: Vec<u8>,
|
|
|
|
}
|
|
|
|
|
2024-08-12 15:43:17 +08:00
|
|
|
impl QuestionStream {
|
2024-08-06 07:56:13 +08:00
|
|
|
pub fn new<S>(stream: S) -> Self
|
|
|
|
where
|
2024-08-12 15:43:17 +08:00
|
|
|
S: Stream<Item = Result<Value, PluginError>> + Send + 'static,
|
2024-08-06 07:56:13 +08:00
|
|
|
{
|
2024-08-12 15:43:17 +08:00
|
|
|
QuestionStream {
|
2024-08-06 07:56:13 +08:00
|
|
|
stream: Box::pin(stream),
|
|
|
|
buffer: Vec::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-12 15:43:17 +08:00
|
|
|
impl Stream for QuestionStream {
|
2024-08-06 07:56:13 +08:00
|
|
|
type Item = Result<QuestionStreamValue, FlowyError>;
|
|
|
|
|
|
|
|
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
|
|
|
let this = self.project();
|
2024-08-12 15:43:17 +08:00
|
|
|
|
2024-08-06 13:17:56 +08:00
|
|
|
match ready!(this.stream.as_mut().poll_next(cx)) {
|
2024-08-12 15:43:17 +08:00
|
|
|
Some(Ok(value)) => match value {
|
|
|
|
Value::Object(mut value) => {
|
|
|
|
if let Some(metadata) = value.remove(STEAM_METADATA_KEY) {
|
|
|
|
return Poll::Ready(Some(Ok(QuestionStreamValue::Metadata { value: metadata })));
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(answer) = value
|
|
|
|
.remove(STEAM_ANSWER_KEY)
|
|
|
|
.and_then(|s| s.as_str().map(ToString::to_string))
|
|
|
|
{
|
|
|
|
return Poll::Ready(Some(Ok(QuestionStreamValue::Answer { value: answer })));
|
|
|
|
}
|
|
|
|
|
|
|
|
error!("Invalid streaming value: {:?}", value);
|
|
|
|
Poll::Ready(None)
|
|
|
|
},
|
|
|
|
_ => {
|
|
|
|
error!("Unexpected JSON value type: {:?}", value);
|
|
|
|
Poll::Ready(None)
|
|
|
|
},
|
2024-08-06 07:56:13 +08:00
|
|
|
},
|
|
|
|
Some(Err(err)) => Poll::Ready(Some(Err(FlowyError::local_ai().with_context(err)))),
|
|
|
|
None => Poll::Ready(None),
|
2024-08-06 13:17:56 +08:00
|
|
|
}
|
2024-08-06 07:56:13 +08:00
|
|
|
}
|
|
|
|
}
|