use super::client::MediaFile;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ChatRole {
System,
User,
Assistant,
}
impl ChatRole {
pub fn as_str(&self) -> &'static str {
match self {
ChatRole::System => "system",
ChatRole::User => "user",
ChatRole::Assistant => "assistant",
}
}
}
#[derive(Debug, Clone)]
pub struct ChatMessage {
pub role: ChatRole,
pub content: String,
pub media: Vec<MediaFile>,
}
impl ChatMessage {
pub fn new(role: ChatRole, content: impl Into<String>) -> Self {
Self {
role,
content: content.into(),
media: Vec::new(),
}
}
pub fn user(content: impl Into<String>) -> Self {
Self::new(ChatRole::User, content)
}
pub fn user_with_media(content: impl Into<String>, media: Vec<MediaFile>) -> Self {
let mut msg = Self::new(ChatRole::User, content);
msg.media = media;
msg
}
pub fn assistant(content: impl Into<String>) -> Self {
Self::new(ChatRole::Assistant, content)
}
pub fn system(content: impl Into<String>) -> Self {
Self::new(ChatRole::System, content)
}
}
#[cfg(feature = "_client")]
pub(crate) fn request_messages(
system: Option<&str>,
prompt: &str,
media: &[MediaFile],
) -> Vec<ChatMessage> {
let mut messages = Vec::with_capacity(usize::from(system.is_some()) + 1);
if let Some(system) = system {
messages.push(ChatMessage::system(system));
}
messages.push(ChatMessage::user_with_media(prompt, media.to_vec()));
messages
}
#[cfg(feature = "_client")]
#[derive(Debug)]
pub struct MaterializeInternalOutput<T> {
pub data: T,
#[allow(dead_code)]
pub raw_response: String,
pub usage: Option<crate::backend::TokenUsage>,
}
#[cfg(feature = "_client")]
impl<T> MaterializeInternalOutput<T> {
pub fn new(data: T, raw_response: String, usage: Option<crate::backend::TokenUsage>) -> Self {
Self {
data,
raw_response,
usage,
}
}
}
#[cfg(feature = "_client")]
#[derive(Debug, Clone)]
pub struct ValidationFailureContext {
pub error_message: String,
pub raw_response: String,
}
#[cfg(feature = "_client")]
impl ValidationFailureContext {
pub fn new(error_message: impl Into<String>, raw_response: impl Into<String>) -> Self {
Self {
error_message: error_message.into(),
raw_response: raw_response.into(),
}
}
}
#[cfg(feature = "_client")]
#[derive(Debug)]
pub(crate) enum MaterializeAttemptError {
Preflight(Box<crate::RStructorError>),
Transport {
error: Box<crate::RStructorError>,
usage: Option<crate::backend::TokenUsage>,
},
Semantic {
error: Box<crate::RStructorError>,
context: ValidationFailureContext,
usage: Option<crate::backend::TokenUsage>,
},
}
#[cfg(feature = "_client")]
impl MaterializeAttemptError {
pub(crate) fn preflight(error: crate::RStructorError) -> Self {
Self::Preflight(Box::new(error))
}
pub(crate) fn transport(error: crate::RStructorError) -> Self {
Self::Transport {
error: Box::new(error),
usage: None,
}
}
pub(crate) fn transport_with_usage(
error: crate::RStructorError,
usage: Option<crate::backend::TokenUsage>,
) -> Self {
Self::Transport {
error: Box::new(error),
usage,
}
}
pub(crate) fn semantic(
error: crate::RStructorError,
context: ValidationFailureContext,
usage: Option<crate::backend::TokenUsage>,
) -> Self {
Self::Semantic {
error: Box::new(error),
context,
usage,
}
}
}