- Notifications
You must be signed in to change notification settings - Fork125
The most complete open-source Swift package for interacting with OpenAI's public API.
License
jamesrochabrun/SwiftOpenAI
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation

An open-source Swift package designed for effortless interaction with OpenAI's public API.
🚀 Now also available asCLI and also asMCP
SwiftOpenAI is an open-source Swift package that streamlines interactions withall OpenAI's API endpoints, now with added support for Azure, AIProxy, Assistant stream APIs, and the newRealtime API for low-latency bidirectional voice conversations.
To interact with OpenAI services, you'll need an API key. Follow these steps to obtain one:
- VisitOpenAI.
- Sign up for anaccount orlog in if you already have one.
- Navigate to theAPI key page and follow the instructions to generate a new API key.
For more information, consult OpenAI'sofficial documentation.
Remember that your API key is a secret! Do not share it with others or exposeit in any client-side code (browsers, apps). Production requests must berouted through your backend server where your API key can be securelyloaded from an environment variable or key management service.
SwiftOpenAI has built-in support for AIProxy, which is a backend for AI apps, to satisfy this requirement.To configure AIProxy, see the instructionshere.
- Open your Swift project in Xcode.
- Go to
File->Add Package Dependency. - In the search bar, enterthis URL.
- Choose the version you'd like to install (see the note below).
- Click
Add Package.
Note: Xcode has a quirk where it defaults an SPM package's upper limit to 2.0.0. This package is beyond thatlimit, so you should not accept the defaults that Xcode proposes. Instead, enter the lower bound of therelease version that you'd like to support, and thentab out of the input box for Xcode to adjust the upper bound. Alternatively, you may selectbranch ->mainto stay on the bleeding edge.
SwiftOpenAI supports both Apple platforms and Linux.
- Apple platforms include iOS 15+, macOS 13+, and watchOS 9+.
- Linux: SwiftOpenAI on Linux uses AsyncHTTPClient to work around URLSession bugs in Apple's Foundation framework, and can be used with theVapor server framework.
SwiftOpenAI supports various providers that are OpenAI-compatible, including but not limited to:
Check OpenAIServiceFactory for convenience initializers that you can use to provide custom URLs.
To use SwiftOpenAI in your project, first import the package:
import SwiftOpenAIThen, initialize the service using your OpenAI API key:
letapiKey="your_openai_api_key_here"letservice=OpenAIServiceFactory.service(apiKey: apiKey)
You can optionally specify an organization name if needed.
letapiKey="your_openai_api_key_here"letoganizationID="your_organixation_id"letservice=OpenAIServiceFactory.service(apiKey: apiKey, organizationID: oganizationID)
For reasoning models, ensure that you extend the timeoutIntervalForRequest in the URL session configuration to a higher value. The default is 60 seconds, which may be insufficient, as requests to reasoning models can take longer to process and respond.
To configure it:
letapiKey="your_openai_api_key_here"letorganizationID="your_organization_id"letsession=URLSession.sharedsession.configuration.timeoutIntervalForRequest=360 // e.g., 360 seconds or more.lethttpClient=URLSessionHTTPClientAdapter(urlSession: session)letservice=OpenAIServiceFactory.service(apiKey: apiKey, organizationID: organizationID, httpClient: httpClient)
That's all you need to begin accessing the full range of OpenAI endpoints.
You may want to build UI around the type of error that the API returns.For example, a429 means that your requests are being rate limited.TheAPIError type has a caseresponseUnsuccessful with two associated values: adescription andstatusCode.Here is a usage example using the chat completion API:
letservice=OpenAIServiceFactory.service(apiKey: apiKey)letparameters=ChatCompletionParameters(messages:[.init(role:.user, content:.text("hello world"))], model:.gpt4o)do{letchoices=tryawait service.startChat(parameters: parameters).choices // Work with choices}catchAPIError.responseUnsuccessful(let description,let statusCode){print("Network error with status code:\(statusCode) and description:\(description)")}catch{print(error.localizedDescription)}
Parameters
publicstructAudioTranscriptionParameters:Encodable{ /// The name of the file asset is not documented in OpenAI's official documentation; however, it is essential for constructing the multipart request.letfileName:String /// The audio file object (not file name) translate, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm.letfile:Data /// ID of the model to use. Only whisper-1 is currently available.letmodel:String /// The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format will improve accuracy and latency.letlanguage:String? /// An optional text to guide the model's style or continue a previous audio segment. The [prompt](https://platform.openai.com/docs/guides/speech-to-text/prompting) should match the audio language.letprompt:String? /// The format of the transcript output, in one of these options: json, text, srt, verbose_json, or vtt. Defaults to jsonletresponseFormat:String? /// The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. Defaults to 0lettemperature:Double?publicenumModel{case whisperOnecase custom(model:String)}publicinit( fileName:String, file:Data, model:Model=.whisperOne, prompt:String?=nil, responseFormat:String?=nil, temperature:Double?=nil, language:String?=nil){self.fileName= fileNameself.file= fileself.model= model.rawValueself.prompt= promptself.responseFormat= responseFormatself.temperature= temperatureself.language= language}}
Response
publicstructAudioObject:Decodable{ /// The transcribed text if the request uses the `transcriptions` API, or the translated text if the request uses the `translations` endpoint.publiclettext:String}
Usage
letfileName="narcos.m4a"letdata=Data(contentsOfURL:_) // Data retrieved from the file named "narcos.m4a".letparameters=AudioTranscriptionParameters(fileName: fileName, file: data) // **Important**: in the file name always provide the file extension.letaudioObject=tryawait service.createTranscription(parameters: parameters)
Parameters
publicstructAudioTranslationParameters:Encodable{ /// The name of the file asset is not documented in OpenAI's official documentation; however, it is essential for constructing the multipart request.letfileName:String /// The audio file object (not file name) translate, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm.letfile:Data /// ID of the model to use. Only whisper-1 is currently available.letmodel:String /// An optional text to guide the model's style or continue a previous audio segment. The [prompt](https://platform.openai.com/docs/guides/speech-to-text/prompting) should match the audio language.letprompt:String? /// The format of the transcript output, in one of these options: json, text, srt, verbose_json, or vtt. Defaults to jsonletresponseFormat:String? /// The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. Defaults to 0lettemperature:Double?publicenumModel{case whisperOnecase custom(model:String)}publicinit( fileName:String, file:Data, model:Model=.whisperOne, prompt:String?=nil, responseFormat:String?=nil, temperature:Double?=nil){self.fileName= fileNameself.file= fileself.model= model.rawValueself.prompt= promptself.responseFormat= responseFormatself.temperature= temperature}}
Response
publicstructAudioObject:Decodable{ /// The transcribed text if the request uses the `transcriptions` API, or the translated text if the request uses the `translations` endpoint.publiclettext:String}
Usage
letfileName="german.m4a"letdata=Data(contentsOfURL:_) // Data retrieved from the file named "german.m4a".letparameters=AudioTranslationParameters(fileName: fileName, file: data) // **Important**: in the file name always provide the file extension.letaudioObject=tryawait service.createTranslation(parameters: parameters)
Parameters
/// [Generates audio from the input text.](https://platform.openai.com/docs/api-reference/audio/createSpeech)publicstructAudioSpeechParameters:Encodable{ /// One of the available [TTS models](https://platform.openai.com/docs/models/tts): tts-1 or tts-1-hdletmodel:String /// The text to generate audio for. The maximum length is 4096 characters.letinput:String /// The voice to use when generating the audio. Supported voices are alloy, echo, fable, onyx, nova, and shimmer. Previews of the voices are available in the [Text to speech guide.](https://platform.openai.com/docs/guides/text-to-speech/voice-options)letvoice:String /// Defaults to mp3, The format to audio in. Supported formats are mp3, opus, aac, and flac.letresponseFormat:String? /// Defaults to 1, The speed of the generated audio. Select a value from 0.25 to 4.0. 1.0 is the default.letspeed:Double?publicenumTTSModel:String{case tts1="tts-1"case tts1HD="tts-1-hd"}publicenumVoice:String{case alloycase echocase fablecase onyxcase novacase shimmer}publicenumResponseFormat:String{case mp3case opuscase aaccase flac}publicinit( model:TTSModel, input:String, voice:Voice, responseFormat:ResponseFormat?=nil, speed:Double?=nil){self.model= model.rawValueself.input= inputself.voice= voice.rawValueself.responseFormat= responseFormat?.rawValueself.speed= speed}}
Response
/// The [audio speech](https://platform.openai.com/docs/api-reference/audio/createSpeech) response.publicstructAudioSpeechObject:Decodable{ /// The audio file content data.publicletoutput:Data}
Usage
letprompt="Hello, how are you today?"letparameters=AudioSpeechParameters(model:.tts1, input: prompt, voice:.shimmer)letaudioObjectData=tryawait service.createSpeech(parameters: parameters).outputplayAudio(from: audioObjectData)// Play dataprivatefunc playAudio(from data:Data){do{ // Initialize the audio player with the data audioPlayer=tryAVAudioPlayer(data: data) audioPlayer?.prepareToPlay() audioPlayer?.play()}catch{ // Handle errorsprint("Error playing audio:\(error.localizedDescription)")}}
TheRealtime API enables bidirectional voice conversations with OpenAI's models using WebSockets and low-latency audio streaming. The API supports both audio-to-audio and text-to-audio interactions with built-in voice activity detection, transcription, and function calling.
Platform Requirements: iOS 15+, macOS 13+, watchOS 9+. Requires AVFoundation (not available on Linux).
Permissions Required:
- Add
NSMicrophoneUsageDescriptionto your Info.plist - On macOS: Enable sandbox entitlements for microphone access and outgoing network connections
Parameters
/// Configuration for creating a realtime sessionpublicstructOpenAIRealtimeSessionConfiguration:Encodable,Sendable{ /// The input audio format. Options: .pcm16, .g711_ulaw, .g711_alaw. Default is .pcm16letinputAudioFormat:AudioFormat? /// Configuration for input audio transcription using WhisperletinputAudioTranscription:InputAudioTranscription? /// System instructions for the model. Recommended default providedletinstructions:String? /// Maximum tokens for response output. Can be .value(Int) or .infiniteletmaxResponseOutputTokens:MaxResponseOutputTokens? /// Output modalities: [.audio, .text] or [.text] only. Default is [.audio, .text]letmodalities:[Modality]? /// The output audio format. Options: .pcm16, .g711_ulaw, .g711_alaw. Default is .pcm16letoutputAudioFormat:AudioFormat? /// Audio playback speed. Range: 0.25 to 4.0. Default is 1.0letspeed:Double? /// Sampling temperature for model responses. Range: 0.6 to 1.2. Default is 0.8lettemperature:Double? /// Array of tools/functions available for the model to calllettools:[Tool]? /// Tool selection mode: .none, .auto, .required, or .specific(functionName: String)lettoolChoice:ToolChoice? /// Voice activity detection configuration. Options: .serverVAD or .semanticVADletturnDetection:TurnDetection? /// The voice to use. Options: "alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse"letvoice:String? /// Available audio formatspublicenumAudioFormat:String,Encodable,Sendable{case pcm16case g711_ulaw="g711-ulaw"case g711_alaw="g711-alaw"} /// Output modalitiespublicenumModality:String,Encodable,Sendable{case audiocase text} /// Turn detection configurationpublicstructTurnDetection:Encodable,Sendable{ /// Server-based VAD with customizable timingpublicstaticfunc serverVAD( prefixPaddingMs:Int=300, silenceDurationMs:Int=500, threshold:Double=0.5)-> TurnDetection /// Semantic VAD with eagerness level public staticfunc semanticVAD(eagerness:Eagerness=.medium)->TurnDetection publicenum Eagerness: String, Encodable, Sendable{ case low, medium, high}}}
Response
/// Messages received from the realtime APIpublicenumOpenAIRealtimeMessage:Sendable{case error(String?) // Error occurredcase sessionCreated // Session successfully createdcase sessionUpdated // Configuration updatedcase responseCreated // Model started generating responsecase responseAudioDelta(String) // Audio chunk (base64 PCM16)case inputAudioBufferSpeechStarted // User started speaking (VAD detected)case responseFunctionCallArgumentsDone(name:String, arguments:String, callId:String)case responseTranscriptDelta(String) // Partial AI transcriptcase responseTranscriptDone(String) // Complete AI transcriptcase inputAudioBufferTranscript(String) // User audio transcriptcase inputAudioTranscriptionDelta(String) // Partial user transcriptioncase inputAudioTranscriptionCompleted(String) // Complete user transcription}
Supporting Types
/// Manages microphone input and audio playback for realtime conversations./// Audio played through AudioController does not interfere with mic input (the model won't hear itself).@RealtimeActorpublicfinalclassAudioController{ /// Initialize with specified modes /// - Parameter modes: Array of .record (for microphone) and/or .playback (for audio output)publicinit(modes:[Mode])asyncthrowspublicenumMode{case record // Enable microphone streamingcase playback // Enable audio playback} /// Returns an AsyncStream of microphone audio buffers /// - Throws: OpenAIError if .record mode wasn't enabled during initializationpublicfunc micStream()throws->AsyncStream<AVAudioPCMBuffer> /// Plays base64-encoded PCM16 audio from the model /// - Parameter base64String: Base64-encoded PCM16 audio datapublicfunc playPCM16Audio(base64String:String) /// Interrupts current audio playback (useful when user starts speaking) publicfunc interruptPlayback() /// Stops all audio operations publicfunc stop()}/// Utility for encoding audio buffers to base64publicenum AudioUtils{ /// Converts AVAudioPCMBuffer to base64 string for transmission public staticfunc base64EncodeAudioPCMBuffer(from buffer:AVAudioPCMBuffer)->String? /// Checks if headphones are connected public staticvarheadphonesConnected:Bool}
Usage
// 1. Create session configurationletconfiguration=OpenAIRealtimeSessionConfiguration( voice:"alloy", instructions:"You are a helpful AI assistant. Be concise and friendly.", turnDetection:.serverVAD( prefixPaddingMs:300, silenceDurationMs:500, threshold:0.5), inputAudioTranscription:.init(model:"whisper-1"))// 2. Create realtime sessionletsession=tryawait service.realtimeSession( model:"gpt-4o-mini-realtime-preview-2024-12-17", configuration: configuration)// 3. Initialize audio controller for recording and playbackletaudioController=tryawaitAudioController(modes:[.record,.playback])// 4. Handle incoming messages from OpenAITask{forawaitmessagein session.receiver{switch message{case.responseAudioDelta(let audio): // Play audio from the model audioController.playPCM16Audio(base64String: audio)case.inputAudioBufferSpeechStarted: // User started speaking - interrupt model's audio audioController.interruptPlayback()case.responseTranscriptDelta(let text): // Display partial model transcriptprint("Model (partial):\(text)")case.responseTranscriptDone(let text): // Display complete model transcriptprint("Model:\(text)")case.inputAudioTranscriptionCompleted(let text): // Display user's transcribed speechprint("User:\(text)")case.responseFunctionCallArgumentsDone(let name,let args,let callId): // Handle function call from modelprint("Function call:\(name) with args:\(args)") // Execute function and send result backcase.error(let error):print("Error:\(error??"Unknown error")")default:break}}}// 5. Stream microphone audio to OpenAITask{do{fortryawaitbufferin audioController.micStream(){ // Encode audio buffer to base64guardlet base64Audio=AudioUtils.base64EncodeAudioPCMBuffer(from: buffer)else{continue} // Send audio to OpenAItryawait session.sendMessage(OpenAIRealtimeInputAudioBufferAppend(audio: base64Audio))}}catch{print("Microphone error:\(error)")}}// 6. Manually trigger a response (optional - usually VAD handles this)tryawait session.sendMessage(OpenAIRealtimeResponseCreate())// 7. Update session configuration mid-conversation (optional)letnewConfig=OpenAIRealtimeSessionConfiguration( voice:"shimmer", temperature:0.9)tryawait session.sendMessage(OpenAIRealtimeSessionUpdate(sessionConfig: newConfig))// 8. Cleanup when doneaudioController.stop()session.disconnect()
Function Calling
// Define tools in configurationlettools:[OpenAIRealtimeSessionConfiguration.Tool]=[.init( name:"get_weather", description:"Get the current weather in a location", parameters:["type":"object","properties":["location":["type":"string","description":"City name, e.g. San Francisco"]],"required":["location"]])]letconfig=OpenAIRealtimeSessionConfiguration( voice:"alloy", tools: tools, toolChoice:.auto)// Handle function calls in message receivercase.responseFunctionCallArgumentsDone(let name, let args, let callId):if name=="get_weather"{ // Parse arguments and execute functionletresult=getWeather(arguments: args) // Send result back to modeltryawait session.sendMessage(OpenAIRealtimeConversationItemCreate( item:.functionCallOutput( callId: callId, output: result)))}
Advanced Features
- Voice Activity Detection (VAD): Choose between server-based VAD (with configurable timing) or semantic VAD (with eagerness levels)
- Transcription: Enable Whisper transcription for both user input and model output
- Session Updates: Change voice, instructions, or tools mid-conversation without reconnecting
- Response Triggers: Manually trigger model responses or rely on automatic VAD
- Platform-Specific Behavior: Automatically selects optimal audio API based on platform and headphone connection
For a complete implementation example, seeExamples/RealtimeExample/RealtimeExample.swift in the repository.
Parameters
publicstructChatCompletionParameters:Encodable{ /// A list of messages comprising the conversation so far. [Example Python code](https://cookbook.openai.com/examples/how_to_format_inputs_to_chatgpt_models)publicvarmessages:[Message] /// ID of the model to use. See the [model endpoint compatibility](https://platform.openai.com/docs/models/how-we-use-your-data) table for details on which models work with the Chat API. /// Supports GPT-4, GPT-4o, GPT-5, and other models. For GPT-5 family: .gpt5, .gpt5Mini, .gpt5Nanopublicvarmodel:String /// Whether or not to store the output of this chat completion request for use in our [model distillation](https://platform.openai.com/docs/guides/distillation) or [evals](https://platform.openai.com/docs/guides/evals) products. /// Defaults to falsepublicvarstore:Bool? /// Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. Defaults to 0 /// [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/gpt/parameter-details)publicvarfrequencyPenalty:Double? /// Controls how the model responds to function calls. none means the model does not call a function, and responds to the end-user. auto means the model can pick between an end-user or calling a function. Specifying a particular function via {"name": "my_function"} forces the model to call that function. none is the default when no functions are present. auto is the default if functions are present.@available(*, deprecated, message:"Deprecated in favor of tool_choice.")publicvarfunctionCall:FunctionCall? /// Controls which (if any) function is called by the model. none means the model will not call a function and instead generates a message. /// auto means the model can pick between generating a message or calling a function. Specifying a particular function via `{"type: "function", "function": {"name": "my_function"}}` forces the model to call that function. /// `none` is the default when no functions are present. auto is the default if functions are present.publicvartoolChoice:ToolChoice? /// A list of functions the model may generate JSON inputs for.@available(*, deprecated, message:"Deprecated in favor of tools.")publicvarfunctions:[ChatFunction]? /// A list of tools the model may call. Currently, only functions are supported as a tool. Use this to provide a list of functions the model may generate JSON inputs for.publicvartools:[Tool]? /// Whether to enable parallel function calling during tool use. Defaults to true.publicvarparallelToolCalls:Bool? /// Modify the likelihood of specified tokens appearing in the completion. /// Accepts a json object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. Defaults to null.publicvarlogitBias:[Int:Double]? /// Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the content of message. This option is currently not available on the gpt-4-vision-preview model. Defaults to false.publicvarlogprobs:Bool? /// An integer between 0 and 5 specifying the number of most likely tokens to return at each token position, each with an associated log probability. logprobs must be set to true if this parameter is used.publicvartopLogprobs:Int? /// The maximum number of [tokens](https://platform.openai.com/tokenizer) that can be generated in the chat completion. This value can be used to control [costs](https://openai.com/api/pricing/) for text generated via API. /// This value is now deprecated in favor of max_completion_tokens, and is not compatible with [o1 series models](https://platform.openai.com/docs/guides/reasoning)publicvarmaxTokens:Int? /// An upper bound for the number of tokens that can be generated for a completion, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning)publicvarmaCompletionTokens:Int? /// How many chat completion choices to generate for each input message. Defaults to 1.publicvarn:Int? /// Output types that you would like the model to generate for this request. Most models are capable of generating text, which is the default: /// ["text"] ///The gpt-4o-audio-preview model can also be used to [generate audio](https://platform.openai.com/docs/guides/audio). To request that this model generate both text and audio responses, you can use: /// ["text", "audio"]publicvarmodalities:[String]? /// Parameters for audio output. Required when audio output is requested with modalities: ["audio"]. [Learn more.](https://platform.openai.com/docs/guides/audio)publicvaraudio:Audio? /// Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. Defaults to 0 /// [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/gpt/parameter-details)publicvarpresencePenalty:Double? /// An object specifying the format that the model must output. Used to enable JSON mode. /// Setting to `{ type: "json_object" }` enables `JSON` mode, which guarantees the message the model generates is valid JSON. ///Important: when using `JSON` mode you must still instruct the model to produce `JSON` yourself via some conversation message, for example via your system message. If you don't do this, the model may generate an unending stream of whitespace until the generation reaches the token limit, which may take a lot of time and give the appearance of a "stuck" request. Also note that the message content may be partial (i.e. cut off) if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length.publicvarresponseFormat:ResponseFormat? /// Specifies the latency tier to use for processing the request. This parameter is relevant for customers subscribed to the scale tier service: /// If set to 'auto', the system will utilize scale tier credits until they are exhausted. /// If set to 'default', the request will be processed in the shared cluster. /// When this parameter is set, the response body will include the service_tier utilized.publicvarserviceTier:String? /// This feature is in `Beta`. If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. /// Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend.publicvarseed:Int? /// Up to 4 sequences where the API will stop generating further tokens. Defaults to null.publicvarstop:[String]? /// If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#event_stream_format) as they become available, with the stream terminated by a data: [DONE] message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions ). /// Defaults to false.varstream:Bool?=nil /// Options for streaming response. Only set this when you set stream: truevarstreamOptions:StreamOptions? /// What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. /// We generally recommend altering this or `top_p` but not both. Defaults to 1.publicvartemperature:Double? /// An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. /// We generally recommend altering this or `temperature` but not both. Defaults to 1publicvartopP:Double? /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. /// [Learn more](https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids).publicvaruser:String?publicstructMessage:Encodable{ /// The role of the messages author. One of system, user, assistant, or tool message.letrole:String /// The contents of the message. content is required for all messages, and may be null for assistant messages with function calls.letcontent:ContentType /// The name of the author of this message. name is required if role is function, and it should be the name of the function whose response is in the content. May contain a-z, A-Z, 0-9, and underscores, with a maximum length of 64 characters.letname:String? /// The name and arguments of a function that should be called, as generated by the model.@available(*, deprecated, message:"Deprecated and replaced by `tool_calls`")letfunctionCall:FunctionCall? /// The tool calls generated by the model, such as function calls.lettoolCalls:[ToolCall]? /// Tool call that this message is responding to.lettoolCallID:String?publicenumContentType:Encodable{case text(String)case contentArray([MessageContent])publicfunc encode(to encoder:Encoder)throws{varcontainer= encoder.singleValueContainer()switchself{case.text(let text):try container.encode(text)case.contentArray(let contentArray):try container.encode(contentArray)}}publicenumMessageContent:Encodable,Equatable,Hashable{case text(String)case imageUrl(ImageDetail)publicstructImageDetail:Encodable,Equatable,Hashable{publicleturl:URLpublicletdetail:String?enumCodingKeys:String,CodingKey{case urlcase detail}publicfunc encode(to encoder:Encoder)throws{varcontainer= encoder.container(keyedBy:CodingKeys.self)try container.encode(url, forKey:.url)try container.encode(detail, forKey:.detail)}publicinit(url:URL, detail:String?=nil){self.url= urlself.detail= detail}}enumCodingKeys:String,CodingKey{case typecase textcase imageUrl="image_url"}publicfunc encode(to encoder:Encoder)throws{varcontainer= encoder.container(keyedBy:CodingKeys.self)switchself{case.text(let text):try container.encode("text", forKey:.type)try container.encode(text, forKey:.text)case.imageUrl(let imageDetail):try container.encode("image_url", forKey:.type)try container.encode(imageDetail, forKey:.imageUrl)}}publicfunc hash(into hasher:inoutHasher){switchself{case.text(let string): hasher.combine(string)case.imageUrl(let imageDetail): hasher.combine(imageDetail)}}publicstaticfunc==(lhs:MessageContent, rhs:MessageContent)->Bool{switch(lhs, rhs){caselet(.text(a),.text(b)):return a== bcaselet(.imageUrl(a),.imageUrl(b)):return a== bdefault:returnfalse}}}}publicenumRole:String{case system // content, rolecase user // content, rolecase assistant // content, role, tool_callscase tool // content, role, tool_call_id}enumCodingKeys:String,CodingKey{case rolecase contentcase namecase functionCall="function_call"case toolCalls="tool_calls"case toolCallID="tool_call_id"}publicinit( role:Role, content:ContentType, name:String?=nil, functionCall:FunctionCall?=nil, toolCalls:[ToolCall]?=nil, toolCallID:String?=nil){self.role= role.rawValueself.content= contentself.name= nameself.functionCall= functionCallself.toolCalls= toolCallsself.toolCallID= toolCallID}}@available(*, deprecated, message:"Deprecated in favor of ToolChoice.")publicenumFunctionCall:Encodable,Equatable{case nonecase autocase function(String)enumCodingKeys:String,CodingKey{case none="none"case auto="auto"case function="name"}publicfunc encode(to encoder:Encoder)throws{switchself{case.none:varcontainer= encoder.singleValueContainer()try container.encode(CodingKeys.none.rawValue)case.auto:varcontainer= encoder.singleValueContainer()try container.encode(CodingKeys.auto.rawValue)case.function(let name):varcontainer= encoder.container(keyedBy:CodingKeys.self)try container.encode(name, forKey:.function)}}} /// [Documentation](https://platform.openai.com/docs/api-reference/chat/create#chat-create-tools)publicstructTool:Encodable{ /// The type of the tool. Currently, only `function` is supported.lettype:String /// objectletfunction:ChatFunctionpublicinit( type:String="function", function:ChatFunction){self.type= typeself.function= function}}publicstructChatFunction:Codable,Equatable{ /// The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64.letname:String /// A description of what the function does, used by the model to choose when and how to call the function.letdescription:String? /// The parameters the functions accepts, described as a JSON Schema object. See the [guide](https://platform.openai.com/docs/guides/gpt/function-calling) for examples, and the [JSON Schema reference](https://json-schema.org/understanding-json-schema) for documentation about the format. /// Omitting parameters defines a function with an empty parameter list.letparameters:JSONSchema? /// Defaults to false, Whether to enable strict schema adherence when generating the function call. If set to true, the model will follow the exact schema defined in the parameters field. Only a subset of JSON Schema is supported when strict is true. Learn more about Structured Outputs in the [function calling guide].(https://platform.openai.com/docs/api-reference/chat/docs/guides/function-calling)letstrict:Bool?publicinit( name:String, strict:Bool?, description:String?, parameters:JSONSchema?){self.name= nameself.strict= strictself.description= descriptionself.parameters= parameters}}publicenumServiceTier:String,Encodable{ /// Specifies the latency tier to use for processing the request. This parameter is relevant for customers subscribed to the scale tier service: /// If set to 'auto', the system will utilize scale tier credits until they are exhausted. /// If set to 'default', the request will be processed in the shared cluster. /// When this parameter is set, the response body will include the service_tier utilized.case autocase `default`}publicstructStreamOptions:Encodable{ /// If set, an additional chunk will be streamed before the data: [DONE] message. /// The usage field on this chunk shows the token usage statistics for the entire request, /// and the choices field will always be an empty array. All other chunks will also include /// a usage field, but with a null value.letincludeUsage:BoolenumCodingKeys:String,CodingKey{case includeUsage="include_usage"}} /// Parameters for audio output. Required when audio output is requested with modalities: ["audio"] /// [Learn more.](https://platform.openai.com/docs/guides/audio)publicstructAudio:Encodable{ /// Specifies the voice type. Supported voices are alloy, echo, fable, onyx, nova, and shimmer.publicletvoice:String /// Specifies the output audio format. Must be one of wav, mp3, flac, opus, or pcm16.publicletformat:Stringpublicinit( voice:String, format:String){self.voice= voiceself.format= format}}enumCodingKeys:String,CodingKey{case messagescase modelcase storecase frequencyPenalty="frequency_penalty"case toolChoice="tool_choice"case functionCall="function_call"case toolscase parallelToolCalls="parallel_tool_calls"case functionscase logitBias="logit_bias"case logprobscase topLogprobs="top_logprobs"case maxTokens="max_tokens"case maCompletionTokens="max_completion_tokens"case ncase modalitiescase audiocase responseFormat="response_format"case presencePenalty="presence_penalty"case seedcase serviceTier="service_tier"case stopcase streamcase streamOptions="stream_options"case temperaturecase topP="top_p"case user}publicinit( messages:[Message], model:Model, store:Bool?=nil, frequencyPenalty:Double?=nil, functionCall:FunctionCall?=nil, toolChoice:ToolChoice?=nil, functions:[ChatFunction]?=nil, tools:[Tool]?=nil, parallelToolCalls:Bool?=nil, logitBias:[Int:Double]?=nil, logProbs:Bool?=nil, topLogprobs:Int?=nil, maxTokens:Int?=nil, n:Int?=nil, modalities:[String]?=nil, audio:Audio?=nil, responseFormat:ResponseFormat?=nil, presencePenalty:Double?=nil, serviceTier:ServiceTier?=nil, seed:Int?=nil, stop:[String]?=nil, temperature:Double?=nil, topProbability:Double?=nil, user:String?=nil){self.messages= messagesself.model= model.valueself.store= storeself.frequencyPenalty= frequencyPenaltyself.functionCall= functionCallself.toolChoice= toolChoiceself.functions= functionsself.tools= toolsself.parallelToolCalls= parallelToolCallsself.logitBias= logitBiasself.logprobs= logProbsself.topLogprobs= topLogprobsself.maxTokens= maxTokensself.n= nself.modalities= modalitiesself.audio= audioself.responseFormat= responseFormatself.presencePenalty= presencePenaltyself.serviceTier= serviceTier?.rawValueself.seed= seedself.stop= stopself.temperature= temperatureself.topP= topProbabilityself.user= user}}
Response
/// Represents a chat [completion](https://platform.openai.com/docs/api-reference/chat/object) response returned by model, based on the provided input.publicstructChatCompletionObject:Decodable{ /// A unique identifier for the chat completion.publicletid:String /// A list of chat completion choices. Can be more than one if n is greater than 1.publicletchoices:[ChatChoice] /// The Unix timestamp (in seconds) of when the chat completion was created.publicletcreated:Int /// The model used for the chat completion.publicletmodel:String /// The service tier used for processing the request. This field is only included if the service_tier parameter is specified in the request.publicletserviceTier:String? /// This fingerprint represents the backend configuration that the model runs with. /// Can be used in conjunction with the seed request parameter to understand when backend changes have been made that might impact determinism.publicletsystemFingerprint:String? /// The object type, which is always chat.completion.publicletobject:String /// Usage statistics for the completion request.publicletusage:ChatUsagepublicstructChatChoice:Decodable{ /// The reason the model stopped generating tokens. This will be stop if the model hit a natural stop point or a provided stop sequence, length if the maximum number of tokens specified in the request was reached, content_filter if content was omitted due to a flag from our content filters, tool_calls if the model called a tool, or function_call (deprecated) if the model called a function.publicletfinishReason:IntOrStringValue? /// The index of the choice in the list of choices.publicletindex:Int /// A chat completion message generated by the model.publicletmessage:ChatMessage /// Log probability information for the choice.publicletlogprobs:LogProb?publicstructChatMessage:Decodable{ /// The contents of the message.publicletcontent:String? /// The tool calls generated by the model, such as function calls.publiclettoolCalls:[ToolCall]? /// The name and arguments of a function that should be called, as generated by the model.@available(*, deprecated, message:"Deprecated and replaced by `tool_calls`")publicletfunctionCall:FunctionCall? /// The role of the author of this message.publicletrole:String /// Provided by the Vision API.publicletfinishDetails:FinishDetails? /// The refusal message generated by the model.publicletrefusal:String? /// If the audio output modality is requested, this object contains data about the audio response from the model. [Learn more](https://platform.openai.com/docs/guides/audio).publicletaudio:Audio? /// Provided by the Vision API.publicstructFinishDetails:Decodable{lettype:String}publicstructAudio:Decodable{ /// Unique identifier for this audio response.publicletid:String /// The Unix timestamp (in seconds) for when this audio response will no longer be accessible on the server for use in multi-turn conversations.publicletexpiresAt:Int /// Base64 encoded audio bytes generated by the model, in the format specified in the request.publicletdata:String /// Transcript of the audio generated by the model.publiclettranscript:StringenumCodingKeys:String,CodingKey{case idcase expiresAt="expires_at"case datacase transcript}}}publicstructLogProb:Decodable{ /// A list of message content tokens with log probability information.letcontent:[TokenDetail]}publicstructTokenDetail:Decodable{ /// The token.lettoken:String /// The log probability of this token.letlogprob:Double /// A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and their byte representations must be combined to generate the correct text representation. Can be null if there is no bytes representation for the token.letbytes:[Int]? /// List of the most likely tokens and their log probability, at this token position. In rare cases, there may be fewer than the number of requested top_logprobs returned.lettopLogprobs:[TopLogProb]enumCodingKeys:String,CodingKey{case token, logprob, bytescase topLogprobs="top_logprobs"}structTopLogProb:Decodable{ /// The token.lettoken:String /// The log probability of this token.letlogprob:Double /// A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and their byte representations must be combined to generate the correct text representation. Can be null if there is no bytes representation for the token.letbytes:[Int]?}}}publicstructChatUsage:Decodable{ /// Number of tokens in the generated completion.publicletcompletionTokens:Int /// Number of tokens in the prompt.publicletpromptTokens:Int /// Total number of tokens used in the request (prompt + completion).publiclettotalTokens:Int}}
Usage
letprompt="Tell me a joke"letparameters=ChatCompletionParameters(messages:[.init(role:.user, content:.text(prompt))], model:.gpt4o)letchatCompletionObject= service.startChat(parameters: parameters)
Response
/// Represents a [streamed](https://platform.openai.com/docs/api-reference/chat/streaming) chunk of a chat completion response returned by model, based on the provided input.publicstructChatCompletionChunkObject:Decodable{ /// A unique identifier for the chat completion chunk.publicletid:String /// A list of chat completion choices. Can be more than one if n is greater than 1.publicletchoices:[ChatChoice] /// The Unix timestamp (in seconds) of when the chat completion chunk was created.publicletcreated:Int /// The model to generate the completion.publicletmodel:String /// The service tier used for processing the request. This field is only included if the service_tier parameter is specified in the request.publicletserviceTier:String? /// This fingerprint represents the backend configuration that the model runs with. /// Can be used in conjunction with the seed request parameter to understand when backend changes have been made that might impact determinism.publicletsystemFingerprint:String? /// The object type, which is always chat.completion.chunk.publicletobject:StringpublicstructChatChoice:Decodable{ /// A chat completion delta generated by streamed model responses.publicletdelta:Delta /// The reason the model stopped generating tokens. This will be stop if the model hit a natural stop point or a provided stop sequence, length if the maximum number of tokens specified in the request was reached, content_filter if content was omitted due to a flag from our content filters, tool_calls if the model called a tool, or function_call (deprecated) if the model called a function.publicletfinishReason:IntOrStringValue? /// The index of the choice in the list of choices.publicletindex:Int /// Provided by the Vision API.publicletfinishDetails:FinishDetails?publicstructDelta:Decodable{ /// The contents of the chunk message.publicletcontent:String? /// The tool calls generated by the model, such as function calls.publiclettoolCalls:[ToolCall]? /// The name and arguments of a function that should be called, as generated by the model.@available(*, deprecated, message:"Deprecated and replaced by `tool_calls`")publicletfunctionCall:FunctionCall? /// The role of the author of this message.publicletrole:String?}publicstructLogProb:Decodable{ /// A list of message content tokens with log probability information.letcontent:[TokenDetail]}publicstructTokenDetail:Decodable{ /// The token.lettoken:String /// The log probability of this token.letlogprob:Double /// A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and their byte representations must be combined to generate the correct text representation. Can be null if there is no bytes representation for the token.letbytes:[Int]? /// List of the most likely tokens and their log probability, at this token position. In rare cases, there may be fewer than the number of requested top_logprobs returned.lettopLogprobs:[TopLogProb]enumCodingKeys:String,CodingKey{case token, logprob, bytescase topLogprobs="top_logprobs"}structTopLogProb:Decodable{ /// The token.lettoken:String /// The log probability of this token.letlogprob:Double /// A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and their byte representations must be combined to generate the correct text representation. Can be null if there is no bytes representation for the token.letbytes:[Int]?}} /// Provided by the Vision API.publicstructFinishDetails:Decodable{lettype:String}}}
Usage
letprompt="Tell me a joke"letparameters=ChatCompletionParameters(messages:[.init(role:.user, content:.text(prompt))], model:.gpt4o)letchatCompletionObject=tryawait service.startStreamedChat(parameters: parameters)
Chat Completion also supportsFunction Calling andParallel Function Calling.functions has been deprecated in favor oftools checkOpenAI Documentation for more.
publicstructToolCall:Codable{publicletindex:Int /// The ID of the tool call.publicletid:String? /// The type of the tool. Currently, only `function` is supported.publiclettype:String? /// The function that the model called.publicletfunction:FunctionCallpublicinit( index:Int, id:String, type:String="function", function:FunctionCall){self.index= indexself.id= idself.type= typeself.function= function}}publicstructFunctionCall:Codable{ /// The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function.letarguments:String /// The name of the function to call.letname:Stringpublicinit( arguments:String, name:String){self.arguments= argumentsself.name= name}}
Usage
/// Define a `ToolCall`vartool:ToolCall{.init( type:"function", // The type of the tool. Currently, only "function" is supported. function:.init( name:"create_image", description:"Call this function if the request asks to generate an image", parameters:.init( type:.object, properties:["prompt":.init(type:.string, description:"The exact prompt passed in."),"count":.init(type:.integer, description:"The number of images requested")], required:["prompt","count"])))}letprompt="Show me an image of an unicorn eating ice cream"letcontent:ChatCompletionParameters.Message.ContentType=.text(prompt)letparameters=ChatCompletionParameters(messages:[.init(role:.user, content: content)], model:.gpt41106Preview, tools:[tool])letchatCompletionObject=tryawait service.startStreamedChat(parameters: parameters)
For more details about how to also uploading base 64 encoded images in iOS check theChatFunctionsCalllDemo demo on the Examples section of this package.
Must knowns:
All fields must be required , To use Structured Outputs, all fields or function parameters must be specified as required.
Although all fields must be required (and the model will return a value for each parameter), it is possible to emulate an optional parameter by using a union type with null.
Objects have limitations on nesting depth and size, A schema may have up to 100 object properties total, with up to 5 levels of nesting.
additionalProperties): false must always be set in objectsadditionalProperties controls whether it is allowable for an object to contain additional keys / values that were not defined in the JSON Schema.Structured Outputs only supports generating specified keys / values, so we require developers to set additionalProperties: false to opt into Structured Outputs.
Key ordering, When using Structured Outputs, outputs will be produced in the same order as the ordering of keys in the schema.
- Function calling: Structured Outputs via tools is available by setting strict: true within your function definition. This feature works with all models that support tools, including all models gpt-4-0613 and gpt-3.5-turbo-0613 and later. When Structured Outputs are enabled, model outputs will match the supplied tool definition.
Using this schema:
{"schema": {"type":"object","properties": {"steps": {"type":"array","items": {"type":"object","properties": {"explanation": {"type":"string" },"output": {"type":"string" } },"required": ["explanation","output"],"additionalProperties":false } },"final_answer": {"type":"string" } },"required": ["steps","final_answer"],"additionalProperties":false }}You can use the convenientJSONSchema object like this:
// 1: Define the Step schema objectletstepSchema=JSONSchema( type:.object, properties:["explanation":JSONSchema(type:.string),"output":JSONSchema( type:.string)], required:["explanation","output"], additionalProperties:false)// 2. Define the steps Array schema.letstepsArraySchema=JSONSchema(type:.array, items: stepSchema)// 3. Define the final Answer schema.letfinalAnswerSchema=JSONSchema(type:.string)// 4. Define math reponse JSON schema.letmathResponseSchema=JSONSchema( type:.object, properties:["steps": stepsArraySchema,"final_answer": finalAnswerSchema], required:["steps","final_answer"], additionalProperties:false)lettool=ChatCompletionParameters.Tool( function:.init( name:"math_response", strict:true, parameters: mathResponseSchema)))letprompt="solve 8x + 31 = 2"letsystemMessage=ChatCompletionParameters.Message(role:.system, content:.text("You are a math tutor"))letuserMessage=ChatCompletionParameters.Message(role:.user, content:.text(prompt))letparameters=ChatCompletionParameters( messages:[systemMessage, userMessage], model:.gpt4o20240806, tools:[tool])letchat=tryawait service.startChat(parameters: parameters)
- A new option for the
response_formatparameter: developers can now supply a JSON Schema viajson_schema, a new option for the response_format parameter. This is useful when the model is not calling a tool, but rather, responding to the user in a structured way. This feature works with our newest GPT-4o models:gpt-4o-2024-08-06, released today, andgpt-4o-mini-2024-07-18. When a response_format is supplied with strict: true, model outputs will match the supplied schema.
Using the previous schema, this is how you can implement it as json schema using the convenientJSONSchemaResponseFormat object:
// 1: Define the Step schema objectletstepSchema=JSONSchema( type:.object, properties:["explanation":JSONSchema(type:.string),"output":JSONSchema( type:.string)], required:["explanation","output"], additionalProperties:false)// 2. Define the steps Array schema.letstepsArraySchema=JSONSchema(type:.array, items: stepSchema)// 3. Define the final Answer schema.letfinalAnswerSchema=JSONSchema(type:.string)// 4. Define the response format JSON schema.letresponseFormatSchema=JSONSchemaResponseFormat( name:"math_response", strict:true, schema:JSONSchema( type:.object, properties:["steps": stepsArraySchema,"final_answer": finalAnswerSchema], required:["steps","final_answer"], additionalProperties:false))letprompt="solve 8x + 31 = 2"letsystemMessage=ChatCompletionParameters.Message(role:.system, content:.text("You are a math tutor"))letuserMessage=ChatCompletionParameters.Message(role:.user, content:.text(prompt))letparameters=ChatCompletionParameters( messages:[systemMessage, userMessage], model:.gpt4o20240806, responseFormat:.jsonSchema(responseFormatSchema))
SwiftOpenAI Structred outputs supports:
- Tools Structured output.
- Response format Structure output.
- Recursive Schema.
- Optional values Schema.
- Pydantic models.
We don't support Pydantic models, users need tos manually create Schemas usingJSONSchema orJSONSchemaResponseFormat objects.
Pro tip 🔥 UseiosAICodeAssistant GPT to construct SwifOpenAI schemas. Just paste your JSON schema and ask the GPT to create SwiftOpenAI schemas for tools and response format.
For more details visit the Demo project fortools andresponse format.
Vision API is available for use; developers must access it through the chat completions API, specifically using the gpt-4-vision-preview model or gpt-4o model. Using any other model will not provide an image description
Usage
letimageURL="https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"letprompt="What is this?"letmessageContent:[ChatCompletionParameters.Message.ContentType.MessageContent]=[.text(prompt),.imageUrl(.init(url: imageURL)] // Users can add as many `.imageUrl` instances to the service.letparameters=ChatCompletionParameters(messages:[.init(role:.user, content:.contentArray(messageContent))], model:.gpt4o)letchatCompletionObject=tryawait service.startStreamedChat(parameters: parameters)
For more details about how to also uploading base 64 encoded images in iOS check theChatVision demo on the Examples section of this package.
OpenAI's most advanced interface for generating model responses. Supports text and image inputs, and text outputs. Create stateful interactions with the model, using the output of previous responses as input. Extend the model's capabilities with built-in tools for file search, web search, computer use, and more. Allow the model access to external systems and data using function calling.
- Full streaming support with
responseCreateStreammethod - Comprehensive
ResponseStreamEventenum covering 40+ event types - Enhanced
InputMessagewithidfield for response ID tracking - Improved conversation state management with
previousResponseId - Real-time text streaming, function calls, and tool usage events
- Support for reasoning summaries, web search, file search, and image generation events
- NEW: Support for GPT-5 models (gpt-5, gpt-5-mini, gpt-5-nano)
- NEW: Verbosity parameter for controlling response detail level
TheModelResponseParameter provides a comprehensive interface for creating model responses:
letparameters=ModelResponseParameter( input:.text("What is the answer to life, the universe, and everything?"), model:.gpt5, // Support for GPT-5, GPT-5-mini, GPT-5-nano text:TextConfiguration( format:.text, verbosity:"low" // NEW: Control response verbosity ("low", "medium", "high")), temperature:0.7)letresponse=tryawait service.responseCreate(parameters)
publicenumModel{case gpt5 // Complex reasoning, broad world knowledge, and code-heavy or multi-step agentic taskscase gpt5Mini // Cost-optimized reasoning and chat; balances speed, cost, and capabilitycase gpt5Nano // High-throughput tasks, especially simple instruction-following or classification // ... other models}
// Create a text configuration with verbosity controllettextConfig=TextConfiguration( format:.text, // Can be .text, .jsonObject, or .jsonSchema verbosity:"medium" // Controls response detail level)
Related guides:
- Quickstart
- Text inputs and outputs
- Image inputs
- Structured Outputs
- Function calling
- Conversation state
- Extend the models with tools
Parameters
/// [Creates a model response.](https://platform.openai.com/docs/api-reference/responses/create)publicstructModelResponseParameter:Codable{ /// Text, image, or file inputs to the model, used to generate a response. /// A text input to the model, equivalent to a text input with the user role. /// A list of one or many input items to the model, containing different content types.publicvarinput:InputType /// Model ID used to generate the response, like gpt-4o or o1. OpenAI offers a wide range of models with /// different capabilities, performance characteristics, and price points. /// Refer to the model guide to browse and compare available models.publicvarmodel:String /// Specify additional output data to include in the model response. Currently supported values are: /// file_search_call.results : Include the search results of the file search tool call. /// message.input_image.image_url : Include image urls from the input message. /// computer_call_output.output.image_url : Include image urls from the computer call output.publicvarinclude:[String]? /// Inserts a system (or developer) message as the first item in the model's context. /// When using along with previous_response_id, the instructions from a previous response will be not be /// carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses.publicvarinstructions:String? /// An upper bound for the number of tokens that can be generated for a response, including visible output tokens /// and reasoning tokens.publicvarmaxOutputTokens:Int? /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information /// about the object in a structured format, and querying for objects via API or the dashboard. /// Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters.publicvarmetadata:[String:String]? /// Whether to allow the model to run tool calls in parallel. /// Defaults to truepublicvarparallelToolCalls:Bool? /// The unique ID of the previous response to the model. Use this to create multi-turn conversations. /// Learn more about conversation state.publicvarpreviousResponseId:String? /// o-series models only /// Configuration options for reasoning models.publicvarreasoning:Reasoning? /// Whether to store the generated model response for later retrieval via API. /// Defaults to truepublicvarstore:Bool? /// If set to true, the model response data will be streamed to the client as it is generated using server-sent events.publicvarstream:Bool? /// What sampling temperature to use, between 0 and 2. /// Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. /// We generally recommend altering this or top_p but not both. /// Defaults to 1publicvartemperature:Double? /// Configuration options for a text response from the model. Can be plain text or structured JSON data.publicvartext:TextConfiguration? /// How the model should select which tool (or tools) to use when generating a response. /// See the tools parameter to see how to specify which tools the model can call.publicvartoolChoice:ToolChoiceMode? /// An array of tools the model may call while generating a response. You can specify which tool to use by setting the tool_choice parameter.publicvartools:[Tool]? /// An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. /// So 0.1 means only the tokens comprising the top 10% probability mass are considered. /// We generally recommend altering this or temperature but not both. /// Defaults to 1publicvartopP:Double? /// The truncation strategy to use for the model response. /// Defaults to disabledpublicvartruncation:String? /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse.publicvaruser:String?}
/// The Response object returned when retrieving a model responsepublicstructResponseModel:Decodable{ /// Unix timestamp (in seconds) of when this Response was created.publicletcreatedAt:Int /// An error object returned when the model fails to generate a Response.publicleterror:ErrorObject? /// Unique identifier for this Response.publicletid:String /// Details about why the response is incomplete.publicletincompleteDetails:IncompleteDetails? /// Inserts a system (or developer) message as the first item in the model's context.publicletinstructions:String? /// An upper bound for the number of tokens that can be generated for a response, including visible output tokens /// and reasoning tokens.publicletmaxOutputTokens:Int? /// Set of 16 key-value pairs that can be attached to an object.publicletmetadata:[String:String] /// Model ID used to generate the response, like gpt-4o or o1.publicletmodel:String /// The object type of this resource - always set to response.publicletobject:String /// An array of content items generated by the model.publicletoutput:[OutputItem] /// Whether to allow the model to run tool calls in parallel.publicletparallelToolCalls:Bool /// The unique ID of the previous response to the model. Use this to create multi-turn conversations.publicletpreviousResponseId:String? /// Configuration options for reasoning models.publicletreasoning:Reasoning? /// The status of the response generation. One of completed, failed, in_progress, or incomplete.publicletstatus:String /// What sampling temperature to use, between 0 and 2.publiclettemperature:Double? /// Configuration options for a text response from the model.publiclettext:TextConfiguration /// How the model should select which tool (or tools) to use when generating a response.publiclettoolChoice:ToolChoiceMode /// An array of tools the model may call while generating a response.publiclettools:[Tool] /// An alternative to sampling with temperature, called nucleus sampling.publiclettopP:Double? /// The truncation strategy to use for the model response.publiclettruncation:String? /// Represents token usage details.publicletusage:Usage? /// A unique identifier representing your end-user.publicletuser:String? /// Convenience property that aggregates all text output from output_text items in the output array. /// Similar to the outputText property in Python and JavaScript SDKs.publicvaroutputText:String?}
Input Types
// InputType represents the input to the Response APIpublicenumInputType:Codable{case string(String) // Simple text inputcase array([InputItem]) // Array of input items for complex conversations}// InputItem represents different types of inputpublicenumInputItem:Codable{case message(InputMessage) // User, assistant, system messagescase functionToolCall(FunctionToolCall) // Function callscase functionToolCallOutput(FunctionToolCallOutput) // Function outputs // ... other input types}// InputMessage structure with support for response IDspublicstructInputMessage:Codable{publicletrole:String // "user", "assistant", "system"publicletcontent:MessageContentpubliclettype:String? // Always "message"publicletstatus:String? // "completed" for assistant messagespublicletid:String? // Response ID for assistant messages}// MessageContent can be text or array of content itemspublicenumMessageContent:Codable{case text(String)case array([ContentItem]) // For multimodal content}
Usage
Simple text input
letprompt="What is the capital of France?"letparameters=ModelResponseParameter(input:.string(prompt), model:.gpt4o)letresponse=tryawait service.responseCreate(parameters)
Text input with reasoning
letprompt="How much wood would a woodchuck chuck?"letparameters=ModelResponseParameter( input:.string(prompt), model:.o3Mini, reasoning:Reasoning(effort:"high"))letresponse=tryawait service.responseCreate(parameters)
Image input
lettextPrompt="What is in this image?"letimageUrl="https://example.com/path/to/image.jpg"letimageContent=ContentItem.imageUrl(ImageUrlContent(imageUrl: imageUrl))lettextContent=ContentItem.text(TextContent(text: textPrompt))letmessage=InputItem(role:"user", content:[textContent, imageContent])letparameters=ModelResponseParameter(input:.array([message]), model:.gpt4o)letresponse=tryawait service.responseCreate(parameters)
Using tools (web search)
letprompt="What was a positive news story from today?"letparameters=ModelResponseParameter( input:.string(prompt), model:.gpt4o, tools:[Tool(type:"web_search_preview", function:nil)])letresponse=tryawait service.responseCreate(parameters)
Using tools (file search)
letprompt="What are the key points in the document?"letparameters=ModelResponseParameter( input:.string(prompt), model:.gpt4o, tools:[Tool( type:"file_search", function:ChatCompletionParameters.ChatFunction( name:"file_search", strict:false, description:"Search through files", parameters:JSONSchema( type:.object, properties:["vector_store_ids":JSONSchema( type:.array, items:JSONSchema(type:.string)),"max_num_results":JSONSchema(type:.integer)], required:["vector_store_ids"], additionalProperties:false)))])letresponse=tryawait service.responseCreate(parameters)
Function calling
letprompt="What is the weather like in Boston today?"letparameters=ModelResponseParameter( input:.string(prompt), model:.gpt4o, tools:[Tool( type:"function", function:ChatCompletionParameters.ChatFunction( name:"get_current_weather", strict:false, description:"Get the current weather in a given location", parameters:JSONSchema( type:.object, properties:["location":JSONSchema( type:.string, description:"The city and state, e.g. San Francisco, CA"),"unit":JSONSchema( type:.string, enum:["celsius","fahrenheit"])], required:["location","unit"], additionalProperties:false)))], toolChoice:.auto)letresponse=tryawait service.responseCreate(parameters)
Retrieving a response
letresponseId="resp_abc123"letresponse=tryawait service.responseModel(id: responseId)
The Response API supports streaming responses using Server-Sent Events (SSE). This allows you to receive partial responses as they are generated, enabling real-time UI updates and better user experience.
Stream Events
// The ResponseStreamEvent enum represents all possible streaming eventspublicenumResponseStreamEvent:Decodable{case responseCreated(ResponseCreatedEvent)case responseInProgress(ResponseInProgressEvent)case responseCompleted(ResponseCompletedEvent)case responseFailed(ResponseFailedEvent)case outputItemAdded(OutputItemAddedEvent)case outputTextDelta(OutputTextDeltaEvent)case outputTextDone(OutputTextDoneEvent)case functionCallArgumentsDelta(FunctionCallArgumentsDeltaEvent)case reasoningSummaryTextDelta(ReasoningSummaryTextDeltaEvent)case error(ErrorEvent) // ... and many more event types}
Basic Streaming Example
// Enable streaming by setting stream: trueletparameters=ModelResponseParameter( input:.string("Tell me a story"), model:.gpt4o, stream:true)// Create a streamletstream=tryawait service.responseCreateStream(parameters)// Process events as they arrivefortryawaiteventin stream{switch event{case.outputTextDelta(let delta): // Append text chunk to your UIprint(delta.delta, terminator:"")case.responseCompleted(let completed): // Response is completeprint("\nResponse ID:\(completed.response.id)")case.error(let error): // Handle errorsprint("Error:\(error.message)")default: // Handle other events as neededbreak}}
Streaming with Conversation State
// Maintain conversation continuity with previousResponseIdvarpreviousResponseId:String?=nilvarmessages:[(role:String, content:String)]=[]// First messageletfirstParams=ModelResponseParameter( input:.string("Hello!"), model:.gpt4o, stream:true)letfirstStream=tryawait service.responseCreateStream(firstParams)varfirstResponse=""fortryawaiteventin firstStream{switch event{case.outputTextDelta(let delta): firstResponse+= delta.deltacase.responseCompleted(let completed): previousResponseId= completed.response.id messages.append((role:"user", content:"Hello!")) messages.append((role:"assistant", content: firstResponse))default:break}}// Follow-up message with conversation contextvarinputArray:[InputItem]=[]// Add conversation historyformessagein messages{ inputArray.append(.message(InputMessage( role: message.role, content:.text(message.content))))}// Add new user messageinputArray.append(.message(InputMessage( role:"user", content:.text("How are you?"))))letfollowUpParams=ModelResponseParameter( input:.array(inputArray), model:.gpt4o, previousResponseId: previousResponseId, stream:true)letfollowUpStream=tryawait service.responseCreateStream(followUpParams)// Process the follow-up stream...
Streaming with Tools and Function Calling
letparameters=ModelResponseParameter( input:.string("What's the weather in San Francisco?"), model:.gpt4o, tools:[Tool( type:"function", function:ChatCompletionParameters.ChatFunction( name:"get_weather", description:"Get current weather", parameters:JSONSchema( type:.object, properties:["location":JSONSchema(type:.string)], required:["location"])))], stream:true)letstream=tryawait service.responseCreateStream(parameters)varfunctionCallArguments=""fortryawaiteventin stream{switch event{case.functionCallArgumentsDelta(let delta): // Accumulate function call arguments functionCallArguments+= delta.deltacase.functionCallArgumentsDone(let done): // Function call is completeprint("Function:\(done.name)")print("Arguments:\(functionCallArguments)")case.outputTextDelta(let delta): // Regular text outputprint(delta.delta, terminator:"")default:break}}
Canceling a Stream
// Streams can be canceled using Swift's task cancellationletstreamTask=Task{letstream=tryawait service.responseCreateStream(parameters)fortryawaiteventin stream{ // Check if task is cancelledifTask.isCancelled{break} // Process events...}}// Cancel the stream when neededstreamTask.cancel()
Complete Streaming Implementation Example
@MainActor@ObservableclassResponseStreamProvider{varmessages:[Message]=[]varisStreaming=falsevarerror:String?privateletservice:OpenAIServiceprivatevarpreviousResponseId:String?privatevarstreamTask:Task<Void,Never>?init(service:OpenAIService){self.service= service}func sendMessage(_ text:String){ streamTask?.cancel() // Add user message messages.append(Message(role:.user, content: text)) // Start streaming streamTask=Task{awaitstreamResponse(for: text)}}privatefunc streamResponse(for userInput:String)async{ isStreaming=true error=nil // Create streaming message placeholderletstreamingMessage=Message(role:.assistant, content:"", isStreaming:true) messages.append(streamingMessage)do{ // Build conversation historyvarinputArray:[InputItem]=[]formessagein messages.dropLast(2){ inputArray.append(.message(InputMessage( role: message.role.rawValue, content:.text(message.content))))} inputArray.append(.message(InputMessage( role:"user", content:.text(userInput))))letparameters=ModelResponseParameter( input:.array(inputArray), model:.gpt4o, previousResponseId: previousResponseId, stream:true)letstream=tryawait service.responseCreateStream(parameters)varaccumulatedText=""fortryawaiteventin stream{guard !Task.isCancelledelse{break}switch event{case.outputTextDelta(let delta): accumulatedText+= delta.deltaupdateStreamingMessage(with: accumulatedText)case.responseCompleted(let completed): previousResponseId= completed.response.idfinalizeStreamingMessage(with: accumulatedText, responseId: completed.response.id)case.error(let errorEvent):throwAPIError.requestFailed(description: errorEvent.message)default:break}}}catch{self.error= error.localizedDescription messages.removeLast() // Remove streaming message on error} isStreaming=false}privatefunc updateStreamingMessage(with content:String){iflet index= messages.lastIndex(where:{ $0.isStreaming}){messages[index].content= content}}privatefunc finalizeStreamingMessage(with content:String, responseId:String){iflet index= messages.lastIndex(where:{ $0.isStreaming}){messages[index].content= contentmessages[index].isStreaming=falsemessages[index].responseId= responseId}}}
Parameters
/// [Creates](https://platform.openai.com/docs/api-reference/embeddings/create) an embedding vector representing the input text.publicstructEmbeddingParameter:Encodable{ /// ID of the model to use. You can use the List models API to see all of your available models, or see our [Model overview ](https://platform.openai.com/docs/models/overview) for descriptions of them.letmodel:String /// Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a single request, pass an array of strings or an array of token arrays. Each input must not exceed the max input tokens for the model (8191 tokens for text-embedding-ada-002) and cannot be an empty string. [How to Count Tokens with `tiktoken`](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken)letinput:String /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more.](https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids)letuser:String?publicenumModel:String{case textEmbeddingAda002="text-embedding-ada-002"}publicinit( model:Model=.textEmbeddingAda002, input:String, user:String?=nil){self.model= model.valueself.input= inputself.user= user}}
Response
/// [Represents an embedding vector returned by embedding endpoint.](https://platform.openai.com/docs/api-reference/embeddings/object)publicstructEmbeddingObject:Decodable{ /// The object type, which is always "embedding".publicletobject:String /// The embedding vector, which is a list of floats. The length of vector depends on the model as listed in the embedding guide.[https://platform.openai.com/docs/guides/embeddings]publicletembedding:[Float] /// The index of the embedding in the list of embeddings.publicletindex:Int}
Usage
letprompt="Hello world."letembeddingObjects=tryawait service.createEmbeddings(parameters: parameters).data
Parameters
/// [Creates a job](https://platform.openai.com/docs/api-reference/fine-tuning/create) that fine-tunes a specified model from a given dataset.///Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete.publicstructFineTuningJobParameters:Encodable{ /// The name of the model to fine-tune. You can select one of the [supported models](https://platform.openai.com/docs/models/overview).letmodel:String /// The ID of an uploaded file that contains training data. /// See [upload file](https://platform.openai.com/docs/api-reference/files/upload) for how to upload a file. /// Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with the purpose fine-tune. /// See the [fine-tuning guide](https://platform.openai.com/docs/guides/fine-tuning) for more details.lettrainingFile:String /// The hyperparameters used for the fine-tuning job.lethyperparameters:HyperParameters? /// A string of up to 18 characters that will be added to your fine-tuned model name. /// For example, a suffix of "custom-model-name" would produce a model name like ft:gpt-3.5-turbo:openai:custom-model-name:7p4lURel. /// Defaults to null.letsuffix:String? /// The ID of an uploaded file that contains validation data. /// If you provide this file, the data is used to generate validation metrics periodically during fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should not be present in both train and validation files. /// Your dataset must be formatted as a JSONL file. You must upload your file with the purpose fine-tune. /// See the [fine-tuning guide](https://platform.openai.com/docs/guides/fine-tuning) for more details.letvalidationFile:String? /// A list of integrations to enable for your fine-tuning job.letintegrations:[Integration]? /// The seed controls the reproducibility of the job. Passing in the same seed and job parameters should produce the same results, but may differ in rare cases. If a seed is not specified, one will be generated for you.letseed:Int? /// Fine-tuning is [currently available](https://platform.openai.com/docs/guides/fine-tuning/what-models-can-be-fine-tuned) for the following models: /// gpt-3.5-turbo-0613 (recommended) /// babbage-002 /// davinci-002 /// OpenAI expects gpt-3.5-turbo to be the right model for most users in terms of results and ease of use, unless you are migrating a legacy fine-tuned model.publicenumModel:String{case gpt35="gpt-3.5-turbo-0613" /// recommendedcase babbage002="babbage-002"case davinci002="davinci-002"}publicstructHyperParameters:Encodable{ /// The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. /// Defaults to auto.letnEpochs:Int?publicinit( nEpochs:Int?){self.nEpochs= nEpochs}}publicinit( model:Model, trainingFile:String, hyperparameters:HyperParameters?=nil, suffix:String?=nil, validationFile:String?=nil){self.model= model.rawValueself.trainingFile= trainingFileself.hyperparameters= hyperparametersself.suffix= suffixself.validationFile= validationFile}}
Response
/// The fine_tuning.job object represents a [fine-tuning job](https://platform.openai.com/docs/api-reference/fine-tuning/object) that has been created through the API.publicstructFineTuningJobObject:Decodable{ /// The object identifier, which can be referenced in the API endpoints.publicletid:String /// The Unix timestamp (in seconds) for when the fine-tuning job was created.publicletcreatedAt:Int /// For fine-tuning jobs that have failed, this will contain more information on the cause of the failure.publicleterror:OpenAIErrorResponse.Error? /// The name of the fine-tuned model that is being created. The value will be null if the fine-tuning job is still running.publicletfineTunedModel:String? /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be null if the fine-tuning job is still running.publicletfinishedAt:Int? /// The hyperparameters used for the fine-tuning job. See the [fine-tuning guide](https://platform.openai.com/docs/guides/fine-tuning) for more details.publiclethyperparameters:HyperParameters /// The base model that is being fine-tuned.publicletmodel:String /// The object type, which is always "fine_tuning.job".publicletobject:String /// The organization that owns the fine-tuning job.publicletorganizationId:String /// The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the [Files API](https://platform.openai.com/docs/api-reference/files/retrieve-contents).publicletresultFiles:[String] /// The current status of the fine-tuning job, which can be either `validating_files`, `queued`, `running`, `succeeded`, `failed`, or `cancelled`.publicletstatus:String /// The total number of billable tokens processed by this fine-tuning job. The value will be null if the fine-tuning job is still running.publiclettrainedTokens:Int? /// The file ID used for training. You can retrieve the training data with the [Files API](https://platform.openai.com/docs/api-reference/files/retrieve-contents).publiclettrainingFile:String /// The file ID used for validation. You can retrieve the validation results with the [Files API](https://platform.openai.com/docs/api-reference/files/retrieve-contents).publicletvalidationFile:String?publicenumStatus:String{case validatingFiles="validating_files"case queuedcase runningcase succeededcase failedcase cancelled}publicstructHyperParameters:Decodable{ /// The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. "auto" decides the optimal number of epochs based on the size of the dataset. If setting the number manually, we support any number between 1 and 50 epochs.publicletnEpochs:IntOrStringValue}}
UsageList fine-tuning jobs
letfineTuningJobs=tryawait service.istFineTuningJobs()
Create fine-tuning job
lettrainingFileID="file-Atc9okK0MOuQwQzDJCZXnrh6" // The id of the file that has been uploaded using the `Files` API. https://platform.openai.com/docs/api-reference/fine-tuning/create#fine-tuning/create-training_fileletparameters=FineTuningJobParameters(model:.gpt35, trainingFile: trainingFileID)letfineTuningJob=tryawait service.createFineTuningJob(parameters: parameters)
Retrieve fine-tuning job
letfineTuningJobID="ftjob-abc123"letfineTuningJob=tryawait service.retrieveFineTuningJob(id: fineTuningJobID)
Cancel fine-tuning job
letfineTuningJobID="ftjob-abc123"letcanceledFineTuningJob=tryawait service.cancelFineTuningJobWith(id: fineTuningJobID)
Response
/// [Fine-tuning job event object](https://platform.openai.com/docs/api-reference/fine-tuning/event-object)publicstructFineTuningJobEventObject:Decodable{publicletid:StringpublicletcreatedAt:Intpublicletlevel:Stringpublicletmessage:Stringpublicletobject:Stringpubliclettype:String?publicletdata:Data?publicstructData:Decodable{publicletstep:IntpubliclettrainLoss:DoublepubliclettrainMeanTokenAccuracy:Double}}
Usage
letfineTuningJobID="ftjob-abc123"letjobEvents=tryawait service.listFineTuningEventsForJobWith(id: id, after:nil, limit:nil).data
Parameters
publicstructBatchParameter:Encodable{ /// The ID of an uploaded file that contains requests for the new batch. /// See [upload file](https://platform.openai.com/docs/api-reference/files/create) for how to upload a file. /// Your input file must be formatted as a [JSONL file](https://platform.openai.com/docs/api-reference/batch/requestInput), and must be uploaded with the purpose batch.letinputFileID:String /// The endpoint to be used for all requests in the batch. Currently only /v1/chat/completions is supported.letendpoint:String /// The time frame within which the batch should be processed. Currently only 24h is supported.letcompletionWindow:String /// Optional custom metadata for the batch.letmetadata:[String:String]?enumCodingKeys:String,CodingKey{case inputFileID="input_file_id"case endpointcase completionWindow="completion_window"case metadata}}
Response
publicstructBatchObject:Decodable{letid:String /// The object type, which is always batch.letobject:String /// The OpenAI API endpoint used by the batch.letendpoint:Stringleterrors:Error /// The ID of the input file for the batch.letinputFileID:String /// The time frame within which the batch should be processed.letcompletionWindow:String /// The current status of the batch.letstatus:String /// The ID of the file containing the outputs of successfully executed requests.letoutputFileID:String /// The ID of the file containing the outputs of requests with errors.leterrorFileID:String /// The Unix timestamp (in seconds) for when the batch was created.letcreatedAt:Int /// The Unix timestamp (in seconds) for when the batch started processing.letinProgressAt:Int /// The Unix timestamp (in seconds) for when the batch will expire.letexpiresAt:Int /// The Unix timestamp (in seconds) for when the batch started finalizing.letfinalizingAt:Int /// The Unix timestamp (in seconds) for when the batch was completed.letcompletedAt:Int /// The Unix timestamp (in seconds) for when the batch failed.letfailedAt:Int /// The Unix timestamp (in seconds) for when the batch expired.letexpiredAt:Int /// The Unix timestamp (in seconds) for when the batch started cancelling.letcancellingAt:Int /// The Unix timestamp (in seconds) for when the batch was cancelled.letcancelledAt:Int /// The request counts for different statuses within the batch.letrequestCounts:RequestCount /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.letmetadata:[String:String]publicstructError:Decodable{letobject:Stringletdata:[Data]publicstructData:Decodable{ /// An error code identifying the error type.letcode:String /// A human-readable message providing more details about the error.letmessage:String /// The name of the parameter that caused the error, if applicable.letparam:String? /// The line number of the input file where the error occurred, if applicable.letline:Int?}}publicstructRequestCount:Decodable{ /// Total number of requests in the batch.lettotal:Int /// Number of requests that have been completed successfully.letcompleted:Int /// Number of requests that have failed.letfailed:Int}}
Usage
Create batch
letinputFileID="file-abc123"letendpoint="/v1/chat/completions"letcompletionWindow="24h"letparameter=BatchParameter(inputFileID: inputFileID, endpoint: endpoint, completionWindow: completionWindow, metadata:nil)letbatch=tryawait service.createBatch(parameters: parameters)
Retrieve batch
letbatchID="batch_abc123"letbatch=tryawait service.retrieveBatch(id: batchID)
Cancel batch
letbatchID="batch_abc123"letbatch=tryawait service.cancelBatch(id: batchID)
List batch
letbatches=tryawait service.listBatch(after:nil, limit:nil)
Parameters
/// [Upload a file](https://platform.openai.com/docs/api-reference/files/create) that can be used across various endpoints/features. Currently, the size of all the files uploaded by one organization can be up to 1 GB. Please contact us if you need to increase the storage limit.publicstructFileParameters:Encodable{ /// The name of the file asset is not documented in OpenAI's official documentation; however, it is essential for constructing the multipart request.letfileName:String /// The file object (not file name) to be uploaded. /// If the purpose is set to "fine-tune", the file will be used for fine-tuning.letfile:Data /// The intended purpose of the uploaded file. /// Use "fine-tune" for [fine-tuning](https://platform.openai.com/docs/api-reference/fine-tuning). This allows us to validate the format of the uploaded file is correct for fine-tuning.letpurpose:Stringpublicinit( fileName:String, file:Data, purpose:String){self.fileName= fileNameself.file= fileself.purpose= purpose}}
Response
/// The [File object](https://platform.openai.com/docs/api-reference/files/object) represents a document that has been uploaded to OpenAI.publicstructFileObject:Decodable{ /// The file identifier, which can be referenced in the API endpoints.publicletid:String /// The size of the file in bytes.publicletbytes:Int /// The Unix timestamp (in seconds) for when the file was created.publicletcreatedAt:Int /// The name of the file.publicletfilename:String /// The object type, which is always "file".publicletobject:String /// The intended purpose of the file. Currently, only "fine-tune" is supported.publicletpurpose:String /// The current status of the file, which can be either uploaded, processed, pending, error, deleting or deleted.publicletstatus:String /// Additional details about the status of the file. If the file is in the error state, this will include a message describing the error.publicletstatusDetails:String?publicenumStatus:String{case uploadedcase processedcase pendingcase errorcase deletingcase deleted}publicinit( id:String, bytes:Int, createdAt:Int, filename:String, object:String, purpose:String, status:Status, statusDetails:String?){self.id= idself.bytes= bytesself.createdAt= createdAtself.filename= filenameself.object= objectself.purpose= purposeself.status= status.rawValueself.statusDetails= statusDetails}}
UsageList files
letfiles=tryawait service.listFiles().data
letfileName="worldCupData.jsonl"letdata=Data(contentsOfURL:_) // Data retrieved from the file named "worldCupData.jsonl".letparameters=FileParameters(fileName:"WorldCupData", file: data, purpose:"fine-tune") // Important: make sure to provide a file name.letuploadedFile=tryawait service.uploadFile(parameters: parameters)
Delete file
letfileID="file-abc123"letdeletedStatus=tryawait service.deleteFileWith(id: fileID)
Retrieve file
letfileID="file-abc123"letretrievedFile=tryawait service.retrieveFileWith(id: fileID)
Retrieve file content
letfileID="file-abc123"letfileContent=tryawait service.retrieveContentForFileWith(id: fileID)
This library supports latest OpenAI Image generation
- Parameters Create
/// 'Create Image':/// https://platform.openai.com/docs/api-reference/images/createpublicstructCreateImageParameters:Encodable{ /// A text description of the desired image(s). /// The maximum length is 32000 characters for `gpt-image-1`, 1000 characters for `dall-e-2` and 4000 characters for `dall-e-3`.publicletprompt:String // MARK: - Optional properties /// Allows to set transparency for the background of the generated image(s). /// This parameter is only supported for `gpt-image-1`. /// Must be one of `transparent`, `opaque` or `auto` (default value). /// When `auto` is used, the model will automatically determine the best background for the image. /// If `transparent`, the output format needs to support transparency, so it should be set to either `png` (default value) or `webp`.publicletbackground:Background? /// The model to use for image generation. One of `dall-e-2`, `dall-e-3`, or `gpt-image-1`. /// Defaults to `dall-e-2` unless a parameter specific to `gpt-image-1` is used.publicletmodel:Model? /// Control the content-moderation level for images generated by `gpt-image-1`. /// Must be either low for less restrictive filtering or auto (default value).publicletmoderation:Moderation? /// The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is supported. /// Defaults to `1`publicletn:Int? /// The compression level (0-100%) for the generated images. /// This parameter is only supported for `gpt-image-1` with the `webp` or `jpeg` output formats, and defaults to 100.publicletoutputCompression:Int? /// The format in which the generated images are returned. /// This parameter is only supported for `gpt-image-1`. /// Must be one of `png`, `jpeg`, or `webp`.publicletoutputFormat:OutputFormat? /// The quality of the image that will be generated. /// - `auto` (default value) will automatically select the best quality for the given model. /// - `high`, `medium` and `low` are supported for gpt-image-1. /// - `hd` and `standard` are supported for dall-e-3. /// - `standard` is the only option for dall-e-2.publicletquality:Quality? /// The format in which generated images with dall-e-2 and dall-e-3 are returned. /// Must be one of `url` or `b64_json`. /// URLs are only valid for 60 minutes after the image has been generated. /// This parameter isn't supported for `gpt-image-1` which will always return base64-encoded images.publicletresponseFormat:ResponseFormat? /// The size of the generated images. /// - For gpt-image-1, one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) /// - For dall-e-3, one of `1024x1024`, `1792x1024`, or `1024x1792` /// - For dall-e-2, one of `256x256`, `512x512`, or `1024x1024`publicletsize:String? /// The style of the generated images. /// This parameter is only supported for `dall-e-3`. /// Must be one of `vivid` or `natural`. /// Vivid causes the model to lean towards generating hyper-real and dramatic images. /// Natural causes the model to produce more natural, less hyper-real looking images.publicletstyle:Style? /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse.publicletuser:String?}
- Parameters Edit
/// Creates an edited or extended image given one or more source images and a prompt./// This endpoint only supports `gpt-image-1` and `dall-e-2`.publicstructCreateImageEditParameters:Encodable{ /// The image(s) to edit. /// For `gpt-image-1`, each image should be a `png`, `webp`, or `jpg` file less than 25MB. /// For `dall-e-2`, you can only provide one image, and it should be a square `png` file less than 4MB.letimage:[Data] /// A text description of the desired image(s). /// The maximum length is 1000 characters for `dall-e-2`, and 32000 characters for `gpt-image-1`.letprompt:String /// An additional image whose fully transparent areas indicate where `image` should be edited. /// If there are multiple images provided, the mask will be applied on the first image. /// Must be a valid PNG file, less than 4MB, and have the same dimensions as `image`.letmask:Data? /// The model to use for image generation. Only `dall-e-2` and `gpt-image-1` are supported. /// Defaults to `dall-e-2` unless a parameter specific to `gpt-image-1` is used.letmodel:String? /// The number of images to generate. Must be between 1 and 10. /// Defaults to 1.letn:Int? /// The quality of the image that will be generated. /// `high`, `medium` and `low` are only supported for `gpt-image-1`. /// `dall-e-2` only supports `standard` quality. /// Defaults to `auto`.letquality:String? /// The format in which the generated images are returned. /// Must be one of `url` or `b64_json`. /// URLs are only valid for 60 minutes after the image has been generated. /// This parameter is only supported for `dall-e-2`, as `gpt-image-1` will always return base64-encoded images.letresponseFormat:String? /// The size of the generated images. /// Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for `gpt-image-1`, /// and one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`.letsize:String? /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse.letuser:String?}
- Parameters Variations
/// Creates a variation of a given image./// This endpoint only supports `dall-e-2`.publicstructCreateImageVariationParameters:Encodable{ /// The image to use as the basis for the variation(s). /// Must be a valid PNG file, less than 4MB, and square.letimage:Data /// The model to use for image generation. Only `dall-e-2` is supported at this time. /// Defaults to `dall-e-2`.letmodel:String? /// The number of images to generate. Must be between 1 and 10. /// Defaults to 1.letn:Int? /// The format in which the generated images are returned. /// Must be one of `url` or `b64_json`. /// URLs are only valid for 60 minutes after the image has been generated. /// Defaults to `url`.letresponseFormat:String? /// The size of the generated images. /// Must be one of `256x256`, `512x512`, or `1024x1024`. /// Defaults to `1024x1024`.letsize:String? /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse.letuser:String?}
- Request example
import SwiftOpenAIletservice=OpenAIServiceFactory.service(apiKey:"<YOUR_KEY>")// ❶ Describe the image you wantletprompt="A watercolor dragon-unicorn hybrid flying above snowy mountains"// ❷ Build parameters with the brand-new types (commit 880a15c)letparams=CreateImageParameters( prompt: prompt, model:.gptImage1, // .dallE3 / .dallE2 also valid n:1, // 1-10 (only 1 for DALL-E 3) quality:.high, // .hd / .standard for DALL-E 3 size:"1024x1024" // use "1792x1024" or "1024x1792" for wide / tall)do{ // ❸ Fire the request – returns a `CreateImageResponse`letresult=tryawait service.createImages(parameters: params)leturl= result.data?.first?.url // or `b64Json` for base-64print("Image URL:", url??"none")}catch{print("Generation failed:", error)}
For a sample app example go to theExamples/SwiftOpenAIExample project on this repo.
For handling image sizes, we utilize theDalle model. An enum with associated values has been defined to represent its size constraints accurately.
DALL·E is a AI system that can create realistic images and art from a description in natural language. DALL·E 3 currently supports the ability, given a prompt, to create a new image with a specific size. DALL·E 2 also support the ability to edit an existing image, or create variations of a user provided image.
DALL·E 3 is available through our Images API along with DALL·E 2. You can try DALL·E 3 through ChatGPT Plus.
| MODEL | DESCRIPTION |
|---|---|
| dall-e-3 | DALL·E 3 New |
| The latest DALL·E model released in Nov 2023. Learn more. | |
| dall-e-2 | The previous DALL·E model released in Nov 2022. |
| The 2nd iteration of DALL·E with more realistic, accurate, | |
| and 4x greater resolution images than the original model. |
public enum Dalle {
case dalle2(Dalle2ImageSize)case dalle3(Dalle3ImageSize)
public enum Dalle2ImageSize: String {case small = "256x256"case medium = "512x512"case large = "1024x1024"}
public enum Dalle3ImageSize: String {case largeSquare = "1024x1024"case landscape = "1792x1024"case portrait = "1024x1792"}
var model: String {switch self {case .dalle2: return Model.dalle2.rawValuecase .dalle3: return Model.dalle3.rawValue}}
var size: String {switch self {case .dalle2(let dalle2ImageSize):return dalle2ImageSize.rawValuecase .dalle3(let dalle3ImageSize):return dalle3ImageSize.rawValue}}}
Parameters
publicstructImageCreateParameters:Encodable{ /// A text description of the desired image(s). The maximum length is 1000 characters for dall-e-2 and 4000 characters for dall-e-3.letprompt:String /// The model to use for image generation. Defaults to dall-e-2letmodel:String? /// The number of images to generate. Must be between 1 and 10. For dall-e-3, only n=1 is supported.letn:Int? /// The quality of the image that will be generated. hd creates images with finer details and greater consistency across the image. This param is only supported for dall-e-3. Defaults to standardletquality:String? /// The format in which the generated images are returned. Must be one of url or b64_json. Defaults to urlletresponseFormat:String? /// The size of the generated images. Must be one of 256x256, 512x512, or 1024x1024 for dall-e-2. Must be one of 1024x1024, 1792x1024, or 1024x1792 for dall-e-3 models. Defaults to 1024x1024letsize:String? /// The style of the generated images. Must be one of vivid or natural. Vivid causes the model to lean towards generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real looking images. This param is only supported for dall-e-3. Defaults to vividletstyle:String? /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices)letuser:String?publicinit( prompt:String, model:Dalle, numberOfImages:Int=1, quality:String?=nil, responseFormat:ImageResponseFormat?=nil, style:String?=nil, user:String?=nil){self.prompt= promptself.model= model.modelself.n= numberOfImagesself.quality= qualityself.responseFormat= responseFormat?.rawValueself.size= model.sizeself.style= styleself.user= user}}
Parameters
/// [Creates an edited or extended image given an original image and a prompt.](https://platform.openai.com/docs/api-reference/images/createEdit)publicstructImageEditParameters:Encodable{ /// 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.letimage:Data /// A text description of the desired image(s). The maximum length is 1000 characters.letprompt:String /// 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.letmask:Data? /// The model to use for image generation. Only dall-e-2 is supported at this time. Defaults to dall-e-2letmodel:String? /// The number of images to generate. Must be between 1 and 10. Defaults to 1letn:Int? /// The size of the generated images. Must be one of 256x256, 512x512, or 1024x1024. Defaults to 1024x1024letsize:String? /// The format in which the generated images are returned. Must be one of url or b64_json. Defaults to urlletresponseFormat:String? /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices)letuser:String?publicinit( image:UIImage, model:Dalle?=nil, mask:UIImage?=nil, prompt:String, numberOfImages:Int?=nil, responseFormat:ImageResponseFormat?=nil, user:String?=nil){if(image.pngData()==nil){assertionFailure("Failed to get PNG data from image")}iflet mask, mask.pngData()==nil{assertionFailure("Failed to get PNG data from mask")}iflet model, model.model!=Model.dalle2.rawValue{assertionFailure("Only dall-e-2 is supported at this time [https://platform.openai.com/docs/api-reference/images/createEdit]")}self.image= image.pngData()!self.model= model?.modelself.mask= mask?.pngData()self.prompt= promptself.n= numberOfImagesself.size= model?.sizeself.responseFormat= responseFormat?.rawValueself.user= user}}
Parameters
/// [Creates a variation of a given image.](https://platform.openai.com/docs/api-reference/images/createVariation)publicstructImageVariationParameters:Encodable{ /// The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, and square.letimage:Data /// The model to use for image generation. Only dall-e-2 is supported at this time. Defaults to dall-e-2letmodel:String? /// The number of images to generate. Must be between 1 and 10. Defaults to 1letn:Int? /// The format in which the generated images are returned. Must be one of url or b64_json. Defaults to urlletresponseFormat:String? /// The size of the generated images. Must be one of 256x256, 512x512, or 1024x1024. Defaults to 1024x1024letsize:String? /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices)letuser:String?publicinit( image:UIImage, model:Dalle?=nil, numberOfImages:Int?=nil, responseFormat:ImageResponseFormat?=nil, user:String?=nil){iflet model, model.model!=Model.dalle2.rawValue{assertionFailure("Only dall-e-2 is supported at this time [https://platform.openai.com/docs/api-reference/images/createEdit]")}self.image= image.pngData()!self.n= numberOfImagesself.model= model?.modelself.size= model?.sizeself.responseFormat= responseFormat?.rawValueself.user= user}}
Response
/// [Represents the url or the content of an image generated by the OpenAI API.](https://platform.openai.com/docs/api-reference/images/object)publicstructImageObject:Decodable{ /// The URL of the generated image, if response_format is url (default).publicleturl:URL? /// The base64-encoded JSON of the generated image, if response_format is b64_json.publicletb64Json:String? /// The prompt that was used to generate the image, if there was any revision to the prompt.publicletrevisedPrompt:String?}
Usage
/// Create imageletprompt="A mix of a dragon and an unicorn"letcreateParameters=ImageCreateParameters(prompt: prompt, model:.dalle3(.largeSquare))letimageURLS=tryawait service.legacyCreateImages(parameters: createParameters).data.map(\.url)
/// Edit imageletdata=Data(contentsOfURL:_) // the data from an image.letimage=UIImage(data: data)letprompt="Add a background filled with pink balloons."leteditParameters=ImageEditParameters(image: image, prompt: prompt, numberOfImages:4)letimageURLS=tryawait service.legacyEditImage(parameters: parameters).data.map(\.url)
/// Image variationsletdata=Data(contentsOfURL:_) // the data from an image.letimage=UIImage(data: data)letvariationParameters=ImageVariationParameters(image: image, numberOfImages:4)letimageURLS=tryawait service.legacyCreateImageVariations(parameters: parameters).data.map(\.url)
Response
/// Describes an OpenAI [model](https://platform.openai.com/docs/api-reference/models/object) offering that can be used with the API.publicstructModelObject:Decodable{ /// The model identifier, which can be referenced in the API endpoints.publicletid:String /// The Unix timestamp (in seconds) when the model was created.publicletcreated:Int /// The object type, which is always "model".publicletobject:String /// The organization that owns the model.publicletownedBy:String /// An array representing the current permissions of a model. Each element in the array corresponds to a specific permission setting. If there are no permissions or if the data is unavailable, the array may be nil.publicletpermission:[Permission]?publicstructPermission:Decodable{publicletid:String?publicletobject:String?publicletcreated:Int?publicletallowCreateEngine:Bool?publicletallowSampling:Bool?publicletallowLogprobs:Bool?publicletallowSearchIndices:Bool?publicletallowView:Bool?publicletallowFineTuning:Bool?publicletorganization:String?publicletgroup:String?publicletisBlocking:Bool?} /// Represents the response from the [delete](https://platform.openai.com/docs/api-reference/models/delete) fine-tuning APIpublicstructDeletionStatus:Decodable{publicletid:Stringpublicletobject:Stringpublicletdeleted:Bool}}
Usage
/// List modelsletmodels=tryawait service.listModels().data
/// Retrieve modelletmodelID="gpt-3.5-turbo-instruct"letretrievedModel=tryawait service.retrieveModelWith(id: modelID)
/// Delete fine tuned modelletmodelID="fine-tune-model-id"letdeletionStatus=tryawait service.deleteFineTuneModelWith(id: modelID)
Parameters
/// [Classifies if text violates OpenAI's Content Policy.](https://platform.openai.com/docs/api-reference/moderations/create)publicstructModerationParameter<Input:Encodable>:Encodable{ /// The input text to classify, string or array.letinput:Input /// Two content moderations models are available: text-moderation-stable and text-moderation-latest. /// The default is text-moderation-latest which will be automatically upgraded over time. This ensures you are always using our most accurate model. If you use text-moderation-stable, we will provide advanced notice before updating the model. Accuracy of text-moderation-stable may be slightly lower than for text-moderation-latest.letmodel:String?enumModel:String{case stable="text-moderation-stable"case latest="text-moderation-latest"}init( input:Input, model:Model?=nil){self.input= inputself.model= model?.rawValue}}
Response
/// The [moderation object](https://platform.openai.com/docs/api-reference/moderations/object). Represents policy compliance report by OpenAI's content moderation model against a given input.publicstructModerationObject:Decodable{ /// The unique identifier for the moderation request.publicletid:String /// The model used to generate the moderation results.publicletmodel:String /// A list of moderation objects.publicletresults:[Moderation]publicstructModeration:Decodable{ /// Whether the content violates OpenAI's usage policies.publicletflagged:Bool /// A list of the categories, and whether they are flagged or not.publicletcategories:Category<Bool> /// A list of the categories along with their scores as predicted by model.publicletcategoryScores:Category<Double>publicstructCategory<T:Decodable>:Decodable{ /// Content that expresses, incites, or promotes hate based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste. Hateful content aimed at non-protected groups (e.g., chess players) is harrassment.publiclethate:T /// Hateful content that also includes violence or serious harm towards the targeted group based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste.publiclethateThreatening:T /// Content that expresses, incites, or promotes harassing language towards any target.publicletharassment:T /// Harassment content that also includes violence or serious harm towards any target.publicletharassmentThreatening:T /// Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, and eating disorders.publicletselfHarm:T /// Content where the speaker expresses that they are engaging or intend to engage in acts of self-harm, such as suicide, cutting, and eating disorders.publicletselfHarmIntent:T /// Content that encourages performing acts of self-harm, such as suicide, cutting, and eating disorders, or that gives instructions or advice on how to commit such acts.publicletselfHarmInstructions:T /// Content meant to arouse sexual excitement, such as the description of sexual activity, or that promotes sexual services (excluding sex education and wellness).publicletsexual:T /// Sexual content that includes an individual who is under 18 years old.publicletsexualMinors:T /// Content that depicts death, violence, or physical injury.publicletviolence:T /// Content that depicts death, violence, or physical injury in graphic detail.publicletviolenceGraphic:T}}}
Usage
/// Single promptletprompt="I am going to kill him"letparameters=ModerationParameter(input: prompt)letisFlagged=tryawait service.createModerationFromText(parameters: parameters)
/// Multiple promptsletprompts=["I am going to kill him","I am going to die"]letparameters=ModerationParameter(input: prompts)letisFlagged=tryawait service.createModerationFromTexts(parameters: parameters)
Parameters
/// Create an [assistant](https://platform.openai.com/docs/api-reference/assistants/createAssistant) with a model and instructions./// Modifies an [assistant](https://platform.openai.com/docs/api-reference/assistants/modifyAssistant).publicstructAssistantParameters:Encodable{ /// ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models/overview) for descriptions of them.publicvarmodel:String? /// The name of the assistant. The maximum length is 256 characters.publicvarname:String? /// The description of the assistant. The maximum length is 512 characters.publicvardescription:String? /// The system instructions that the assistant uses. The maximum length is 32768 characters.publicvarinstructions:String? /// A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types code_interpreter, retrieval, or function. Defaults to []publicvartools:[AssistantObject.Tool]=[] /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.publicvarmetadata:[String:String]? /// What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. /// Defaults to 1publicvartemperature:Double? /// An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. /// We generally recommend altering this or temperature but not both. /// Defaults to 1publicvartopP:Double? /// Specifies the format that the model must output. Compatible with GPT-4 Turbo and all GPT-3.5 Turbo models since gpt-3.5-turbo-1106. /// Setting to { "type": "json_object" } enables JSON mode, which guarantees the message the model generates is valid JSON. /// Important: when using JSON mode, you must also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if finish_reason="length", which indicates the generation exceeded max_tokens or the conversation exceeded the max context length. /// Defaults to `auto`publicvarresponseFormat:ResponseFormat?publicenumAction{case create(model:String) // model is required on creation of assistant.case modify(model:String?) // model is optional on modification of assistant.varmodel:String?{switchself{case.create(let model):return modelcase.modify(let model):return model}}}}
Response
/// Represents an [assistant](https://platform.openai.com/docs/api-reference/assistants) that can call the model and use tools.publicstructAssistantObject:Decodable{ /// The identifier, which can be referenced in API endpoints.publicletid:String /// The object type, which is always "assistant".publicletobject:String /// The Unix timestamp (in seconds) for when the assistant was created.publicletcreatedAt:Int /// The name of the assistant. The maximum length is 256 characters.publicletname:String? /// The description of the assistant. The maximum length is 512 characters.publicletdescription:String? /// ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models/overview) for descriptions of them.publicletmodel:String /// The system instructions that the assistant uses. The maximum length is 32768 characters.publicletinstructions:String? /// A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types code_interpreter, retrieval, or function.publiclettools:[Tool] /// A list of [file](https://platform.openai.com/docs/api-reference/files) IDs attached to this assistant. There can be a maximum of 20 files attached to the assistant. Files are ordered by their creation date in ascending order. /// A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the code_interpreter tool requires a list of file IDs, while the file_search tool requires a list of vector store IDs.publiclettoolResources:ToolResources? /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.publicletmetadata:[String:String]? /// What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. /// Defaults to 1publicvartemperature:Double? /// An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. /// We generally recommend altering this or temperature but not both. /// Defaults to 1publicvartopP:Double? /// Specifies the format that the model must output. Compatible with GPT-4 Turbo and all GPT-3.5 Turbo models since gpt-3.5-turbo-1106. /// Setting to { "type": "json_object" } enables JSON mode, which guarantees the message the model generates is valid JSON. /// Important: when using JSON mode, you must also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if finish_reason="length", which indicates the generation exceeded max_tokens or the conversation exceeded the max context length. /// Defaults to `auto`publicvarresponseFormat:ResponseFormat?publicstructTool:Codable{ /// The type of tool being defined.publiclettype:Stringpublicletfunction:ChatCompletionParameters.ChatFunction?publicenumToolType:String,CaseIterable{case codeInterpreter="code_interpreter"case fileSearch="file_search"case function} /// Helper.publicvardisplayToolType:ToolType?{.init(rawValue: type)}publicinit( type:ToolType, function:ChatCompletionParameters.ChatFunction?=nil){self.type= type.rawValueself.function= function}}publicstructDeletionStatus:Decodable{publicletid:Stringpublicletobject:Stringpublicletdeleted:Bool}}
Usage
Create Assistant
letparameters=AssistantParameters(action:.create(model:Model.gpt41106Preview.rawValue), name:"Math tutor")letassistant=tryawait service.createAssistant(parameters: parameters)
Retrieve Assistant
letassistantID="asst_abc123"letassistant=tryawait service.retrieveAssistant(id: assistantID)
Modify Assistant
letassistantID="asst_abc123"letparameters=AssistantParameters(action:.modify, name:"Math tutor for kids")letassistant=tryawait service.modifyAssistant(id: assistantID, parameters: parameters)
Delete Assistant
letassistantID="asst_abc123"letdeletionStatus=tryawait service.deleteAssistant(id: assistantID)
List Assistants
letassistants=tryawait service.listAssistants()
Parameters
/// Create a [Thread](https://platform.openai.com/docs/api-reference/threads/createThread)publicstructCreateThreadParameters:Encodable{ /// A list of [messages](https://platform.openai.com/docs/api-reference/messages) to start the thread with.publicvarmessages:[MessageObject]? /// A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the code_interpreter tool requires a list of file IDs, while the file_search tool requires a list of vector store IDs.publicvartoolResources:ToolResources? /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.publicvarmetadata:[String:String]?}
Response
/// A [thread object](https://platform.openai.com/docs/api-reference/threads) represents a thread that contains [messages](https://platform.openai.com/docs/api-reference/messages).publicstructThreadObject:Decodable{ /// The identifier, which can be referenced in API endpoints.publicletid:String /// The object type, which is always thread.publicletobject:String /// The Unix timestamp (in seconds) for when the thread was created.publicletcreatedAt:Int /// A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the code_interpreter tool requires a list of file IDs, while the file_search tool requires a list of vector store IDs.publicvartoolResources:ToolResources? /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.publicletmetadata:[String:String]}
Usage
Create thread.
letparameters=CreateThreadParameters()letthread=tryawait service.createThread(parameters: parameters)
Retrieve thread.
letthreadID="thread_abc123"letthread=tryawait service.retrieveThread(id: id)
Modify thread.
letthreadID="thread_abc123"letparamaters=CreateThreadParameters(metadata:["modified":"true","user":"abc123"]let thread=tryawait service.modifyThread(id: id, parameters: parameters)
Delete thread.
letthreadID="thread_abc123"letthread=tryawait service.deleteThread(id: id)
ParametersCreate a Message)
publicstructMessageParameter:Encodable{ /// The role of the entity that is creating the message. Allowed values include: /// user: Indicates the message is sent by an actual user and should be used in most cases to represent user-generated messages. /// assistant: Indicates the message is generated by the assistant. Use this value to insert messages from the assistant into the conversation.letrole:String /// The content of the message, which can be a string or an array of content parts (text, image URL, image file).letcontent:Content /// A list of files attached to the message, and the tools they should be added to.letattachments:[MessageAttachment]? /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.letmetadata:[String:String]?}
publicstructModifyMessageParameters:Encodable{ /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.publicvarmetadata:[String:String]}
Response
/// Represents a [message](https://platform.openai.com/docs/api-reference/messages) within a [thread](https://platform.openai.com/docs/api-reference/threads).publicstructMessageObject:Codable{ /// The identifier, which can be referenced in API endpoints.publicletid:String /// The object type, which is always thread.message.publicletobject:String /// The Unix timestamp (in seconds) for when the message was created.publicletcreatedAt:Int /// The [thread](https://platform.openai.com/docs/api-reference/threads) ID that this message belongs to.publicletthreadID:String /// The status of the message, which can be either in_progress, incomplete, or completed.publicletstatus:String /// On an incomplete message, details about why the message is incomplete.publicletincompleteDetails:IncompleteDetails? /// The Unix timestamp (in seconds) for when the message was completed.publicletcompletedAt:Int /// The entity that produced the message. One of user or assistant.publicletrole:String /// The content of the message in array of text and/or images.publicletcontent:[MessageContent] /// If applicable, the ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) that authored this message.publicletassistantID:String? /// If applicable, the ID of the [run](https://platform.openai.com/docs/api-reference/runs) associated with the authoring of this message.publicletrunID:String? /// A list of files attached to the message, and the tools they were added to.publicletattachments:[MessageAttachment]? /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.publicletmetadata:[String:String]?enumRole:String{case usercase assistant}}// MARK: MessageContentpublicenumMessageContent:Codable{case imageFile(ImageFile)case text(Text)}// MARK: Image FilepublicstructImageFile:Codable{ /// Always image_file.publiclettype:String /// References an image [File](https://platform.openai.com/docs/api-reference/files) in the content of a message.publicletimageFile:ImageFileContentpublicstructImageFileContent:Codable{ /// The [File](https://platform.openai.com/docs/api-reference/files) ID of the image in the message content.publicletfileID:String}}// MARK: TextpublicstructText:Codable{ /// Always text.publiclettype:String /// The text content that is part of a message.publiclettext:TextContentpublicstructTextContent:Codable{ // The data that makes up the text.publicletvalue:Stringpublicletannotations:[Annotation]}}// MARK: AnnotationpublicenumAnnotation:Codable{case fileCitation(FileCitation)case filePath(FilePath)}// MARK: FileCitation/// A citation within the message that points to a specific quote from a specific File associated with the assistant or the message. Generated when the assistant uses the "retrieval" tool to search files.publicstructFileCitation:Codable{ /// Always file_citation.publiclettype:String /// The text in the message content that needs to be replaced.publiclettext:StringpublicletfileCitation:FileCitationpublicletstartIndex:IntpublicletendIndex:IntpublicstructFileCitation:Codable{ /// The ID of the specific File the citation is from.publicletfileID:String /// The specific quote in the file.publicletquote:String}}// MARK: FilePath/// A URL for the file that's generated when the assistant used the code_interpreter tool to generate a file.publicstructFilePath:Codable{ /// Always file_pathpubliclettype:String /// The text in the message content that needs to be replaced.publiclettext:StringpublicletfilePath:FilePathpublicletstartIndex:IntpublicletendIndex:IntpublicstructFilePath:Codable{ /// The ID of the file that was generated.publicletfileID:String}}
Usage
Create Message.
letthreadID="thread_abc123"letprompt="Give me some ideas for a birthday party."letparameters=MessageParameter(role:"user", content:.stringContent(prompt)")letmessage=tryawait service.createMessage(threadID: threadID, parameters: parameters)
Retrieve Message.
letthreadID="thread_abc123"letmessageID="msg_abc123"letmessage=tryawait service.retrieveMessage(threadID: threadID, messageID: messageID)
Modify Message.
letthreadID="thread_abc123"letmessageID="msg_abc123"letparameters=ModifyMessageParameters(metadata:["modified":"true","user":"abc123"]let message=tryawait service.modifyMessage(threadID: threadID, messageID: messageID, parameters: parameters)
List Messages
letthreadID="thread_abc123"letmessages=tryawait service.listMessages(threadID: threadID, limit:nil, order:nil, after:nil, before:nil)
Parameters
publicstructRunParameter:Encodable{ /// The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run.letassistantID:String /// The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used.letmodel:String? /// Override the default system message of the assistant. This is useful for modifying the behavior on a per-run basis.letinstructions:String? /// Appends additional instructions at the end of the instructions for the run. This is useful for modifying the behavior on a per-run basis without overriding other instructions.letadditionalInstructions:String? /// Adds additional messages to the thread before creating the run.letadditionalMessages:[MessageParameter]? /// Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis.lettools:[AssistantObject.Tool]? /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.letmetadata:[String:String]? /// What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. /// Optional Defaults to 1lettemperature:Double? /// If true, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a data: [DONE] message.varstream:Bool /// The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status complete. See incomplete_details for more info.letmaxPromptTokens:Int? /// The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status complete. See incomplete_details for more info.letmaxCompletionTokens:Int? /// Controls for how a thread will be truncated prior to the run. Use this to control the intial context window of the run.lettruncationStrategy:TruncationStrategy? /// Controls which (if any) tool is called by the model. none means the model will not call any tools and instead generates a message. auto is the default value and means the model can pick between generating a message or calling a tool. Specifying a particular tool like {"type": "file_search"} or {"type": "function", "function": {"name": "my_function"}} forces the model to call that tool.lettoolChoice:ToolChoice? /// Specifies the format that the model must output. Compatible with GPT-4 Turbo and all GPT-3.5 Turbo models newer than gpt-3.5-turbo-1106. /// Setting to { "type": "json_object" } enables JSON mode, which guarantees the message the model generates is valid JSON. /// Important: when using JSON mode, you must also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if finish_reason="length", which indicates the generation exceeded max_tokens or the conversation exceeded the max context length.letresponseFormat:ResponseFormat?}
publicstructModifyRunParameters:Encodable{ /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.publicvarmetadata:[String:String]publicinit( metadata:[String:String]){self.metadata= metadata}}
publicstructCreateThreadAndRunParameter:Encodable{ /// The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to execute this run.letassistantId:String /// A thread to create.letthread:CreateThreadParameters? /// The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used.letmodel:String? /// Override the default system message of the assistant. This is useful for modifying the behavior on a per-run basis.letinstructions:String? /// Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis.lettools:[AssistantObject.Tool]? /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.letmetadata:[String:String]? /// What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. /// Defaults to 1lettemperature:Double? /// An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. /// We generally recommend altering this or temperature but not both.lettopP:Double? /// If true, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a data: [DONE] message.varstream:Bool=false /// The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status incomplete. See incomplete_details for more info.letmaxPromptTokens:Int? /// The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status complete. See incomplete_details for more info.letmaxCompletionTokens:Int? /// Controls for how a thread will be truncated prior to the run. Use this to control the intial context window of the run.lettruncationStrategy:TruncationStrategy? /// Controls which (if any) tool is called by the model. none means the model will not call any tools and instead generates a message. auto is the default value and means the model can pick between generating a message or calling a tool. Specifying a particular tool like {"type": "file_search"} or {"type": "function", "function": {"name": "my_function"}} forces the model to call that tool.lettoolChoice:ToolChoice? /// Specifies the format that the model must output. Compatible with GPT-4 Turbo and all GPT-3.5 Turbo models newer than gpt-3.5-turbo-1106. /// Setting to { "type": "json_object" } enables JSON mode, which guarantees the message the model generates is valid JSON. /// Important: when using JSON mode, you must also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if finish_reason="length", which indicates the generation exceeded max_tokens or the conversation exceeded the max context length.letresponseFormat:ResponseFormat?}
publicstructRunToolsOutputParameter:Encodable{ /// A list of tools for which the outputs are being submitted.publiclettoolOutputs:[ToolOutput] /// If true, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a data: [DONE] message.publicletstream:Bool}
Response
publicstructRunObject:Decodable{ /// The identifier, which can be referenced in API endpoints.publicletid:String /// The object type, which is always thread.run.publicletobject:String /// The Unix timestamp (in seconds) for when the run was created.publicletcreatedAt:Int? /// The ID of the [thread](https://platform.openai.com/docs/api-reference/threads) that was executed on as a part of this run.publicletthreadID:String /// The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) used for execution of this run.publicletassistantID:String /// The status of the run, which can be either queued, in_progress, requires_action, cancelling, cancelled, failed, completed, or expired.publicletstatus:String /// Details on the action required to continue the run. Will be null if no action is required.publicletrequiredAction:RequiredAction? /// The last error associated with this run. Will be null if there are no errors.publicletlastError:LastError? /// The Unix timestamp (in seconds) for when the run will expire.publicletexpiresAt:Int? /// The Unix timestamp (in seconds) for when the run was started.publicletstartedAt:Int? /// The Unix timestamp (in seconds) for when the run was cancelled.publicletcancelledAt:Int? /// The Unix timestamp (in seconds) for when the run failed.publicletfailedAt:Int? /// The Unix timestamp (in seconds) for when the run was completed.publicletcompletedAt:Int? /// Details on why the run is incomplete. Will be null if the run is not incomplete.publicletincompleteDetails:IncompleteDetails? /// The model that the [assistant](https://platform.openai.com/docs/api-reference/assistants) used for this run.publicletmodel:String /// The instructions that the [assistant](https://platform.openai.com/docs/api-reference/assistants) used for this run.publicletinstructions:String? /// The list of tools that the [assistant](https://platform.openai.com/docs/api-reference/assistants) used for this run.publiclettools:[AssistantObject.Tool] /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.publicletmetadata:[String:String] /// Usage statistics related to the run. This value will be null if the run is not in a terminal state (i.e. in_progress, queued, etc.).publicletusage:Usage? /// The sampling temperature used for this run. If not set, defaults to 1.publiclettemperature:Double? /// The nucleus sampling value used for this run. If not set, defaults to 1.publiclettopP:Double? /// The maximum number of prompt tokens specified to have been used over the course of the run.publicletmaxPromptTokens:Int? /// The maximum number of completion tokens specified to have been used over the course of the run.publicletmaxCompletionTokens:Int? /// Controls for how a thread will be truncated prior to the run. Use this to control the intial context window of the run.publiclettruncationStrategy:TruncationStrategy? /// Controls which (if any) tool is called by the model. none means the model will not call any tools and instead generates a message. auto is the default value and means the model can pick between generating a message or calling a tool. Specifying a particular tool like {"type": "TOOL_TYPE"} or {"type": "function", "function": {"name": "my_function"}} forces the model to call that tool.publiclettoolChoice:ToolChoice? /// Specifies the format that the model must output. Compatible with GPT-4 Turbo and all GPT-3.5 Turbo models newer than gpt-3.5-turbo-1106. /// Setting to { "type": "json_object" } enables JSON mode, which guarantees the message the model generates is valid JSON. /// Important: when using JSON mode, you must also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if finish_reason="length", which indicates the generation exceeded max_tokens or the conversation exceeded the max context length.publicletresponseFormat:ResponseFormat?}
Usage
Create a Run
letassistantID="asst_abc123"letparameters=RunParameter(assistantID: assistantID)letrun=tryawait service.createRun(threadID: threadID, parameters: parameters)
Retrieve a Run
letthreadID="thread_abc123"letrunID="run_abc123"letrun=tryawait service.retrieveRun(threadID: threadID, runID: runID)
Modify a Run
letthreadID="thread_abc123"letrunID="run_abc123"letparameters=ModifyRunParameters(metadata:["modified":"true","user":"abc123"]let message=tryawait service.modifyRun(threadID: threadID, messageID: messageID, parameters: parameters)
List runs
letthreadID="thread_abc123"letruns=tryawait service.listRuns(threadID: threadID, limit:nil, order:nil, after:nil, before:nil)
Submit tool outputs to Run
letthreadID="thread_abc123"letrunID="run_abc123"lettoolCallID="call_abc123"letoutput="28C"letparameters=RunToolsOutputParameter(toolOutputs:[.init(toolCallId: toolCallID, output: output)])letrun=tryawait service.submitToolOutputsToRun(threadID: threadID", runID: runID", parameters: parameters)
Cancel a Run
/// Cancels a run that is in_progress.letthreadID="thread_abc123"letrunID="run_abc123"letrun=tryawait service.cancelRun(threadID: threadID, runID: runID)
Create thread and Run
letassistantID="asst_abc123"letparameters=CreateThreadAndRunParameter(assistantID: assistantID)letrun= service.createThreadAndRun(parameters: parameters)
Represents astep in execution of a run.Response
publicstructRunStepObject:Decodable{ /// The identifier of the run step, which can be referenced in API endpoints.publicletid:String /// The object type, which is always `thread.run.step``.publicletobject:String /// The Unix timestamp (in seconds) for when the run step was created.publicletcreatedAt:Int /// The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) associated with the run step.publicletassistantId:String /// The ID of the [thread](https://platform.openai.com/docs/api-reference/threads) that was run.publicletthreadId:String ///The ID of the [run](https://platform.openai.com/docs/api-reference/runs) that this run step is a part of.publicletrunId:String /// The type of run step, which can be either message_creation or tool_calls.publiclettype:String /// The status of the run step, which can be either in_progress, cancelled, failed, completed, or expired.publicletstatus:String /// The details of the run step.publicletstepDetails:RunStepDetails /// The last error associated with this run step. Will be null if there are no errors.publicletlastError:RunObject.LastError? /// The Unix timestamp (in seconds) for when the run step expired. A step is considered expired if the parent run is expired.publicletexpiredAt:Int? /// The Unix timestamp (in seconds) for when the run step was cancelled.publicletcancelledAt:Int? /// The Unix timestamp (in seconds) for when the run step failed.publicletfailedAt:Int? /// The Unix timestamp (in seconds) for when the run step completed.publicletcompletedAt:Int? /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.publicletmetadata:[String:String]? /// Usage statistics related to the run step. This value will be null while the run step's status is in_progress.publicletusage:Usage?}
UsageRetrieve a Run step
letthreadID="thread_abc123"letrunID="run_abc123"letstepID="step_abc123"letrunStep=tryawait service.retrieveRunstep(threadID: threadID, runID: runID, stepID: stepID)
List run steps
letthreadID="thread_abc123"letrunID="run_abc123"letrunSteps=tryawait service.listRunSteps(threadID: threadID, runID: runID, limit:nil, order:nil, after:nil, before:nil)
The details of the run step.
publicstructRunStepDetails:Codable{ /// `message_creation` or `tool_calls`publiclettype:String /// Details of the message creation by the run step.publicletmessageCreation:MessageCreation? /// Details of the tool call.publiclettoolCalls:[ToolCall]?}
Assistants APIstreaming.
Stream the result of executing a Run or resuming a Run after submitting tool outputs.
You can stream events from theCreate Thread and Run,Create Run, andSubmit Tool Outputs endpoints by passing "stream": true. The response will be a Server-Sent events stream.
OpenAI Python tutorial(https://platform.openai.com/docs/assistants/overview?context=with-streaming))
MessageDeltaObject Represents a message delta i.e. any changed fields on a message during streaming.
publicstructMessageDeltaObject:Decodable{ /// The identifier of the message, which can be referenced in API endpoints.publicletid:String /// The object type, which is always thread.message.delta.publicletobject:String /// The delta containing the fields that have changed on the Message.publicletdelta:DeltapublicstructDelta:Decodable{ /// The entity that produced the message. One of user or assistant.publicletrole:String /// The content of the message in array of text and/or images.publicletcontent:[MessageContent]}}
Represents arun step delta i.e. any changed fields on a run step during streaming.
publicstructRunStepDeltaObject:Decodable{ /// The identifier of the run step, which can be referenced in API endpoints.publicletid:String /// The object type, which is always thread.run.step.delta.publicletobject:String /// The delta containing the fields that have changed on the run step.publicletdelta:DeltapublicstructDelta:Decodable{ /// The details of the run step.publicletstepDetails:RunStepDetailsprivateenumCodingKeys:String,CodingKey{case stepDetails="step_details"}}}
createRunAndStreamMessage, first create an assistant and initiate a thread.
UsageCreate Run with stream.
ThecreateRunAndStreamMessage streamsevents, You can decide which one you need for your implementation. For example, this is how you can access message delta and run step delta objects
letassistantID="asst_abc123"letthreadID="thread_abc123"letmessageParameter=MessageParameter(role:.user, content:"Tell me the square root of 1235")letmessage=tryawait service.createMessage(threadID: threadID, parameters: messageParameter)letrunParameters=RunParameter(assistantID: assistantID)letstream=tryawait service.createRunAndStreamMessage(threadID: threadID, parameters: runParameters)fortryawaitresultin stream{switch result{case.threadMessageDelta(let messageDelta):letcontent= messageDelta.delta.content.firstswitch content{case.imageFile,nil:breakcase.text(let textContent):print(textContent.text.value) // this will print the streamed response for a message.}case.threadRunStepDelta(let runStepDelta):iflet toolCall= runStepDelta.delta.stepDetails.toolCalls?.first?.toolCall{switch toolCall{case.codeInterpreterToolCall(let toolCall):print(toolCall.input??"") // this will print the streamed response for code interpreter tool call.case.fileSearchToolCall(let toolCall):print("File search tool call")case.functionToolCall(let toolCall):print("Function tool call")casenil:break}}}}
You can go to theExamples folder in this package, navigate to the 'Configure Assistants' tab, create an assistant, and follow the subsequent steps.
/// Creates a thread and run with stream enabled. /// /// - Parameter parameters: The parameters needed to create a thread and run. /// - Returns: An AsyncThrowingStream of [AssistantStreamEvent](https://platform.openai.com/docs/api-reference/assistants-streaming/events) objects. /// - Throws: An error if the request fails. /// /// For more information, refer to [OpenAI's Run API documentation](https://platform.openai.com/docs/api-reference/runs/createThreadAndRun).func createThreadAndRunStream( parameters:CreateThreadAndRunParameter)asyncthrows->AsyncThrowingStream<AssistantStreamEvent,Error>
/// When a run has the status: "requires_action" and required_action.type is submit_tool_outputs, this endpoint can be used to submit the outputs from the tool calls once they're all completed. All outputs must be submitted in a single request. Stream enabled /// /// - Parameter threadID: The ID of the [thread](https://platform.openai.com/docs/api-reference/threads) to which this run belongs. /// - Parameter runID: The ID of the run that requires the tool output submission. /// - Parameter parameters: The parameters needed for the run tools output. /// - Returns: An AsyncThrowingStream of [AssistantStreamEvent](https://platform.openai.com/docs/api-reference/assistants-streaming/events) objects. /// - Throws: An error if the request fails. /// /// For more information, refer to [OpenAI's Run API documentation](https://platform.openai.com/docs/api-reference/runs/submitToolOutputs).func submitToolOutputsToRunStream( threadID:String, runID:String, parameters:RunToolsOutputParameter)asyncthrows->AsyncThrowingStream<AssistantStreamEvent,Error>
Parameters
publicstructVectorStoreParameter:Encodable{ /// A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the vector store should use. Useful for tools like file_search that can access files.letfileIDS:[String]? /// The name of the vector store.letname:String? /// The expiration policy for a vector store.letexpiresAfter:ExpirationPolicy? /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.letmetadata:[String:String]?}
Response
publicstructVectorStoreObject:Decodable{ /// The identifier, which can be referenced in API endpoints.letid:String /// The object type, which is always vector_store.letobject:String /// The Unix timestamp (in seconds) for when the vector store was created.letcreatedAt:Int /// The name of the vector store.letname:String /// The total number of bytes used by the files in the vector store.letusageBytes:IntletfileCounts:FileCount /// The status of the vector store, which can be either expired, in_progress, or completed. A status of completed indicates that the vector store is ready for use.letstatus:String /// The expiration policy for a vector store.letexpiresAfter:ExpirationPolicy? /// The Unix timestamp (in seconds) for when the vector store will expire.letexpiresAt:Int? /// The Unix timestamp (in seconds) for when the vector store was last active.letlastActiveAt:Int? /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.letmetadata:[String:String]publicstructFileCount:Decodable{ /// The number of files that are currently being processed.letinProgress:Int /// The number of files that have been successfully processed.letcompleted:Int /// The number of files that have failed to process.letfailed:Int /// The number of files that were cancelled.letcancelled:Int /// The total number of files.lettotal:Int}}
UsageCreate vector Store
letname="Support FAQ"letparameters=VectorStoreParameter(name: name)try vectorStore=tryawait service.createVectorStore(parameters: parameters)
letvectorStores=tryawait service.listVectorStores(limit:nil, order:nil, after:nil, before:nil)
letvectorStoreID="vs_abc123"letvectorStore=tryawait service.retrieveVectorStore(id: vectorStoreID)
letvectorStoreID="vs_abc123"letvectorStore=tryawait service.modifyVectorStore(id: vectorStoreID)
letvectorStoreID="vs_abc123"letdeletionStatus=tryawait service.deleteVectorStore(id: vectorStoreID)
Parameters
publicstructVectorStoreFileParameter:Encodable{ /// A [File](https://platform.openai.com/docs/api-reference/files) ID that the vector store should use. Useful for tools like file_search that can access files.letfileID:String}
Response
publicstructVectorStoreFileObject:Decodable{ /// The identifier, which can be referenced in API endpoints.letid:String /// The object type, which is always vector_store.file.letobject:String /// The total vector store usage in bytes. Note that this may be different from the original file size.letusageBytes:Int /// The Unix timestamp (in seconds) for when the vector store file was created.letcreatedAt:Int /// The ID of the [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) that the [File](https://platform.openai.com/docs/api-reference/files) is attached to.letvectorStoreID:String /// The status of the vector store file, which can be either in_progress, completed, cancelled, or failed. The status completed indicates that the vector store file is ready for use.letstatus:String /// The last error associated with this vector store file. Will be null if there are no errors.letlastError:LastError?}
letvectorStoreID="vs_abc123"letfileID="file-abc123"letparameters=VectorStoreFileParameter(fileID: fileID)letvectoreStoreFile=tryawait service.createVectorStoreFile(vectorStoreID: vectorStoreID, parameters: parameters)
letvectorStoreID="vs_abc123"letvectorStoreFiles=tryawait service.listVectorStoreFiles(vectorStoreID: vectorStoreID, limit:nil, order:nil, aftre:nil, before:nil, filter:nil)
letvectorStoreID="vs_abc123"letfileID="file-abc123"letvectoreStoreFile=tryawait service.retrieveVectorStoreFile(vectorStoreID: vectorStoreID, fileID: fileID)
letvectorStoreID="vs_abc123"letfileID="file-abc123"letdeletionStatus=tryawait service.deleteVectorStoreFile(vectorStoreID: vectorStoreID, fileID: fileID)
Parameters
publicstructVectorStoreFileBatchParameter:Encodable{ /// A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the vector store should use. Useful for tools like file_search that can access files.letfileIDS:[String]}
Response
publicstructVectorStoreFileBatchObject:Decodable{ /// The identifier, which can be referenced in API endpoints.letid:String /// The object type, which is always vector_store.file_batch.letobject:String /// The Unix timestamp (in seconds) for when the vector store files batch was created.letcreatedAt:Int /// The ID of the [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) that the [File](https://platform.openai.com/docs/api-reference/files) is attached to.letvectorStoreID:String /// The status of the vector store files batch, which can be either in_progress, completed, cancelled or failed.letstatus:StringletfileCounts:FileCount}
Usage
Create vector store file batch
letvectorStoreID="vs_abc123"letfileIDS=["file-abc123","file-abc456"]letparameters=VectorStoreFileBatchParameter(fileIDS: fileIDS)letvectorStoreFileBatch=tryawait service.createVectorStoreFileBatch(vectorStoreID: vectorStoreID, parameters: parameters)
Retrieve vector store file batch
letvectorStoreID="vs_abc123"letbatchID="vsfb_abc123"letvectorStoreFileBatch=tryawait service.retrieveVectorStoreFileBatch(vectorStoreID: vectorStoreID, batchID: batchID)
Cancel vector store file batch
letvectorStoreID="vs_abc123"letbatchID="vsfb_abc123"letvectorStoreFileBatch=tryawait service.cancelVectorStoreFileBatch(vectorStoreID: vectorStoreID, batchID: batchID)
List vector store files in a batch
letvectorStoreID="vs_abc123"letbatchID="vsfb_abc123"letvectorStoreFiles=tryawait service.listVectorStoreFilesInABatch(vectorStoreID: vectorStoreID, batchID: batchID)
Anthropic provides OpenAI compatibility, for more, visit thedocumentation
To use Claude models withSwiftOpenAI you can.
letanthropicApiKey=""letopenAIService=OpenAIServiceFactory.service(apiKey: anthropicApiKey, overrideBaseURL:"https://api.anthropic.com", overrideVersion:"v1")
Now you can create the completio parameters like this:
letparameters=ChatCompletionParameters( messages:[.init( role:.user, content:"Are you Claude?")], model:.custom("claude-3-7-sonnet-20250219"))
For a more complete Anthropic Swift Package, you can useSwiftAnthropic
This library provides support for both chat completions and chat stream completions through Azure OpenAI. Currently,DefaultOpenAIAzureService supports chat completions, including both streamed and non-streamed options.
For more information about Azure configuration refer to thedocumentation.
To instantiateDefaultOpenAIAzureService you need to provide aAzureOpenAIConfiguration
letazureConfiguration= AzureOpenAIConfiguration( resourceName:"YOUR_RESOURCE_NAME", openAIAPIKey:.apiKey("YOUR_OPENAI_APIKEY), apiVersion:"THE_API_VERSION")let service = OpenAIServiceFactory.service(azureConfiguration: azureConfiguration)
supported api version can be found on the azuredocumentation
Current Supported versions
2022-12-012023-03-15-preview2023-05-152023-06-01-preview2023-07-01-preview2023-08-01-preview2023-09-01-preview
Usage onChat completions:
letparameters=ChatCompletionParameters( messages:[.init(role:.user, content:.text(prompt))], model:.custom("DEPLOYMENT_NAME") /// The deployment name you chose when you deployed the model. e.g: "gpt-35-turbo-0613"let completionObject=tryawait service.startChat(parameters: parameters)
AIProxy is a backend for iOS apps that proxies requests from your app to OpenAI.Using a proxy keeps your OpenAI key secret, protecting you from unexpectedly high bills due to key theft.Requests are only proxied if they pass your defined rate limits and Apple'sDeviceCheck verification.We offer AIProxy support so you can safely distribute apps built with SwiftOpenAI.
Proxy requests through AIProxy with two changes to your Xcode project:
Instead of initializing
servicewith:let apiKey = "your_openai_api_key_here" let service = OpenAIServiceFactory.service(apiKey: apiKey)
Use:
let service = OpenAIServiceFactory.service( aiproxyPartialKey: "your_partial_key_goes_here", aiproxyServiceURL: "your_service_url_goes_here" )TheaiproxyPartialKey andaiproxyServiceURL values are provided to you on theAIProxy developer dashboard
- Add an `AIPROXY_DEVICE_CHECK_BYPASS' env variable to Xcode. This token is provided to you in the AIProxydeveloper dashboard, and is necessary for the iOS simulator to communicate with the AIProxy backend.
- Type
cmd shift ,to open up the "Edit Schemes" menu in Xcode - Select
Runin the sidebar - Select
Argumentsfrom the top nav - Add to the "Environment Variables" section (not the "Arguments Passed on Launch" section) an envvariable with name
AIPROXY_DEVICE_CHECK_BYPASSand value that we provided you in the AIProxy dashboard
- Type
AIPROXY_DEVICE_CHECK_BYPASS is intended for the simulator only. Do not let it leak intoa distribution build of your app (including a TestFlight distribution). If you follow the steps above,then the constant won't leak because env variables are not packaged into the app bundle.
AIProxy uses Apple'sDeviceCheck to ensurethat requests received by the backend originated from your app on a legitimate Apple device.However, the iOS simulator cannot produce DeviceCheck tokens. Rather than requiring you toconstantly build and run on device during development, AIProxy provides a way to skip theDeviceCheck integrity check. The token is intended for use by developers only. If an attacker getsthe token, they can make requests to your AIProxy project without including a DeviceCheck token, andthus remove one level of protection.
This constant is safe to include in distributed version of your app. It is one part of anencrypted representation of your real secret key. The other part resides on AIProxy's backend.As your app makes requests to AIProxy, the two encrypted parts are paired, decrypted, and usedto fulfill the request to OpenAI.
Please see theAIProxy integration guide
Contributors of SwiftOpenAI shall not be liable for any damages or losses caused by third parties.Contributors of this library provide third party integrations as a convenience. Any use of a thirdparty's services are assumed at your own risk.
Ollama now has built-in compatibility with the OpenAIChat Completions API, making it possible to use more tooling and applications with Ollama locally.

Remember that these models run locally, so you need to download them. If you want to use llama3, you can open the terminal and run the following command:
ollamapullllama3
you can followOllama documentation for more.
To use local models with anOpenAIService in your application, you need to provide a URL.
letservice=OpenAIServiceFactory.service(baseURL:"http://localhost:11434")
Then you can use the completions API as follows:
letprompt="Tell me a joke"letparameters=ChatCompletionParameters(messages:[.init(role:.user, content:.text(prompt))], model:.custom("llama3"))letchatCompletionObject= service.startStreamedChat(parameters: parameters)
OpenAIServiceFactory.service(apiKey:overrideBaseURL:proxyPath) for any OpenAI compatible service.
Ollama OpenAI compatibility docs.Ollama OpenAI compatibility blog post.
You can also use this service constructor to provide any URL or apiKey if you need.
letservice=OpenAIServiceFactory.service(apiKey:"YOUR_API_KEY", baseURL:"http://localhost:11434")

Groq API is mostly compatible with OpenAI's client libraries likeSwiftOpenAI to use Groq using this library you just need to create an instance ofOpenAIService like this:
letapiKey="your_api_key"letservice=OpenAIServiceFactory.service(apiKey: apiKey, overrideBaseURL:"https://api.groq.com/", proxyPath:"openai")
For Supported API's using Groq visit itsdocumentation.

xAI provides an OpenAI-compatible completion API to its Grok models. You can use the OpenAI SDK to access these models.
letapiKey="your_api_xai_key"letservice=OpenAIServiceFactory.service(apiKey: apiKey, overrideBaseURL:"https://api.x.ai", overrideVersion:"v1")
For more information about thexAI api visit itsdocumentation.

OpenRouter provides an OpenAI-compatible completion API to 314 models & providers that you can call directly, or using the OpenAI SDK. Additionally, some third-party SDKs are available.
// Creating the serviceletapiKey="your_api_key"letservcie=OpenAIServiceFactory.service(apiKey: apiKey, overrideBaseURL:"https://openrouter.ai", proxyPath:"api", extraHeaders:["HTTP-Referer":"<YOUR_SITE_URL>", // Optional. Site URL for rankings on openrouter.ai."X-Title":"<YOUR_SITE_NAME>" // Optional. Site title for rankings on openrouter.ai.])// Making a requestletprompt="What is the Manhattan project?"letparameters=ChatCompletionParameters(messages:[.init(role:.user, content:.text(prompt))], model:.custom("deepseek/deepseek-r1:free"))letstream= service.startStreamedChat(parameters: parameters)
For more inofrmation about theOpenRouter api visit itsdocumentation.
TheDeepSeek API uses an API format compatible with OpenAI. By modifying the configuration, you can use SwiftOpenAI to access the DeepSeek API.
Creating the service
letapiKey="your_api_key"letservice=OpenAIServiceFactory.service( apiKey: apiKey, overrideBaseURL:"https://api.deepseek.com")
Non-Streaming Example
letprompt="What is the Manhattan project?"letparameters=ChatCompletionParameters( messages:[.init(role:.user, content:.text(prompt))], model:.custom("deepseek-reasoner"))do{letresult=tryawait service.chat(parameters: parameters) // Access the response contentiflet content= result.choices.first?.message.content{print("Response:\(content)")} // Access reasoning content if availableiflet reasoning= result.choices.first?.message.reasoningContent{print("Reasoning:\(reasoning)")}}catch{print("Error:\(error)")}
Streaming Example
letprompt="What is the Manhattan project?"letparameters=ChatCompletionParameters( messages:[.init(role:.user, content:.text(prompt))], model:.custom("deepseek-reasoner"))// Start the streamdo{letstream=tryawait service.startStreamedChat(parameters: parameters)fortryawaitresultin stream{letcontent= result.choices.first?.delta.content??""self.message+= content // Optional: Handle reasoning content if availableiflet reasoning= result.choices.first?.delta.reasoningContent{self.reasoningMessage+= reasoning}}}catchAPIError.responseUnsuccessful(let description,let statusCode){self.errorMessage="Network error with status code:\(statusCode) and description:\(description)"}catch{self.errorMessage= error.localizedDescription}
Notes
- The DeepSeek API is compatible with OpenAI's format but uses different model names
- Use .custom("deepseek-reasoner") to specify the DeepSeek model
- The
reasoningContentfield is optional and specific to DeepSeek's API - Error handling follows the same pattern as standard OpenAI requests.
For more inofrmation about theDeepSeek api visit itsdocumentation.

Gemini is now accessible from the OpenAI Library. Announcement .SwiftOpenAI support all OpenAI endpoints, however Please refer to Gemini documentation to understand which API's are currently compatible'
Gemini is now accessible through the OpenAI Library. See the announcementhere.SwiftOpenAI supports all OpenAI endpoints. However, please refer to theGemini documentation to understand which APIs are currently compatible."
You can instantiate aOpenAIService using your Gemini token like this...
letgeminiAPIKey="your_api_key"letbaseURL="https://generativelanguage.googleapis.com"letversion="v1beta"letservice=OpenAIServiceFactory.service( apiKey: apiKey, overrideBaseURL: baseURL, overrideVersion: version)
You can now create a chat request using the .custom model parameter and pass the model name as a string.
letparameters=ChatCompletionParameters( messages:[.init( role:.user, content: content)], model:.custom("gemini-1.5-flash"))letstream=tryawait service.startStreamedChat(parameters: parameters)
Open a PR for any proposed change pointing it tomain branch. Unit tests are highly appreciated ❤️
About
The most complete open-source Swift package for interacting with OpenAI's public API.
Topics
Resources
License
Contributing
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.

