use async_trait::async_trait;
use futures::Stream;
use std::pin::Pin;
use crate::error::LLMError;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Role {
System,
User,
Assistant,
}
#[derive(Debug, Clone)]
pub struct LLMMessage {
pub role: Role,
pub content: String,
}
impl LLMMessage {
#[must_use]
pub fn system(content: impl Into<String>) -> Self {
Self {
role: Role::System,
content: content.into(),
}
}
#[must_use]
pub fn user(content: impl Into<String>) -> Self {
Self {
role: Role::User,
content: content.into(),
}
}
#[must_use]
pub fn assistant(content: impl Into<String>) -> Self {
Self {
role: Role::Assistant,
content: content.into(),
}
}
}
#[derive(Debug, Clone, Default)]
pub struct TokenUsage {
pub prompt: u32,
pub completion: u32,
pub total: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FinishReason {
Stop,
Length,
Error,
}
#[derive(Debug, Clone)]
pub struct LLMResponse {
pub content: String,
pub tokens_used: TokenUsage,
pub finish_reason: FinishReason,
pub model: String,
}
#[derive(Debug, Clone)]
pub struct StreamChunk {
pub content: String,
pub done: bool,
pub tokens_used: Option<TokenUsage>,
pub finish_reason: Option<FinishReason>,
}
#[async_trait]
pub trait LLMAdapter: Send + Sync {
fn provider(&self) -> &str;
fn model(&self) -> &str;
async fn generate(&self, messages: &[LLMMessage]) -> Result<LLMResponse, LLMError>;
fn generate_stream(
&self,
messages: &[LLMMessage],
) -> Pin<Box<dyn Stream<Item = Result<StreamChunk, LLMError>> + Send + '_>>;
async fn health_check(&self) -> Result<bool, LLMError>;
}