Skip to content

Commit

Permalink
Merge pull request #62 from fumito-ito/feature/pdf
Browse files Browse the repository at this point in the history
PDF support
  • Loading branch information
fumito-ito authored Nov 5, 2024
2 parents 54de9a9 + c7426bd commit 3fbc81a
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public enum ContentType: String {
case toolUse = "tool_use"
/// result of tool use
case toolResult = "tool_result"
/// document, like pdf
case document
}

/// The content of message.
Expand All @@ -31,18 +33,21 @@ public enum Content {
case image(ImageContent)
case toolUse(ToolUseContent)
case toolResult(ToolResultContent)
case document(DocumentContent)

/// The type of content block.
public var contentType: ContentType {
switch self {
case .text:
return ContentType.text
return .text
case .image:
return ContentType.image
return .image
case .toolUse:
return ContentType.toolUse
return .toolUse
case .toolResult:
return ContentType.toolResult
return .toolResult
case .document:
return .document
}
}
}
Expand Down Expand Up @@ -92,6 +97,10 @@ extension Content: Encodable {
if toolResult.isError != nil {
try container.encode(toolResult.isError, forKey: .isError)
}
case let .document(document):
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.contentType.rawValue, forKey: .type)
try container.encode(document, forKey: .source)
}
}
}
Expand All @@ -114,6 +123,9 @@ extension Content: Decodable {
self = .toolUse(content)
case .toolResult:
fatalError("ContentType: `tool_result` is only used by user, not by assistant")
case .document:
let document = try container.decode(DocumentContent.self, forKey: .source)
self = .document(document)
case .none:
throw ClientError.failedToParseContentType(contentTypeString)
}
Expand Down
42 changes: 42 additions & 0 deletions Sources/AnthropicSwiftSDK/Entity/Content/DocumentContent.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// DocumentContent.swift
// AnthropicSwiftSDK
//
// Created by 伊藤史 on 2024/11/05.
//
import Foundation

public struct DocumentContent {
public enum DocumentContentType: String, Codable {
case base64
}

public enum DocumentContentMediaType: String, Codable {
case pdf = "application/pdf"
}

public let type: DocumentContentType
public let mediaType: DocumentContentMediaType
public let data: Data

public init(type: DocumentContentType, mediaType: DocumentContentMediaType, data: Data) {
self.type = type
self.mediaType = mediaType
self.data = data
}
}

extension DocumentContent: Codable {
enum CodingKeys: String, CodingKey {
case type
case mediaType = "media_type"
case data
}

public init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.type = try container.decode(DocumentContent.DocumentContentType.self, forKey: .type)
self.mediaType = try container.decode(DocumentContent.DocumentContentMediaType.self, forKey: .mediaType)
self.data = try container.decode(Data.self, forKey: .data)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,8 @@ public enum BetaFeatures: String, CaseIterable {
///
/// https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching
case promptCaching = "prompt-caching-2024-07-31"
/// PDF Support (beta)
///
/// https://docs.anthropic.com/en/docs/build-with-claude/pdf-support
case pdfSupport = "pdfs-2024-09-25"
}
20 changes: 20 additions & 0 deletions Tests/AnthropicSwiftSDKTests/Entity/ContentTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,26 @@ final class ContentTests: XCTestCase {
)
}

func testEncodeContentDocument() throws {
let expect = Content.document(
.init(
type: .base64,
mediaType: .pdf,
data: "data".data(using: .utf8)!
)
)

let dictionary = try XCTUnwrap(expect.toDictionary(encoder))
XCTAssertEqual(dictionary["type"] as! String, "document")
let source = try XCTUnwrap(dictionary["source"] as? [String: Any])
XCTAssertEqual(source["type"] as! String, "base64")
XCTAssertEqual(source["media_type"] as! String, "application/pdf")
XCTAssertEqual(
source["data"] as! String,
"data".data(using: .utf8)!.base64EncodedString()
)
}

func testEncodeContentToolResult() throws {
let expect = Content.toolResult(
.init(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ final class AnthropicAPIClientTests: XCTestCase {
XCTAssertEqual(headers!["x-api-key"], "test-api-key")
XCTAssertEqual(headers!["anthropic-version"], "2023-06-01")
XCTAssertEqual(headers!["Content-Type"], "application/json")
XCTAssertEqual(headers!["anthropic-beta"], "message-batches-2024-09-24,computer-use-2024-10-22,prompt-caching-2024-07-31")
XCTAssertEqual(headers!["anthropic-beta"], "message-batches-2024-09-24,computer-use-2024-10-22,prompt-caching-2024-07-31,pdfs-2024-09-25")

expectation.fulfill()
}, nil)
Expand All @@ -90,7 +90,7 @@ final class AnthropicAPIClientTests: XCTestCase {
XCTAssertEqual(headers!["x-api-key"], "test-api-key")
XCTAssertEqual(headers!["anthropic-version"], "2023-06-01")
XCTAssertEqual(headers!["Content-Type"], "application/json")
XCTAssertEqual(headers!["anthropic-beta"], "message-batches-2024-09-24,computer-use-2024-10-22,prompt-caching-2024-07-31")
XCTAssertEqual(headers!["anthropic-beta"], "message-batches-2024-09-24,computer-use-2024-10-22,prompt-caching-2024-07-31,pdfs-2024-09-25")

expectation.fulfill()
}, nil)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ final class DefaultAnthropicHeaderProviderTests: XCTestCase {
let provider = DefaultAnthropicHeaderProvider(useBeta: true)
let headers = provider.getAnthropicAPIHeaders()

XCTAssertEqual(headers["anthropic-beta"], "message-batches-2024-09-24,computer-use-2024-10-22,prompt-caching-2024-07-31")
XCTAssertEqual(headers["anthropic-beta"], "message-batches-2024-09-24,computer-use-2024-10-22,prompt-caching-2024-07-31,pdfs-2024-09-25")
}

func testBetaHeaderShouldNotBeProvidedIfUseBeta() {
Expand Down

0 comments on commit 3fbc81a

Please sign in to comment.