batch_mode_batch_scribe/
language_model_message.rs1crate::ix!();
3
4#[derive(Getters,Setters,Clone,Debug, Serialize, Deserialize)]
6#[getset(get="pub")]
7pub struct LanguageModelMessage {
8 #[serde(with = "message_role")]
10 role: LanguageModelMessageRole,
11 content: ChatCompletionRequestUserMessageContent,
13}
14
15impl LanguageModelMessage {
16
17 pub fn system_message(msg: &str) -> Self {
18 Self {
19 role: LanguageModelMessageRole::System,
20 content: ChatCompletionRequestUserMessageContent::Text(msg.to_string()),
21 }
22 }
23
24 pub fn user_message(msg: &str) -> Self {
25 Self {
26 role: LanguageModelMessageRole::User,
27 content: ChatCompletionRequestUserMessageContent::Text(msg.to_string()),
28 }
29 }
30
31 pub fn user_message_with_image(msg: &str, image_b64: &str) -> Self {
32
33 let image_url = ImageUrl {
34 url: image_b64.to_string(),
35 detail: Some(ImageDetail::High),
36 };
37
38 let text_part = ChatCompletionRequestMessageContentPartText { text: msg.into() };
39 let image_part = ChatCompletionRequestMessageContentPartImage { image_url };
40
41 let parts = vec![
42 ChatCompletionRequestUserMessageContentPart::Text(text_part),
43 ChatCompletionRequestUserMessageContentPart::ImageUrl(image_part),
44 ];
45
46 Self {
47 role: LanguageModelMessageRole::User,
48 content: ChatCompletionRequestUserMessageContent::Array(parts),
49 }
50 }
51}
52
53#[cfg(test)]
54mod language_model_message_exhaustive_tests {
55 use super::*;
56
57 #[traced_test]
58 fn system_message_construction_produces_correct_role_and_text() {
59 trace!("===== BEGIN TEST: system_message_construction_produces_correct_role_and_text =====");
60 let msg_text = "System message content";
61 let message = LanguageModelMessage::system_message(msg_text);
62 debug!("Constructed system message: {:?}", message);
63
64 match &message.role {
65 LanguageModelMessageRole::System => {
66 trace!("Message role is correct: System");
67 },
68 _ => {
69 error!("Expected role System, got something else");
70 panic!("Role mismatch");
71 },
72 }
73
74 match &message.content {
75 ChatCompletionRequestUserMessageContent::Text(text) => {
76 debug!("Message content is a text field: {}", text);
77 pretty_assert_eq!(text, msg_text, "Content text should match");
78 },
79 _ => {
80 error!("Expected text content, found a different variant");
81 panic!("Content mismatch");
82 }
83 }
84
85 trace!("===== END TEST: system_message_construction_produces_correct_role_and_text =====");
86 }
87
88 #[traced_test]
89 fn user_message_construction_produces_correct_role_and_text() {
90 trace!("===== BEGIN TEST: user_message_construction_produces_correct_role_and_text =====");
91 let msg_text = "User message content";
92 let message = LanguageModelMessage::user_message(msg_text);
93 debug!("Constructed user message: {:?}", message);
94
95 match &message.role {
96 LanguageModelMessageRole::User => {
97 trace!("Message role is correct: User");
98 },
99 _ => {
100 error!("Expected role User, got something else");
101 panic!("Role mismatch");
102 },
103 }
104
105 match &message.content {
106 ChatCompletionRequestUserMessageContent::Text(text) => {
107 debug!("Message content is a text field: {}", text);
108 pretty_assert_eq!(text, msg_text, "Content text should match");
109 },
110 _ => {
111 error!("Expected text content, found a different variant");
112 panic!("Content mismatch");
113 }
114 }
115
116 trace!("===== END TEST: user_message_construction_produces_correct_role_and_text =====");
117 }
118
119 #[traced_test]
120 fn user_message_with_image_construction_includes_text_and_image() {
121 trace!("===== BEGIN TEST: user_message_with_image_construction_includes_text_and_image =====");
122 let msg_text = "Look at this image";
123 let image_b64 = "base64image==";
124 let message = LanguageModelMessage::user_message_with_image(msg_text, image_b64);
125 debug!("Constructed user message with image: {:?}", message);
126
127 match &message.role {
128 LanguageModelMessageRole::User => {
129 trace!("Message role is correct: User");
130 },
131 _ => {
132 error!("Expected role User, got something else");
133 panic!("Role mismatch");
134 },
135 }
136
137 match &message.content {
138 ChatCompletionRequestUserMessageContent::Array(parts) => {
139 debug!("Message content is an array with {} part(s)", parts.len());
140 pretty_assert_eq!(parts.len(), 2, "Expected two parts: text + image");
141 match (&parts[0], &parts[1]) {
142 (
143 ChatCompletionRequestUserMessageContentPart::Text(ChatCompletionRequestMessageContentPartText{ text: t }),
144 ChatCompletionRequestUserMessageContentPart::ImageUrl(ChatCompletionRequestMessageContentPartImage { image_url: img }),
145 ) => {
146 debug!("Text part: {}, Image URL: {}", t, img.url);
147 pretty_assert_eq!(t, msg_text, "Text part should match original message");
148 pretty_assert_eq!(&img.url, image_b64, "Image URL should match input");
149 },
150 _ => {
151 error!("Array content did not have the expected (Text, ImageUrl) structure");
152 panic!("Parts mismatch");
153 }
154 }
155 },
156 _ => {
157 error!("Expected array content, found a different variant");
158 panic!("Content mismatch");
159 }
160 }
161
162 trace!("===== END TEST: user_message_with_image_construction_includes_text_and_image =====");
163 }
164
165 #[traced_test]
166 fn serialization_and_deserialization_of_system_message() {
167 trace!("===== BEGIN TEST: serialization_and_deserialization_of_system_message =====");
168 let original = LanguageModelMessage::system_message("Hello system");
169 let serialized = serde_json::to_string(&original)
170 .expect("Failed to serialize system message");
171 debug!("Serialized system message: {}", serialized);
172
173 let deserialized: LanguageModelMessage = serde_json::from_str(&serialized)
174 .expect("Failed to deserialize system message");
175 debug!("Deserialized system message: {:?}", deserialized);
176
177 pretty_assert_eq!(format!("{:?}", original.role), format!("{:?}", deserialized.role));
179 pretty_assert_eq!(format!("{:?}", original.content), format!("{:?}", deserialized.content));
180
181 trace!("===== END TEST: serialization_and_deserialization_of_system_message =====");
182 }
183
184 #[traced_test]
185 fn serialization_and_deserialization_of_user_message_with_image() {
186 trace!("===== BEGIN TEST: serialization_and_deserialization_of_user_message_with_image =====");
187 let original = LanguageModelMessage::user_message_with_image("User says hi", "b64encoded==");
188 let serialized = serde_json::to_string(&original)
189 .expect("Failed to serialize user message with image");
190 debug!("Serialized user message with image: {}", serialized);
191
192 let deserialized: LanguageModelMessage = serde_json::from_str(&serialized)
193 .expect("Failed to deserialize user message with image");
194 debug!("Deserialized user message with image: {:?}", deserialized);
195
196 pretty_assert_eq!(format!("{:?}", original.role), format!("{:?}", deserialized.role));
198 pretty_assert_eq!(format!("{:?}", original.content), format!("{:?}", deserialized.content));
199
200 trace!("===== END TEST: serialization_and_deserialization_of_user_message_with_image =====");
201 }
202}