Swift Together AI
tldr; Link to the gist
import UIKit
import Foundation
@MainActor
class TogetherAIRequest {
private let apiKey = "YOUR_API_KEY"
private let apiUrl = "https://api.together.xyz/v1/chat/completions"
func sendRequest(prompt: String) async throws -> String {
let requestBody: [String: Any] = [
"model": "meta-llama/Llama-Vision-Free",
"messages": [["role": "user", "content": prompt]],
"stream": false
]
guard let jsonData = try? JSONSerialization.data(withJSONObject: requestBody, options: []) else {
throw NSError(domain: "SerializationError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Could not serialize request body"])
}
var request = URLRequest(url: URL(string: apiUrl)!)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.httpBody = jsonData
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse else {
throw NSError(domain: "HTTPError", code: 0, userInfo: [NSLocalizedDescriptionKey: "Invalid response"])
}
guard httpResponse.statusCode == 200 else {
throw NSError(domain: "HTTPError", code: httpResponse.statusCode, userInfo: [NSLocalizedDescriptionKey: "Invalid response"])
}
// Parse the JSON response
guard let jsonResponse = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
let choices = jsonResponse["choices"] as? [[String: Any]],
let firstChoice = choices.first,
let message = firstChoice["message"] as? [String: Any],
let content = message["content"] as? String else {
throw NSError(domain: "JSONError", code: 1, userInfo: [NSLocalizedDescriptionKey: "JSON parsing failed"])
}
return content
}
}
// Example usage
let togetherAIRequest = TogetherAIRequest()
let prompt = "List 20 fruits in alphabetical order "
Task {
do {
let content = try await togetherAIRequest.sendRequest(prompt: prompt)
print("Content: \(content)")
} catch {
print("Error: \(error.localizedDescription)")
}
}
Code Explanation
This Swift code defines a class TogetherAIRequest
that is used to send a request to a language model API provided by Together.xyz. The class is designed to interact with the API asynchronously, using Swift’s async and await syntax. Here’s a breakdown of the code:
Class Definition
@MainActor
class TogetherAIRequest {
private let apiKey = "YOUR_API_KEY"
private let apiUrl = "https://api.together.xyz/v1/chat/completions"
-
@MainActor
ensures that the class methods are executed on the main thread, which is necessary for UI updates. -
apiKey
is a private constant that holds the API key for authentication. -
apiUrl
is the URL endpoint for the API.
Method sendRequest
func sendRequest(prompt: String) async throws -> String {
let requestBody: [String: Any] = [
"model": "meta-llama/Llama-Vision-Free",
"messages": [["role": "user", "content": prompt]],
"stream": false
]
-
sendRequest
is an asynchronous method that takes a prompt as input and returns a String. -
requestBody
is a dictionary that represents the JSON payload to be sent to the API. It includes:-
"model"
: Specifies the model to use. -
"messages"
: An array of messages, where each message has a “role” (e.g., “user”) and “content” (the prompt). -
"stream"
: Set to false to receive the response as a single JSON object.
-
JSON Serialization
guard let jsonData = try? JSONSerialization.data(withJSONObject: requestBody, options: []) else {
throw NSError(domain: "SerializationError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Could not serialize request body"])
}
-
JSONSerialization
is used to convert therequestBody
dictionary into a JSON data object. -
The
requestBody
dictionary is serialized into JSON data. If serialization fails, an error is thrown.
URL Request Configuration
var request = URLRequest(url: URL(string: apiUrl)!)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.httpBody = jsonData
- A
URLRequest
object is created with the API URL. - The HTTP method is set to
"POST"
. - The
Content-Type
header is set to"application/json"
. - The
Authorization
header is set with the Bearer token using the API key. - The serialized JSON data is set as the HTTP body of the request.
Sending the Request
let (data, response) = try await URLSession.shared.data(for: request)
- The request is sent asynchronously using
URLSession.shared.data(for:)
, which returns the response data and the response object.
Response Validation
guard let httpResponse = response as? HTTPURLResponse else {
throw NSError(domain: "HTTPError", code: 0, userInfo: [NSLocalizedDescriptionKey: "Invalid response"])
}
guard httpResponse.statusCode == 200 else {
throw NSError(domain: "HTTPError", code: httpResponse.statusCode, userInfo: [NSLocalizedDescriptionKey: "Invalid response"])
}
- The response is checked to ensure it is an
HTTPURLResponse
. - The status code is checked to ensure it is
200
(OK). If not, an error is thrown.
JSON Parsing
guard let jsonResponse = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
let choices = jsonResponse["choices"] as? [[String: Any]],
let firstChoice = choices.first,
let message = firstChoice["message"] as? [String: Any],
let content = message["content"] as? String else {
throw NSError(domain: "JSONError", code: 1, userInfo: [NSLocalizedDescriptionKey: "JSON parsing failed"])
}
return content
- The response data is parsed from JSON into a dictionary.
- The code navigates through the JSON structure to extract the content of the first choice’s message.
- If any step in the parsing fails, an error is thrown.
- The extracted content is returned as a String.
Example Usage
let togetherAIRequest = TogetherAIRequest()
let prompt = "List 20 fruits in alphabetical order "
Task {
do {
let content = try await togetherAIRequest.sendRequest(prompt: prompt)
print("Content: \(content)")
} catch {
print("Error: \(error.localizedDescription)")
}
}
- An instance of TogetherAIRequest is created.
- A prompt is defined.
- An asynchronous task is created to send the request and handle the response.
- If the request is successful, the content is printed.
- If an error occurs, it is caught and its description is printed.
Conclusion
This code is a Swift implementation for sending a request to a language model API, handling the response, and extracting the content of the response. It uses asynchronous programming to ensure that the network request does not block the main thread, which is crucial for maintaining a responsive user interface in iOS applications.