Skip to content
Open
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
58 changes: 54 additions & 4 deletions Sources/AnyLanguageModel/Models/SystemLanguageModel.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#if canImport(FoundationModels)
import CoreGraphics
import FoundationModels
import Foundation
import ImageIO
import PartialJSONDecoder

import JSONSchema
Expand Down Expand Up @@ -55,6 +57,21 @@
self.systemModel = FoundationModels.SystemLanguageModel(adapter: adapter, guardrails: guardrails)
}

/// The size of the context window in tokens.
nonisolated public var contextSize: Int {
systemModel.contextSize
}

/// Whether the model accepts image input.
nonisolated public var supportsImageInput: Bool {
#if compiler(>=6.4) && !os(tvOS) && !os(watchOS)
if #available(macOS 27.0, iOS 27.0, visionOS 27.0, *) {
return systemModel.capabilities.contains(.vision)
}
#endif
return false
}

/// The availability status for the system language model.
nonisolated public var availability: Availability<UnavailableReason> {
switch systemModel.availability {
Expand Down Expand Up @@ -390,8 +407,9 @@
options.temperature = temperature
}

// Note: FoundationModels.GenerationOptions may not have all properties
// Only set those that are available
if let maximumResponseTokens = self.maximumResponseTokens {
options.maximumResponseTokens = maximumResponseTokens
}

return options
}
Expand Down Expand Up @@ -754,14 +772,46 @@
content: fmContent
)
)
case .image:
// FoundationModels Transcript does not support image segments
case .image(let imageSegment):
#if compiler(>=6.4) && !os(tvOS)
if #available(macOS 27.0, iOS 27.0, visionOS 27.0, watchOS 27.0, *) {
guard let fmImage = FoundationModels.Transcript.ImageAttachment(imageSegment) else {
return nil
}
return .attachment(
.init(
id: imageSegment.id,
content: .image(fmImage)
)
)
}
#endif
return nil
}
}
}
}

#if compiler(>=6.4) && !os(tvOS)
@available(macOS 27.0, iOS 27.0, visionOS 27.0, watchOS 27.0, *)
extension FoundationModels.Transcript.ImageAttachment {
fileprivate init?(_ imageSegment: Transcript.ImageSegment) {
switch imageSegment.source {
case .url(let url):
self.init(imageURL: url)
case .data(let data, _):
guard
let imageSource = CGImageSourceCreateWithData(data as CFData, nil),
let cgImage = CGImageSourceCreateImageAtIndex(imageSource, 0, nil)
else {
return nil
}
self.init(cgImage)
}
}
}
#endif

@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *)
extension Array where Element == Transcript.ToolDefinition {
fileprivate func toFoundationModels() -> [FoundationModels.Transcript.ToolDefinition] {
Expand Down