1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
4#[serde(rename_all = "lowercase")]
5pub enum Role {
6 System,
7 User,
8 Assistant,
9 Tool,
10}
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct ChatMessage {
14 pub role: Role,
15 #[serde(default)]
16 pub content: String,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pub name: Option<String>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub tool_calls: Option<Vec<ToolCall>>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub tool_call_id: Option<String>,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct ToolCall {
27 pub id: String,
28 #[serde(rename = "type")]
29 pub call_type: String,
30 pub function: FunctionCall,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct FunctionCall {
35 pub name: String,
36 pub arguments: String,
37}
38
39impl ChatMessage {
40 pub fn system(content: impl Into<String>) -> Self {
41 Self {
42 role: Role::System,
43 content: content.into(),
44 name: None,
45 tool_calls: None,
46 tool_call_id: None,
47 }
48 }
49
50 pub fn user(content: impl Into<String>) -> Self {
51 Self {
52 role: Role::User,
53 content: content.into(),
54 name: None,
55 tool_calls: None,
56 tool_call_id: None,
57 }
58 }
59
60 pub fn assistant(content: impl Into<String>) -> Self {
61 Self {
62 role: Role::Assistant,
63 content: content.into(),
64 name: None,
65 tool_calls: None,
66 tool_call_id: None,
67 }
68 }
69
70 pub fn tool(content: impl Into<String>, tool_call_id: impl Into<String>) -> Self {
71 Self {
72 role: Role::Tool,
73 content: content.into(),
74 name: None,
75 tool_calls: None,
76 tool_call_id: Some(tool_call_id.into()),
77 }
78 }
79}
80
81#[derive(Debug, Clone)]
82pub struct ChatSession {
83 pub messages: Vec<ChatMessage>,
84 pub system_prompt: Option<String>,
85}
86
87impl ChatSession {
88 pub fn new() -> Self {
89 Self {
90 messages: Vec::new(),
91 system_prompt: None,
92 }
93 }
94
95 pub fn with_system_prompt(mut self, prompt: impl Into<String>) -> Self {
96 self.system_prompt = Some(prompt.into());
97 self
98 }
99
100 pub fn add_message(&mut self, message: ChatMessage) {
101 self.messages.push(message);
102 }
103
104 pub fn add_user_message(&mut self, content: impl Into<String>) {
105 self.messages.push(ChatMessage::user(content));
106 }
107
108 pub fn add_assistant_message(&mut self, content: impl Into<String>) {
109 self.messages.push(ChatMessage::assistant(content));
110 }
111
112 pub fn get_messages(&self) -> Vec<ChatMessage> {
113 let mut messages = Vec::new();
114
115 if let Some(ref system_prompt) = self.system_prompt {
116 messages.push(ChatMessage::system(system_prompt.clone()));
117 }
118
119 messages.extend(self.messages.clone());
120 messages
121 }
122
123 pub fn clear(&mut self) {
124 self.messages.clear();
125 }
126}
127
128impl Default for ChatSession {
129 fn default() -> Self {
130 Self::new()
131 }
132}