Skip to content

Commit aa626db

Browse files
committed
refactor: consolidate message handling by removing Text and Image classes
- Replaced the Text and Image message classes with a unified Message class to streamline message handling. - Updated all relevant code and tests to utilize the new Message class, ensuring compatibility and functionality. - Enhanced the Message class to include MIME type detection for better attachment management.
1 parent 25a8232 commit aa626db

18 files changed

Lines changed: 144 additions & 306 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ tests/chunk.php
55
.idea/
66
.env
77
example.php
8-
example.md
8+
example.md
9+
/blueprints/

README.md

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@ Utopia Framework requires PHP 8.0 or later. We recommend using the latest PHP ve
3737
<?php
3838

3939
use Utopia\Agents\Agent;
40+
use Utopia\Agents\Message;
4041
use Utopia\Agents\Roles\User;
41-
use Utopia\Agents\Messages\Text;
42-
use Utopia\Agents\Messages\Image;
4342
use Utopia\Agents\Conversation;
4443
use Utopia\Agents\Adapters\OpenAI;
4544

@@ -53,7 +52,7 @@ $user = new User('user-1', 'John');
5352
// Start a conversation
5453
$conversation = new Conversation($agent);
5554
$conversation
56-
->message($user, new Text('What is artificial intelligence?'))
55+
->message($user, new Message('What is artificial intelligence?'))
5756
->send();
5857
```
5958

@@ -185,7 +184,7 @@ $openrouter = new OpenRouter(
185184
```php
186185
use Utopia\Agents\Roles\User;
187186
use Utopia\Agents\Roles\Assistant;
188-
use Utopia\Agents\Messages\Text;
187+
use Utopia\Agents\Message;
189188

190189
// Create a conversation with system instructions
191190
$agent = new Agent($adapter);
@@ -200,15 +199,15 @@ $assistant = new Assistant('assistant-1');
200199

201200
$conversation = new Conversation($agent);
202201
$conversation
203-
->message($user, new Text('Hello!'))
204-
->message($assistant, new Text('Hi! How can I help you today?'))
205-
->message($user, new Text('What is the capital of France?'));
202+
->message($user, new Message('Hello!'))
203+
->message($assistant, new Message('Hi! How can I help you today?'))
204+
->message($user, new Message('What is the capital of France?'));
206205

207206
// Add a user message with attachments
208207
$conversation->message(
209208
$user,
210-
new Text('Please summarize this screenshot'),
211-
[new Image($imageBinaryContent)]
209+
new Message('Please summarize this screenshot'),
210+
[new Message($imageBinaryContent)]
212211
);
213212

214213
// Send and get response
@@ -226,8 +225,8 @@ The callback receives each text delta as it arrives from the provider's SSE stre
226225
use Utopia\Agents\Agent;
227226
use Utopia\Agents\Conversation;
228227
use Utopia\Agents\Adapters\OpenAI;
228+
use Utopia\Agents\Message;
229229
use Utopia\Agents\Roles\User;
230-
use Utopia\Agents\Messages\Text;
231230

232231
$agent = new Agent(new OpenAI('your-api-key', OpenAI::MODEL_GPT_4O));
233232
$conversation = new Conversation($agent);
@@ -237,7 +236,7 @@ $conversation
237236
->listen(function (string $chunk): void {
238237
echo $chunk; // render partial output as soon as it is received
239238
})
240-
->message($user, new Text('Explain vector databases in one paragraph.'));
239+
->message($user, new Message('Explain vector databases in one paragraph.'));
241240

242241
$final = $conversation->send(); // final, complete assistant message
243242
```
@@ -248,8 +247,8 @@ $final = $conversation->send(); // final, complete assistant message
248247
use Utopia\Agents\Agent;
249248
use Utopia\Agents\Conversation;
250249
use Utopia\Agents\Adapters\OpenAI;
250+
use Utopia\Agents\Message;
251251
use Utopia\Agents\Roles\User;
252-
use Utopia\Agents\Messages\Text;
253252

254253
header('Content-Type: text/event-stream');
255254
header('Cache-Control: no-cache');
@@ -269,7 +268,7 @@ $conversation
269268
}
270269
flush();
271270
})
272-
->message($user, new Text('Write a short release note for today''s deployment.'));
271+
->message($user, new Message('Write a short release note for today''s deployment.'));
273272

274273
$final = $conversation->send();
275274

@@ -291,26 +290,24 @@ flush();
291290
### Working with Messages
292291

293292
```php
294-
use Utopia\Agents\Messages\Text;
295-
use Utopia\Agents\Messages\Image;
293+
use Utopia\Agents\Message;
296294

297-
// Text message
298-
$textMessage = new Text('Hello, how are you?');
295+
// Message content is always text
296+
$textMessage = new Message('Hello, how are you?');
299297

300-
// Image message
301-
$imageMessage = new Image($imageBinaryContent);
298+
// Attachments are binary payloads (for example images)
299+
$imageMessage = new Message($imageBinaryContent);
302300
$mimeType = $imageMessage->getMimeType(); // Get the MIME type of the image
303301

304302
// Attach image to a text prompt
305-
$message = (new Text('Describe this image'))->addAttachment($imageMessage);
303+
$message = (new Message('Describe this image'))->addAttachment($imageMessage);
306304
```
307305

308306
### Attachment Examples
309307

310308
```php
311309
use Utopia\Agents\Conversation;
312-
use Utopia\Agents\Messages\Image;
313-
use Utopia\Agents\Messages\Text;
310+
use Utopia\Agents\Message;
314311
use Utopia\Agents\Roles\User;
315312

316313
$conversation = new Conversation($agent);
@@ -319,23 +316,23 @@ $user = new User('user-1', 'John');
319316
// 1) Attach a single image in the same turn
320317
$conversation->message(
321318
$user,
322-
new Text('What is shown here?'),
323-
[new Image(file_get_contents(__DIR__.'/images/screenshot.png'))]
319+
new Message('What is shown here?'),
320+
[new Message(file_get_contents(__DIR__.'/images/screenshot.png'))]
324321
);
325322

326323
// 2) Attach multiple images in one turn
327324
$conversation->message(
328325
$user,
329-
new Text('Compare these two images and list differences.'),
326+
new Message('Compare these two images and list differences.'),
330327
[
331-
new Image(file_get_contents(__DIR__.'/images/before.png')),
332-
new Image(file_get_contents(__DIR__.'/images/after.png')),
328+
new Message(file_get_contents(__DIR__.'/images/before.png')),
329+
new Message(file_get_contents(__DIR__.'/images/after.png')),
333330
]
334331
);
335332

336333
// 3) Build and reuse a message object with attachments
337-
$prompt = (new Text('Extract visible text from this receipt'))
338-
->addAttachment(new Image(file_get_contents(__DIR__.'/images/receipt.jpg')));
334+
$prompt = (new Message('Extract visible text from this receipt'))
335+
->addAttachment(new Message(file_get_contents(__DIR__.'/images/receipt.jpg')));
339336

340337
$conversation->message($user, $prompt);
341338
```

src/Agents/Adapter.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,17 @@ public function supportsAttachment(Message $attachment): bool
129129
return $this->supportsAttachments();
130130
}
131131

132+
protected function isImageAttachment(Message $attachment): bool
133+
{
134+
if ($attachment->getContent() === '') {
135+
return false;
136+
}
137+
138+
$mimeType = $attachment->getMimeType();
139+
140+
return $mimeType !== null && str_starts_with($mimeType, 'image/');
141+
}
142+
132143
/**
133144
* Maximum attachments allowed per single conversation message.
134145
* Null means adapter does not set this limit.

src/Agents/Adapters/Anthropic.php

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
use Utopia\Agents\Adapter;
66
use Utopia\Agents\Message;
7-
use Utopia\Agents\Messages\Image;
8-
use Utopia\Agents\Messages\Text;
97
use Utopia\Fetch\Chunk;
108
use Utopia\Fetch\Client;
119

@@ -235,7 +233,7 @@ function ($chunk) use (&$content, $listener) {
235233
}
236234

237235
if ($payload['stream']) {
238-
return new Text($content);
236+
return new Message($content);
239237
}
240238

241239
$body = $response->getBody();
@@ -258,7 +256,7 @@ function ($chunk) use (&$content, $listener) {
258256
$text = is_string($body) ? $body : (is_array($json) ? (json_encode($json) ?: '') : '');
259257
}
260258

261-
return new Text($text);
259+
return new Message($text);
262260
}
263261

264262
/**
@@ -268,19 +266,15 @@ protected function formatMessageContent(Message $message): array|string
268266
{
269267
$parts = [];
270268

271-
if (! ($message instanceof Image) && $message->getContent() !== '') {
269+
if ($message->getContent() !== '') {
272270
$parts[] = [
273271
'type' => 'text',
274272
'text' => $message->getContent(),
275273
];
276274
}
277275

278-
if ($message instanceof Image && $message->getContent() !== '') {
279-
$parts[] = $this->buildImagePart($message);
280-
}
281-
282276
foreach ($message->getAttachments() as $attachment) {
283-
if (! $attachment instanceof Image || $attachment->getContent() === '') {
277+
if (! $this->isImageAttachment($attachment)) {
284278
continue;
285279
}
286280

@@ -303,7 +297,7 @@ protected function formatMessageContent(Message $message): array|string
303297
/**
304298
* @return array<string, mixed>
305299
*/
306-
protected function buildImagePart(Image $image): array
300+
protected function buildImagePart(Message $image): array
307301
{
308302
$mimeType = $image->getMimeType() ?? 'application/octet-stream';
309303
$mediaType = str_starts_with($mimeType, 'image/') ? $mimeType : 'application/octet-stream';
@@ -491,7 +485,7 @@ public function supportsAttachments(): bool
491485

492486
public function supportsAttachment(Message $attachment): bool
493487
{
494-
return $attachment instanceof Image;
488+
return $this->isImageAttachment($attachment);
495489
}
496490

497491
public function getMaxAttachmentsPerMessage(): ?int

src/Agents/Adapters/Deepseek.php

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
use Utopia\Agents\Adapter;
66
use Utopia\Agents\Message;
7-
use Utopia\Agents\Messages\Image;
8-
use Utopia\Agents\Messages\Text;
97
use Utopia\Fetch\Chunk;
108
use Utopia\Fetch\Client;
119

@@ -164,21 +162,17 @@ function ($chunk) use (&$content, $listener) {
164162
);
165163
}
166164

167-
return new Text($content);
165+
return new Message($content);
168166
}
169167

170168
protected function hasTextOrImageContent(Message $message): bool
171169
{
172-
if ($message instanceof Image && $message->getContent() !== '') {
173-
return true;
174-
}
175-
176170
if ($message->getContent() !== '') {
177171
return true;
178172
}
179173

180174
foreach ($message->getAttachments() as $attachment) {
181-
if ($attachment instanceof Image && $attachment->getContent() !== '') {
175+
if ($this->isImageAttachment($attachment)) {
182176
return true;
183177
}
184178
}
@@ -193,19 +187,15 @@ protected function formatMessageContent(Message $message): string|array
193187
{
194188
$parts = [];
195189

196-
if (! ($message instanceof Image) && $message->getContent() !== '') {
190+
if ($message->getContent() !== '') {
197191
$parts[] = [
198192
'type' => 'text',
199193
'text' => $message->getContent(),
200194
];
201195
}
202196

203-
if ($message instanceof Image && $message->getContent() !== '') {
204-
$parts[] = $this->buildImagePart($message);
205-
}
206-
207197
foreach ($message->getAttachments() as $attachment) {
208-
if (! $attachment instanceof Image || $attachment->getContent() === '') {
198+
if (! $this->isImageAttachment($attachment)) {
209199
continue;
210200
}
211201

@@ -228,7 +218,7 @@ protected function formatMessageContent(Message $message): string|array
228218
/**
229219
* @return array<string, mixed>
230220
*/
231-
protected function buildImagePart(Image $image): array
221+
protected function buildImagePart(Message $image): array
232222
{
233223
$mimeType = $image->getMimeType() ?? 'application/octet-stream';
234224

@@ -368,7 +358,7 @@ public function supportsAttachments(): bool
368358

369359
public function supportsAttachment(Message $attachment): bool
370360
{
371-
return $attachment instanceof Image;
361+
return $this->isImageAttachment($attachment);
372362
}
373363

374364
public function getMaxAttachmentsPerMessage(): ?int

src/Agents/Adapters/Gemini.php

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
use Utopia\Agents\Adapter;
66
use Utopia\Agents\Message;
7-
use Utopia\Agents\Messages\Image;
8-
use Utopia\Agents\Messages\Text;
97
use Utopia\Fetch\Chunk;
108
use Utopia\Fetch\Client;
119

@@ -168,7 +166,7 @@ function ($chunk) use (&$content, $listener) {
168166
);
169167
}
170168

171-
$message = new Text($content);
169+
$message = new Message($content);
172170

173171
return $message;
174172
}
@@ -180,18 +178,14 @@ protected function formatMessageParts(Message $message): array
180178
{
181179
$parts = [];
182180

183-
if (! ($message instanceof Image) && $message->getContent() !== '') {
181+
if ($message->getContent() !== '') {
184182
$parts[] = [
185183
'text' => $message->getContent(),
186184
];
187185
}
188186

189-
if ($message instanceof Image && $message->getContent() !== '') {
190-
$parts[] = $this->buildImagePart($message);
191-
}
192-
193187
foreach ($message->getAttachments() as $attachment) {
194-
if (! $attachment instanceof Image || $attachment->getContent() === '') {
188+
if (! $this->isImageAttachment($attachment)) {
195189
continue;
196190
}
197191

@@ -210,7 +204,7 @@ protected function formatMessageParts(Message $message): array
210204
/**
211205
* @return array<string, mixed>
212206
*/
213-
protected function buildImagePart(Image $image): array
207+
protected function buildImagePart(Message $image): array
214208
{
215209
$mimeType = $image->getMimeType() ?? 'application/octet-stream';
216210

@@ -364,7 +358,7 @@ public function supportsAttachments(): bool
364358

365359
public function supportsAttachment(Message $attachment): bool
366360
{
367-
return $attachment instanceof Image;
361+
return $this->isImageAttachment($attachment);
368362
}
369363

370364
public function getMaxAttachmentsPerMessage(): ?int

0 commit comments

Comments
 (0)