diff --git a/src/Providers/OpenAI/Handlers/Text.php b/src/Providers/OpenAI/Handlers/Text.php index acfedf1d4..90eccb015 100644 --- a/src/Providers/OpenAI/Handlers/Text.php +++ b/src/Providers/OpenAI/Handlers/Text.php @@ -118,6 +118,11 @@ protected function shouldContinue(Request $request): bool return $this->responseBuilder->steps->count() < $request->maxSteps(); } + protected function finalRequestStep(Request $request): bool + { + return $this->responseBuilder->steps->count() === $request->maxSteps() - 1; + } + protected function sendRequest(Request $request): ClientResponse { return $this->client->post( @@ -131,11 +136,16 @@ protected function sendRequest(Request $request): ClientResponse 'top_p' => $request->topP(), 'metadata' => $request->providerOptions('metadata'), 'tools' => $this->buildTools($request), - 'tool_choice' => ToolChoiceMap::map($request->toolChoice()), + 'tool_choice' => ToolChoiceMap::map( + $request->toolChoice( + $this->finalRequestStep($request), + ), + ), 'parallel_tool_calls' => $request->providerOptions('parallel_tool_calls'), 'previous_response_id' => $request->providerOptions('previous_response_id'), 'truncation' => $request->providerOptions('truncation'), 'reasoning' => $request->providerOptions('reasoning'), + 'text' => $request->providerOptions('text'), ])) ); } diff --git a/src/Providers/OpenAI/Maps/ToolCallMap.php b/src/Providers/OpenAI/Maps/ToolCallMap.php index 999a1e2af..712353daf 100644 --- a/src/Providers/OpenAI/Maps/ToolCallMap.php +++ b/src/Providers/OpenAI/Maps/ToolCallMap.php @@ -10,22 +10,37 @@ class ToolCallMap { /** * @param array> $toolCalls - * @param null|array> $reasonings + * @param null|array> $reasoningItems * @return array */ - public static function map(?array $toolCalls, ?array $reasonings = null): array + public static function map(?array $toolCalls, ?array $reasoningItems = null): array { if ($toolCalls === null) { return []; } - return array_map(fn (array $toolCall): ToolCall => new ToolCall( - id: data_get($toolCall, 'id'), - name: data_get($toolCall, 'name'), - arguments: data_get($toolCall, 'arguments'), - resultId: data_get($toolCall, 'call_id'), - reasoningId: data_get($reasonings, '0.id'), - reasoningSummary: data_get($reasonings, '0.summary'), - ), $toolCalls); + [$reasoningId, $reasoningSummary] = self::resolveReasoningItem($reasoningItems); + + return collect($toolCalls)->map( + fn (array $toolCall): ToolCall => new ToolCall( + id: data_get($toolCall, 'id'), + name: data_get($toolCall, 'name'), + arguments: data_get($toolCall, 'arguments'), + resultId: data_get($toolCall, 'call_id'), + reasoningId: $reasoningId, + reasoningSummary: $reasoningSummary, + ), + ) + ->toArray(); + } + + protected static function resolveReasoningItem(?array $reasoningItems): array + { + $reasoningItems = array_reverse($reasoningItems ?? []); + + return [ + data_get($reasoningItems, '0.id'), + data_get($reasoningItems, '0.summary'), + ]; } } diff --git a/src/Text/Request.php b/src/Text/Request.php index 7b70c2de1..b7af68471 100644 --- a/src/Text/Request.php +++ b/src/Text/Request.php @@ -47,9 +47,9 @@ public function __construct( $this->providerOptions = $providerOptions; } - public function toolChoice(): string|ToolChoice|null + public function toolChoice(bool $finalRequest = false): string|ToolChoice|null { - return $this->toolChoice; + return $finalRequest ? ToolChoice::None : $this->toolChoice; } /**