├── .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 | --------------------------------------------------------------------------------