use async_trait::async_trait; use serde::{Deserialize, Serialize}; use crate::bus::message::ContentBlock; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Message { pub role: String, pub content: Vec, #[serde(skip_serializing_if = "Option::is_none")] pub tool_call_id: Option, #[serde(skip_serializing_if = "Option::is_none")] pub name: Option, #[serde(skip_serializing_if = "Option::is_none")] pub tool_calls: Option>, } impl Message { pub fn user(content: impl Into) -> Self { Self { role: "user".to_string(), content: vec![ContentBlock::text(content)], tool_call_id: None, name: None, tool_calls: None, } } pub fn user_with_blocks(content: Vec) -> Self { Self { role: "user".to_string(), content, tool_call_id: None, name: None, tool_calls: None, } } pub fn assistant(content: impl Into) -> Self { Self { role: "assistant".to_string(), content: vec![ContentBlock::text(content)], tool_call_id: None, name: None, tool_calls: None, } } pub fn system(content: impl Into) -> Self { Self { role: "system".to_string(), content: vec![ContentBlock::text(content)], tool_call_id: None, name: None, tool_calls: None, } } pub fn tool(tool_call_id: impl Into, tool_name: impl Into, content: impl Into) -> Self { Self { role: "tool".to_string(), content: vec![ContentBlock::text(content)], tool_call_id: Some(tool_call_id.into()), name: Some(tool_name.into()), tool_calls: None, } } } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Tool { #[serde(rename = "type")] pub tool_type: String, pub function: ToolFunction, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ToolFunction { pub name: String, pub description: String, pub parameters: serde_json::Value, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ToolCall { pub id: String, pub name: String, pub arguments: serde_json::Value, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ChatCompletionRequest { pub messages: Vec, pub temperature: Option, pub max_tokens: Option, pub tools: Option>, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ChatCompletionResponse { pub id: String, pub model: String, pub content: String, pub tool_calls: Vec, pub usage: Usage, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Usage { pub prompt_tokens: u32, pub completion_tokens: u32, pub total_tokens: u32, } #[async_trait] pub trait LLMProvider: Send + Sync { async fn chat( &self, request: ChatCompletionRequest, ) -> Result>; fn ptype(&self) -> &str; fn name(&self) -> &str; fn model_id(&self) -> &str; }