diff --git a/Sources/AnyLanguageModel/Generable.swift b/Sources/AnyLanguageModel/Generable.swift index 19437ed2..97ef472c 100644 --- a/Sources/AnyLanguageModel/Generable.swift +++ b/Sources/AnyLanguageModel/Generable.swift @@ -32,12 +32,6 @@ public protocol Generable: ConvertibleFromGeneratedContent, ConvertibleToGenerat static var generationSchema: GenerationSchema { get } } -// MARK: - Error - -/// Errors from converting generated content are ``GeneratedContentError``. -@available(*, deprecated, renamed: "GeneratedContentError") -public typealias GeneratedContentConversionError = GeneratedContentError - // MARK: - Macros /// Conforms a type to ``Generable`` protocol. diff --git a/Sources/AnyLanguageModel/Models/GeminiLanguageModel.swift b/Sources/AnyLanguageModel/Models/GeminiLanguageModel.swift index ba06a0c8..a193d9cb 100644 --- a/Sources/AnyLanguageModel/Models/GeminiLanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/GeminiLanguageModel.swift @@ -136,14 +136,6 @@ public struct GeminiLanguageModel: LanguageModel { } } - /// Deprecated. Use ``CustomGenerationOptions/Thinking`` instead. - @available(*, deprecated, renamed: "CustomGenerationOptions.Thinking") - public typealias Thinking = CustomGenerationOptions.Thinking - - /// Deprecated. Use ``CustomGenerationOptions/ServerTool`` instead. - @available(*, deprecated, renamed: "CustomGenerationOptions.ServerTool") - public typealias ServerTool = CustomGenerationOptions.ServerTool - public let baseURL: URL private let tokenProvider: @Sendable () -> String @@ -152,40 +144,6 @@ public struct GeminiLanguageModel: LanguageModel { public let model: String - /// The thinking mode for this model. - /// - /// - Important: This property is deprecated. Use ``GenerationOptions`` with - /// custom options instead: - /// ```swift - /// var options = GenerationOptions() - /// options[custom: GeminiLanguageModel.self] = .init(thinking: .dynamic) - /// ``` - @available(*, deprecated, message: "Use GenerationOptions with custom options instead") - public var thinking: Thinking { - get { _thinking } - set { _thinking = newValue } - } - - /// Internal storage for the deprecated thinking property. - internal var _thinking: CustomGenerationOptions.Thinking - - /// Server-side tools enabled for this model. - /// - /// - Important: This property is deprecated. Use ``GenerationOptions`` with - /// custom options instead: - /// ```swift - /// var options = GenerationOptions() - /// options[custom: GeminiLanguageModel.self] = .init(serverTools: [.googleSearch]) - /// ``` - @available(*, deprecated, message: "Use GenerationOptions with custom options instead") - public var serverTools: [CustomGenerationOptions.ServerTool] { - get { _serverTools } - set { _serverTools = newValue } - } - - /// Internal storage for the deprecated serverTools property. - internal var _serverTools: [CustomGenerationOptions.ServerTool] - private let httpSession: HTTPSession /// Creates a new Gemini language model. @@ -212,50 +170,6 @@ public struct GeminiLanguageModel: LanguageModel { self.tokenProvider = tokenProvider self.apiVersion = apiVersion self.model = model - self._thinking = .disabled - self._serverTools = [] - self.httpSession = session - } - - /// Creates a new Gemini language model with thinking and server tools configuration. - /// - /// - Parameters: - /// - baseURL: The base URL for the Gemini API. - /// - tokenProvider: A closure that provides the API key. - /// - apiVersion: The API version to use. - /// - model: The model identifier. - /// - thinking: The thinking mode configuration. - /// - serverTools: Server-side tools to enable. - /// - session: The HTTP session or client used for network requests. - /// - /// - Important: This initializer is deprecated. Use the initializer without - /// `thinking` and `serverTools` parameters, and pass these options through - /// ``GenerationOptions`` instead. - @available( - *, - deprecated, - message: "Use init without thinking/serverTools and pass them via GenerationOptions custom options" - ) - public init( - baseURL: URL = defaultBaseURL, - apiKey tokenProvider: @escaping @autoclosure @Sendable () -> String, - apiVersion: String = defaultAPIVersion, - model: String, - thinking: CustomGenerationOptions.Thinking = .disabled, - serverTools: [CustomGenerationOptions.ServerTool] = [], - session: HTTPSession = makeDefaultSession(), - ) { - var baseURL = baseURL - if !baseURL.path.hasSuffix("/") { - baseURL = baseURL.appendingPathComponent("") - } - - self.baseURL = baseURL - self.tokenProvider = tokenProvider - self.apiVersion = apiVersion - self.model = model - self._thinking = thinking - self._serverTools = serverTools self.httpSession = session } @@ -303,8 +217,8 @@ public struct GeminiLanguageModel: LanguageModel { ) async throws -> LanguageModelSession.Response where Content: Generable { // Extract effective configuration from custom options or fall back to model defaults let customOptions = options[custom: GeminiLanguageModel.self] - let effectiveThinking = customOptions?.thinking ?? _thinking - let effectiveServerTools = customOptions?.serverTools ?? _serverTools + let effectiveThinking = customOptions?.thinking ?? .disabled + let effectiveServerTools = customOptions?.serverTools ?? [] let effectiveJsonMode = customOptions?.jsonMode let url = @@ -469,8 +383,8 @@ public struct GeminiLanguageModel: LanguageModel { ) -> sending LanguageModelSession.ResponseStream where Content: Generable { // Extract effective configuration from custom options or fall back to model defaults let customOptions = options[custom: GeminiLanguageModel.self] - let effectiveThinking = customOptions?.thinking ?? _thinking - let effectiveServerTools = customOptions?.serverTools ?? _serverTools + let effectiveThinking = customOptions?.thinking ?? .disabled + let effectiveServerTools = customOptions?.serverTools ?? [] let effectiveJsonMode = customOptions?.jsonMode var streamURL = diff --git a/Sources/AnyLanguageModel/Models/LlamaLanguageModel.swift b/Sources/AnyLanguageModel/Models/LlamaLanguageModel.swift index 68c5ea1d..68e4f385 100644 --- a/Sources/AnyLanguageModel/Models/LlamaLanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/LlamaLanguageModel.swift @@ -25,10 +25,7 @@ import Foundation /// Use this model to generate text using GGUF models running directly with llama.cpp. /// /// ```swift - /// let model = LlamaLanguageModel( - /// modelPath: "/path/to/model.gguf", - /// contextSize: 2048 - /// ) + /// let model = LlamaLanguageModel(modelPath: "/path/to/model.gguf") /// ``` public final class LlamaLanguageModel: LanguageModel, @unchecked Sendable { /// The reason the model is unavailable. @@ -227,109 +224,8 @@ import Foundation #endif } - /// The context size for the model. - /// - /// - Important: This property is deprecated. - /// Use ``GenerationOptions`` with custom options instead: - /// ```swift - /// var options = GenerationOptions() - /// options[custom: LlamaLanguageModel.self] = .init(contextSize: 4096) - /// ``` - @available(*, deprecated, message: "Use GenerationOptions custom options instead") - public var contextSize: UInt32 { legacyDefaults.contextSize } - - /// The batch size for processing. - /// - /// - Important: This property is deprecated. - /// Use ``GenerationOptions`` with custom options instead: - /// ```swift - /// var options = GenerationOptions() - /// options[custom: LlamaLanguageModel.self] = .init(batchSize: 1024) - /// ``` - @available(*, deprecated, message: "Use GenerationOptions custom options instead") - public var batchSize: UInt32 { legacyDefaults.batchSize } - - /// The number of threads to use. - /// - /// - Important: This property is deprecated. - /// Use ``GenerationOptions`` with custom options instead: - /// ```swift - /// var options = GenerationOptions() - /// options[custom: LlamaLanguageModel.self] = .init(threads: 8) - /// ``` - /// custom options instead. - @available(*, deprecated, message: "Use GenerationOptions custom options instead") - public var threads: Int32 { legacyDefaults.threads } - - /// The random seed for generation. - /// - /// - Important: This property is deprecated. - /// Use ``GenerationOptions`` with custom options instead: - /// ```swift - /// var options = GenerationOptions() - /// options[custom: LlamaLanguageModel.self] = .init(seed: 42) - /// ``` - /// custom options instead. - @available(*, deprecated, message: "Use GenerationOptions custom options instead") - public var seed: UInt32 { legacyDefaults.seed } - - /// The temperature for sampling. - /// - /// - Important: This property is deprecated. - /// Use ``GenerationOptions`` with custom options instead: - /// ```swift - /// var options = GenerationOptions() - /// options[custom: LlamaLanguageModel.self] = .init(temperature: 0.6) - /// ``` - @available(*, deprecated, message: "Use GenerationOptions custom options instead") - public var temperature: Float { legacyDefaults.temperature } - - /// The top-K sampling parameter. - /// - /// - Important: This property is deprecated. - /// Use ``GenerationOptions`` with custom options instead: - /// ```swift - /// var options = GenerationOptions() - /// options[custom: LlamaLanguageModel.self] = .init(topK: 25) - /// ``` - @available(*, deprecated, message: "Use GenerationOptions custom options instead") - public var topK: Int32 { legacyDefaults.topK } - - /// The top-P (nucleus) sampling parameter. - /// - /// - Important: This property is deprecated. - /// Use ``GenerationOptions`` with custom options instead: - /// ```swift - /// var options = GenerationOptions() - /// options[custom: LlamaLanguageModel.self] = .init(topP: 0.9) - /// ``` - @available(*, deprecated, message: "Use GenerationOptions custom options instead") - public var topP: Float { legacyDefaults.topP } - - /// The repeat penalty for generation. - /// - /// - Important: This property is deprecated. - /// Use ``GenerationOptions`` with custom options instead: - /// ```swift - /// var options = GenerationOptions() - /// options[custom: LlamaLanguageModel.self] = .init(repeatPenalty: 1.2) - /// ``` - @available(*, deprecated, message: "Use GenerationOptions custom options instead") - public var repeatPenalty: Float { legacyDefaults.repeatPenalty } - - /// The number of tokens to consider for repeat penalty. - /// - /// - Important: This property is deprecated. - /// Use ``GenerationOptions`` with custom options instead: - /// ```swift - /// var options = GenerationOptions() - /// options[custom: LlamaLanguageModel.self] = .init(repeatLastN: 128) - /// ``` - @available(*, deprecated, message: "Use GenerationOptions custom options instead") - public var repeatLastN: Int32 { legacyDefaults.repeatLastN } - - /// Normalized legacy defaults used for deprecated properties. - private let legacyDefaults: ResolvedGenerationOptions + /// The default options that each request's options override. + private let defaultOptions: ResolvedGenerationOptions /// The minimum log level for llama.cpp output. /// @@ -733,43 +629,7 @@ import Foundation self.modelPath = modelPath self.gpuLayers = gpuLayers self.mmprojPath = mmprojPath - self.legacyDefaults = ResolvedGenerationOptions() - } - - /// Creates a Llama language model using legacy parameter defaults. - /// - /// - Important: This initializer is deprecated. - /// Use `init(modelPath:)` and configure per-request values via - /// ``GenerationOptions`` custom options instead. - /// - /// ```swift - /// let model = LlamaLanguageModel(modelPath: "/path/to/model.gguf") - /// var options = GenerationOptions() - /// options[custom: LlamaLanguageModel.self] = .init(contextSize: 4096) - /// - /// let session = LanguageModelSession(model: model) - /// session.respond(to: "Hello, world!", options: options) - /// ``` - @available( - *, - deprecated, - message: "Use init(modelPath:) and pass values via GenerationOptions custom options" - ) - public convenience init( - modelPath: String, - contextSize: UInt32 = 2048, - batchSize: UInt32 = 512, - threads: Int32 = Int32(ProcessInfo.processInfo.processorCount), - seed: UInt32 = UInt32.random(in: 0 ... UInt32.max), - temperature: Float = 0.8, - topK: Int32 = 40, - topP: Float = 0.95, - repeatPenalty: Float = 1.1, - repeatLastN: Int32 = 64 - ) { - // Deprecated: prefer setting these via GenerationOptions custom options. - // We intentionally ignore legacy parameters to avoid storing model-level state. - self.init(modelPath: modelPath) + self.defaultOptions = ResolvedGenerationOptions() } deinit { @@ -1455,7 +1315,7 @@ import Foundation var mtmdParams = mtmd_context_params_default() mtmdParams.use_gpu = gpuLayers != 0 mtmdParams.print_timings = false - mtmdParams.n_threads = legacyDefaults.threads + mtmdParams.n_threads = defaultOptions.threads guard let projector = mtmd_init_from_file(mmprojPath, loadedModel, mtmdParams) else { llama_model_free(loadedModel) throw LlamaLanguageModelError.modelLoadFailed @@ -1479,7 +1339,7 @@ import Foundation } private func resolvedOptions(from options: GenerationOptions) -> ResolvedGenerationOptions { - var base = legacyDefaults + var base = defaultOptions if let temp = options.temperature { base.temperature = Float(temp) } @@ -1494,7 +1354,7 @@ import Foundation /// Builds structured-generation defaults while honoring explicit overrides. private func resolvedStructuredOptions(from options: GenerationOptions) -> ResolvedGenerationOptions { - var base = legacyDefaults + var base = defaultOptions if let temp = options.temperature { base.temperature = Float(temp) } else { diff --git a/Tests/AnyLanguageModelTests/GeneratedContentErrorTests.swift b/Tests/AnyLanguageModelTests/GeneratedContentErrorTests.swift index 1c072fae..384a9f82 100644 --- a/Tests/AnyLanguageModelTests/GeneratedContentErrorTests.swift +++ b/Tests/AnyLanguageModelTests/GeneratedContentErrorTests.swift @@ -4,12 +4,12 @@ import AnyLanguageModel @Suite("Generated content errors") struct GeneratedContentErrorTests { - @Test func conversionErrorAliasPreservesEqualityAndHashing() { - let error = GeneratedContentConversionError.typeMismatch + @Test func errorsSupportEqualityAndHashing() { + let error = GeneratedContentError.typeMismatch #expect(error == .typeMismatch) #expect(error != .neverCannotBeInstantiated) - let errors: Set = [ + let errors: Set = [ .typeMismatch, .typeMismatch, .neverCannotBeInstantiated, ] #expect(errors.count == 2) diff --git a/Tests/AnyLanguageModelTests/LlamaLanguageModelTests.swift b/Tests/AnyLanguageModelTests/LlamaLanguageModelTests.swift index 07fd44c8..c095b4dd 100644 --- a/Tests/AnyLanguageModelTests/LlamaLanguageModelTests.swift +++ b/Tests/AnyLanguageModelTests/LlamaLanguageModelTests.swift @@ -21,14 +21,6 @@ import Testing let cpuOnlyModel = LlamaLanguageModel(modelPath: "/path/to/model.gguf", gpuLayers: 0) #expect(cpuOnlyModel.gpuLayers == 0) - #expect(customModel.contextSize == 2048) - #expect(customModel.batchSize == 512) - #expect(customModel.threads == Int32(ProcessInfo.processInfo.processorCount)) - #expect(customModel.temperature == 0.8) - #expect(customModel.topK == 40) - #expect(customModel.topP == 0.95) - #expect(customModel.repeatPenalty == 1.1) - #expect(customModel.repeatLastN == 64) } @Test func concurrentFirstRequests() async throws { @@ -155,31 +147,6 @@ import Testing #expect(defaults.mirostat == nil) } - @Test func deprecatedInitializerFallback() { - let legacy = LlamaLanguageModel( - modelPath: "/legacy/model.gguf", - contextSize: 1024, - batchSize: 128, - threads: 3, - seed: 7, - temperature: 0.65, - topK: 32, - topP: 0.88, - repeatPenalty: 1.02, - repeatLastN: 24 - ) - - // Deprecated initializer ignores parameters; defaults are used. - #expect(legacy.contextSize == 2048) - #expect(legacy.batchSize == 512) - #expect(legacy.threads == Int32(ProcessInfo.processInfo.processorCount)) - #expect(legacy.temperature == 0.8) - #expect(legacy.topK == 40) - #expect(legacy.topP == 0.95) - #expect(legacy.repeatPenalty == 1.1) - #expect(legacy.repeatLastN == 64) - } - @Test func logLevelConfiguration() { let originalLevel = LlamaLanguageModel.logLevel