pub mod anthropic;
pub mod ollama;
pub mod openai;
pub use anthropic::AnthropicClient;
pub use ollama::OllamaClient;
pub use openai::OpenAiClient;
use crate::error::Error;
use async_trait::async_trait;
use futures::stream::BoxStream;
pub type TokenStream = BoxStream<'static, Result<String, Error>>;
#[derive(Debug, Clone)]
pub enum Role {
User,
Assistant,
Tool,
}
#[derive(Debug, Clone)]
pub struct Message {
pub role: Role,
pub content: String,
pub tool_call_id: Option<String>,
}
#[derive(Debug, Clone)]
pub struct ToolRequest {
pub name: String,
pub description: String,
pub parameters_schema: serde_json::Value,
}
#[derive(Debug, Clone)]
pub enum ToolChoice {
Auto,
None,
}
#[derive(Debug, Clone)]
pub struct ToolUseBlock {
pub id: String,
pub name: String,
pub input: serde_json::Value,
}
#[derive(Debug)]
pub enum CompletionResponse {
Text(String),
ToolUse {
blocks: Vec<ToolUseBlock>,
assistant_content: String,
},
}
#[derive(Debug, Clone)]
pub struct CompletionRequest {
pub system: Option<String>,
pub messages: Vec<Message>,
pub max_tokens: u32,
pub model_override: Option<String>,
pub schema: Option<serde_json::Value>,
pub tools: Option<Vec<ToolRequest>>,
pub tool_choice: Option<ToolChoice>,
}
#[async_trait]
pub trait LlmClient: Send + Sync {
fn default_model(&self) -> &str;
async fn complete(&self, request: CompletionRequest) -> Result<String, Error>;
async fn complete_stream(&self, request: CompletionRequest) -> Result<TokenStream, Error>;
async fn embed(&self, text: &str) -> Result<Vec<f32>, Error>;
async fn complete_with_tools(
&self,
request: CompletionRequest,
) -> Result<CompletionResponse, Error> {
let _ = request;
Err(Error::Unsupported)
}
}