use serde_json::Value;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Role {
System,
User,
Assistant,
Tool,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ChatMessage {
pub role: Role,
pub content: Option<String>,
pub tool_calls: Option<Vec<ToolCall>>,
pub tool_call_id: Option<String>,
pub name: Option<String>,
}
impl ChatMessage {
pub fn user(text: impl Into<String>) -> Self {
Self {
role: Role::User,
content: Some(text.into()),
tool_calls: None,
tool_call_id: None,
name: None,
}
}
pub fn system(text: impl Into<String>) -> Self {
Self {
role: Role::System,
content: Some(text.into()),
tool_calls: None,
tool_call_id: None,
name: None,
}
}
pub fn assistant(text: impl Into<String>) -> Self {
Self {
role: Role::Assistant,
content: Some(text.into()),
tool_calls: None,
tool_call_id: None,
name: None,
}
}
pub fn tool(tool_call_id: impl Into<String>, content: impl Into<String>) -> Self {
Self {
role: Role::Tool,
content: Some(content.into()),
tool_calls: None,
tool_call_id: Some(tool_call_id.into()),
name: None,
}
}
pub fn tool_with_name(
tool_call_id: impl Into<String>,
name: impl Into<String>,
content: impl Into<String>,
) -> Self {
Self {
role: Role::Tool,
content: Some(content.into()),
tool_calls: None,
tool_call_id: Some(tool_call_id.into()),
name: Some(name.into()),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ToolDefinition {
pub function: FunctionDefinition,
}
#[derive(Debug, Clone, PartialEq)]
pub struct FunctionDefinition {
pub name: String,
pub description: Option<String>,
pub parameters: Value,
}
impl FunctionDefinition {
pub fn new(name: impl Into<String>, parameters: Value) -> Self {
Self {
name: name.into(),
description: None,
parameters,
}
}
pub fn with_description(
name: impl Into<String>,
description: impl Into<String>,
parameters: Value,
) -> Self {
Self {
name: name.into(),
description: Some(description.into()),
parameters,
}
}
}
impl ToolDefinition {
pub fn function(name: impl Into<String>, parameters: Value) -> Self {
Self {
function: FunctionDefinition::new(name, parameters),
}
}
pub fn function_with_description(
name: impl Into<String>,
description: impl Into<String>,
parameters: Value,
) -> Self {
Self {
function: FunctionDefinition::with_description(name, description, parameters),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum ToolChoice {
None,
Auto,
Required,
Tool(String),
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct ChatRequest {
pub messages: Vec<ChatMessage>,
pub tools: Option<Vec<ToolDefinition>>,
pub tool_choice: Option<ToolChoice>,
pub temperature: Option<f32>,
pub max_tokens: Option<u32>,
pub top_p: Option<f32>,
}
impl ChatRequest {
pub fn single_user(text: impl Into<String>) -> Self {
Self {
messages: vec![ChatMessage::user(text)],
..Default::default()
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ChatResponse {
pub content: Option<String>,
pub tool_calls: Option<Vec<ToolCall>>,
pub finish_reason: Option<FinishReason>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ToolCall {
pub id: String,
pub function: FunctionCallResult,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FunctionCallResult {
pub name: String,
pub arguments: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FinishReason {
Stop,
Length,
ContentFilter,
ToolCalls,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ChatChunk {
pub delta: Option<String>,
pub tool_call_deltas: Option<Vec<ToolCallDelta>>,
pub finish_reason: Option<FinishReason>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ToolCallDelta {
pub index: u32,
pub id: Option<String>,
pub function_name: Option<String>,
pub function_arguments: Option<String>,
}
impl ChatChunk {
pub fn delta(text: impl Into<String>) -> Self {
Self {
delta: Some(text.into()),
tool_call_deltas: None,
finish_reason: None,
}
}
pub fn finish(reason: FinishReason) -> Self {
Self {
delta: None,
tool_call_deltas: None,
finish_reason: Some(reason),
}
}
pub fn tool_deltas(deltas: Vec<ToolCallDelta>) -> Self {
Self {
delta: None,
tool_call_deltas: Some(deltas),
finish_reason: None,
}
}
}