use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use serde_json::Value;
#[async_trait]
pub trait LlmCall: Send + Sync {
async fn call(&self, messages: Vec<Message>) -> Result<String, String>;
async fn call_with_tools(
&self,
messages: Vec<Value>,
tools: &[ToolDef],
) -> Result<CallResult, String> {
let simple: Vec<Message> = messages
.into_iter()
.filter_map(|m| {
let role = m.get("role")?.as_str()?;
let content = m.get("content")?.as_str()?.to_string();
let role = match role {
"system" => MessageRole::System,
"user" => MessageRole::User,
"assistant" => MessageRole::Assistant,
_ => return None,
};
Some(Message { role, content })
})
.collect();
let _ = tools; let text = self.call(simple).await?;
Ok(CallResult::Text(text))
}
}
#[derive(Debug, Clone)]
pub struct Message {
pub role: MessageRole,
pub content: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MessageRole {
System,
User,
Assistant,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolDef {
pub name: String,
pub description: String,
pub parameters: Value,
}
#[derive(Debug, Clone, Deserialize)]
pub struct ToolCall {
pub id: String,
pub name: String,
pub arguments: String,
}
#[derive(Debug, Clone)]
pub enum CallResult {
Text(String),
ToolCalls(Vec<ToolCall>),
}