Skip to content
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Always prefer text only content if possible in OpenAI Api
  • Loading branch information
intitni committed Oct 22, 2025
commit 6bfb0d157a7296664535987ba5a5e52fa3646a7d
38 changes: 32 additions & 6 deletions Tool/Sources/OpenAIService/APIs/OpenAIChatCompletionsService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,14 @@ public actor OpenAIChatCompletionsService: ChatCompletionsStreamAPI, ChatComplet

public struct RequestBody: Codable, Equatable {
public typealias ClaudeCacheControl = ClaudeChatCompletionsService.RequestBody.CacheControl

public struct GitHubCopilotCacheControl: Codable, Equatable, Sendable {
public var type: String

public init(type: String = "ephemeral") {
self.type = type
}
}

public struct Message: Codable, Equatable {
public enum MessageContent: Codable, Equatable {
Expand Down Expand Up @@ -457,21 +465,26 @@ public actor OpenAIChatCompletionsService: ChatCompletionsStreamAPI, ChatComplet
///
/// Deprecated.
public var function_call: MessageFunctionCall?
#warning("TODO: when to use it?")
/// Cache control for GitHub Copilot models.
public var copilot_cache_control: GitHubCopilotCacheControl?

public init(
role: MessageRole,
content: MessageContent,
name: String? = nil,
tool_calls: [MessageToolCall]? = nil,
tool_call_id: String? = nil,
function_call: MessageFunctionCall? = nil
function_call: MessageFunctionCall? = nil,
copilot_cache_control: GitHubCopilotCacheControl? = nil
) {
self.role = role
self.content = content
self.name = name
self.tool_calls = tool_calls
self.tool_call_id = tool_call_id
self.function_call = function_call
self.copilot_cache_control = copilot_cache_control
}
}

Expand Down Expand Up @@ -623,6 +636,7 @@ public actor OpenAIChatCompletionsService: ChatCompletionsStreamAPI, ChatComplet
Self.setupCustomBody(&request, model: model)
Self.setupAppInformation(&request)
Self.setupAPIKey(&request, model: model, apiKey: apiKey)
Self.setupGitHubCopilotVisionField(&request, model: model)
await Self.setupExtraHeaderFields(&request, model: model, apiKey: apiKey)
requestModifier?(&request)

Expand Down Expand Up @@ -771,6 +785,13 @@ public actor OpenAIChatCompletionsService: ChatCompletionsStreamAPI, ChatComplet
}
}
}

static func setupGitHubCopilotVisionField(_ request: inout URLRequest, model: ChatModel) {
guard model.format == .gitHubCopilot else { return }
if model.info.supportsImage {
request.setValue("true", forHTTPHeaderField: "copilot-vision-request")
}
}

static func setupCustomBody(_ request: inout URLRequest, model: ChatModel) {
switch model.format {
Expand Down Expand Up @@ -1242,12 +1263,17 @@ extension OpenAIChatCompletionsService.RequestBody {
}
}(),
content: {
// always prefer text only content if possible.
if supportsMultipartMessageContent {
return .contentParts(Self.convertContentPart(
content: message.content,
images: supportsImage ? message.images : [],
audios: supportsAudio ? message.audios : []
))
let images = supportsImage ? message.images : []
let audios = supportsAudio ? message.audios : []
if !images.isEmpty || !audios.isEmpty {
return .contentParts(Self.convertContentPart(
content: message.content,
images: images,
audios: audios
))
}
}
return .text(message.content)
}(),
Expand Down