├── .gitignore
├── .github
├── FUNDING.yml
├── PULL_REQUEST_TEMPLATE.md
├── workflows
│ ├── update-contributors.yml
│ ├── validate-pr.yml
│ └── create-release.yml
└── ISSUE_TEMPLATE
│ ├── documentation.yml
│ ├── feature.yml
│ └── bug.yml
├── examples
├── audio
│ ├── fixtures
│ │ ├── audio.mp3
│ │ └── german.m4a
│ ├── createTranslation.php
│ ├── createTranscription.php
│ └── createSpeech.php
├── images
│ ├── fixtures
│ │ ├── mask.png
│ │ └── otter.png
│ ├── createImage.php
│ ├── createImageVariation.php
│ └── createImageEdit.php
├── uploads
│ ├── fixtures
│ │ └── chunk1.bin
│ ├── cancelUpload.php
│ ├── completeUpload.php
│ ├── addUploadPart.php
│ └── createUpload.php
├── files
│ ├── fixtures
│ │ └── mydata.jsonl
│ ├── listFiles.php
│ ├── deleteFile.php
│ ├── retrieveFile.php
│ ├── retrieveFileContent.php
│ └── uploadFile.php
├── assistants
│ ├── runs
│ │ ├── listRuns.php
│ │ ├── cancelRun.php
│ │ ├── retrieveRun.php
│ │ ├── createRun.php
│ │ ├── modifyRun.php
│ │ ├── createThreadAndRun.php
│ │ └── submitToolOutputsToRun.php
│ ├── assistants
│ │ ├── listAssistants.php
│ │ ├── deleteAssistant.php
│ │ ├── retrieveAssistant.php
│ │ ├── createAssistant.php
│ │ └── modifyAssistant.php
│ ├── threads
│ │ ├── createThread.php
│ │ ├── deleteThread.php
│ │ ├── retrieveThread.php
│ │ └── modifyThread.php
│ ├── vector-stores
│ │ ├── listVectorStores.php
│ │ ├── deleteVectorStore.php
│ │ ├── retrieveVectorStore.php
│ │ ├── createVectorStore.php
│ │ ├── modifyVectorStore.php
│ │ └── searchVectorStore.php
│ ├── messages
│ │ ├── listMessages.php
│ │ ├── deleteMessage.php
│ │ ├── retrieveMessage.php
│ │ ├── createMessage.php
│ │ └── modifyMessage.php
│ ├── vector-store-files
│ │ ├── listVectorStoreFiles.php
│ │ ├── createVectorStoreFile.php
│ │ ├── deleteVectorStoreFile.php
│ │ ├── retrieveVectorStoreFile.php
│ │ ├── retrieveVectorStoreFileContent.php
│ │ └── updateVectorStoreFileAttributes.php
│ ├── run-steps
│ │ ├── listRunSteps.php
│ │ └── retrieveRunStep.php
│ └── vector-store-file-batches
│ │ ├── cancelVectorStoreFileBatch.php
│ │ ├── listVectorStoreFilesInBatch.php
│ │ ├── retrieveVectorStoreFileBatch.php
│ │ └── createVectorStoreFileBatch.php
├── batch
│ ├── listBatches.php
│ ├── cancelBatch.php
│ ├── retrieveBatch.php
│ └── createBatch.php
├── models
│ ├── listModels.php
│ ├── retrieveModel.php
│ └── deleteModel.php
├── chat
│ ├── listChatCompletions.php
│ ├── getChatMessages.php
│ ├── getChatCompletion.php
│ ├── deleteChatCompletion.php
│ ├── updateChatCompletion.php
│ ├── createChatCompletion.php
│ ├── createChatCompletionStream.php
│ └── createVisionChatCompletion.php
├── administration
│ ├── org-users
│ │ ├── listUsers.php
│ │ ├── deleteUser.php
│ │ ├── retrieveUser.php
│ │ └── modifyUser.php
│ ├── invites
│ │ ├── listInvites.php
│ │ ├── deleteInvite.php
│ │ ├── retrieveInvite.php
│ │ └── createInvite.php
│ ├── projects
│ │ ├── listProjects.php
│ │ ├── createProject.php
│ │ ├── archiveProject.php
│ │ ├── retrieveProject.php
│ │ └── modifyProject.php
│ ├── audit-logs
│ │ └── listAuditLogs.php
│ ├── certificates
│ │ ├── listCertificates.php
│ │ ├── deleteCertificate.php
│ │ ├── listProjectCertificates.php
│ │ ├── modifyCertificate.php
│ │ ├── getCertificate.php
│ │ ├── activateCertificates.php
│ │ ├── deactivateCertificates.php
│ │ ├── uploadCertificate.php
│ │ ├── activateProjectCertificates.php
│ │ └── deactivateProjectCertificates.php
│ ├── admin-api-keys
│ │ ├── listAdminApiKeys.php
│ │ ├── createAdminApiKey.php
│ │ ├── deleteAdminApiKey.php
│ │ └── retrieveAdminApiKey.php
│ ├── usage
│ │ ├── getCosts.php
│ │ ├── getImagesUsage.php
│ │ ├── getCompletionsUsage.php
│ │ ├── getEmbeddingsUsage.php
│ │ ├── getModerationsUsage.php
│ │ ├── getAudioSpeechesUsage.php
│ │ └── getVectorStoresUsage.php
│ ├── project-users
│ │ ├── listProjectUsers.php
│ │ ├── deleteProjectUser.php
│ │ ├── retrieveProjectUser.php
│ │ ├── createProjectUser.php
│ │ └── modifyProjectUser.php
│ ├── project-api-keys
│ │ ├── listProjectApiKeys.php
│ │ ├── deleteProjectApiKey.php
│ │ └── retrieveProjectApiKey.php
│ ├── rate-limits
│ │ ├── listProjectRateLimits.php
│ │ └── modifyProjectRateLimit.php
│ └── project-service-accounts
│ │ ├── listProjectServiceAccounts.php
│ │ ├── createProjectServiceAccount.php
│ │ ├── deleteProjectServiceAccount.php
│ │ └── retrieveProjectServiceAccount.php
├── fine-tuning
│ ├── listFineTuningJobs.php
│ ├── cancelFineTuning.php
│ ├── listFineTuningEvents.php
│ ├── listFineTuningCheckpoints.php
│ ├── retrieveFineTuningJob.php
│ └── createFineTuningJob.php
├── responses
│ ├── getResponse.php
│ ├── deleteResponse.php
│ ├── listInputItems.php
│ └── createResponse.php
├── moderations
│ ├── createModeration.php
│ └── createImageModeration.php
├── embeddings
│ └── createEmbedding.php
└── OpenAIFactory.php
├── tests
├── fixtures
│ ├── retrieveModel.json
│ ├── uploadFile.json
│ ├── createEmbedding.json
│ ├── listModels.json
│ ├── chatCompletion.json
│ └── chatCompletionStreaming.txt
├── OpenAIURLBuilderTest.php
├── TestHelper.php
└── OpenAIExceptionTest.php
├── .env.example
├── LICENSE.md
├── phpunit.xml.dist
├── composer.json
├── src
└── Exception
│ └── OpenAIException.php
├── CODE_OF_CONDUCT.md
└── .php-cs-fixer.dist.php
/.gitignore:
--------------------------------------------------------------------------------
1 | /composer.lock
2 | vendor/
3 | /*.cache
4 | .idea/
5 | /coverage.xml
6 | .env
7 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: softcreatr
2 | custom: ['https://ecologi.com/softcreatr?r=61212ab3fc69b8eb8a2014f4']
3 |
--------------------------------------------------------------------------------
/examples/audio/fixtures/audio.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftCreatR/php-openai-sdk/HEAD/examples/audio/fixtures/audio.mp3
--------------------------------------------------------------------------------
/examples/images/fixtures/mask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftCreatR/php-openai-sdk/HEAD/examples/images/fixtures/mask.png
--------------------------------------------------------------------------------
/examples/audio/fixtures/german.m4a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftCreatR/php-openai-sdk/HEAD/examples/audio/fixtures/german.m4a
--------------------------------------------------------------------------------
/examples/images/fixtures/otter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftCreatR/php-openai-sdk/HEAD/examples/images/fixtures/otter.png
--------------------------------------------------------------------------------
/examples/uploads/fixtures/chunk1.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftCreatR/php-openai-sdk/HEAD/examples/uploads/fixtures/chunk1.bin
--------------------------------------------------------------------------------
/tests/fixtures/retrieveModel.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "gpt-3.5-turbo-instruct",
3 | "object": "model",
4 | "created": 1686935002,
5 | "owned_by": "openai"
6 | }
7 |
--------------------------------------------------------------------------------
/tests/fixtures/uploadFile.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "file-abc123",
3 | "object": "file",
4 | "bytes": 120000,
5 | "created_at": 1677610602,
6 | "filename": "mydata.jsonl",
7 | "purpose": "fine-tune",
8 | }
9 |
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | # https://platform.openai.com/api-keys
2 | OPENAI_API_KEY=
3 |
4 | # https://platform.openai.com/settings/organization/admin-keys
5 | OPENAI_ADMIN_KEY=
6 |
7 | # https://platform.openai.com/settings/organization/general
8 | ORGANIZATION_ID=
9 |
--------------------------------------------------------------------------------
/examples/files/fixtures/mydata.jsonl:
--------------------------------------------------------------------------------
1 | {"prompt":"Company: BHFF insurance\nProduct: allround insurance\nAd:One stop shop for all your insurance needs!\nSupported:", "completion":" yes"}
2 | {"prompt":"Company: Loft conversion specialists\nProduct: -\nAd:Straight teeth in weeks!\nSupported:", "completion":" no"}
--------------------------------------------------------------------------------
/examples/assistants/runs/listRuns.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123'],
13 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
14 | );
15 |
--------------------------------------------------------------------------------
/tests/fixtures/createEmbedding.json:
--------------------------------------------------------------------------------
1 | {
2 | "object": "list",
3 | "data": [
4 | {
5 | "object": "embedding",
6 | "embedding": [
7 | 0.0023064255,
8 | -0.009327292,
9 | .... (1536 floats total for ada-002)
10 | -0.0028842222,
11 | ],
12 | "index": 0
13 | }
14 | ],
15 | "model": "text-embedding-ada-002",
16 | "usage": {
17 | "prompt_tokens": 8,
18 | "total_tokens": 8
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/examples/assistants/runs/cancelRun.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123',
14 | 'run_id' => 'run_abc123',
15 | ],
16 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
17 | );
18 |
--------------------------------------------------------------------------------
/examples/assistants/runs/retrieveRun.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123',
14 | 'run_id' => 'run_abc123',
15 | ],
16 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
17 | );
18 |
--------------------------------------------------------------------------------
/examples/assistants/runs/createRun.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123'],
13 | [
14 | 'assistant_id' => 'asst_abc123',
15 | 'customHeaders' => ['OpenAI-Beta' => 'assistants=v2'],
16 | ]
17 | );
18 |
--------------------------------------------------------------------------------
/examples/assistants/runs/modifyRun.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123',
14 | 'run_id' => 'run_abc123',
15 | ],
16 | [
17 | 'metadata' => ['user' => 'user-abc123'],
18 | 'customHeaders' => ['OpenAI-Beta' => 'assistants=v2'],
19 | ]
20 | );
21 |
--------------------------------------------------------------------------------
/tests/fixtures/listModels.json:
--------------------------------------------------------------------------------
1 | {
2 | "object": "list",
3 | "data": [
4 | {
5 | "id": "model-id-0",
6 | "object": "model",
7 | "created": 1686935002,
8 | "owned_by": "organization-owner"
9 | },
10 | {
11 | "id": "model-id-1",
12 | "object": "model",
13 | "created": 1686935002,
14 | "owned_by": "organization-owner",
15 | },
16 | {
17 | "id": "model-id-2",
18 | "object": "model",
19 | "created": 1686935002,
20 | "owned_by": "openai"
21 | },
22 | ],
23 | "object": "list"
24 | }
25 |
--------------------------------------------------------------------------------
/tests/fixtures/chatCompletion.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "chatcmpl-123",
3 | "object": "chat.completion",
4 | "created": 1677652288,
5 | "model": "gpt-4o-mini",
6 | "system_fingerprint": "fp_44709d6fcb",
7 | "choices": [{
8 | "index": 0,
9 | "message": {
10 | "role": "assistant",
11 | "content": "\n\nHello there, how may I assist you today?",
12 | },
13 | "logprobs": null,
14 | "finish_reason": "stop"
15 | }],
16 | "usage": {
17 | "prompt_tokens": 9,
18 | "completion_tokens": 12,
19 | "total_tokens": 21,
20 | "completion_tokens_details": {
21 | "reasoning_tokens": 0
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/examples/assistants/runs/createThreadAndRun.php:
--------------------------------------------------------------------------------
1 | 'asst_abc123',
15 | 'thread' => [
16 | 'messages' => [
17 | [
18 | 'role' => 'user',
19 | 'content' => 'Explain deep learning to a 5 year old.',
20 | ],
21 | ],
22 | ],
23 | 'customHeaders' => ['OpenAI-Beta' => 'assistants=v2'],
24 | ]
25 | );
26 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
9 |
10 | # 🔀 Pull Request
11 |
12 | ## What does this PR do?
13 |
14 | (Provide a description of what this PR does.)
15 |
16 | ## Test Plan
17 |
18 | (Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work.)
19 |
20 | ## Related PRs and Issues
21 |
22 | (If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)
23 |
--------------------------------------------------------------------------------
/examples/assistants/runs/submitToolOutputsToRun.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123',
14 | 'run_id' => 'run_abc123',
15 | ],
16 | [
17 | 'tool_outputs' => [
18 | [
19 | 'tool_call_id' => 'call_001',
20 | 'output' => '70 degrees and sunny.',
21 | ],
22 | ],
23 | 'customHeaders' => ['OpenAI-Beta' => 'assistants=v2'],
24 | ]
25 | );
26 |
--------------------------------------------------------------------------------
/tests/fixtures/chatCompletionStreaming.txt:
--------------------------------------------------------------------------------
1 | data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-4o-mini", "system_fingerprint": "fp_44709d6fcb", "choices":[{"index":0,"delta":{"role":"assistant","content":""},"logprobs":null,"finish_reason":null}]}
2 | data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-4o-mini", "system_fingerprint": "fp_44709d6fcb", "choices":[{"index":0,"delta":{"content":"Hello"},"logprobs":null,"finish_reason":null}]}
3 | data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-4o-mini", "system_fingerprint": "fp_44709d6fcb", "choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}]}
4 | data: [DONE]
5 |
--------------------------------------------------------------------------------
/.github/workflows/update-contributors.yml:
--------------------------------------------------------------------------------
1 | name: Update Contributors
2 |
3 | on:
4 | pull_request:
5 | types: [closed]
6 | branches:
7 | - main
8 | if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main'
9 | workflow_dispatch:
10 |
11 | jobs:
12 | update-contributors:
13 | runs-on: ubuntu-latest
14 | permissions:
15 | contents: write
16 |
17 | steps:
18 | - name: Checkout repository
19 | uses: actions/checkout@v4
20 |
21 | - name: Add contributors
22 | uses: BobAnkh/add-contributors@v0.2.2
23 | with:
24 | CONTRIBUTOR: '## Contributors ✨'
25 | ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26 | IGNORED_CONTRIBUTORS: 'Sascha Greuel'
27 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2024, Sascha Greuel and Contributors
2 |
3 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted,
4 | provided that the above copyright notice and this permission notice appear in all copies.
5 |
6 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
7 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
8 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
9 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
10 | THIS SOFTWARE.
11 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 | tests
16 |
17 |
18 |
19 |
20 |
21 | src
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/documentation.yml:
--------------------------------------------------------------------------------
1 | name: 📚 Documentation
2 | description: Report an issue related to documentation.
3 | labels: ["documentation"]
4 |
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: "## 📚 Documentation"
9 |
10 | - type: textarea
11 | id: issue-description
12 | attributes:
13 | label: Description
14 | description: A clear and concise description of what the issue is.
15 | placeholder: Enter the issue details here.
16 | validations:
17 | required: true
18 |
19 | - type: markdown
20 | attributes:
21 | value: "### Have you read the [Code of Conduct](https://github.com/SoftCreatR/php-openai-sdk/blob/main/CODE_OF_CONDUCT.md)?"
22 |
23 | - type: checkboxes
24 | id: code-of-conduct
25 | attributes:
26 | label: Code of Conduct
27 | description: Please confirm that you have read the Code of Conduct.
28 | options:
29 | - label: I have read the Code of Conduct
30 | required: true
31 |
--------------------------------------------------------------------------------
/examples/batch/listBatches.php:
--------------------------------------------------------------------------------
1 | 'file-abc123']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/files/retrieveFile.php:
--------------------------------------------------------------------------------
1 | 'file-abc123']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/certificates/listCertificates.php:
--------------------------------------------------------------------------------
1 | 'batch_abc123']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/admin-api-keys/listAdminApiKeys.php:
--------------------------------------------------------------------------------
1 | 'batch_abc123']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/responses/getResponse.php:
--------------------------------------------------------------------------------
1 | 'resp_123'],
25 | );
26 |
--------------------------------------------------------------------------------
/examples/models/retrieveModel.php:
--------------------------------------------------------------------------------
1 | 'gpt-3.5-turbo-instruct']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/uploads/cancelUpload.php:
--------------------------------------------------------------------------------
1 | 'upload_abc123']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/files/retrieveFileContent.php:
--------------------------------------------------------------------------------
1 | 'file-abc123']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/models/deleteModel.php:
--------------------------------------------------------------------------------
1 | 'ft:gpt-4o-mini:acemeco:suffix:abc123']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/responses/deleteResponse.php:
--------------------------------------------------------------------------------
1 | 'resp_123'],
25 | );
26 |
--------------------------------------------------------------------------------
/examples/responses/listInputItems.php:
--------------------------------------------------------------------------------
1 | 'resp_123'],
25 | );
26 |
--------------------------------------------------------------------------------
/examples/uploads/completeUpload.php:
--------------------------------------------------------------------------------
1 | 'upload_abc123']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/chat/getChatMessages.php:
--------------------------------------------------------------------------------
1 | 'chat_abc123']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/fine-tuning/cancelFineTuning.php:
--------------------------------------------------------------------------------
1 | 'ftjob-abc123']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/chat/getChatCompletion.php:
--------------------------------------------------------------------------------
1 | 'chatcmpl-abc123'],
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/usage/getCosts.php:
--------------------------------------------------------------------------------
1 | 1],
25 | );
26 |
--------------------------------------------------------------------------------
/examples/chat/deleteChatCompletion.php:
--------------------------------------------------------------------------------
1 | 'chat_abc123'],
25 | );
26 |
--------------------------------------------------------------------------------
/examples/fine-tuning/listFineTuningEvents.php:
--------------------------------------------------------------------------------
1 | 'ftjob-abc123']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/org-users/deleteUser.php:
--------------------------------------------------------------------------------
1 | 'user_abc']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/fine-tuning/listFineTuningCheckpoints.php:
--------------------------------------------------------------------------------
1 | 'ftjob-abc123']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/org-users/retrieveUser.php:
--------------------------------------------------------------------------------
1 | 'user_abc']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/projects/createProject.php:
--------------------------------------------------------------------------------
1 | 'My Project']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/usage/getImagesUsage.php:
--------------------------------------------------------------------------------
1 | 1],
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/admin-api-keys/createAdminApiKey.php:
--------------------------------------------------------------------------------
1 | 'New Admin Key']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/fine-tuning/retrieveFineTuningJob.php:
--------------------------------------------------------------------------------
1 | 'ft-AF1WoRqd3aJAHsqc9NY7iL8F']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/invites/deleteInvite.php:
--------------------------------------------------------------------------------
1 | 'invite-abc123']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/projects/archiveProject.php:
--------------------------------------------------------------------------------
1 | 'proj_abc']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/assistants/assistants/listAssistants.php:
--------------------------------------------------------------------------------
1 | ['OpenAI-Beta' => 'assistants=v2']]
25 | );
26 |
--------------------------------------------------------------------------------
/examples/assistants/threads/createThread.php:
--------------------------------------------------------------------------------
1 | ['OpenAI-Beta' => 'assistants=v2']]
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/invites/retrieveInvite.php:
--------------------------------------------------------------------------------
1 | 'invite-abc123']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/projects/retrieveProject.php:
--------------------------------------------------------------------------------
1 | 'proj_abc']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/usage/getCompletionsUsage.php:
--------------------------------------------------------------------------------
1 | 1],
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/usage/getEmbeddingsUsage.php:
--------------------------------------------------------------------------------
1 | 1],
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/usage/getModerationsUsage.php:
--------------------------------------------------------------------------------
1 | 1],
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/admin-api-keys/deleteAdminApiKey.php:
--------------------------------------------------------------------------------
1 | 'key_abc']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/usage/getAudioSpeechesUsage.php:
--------------------------------------------------------------------------------
1 | 1],
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/usage/getVectorStoresUsage.php:
--------------------------------------------------------------------------------
1 | 1],
25 | );
26 |
--------------------------------------------------------------------------------
/examples/assistants/vector-stores/listVectorStores.php:
--------------------------------------------------------------------------------
1 | ['OpenAI-Beta' => 'assistants=v2']]
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/admin-api-keys/retrieveAdminApiKey.php:
--------------------------------------------------------------------------------
1 | 'key_abc']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/invites/createInvite.php:
--------------------------------------------------------------------------------
1 | 'user@example.com',
24 | 'role' => 'owner',
25 | ]);
26 |
--------------------------------------------------------------------------------
/examples/administration/project-users/listProjectUsers.php:
--------------------------------------------------------------------------------
1 | 'proj_abc']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/files/uploadFile.php:
--------------------------------------------------------------------------------
1 | __DIR__ . '/fixtures/mydata.jsonl',
26 | 'purpose' => 'fine-tune',
27 | ]
28 | );
29 |
--------------------------------------------------------------------------------
/examples/administration/project-api-keys/listProjectApiKeys.php:
--------------------------------------------------------------------------------
1 | 'proj_abc']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/certificates/deleteCertificate.php:
--------------------------------------------------------------------------------
1 | 'cert_abc']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/administration/org-users/modifyUser.php:
--------------------------------------------------------------------------------
1 | 'user_abc'],
25 | ['role' => 'owner']
26 | );
27 |
--------------------------------------------------------------------------------
/examples/administration/rate-limits/listProjectRateLimits.php:
--------------------------------------------------------------------------------
1 | 'proj_abc']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/uploads/addUploadPart.php:
--------------------------------------------------------------------------------
1 | 'upload_abc123'],
25 | ['data' => __DIR__ . '/fixtures/chunk1.bin'],
26 | );
27 |
--------------------------------------------------------------------------------
/examples/administration/certificates/listProjectCertificates.php:
--------------------------------------------------------------------------------
1 | 'proj_abc']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/audio/createTranslation.php:
--------------------------------------------------------------------------------
1 | __DIR__ . '/fixtures/german.m4a',
26 | 'model' => 'whisper-1',
27 | ]
28 | );
29 |
--------------------------------------------------------------------------------
/examples/audio/createTranscription.php:
--------------------------------------------------------------------------------
1 | __DIR__ . '/fixtures/audio.mp3',
26 | 'model' => 'whisper-1',
27 | ]
28 | );
29 |
--------------------------------------------------------------------------------
/examples/moderations/createModeration.php:
--------------------------------------------------------------------------------
1 | 'omni-moderation-latest',
26 | 'input' => 'I want to kill them.',
27 | ]
28 | );
29 |
--------------------------------------------------------------------------------
/examples/responses/createResponse.php:
--------------------------------------------------------------------------------
1 | 'gpt-4.1',
26 | 'input' => 'Tell me a three sentence bedtime story about a unicorn.',
27 | ]
28 | );
29 |
--------------------------------------------------------------------------------
/examples/administration/projects/modifyProject.php:
--------------------------------------------------------------------------------
1 | 'proj_abc'],
25 | ['name' => 'Project DEF']
26 | );
27 |
--------------------------------------------------------------------------------
/examples/assistants/threads/deleteThread.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123'],
25 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
26 | );
27 |
--------------------------------------------------------------------------------
/examples/assistants/messages/listMessages.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123'],
25 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
26 | );
27 |
--------------------------------------------------------------------------------
/examples/administration/project-service-accounts/listProjectServiceAccounts.php:
--------------------------------------------------------------------------------
1 | 'proj_abc']
25 | );
26 |
--------------------------------------------------------------------------------
/examples/assistants/threads/retrieveThread.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123'],
25 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
26 | );
27 |
--------------------------------------------------------------------------------
/examples/fine-tuning/createFineTuningJob.php:
--------------------------------------------------------------------------------
1 | 'file-BK7bzQj3FfZFXr7DbL6xJwfo',
26 | 'model' => 'gpt-4o-mini',
27 | ]
28 | );
29 |
--------------------------------------------------------------------------------
/examples/batch/createBatch.php:
--------------------------------------------------------------------------------
1 | 'file-abc123',
26 | 'endpoint' => '/v1/chat/completions',
27 | 'completion_window' => '24h',
28 | ]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/assistants/assistants/deleteAssistant.php:
--------------------------------------------------------------------------------
1 | 'asst_abc123'],
25 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
26 | );
27 |
--------------------------------------------------------------------------------
/examples/images/createImage.php:
--------------------------------------------------------------------------------
1 | 'dall-e-3',
26 | 'prompt' => 'A cute baby sea otter',
27 | 'n' => 1,
28 | 'size' => '1024x1024',
29 | ]
30 | );
31 |
--------------------------------------------------------------------------------
/examples/images/createImageVariation.php:
--------------------------------------------------------------------------------
1 | __DIR__ . '/fixtures/otter.png',
26 | 'n' => 2,
27 | 'size' => '1024x1024',
28 | ]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/assistants/assistants/retrieveAssistant.php:
--------------------------------------------------------------------------------
1 | 'asst_abc123'],
25 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
26 | );
27 |
--------------------------------------------------------------------------------
/examples/assistants/vector-stores/deleteVectorStore.php:
--------------------------------------------------------------------------------
1 | 'vs-abc123'],
25 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
26 | );
27 |
--------------------------------------------------------------------------------
/examples/administration/certificates/modifyCertificate.php:
--------------------------------------------------------------------------------
1 | 'cert_abc'],
25 | ['name' => 'Renamed Certificate'],
26 | );
27 |
--------------------------------------------------------------------------------
/examples/assistants/vector-stores/retrieveVectorStore.php:
--------------------------------------------------------------------------------
1 | 'vs-abc123'],
25 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
26 | );
27 |
--------------------------------------------------------------------------------
/examples/assistants/vector-stores/createVectorStore.php:
--------------------------------------------------------------------------------
1 | 'Support FAQ',
26 | 'customHeaders' => ['OpenAI-Beta' => 'assistants=v2'],
27 | ]
28 | );
29 |
--------------------------------------------------------------------------------
/examples/administration/project-users/deleteProjectUser.php:
--------------------------------------------------------------------------------
1 | 'proj_abc',
26 | 'user_id' => 'user_abc',
27 | ]
28 | );
29 |
--------------------------------------------------------------------------------
/examples/assistants/vector-store-files/listVectorStoreFiles.php:
--------------------------------------------------------------------------------
1 | 'vs-abc123'],
25 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
26 | );
27 |
--------------------------------------------------------------------------------
/examples/chat/updateChatCompletion.php:
--------------------------------------------------------------------------------
1 | 'chat_abc123'],
25 | [
26 | 'metadata' => [
27 | 'foo' => 'bar',
28 | ],
29 | ]
30 | );
31 |
--------------------------------------------------------------------------------
/examples/administration/certificates/getCertificate.php:
--------------------------------------------------------------------------------
1 | 'cert_abc',
25 | 'include' => [
26 | 'content',
27 | ],
28 | ],
29 | );
30 |
--------------------------------------------------------------------------------
/examples/administration/project-api-keys/deleteProjectApiKey.php:
--------------------------------------------------------------------------------
1 | 'proj_abc',
26 | 'key_id' => 'key_abc',
27 | ]
28 | );
29 |
--------------------------------------------------------------------------------
/examples/administration/project-users/retrieveProjectUser.php:
--------------------------------------------------------------------------------
1 | 'proj_abc',
26 | 'user_id' => 'user_abc',
27 | ]
28 | );
29 |
--------------------------------------------------------------------------------
/examples/uploads/createUpload.php:
--------------------------------------------------------------------------------
1 | 'fine-tune',
26 | 'filename' => 'training_examples.jsonl',
27 | 'bytes' => 2147483648,
28 | 'mime_type' => 'text/jsonl',
29 | ]
30 | );
31 |
--------------------------------------------------------------------------------
/examples/embeddings/createEmbedding.php:
--------------------------------------------------------------------------------
1 | 'The food was delicious and the waiter...',
26 | 'model' => 'text-embedding-ada-002',
27 | 'encoding_format' => 'float',
28 | ]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/administration/project-api-keys/retrieveProjectApiKey.php:
--------------------------------------------------------------------------------
1 | 'proj_abc',
26 | 'key_id' => 'key_abc',
27 | ]
28 | );
29 |
--------------------------------------------------------------------------------
/examples/administration/project-service-accounts/createProjectServiceAccount.php:
--------------------------------------------------------------------------------
1 | 'proj_abc'],
25 | ['name' => 'Production App']
26 | );
27 |
--------------------------------------------------------------------------------
/examples/administration/certificates/activateCertificates.php:
--------------------------------------------------------------------------------
1 | [
26 | 'cert_abc',
27 | 'cert_def',
28 | ],
29 | ]
30 | );
31 |
--------------------------------------------------------------------------------
/examples/administration/rate-limits/modifyProjectRateLimit.php:
--------------------------------------------------------------------------------
1 | 'proj_abc',
26 | 'rate_limit_id' => 'rl_xxx',
27 | ]
28 | );
29 |
--------------------------------------------------------------------------------
/examples/administration/certificates/deactivateCertificates.php:
--------------------------------------------------------------------------------
1 | [
26 | 'cert_abc',
27 | 'cert_def',
28 | ],
29 | ]
30 | );
31 |
--------------------------------------------------------------------------------
/examples/administration/project-users/createProjectUser.php:
--------------------------------------------------------------------------------
1 | 'proj_abc'],
25 | [
26 | 'user_id' => 'user_abc',
27 | 'role' => 'member',
28 | ]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/assistants/run-steps/listRunSteps.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123',
26 | 'run_id' => 'run_abc123',
27 | ],
28 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/assistants/messages/deleteMessage.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123',
26 | 'message_id' => 'msg_abc123',
27 | ],
28 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/assistants/messages/retrieveMessage.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123',
26 | 'message_id' => 'msg_abc123',
27 | ],
28 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/administration/certificates/uploadCertificate.php:
--------------------------------------------------------------------------------
1 | 'My Example Certificate',
26 | 'certificate' => "-----BEGIN CERTIFICATE-----\\nMIIDeT...\\n-----END CERTIFICATE-----",
27 | ]
28 | );
29 |
--------------------------------------------------------------------------------
/examples/assistants/vector-stores/modifyVectorStore.php:
--------------------------------------------------------------------------------
1 | 'vs-abc123'],
25 | [
26 | 'name' => 'Support FAQ',
27 | 'customHeaders' => ['OpenAI-Beta' => 'assistants=v2'],
28 | ]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/administration/project-users/modifyProjectUser.php:
--------------------------------------------------------------------------------
1 | 'proj_abc',
26 | 'user_id' => 'user_abc',
27 | ],
28 | [
29 | 'role' => 'owner',
30 | ]
31 | );
32 |
--------------------------------------------------------------------------------
/examples/administration/project-service-accounts/deleteProjectServiceAccount.php:
--------------------------------------------------------------------------------
1 | 'proj_abc',
26 | 'service_account_id' => 'svc_acct_abc',
27 | ]
28 | );
29 |
--------------------------------------------------------------------------------
/examples/administration/project-service-accounts/retrieveProjectServiceAccount.php:
--------------------------------------------------------------------------------
1 | 'proj_abc',
26 | 'service_account_id' => 'svc_acct_abc',
27 | ]
28 | );
29 |
--------------------------------------------------------------------------------
/examples/assistants/vector-store-files/createVectorStoreFile.php:
--------------------------------------------------------------------------------
1 | 'vs-abc123'],
25 | [
26 | 'file_id' => 'file-abc123',
27 | 'customHeaders' => ['OpenAI-Beta' => 'assistants=v2'],
28 | ]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/assistants/vector-store-files/deleteVectorStoreFile.php:
--------------------------------------------------------------------------------
1 | 'vs-abc123',
26 | 'file_id' => 'file-abc123',
27 | ],
28 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/assistants/vector-stores/searchVectorStore.php:
--------------------------------------------------------------------------------
1 | 'vs-abc123'],
25 | [
26 | 'query' => 'What is the return policy?',
27 | 'customHeaders' => ['OpenAI-Beta' => 'assistants=v2'],
28 | ]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/images/createImageEdit.php:
--------------------------------------------------------------------------------
1 | __DIR__ . '/fixtures/otter.png',
26 | 'mask' => __DIR__ . '/fixtures/mask.png',
27 | 'prompt' => 'A cute baby sea otter wearing a beret',
28 | 'n' => 2,
29 | 'size' => '256x256',
30 | ]
31 | );
32 |
--------------------------------------------------------------------------------
/examples/assistants/vector-store-files/retrieveVectorStoreFile.php:
--------------------------------------------------------------------------------
1 | 'vs-abc123',
26 | 'file_id' => 'file-abc123',
27 | ],
28 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/assistants/run-steps/retrieveRunStep.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123',
26 | 'run_id' => 'run_abc123',
27 | 'step_id' => 'step-abc123',
28 | ],
29 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
30 | );
31 |
--------------------------------------------------------------------------------
/examples/administration/certificates/activateProjectCertificates.php:
--------------------------------------------------------------------------------
1 | 'proj_abc'],
25 | [
26 | 'certificate_ids' => [
27 | 'cert_abc',
28 | 'cert_def',
29 | ],
30 | ]
31 | );
32 |
--------------------------------------------------------------------------------
/examples/administration/certificates/deactivateProjectCertificates.php:
--------------------------------------------------------------------------------
1 | 'proj_abc'],
25 | [
26 | 'certificate_ids' => [
27 | 'cert_abc',
28 | 'cert_def',
29 | ],
30 | ]
31 | );
32 |
--------------------------------------------------------------------------------
/examples/assistants/messages/createMessage.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123'],
25 | [
26 | 'role' => 'user',
27 | 'content' => 'How does AI work? Explain it in simple terms.',
28 | 'customHeaders' => ['OpenAI-Beta' => 'assistants=v2'],
29 | ]
30 | );
31 |
--------------------------------------------------------------------------------
/examples/assistants/vector-store-file-batches/cancelVectorStoreFileBatch.php:
--------------------------------------------------------------------------------
1 | 'vs_abc123',
26 | 'batch_id' => 'vsfb_abc123',
27 | ],
28 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/assistants/vector-store-file-batches/listVectorStoreFilesInBatch.php:
--------------------------------------------------------------------------------
1 | 'vs_abc123',
26 | 'batch_id' => 'vsfb_abc123',
27 | ],
28 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/assistants/vector-store-file-batches/retrieveVectorStoreFileBatch.php:
--------------------------------------------------------------------------------
1 | 'vs_abc123',
26 | 'batch_id' => 'vsfb_abc123',
27 | ],
28 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/assistants/vector-store-files/retrieveVectorStoreFileContent.php:
--------------------------------------------------------------------------------
1 | 'vs-abc123',
26 | 'file_id' => 'file-abc123',
27 | ],
28 | ['customHeaders' => ['OpenAI-Beta' => 'assistants=v2']]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/assistants/threads/modifyThread.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123'],
25 | [
26 | 'metadata' => [
27 | 'modified' => 'true',
28 | 'user' => 'abc123',
29 | ],
30 | 'customHeaders' => ['OpenAI-Beta' => 'assistants=v2'],
31 | ]
32 | );
33 |
--------------------------------------------------------------------------------
/examples/assistants/vector-store-file-batches/createVectorStoreFileBatch.php:
--------------------------------------------------------------------------------
1 | 'vs_abc123'],
25 | [
26 | 'file_ids' => ['file-abc123', 'file-abc456'],
27 | 'customHeaders' => ['OpenAI-Beta' => 'assistants=v2'],
28 | ]
29 | );
30 |
--------------------------------------------------------------------------------
/examples/audio/createSpeech.php:
--------------------------------------------------------------------------------
1 | 'tts-1',
27 | 'input' => 'The quick brown fox jumped over the lazy dog.',
28 | 'voice' => 'alloy',
29 | ],
30 | null,
31 | true
32 | );
33 |
34 | \file_put_contents(__DIR__ . '/fixtures/speech.mp3', $response);
35 |
--------------------------------------------------------------------------------
/examples/chat/createChatCompletion.php:
--------------------------------------------------------------------------------
1 | 'gpt-4o',
26 | 'messages' => [
27 | [
28 | 'role' => 'system',
29 | 'content' => 'You are a helpful assistant.',
30 | ],
31 | [
32 | 'role' => 'user',
33 | 'content' => 'Hello!',
34 | ],
35 | ],
36 | ]
37 | );
38 |
--------------------------------------------------------------------------------
/examples/assistants/messages/modifyMessage.php:
--------------------------------------------------------------------------------
1 | 'thread_abc123',
26 | 'message_id' => 'msg_abc123',
27 | ],
28 | [
29 | 'metadata' => [
30 | 'modified' => 'true',
31 | 'user' => 'abc123',
32 | ],
33 | 'customHeaders' => ['OpenAI-Beta' => 'assistants=v2'],
34 | ]
35 | );
36 |
--------------------------------------------------------------------------------
/examples/assistants/assistants/createAssistant.php:
--------------------------------------------------------------------------------
1 | 'You are a personal math tutor. When asked a question, write and run Python code to answer the question.',
26 | 'name' => 'Math Tutor',
27 | 'tools' => [['type' => 'code_interpreter']],
28 | 'model' => 'gpt-4o',
29 | 'customHeaders' => ['OpenAI-Beta' => 'assistants=v2'],
30 | ]
31 | );
32 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "softcreatr/php-openai-sdk",
3 | "description": "A powerful and easy-to-use PHP SDK for the OpenAI API, allowing seamless integration of advanced AI-powered features into your PHP projects.",
4 | "license": "ISC",
5 | "type": "library",
6 | "version": "3.1.0",
7 | "keywords": [
8 | "openai",
9 | "gpt",
10 | "gpt-3",
11 | "gpt-4",
12 | "gpt-o1",
13 | "artificial-intelligence",
14 | "machine-learning",
15 | "natural-language-processing",
16 | "nlp",
17 | "php",
18 | "sdk",
19 | "api-wrapper"
20 | ],
21 | "authors": [
22 | {
23 | "name": "Sascha Greuel",
24 | "email": "hello@1-2.dev"
25 | }
26 | ],
27 | "require": {
28 | "php": ">=8.1",
29 | "ext-json": "*",
30 | "psr/http-client": "*",
31 | "psr/http-factory": "*",
32 | "psr/http-message": "*"
33 | },
34 | "require-dev": {
35 | "friendsofphp/php-cs-fixer": ">=3",
36 | "guzzlehttp/guzzle": ">=7",
37 | "phpunit/phpunit": ">=10",
38 | "vlucas/phpdotenv": "^5.6"
39 | },
40 | "minimum-stability": "stable",
41 | "autoload": {
42 | "psr-4": {
43 | "SoftCreatR\\OpenAI\\": "src/"
44 | }
45 | },
46 | "autoload-dev": {
47 | "psr-4": {
48 | "SoftCreatR\\OpenAI\\Tests\\": "tests/"
49 | }
50 | },
51 | "config": {
52 | "sort-packages": true
53 | },
54 | "scripts": {
55 | "phpcsf": "php-cs-fixer fix",
56 | "test": "phpunit"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/examples/moderations/createImageModeration.php:
--------------------------------------------------------------------------------
1 | 'omni-moderation-latest',
26 | 'input' => [
27 | [
28 | 'type' => 'image_url',
29 | 'image_url' => [
30 | 'url' => 'https://upload.wikimedia.org/wikipedia/en/7/7f/Wolverine_%26_Deadpool_104.jpg',
31 | ],
32 | ],
33 | ],
34 | ]
35 | );
36 |
--------------------------------------------------------------------------------
/examples/assistants/vector-store-files/updateVectorStoreFileAttributes.php:
--------------------------------------------------------------------------------
1 | 'vs-abc123',
26 | 'file_id' => 'file-abc123',
27 | ],
28 | [
29 | 'attributes' => [
30 | 'key1' => 'value1',
31 | 'key2' => 'value2',
32 | ],
33 | 'customHeaders' => ['OpenAI-Beta' => 'assistants=v2'],
34 | ]
35 | );
36 |
--------------------------------------------------------------------------------
/examples/assistants/assistants/modifyAssistant.php:
--------------------------------------------------------------------------------
1 | 'asst_abc123'],
25 | [
26 | 'instructions' => 'You are an HR bot, and you have access to files to answer employee questions about company policies. Always response with info from either of the files.',
27 | 'tools' => [['type' => 'file_search']],
28 | 'model' => 'gpt-4o',
29 | 'customHeaders' => ['OpenAI-Beta' => 'assistants=v2'],
30 | ]
31 | );
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature.yml:
--------------------------------------------------------------------------------
1 | name: 💡 Feature / Idea
2 | description: Submit a proposal for a new feature.
3 | labels: ["feature"]
4 | body:
5 | - type: markdown
6 | attributes:
7 | value: "## 💡 Feature / Idea"
8 | - type: textarea
9 | id: feature-description
10 | attributes:
11 | label: "A clear and concise description of what the feature is."
12 | placeholder: "Describe the feature here..."
13 | validations:
14 | required: true
15 | - type: checkboxes
16 | id: checked-previous-issues
17 | attributes:
18 | label: "Have you spent some time to check if this issue has been raised before?"
19 | description: "Please check if a similar issue has been raised before."
20 | options:
21 | - label: "I have googled for a similar issue or checked our older issues for a similar idea"
22 | required: true
23 | - type: checkboxes
24 | id: read-code-of-conduct
25 | attributes:
26 | label: "Have you read the [Code of Conduct](https://github.com/SoftCreatR/php-openai-sdk/blob/main/CODE_OF_CONDUCT.md)?"
27 | options:
28 | - label: "I have read the Code of Conduct"
29 | required: true
30 | - type: textarea
31 | id: pitch
32 | attributes:
33 | label: "Pitch"
34 | description: "Please explain why this feature should be implemented and how it would be used. Add examples, if applicable."
35 | placeholder: "Explain the reasoning behind the feature and provide examples..."
36 | validations:
37 | required: true
38 |
--------------------------------------------------------------------------------
/examples/chat/createChatCompletionStream.php:
--------------------------------------------------------------------------------
1 | 'gpt-4o-mini',
27 | 'messages' => [
28 | [
29 | 'role' => 'user',
30 | 'content' => 'Tell me a story about a brave knight.',
31 | ],
32 | ],
33 | 'stream' => true,
34 | ],
35 | static function ($data) {
36 | if (isset($data['choices'][0]['delta']['content'])) {
37 | echo $data['choices'][0]['delta']['content'];
38 | }
39 | }
40 | );
41 |
--------------------------------------------------------------------------------
/examples/chat/createVisionChatCompletion.php:
--------------------------------------------------------------------------------
1 | 'gpt-4o',
26 | 'max_tokens' => 300,
27 | 'messages' => [
28 | [
29 | 'role' => 'user',
30 | 'content' => [
31 | [
32 | 'type' => 'text',
33 | 'text' => 'What’s in this image?',
34 | ],
35 | [
36 | 'type' => 'image_url',
37 | 'image_url' => [
38 | 'url' => 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg',
39 | ],
40 | ],
41 | ],
42 | ],
43 | ],
44 | ]
45 | );
46 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug.yml:
--------------------------------------------------------------------------------
1 | name: 🐛 Bug Report
2 | description: Submit a bug report to help us improve.
3 | labels: ["bug"]
4 | body:
5 | - type: markdown
6 | attributes:
7 | value: "## 🐛 Bug Report"
8 |
9 | - type: textarea
10 | id: bug-description
11 | attributes:
12 | label: Description
13 | description: A clear and concise description of what the bug is.
14 | validations:
15 | required: true
16 |
17 | - type: checkboxes
18 | id: previous-research
19 | attributes:
20 | label: Have you spent some time to check if this issue has been raised before?
21 | options:
22 | - label: I have googled for a similar issue or checked our older issues for a similar bug
23 | required: true
24 |
25 | - type: checkboxes
26 | id: code-of-conduct
27 | attributes:
28 | label: Have you read the Code of Conduct?
29 | options:
30 | - label: I have read the [Code of Conduct](https://github.com/SoftCreatR/php-openai-sdk/blob/main/CODE_OF_CONDUCT.md)
31 | required: true
32 |
33 | - type: textarea
34 | id: reproduction-steps
35 | attributes:
36 | label: To Reproduce
37 | description: Write your steps here
38 | validations:
39 | required: true
40 |
41 | - type: textarea
42 | id: expected-behavior
43 | attributes:
44 | label: Expected behavior
45 | description: Write down what you thought would happen.
46 | validations:
47 | required: true
48 |
49 | - type: textarea
50 | id: actual-behavior
51 | attributes:
52 | label: Actual Behavior
53 | description: Write what happened. Add screenshots, if applicable.
54 | validations:
55 | required: true
56 |
57 | - type: textarea
58 | id: environment
59 | attributes:
60 | label: Your Environment
61 | description: Include as many relevant details about the environment you experienced the bug in (e.g., Environment, Operating system and version, etc.)
62 | validations:
63 | required: true
64 |
--------------------------------------------------------------------------------
/.github/workflows/validate-pr.yml:
--------------------------------------------------------------------------------
1 | name: Validate PR
2 |
3 | on:
4 | pull_request:
5 | paths:
6 | - 'composer.json'
7 | - '**.php'
8 |
9 | jobs:
10 | syntax-check:
11 | runs-on: ubuntu-latest
12 | strategy:
13 | matrix:
14 | php: [ '8.1', '8.2', '8.3', '8.4' ]
15 | steps:
16 | - name: Checkout code
17 | uses: actions/checkout@v4
18 |
19 | - name: Setup PHP
20 | uses: shivammathur/setup-php@v2
21 | with:
22 | php-version: ${{ matrix.php }}
23 |
24 | - name: Install Composer dependencies
25 | run: composer install --no-dev
26 |
27 | - name: Check PHP syntax
28 | run: find {src,tests} -type f -name "*.php" -exec php -l {} \;
29 |
30 | analyze-code:
31 | needs: syntax-check
32 | runs-on: ubuntu-latest
33 | steps:
34 | - name: Checkout code
35 | uses: actions/checkout@v4
36 |
37 | - name: Setup PHP
38 | uses: shivammathur/setup-php@v2
39 | with:
40 | php-version: '8.1'
41 | tools: php-cs-fixer, phpstan
42 | extensions: mbstring
43 |
44 | - name: Install Composer dependencies
45 | run: composer install
46 |
47 | - name: Run PHP-CS-Fixer
48 | run: php-cs-fixer fix --dry-run --diff
49 |
50 | - name: Run PHPStan
51 | run: phpstan analyse src tests
52 |
53 | check-dependencies:
54 | needs: analyze-code
55 | runs-on: ubuntu-latest
56 |
57 | steps:
58 | - name: Checkout code
59 | uses: actions/checkout@v4
60 |
61 | - name: Setup PHP
62 | uses: shivammathur/setup-php@v2
63 | with:
64 | php-version: '8.1'
65 |
66 | - name: Install Composer dependencies
67 | run: composer install
68 |
69 | - name: Run security checker
70 | run: composer require --dev enlightn/security-checker && vendor/bin/security-checker security:check
71 |
72 | run-tests:
73 | needs: check-dependencies
74 | runs-on: ubuntu-latest
75 |
76 | steps:
77 | - name: Checkout code
78 | uses: actions/checkout@v4
79 |
80 | - name: Setup PHP
81 | uses: shivammathur/setup-php@v2
82 | with:
83 | php-version: '8.1'
84 | coverage: pcov
85 | ini-values: zend.assertions=1
86 |
87 | - name: Install Composer dependencies
88 | run: composer install
89 |
90 | - name: Run PHPUnit
91 | run: vendor/bin/phpunit --coverage-clover=coverage.xml
92 |
93 | - name: Upload coverage report to Codecov
94 | uses: codecov/codecov-action@v4
95 | with:
96 | token: ${{ secrets.CODECOV_TOKEN }}
97 | file: coverage.xml
98 | fail_ci_if_error: true
99 |
100 | - name: Upload coverage report to Code Climate
101 | uses: paambaati/codeclimate-action@v9
102 | env:
103 | CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
104 | with:
105 | coverageLocations: ${{github.workspace}}/coverage.xml:clover
106 |
--------------------------------------------------------------------------------
/tests/OpenAIURLBuilderTest.php:
--------------------------------------------------------------------------------
1 | newInstanceWithoutConstructor();
44 |
45 | // Invoke the constructor
46 | $constructor->invoke($instance);
47 |
48 | $this->assertInstanceOf(OpenAIURLBuilder::class, $instance);
49 | }
50 |
51 | /**
52 | * Tests that getEndpoint throws an exception for an invalid key.
53 | */
54 | public function testGetEndpointWithInvalidKey(): void
55 | {
56 | $this->expectException(InvalidArgumentException::class);
57 | $this->expectExceptionMessage('Invalid OpenAI URL key "invalidKey".');
58 |
59 | OpenAIURLBuilder::getEndpoint('invalidKey');
60 | }
61 |
62 | /**
63 | * Tests that createUrl throws an exception when a required path parameter is missing.
64 | */
65 | public function testCreateUrlWithMissingPathParameter(): void
66 | {
67 | $this->expectException(InvalidArgumentException::class);
68 | $this->expectExceptionMessage('Missing path parameter "model".');
69 |
70 | $uriFactory = new HttpFactory();
71 | OpenAIURLBuilder::createUrl($uriFactory, 'retrieveModel');
72 | }
73 |
74 | /**
75 | * Tests that createUrl throws an exception when a path parameter is not scalar.
76 | */
77 | public function testCreateUrlWithNonScalarPathParameter(): void
78 | {
79 | $this->expectException(InvalidArgumentException::class);
80 | $this->expectExceptionMessage('Parameter "model" must be a scalar value, array given.');
81 |
82 | $uriFactory = new HttpFactory();
83 | OpenAIURLBuilder::createUrl($uriFactory, 'retrieveModel', ['model' => ['not', 'scalar']]);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/Exception/OpenAIException.php:
--------------------------------------------------------------------------------
1 | extractErrorMessageFromJson($message);
53 | }
54 |
55 | parent::__construct($message, $code, $previous);
56 | }
57 |
58 | /**
59 | * Attempts to extract the error message from a JSON-encoded string.
60 | *
61 | * If the provided error message is a JSON string containing an "error.message",
62 | * this method will extract and return that message. Otherwise, it returns the original message.
63 | *
64 | * @param string $errorMessage The error message, potentially encoded as a JSON string.
65 | *
66 | * @return string The extracted error message, or the original message if extraction fails.
67 | */
68 | private function extractErrorMessageFromJson(string $errorMessage): string
69 | {
70 | try {
71 | $decoded = \json_decode($errorMessage, true, 512, JSON_THROW_ON_ERROR);
72 |
73 | if (isset($decoded['error']['message']) && \is_string($decoded['error']['message'])) {
74 | return $decoded['error']['message'];
75 | }
76 | } catch (JsonException) {
77 | // Ignore JSON decoding errors and return the original message
78 | }
79 |
80 | return $errorMessage;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of Conduct
2 |
3 | ## Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project maintainer at . All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project maintainer is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html)
44 |
--------------------------------------------------------------------------------
/tests/TestHelper.php:
--------------------------------------------------------------------------------
1 | getMethod($methodName);
41 | }
42 |
43 | /**
44 | * Retrieves the private constructor of a class using reflection.
45 | *
46 | * @param string $className The fully qualified class name.
47 | *
48 | * @return ReflectionMethod The reflection method instance representing the constructor.
49 | *
50 | * @throws ReflectionException If the class or constructor does not exist.
51 | */
52 | public static function getPrivateConstructor(string $className): ReflectionMethod
53 | {
54 | $reflection = new ReflectionClass($className);
55 | $constructor = $reflection->getConstructor();
56 |
57 | if ($constructor !== null) {
58 | return $constructor;
59 | }
60 |
61 | throw new ReflectionException("Constructor does not exist for class {$className}.");
62 | }
63 |
64 | /**
65 | * Loads the contents of a response file for testing purposes.
66 | *
67 | * @param string $filename The filename to load from the 'fixtures/responses' directory.
68 | *
69 | * @return string The contents of the response file.
70 | *
71 | * @throws RuntimeException If the file cannot be found or read.
72 | */
73 | public static function loadResponseFromFile(string $filename): string
74 | {
75 | $filePath = __DIR__ . '/fixtures/' . $filename;
76 |
77 | if (!\file_exists($filePath)) {
78 | throw new RuntimeException("Response file not found: {$filePath}");
79 | }
80 |
81 | $content = \file_get_contents($filePath);
82 |
83 | if ($content === false) {
84 | throw new RuntimeException("Unable to read response file: {$filePath}");
85 | }
86 |
87 | return $content;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/.github/workflows/create-release.yml:
--------------------------------------------------------------------------------
1 | name: Create Release
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | syntax-check:
10 | runs-on: ubuntu-latest
11 | if: startsWith(github.event.head_commit.message, '[Release]')
12 |
13 | strategy:
14 | matrix:
15 | php: [ '8.1', '8.2', '8.3', '8.4' ]
16 |
17 | steps:
18 | - name: Checkout code
19 | uses: actions/checkout@v4
20 |
21 | - name: Setup PHP
22 | uses: shivammathur/setup-php@v2
23 | with:
24 | php-version: ${{ matrix.php }}
25 |
26 | - name: Install Composer dependencies
27 | run: composer install --no-dev
28 |
29 | - name: Check PHP syntax
30 | run: find {src,tests} -type f -name "*.php" -exec php -l {} \;
31 |
32 | analyze-code:
33 | needs: syntax-check
34 | runs-on: ubuntu-latest
35 | steps:
36 | - name: Checkout code
37 | uses: actions/checkout@v4
38 |
39 | - name: Setup PHP
40 | uses: shivammathur/setup-php@v2
41 | with:
42 | php-version: '8.1'
43 | tools: php-cs-fixer, phpstan
44 | extensions: mbstring
45 |
46 | - name: Install Composer dependencies
47 | run: composer install
48 |
49 | - name: Run PHP-CS-Fixer
50 | run: php-cs-fixer fix --dry-run --diff
51 |
52 | - name: Run PHPStan
53 | run: phpstan analyse src tests
54 |
55 | check-dependencies:
56 | needs: analyze-code
57 | runs-on: ubuntu-latest
58 |
59 | steps:
60 | - name: Checkout code
61 | uses: actions/checkout@v4
62 |
63 | - name: Setup PHP
64 | uses: shivammathur/setup-php@v2
65 | with:
66 | php-version: '8.1'
67 |
68 | - name: Install Composer dependencies
69 | run: composer install
70 |
71 | - name: Run security checker
72 | run: composer require --dev enlightn/security-checker && vendor/bin/security-checker security:check
73 |
74 | run-tests:
75 | needs: check-dependencies
76 | runs-on: ubuntu-latest
77 |
78 | steps:
79 | - name: Checkout code
80 | uses: actions/checkout@v4
81 |
82 | - name: Setup PHP
83 | uses: shivammathur/setup-php@v2
84 | with:
85 | php-version: '8.1'
86 | coverage: pcov
87 | ini-values: zend.assertions=1
88 |
89 | - name: Install Composer dependencies
90 | run: composer install
91 |
92 | - name: Run PHPUnit
93 | run: vendor/bin/phpunit --coverage-clover=coverage.xml
94 |
95 | - name: Upload coverage report to Codecov
96 | uses: codecov/codecov-action@v4
97 | with:
98 | token: ${{ secrets.CODECOV_TOKEN }}
99 | file: coverage.xml
100 | fail_ci_if_error: true
101 |
102 | - name: Upload coverage report to Code Climate
103 | uses: paambaati/codeclimate-action@v9
104 | env:
105 | CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
106 | with:
107 | coverageLocations: ${{github.workspace}}/coverage.xml:clover
108 |
109 | create-release:
110 | needs: run-tests
111 | runs-on: ubuntu-latest
112 |
113 | steps:
114 | - name: Checkout code
115 | uses: actions/checkout@v4
116 |
117 | - name: Setup PHP
118 | uses: shivammathur/setup-php@v2
119 | with:
120 | php-version: '8.1'
121 |
122 | - name: Install Composer dependencies
123 | run: composer install --no-dev
124 |
125 | - name: Get current version
126 | id: current-version
127 | run: |
128 | VERSION=$(composer config version --quiet)
129 | echo "Current version: $VERSION"
130 | echo "version=$VERSION" >> $GITHUB_OUTPUT
131 |
132 | - name: Create Release
133 | id: create-release
134 | uses: softprops/action-gh-release@v2
135 | env:
136 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
137 | with:
138 | tag_name: v${{ steps.current-version.outputs.version }}
139 | name: Release v${{ steps.current-version.outputs.version }}
140 | body: 'New release for version ${{ steps.current-version.outputs.version }}'
141 | draft: false
142 | prerelease: false
143 |
--------------------------------------------------------------------------------
/.php-cs-fixer.dist.php:
--------------------------------------------------------------------------------
1 | exclude('*/vendor/*')
4 | ->exclude('node_modules')
5 | ->in(__DIR__)
6 | ->notPath('lib/system/api');
7 |
8 | return (new PhpCsFixer\Config())
9 | ->setRiskyAllowed(true)
10 | ->setRules([
11 | '@PSR1' => true,
12 | '@PSR2' => true,
13 | '@PSR12' => true,
14 | '@PER-CS' => true,
15 |
16 | 'array_push' => true,
17 | 'backtick_to_shell_exec' => true,
18 | 'no_alias_language_construct_call' => true,
19 | 'no_mixed_echo_print' => true,
20 | 'pow_to_exponentiation' => true,
21 | 'random_api_migration' => true,
22 |
23 | 'array_syntax' => ['syntax' => 'short'],
24 | 'no_multiline_whitespace_around_double_arrow' => true,
25 | 'no_trailing_comma_in_singleline' => true,
26 | 'no_whitespace_before_comma_in_array' => true,
27 | 'normalize_index_brace' => true,
28 | 'whitespace_after_comma_in_array' => true,
29 |
30 | 'non_printable_character' => ['use_escape_sequences_in_strings' => true],
31 |
32 | 'magic_constant_casing' => true,
33 | 'magic_method_casing' => true,
34 | 'native_function_casing' => true,
35 | 'native_type_declaration_casing' => true,
36 |
37 | 'cast_spaces' => ['space' => 'none'],
38 | 'no_unset_cast' => true,
39 |
40 | 'class_attributes_separation' => true,
41 | 'no_null_property_initialization' => true,
42 | 'self_accessor' => true,
43 | 'single_class_element_per_statement' => true,
44 |
45 | 'no_empty_comment' => true,
46 | 'single_line_comment_style' => ['comment_types' => ['hash']],
47 |
48 | 'native_constant_invocation' => ['strict' => false],
49 |
50 | 'no_alternative_syntax' => true,
51 | 'no_trailing_comma_in_singleline' => true,
52 | 'no_unneeded_control_parentheses' => ['statements' => ['break', 'clone', 'continue', 'echo_print', 'return', 'switch_case', 'yield', 'yield_from']],
53 | 'no_unneeded_braces' => ['namespaces' => true],
54 | 'switch_continue_to_break' => true,
55 | 'trailing_comma_in_multiline' => ['elements' => ['arrays']],
56 |
57 | 'type_declaration_spaces' => true,
58 | 'lambda_not_used_import' => true,
59 | 'native_function_invocation' => ['include' => ['@internal']],
60 | 'no_unreachable_default_argument_value' => true,
61 | 'nullable_type_declaration_for_default_null_value' => true,
62 | 'static_lambda' => true,
63 |
64 | 'fully_qualified_strict_types' => true,
65 | 'no_unused_imports' => true,
66 |
67 | 'dir_constant' => true,
68 | 'explicit_indirect_variable' => true,
69 | 'function_to_constant' => true,
70 | 'is_null' => true,
71 | 'no_unset_on_property' => true,
72 |
73 | 'list_syntax' => ['syntax' => 'short'],
74 |
75 | 'clean_namespace' => true,
76 | 'no_leading_namespace_whitespace' => true,
77 |
78 | 'no_homoglyph_names' => true,
79 |
80 | 'binary_operator_spaces' => true,
81 | 'concat_space' => ['spacing' => 'one'],
82 | 'increment_style' => ['style' => 'post'],
83 | 'logical_operators' => true,
84 | 'object_operator_without_whitespace' => true,
85 | 'operator_linebreak' => true,
86 | 'standardize_increment' => true,
87 | 'standardize_not_equals' => true,
88 | 'ternary_to_elvis_operator' => true,
89 | 'ternary_to_null_coalescing' => true,
90 | 'unary_operator_spaces' => true,
91 |
92 | 'no_useless_return' => true,
93 | 'return_assignment' => true,
94 |
95 | 'multiline_whitespace_before_semicolons' => true,
96 | 'no_empty_statement' => true,
97 | 'no_singleline_whitespace_before_semicolons' => true,
98 | 'space_after_semicolon' => ['remove_in_empty_for_expressions' => true],
99 |
100 | 'escape_implicit_backslashes' => true,
101 | 'explicit_string_variable' => true,
102 | 'heredoc_to_nowdoc' => true,
103 | 'no_binary_string' => true,
104 | 'simple_to_complex_string_variable' => true,
105 |
106 | 'array_indentation' => true,
107 | 'blank_line_before_statement' => ['statements' => ['return', 'exit']],
108 | 'method_chaining_indentation' => true,
109 | 'no_extra_blank_lines' => ['tokens' => ['case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'square_brace_block', 'switch', 'throw', 'use']],
110 | 'no_spaces_around_offset' => true,
111 |
112 | // SoftCreatR style
113 | 'global_namespace_import' => [
114 | 'import_classes' => true,
115 | 'import_constants' => true,
116 | 'import_functions' => false,
117 | ],
118 | 'ordered_imports' => [
119 | 'imports_order' => ['class', 'function', 'const'],
120 | ],
121 | ])
122 | ->setFinder($finder);
123 |
--------------------------------------------------------------------------------
/examples/OpenAIFactory.php:
--------------------------------------------------------------------------------
1 | load();
36 | }
37 |
38 | /**
39 | * Example factory class for creating and using the OpenAI client.
40 | */
41 | final class OpenAIFactory
42 | {
43 | private function __construct() {}
44 |
45 | /**
46 | * Create an OpenAI client.
47 | *
48 | * @param string $apiKey
49 | * @return OpenAI
50 | */
51 | public static function create(
52 | #[SensitiveParameter]
53 | string $apiKey = ''
54 | ): OpenAI {
55 | $psr17Factory = new HttpFactory();
56 | $httpClient = new Client(['stream' => true]);
57 |
58 | return new OpenAI(
59 | requestFactory: $psr17Factory,
60 | streamFactory: $psr17Factory,
61 | uriFactory: $psr17Factory,
62 | httpClient: $httpClient,
63 | apiKey: $apiKey,
64 | organization: $_ENV['OPENAI_ORGANIZATION_ID'] ?? '',
65 | origin: $_ENV['OPENAI_API_ORIGIN'] ?? '',
66 | basePath: $_ENV['OPENAI_API_BASE_PATH'] ?? '',
67 | );
68 | }
69 |
70 | /**
71 | * Send a generic request to an OpenAI endpoint.
72 | *
73 | * @param string $method Method name, e.g. 'createChatCompletion'
74 | * @param array $parameters URL/path params
75 | * @param array $options Body or query params
76 | * @param callable|null $streamCallback Stream callback for SSE
77 | * @param bool $returnResponse If true, returns raw body
78 | * @param bool $useAdminKey If true, uses $_ENV['OPENAI_ADMIN_KEY']
79 | */
80 | public static function request(
81 | string $method,
82 | array $parameters = [],
83 | array $options = [],
84 | ?callable $streamCallback = null,
85 | bool $returnResponse = false,
86 | bool $useAdminKey = false
87 | ): mixed {
88 | $keyName = $useAdminKey ? 'OPENAI_ADMIN_KEY' : 'OPENAI_API_KEY';
89 | $openAI = self::create($_ENV[$keyName] ?? '');
90 |
91 | try {
92 | $endpoint = OpenAIURLBuilder::getEndpoint($method);
93 | $path = $endpoint['path'];
94 | $hasPlaceholders = (bool)\preg_match('/\{\w+}/', $path);
95 |
96 | if ($hasPlaceholders) {
97 | $urlParams = $parameters;
98 | $bodyOpts = $options;
99 | } else {
100 | $urlParams = [];
101 | $bodyOpts = $parameters + $options;
102 | }
103 |
104 | if ($streamCallback !== null) {
105 | $openAI->{$method}($urlParams, $bodyOpts, $streamCallback);
106 |
107 | return null;
108 | }
109 |
110 | $response = $openAI->{$method}($urlParams, $bodyOpts);
111 |
112 | if ($returnResponse) {
113 | return $response->getBody()->getContents();
114 | }
115 |
116 | $contentType = $response->getHeaderLine('Content-Type');
117 | $body = $response->getBody()->getContents();
118 |
119 | if (\str_contains($contentType, 'application/json')) {
120 | $decoded = \json_decode($body, true, 512, \JSON_THROW_ON_ERROR);
121 | echo "============\n| Response |\n============\n\n"
122 | . \json_encode($decoded, \JSON_PRETTY_PRINT | \JSON_THROW_ON_ERROR)
123 | . "\n\n============\n";
124 | } else {
125 | echo "Received response with Content-Type: {$contentType}\n";
126 | echo $body;
127 | }
128 | } catch (Exception $e) {
129 | echo "Error: {$e->getMessage()}\n";
130 | }
131 |
132 | return null;
133 | }
134 |
135 | /**
136 | * Send an administrative request.
137 | */
138 | public static function adminRequest(
139 | string $method,
140 | array $parameters = [],
141 | array $options = [],
142 | ?callable $streamCallback = null,
143 | bool $returnResponse = false
144 | ): mixed {
145 | return self::request(
146 | $method,
147 | $parameters,
148 | $options,
149 | $streamCallback,
150 | $returnResponse,
151 | true
152 | );
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/tests/OpenAIExceptionTest.php:
--------------------------------------------------------------------------------
1 | assertEquals('An unknown error occurred', $exception->getMessage());
40 |
41 | $exceptionEmptyString = new OpenAIException('');
42 | $this->assertEquals('An unknown error occurred', $exceptionEmptyString->getMessage());
43 | }
44 |
45 | /**
46 | * Tests that the exception extracts the error message from a valid JSON string containing 'error.message'.
47 | *
48 | * @throws JsonException
49 | */
50 | public function testConstructWithValidJsonErrorMessage(): void
51 | {
52 | $jsonErrorMessage = \json_encode([
53 | 'error' => [
54 | 'message' => 'Invalid API key provided.',
55 | 'type' => 'authentication_error',
56 | 'param' => null,
57 | 'code' => 'invalid_api_key',
58 | ],
59 | ], JSON_THROW_ON_ERROR);
60 |
61 | $exception = new OpenAIException($jsonErrorMessage);
62 | $this->assertEquals('Invalid API key provided.', $exception->getMessage());
63 | }
64 |
65 | /**
66 | * Tests that the exception retains the original message when provided with invalid JSON.
67 | */
68 | public function testConstructWithInvalidJson(): void
69 | {
70 | $invalidJson = 'This is not a JSON string.';
71 |
72 | $exception = new OpenAIException($invalidJson);
73 | $this->assertEquals($invalidJson, $exception->getMessage());
74 | }
75 |
76 | /**
77 | * Tests that the exception retains the original message when JSON does not contain 'error.message'.
78 | *
79 | * @throws JsonException
80 | */
81 | public function testConstructWithJsonWithoutErrorMessage(): void
82 | {
83 | $jsonWithoutErrorMessage = \json_encode([
84 | 'error' => [
85 | 'type' => 'invalid_request_error',
86 | 'param' => 'model',
87 | 'code' => 'invalid_model',
88 | ],
89 | ], JSON_THROW_ON_ERROR);
90 |
91 | $exception = new OpenAIException($jsonWithoutErrorMessage);
92 | $this->assertEquals($jsonWithoutErrorMessage, $exception->getMessage());
93 | }
94 |
95 | /**
96 | * Tests that the exception retains the original message when 'error.message' is not a string.
97 | *
98 | * @throws JsonException
99 | */
100 | public function testConstructWithNonStringErrorMessage(): void
101 | {
102 | $jsonWithNonStringErrorMessage = \json_encode([
103 | 'error' => [
104 | 'message' => ['This', 'is', 'an', 'array'],
105 | 'type' => 'invalid_request_error',
106 | ],
107 | ], JSON_THROW_ON_ERROR);
108 |
109 | $exception = new OpenAIException($jsonWithNonStringErrorMessage);
110 | $this->assertEquals($jsonWithNonStringErrorMessage, $exception->getMessage());
111 | }
112 |
113 | /**
114 | * Tests that the exception retains the original message when 'error' key is missing.
115 | *
116 | * @throws JsonException
117 | */
118 | public function testConstructWithMissingErrorKey(): void
119 | {
120 | $jsonMissingErrorKey = \json_encode(['message' => 'A general error occurred.'], JSON_THROW_ON_ERROR);
121 |
122 | $exception = new OpenAIException($jsonMissingErrorKey);
123 | $this->assertEquals($jsonMissingErrorKey, $exception->getMessage());
124 | }
125 |
126 | /**
127 | * Tests that the exception sets the correct code.
128 | */
129 | public function testConstructSetsCode(): void
130 | {
131 | $exception = new OpenAIException('Error message', 123);
132 | $this->assertEquals(123, $exception->getCode());
133 | }
134 |
135 | /**
136 | * Tests that the exception chains the previous throwable correctly.
137 | */
138 | public function testConstructChainsPreviousThrowable(): void
139 | {
140 | $previous = new Exception('Previous exception');
141 | $exception = new OpenAIException('Error message', 0, $previous);
142 |
143 | $this->assertSame($previous, $exception->getPrevious());
144 | }
145 |
146 | /**
147 | * Tests that the exception handles JSON_THROW_ON_ERROR correctly by providing malformed JSON.
148 | */
149 | public function testConstructWithMalformedJsonThrowsNoException(): void
150 | {
151 | // Since JSON_THROW_ON_ERROR is used internally, malformed JSON will not throw here,
152 | // but the original message should be retained.
153 | $malformedJson = '{"error": {"message": "Invalid JSON",}';
154 |
155 | $exception = new OpenAIException($malformedJson);
156 | $this->assertEquals($malformedJson, $exception->getMessage());
157 | }
158 |
159 | /**
160 | * Tests that the exception correctly handles a non-empty, non-JSON message.
161 | */
162 | public function testConstructWithNonEmptyNonJsonMessage(): void
163 | {
164 | $message = 'A simple error message.';
165 | $exception = new OpenAIException($message);
166 | $this->assertEquals($message, $exception->getMessage());
167 | }
168 | }
169 |
--------------------------------------------------------------------------------