Skip to content

Commit 27f9329

Browse files
Add support for Responses API (#541)
* Add support for Responses API Full support to the new Responses API https://platform.openai.com/docs/api-reference/responses * Updated miss placed files that occurred during first upload * Heavy refactoring to match codebase pattern, added testing files * fixed some phpstan errors * fixing minor bugs after live testing now all models work during live testing * Fixed lint errors * Fixed all PHPStan Errors and all other tests Pass 100% * Completed missing Tests, Created ClientFakeResponses, Modified Fakeable I had to modify OpenAI\Testing\Responses\Concerns\Fakeable as $class = str_replace('Responses\\', 'Testing\\Responses\\Fixtures\\', static::class).'Fixture'; was conflicting with newly added Responses folder and added docblock explaining the modification and tested against all files. Updated readme can be found at README-RESPONSES.md Added dedicated ClientFake for Responses tests/Testing/ClientFakeResponses.php * Updated Test files, Fixed Lint errors, all tests pass except test:unit * chore: remove log file * chore: pint * chore: inline Responses doc to readme * chore: align client contract to pattern * docs: re-order chat/completion * fix: use longer replacement to not clobber Responses/* * fix: parse metadata (optionally) * test: don't assert on plain arrays * test: assert stream properly on responses * chore: add missing docblock property * fix: add metadata into Responses payload * test: fix double nesting on delete attrs * test: correct bad assertions on tests * fix: remove ResponseObject * feat: split out usage into classes * feat: split out error into classes * feat: split out incomplete_details into classes * chore(wip): introduction of 'output' typing * fix: correct OutputMessageContentOutputText + child classes * OutputMessage * chore: continued work on output message * chore: start of ComputerToolActions * feat: complete "computer tool call" * fix: add response contract to existing classes * fix: more fixes to typing on CreateResponse * feat: add 'reasoning' prop for response * feat: add 'text' (format) to create * feat: add 'tool_choice' * fix: add 'truncation' * feat: add tool: FileSearch response * feat: add tool: FunctionTool response * feat: add tool 'ComputerUse' * fix: wire up 'tools' to CreateResponse * Added InputMessage types, refactored ListInputItems - Added Classes related to InputMessage types - refactored ListInputItems to reflect the newly added classes * Corrected some properties to use camelCase * fix: cleanup docblock on CreateResponse * chore: remove unused test response object * chore: remove extra newline * fix: 'role' is always 'assistant' * test: augment tests with single click * chore: add missing int for computer single click * test: progression towards 100% coverage on create response * test: assertion on OutputFileSearchToolCall * chore: ints for x/y on click event * fix: further cleanup on CreateResponse * feat: add computer tool call output * feat: add function tool call output * fix: city, region and timezone can return null * fix: json_schema description can be missing * Lint Test Pass, Fixed Array map at ListInputItems * chore: rework text format typing on create response * feat: rework into phpstan-types * fix: work on ListInputItems for phpstan-types * fix: wire up RetrieveResponse * fix: migrate to phpstan-type for delete * fix: wip towards stream responses * chore: add typing props for delete * test: correct tests for retrieve response * fix: add outputItem types for streaming * fix: contentPart/textDelta/textAnnotation added * fix: outputrefusal*/outputText wired up * chore: rename Refusal types * feat: finish typing for streaming * Wired all classes under Responses/Input * chore: type ListInputItems * fix: finalize ListInputItems * test: ListInputItem tests * test: stream testing * fix: shove mock meta object into stream * test: correct streaming tests * chore: use local type * docs: cleanup readme * chore: align constructors * fix: mark 'status' as optional in reasoning * fix: add encrypted_content to reasoning * fix: file search filters can be null --------- Co-authored-by: Connor Tumbleson <[email protected]> Co-authored-by: Connor Tumbleson <[email protected]>
1 parent 2241ae0 commit 27f9329

File tree

102 files changed

+6847
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+6847
-2
lines changed

README.md

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ If you or your business relies on this package, it's important to support the de
2828
- [Get Started](#get-started)
2929
- [Usage](#usage)
3030
- [Models Resource](#models-resource)
31+
- [Responses Resource](#responses-resource)
3132
- [Chat Resource](#chat-resource)
3233
- [Completions Resource](#completions-resource)
3334
- [Audio Resource](#audio-resource)
@@ -154,6 +155,199 @@ $response->deleted; // true
154155
$response->toArray(); // ['id' => 'curie:ft-acmeco-2021-03-03-21-44-20', ...]
155156
```
156157

158+
### `Responses` Resource
159+
160+
#### `create`
161+
162+
Creates a model response. Provide text or image inputs to generate text or JSON outputs. Have the model call your own custom code or use built-in tools like web search or file search to use your own data as input for the model's response.
163+
164+
```php
165+
$response = $client->responses()->create([
166+
'model' => 'gpt-4o-mini',
167+
'tools' => [
168+
[
169+
'type' => 'web_search_preview'
170+
]
171+
],
172+
'input' => "what was a positive news story from today?",
173+
'temperature' => 0.7,
174+
'max_output_tokens' => 150,
175+
'tool_choice' => 'auto',
176+
'parallel_tool_calls' => true,
177+
'store' => true,
178+
'metadata' => [
179+
'user_id' => '123',
180+
'session_id' => 'abc456'
181+
]
182+
]);
183+
184+
$response->id; // 'resp_67ccd2bed1ec8190b14f964abc054267'
185+
$response->object; // 'response'
186+
$response->createdAt; // 1741476542
187+
$response->status; // 'completed'
188+
$response->model; // 'gpt-4o-mini'
189+
190+
foreach ($response->output as $output) {
191+
$output->type; // 'message'
192+
$output->id; // 'msg_67ccd2bf17f0819081ff3bb2cf6508e6'
193+
$output->status; // 'completed'
194+
$output->role; // 'assistant'
195+
196+
foreach ($output->content as $content) {
197+
$content->type; // 'output_text'
198+
$content->text; // The response text
199+
$content->annotations; // Any annotations in the response
200+
}
201+
}
202+
203+
$response->usage->inputTokens; // 36
204+
$response->usage->outputTokens; // 87
205+
$response->usage->totalTokens; // 123
206+
207+
$response->toArray(); // ['id' => 'resp_67ccd2bed1ec8190b14f964abc054267', ...]
208+
```
209+
210+
#### `create streamed`
211+
212+
When you create a Response with stream set to true, the server will emit server-sent events to the client as the Response is generated. All events and their payloads can be found in [OpenAI docs](https://platform.openai.com/docs/api-reference/responses-streaming).
213+
214+
```php
215+
$stream = $client->responses()->createStreamed([
216+
'model' => 'gpt-4o-mini',
217+
'tools' => [
218+
[
219+
'type' => 'web_search_preview'
220+
]
221+
],
222+
'input' => "what was a positive news story from today?",
223+
]);
224+
225+
foreach ($stream as $response) {
226+
$response->event; // 'response.created'
227+
}
228+
```
229+
230+
### `retrieve`
231+
232+
Retrieves a model response with the given ID.
233+
234+
```php
235+
$response = $client->responses()->retrieve('resp_67ccd2bed1ec8190b14f964abc054267');
236+
237+
$response->id; // 'resp_67ccd2bed1ec8190b14f964abc054267'
238+
$response->object; // 'response'
239+
$response->createdAt; // 1741476542
240+
$response->status; // 'completed'
241+
$response->error; // null
242+
$response->incompleteDetails; // null
243+
$response->instructions; // null
244+
$response->maxOutputTokens; // null
245+
$response->model; // 'gpt-4o-mini-2024-07-18"'
246+
$response->parallelToolCalls; // true
247+
$response->previousResponseId; // null
248+
$response->store; // true
249+
$response->temperature; // 1.0
250+
$response->toolChoice; // 'auto'
251+
$response->topP; // 1.0
252+
$response->truncation; // 'disabled'
253+
254+
$response->toArray(); // ['id' => 'resp_67ccd2bed1ec8190b14f964abc054267', ...]
255+
```
256+
257+
### `delete`
258+
259+
Deletes a model response with the given ID.
260+
261+
```php
262+
$response = $client->responses()->delete('resp_67ccd2bed1ec8190b14f964abc054267');
263+
264+
$response->id; // 'resp_67ccd2bed1ec8190b14f964abc054267'
265+
$response->object; // 'response'
266+
$response->deleted; // true
267+
268+
$response->toArray(); // ['id' => 'resp_67ccd2bed1ec8190b14f964abc054267', 'deleted' => true, ...]
269+
```
270+
271+
### `list`
272+
273+
Lists input items for a response with the given ID. All events and their payloads can be found in [OpenAI docs](https://platform.openai.com/docs/api-reference/responses/list).
274+
275+
```php
276+
$response = $client->responses()->list('resp_67ccd2bed1ec8190b14f964abc054267', [
277+
'limit' => 10,
278+
'order' => 'desc'
279+
]);
280+
281+
$response->object; // 'list'
282+
283+
foreach ($response->data as $item) {
284+
$item->type; // 'message'
285+
$item->id; // 'msg_680bf4e8c1948192b64abf0bad54b30806e0834f49400fc3'
286+
$item->status; // 'completed'
287+
$item->role; // 'user'
288+
}
289+
290+
$response->firstId; // 'msg_680bf4e8c1948192b64abf0bad54b30806e0834f49400fc3'
291+
$response->lastId; // 'msg_680bf4e8c1948192b64abf0bad54b30806e0834f49400fc3'
292+
$response->hasMore; // false
293+
294+
$response->toArray(); // ['object' => 'list', 'data' => [...], ...]
295+
```
296+
297+
### `Completions` Resource
298+
299+
#### `create`
300+
301+
Creates a completion for the provided prompt and parameters.
302+
303+
```php
304+
$response = $client->completions()->create([
305+
'model' => 'gpt-3.5-turbo-instruct',
306+
'prompt' => 'Say this is a test',
307+
'max_tokens' => 6,
308+
'temperature' => 0
309+
]);
310+
311+
$response->id; // 'cmpl-uqkvlQyYK7bGYrRHQ0eXlWi7'
312+
$response->object; // 'text_completion'
313+
$response->created; // 1589478378
314+
$response->model; // 'gpt-3.5-turbo-instruct'
315+
316+
foreach ($response->choices as $choice) {
317+
$choice->text; // '\n\nThis is a test'
318+
$choice->index; // 0
319+
$choice->logprobs; // null
320+
$choice->finishReason; // 'length' or null
321+
}
322+
323+
$response->usage->promptTokens; // 5,
324+
$response->usage->completionTokens; // 6,
325+
$response->usage->totalTokens; // 11
326+
327+
$response->toArray(); // ['id' => 'cmpl-uqkvlQyYK7bGYrRHQ0eXlWi7', ...]
328+
```
329+
330+
#### `create streamed`
331+
332+
Creates a streamed completion for the provided prompt and parameters.
333+
334+
```php
335+
$stream = $client->completions()->createStreamed([
336+
'model' => 'gpt-3.5-turbo-instruct',
337+
'prompt' => 'Hi',
338+
'max_tokens' => 10,
339+
]);
340+
341+
foreach($stream as $response){
342+
$response->choices[0]->text;
343+
}
344+
// 1. iteration => 'I'
345+
// 2. iteration => ' am'
346+
// 3. iteration => ' very'
347+
// 4. iteration => ' excited'
348+
// ...
349+
```
350+
157351
### `Chat` Resource
158352

159353
#### `create`

src/Client.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use OpenAI\Resources\Images;
2222
use OpenAI\Resources\Models;
2323
use OpenAI\Resources\Moderations;
24+
use OpenAI\Resources\Responses;
2425
use OpenAI\Resources\Threads;
2526
use OpenAI\Resources\VectorStores;
2627

@@ -34,6 +35,16 @@ public function __construct(private readonly TransporterContract $transporter)
3435
// ..
3536
}
3637

38+
/**
39+
* Manage responses to assist models with tasks.
40+
*
41+
* @see https://platform.openai.com/docs/api-reference/responses
42+
*/
43+
public function responses(): Responses
44+
{
45+
return new Responses($this->transporter);
46+
}
47+
3748
/**
3849
* Given a prompt, the model will return one or more predicted completions, and can also return the probabilities
3950
* of alternative tokens at each position.

src/Contracts/ClientContract.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use OpenAI\Contracts\Resources\ImagesContract;
1616
use OpenAI\Contracts\Resources\ModelsContract;
1717
use OpenAI\Contracts\Resources\ModerationsContract;
18+
use OpenAI\Contracts\Resources\ResponsesContract;
1819
use OpenAI\Contracts\Resources\ThreadsContract;
1920
use OpenAI\Contracts\Resources\VectorStoresContract;
2021

@@ -28,6 +29,13 @@ interface ClientContract
2829
*/
2930
public function completions(): CompletionsContract;
3031

32+
/**
33+
* Manage responses to assist models with tasks.
34+
*
35+
* @see https://platform.openai.com/docs/api-reference/responses
36+
*/
37+
public function responses(): ResponsesContract;
38+
3139
/**
3240
* Given a chat conversation, the model will return a chat completion response.
3341
*
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenAI\Contracts\Resources;
6+
7+
use OpenAI\Responses\Responses\CreateResponse;
8+
use OpenAI\Responses\Responses\CreateStreamedResponse;
9+
use OpenAI\Responses\Responses\DeleteResponse;
10+
use OpenAI\Responses\Responses\ListInputItems;
11+
use OpenAI\Responses\Responses\RetrieveResponse;
12+
use OpenAI\Responses\StreamResponse;
13+
14+
interface ResponsesContract
15+
{
16+
/**
17+
* Creates a model response.
18+
* Provide text or image inputs to generate text or JSON outputs.
19+
* Have the model call your own custom code or use built-in tools
20+
* like web search or file search to use your own data as input for the model's response.
21+
*
22+
* @see https://platform.openai.com/docs/api-reference/responses/create
23+
*
24+
* @param array<string, mixed> $parameters
25+
*/
26+
public function create(array $parameters): CreateResponse;
27+
28+
/**
29+
* Create a streamed response.
30+
*
31+
* @see https://platform.openai.com/docs/api-reference/responses/create
32+
*
33+
* @param array<string, mixed> $parameters
34+
* @return StreamResponse<CreateStreamedResponse>
35+
*/
36+
public function createStreamed(array $parameters): StreamResponse;
37+
38+
/**
39+
* Retrieves a model response with the given ID.
40+
*
41+
* @see https://platform.openai.com/docs/api-reference/responses/retrieve
42+
*/
43+
public function retrieve(string $id): RetrieveResponse;
44+
45+
/**
46+
* Deletes a model response with the given ID.
47+
*
48+
* @see https://platform.openai.com/docs/api-reference/responses/delete
49+
*/
50+
public function delete(string $id): DeleteResponse;
51+
52+
/**
53+
* Returns a list of input items for a given response.
54+
*
55+
* @see https://platform.openai.com/docs/api-reference/responses/input-items
56+
*
57+
* @param array<string, mixed> $parameters
58+
*/
59+
public function list(string $id, array $parameters = []): ListInputItems;
60+
}

0 commit comments

Comments
 (0)