diff --git a/src/Responses/Chat/CreateResponseToolCall.php b/src/Responses/Chat/CreateResponseToolCall.php index 17560b2ef..de61a4540 100644 --- a/src/Responses/Chat/CreateResponseToolCall.php +++ b/src/Responses/Chat/CreateResponseToolCall.php @@ -6,14 +6,18 @@ final class CreateResponseToolCall { + /** + * @param array>|null $extraContent + */ private function __construct( public readonly string $id, public readonly string $type, public readonly CreateResponseToolCallFunction $function, + public readonly ?array $extraContent = null, ) {} /** - * @param array{id: string, type?: string, function: array{name: string, arguments: string}} $attributes + * @param array{id: string, type?: string, function: array{name: string, arguments: string}, extra_content?: array>|null} $attributes */ public static function from(array $attributes): self { @@ -21,18 +25,20 @@ public static function from(array $attributes): self $attributes['id'], $attributes['type'] ?? 'function', CreateResponseToolCallFunction::from($attributes['function']), + $attributes['extra_content'] ?? null, ); } /** - * @return array{id: string, type: string, function: array{name: string, arguments: string}} + * @return array{id: string, type: string, function: array{name: string, arguments: string}, extra_content?: array>} */ public function toArray(): array { - return [ + return array_filter([ 'id' => $this->id, 'type' => $this->type, 'function' => $this->function->toArray(), - ]; + 'extra_content' => $this->extraContent, + ], fn (mixed $value): bool => ! is_null($value)); } } diff --git a/src/Responses/Chat/CreateStreamedResponseToolCall.php b/src/Responses/Chat/CreateStreamedResponseToolCall.php index 9173c653b..6cf6e4270 100644 --- a/src/Responses/Chat/CreateStreamedResponseToolCall.php +++ b/src/Responses/Chat/CreateStreamedResponseToolCall.php @@ -6,15 +6,19 @@ final class CreateStreamedResponseToolCall { + /** + * @param array>|null $extraContent + */ private function __construct( public readonly ?int $index, public readonly ?string $id, public readonly ?string $type, public readonly CreateStreamedResponseToolCallFunction $function, + public readonly ?array $extraContent, ) {} /** - * @param array{index?: int, id?: string, type?: string, function: array{name?: string, arguments: string}} $attributes + * @param array{index?: int, id?: string, type?: string, function: array{name?: string, arguments: string}, extra_content?: array>|null} $attributes */ public static function from(array $attributes): self { @@ -23,11 +27,12 @@ public static function from(array $attributes): self $attributes['id'] ?? null, $attributes['type'] ?? null, CreateStreamedResponseToolCallFunction::from($attributes['function']), + $attributes['extra_content'] ?? null, ); } /** - * @return array{index?: int, id?: string, type?: string, function?: array{name?: string, arguments: string}} + * @return array{index?: int, id?: string, type?: string, function?: array{name?: string, arguments: string}, extra_content?: array>} */ public function toArray(): array { @@ -36,6 +41,7 @@ public function toArray(): array 'id' => $this->id, 'type' => $this->type, 'function' => $this->function->toArray(), + 'extra_content' => $this->extraContent, ], fn (mixed $value): bool => ! is_null($value)); } } diff --git a/tests/Fixtures/Chat.php b/tests/Fixtures/Chat.php index f1cc56b9b..85c9ddf38 100644 --- a/tests/Fixtures/Chat.php +++ b/tests/Fixtures/Chat.php @@ -492,6 +492,50 @@ function chatCompletionWithToolCalls(): array ]; } +/** + * @return array + */ +function chatCompletionWithToolCallsAndExtraContent(): array +{ + return [ + 'id' => 'chatcmpl-123', + 'object' => 'chat.completion', + 'created' => 1699333252, + 'model' => 'gpt-3.5-turbo-0613', + 'choices' => [ + [ + 'index' => 0, + 'message' => [ + 'role' => 'assistant', + 'content' => null, + 'tool_calls' => [ + [ + 'id' => 'call_trlgKnhMpYSC7CFXKw3CceUZ', + 'type' => 'function', + 'function' => [ + 'name' => 'get_current_weather', + 'arguments' => "{\n \"location\": \"Boston, MA\"\n}", + ], + 'extra_content' => [ + 'google' => [ + 'thought_signature' => 'trlgKnhMpYSC7CFXKw3CceUZ', + ], + ], + ], + ], + ], + 'logprobs' => null, + 'finish_reason' => 'tool_calls', + ], + ], + 'usage' => [ + 'prompt_tokens' => 71, + 'completion_tokens' => 17, + 'total_tokens' => 88, + ], + ]; +} + /** * @return array */ diff --git a/tests/Responses/Chat/CreateResponseMessage.php b/tests/Responses/Chat/CreateResponseMessage.php index 39c480f74..ba61451ce 100644 --- a/tests/Responses/Chat/CreateResponseMessage.php +++ b/tests/Responses/Chat/CreateResponseMessage.php @@ -33,7 +33,26 @@ ->content->toBeNull() ->toolCalls->toBeArray() ->toolCalls->toHaveCount(1) - ->toolCalls->each->toBeInstanceOf(CreateResponseToolCall::class); + ->toolCalls->each->toBeInstanceOf(CreateResponseToolCall::class) + ->and($result->toolCalls[0]) + ->extraContent->toBeNull(); +}); + +test('from tool calls response with extra content', function () { + $result = CreateResponseMessage::from(chatCompletionWithToolCallsAndExtraContent()['choices'][0]['message']); + + expect($result) + ->role->toBe('assistant') + ->content->toBeNull() + ->toolCalls->toBeArray() + ->toolCalls->toHaveCount(1) + ->toolCalls->each->toBeInstanceOf(CreateResponseToolCall::class) + ->and($result->toolCalls[0]) + ->extraContent->toBeArray() + ->extraContent->toHaveCount(1) + ->extraContent->toHaveKey('google') + ->extraContent->google->toHaveKey('thought_signature') + ->extraContent->google->thought_signature->toBe('trlgKnhMpYSC7CFXKw3CceUZ'); }); test('from annotations response', function () { @@ -94,6 +113,13 @@ ->toBe(chatCompletionWithToolCalls()['choices'][0]['message']); }); +test('to array from tool calls response with extra content', function () { + $result = CreateResponseMessage::from(chatCompletionWithToolCallsAndExtraContent()['choices'][0]['message']); + + expect($result->toArray()) + ->toBe(chatCompletionWithToolCallsAndExtraContent()['choices'][0]['message']); +}); + test('to array from annotations response', function () { $result = CreateResponseMessage::from(chatCompletionWithAnnotations()['choices'][0]['message']);