A comprehensive, protocol-oriented Swift client for the Ollama API. This package provides a type-safe way to interact with Ollama's machine learning models, supporting all API endpoints with native Swift concurrency.
- Autonomous agents with web search capabilities
- Full Ollama API coverage (chat, generation, embeddings, model management)
- Native async/await and AsyncSequence support
- Type-safe API with comprehensive error handling
- Thread-safe implementation using Swift actors
- Automatic retry logic with exponential backoff
- Cross-platform (macOS, Linux, iOS)
- Zero external dependencies
- macOS 14+ / iOS 17+ / Linux
- Swift 5.9+
- Ollama installed and running
Add Swollama to your Package.swift:
dependencies: [ .package(url: "https://github.com/guitaripod/Swollama.git", from: "1.0.0") ]Or add via Xcode: File > Add Package Dependencies > https://github.com/guitaripod/Swollama.git
import Swollama let agent = OllamaAgent(webSearchAPIKey: "your_ollama_api_key") guard let model = OllamaModelName.parse("qwen2.5:3b") else { fatalError() } for try await event in agent.run( prompt: "What are the latest features in Swift 6?", model: model ) { switch event { case .thinking(let thought): print("Thinking: \(thought)") case .toolCall(let name, _): print("Using tool: \(name)") case .message(let answer): print("Answer: \(answer)") case .done: print("Complete") default: break } }import Swollama let client = OllamaClient() guard let model = OllamaModelName.parse("llama3.2") else { fatalError() } let responses = try await client.chat( messages: [ ChatMessage(role: .user, content: "Hello! How are you?") ], model: model ) for try await response in responses { print(response.message.content, terminator: "") }Interactive chat:
swollama chat llama3.2Autonomous agent:
swollama agent qwen2.5:3b --prompt "What's new in Swift?"Generate text:
swollama generate codellamaModel management:
swollama pull llama3.2 swollama list swollama show llama3.2 swollama delete old-modelComplete API documentation, examples, and feature guides:
let client = OllamaClient() guard let model = OllamaModelName.parse("llama3.2") else { fatalError() } let stream = try await client.generateText( prompt: "Explain quantum computing", model: model, options: GenerationOptions( temperature: 0.7, topP: 0.9, numPredict: 200 ) ) for try await response in stream { print(response.response, terminator: "") }let client = OllamaClient() guard let model = OllamaModelName.parse("nomic-embed-text") else { fatalError() } let response = try await client.generateEmbeddings( input: .single("Hello world"), model: model ) print("Vector dimensions: \(response.embeddings[0].count)")let tools = [ ToolDefinition( type: "function", function: FunctionDefinition( name: "get_weather", description: "Get current weather", parameters: JSONSchema( type: "object", properties: [ "location": JSONSchemaProperty(type: "string") ], required: ["location"] ) ) ) ] let stream = try await client.chat( messages: [ChatMessage(role: .user, content: "What's the weather in Paris?")], model: OllamaModelName.parse("llama3.2")!, options: ChatOptions(tools: tools) ) for try await response in stream { if let toolCalls = response.message.toolCalls { for call in toolCalls { print("Tool: \(call.function.name)") print("Args: \(call.function.arguments)") } } }Contributions are welcome. Please open an issue first to discuss major changes.
GPL-v3