Swift Examples - Anthropic

Service setup

Create an Anthropic service in the AIProxy dashboard

Follow the integration guide, selecting the Anthropic icon on the 'Create a New Service' form.

How to send an Anthropic message request

import AIProxy

/* Uncomment for BYOK use cases */
// let anthropicService = AIProxy.anthropicDirectService(
//     unprotectedAPIKey: "your-anthropic-key"
// )

/* Uncomment for all other production use cases */
// let anthropicService = AIProxy.anthropicService(
//     partialKey: "partial-key-from-your-developer-dashboard",
//     serviceURL: "service-url-from-your-developer-dashboard"
// )

do {
    let response = try await anthropicService.messageRequest(body: AnthropicMessageRequestBody(
        maxTokens: 1024,
        messages: [
            AnthropicInputMessage(content: [.text("hello world")], role: .user)
        ],
        model: "claude-3-5-sonnet-20240620"
    ))
    for content in response.content {
        switch content {
        case .text(let message):
            print("Claude sent a message: \(message)")
        case .toolUse(id: _, name: let toolName, input: let toolInput):
            print("Claude used a tool \(toolName) with input: \(toolInput)")
        }
    }
}  catch AIProxyError.unsuccessfulRequest(let statusCode, let responseBody) {
    print("Received \(statusCode) status code with response body: \(responseBody)")
} catch {
    print("Could not create an Anthropic message: \(error.localizedDescription)")
}

How to use streaming text messages with Anthropic

import AIProxy

/* Uncomment for BYOK use cases */
// let anthropicService = AIProxy.anthropicDirectService(
//     unprotectedAPIKey: "your-anthropic-key"
// )

/* Uncomment for all other production use cases */
// let anthropicService = AIProxy.anthropicService(
//     partialKey: "partial-key-from-your-developer-dashboard",
//     serviceURL: "service-url-from-your-developer-dashboard"
// )

do {
    let requestBody = AnthropicMessageRequestBody(
        maxTokens: 1024,
        messages: [
            .init(
                content: [.text("hello world")],
                role: .user
            )
        ],
        model: "claude-3-5-sonnet-20240620"
    )

    let stream = try await anthropicService.streamingMessageRequest(body: requestBody)
    for try await chunk in stream {
        switch chunk {
        case .text(let text):
            print(text)
        case .toolUse(name: let toolName, input: let toolInput):
            print("Claude wants to call tool \(toolName) with input \(toolInput)")
        }
    }
}  catch AIProxyError.unsuccessfulRequest(let statusCode, let responseBody) {
    print("Received non-200 status code: \(statusCode) with response body: \(responseBody)")
} catch {
    print("Could not use Anthropic's message stream: \(error.localizedDescription)")
}

How to use streaming tool calls with Anthropic

import AIProxy

/* Uncomment for BYOK use cases */
// let anthropicService = AIProxy.anthropicDirectService(
//     unprotectedAPIKey: "your-anthropic-key"
// )

/* Uncomment for all other production use cases */
// let anthropicService = AIProxy.anthropicService(
//     partialKey: "partial-key-from-your-developer-dashboard",
//     serviceURL: "service-url-from-your-developer-dashboard"
// )

do {
    let requestBody = AnthropicMessageRequestBody(
        maxTokens: 1024,
        messages: [
            .init(
                content: [.text("What is nvidia's stock price?")],
                role: .user
            )
        ],
        model: "claude-3-5-sonnet-20240620",
        tools: [
            .init(
                description: "Call this function when the user wants a stock symbol",
                inputSchema: [
                    "type": "object",
                    "properties": [
                        "ticker": [
                            "type": "string",
                            "description": "The stock ticker symbol, e.g. AAPL for Apple Inc."
                        ]
                    ],
                    "required": ["ticker"]
                ],
                name: "get_stock_symbol"
            )
        ]
    )

    let stream = try await anthropicService.streamingMessageRequest(body: requestBody)
    for try await chunk in stream {
        switch chunk {
        case .text(let text):
            print(text)
        case .toolUse(name: let toolName, input: let toolInput):
            print("Claude wants to call tool \(toolName) with input \(toolInput)")
        }
    }
    print("Done with stream")
}  catch AIProxyError.unsuccessfulRequest(let statusCode, let responseBody) {
    print("Received non-200 status code: \(statusCode) with response body: \(responseBody)")
} catch {
    print(error.localizedDescription)
}

How to send an image to Anthropic

Use UIImage in place of NSImage for iOS apps:

import AIProxy

guard let image = NSImage(named: "marina") else {
    print("Could not find an image named 'marina' in your app assets")
    return
}

guard let jpegData = AIProxy.encodeImageAsJpeg(image: image, compressionQuality: 0.6) else {
    print("Could not convert image to jpeg")
    return
}

/* Uncomment for BYOK use cases */
// let anthropicService = AIProxy.anthropicDirectService(
//     unprotectedAPIKey: "your-anthropic-key"
// )

/* Uncomment for all other production use cases */
// let anthropicService = AIProxy.anthropicService(
//     partialKey: "partial-key-from-your-developer-dashboard",
//     serviceURL: "service-url-from-your-developer-dashboard"
// )

do {
    let response = try await anthropicService.messageRequest(body: AnthropicMessageRequestBody(
        maxTokens: 1024,
        messages: [
            AnthropicInputMessage(content: [
                .text("Provide a very short description of this image"),
                .image(mediaType: .jpeg, data: jpegData.base64EncodedString())
            ], role: .user)
        ],
        model: "claude-3-5-sonnet-20240620"
    ))
    for content in response.content {
        switch content {
        case .text(let message):
            print("Claude sent a message: \(message)")
        case .toolUse(id: _, name: let toolName, input: let toolInput):
            print("Claude used a tool \(toolName) with input: \(toolInput)")
        }
    }
}  catch AIProxyError.unsuccessfulRequest(let statusCode, let responseBody) {
    print("Received \(statusCode) status code with response body: \(responseBody)")
} catch {
    print("Could not send a multi-modal message to Anthropic: \(error.localizedDescription)")
}

How to use the tools API with Anthropic

import AIProxy

/* Uncomment for BYOK use cases */
// let anthropicService = AIProxy.anthropicDirectService(
//     unprotectedAPIKey: "your-anthropic-key"
// )

/* Uncomment for all other production use cases */
// let anthropicService = AIProxy.anthropicService(
//     partialKey: "partial-key-from-your-developer-dashboard",
//     serviceURL: "service-url-from-your-developer-dashboard"
// )

do {
    let requestBody = AnthropicMessageRequestBody(
        maxTokens: 1024,
        messages: [
            .init(
                content: [.text("What is nvidia's stock price?")],
                role: .user
            )
        ],
        model: "claude-3-5-sonnet-20240620",
        tools: [
            .init(
                description: "Call this function when the user wants a stock symbol",
                inputSchema: [
                    "type": "object",
                    "properties": [
                        "ticker": [
                            "type": "string",
                            "description": "The stock ticker symbol, e.g. AAPL for Apple Inc."
                        ]
                    ],
                    "required": ["ticker"]
                ],
                name: "get_stock_symbol"
            )
        ]
    )
    let response = try await anthropicService.messageRequest(body: requestBody)
    for content in response.content {
        switch content {
        case .text(let message):
            print("Claude sent a message: \(message)")
        case .toolUse(id: _, name: let toolName, input: let toolInput):
            print("Claude used a tool \(toolName) with input: \(toolInput)")
        }
    }
}  catch AIProxyError.unsuccessfulRequest(let statusCode, let responseBody) {
    print("Received \(statusCode) status code with response body: \(responseBody)")
} catch {
    print("Could not create Anthropic message with tool call: \(error.localizedDescription)")
}

How to use Anthropic's pdf support in a buffered chat completion

This snippet includes a pdf mydocument.pdf in the Anthropic request. Adjust the filename to match the pdf included in your Xcode project. The snippet expects the pdf in the app bundle.

import AIProxy

/* Uncomment for BYOK use cases */
// let anthropicService = AIProxy.anthropicDirectService(
//     unprotectedAPIKey: "your-anthropic-key"
// )

/* Uncomment for all other production use cases */
// let anthropicService = AIProxy.anthropicService(
//     partialKey: "partial-key-from-your-developer-dashboard",
//     serviceURL: "service-url-from-your-developer-dashboard"
// )

guard let pdfFileURL = Bundle.main.url(forResource: "mydocument", withExtension: "pdf"),
        let pdfData = try? Data(contentsOf: pdfFileURL)
else {
    print("""
            Drop mydocument.pdf file into your Xcode project first.
            """)
    return
}

do {
    let response = try await anthropicService.messageRequest(body: AnthropicMessageRequestBody(
        maxTokens: 1024,
        messages: [
            AnthropicInputMessage(content: [.pdf(data: pdfData.base64EncodedString())], role: .user),
            AnthropicInputMessage(content: [.text("Summarize this")], role: .user)
        ],
        model: "claude-3-5-sonnet-20241022"
    ))
    for content in response.content {
        switch content {
        case .text(let message):
            print("Claude sent a message: \(message)")
        case .toolUse(id: _, name: let toolName, input: let toolInput):
            print("Claude used a tool \(toolName) with input: \(toolInput)")
        }
    }
} catch AIProxyError.unsuccessfulRequest(let statusCode, let responseBody) {
    print("Received non-200 status code: \(statusCode) with response body: \(responseBody)")
} catch {
    print("Could not use Anthropic's buffered pdf support: \(error.localizedDescription)")
}

How to use Anthropic's pdf support in a streaming chat completion

This snippet includes a pdf mydocument.pdf in the Anthropic request. Adjust the filename to match the pdf included in your Xcode project. The snippet expects the pdf in the app bundle.

import AIProxy

/* Uncomment for BYOK use cases */
// let anthropicService = AIProxy.anthropicDirectService(
//     unprotectedAPIKey: "your-anthropic-key"
// )

/* Uncomment for all other production use cases */
// let anthropicService = AIProxy.anthropicService(
//     partialKey: "partial-key-from-your-developer-dashboard",
//     serviceURL: "service-url-from-your-developer-dashboard"
// )

guard let pdfFileURL = Bundle.main.url(forResource: "mydocument", withExtension: "pdf"),
        let pdfData = try? Data(contentsOf: pdfFileURL)
else {
    print("""
            Drop mydocument.pdf file into your Xcode project first.
            """)
    return
}

do {
    let stream = try await anthropicService.streamingMessageRequest(body: AnthropicMessageRequestBody(
        maxTokens: 1024,
        messages: [
            AnthropicInputMessage(content: [.pdf(data: pdfData.base64EncodedString())], role: .user),
            AnthropicInputMessage(content: [.text("Summarize this")], role: .user)
        ],
        model: "claude-3-5-sonnet-20241022"
    ))
    for try await chunk in stream {
        switch chunk {
        case .text(let text):
            print(text)
        case .toolUse(name: let toolName, input: let toolInput):
            print("Claude wants to call tool \(toolName) with input \(toolInput)")
        }
    }
    print("Done with stream")
} catch AIProxyError.unsuccessfulRequest(let statusCode, let responseBody) {
    print("Received non-200 status code: \(statusCode) with response body: \(responseBody)")
} catch {
    print("Could not use Anthropic's streaming pdf support: \(error.localizedDescription)")
}