Interact with Anthropic and Anthropic-compatible chat completion APIs in a simple and elegant way.
LLMChatAnthropic is a simple yet powerful Swift package that elegantly encapsulates the complexity of interacting with Anthropic and Anthropic-compatible chat completion APIs. It offers a complete set of Swift-idiomatic methods for sending chat completion requests and streaming responses.
You can add LLMChatAnthropic as a dependency to your project using Swift Package Manager by adding it to the dependencies value of your Package.swift.
dependencies: [ .package(url: "https://github.com/kevinhermawan/swift-llm-chat-anthropic.git", .upToNextMajor(from: "1.0.0")) ], targets: [ .target( /// ... dependencies: [.product(name: "LLMChatAnthropic", package: "swift-llm-chat-anthropic")]) ]
Alternatively, in Xcode:
- Open your project in Xcode.
- Click on
File->Swift Packages->Add Package Dependency... - Enter the repository URL:
https://github.com/kevinhermawan/swift-llm-chat-anthropic.git - Choose the version you want to add. You probably want to add the latest version.
- Click
Add Package.
You can find the documentation here: https://kevinhermawan.github.io/swift-llm-chat-anthropic/documentation/llmchatanthropic
import LLMChatAnthropic // Basic initialization let chat = LLMChatAnthropic(apiKey: "<YOUR_ANTHROPIC_API_KEY>") // Initialize with custom endpoint and headers let chat = LLMChatAnthropic( apiKey: "<YOUR_API_KEY>", endpoint: URL(string: "https://custom-api.example.com/v1/messages")!, headers: ["Custom-Header": "Value"] )
let messages = [ ChatMessage(role: .system, content: "You are a helpful assistant."), ChatMessage(role: .user, content: "What is the capital of Indonesia?") ] let task = Task { do { let completion = try await chat.send(model: "claude-3-5-sonnet", messages: messages) print(completion.content.first?.text ?? "No response") } catch { print(String(describing: error)) } } // To cancel completion task.cancel()
let messages = [ ChatMessage(role: .system, content: "You are a helpful assistant."), ChatMessage(role: .user, content: "What is the capital of Indonesia?") ] let task = Task { do { for try await chunk in chat.stream(model: "claude-3-5-sonnet", messages: messages) { if let text = chunk.delta?.text { print(text, terminator: "") } } } catch { print(String(describing: error)) } } // To cancel completion task.cancel()
let messages = [ ChatMessage( role: .user, content: [ .image("https://images.pexels.com/photos/45201/kitty-cat-kitten-pet-45201.jpeg"), // Also supports base64 strings .text("What is in this image?") ] ) ] Task { do { let completion = try await chat.send(model: "claude-3-5-sonnet", messages: messages) print(completion.content.first?.text ?? "") } catch { print(String(describing: error)) } }
To learn more about vision, check out the Anthropic documentation.
let messages = [ ChatMessage(role: .user, content: "Recommend a book similar to '1984'") ] let recommendBookTool = ChatOptions.Tool( name: "recommend_book", description: "Recommend a book based on a given book and genre", parameters: .object( properties: [ "reference_book": .string(description: "The name of a book the user likes"), "genre": .enum( description: "The preferred genre for the book recommendation", values: [.string("fiction"), .string("non-fiction")] ) ], required: ["reference_book", "genre"], additionalProperties: .boolean(false) ) ) let options = ChatOptions(tools: [recommendBookTool]) Task { do { let completion = try await chat.send(model: "claude-3-5-sonnet", messages: messages, options: options) if let toolInput = completion.content.first(where: { 0ドル.type == "tool_use" })?.toolInput { print(toolInput) } } catch { print(String(describing: error)) } }
To learn more about tool use, check out the Anthropic documentation.
let chat = LLMChatAnthropic( apiKey: "<YOUR_ANTHROPIC_API_KEY>", headers: ["anthropic-beta": "prompt-caching-2024年07月31日"] // Required ) let messages = [ ChatMessage(role: .system, content: "<YOUR_LONG_PROMPT>", cacheControl: .init(type: .ephemeral)), ChatMessage(role: .user, content: "What is the capital of Indonesia?") ] let task = Task { do { let completion = try await chat.send(model: "claude-3-5-sonnet", messages: messages) print(completion.content.first?.text ?? "No response") } catch { print(String(describing: error)) } }
To learn more about prompt caching, check out the Anthropic documentation.
let chat = LLMChatAnthropic( apiKey: "<YOUR_ANTHROPIC_API_KEY>", headers: ["anthropic-beta": "pdfs-2024年09月25日"] // Required ) let messages = [ ChatMessage(role: .user, content: [.text("Explain this document"), .document(document)]) ] let task = Task { do { let completion = try await chat.send(model: "claude-3-5-sonnet", messages: messages) print(completion.content.first?.text ?? "No response") } catch { print(String(describing: error)) } }
To learn more about PDF support, check out the Anthropic documentation.
LLMChatAnthropic provides structured error handling through the LLMChatAnthropicError enum. This enum contains three cases that represent different types of errors you might encounter:
let messages = [ ChatMessage(role: .system, content: "You are a helpful assistant."), ChatMessage(role: .user, content: "What is the capital of Indonesia?") ] do { let completion = try await chat.send(model: "claude-3-5-sonnet", messages: messages) print(completion.content.first?.text ?? "No response") } catch let error as LLMChatAnthropicError { switch error { case .serverError(let statusCode, let message): // Handle server-side errors (e.g., invalid API key, rate limits) print("Server Error [\(statusCode)]: \(message)") case .networkError(let error): // Handle network-related errors (e.g., no internet connection) print("Network Error: \(error.localizedDescription)") case .decodingError(let error): // Handle errors that occur when the response cannot be decoded print("Decoding Error: \(error.localizedDescription)") case .streamError: // Handle errors that occur when streaming responses print("Stream Error") case .cancelled: // Handle requests that are cancelled print("Request was cancelled") } } catch { // Handle any other errors print("An unexpected error occurred: \(error)") }
If you find LLMChatAnthropic helpful and would like to support its development, consider making a donation. Your contribution helps maintain the project and develop new features.
Your support is greatly appreciated! ❤️
Contributions are welcome! Please open an issue or submit a pull request if you have any suggestions or improvements.
This repository is available under the Apache License 2.0.