Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ on:

jobs:
test-ios:
runs-on: macos-14
runs-on: macos-15

steps:
- uses: actions/checkout@v4

- name: Build and test
run: xcodebuild test -scheme LLMChatOpenAI -destination 'platform=iOS Simulator,name=iPhone 15 Pro'
run: xcodebuild test -scheme LLMChatOpenAI -destination 'platform=iOS Simulator,name=iPhone 16 Pro'

test-macos:
runs-on: macos-14
runs-on: macos-15

steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ concurrency:

jobs:
deploy:
runs-on: macos-14
runs-on: macos-15

environment:
name: github-pages
Expand Down
4 changes: 2 additions & 2 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ let package = Package(
targets: ["LLMChatOpenAI"]),
],
dependencies: [
.package(url: "https://github.com/kevinhermawan/swift-json-schema.git", exact: "1.0.3"),
.package(url: "https://github.com/kevinhermawan/swift-json-schema.git", .upToNextMajor(from: "2.0.1")),
.package(url: "https://github.com/apple/swift-docc-plugin.git", .upToNextMajor(from: "1.4.3"))
],
targets: [
Expand Down
4 changes: 2 additions & 2 deletions Playground/Playground.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
Expand Down Expand Up @@ -320,7 +320,7 @@
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Playground/Playground/ViewModels/AppViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ enum ServiceProvider: String, CaseIterable {
case groq = "Groq"
}

@MainActor
@Observable
final class AppViewModel {
var stream: Bool = false
var stream: Bool = true
var openaiAPIKey: String = ""
var openRouterAPIKey: String = ""
var groqAPIKey: String = ""
Expand Down
22 changes: 11 additions & 11 deletions Sources/LLMChatOpenAI/ChatCompletion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation

/// A struct that represents a chat completion response.
public struct ChatCompletion: Decodable {
public struct ChatCompletion: Decodable, Sendable {
/// A unique identifier for the chat completion.
public let id: String

Expand All @@ -35,7 +35,7 @@ public struct ChatCompletion: Decodable {
/// The usage statistics for the completion request.
public let usage: Usage?

public struct Choice: Decodable {
public struct Choice: Decodable, Sendable {
/// The index of the choice in the list of choices.
public let index: Int

Expand All @@ -49,7 +49,7 @@ public struct ChatCompletion: Decodable {
/// Log probability information for the choice.
public let logprobs: Logprobs?

public struct Message: Decodable {
public struct Message: Decodable, Sendable {
/// The role of the author of this message.
public let role: String

Expand All @@ -62,7 +62,7 @@ public struct ChatCompletion: Decodable {
/// An array of ``ToolCall`` generated by the model.
public let toolCalls: [ToolCall]?

public struct ToolCall: Codable {
public struct ToolCall: Decodable, Sendable {
/// The ID of the tool call.
public let id: String

Expand All @@ -72,7 +72,7 @@ public struct ChatCompletion: Decodable {
/// The function that the model called.
public let function: Function

public struct Function: Codable {
public struct Function: Codable, Sendable {
/// The name of the function to call.
public let name: String

Expand All @@ -91,7 +91,7 @@ public struct ChatCompletion: Decodable {
}

/// The reason the model stopped generating tokens.
public enum FinishReason: String, Decodable {
public enum FinishReason: String, Decodable, Sendable {
/// The model reached a natural stop point or a provided stop sequence.
case stop

Expand All @@ -105,14 +105,14 @@ public struct ChatCompletion: Decodable {
case contentFilter = "content_filter"
}

public struct Logprobs: Decodable {
public struct Logprobs: Decodable, Sendable {
/// An array of message content tokens with log probability information.
public let content: [TokenInfo]?

/// An array of message refusal tokens with log probability information.
public let refusal: [TokenInfo]?

public struct TokenInfo: Decodable {
public struct TokenInfo: Decodable, Sendable {
/// The token.
public let token: String

Expand Down Expand Up @@ -144,7 +144,7 @@ public struct ChatCompletion: Decodable {
}
}

public struct Usage: Decodable {
public struct Usage: Decodable, Sendable {
/// Number of tokens in the generated completion.
public let completionTokens: Int

Expand All @@ -160,7 +160,7 @@ public struct ChatCompletion: Decodable {
/// Breakdown of tokens used in the prompt.
public let promptTokensDetails: PromptTokensDetails?

public struct CompletionTokensDetails: Decodable {
public struct CompletionTokensDetails: Decodable, Sendable {
/// Tokens generated by the model for reasoning.
public let reasoningTokens: Int

Expand All @@ -169,7 +169,7 @@ public struct ChatCompletion: Decodable {
}
}

public struct PromptTokensDetails: Decodable {
public struct PromptTokensDetails: Decodable, Sendable {
/// Cached tokens present in the prompt.
public let cachedTokens: Int

Expand Down
22 changes: 11 additions & 11 deletions Sources/LLMChatOpenAI/ChatCompletionChunk.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation

/// A struct that represents a streamed chunk of a chat completion response.
public struct ChatCompletionChunk: Decodable {
public struct ChatCompletionChunk: Decodable, Sendable {
/// A unique identifier for the chat completion. Each chunk has the same identifier.
public let id: String

Expand All @@ -35,7 +35,7 @@ public struct ChatCompletionChunk: Decodable {
/// Usage statistics for the completion request.
public let usage: Usage?

public struct Choice: Decodable {
public struct Choice: Decodable, Sendable {
/// The index of the choice in the list of choices.
public let index: Int

Expand All @@ -49,7 +49,7 @@ public struct ChatCompletionChunk: Decodable {
/// Log probability information for the choice.
public let logprobs: Logprobs?

public struct Delta: Decodable {
public struct Delta: Decodable, Sendable {
/// The role of the author of this message.
public let role: String?

Expand All @@ -62,7 +62,7 @@ public struct ChatCompletionChunk: Decodable {
/// An array of ``ToolCall`` generated by the model.
public var toolCalls: [ToolCall]?

public struct ToolCall: Decodable {
public struct ToolCall: Decodable, Sendable {
/// The ID of the tool call.
public let id: String?

Expand All @@ -72,7 +72,7 @@ public struct ChatCompletionChunk: Decodable {
/// The function that the model called.
public var function: Function?

public struct Function: Decodable {
public struct Function: Decodable, Sendable {
/// The name of the function to call.
public var name: String?

Expand All @@ -90,7 +90,7 @@ public struct ChatCompletionChunk: Decodable {
}

/// The reason the model stopped generating tokens.
public enum FinishReason: String, Decodable {
public enum FinishReason: String, Decodable, Sendable {
/// The model reached a natural stop point or a provided stop sequence.
case stop

Expand All @@ -104,14 +104,14 @@ public struct ChatCompletionChunk: Decodable {
case contentFilter = "content_filter"
}

public struct Logprobs: Decodable {
public struct Logprobs: Decodable, Sendable {
/// An array of message content tokens with log probability information.
public let content: [TokenInfo]?

/// An array of message refusal tokens with log probability information.
public let refusal: [TokenInfo]?

public struct TokenInfo: Decodable {
public struct TokenInfo: Decodable, Sendable {
/// The token.
public let token: String

Expand All @@ -136,7 +136,7 @@ public struct ChatCompletionChunk: Decodable {
}
}

public struct Usage: Decodable {
public struct Usage: Decodable, Sendable {
/// Number of tokens in the generated completion.
public let completionTokens: Int?

Expand All @@ -152,7 +152,7 @@ public struct ChatCompletionChunk: Decodable {
/// Breakdown of tokens used in the prompt.
public let promptTokensDetails: PromptTokensDetails?

public struct CompletionTokensDetails: Decodable {
public struct CompletionTokensDetails: Decodable, Sendable {
/// Tokens generated by the model for reasoning.
public let reasoningTokens: Int

Expand All @@ -161,7 +161,7 @@ public struct ChatCompletionChunk: Decodable {
}
}

public struct PromptTokensDetails: Decodable {
public struct PromptTokensDetails: Decodable, Sendable {
/// Cached tokens present in the prompt.
public let cachedTokens: Int

Expand Down
8 changes: 4 additions & 4 deletions Sources/LLMChatOpenAI/ChatMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation

/// A struct that represents a message in a chat conversation.
public struct ChatMessage: Encodable {
public struct ChatMessage: Encodable, Sendable {
/// The role of the message's author.
public let role: Role

Expand All @@ -19,20 +19,20 @@ public struct ChatMessage: Encodable {
/// Provides the model information to differentiate between participants of the same role.
public let name: String?

public enum Role: String, Codable {
public enum Role: String, Encodable, Sendable {
case system
case user
case assistant
}

public enum Content: Encodable {
public enum Content: Encodable, Sendable {
/// Text content of the message.
case text(String)

/// Image content of the message.
case image(String, detail: ImageDetail = .auto)

public enum ImageDetail: String, Encodable, CaseIterable {
public enum ImageDetail: String, Encodable, Sendable, CaseIterable {
/// High detail mode. The model first sees the low res image (using 85 tokens) and then creates detailed crops using 170 tokens for each 512px x 512px tile.
case high

Expand Down
8 changes: 4 additions & 4 deletions Sources/LLMChatOpenAI/ChatOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Foundation
import JSONSchema

/// A struct that represents the options of a chat completion request.
public struct ChatOptions: Encodable {
public struct ChatOptions: Encodable, Sendable {
/// 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.
public let frequencyPenalty: Double?
Expand Down Expand Up @@ -118,7 +118,7 @@ public struct ChatOptions: Encodable {
self.user = user
}

public struct ResponseFormat: Encodable {
public struct ResponseFormat: Encodable, Sendable {
/// The type of response format being defined.
public let type: ResponseType

Expand All @@ -145,13 +145,13 @@ public struct ChatOptions: Encodable {
case jsonSchema = "json_schema"
}

public enum ResponseType: String, Codable, CaseIterable {
public enum ResponseType: String, Codable, Sendable, CaseIterable {
case text
case jsonObject = "json_object"
case jsonSchema = "json_schema"
}

public struct Schema: Encodable {
public struct Schema: Encodable, Sendable {
/// The name of the response format.
/// Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64.
public let name: String
Expand Down
2 changes: 1 addition & 1 deletion Sources/LLMChatOpenAI/LLMChatOpenAI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation

/// A struct that facilitates interactions with OpenAI and OpenAI-compatible chat completion APIs.
public struct LLMChatOpenAI {
public struct LLMChatOpenAI: Sendable {
private let apiKey: String
private let endpoint: URL
private var headers: [String: String]? = nil
Expand Down
2 changes: 1 addition & 1 deletion Sources/LLMChatOpenAI/LLMChatOpenAIError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation

/// An enum that represents errors from the chat completion request.
public enum LLMChatOpenAIError: LocalizedError {
public enum LLMChatOpenAIError: LocalizedError, Sendable {
/// A case that represents a server-side error response.
///
/// - Parameter message: The error message from the server.
Expand Down