14
14
use Symfony \AI \Agent \Chat \InitializableMessageStoreInterface ;
15
15
use Symfony \AI \Agent \Chat \MessageStoreInterface ;
16
16
use Symfony \AI \Agent \Exception \InvalidArgumentException ;
17
+ use Symfony \AI \Agent \Exception \LogicException ;
17
18
use Symfony \AI \Platform \Message \AssistantMessage ;
18
19
use Symfony \AI \Platform \Message \Content \Audio ;
19
20
use Symfony \AI \Platform \Message \Content \ContentInterface ;
26
27
use Symfony \AI \Platform \Message \MessageBagInterface ;
27
28
use Symfony \AI \Platform \Message \MessageInterface ;
28
29
use Symfony \AI \Platform \Message \SystemMessage ;
30
+ use Symfony \AI \Platform \Message \ToolCallMessage ;
29
31
use Symfony \AI \Platform \Message \UserMessage ;
32
+ use Symfony \AI \Platform \Result \ToolCall ;
30
33
use Symfony \Contracts \HttpClient \HttpClientInterface ;
31
34
32
35
/**
@@ -77,7 +80,7 @@ public function initialize(array $options = []): void
77
80
}
78
81
79
82
/**
80
- * @param array<string, mixed> $payload
83
+ * @param array<string, mixed>|list<array<string, mixed>> $payload
81
84
*
82
85
* @return array<string, mixed>
83
86
*/
@@ -94,12 +97,28 @@ private function request(string $method, string $endpoint, array $payload = []):
94
97
return $ result ->toArray ();
95
98
}
96
99
100
+ /**
101
+ * @return array<string, mixed>
102
+ */
97
103
private function convertToIndexableArray (MessageInterface $ message ): array
98
104
{
105
+ $ toolsCalls = [];
106
+
107
+ if ($ message instanceof AssistantMessage && $ message ->hasToolCalls ()) {
108
+ $ toolsCalls = array_map (
109
+ static fn (ToolCall $ toolCall ): array => $ toolCall ->jsonSerialize (),
110
+ $ message ->toolCalls ,
111
+ );
112
+ }
113
+
114
+ if ($ message instanceof ToolCallMessage) {
115
+ $ toolsCalls = $ message ->toolCall ->jsonSerialize ();
116
+ }
117
+
99
118
return [
100
119
'id ' => $ message ->getId ()->toRfc4122 (),
101
120
'type ' => $ message ::class,
102
- 'content ' => ($ message instanceof SystemMessage || $ message instanceof AssistantMessage) ? $ message ->content : '' ,
121
+ 'content ' => ($ message instanceof SystemMessage || $ message instanceof AssistantMessage || $ message instanceof ToolCallMessage ) ? $ message ->content : '' ,
103
122
'contentAsBase64 ' => ($ message instanceof UserMessage && [] !== $ message ->content ) ? array_map (
104
123
static fn (ContentInterface $ content ) => [
105
124
'type ' => $ content ::class,
@@ -110,15 +129,18 @@ private function convertToIndexableArray(MessageInterface $message): array
110
129
Audio::class => $ content ->asBase64 (),
111
130
ImageUrl::class,
112
131
DocumentUrl::class => $ content ->url ,
113
- default => throw new \ LogicException (\sprintf ('Unknown content type "%s". ' , $ content ::class)),
132
+ default => throw new LogicException (\sprintf ('Unknown content type "%s". ' , $ content ::class)),
114
133
},
115
134
],
116
135
$ message ->content ,
117
136
) : [],
118
- 'toolsCalls ' => ( $ message instanceof AssistantMessage && $ message -> hasToolCalls ()) ? $ message -> toolCalls : [] ,
137
+ 'toolsCalls ' => $ toolsCalls ,
119
138
];
120
139
}
121
140
141
+ /**
142
+ * @param array<string, mixed> $payload
143
+ */
122
144
private function convertToMessage (array $ payload ): MessageInterface
123
145
{
124
146
$ type = $ payload ['type ' ];
@@ -127,14 +149,29 @@ private function convertToMessage(array $payload): MessageInterface
127
149
128
150
return match ($ type ) {
129
151
SystemMessage::class => new SystemMessage ($ content ),
130
- AssistantMessage::class => new AssistantMessage ($ content , $ payload ['toolsCalls ' ] ?? []),
152
+ AssistantMessage::class => new AssistantMessage ($ content , array_map (
153
+ static fn (array $ toolsCall ): ToolCall => new ToolCall (
154
+ $ toolsCall ['id ' ],
155
+ $ toolsCall ['function ' ]['name ' ],
156
+ json_decode ($ toolsCall ['function ' ]['arguments ' ], true )
157
+ ),
158
+ $ payload ['toolsCalls ' ],
159
+ )),
131
160
UserMessage::class => new UserMessage (...array_map (
132
161
static fn (array $ contentAsBase64 ) => \in_array ($ contentAsBase64 ['type ' ], [File::class, Image::class, Audio::class], true )
133
162
? $ contentAsBase64 ['type ' ]::fromDataUrl ($ contentAsBase64 ['content ' ])
134
163
: new $ contentAsBase64 ['type ' ]($ contentAsBase64 ['content ' ]),
135
164
$ contentAsBase64 ,
136
165
)),
137
- default => throw new \LogicException (\sprintf ('Unknown message type "%s". ' , $ type )),
166
+ ToolCallMessage::class => new ToolCallMessage (
167
+ new ToolCall (
168
+ $ payload ['toolsCalls ' ]['id ' ],
169
+ $ payload ['toolsCalls ' ]['function ' ]['name ' ],
170
+ json_decode ($ payload ['toolsCalls ' ]['function ' ]['arguments ' ], true )
171
+ ),
172
+ $ content
173
+ ),
174
+ default => throw new LogicException (\sprintf ('Unknown message type "%s". ' , $ type )),
138
175
};
139
176
}
140
177
}
0 commit comments