[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-7056":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":16,"stars30d":17,"stars90d":15,"forks30d":15,"starsTrendScore":18,"compositeScore":19,"rankGlobal":10,"rankLanguage":10,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":23,"hasPages":21,"topics":24,"createdAt":10,"pushedAt":10,"updatedAt":31,"readmeContent":32,"aiSummary":33,"trendingCount":15,"starSnapshotCount":15,"syncStatus":16,"lastSyncTime":34,"discoverSource":35},7056,"OpenAI","MacPaw\u002FOpenAI","MacPaw","Swift community driven package for OpenAI public API","",null,"Swift",2914,511,29,0,2,16,1,30.13,"MIT License",false,"main",true,[25,26,27,28,29,30],"ai","openai","openai-api","spm","swift","swiftpackagemanager","2026-06-12 02:01:33","# OpenAI\n\n![logo](https:\u002F\u002Fuser-images.githubusercontent.com\u002F1411778\u002F218319355-f56b6bd4-961a-4d8f-82cd-6dbd43111d7f.png)\n\n___\n\n![Swift Workflow](https:\u002F\u002Fgithub.com\u002FMacPaw\u002FOpenAI\u002Factions\u002Fworkflows\u002Fswift.yml\u002Fbadge.svg)\n[![](https:\u002F\u002Fimg.shields.io\u002Fendpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FMacPaw%2FOpenAI%2Fbadge%3Ftype%3Dswift-versions)](https:\u002F\u002Fswiftpackageindex.com\u002FMacPaw\u002FOpenAI)\n[![](https:\u002F\u002Fimg.shields.io\u002Fendpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FMacPaw%2FOpenAI%2Fbadge%3Ftype%3Dplatforms)](https:\u002F\u002Fswiftpackageindex.com\u002FMacPaw\u002FOpenAI)\n[![Twitter](https:\u002F\u002Fimg.shields.io\u002Fstatic\u002Fv1?label=Twitter&message=@MacPaw&color=CA1F67)](https:\u002F\u002Ftwitter.com\u002FMacPaw)\n\nThis repository contains Swift community-maintained implementation over [OpenAI](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002F) public API. \n\n- [Installation](#installation)\n    - [Swift Package Manager](#swift-package-manager)\n- [Usage](#usage)\n    - [Initialization](#initialization)\n    - [Using the SDK for other providers except OpenAI](#using-the-sdk-for-other-providers-except-openai)\n    - [Cancelling requests](#cancelling-requests)\n- [Text and prompting](#text-and-prompting)\n    - [Responses](#responses)\n    - [Chat Completions](#chat-completions)\n- [Function calling](#function-calling)\n- [Tools](#tools)\n    - [MCP (Model Context Protocol)](#mcp-model-context-protocol)\n        - [MCP Tool Integration](#mcp-tool-integration)\n- [Images](#images)\n    - [Create Image](#create-image)\n    - [Create Image Edit](#create-image-edit)\n    - [Create Image Variation](#create-image-variation)\n- [Audio](#audio)\n    - [Audio Create Speech](#audio-create-speech)\n    - [Audio Transcriptions](#audio-transcriptions)\n    - [Audio Translations](#audio-translations)\n- [Structured Outputs](#structured-outputs)\n- [Specialized models](#specialized-models)\n    - [Embeddings](#embeddings)\n    - [Moderations](#moderations)\n- [Assistants (Beta)](#assistants)\n    - [Create Assistant](#create-assistant)\n    - [Modify Assistant](#modify-assistant)\n    - [List Assistants](#list-assistants) \n    - [Threads](#threads)\n        - [Create Thread](#create-thread)\n        - [Create and Run Thread](#create-and-run-thread)\n        - [Get Threads Messages](#get-threads-messages)\n        - [Add Message to Thread](#add-message-to-thread)\n    - [Runs](#runs)\n        - [Create Run](#create-run)\n        - [Retrieve Run](#retrieve-run)\n        - [Retrieve Run Steps](#retrieve-run-steps)\n        - [Submit Tool Outputs for Run](#submit-tool-outputs-for-run)\n    - [Files](#files)\n        - [Upload File](#upload-file)\n- [Other APIs](#other-apis)\n    - [Models](#models)\n        - [List Models](#list-models)\n        - [Retrieve Model](#retrieve-model)\n    - [Utilities](#utilities)\n- [Support for other providers: Gemini, DeepSeek, Perplexity, OpenRouter, etc.](#support-for-other-providers)\n- [Example Project](#example-project)\n- [Contribution Guidelines](#contribution-guidelines)\n- [Links](#links)\n- [License](#license)\n## Documentation\n\nThis library implements it's types and methods in close accordance to the REST API documentation, which can be found on [platform.openai.com](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference).\n\n## Installation\n\n### Swift Package Manager\n\nTo integrate OpenAI into your Xcode project using Swift Package Manager:\n\n1.  In Xcode, go to **File > Add Package Dependencies...**\n2.  Enter the repository URL: `https:\u002F\u002Fgithub.com\u002FMacPaw\u002FOpenAI.git`\n3.  Choose your desired dependency rule (e.g., \"Up to Next Major Version\").\n\nAlternatively, you can add it directly to your `Package.swift` file:\n\n```swift\ndependencies: [\n    .package(url: \"https:\u002F\u002Fgithub.com\u002FMacPaw\u002FOpenAI.git\", branch: \"main\")\n]\n```\n\n## Usage\n\n### Initialization\n\nTo initialize API instance you need to [obtain](https:\u002F\u002Fplatform.openai.com\u002Faccount\u002Fapi-keys) API token from your Open AI organization.\n\n**Remember that your API key is a secret!** Do not share it with others or expose it in any client-side code (browsers, apps). Production requests must be routed through your own backend server where your API key can be securely loaded from an environment variable or key management service.\n\n\u003Cimg width=\"1081\" alt=\"company\" src=\"https:\u002F\u002Fuser-images.githubusercontent.com\u002F1411778\u002F213204726-0772373e-14db-4d5d-9a58-bc249bac4c57.png\">\n\nOnce you have a token, you can initialize `OpenAI` class, which is an entry point to the API.\n\n> ⚠️ OpenAI strongly recommends developers of client-side applications proxy requests through a separate backend service to keep their API key safe. API keys can access and manipulate customer billing, usage, and organizational data, so it's a significant risk to [expose](https:\u002F\u002Fnshipster.com\u002Fsecrets\u002F) them.\n\n```swift\nlet openAI = OpenAI(apiToken: \"YOUR_TOKEN_HERE\")\n```\n\nOptionally you can initialize `OpenAI` with token, organization identifier and timeoutInterval.\n\n```swift\nlet configuration = OpenAI.Configuration(token: \"YOUR_TOKEN_HERE\", organizationIdentifier: \"YOUR_ORGANIZATION_ID_HERE\", timeoutInterval: 60.0)\nlet openAI = OpenAI(configuration: configuration)\n```\n\nSee `OpenAI.Configuration` for more values that can be passed on init for customization, like: `host`, `basePath`, `port`, `scheme` and `customHeaders`.\n\nOnce you posses the token, and the instance is initialized you are ready to make requests.\n\n### Using the SDK for other providers except OpenAI\n\nThis SDK is more focused on working with OpenAI Platform, but also works with other providers that support OpenAI-compatible API.\n\nUse `.relaxed` parsing option on Configuration, or see more details on the topic [here](#support-for-other-providers)\n\n### Cancelling requests\n\nFor Swift Concurrency calls, you can simply cancel the calling task, and corresponding underlying `URLSessionDataTask` would get cancelled automatically.\n\n```swift\nlet task = Task {\n    do {\n        let chatResult = try await openAIClient.chats(query: .init(messages: [], model: \"asd\"))\n    } catch {\n        \u002F\u002F Handle cancellation or error\n    }\n}\n            \ntask.cancel()\n```\n\n\u003Cdetails>\n\u003Csummary>Cancelling closure-based API calls\u003C\u002Fsummary>\n\nWhen you call any of the closure-based API methods, it returns discardable `CancellableRequest`. Hold a reference to it to be able to cancel the request later.\n```swift\nlet cancellableRequest = object.chats(query: query, completion: { _ in })\ncancellableReques\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Cancelling Combine subscriptions\u003C\u002Fsummary>\nIn Combine, use a default cancellation mechanism. Just discard the reference to a subscription, or call `cancel()` on it.\n\n```swift\nlet subscription = openAIClient\n    .images(query: query)\n    .sink(receiveCompletion: { completion in }, receiveValue: { imagesResult in })\n    \nsubscription.cancel()\n```\n\u003C\u002Fdetails>\n\n## Text and prompting\n\n### Responses\n\nUse `responses` variable on `OpenAIProtocol` to call Responses API methods.\n\n```swift\npublic protocol OpenAIProtocol {\n    \u002F\u002F ...\n    var responses: ResponsesEndpointProtocol { get }\n    \u002F\u002F ...\n}\n```\n\nSpecify params by passing `CreateModelResponseQuery` to a method. Get `ResponseObject` or a stream of `ResponseStreamEvent` events in response.\n\n**Example: Generate text from a simple prompt**\n```swift\nlet client: OpenAIProtocol = \u002F* client initialization code *\u002F\n\nlet query = CreateModelResponseQuery(\n    input: .textInput(\"Write a one-sentence bedtime story about a unicorn.\"),\n    model: .gpt4_1\n)\n\nlet response: ResponseObject = try await client.responses.createResponse(query: query)\n\u002F\u002F ...\n```\n\u003Cdetails>\n\u003Csummary>print(response)\u003C\u002Fsummary>\n\n```\nResponseObject(\n  createdAt: 1752146109,\n  error: nil,\n  id: \"resp_686fa0bd8f588198affbbf5a8089e2d208a5f6e2111e31f5\",\n  incompleteDetails: nil,\n  instructions: nil,\n  maxOutputTokens: nil,\n  metadata: [:],\n  model: \"gpt-4.1-2025-04-14\",\n  object: \"response\",\n  output: [\n    OpenAI.OutputItem.outputMessage(\n      OpenAI.Components.Schemas.OutputMessage(\n        id: \"msg_686fa0bee24881988a4d1588d7f65c0408a5f6e2111e31f5\",\n        _type: OpenAI.Components.Schemas.OutputMessage._TypePayload.message,\n        role: OpenAI.Components.Schemas.OutputMessage.RolePayload.assistant,\n        content: [\n          OpenAI.Components.Schemas.OutputContent.OutputTextContent(\n            OpenAI.Components.Schemas.OutputTextContent(\n              _type: OpenAI.Components.Schemas.OutputTextContent._TypePayload.outputText,\n              text: \"Under a sky full of twinkling stars, a gentle unicorn named Luna danced through fields of stardust, spreading sweet dreams to every sleeping child.\",\n              annotations: [],\n              logprobs: Optional([])\n            )\n          )\n        ],\n        status: OpenAI.Components.Schemas.OutputMessage.StatusPayload.completed\n      )\n    )\n  ],\n  parallelToolCalls: true,\n  previousResponseId: nil,\n  reasoning: Optional(\n    OpenAI.Components.Schemas.Reasoning(\n      effort: nil,\n      summary: nil,\n      generateSummary: nil\n    )\n  ),\n  status: \"completed\",\n  temperature: Optional(1.0),\n  text: OpenAI.Components.Schemas.ResponseProperties.TextPayload(\n    format: Optional(\n      OpenAI.Components.Schemas.TextResponseFormatConfiguration.ResponseFormatText(\n        OpenAI.Components.Schemas.ResponseFormatText(\n          _type: OpenAI.Components.Schemas.ResponseFormatText._TypePayload.text\n        )\n      )\n    ),\n    toolChoice: OpenAI.Components.Schemas.ResponseProperties.ToolChoicePayload.ToolChoiceOptions(\n      OpenAI.Components.Schemas.ToolChoiceOptions.auto\n    ),\n    tools: [],\n    topP: Optional(1.0),\n    truncation: Optional(\"disabled\"),\n    usage: Optional(\n      OpenAI.Components.Schemas.ResponseUsage(\n        inputTokens: 18,\n        inputTokensDetails: OpenAI.Components.Schemas.ResponseUsage.InputTokensDetailsPayload(\n          cachedTokens: 0\n        ),\n        outputTokens: 32,\n        outputTokensDetails: OpenAI.Components.Schemas.ResponseUsage.OutputTokensDetailsPayload(\n          reasoningTokens: 0\n        ),\n        totalTokens: 50\n      )\n    ),\n    user: nil\n  )\n)\n````\n\n\u003C\u002Fdetails>\n\nAn array of content generated by the model is in the `output` property of the response.\n\n> [!NOTE] **The `output` array often has more than one item in it!** It can contain tool calls, data about reasoning tokens generated by reasoning models, and other items. It is not safe to assume that the model's text output is present at `output[0].content[0].text`.\n\nBecause of the note above, to safely and fully read the response, we'd need to switch both over messages and their contents, like this:\n\n```swift\n\u002F\u002F ...\nfor output in response.output {\n    switch output {\n    case .outputMessage(let outputMessage):\n        for content in outputMessage.content {\n            switch content {\n            case .OutputTextContent(let textContent):\n                print(textContent.text)\n            case .RefusalContent(let refusalContent):\n                print(refusalContent.refusal)\n            }\n        }\n    default:\n        \u002F\u002F Unhandled output items. Handle or throw an error.\n    }\n}\n```\n\n### Chat Completions\n\nUse `ChatQuery` with `func chats(query:)` and `func chatsStream(query:)` methods on `OpenAIProtocol` to generate text using Chat Completions API. Get `ChatResult` or `ChatStreamResult` in response.\n\n**Example: Generate text from a simple prompt**\n\n```swift\nlet query = ChatQuery(\n    messages: [\n        .user(.init(content: .string(\"Who are you?\")))\n    ],\n    model: .gpt4_o\n)\n\nlet result = try await openAI.chats(query: query)\n\nprint(result.choices.first?.message.content ?? \"\")\n\u002F\u002F printed to console:\n\u002F\u002F I'm an AI language model created by OpenAI, designed to assist with a wide range of questions and tasks. How can I help you today?\n```\n\n\u003Cdetails>\n\u003Csummary>po result\u003C\u002Fsummary>\n\n```\n(lldb) po result\n▿ ChatResult\n  - id : \"chatcmpl-BgWJTzbVczdJDusTqVpnR6AQ2w6Fd\"\n  - created : 1749473687\n  - model : \"gpt-4o-2024-08-06\"\n  - object : \"chat.completion\"\n  ▿ serviceTier : Optional\u003CServiceTier>\n    - some : OpenAI.ServiceTier.defaultTier\n  ▿ systemFingerprint : Optional\u003CString>\n    - some : \"fp_07871e2ad8\"\n  ▿ choices : 1 element\n    ▿ 0 : Choice\n      - index : 0\n      - logprobs : nil\n      ▿ message : Message\n        ▿ content : Optional\u003CString>\n          - some : \"I am an AI language model created by OpenAI, known as ChatGPT. I\\'m here to assist with answering questions, providing explanations, and engaging in conversation on a wide range of topics. If you have any questions or need assistance, feel free to ask!\"\n        - refusal : nil\n        - role : \"assistant\"\n        ▿ annotations : Optional\u003CArray\u003CAnnotation>>\n          - some : 0 elements\n        - audio : nil\n        - toolCalls : nil\n        - _reasoning : nil\n        - _reasoningContent : nil\n      - finishReason : \"stop\"\n  ▿ usage : Optional\u003CCompletionUsage>\n    ▿ some : CompletionUsage\n      - completionTokens : 52\n      - promptTokens : 11\n      - totalTokens : 63\n      ▿ promptTokensDetails : Optional\u003CPromptTokensDetails>\n        ▿ some : PromptTokensDetails\n          - audioTokens : 0\n          - cachedTokens : 0\n  - citations : nil\n```\n\n\u003C\u002Fdetails>\n\n\u003C!-- ## Images and vision\n\n## Audio and speech\n\n## Structured Outputs -->\n\n## Function calling\n\nSee [OpenAI Platform Guide: Function calling](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fguides\u002Ffunction-calling?api-mode=responses) for more details.\n\n\u003Cdetails>\n\n\u003Csummary>Chat Completions API Examples\u003C\u002Fsummary>\n\n### Function calling with get_weather function\n\n```swift\nlet openAI = OpenAI(apiToken: \"...\")\n\u002F\u002F Declare functions which model might decide to call.\nlet functions = [\n    ChatQuery.ChatCompletionToolParam.FunctionDefinition(\n        name: \"get_weather\",\n        description: \"Get current temperature for a given location.\",\n        parameters: .init(fields: [\n            .type(.object),\n            .properties([\n                \"location\": .init(fields: [\n                    .type(.string),\n                    .description(\"City and country e.g. Bogotá, Colombia\")\n                ])\n            ]),\n            .required([\"location\"]),\n            .additionalProperties(.boolean(false))\n        ])\n    )\n]\nlet query = ChatQuery(\n    messages: [\n        .user(.init(content: .string(\"What is the weather like in Paris today?\"\n    ],\n    model: .gpt4_1,\n    tools: functions.map { .init(function: $0) }\n)\nlet result = try await openAI.chats(query: query)\nprint(result.choices[0].message.toolCalls)\n```\n\nResult will be (serialized as JSON here for readability):\n```json\n{\n  \"id\": \"chatcmpl-1234\",\n  \"object\": \"chat.completion\",\n  \"created\": 1686000000,\n  \"model\": \"gpt-3.5-turbo-0613\",\n  \"choices\": [\n    {\n      \"index\": 0,\n      \"message\": {\n        \"role\": \"assistant\",\n        \"tool_calls\": [\n          {\n            \"id\": \"call-0\",\n            \"type\": \"function\",\n            \"function\": {\n              \"name\": \"get_current_weather\",\n              \"arguments\": \"{\\n  \\\"location\\\": \\\"Boston, MA\\\"\\n}\"\n            }\n          }\n        ]\n      },\n      \"finish_reason\": \"function_call\"\n    }\n  ],\n  \"usage\": { \"total_tokens\": 100, \"completion_tokens\": 18, \"prompt_tokens\": 82 }\n}\n\n```\n\n\u003C\u002Fdetails>\n\n## Images\n\nGiven a prompt and\u002For an input image, the model will generate a new image.\n\nAs Artificial Intelligence continues to develop, so too does the intriguing concept of Dall-E. Developed by OpenAI, a research lab for artificial intelligence purposes, Dall-E has been classified as an AI system that can generate images based on descriptions provided by humans. With its potential applications spanning from animation and illustration to design and engineering - not to mention the endless possibilities in between - it's easy to see why there is such excitement over this new technology.\n\n### Create Image\n\n**Request**\n\n```swift\nstruct ImagesQuery: Codable {\n    \u002F\u002F\u002F A text description of the desired image(s). The maximum length is 1000 characters.\n    public let prompt: String\n    \u002F\u002F\u002F The number of images to generate. Must be between 1 and 10.\n    public let n: Int?\n    \u002F\u002F\u002F The size of the generated images. Must be one of 256x256, 512x512, or 1024x1024.\n    public let size: String?\n}\n```\n\n**Response**\n\n```swift\nstruct ImagesResult: Codable, Equatable {\n    public struct URLResult: Codable, Equatable {\n        public let url: String\n    }\n    public let created: TimeInterval\n    public let data: [URLResult]\n}\n```\n\n**Example**\n\n```swift\nlet query = ImagesQuery(prompt: \"White cat with heterochromia sitting on the kitchen table\", n: 1, size: \"1024x1024\")\nopenAI.images(query: query) { result in\n  \u002F\u002FHandle result here\n}\n\u002F\u002For\nlet result = try await openAI.images(query: query)\n```\n\n```\n(lldb) po result\n▿ ImagesResult\n  - created : 1671453505.0\n  ▿ data : 1 element\n    ▿ 0 : URLResult\n      - url : \"https:\u002F\u002Foaidalleapiprodscus.blob.core.windows.net\u002Fprivate\u002Forg-CWjU5cDIzgCcVjq10pp5yX5Q\u002Fuser-GoBXgChvLBqLHdBiMJBUbPqF\u002Fimg-WZVUK2dOD4HKbKwW1NeMJHBd.png?st=2022-12-19T11%3A38%3A25Z&se=2022-12-19T13%3A38%3A25Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image\u002Fpng&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2022-12-19T09%3A35%3A16Z&ske=2022-12-20T09%3A35%3A16Z&sks=b&skv=2021-08-06&sig=mh52rmtbQ8CXArv5bMaU6lhgZHFBZz\u002FePr4y%2BJwLKOc%3D\"\n ```\n\n**Generated image**\n\n![Generated Image](https:\u002F\u002Fuser-images.githubusercontent.com\u002F1411778\u002F213134082-ba988a72-fca0-4213-8805-63e5f8324cab.png)\n\n### Create Image Edit\n\nCreates an edited or extended image given an original image and a prompt.\n\n**Request**\n\n```swift\npublic struct ImageEditsQuery: Codable {\n    \u002F\u002F\u002F The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not provided, image must have transparency, which will be used as the mask.\n    public let image: Data\n    public let fileName: String\n    \u002F\u002F\u002F An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where image should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as image.\n    public let mask: Data?\n    public let maskFileName: String?\n    \u002F\u002F\u002F A text description of the desired image(s). The maximum length is 1000 characters.\n    public let prompt: String\n    \u002F\u002F\u002F The number of images to generate. Must be between 1 and 10.\n    public let n: Int?\n    \u002F\u002F\u002F The size of the generated images. Must be one of 256x256, 512x512, or 1024x1024.\n    public let size: String?\n}\n```\n\n**Response**\n\nUses the ImagesResult response similarly to ImagesQuery.\n\n**Example**\n\n```swift\nlet data = image.pngData()\nlet query = ImageEditQuery(image: data, fileName: \"whitecat.png\", prompt: \"White cat with heterochromia sitting on the kitchen table with a bowl of food\", n: 1, size: \"1024x1024\")\nopenAI.imageEdits(query: query) { result in\n  \u002F\u002FHandle result here\n}\n\u002F\u002For\nlet result = try await openAI.imageEdits(query: query)\n```\n\n### Create Image Variation\n\nCreates a variation of a given image.\n\n**Request**\n\n```swift\npublic struct ImageVariationsQuery: Codable {\n    \u002F\u002F\u002F The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not provided, image must have transparency, which will be used as the mask.\n    public let image: Data\n    public let fileName: String\n    \u002F\u002F\u002F The number of images to generate. Must be between 1 and 10.\n    public let n: Int?\n    \u002F\u002F\u002F The size of the generated images. Must be one of 256x256, 512x512, or 1024x1024.\n    public let size: String?\n}\n```\n\n**Response**\n\nUses the ImagesResult response similarly to ImagesQuery.\n\n**Example**\n\n```swift\nlet data = image.pngData()\nlet query = ImageVariationQuery(image: data, fileName: \"whitecat.png\", n: 1, size: \"1024x1024\")\nopenAI.imageVariations(query: query) { result in\n  \u002F\u002FHandle result here\n}\n\u002F\u002For\nlet result = try await openAI.imageVariations(query: query)\n```\n\nReview [Images Documentation](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fimages) for more info.\n\n## Audio\n\nThe speech to text API provides two endpoints, transcriptions and translations, based on our state-of-the-art open source large-v2 [Whisper model](https:\u002F\u002Fopenai.com\u002Fresearch\u002Fwhisper). They can be used to:\n\nTranscribe audio into whatever language the audio is in.\nTranslate and transcribe the audio into english.\nFile uploads are currently limited to 25 MB and the following input file types are supported: mp3, mp4, mpeg, mpga, m4a, wav, and webm.\n\n### Audio Create Speech\n\nThis function sends an `AudioSpeechQuery` to the OpenAI API to create audio speech from text using a specific voice and format. \n\n[Learn more about voices.](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fguides\u002Ftext-to-speech\u002Fvoice-options)  \n[Learn more about models.](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fmodels\u002Ftts)\n\n**Request:**  \n\n```swift\npublic struct AudioSpeechQuery: Codable, Equatable {\n    \u002F\u002F...\n    public let model: Model \u002F\u002F tts-1 or tts-1-hd  \n    public let input: String\n    public let voice: AudioSpeechVoice\n    public let responseFormat: AudioSpeechResponseFormat\n    public let speed: String? \u002F\u002F Initializes with Double?\n    \u002F\u002F...\n}\n```\n\n**Response:**\n\n```swift\n\u002F\u002F\u002F Audio data for one of the following formats :`mp3`, `opus`, `aac`, `flac`, `pcm`\npublic let audioData: Data?\n```\n\n**Example:**   \n\n```swift\nlet query = AudioSpeechQuery(model: .tts_1, input: \"Hello, world!\", voice: .alloy, responseFormat: .mp3, speed: 1.0)\n\nopenAI.audioCreateSpeech(query: query) { result in\n    \u002F\u002F Handle response here\n}\n\u002F\u002For\nlet result = try await openAI.audioCreateSpeech(query: query)\n```\n[OpenAI Create Speech – Documentation](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Faudio\u002FcreateSpeech)\n\n### Audio Create Speech Streaming\n\nAudio Create Speech is available by using `audioCreateSpeechStream` function. Tokens will be sent one-by-one.\n\n**Closures**\n```swift\nopenAI.audioCreateSpeechStream(query: query) { partialResult in\n    switch partialResult {\n    case .success(let result):\n        print(result.audio)\n    case .failure(let error):\n        \u002F\u002FHandle chunk error here\n    }\n} completion: { error in\n    \u002F\u002FHandle streaming error here\n}\n```\n\n**Combine**\n\n```swift\nopenAI\n    .audioCreateSpeechStream(query: query)\n    .sink { completion in\n        \u002F\u002FHandle completion result here\n    } receiveValue: { result in\n        \u002F\u002FHandle chunk here\n    }.store(in: &cancellables)\n```\n\n**Structured concurrency**\n```swift\nfor try await result in openAI.audioCreateSpeechStream(query: query) {\n   \u002F\u002FHandle result here\n}\n```\n\n### Audio Transcriptions\n\nTranscribes audio into the input language.\n\n**Request**\n\n```swift\npublic struct AudioTranscriptionQuery: Codable, Equatable {\n    \n    public let file: Data\n    public let fileName: String\n    public let model: Model\n    \n    public let prompt: String?\n    public let temperature: Double?\n    public let language: String?\n}\n```\n\n**Response**\n\n```swift\npublic struct AudioTranscriptionResult: Codable, Equatable {\n    \n    public let text: String\n}\n```\n\n**Example**\n\n```swift\nlet data = Data(contentsOfURL:...)\nlet query = AudioTranscriptionQuery(file: data, fileName: \"audio.m4a\", model: .whisper_1)        \n\nopenAI.audioTranscriptions(query: query) { result in\n    \u002F\u002FHandle result here\n}\n\u002F\u002For\nlet result = try await openAI.audioTranscriptions(query: query)\n```\n\n### Audio Translations\n\nTranslates audio into into English.\n\n**Request**\n\n```swift\npublic struct AudioTranslationQuery: Codable, Equatable {\n    \n    public let file: Data\n    public let fileName: String\n    public let model: Model\n    \n    public let prompt: String?\n    public let temperature: Double?\n}    \n```\n\n**Response**\n\n```swift\npublic struct AudioTranslationResult: Codable, Equatable {\n    \n    public let text: String\n}\n```\n\n**Example**\n\n```swift\nlet data = Data(contentsOfURL:...)\nlet query = AudioTranslationQuery(file: data, fileName: \"audio.m4a\", model: .whisper_1)  \n\nopenAI.audioTranslations(query: query) { result in\n    \u002F\u002FHandle result here\n}\n\u002F\u002For\nlet result = try await openAI.audioTranslations(query: query)\n```\n\nReview [Audio Documentation](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Faudio) for more info.\n\n## Structured Outputs\n\n> [!NOTE] This section focuses on non-function calling use cases in the Responses and Chat Completions APIs. To learn more about how to use Structured Outputs with function calling, check out the [Function Calling](#function-calling).\n\nTo configure structured outputs you would define a JSON Schema and pass it to a query.\n\n> [!NOTE]\n> The two query types pass the schema via different parameters, mirroring the OpenAI API:\n> - `ChatQuery` (Chat Completions API): `responseFormat: .jsonSchema(...)` — encoded as `response_format`.\n> - `CreateModelResponseQuery` (Responses API): `text: .jsonSchema(...)` — encoded as `text`.\n>\n> Both accept the same `JSONSchemaDefinition` value, so the schema-building examples below apply to either query type.\n\nThis SDK supports multiple ways to define a schema; choose the one you prefer.\n\n\u003Cdetails>\n\n\u003Csummary>JSONSchemaDefinition.jsonSchema\u003C\u002Fsummary>\n\n### Build a schema by specifying fields\n\nThis definition accepts `JSONSchema` which is either `boolean` or `object` JSON Document.\n\nInstead of providing schema yourself you can build one in a type-safe manner using initializers that accept `[JSONSchemaField]`, as shown in the example below.\n\nWhile this method of defining a schema is direct, it can be verbose. For alternative ways to define a schema, see the options below.\n\n### Example\n\n```swift\nlet query = CreateModelResponseQuery(\n    input: .textInput(\"Return structured output\"),\n    model: .gpt4_o,\n    text: .jsonSchema(.init(\n        name: \"research_paper_extraction\",\n        schema: .jsonSchema(.init(\n            .type(.object),\n            .properties([\n                \"title\": Schema.buildBlock(\n                    .type(.string)\n                ),\n                \"authors\": .init(\n                    .type(.array),\n                    .items(.init(\n                        .type(.string)\n                    ))\n                ),\n                \"abstract\": .init(\n                    .type(.string)\n                ),\n                \"keywords\": .init(\n                    .type(.array),\n                    .items(.init(\n                        .type(.string))\n                    )\n                )\n            ]),\n            .required([\"title, authors, abstract, keywords\"]),\n            .additionalProperties(.boolean(false))\n        )),\n        description: \"desc\",\n        strict: false\n    ))\n)\n\nlet response = try await openAIClient.responses.createResponse(query: query)\nfor output in response.output {\n    switch output {\n    case .outputMessage(let message):\n        for content in message.content {\n            switch content {\n            case .OutputTextContent(let textContent):\n                print(\"json output structured by the schema: \", textContent.text)\n            case .RefusalContent(let refusal):\n                \u002F\u002F Handle refusal\n                break\n            }\n        }\n    default:\n        \u002F\u002F Handle other OutputItems\n        break\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\n\u003Csummary>JSONSchemaDefinition.derivedJsonSchema\u003C\u002Fsummary>\n\n### Implement a type that describes a schema\n\nUse [Pydantic](https:\u002F\u002Fdocs.pydantic.dev\u002Flatest\u002F) or [Zod](https:\u002F\u002Fzod.dev) fashion to define schemas.\n\n- Use the `derivedJsonSchema(_ type:)` schema definition. Pass it via `responseFormat:` for `ChatQuery` or via `text:` for `CreateModelResponseQuery`.\n- Provide a type that conforms to `JSONSchemaConvertible` and generates an instance as an example\n- Make sure all enum types within the provided type conform to `JSONSchemaEnumConvertible` and generate an array of names for all cases\n\n### Example\n\n```swift\nstruct MovieInfo: JSONSchemaConvertible {\n    \n    let title: String\n    let director: String\n    let release: Date\n    let genres: [MovieGenre]\n    let cast: [String]\n    \n    static let example: Self = {\n        .init(\n            title: \"Earth\",\n            director: \"Alexander Dovzhenko\",\n            release: Calendar.current.date(from: DateComponents(year: 1930, month: 4, day: 1))!,\n            genres: [.drama],\n            cast: [\"Stepan Shkurat\", \"Semyon Svashenko\", \"Yuliya Solntseva\"]\n        )\n    }()\n}\nenum MovieGenre: String, Codable, JSONSchemaEnumConvertible {\n    case action, drama, comedy, scifi\n    \n    var caseNames: [String] { Self.allCases.map { $0.rawValue } }\n}\nlet query = ChatQuery(\n    messages: [\n        .system(\n            .init(content: .textContent(\"Best Picture winner at the 2011 Oscars\"))\n        )\n    ],\n    model: .gpt4_o,\n    responseFormat: .jsonSchema(\n        .init(\n            name: \"movie-info\",\n            description: nil,\n            schema: .derivedJsonSchema(MovieInfo.self),\n            strict: true\n        )\n    )\n)\nlet result = try await openAI.chats(query: query)\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\n\u003Csummary>JSONSchemaDefinition.dynamicJsonSchema\u003C\u002Fsummary>\n\n### Define a schema with an instance of any type that conforms to Encodable\n\nDefine your JSON schema using simple Dictionaries, or specify JSON schema with a library like https:\u002F\u002Fgithub.com\u002Fkevinhermawan\u002Fswift-json-schema.\n\n### Example\n\n```swift\nstruct AnyEncodable: Encodable {\n    private let _encode: (Encoder) throws -> Void\n    public init\u003CT: Encodable>(_ wrapped: T) {\n        _encode = wrapped.encode\n    }\n    func encode(to encoder: Encoder) throws {\n        try _encode(encoder)\n    }\n}\nlet schema = [\n    \"type\": AnyEncodable(\"object\"),\n    \"properties\": AnyEncodable([\n        \"title\": AnyEncodable([\n            \"type\": \"string\"\n        ]),\n        \"director\": AnyEncodable([\n            \"type\": \"string\"\n        ]),\n        \"release\": AnyEncodable([\n            \"type\": \"string\"\n        ]),\n        \"genres\": AnyEncodable([\n            \"type\": AnyEncodable(\"array\"),\n            \"items\": AnyEncodable([\n                \"type\": AnyEncodable(\"string\"),\n                \"enum\": AnyEncodable([\"action\", \"drama\", \"comedy\", \"scifi\"])\n            ])\n        ]),\n        \"cast\": AnyEncodable([\n            \"type\": AnyEncodable(\"array\"),\n            \"items\": AnyEncodable([\n                \"type\": \"string\"\n            ])\n        ])\n    ]),\n    \"additionalProperties\": AnyEncodable(false)\n]\nlet query = ChatQuery(\n    messages: [.system(.init(content: .textContent(\"Return a structured response.\")))],\n    model: .gpt4_o,\n    responseFormat: .jsonSchema(.init(name: \"movie-info\", schema: .dynamicJsonSchema(schema)))\n)\nlet result = try await openAI.chats(query: query)\n```\n\n\u003C\u002Fdetails>\n\nReview [Structured Output Documentation](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fguides\u002Fstructured-outputs) for more info.\n\n## Tools\n### Remote MCP (Model Context Protocol)\n\nThe Model Context Protocol (MCP) enables AI models to securely connect to external data sources and tools through standardized server connections. This OpenAI Swift library supports MCP integration, allowing you to extend model capabilities with remote tools and services.\n\nYou can use the [MCP Swift library](https:\u002F\u002Fgithub.com\u002Fmodelcontextprotocol\u002Fswift-sdk) to connect to MCP servers and discover available tools, then integrate those tools with OpenAI's chat completions.\n\n#### MCP Tool Integration\n\n**Request**\n\n```swift\n\u002F\u002F Create an MCP tool for connecting to a remote server\nlet mcpTool = Tool.mcpTool(\n    .init(\n        _type: .mcp,\n        serverLabel: \"GitHub_MCP_Server\",\n        serverUrl: \"https:\u002F\u002Fapi.githubcopilot.com\u002Fmcp\u002F\",\n        headers: .init(additionalProperties: [\n            \"Authorization\": \"Bearer YOUR_TOKEN_HERE\"\n        ]),\n        allowedTools: .case1([\"search_repositories\", \"get_file_contents\"]),\n        requireApproval: .case2(.always)\n    )\n)\n\nlet query = ChatQuery(\n    messages: [\n        .user(.init(content: .string(\"Search for Swift repositories on GitHub\")))\n    ],\n    model: .gpt4_o,\n    tools: [mcpTool]\n)\n```\n\n**MCP Tool Properties**\n\n- `serverLabel`: A unique identifier for the MCP server\n- `serverUrl`: The URL endpoint of the MCP server\n- `headers`: Authentication headers and other HTTP headers required by the server\n- `allowedTools`: Specific tools to enable from the server (optional - if not specified, all tools are available)\n- `requireApproval`: Whether tool calls require user approval (`.always`, `.never`, or conditional)\n\n**Example with MCP Swift Library**\n\n```swift\nimport MCP\nimport OpenAI\n\n\u002F\u002F Connect to MCP server using the MCP Swift library\nlet mcpClient = MCP.Client(name: \"MyApp\", version: \"1.0.0\")\n\nlet transport = HTTPClientTransport(\n    endpoint: URL(string: \"https:\u002F\u002Fapi.githubcopilot.com\u002Fmcp\u002F\")!,\n    configuration: URLSessionConfiguration.default\n)\n\nlet result = try await mcpClient.connect(transport: transport)\nlet toolsResponse = try await mcpClient.listTools()\n\n\u002F\u002F Create OpenAI MCP tool with discovered tools\nlet enabledToolNames = toolsResponse.tools.map { $0.name }\nlet mcpTool = Tool.mcpTool(\n    .init(\n        _type: .mcp,\n        serverLabel: \"GitHub_MCP_Server\",\n        serverUrl: \"https:\u002F\u002Fapi.githubcopilot.com\u002Fmcp\u002F\",\n        headers: .init(additionalProperties: authHeaders),\n        allowedTools: .case1(enabledToolNames),\n        requireApproval: .case2(.always)\n    )\n)\n\n\u002F\u002F Use in chat completion\nlet query = ChatQuery(\n    messages: [.user(.init(content: .string(\"Help me search GitHub repositories\")))],\n    model: .gpt4_o,\n    tools: [mcpTool]\n)\n\nlet chatResult = try await openAI.chats(query: query)\n```\n\n**MCP Tool Call Handling**\n\nWhen using MCP tools, the model may generate tool calls that are executed on the remote MCP server. Handle MCP-specific output items in your response processing:\n\n```swift\n\u002F\u002F Handle MCP tool calls in streaming responses\nfor try await result in openAI.chatsStream(query: query) {\n    for choice in result.choices {\n        if let outputItem = choice.delta.content {\n            switch outputItem {\n            case .mcpToolCall(let mcpCall):\n                print(\"MCP tool call: \\(mcpCall.name)\")\n                if let output = mcpCall.output {\n                    print(\"Result: \\(output)\")\n                }\n            case .mcpApprovalRequest(let approvalRequest):\n                \u002F\u002F Handle approval request if requireApproval is enabled\n                print(\"MCP tool requires approval: \\(approvalRequest)\")\n            default:\n                \u002F\u002F Handle other output types\n                break\n            }\n        }\n    }\n}\n```\n\n## Specialized models\n\n### Embeddings\n\nGet a vector representation of a given input that can be easily consumed by machine learning models and algorithms.\n\n**Request**\n\n```swift\nstruct EmbeddingsQuery: Codable {\n    \u002F\u002F\u002F ID of the model to use.\n    public let model: Model\n    \u002F\u002F\u002F Input text to get embeddings for\n    public let input: String\n}\n```\n\n**Response**\n\n```swift\nstruct EmbeddingsResult: Codable, Equatable {\n\n    public struct Embedding: Codable, Equatable {\n\n        public let object: String\n        public let embedding: [Double]\n        public let index: Int\n    }\n    public let data: [Embedding]\n    public let usage: Usage\n}\n```\n\n**Example**\n\n```swift\nlet query = EmbeddingsQuery(model: .textSearchBabbageDoc, input: \"The food was delicious and the waiter...\")\nopenAI.embeddings(query: query) { result in\n  \u002F\u002FHandle response here\n}\n\u002F\u002For\nlet result = try await openAI.embeddings(query: query)\n```\n\n```\n(lldb) po result\n▿ EmbeddingsResult\n  ▿ data : 1 element\n    ▿ 0 : Embedding\n      - object : \"embedding\"\n      ▿ embedding : 2048 elements\n        - 0 : 0.0010535449\n        - 1 : 0.024234328\n        - 2 : -0.0084999\n        - 3 : 0.008647452\n    .......\n        - 2044 : 0.017536353\n        - 2045 : -0.005897616\n        - 2046 : -0.026559394\n        - 2047 : -0.016633155\n      - index : 0\n\n(lldb)\n```\n\nReview [Embeddings Documentation](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fembeddings) for more info.\n\n### Moderations \n\nGiven a input text, outputs if the model classifies it as violating OpenAI's content policy.\n\n**Request**\n\n```swift\npublic struct ModerationsQuery: Codable {\n    \n    public let input: String\n    public let model: Model?\n}    \n```\n\n**Response**\n\n```swift\npublic struct ModerationsResult: Codable, Equatable {\n\n    public let id: String\n    public let model: Model\n    public let results: [CategoryResult]\n}\n```\n\n**Example**\n\n```swift\nlet query = ModerationsQuery(input: \"I want to kill them.\")\nopenAI.moderations(query: query) { result in\n  \u002F\u002FHandle result here\n}\n\u002F\u002For\nlet result = try await openAI.moderations(query: query)\n```\n\nReview [Moderations Documentation](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fmoderations) for more info.\n\n## Other APIs\n\n### Models \n\nModels are represented as a typealias `typealias Model = String`.\n\n```swift\npublic extension Model {\n    static let gpt5_1 = \"gpt-5.1\"\n    static let gpt5_1_chat_latest = \"gpt-5.1-chat-latest\"\n\n    static let gpt5 = \"gpt-5\"\n    static let gpt5_mini = \"gpt-5-mini\"\n    static let gpt5_nano = \"gpt-5-nano\"\n    static let gpt5_chat = \"gpt-5-chat\"\n\n    static let gpt4_1 = \"gpt-4.1\"\n    static let gpt4_1_mini = \"gpt-4.1-mini\"\n    static let gpt4_1_nano = \"gpt-4.1-nano\"\n\n    static let gpt4_turbo_preview = \"gpt-4-turbo-preview\"\n    static let gpt4_vision_preview = \"gpt-4-vision-preview\"\n    static let gpt4_0125_preview = \"gpt-4-0125-preview\"\n    static let gpt4_1106_preview = \"gpt-4-1106-preview\"\n    static let gpt4 = \"gpt-4\"\n    static let gpt4_0613 = \"gpt-4-0613\"\n    static let gpt4_0314 = \"gpt-4-0314\"\n    static let gpt4_32k = \"gpt-4-32k\"\n    static let gpt4_32k_0613 = \"gpt-4-32k-0613\"\n    static let gpt4_32k_0314 = \"gpt-4-32k-0314\"\n    \n    static let gpt3_5Turbo = \"gpt-3.5-turbo\"\n    static let gpt3_5Turbo_0125 = \"gpt-3.5-turbo-0125\"\n    static let gpt3_5Turbo_1106 = \"gpt-3.5-turbo-1106\"\n    static let gpt3_5Turbo_0613 = \"gpt-3.5-turbo-0613\"\n    static let gpt3_5Turbo_0301 = \"gpt-3.5-turbo-0301\"\n    static let gpt3_5Turbo_16k = \"gpt-3.5-turbo-16k\"\n    static let gpt3_5Turbo_16k_0613 = \"gpt-3.5-turbo-16k-0613\"\n    \n    static let textDavinci_003 = \"text-davinci-003\"\n    static let textDavinci_002 = \"text-davinci-002\"\n    static let textCurie = \"text-curie-001\"\n    static let textBabbage = \"text-babbage-001\"\n    static let textAda = \"text-ada-001\"\n    \n    static let textDavinci_001 = \"text-davinci-001\"\n    static let codeDavinciEdit_001 = \"code-davinci-edit-001\"\n    \n    static let tts_1 = \"tts-1\"\n    static let tts_1_hd = \"tts-1-hd\"\n    \n    static let whisper_1 = \"whisper-1\"\n\n    static let dall_e_2 = \"dall-e-2\"\n    static let dall_e_3 = \"dall-e-3\"\n    \n    static let davinci = \"davinci\"\n    static let curie = \"curie\"\n    static let babbage = \"babbage\"\n    static let ada = \"ada\"\n    \n    static let textEmbeddingAda = \"text-embedding-ada-002\"\n    static let textSearchAda = \"text-search-ada-doc-001\"\n    static let textSearchBabbageDoc = \"text-search-babbage-doc-001\"\n    static let textSearchBabbageQuery001 = \"text-search-babbage-query-001\"\n    static let textEmbedding3 = \"text-embedding-3-small\"\n    static let textEmbedding3Large = \"text-embedding-3-large\"\n    \n    static let textModerationStable = \"text-moderation-stable\"\n    static let textModerationLatest = \"text-moderation-latest\"\n    static let moderation = \"text-moderation-007\"\n}\n```\n\nGPT-4 models are supported. \n\nAs an example: To use the `gpt-4-turbo-preview` model, pass `.gpt4_turbo_preview` as the parameter to the `ChatQuery` init.\n\n```swift\nlet query = ChatQuery(model: .gpt4_turbo_preview, messages: [\n    .init(role: .system, content: \"You are Librarian-GPT. You know everything about the books.\"),\n    .init(role: .user, content: \"Who wrote Harry Potter?\")\n])\nlet result = try await openAI.chats(query: query)\nXCTAssertFalse(result.choices.isEmpty)\n```\n\nYou can also pass a custom string if you need to use some model, that is not represented above.\n\n#### List Models\n\nLists the currently available models.\n\n**Response**\n\n```swift\npublic struct ModelsResult: Codable, Equatable {\n    \n    public let data: [ModelResult]\n    public let object: String\n}\n\n```\n**Example**\n\n```swift\nopenAI.models() { result in\n  \u002F\u002FHandle result here\n}\n\u002F\u002For\nlet result = try await openAI.models()\n```\n\n#### Retrieve Model\n\nRetrieves a model instance, providing ownership information.\n\n**Request**\n\n```swift\npublic struct ModelQuery: Codable, Equatable {\n    \n    public let model: Model\n}    \n```\n\n**Response**\n\n```swift\npublic struct ModelResult: Codable, Equatable {\n\n    public let id: Model\n    public let object: String\n    public let ownedBy: String\n}\n```\n\n**Example**\n\n```swift\nlet query = ModelQuery(model: .gpt4)\nopenAI.model(query: query) { result in\n  \u002F\u002FHandle result here\n}\n\u002F\u002For\nlet result = try await openAI.model(query: query)\n```\n\nReview [Models Documentation](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fmodels) for more info.\n\n### Utilities\n\nThe component comes with several handy utility functions to work with the vectors.\n\n```swift\npublic struct Vector {\n\n    \u002F\u002F\u002F Returns the similarity between two vectors\n    \u002F\u002F\u002F\n    \u002F\u002F\u002F - Parameters:\n    \u002F\u002F\u002F     - a: The first vector\n    \u002F\u002F\u002F     - b: The second vector\n    public static func cosineSimilarity(a: [Double], b: [Double]) -> Double {\n        return dot(a, b) \u002F (mag(a) * mag(b))\n    }\n\n    \u002F\u002F\u002F Returns the difference between two vectors. Cosine distance is defined as `1 - cosineSimilarity(a, b)`\n    \u002F\u002F\u002F\n    \u002F\u002F\u002F - Parameters:\n    \u002F\u002F\u002F     - a: The first vector\n    \u002F\u002F\u002F     - b: The second vector\n    public func cosineDifference(a: [Double], b: [Double]) -> Double {\n        return 1 - Self.cosineSimilarity(a: a, b: b)\n    }\n}\n```\n\n**Example**\n\n```swift\nlet vector1 = [0.213123, 0.3214124, 0.421412, 0.3214521251, 0.412412, 0.3214124, 0.1414124, 0.3214521251, 0.213123, 0.3214124, 0.1414124, 0.4214214, 0.213123, 0.3214124, 0.1414124, 0.3214521251, 0.213123, 0.3214124, 0.1414124, 0.3214521251]\nlet vector2 = [0.213123, 0.3214124, 0.1414124, 0.3214521251, 0.213123, 0.3214124, 0.1414124, 0.3214521251, 0.213123, 0.511515, 0.1414124, 0.3214521251, 0.213123, 0.3214124, 0.1414124, 0.3214521251, 0.213123, 0.3214124, 0.1414124, 0.3213213]\nlet similarity = Vector.cosineSimilarity(a: vector1, b: vector2)\nprint(similarity) \u002F\u002F0.9510201910206734\n```\n>In data analysis, cosine similarity is a measure of similarity between two sequences of numbers.\n\n\u003Cimg width=\"574\" alt=\"Screenshot 2022-12-19 at 6 00 33 PM\" src=\"https:\u002F\u002Fuser-images.githubusercontent.com\u002F1411778\u002F208467903-000b52d8-6589-40dd-b020-eeed69e8d284.png\">\n\nRead more about Cosine Similarity [here](https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCosine_similarity).\n\n## Assistants\n\nReview [Assistants Documentation](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fassistants) for more info.\n\n### Create Assistant\n\nExample: Create Assistant\n```swift\nlet query = AssistantsQuery(model: Model.gpt4_o_mini, name: name, description: description, instructions: instructions, tools: tools, toolResources: toolResources)\nopenAI.assistantCreate(query: query) { result in\n   \u002F\u002FHandle response here\n}\n```\n\n### Modify Assistant\n\nExample: Modify Assistant\n```swift\nlet query = AssistantsQuery(model: Model.gpt4_o_mini, name: name, description: description, instructions: instructions, tools: tools, toolResources: toolResources)\nopenAI.assistantModify(query: query, assistantId: \"asst_1234\") { result in\n    \u002F\u002FHandle response here\n}\n```\n\n### List Assistants\n\nExample: List Assistants\n```swift\nopenAI.assistants() { result in\n   \u002F\u002FHandle response here\n}\n```\n\n### Threads\n\nReview [Threads Documentation](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fthreads) for more info.\n\n#### Create Thread\n\nExample: Create Thread\n```swift\nlet threadsQuery = ThreadsQuery(messages: [Chat(role: message.role, content: message.content)])\nopenAI.threads(query: threadsQuery) { result in\n  \u002F\u002FHandle response here\n}\n```\n\n#### Create and Run Thread\n\nExample: Create and Run Thread\n```swift\nlet threadsQuery = ThreadQuery(messages: [Chat(role: message.role, content: message.content)])\nlet threadRunQuery = ThreadRunQuery(assistantId: \"asst_1234\"  thread: threadsQuery)\nopenAI.threadRun(query: threadRunQuery) { result in\n  \u002F\u002FHandle response here\n}\n```\n\n#### Get Threads Messages\n\nReview [Messages Documentation](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fmessages) for more info.\n\nExample: Get Threads Messages\n```swift\nopenAI.threadsMessages(threadId: currentThreadId) { result in\n  \u002F\u002FHandle response here\n}\n```\n\n#### Add Message to Thread\n\nExample: Add Message to Thread\n```swift\nlet query = MessageQuery(role: message.role.rawValue, content: message.content)\nopenAI.threadsAddMessage(threadId: currentThreadId, query: query) { result in\n  \u002F\u002FHandle response here\n}\n```\n\n### Runs\n\nReview [Runs Documentation](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fruns) for more info.\n\n#### Create Run\n\nExample: Create Run\n```swift\nlet runsQuery = RunsQuery(assistantId:  currentAssistantId)\nopenAI.runs(threadId: threadsResult.id, query: runsQuery) { result in\n  \u002F\u002FHandle response here\n}\n```\n\n#### Retrieve Run\n\nExample: Retrieve Run\n```swift\nopenAI.runRetrieve(threadId: currentThreadId, runId: currentRunId) { result in\n  \u002F\u002FHandle response here\n}\n```\n\n#### Retrieve Run Steps\n\nExample: Retrieve Run Steps\n```swift\nopenAI.runRetrieveSteps(threadId: currentThreadId, runId: currentRunId) { result in\n  \u002F\u002FHandle response here\n}\n```\n\n#### Submit Tool Outputs for Run\n\nExample: Submit Tool Outputs for Run\n```swift\nlet output = RunToolOutputsQuery.ToolOutput(toolCallId: \"call123\", output: \"Success\")\nlet query = RunToolOutputsQuery(toolOutputs: [output])\nopenAI.runSubmitToolOutputs(threadId: currentThreadId, runId: currentRunId, query: query) { result in\n  \u002F\u002FHandle response here\n}\n```\n\n### Files\n\nReview [Files Documentation](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Ffiles) for more info.\n\n#### Upload file\n\nExample: Upload file\n```swift\nlet query = FilesQuery(purpose: \"assistants\", file: fileData, fileName: url.lastPathComponent, contentType: \"application\u002Fpdf\")\nopenAI.files(query: query) { result in\n  \u002F\u002FHandle response here\n}\n```\n\n## Support for other providers\n\n> TL;DR Use `.relaxed` parsing option on Configuration\n\nThis SDK has a limited support for other providers like Gemini, Perplexity etc.\n\nThe top priority of this SDK is OpenAI, and the main rule is for all the main types to be fully compatible with [OpenAI's API Reference](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fintroduction). If it says a field should be optional, it must be optional in main subset of Query\u002FResult types of this SDK. The same goes for other info declared in the reference, like default values.\n\nThat said we still want to give a support for other providers.\n\n### Option 1: Use `.relaxed` parsing option\n`.relaxed` parsing option handles both missing and additional key\u002Fvalues in responses. It should be sufficient for most use-cases. Let us know if it doesn't cover any case you need.\n\n### Option 2: Specify parsing options separately\n#### Handle missing keys in responses\nSome providers return responses that don't completely satisfy OpenAI's scheme. Like, Gemini chat completion response ommits `id` field which is a required field in OpenAI's API Reference.\n\nIn such case use `fillRequiredFieldIfKeyNotFound` Parsing Option, like this:\n```swift\nlet configuration = OpenAI.Configuration(token: \"\", parsingOptions: .fillRequiredFieldIfKeyNotFound)\n```\n\n#### Handle missing values in responses\nSome fields are required to be present (non-optional) by OpenAI, but other providers may return `null` for them.\n\nUse `.fillRequiredFieldIfValueNotFound` to handle missing values\n\n#### What if a provider returns additional fields?\nCurrently we handle such cases by simply adding additional fields to main model set. This is possible because optional fields wouldn't break or conflict with OpenAI's scheme. At the moment, such additional fields are added:\n\n`ChatResult`\n\n* `citations` [Perplexity](https:\u002F\u002Fdocs.perplexity.ai\u002Fapi-reference\u002Fchat-completions#response-citations)\n\n`ChatResult.Choice.Message`\n\n* `reasoningContent` [Grok](https:\u002F\u002Fdocs.x.ai\u002Fdocs\u002Fapi-reference#chat-completions), [DeepSeek](https:\u002F\u002Fapi-docs.deepseek.com\u002Fapi\u002Fcreate-chat-completion#responses)\n* `reasoning` [OpenRouter](https:\u002F\u002Fopenrouter.ai\u002Fdocs\u002Fuse-cases\u002Freasoning-tokens#basic-usage-with-reasoning-tokens)\n\n## Example Project\n\nYou can find example iOS application in [Demo](\u002FDemo) folder. \n\n![mockuuups-iphone-13-pro-mockup-perspective-right](https:\u002F\u002Fuser-images.githubusercontent.com\u002F1411778\u002F231449395-2ad6bab6-c21f-43dc-8977-f45f505b609d.png)\n\n## Contribution Guidelines\nMake your Pull Requests clear and obvious to anyone viewing them.  \nSet `main` as your target branch.\n\n#### Use [Conventional Commits](https:\u002F\u002Fwww.conventionalcommits.org\u002Fen\u002Fv1.0.0\u002F) principles in naming PRs and branches:\n\n- `Feat: ...` for new features and new functionality implementations.\n- `Bug: ...` for bug fixes.\n- `Fix: ...` for minor issues fixing, like typos or inaccuracies in code.\n- `Chore: ...` for boring stuff like code polishing, refactoring, deprecation fixing etc.\n\nPR naming example: `Feat: Add Threads API handling` or `Bug: Fix message result duplication`\n\nBranch naming example: `feat\u002Fadd-threads-API-handling` or `bug\u002Ffix-message-result-duplication`\n\n#### Write description to pull requests in following format:\n- What\n\n  ...\n- Why\n  \n  ...\n- Affected Areas\n\n  ...\n- More Info\n\n  ...\n\nWe'll appreciate you including tests to your code if it is needed and possible. ❤️\n\n## Links\n\n- [OpenAI Documentation](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fintroduction)\n- [OpenAI Playground](https:\u002F\u002Fplatform.openai.com\u002Fplayground)\n- [OpenAI Examples](https:\u002F\u002Fplatform.openai.com\u002Fexamples)\n- [Dall-E](https:\u002F\u002Flabs.openai.com\u002F)\n- [Cosine Similarity](https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCosine_similarity)\n\n## License\n\n```\nMIT License\n\nCopyright (c) 2023 MacPaw Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and\u002For sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n","MacPaw\u002FOpenAI 是一个由 Swift 社区维护的 OpenAI 公共 API 的封装库。它支持文本生成、聊天补全、函数调用、图像处理、音频转录与翻译等多种功能，提供了丰富的 API 接口来满足不同的应用场景需求。该项目使用 Swift 语言开发，并通过 Swift Package Manager 进行依赖管理，具有良好的跨平台兼容性。适用于需要在 iOS、macOS 或其他支持 Swift 的平台上集成人工智能功能的应用开发场景，如智能客服系统、内容创作辅助工具等。","2026-06-11 03:10:18","top_language"]