Contents

william-weng/wwsimpleai_ollama

- [Simple connection to Ollama API functionality.](https://github.com/ollama/ollama/blob/main/docs/api.md)

[Introduction - 簡介](https://swiftpackageindex.com/William-Weng)

https://github.com/user-attachments/assets/bdbd6ac0-35ab-45c1-98ad-2846cab198fe

Installation with Swift Package Manager

dependencies: [
    .package(url: "https://github.com/William-Weng/WWSimpleAI_Ollama.git", .upToNextMajor(from: "1.2.1"))
]

[Paramater - 可用參數](https://william-weng.github.io/tags/docker/)

|函式|功能| |-|-| |baseURL|Ollama服務器的URL| |model|要使用的AI模型名稱| |jpegCompressionQuality|傳送圖片的壓縮率|

[Function - 可用函式](https://william-weng.github.io/2025/01/docker容器大家一起來當鯨魚搬運工吧/)

|函式|功能| |-|-| |version(type:using:separator:)|取得版本號| |models()|取得已下載模型列表| |document(model:isVerbose:)|取得模型文件說明| |copy(source:destination:)|複製模型| |delete(model:)|刪除已下載模型| |download(model:type:timeout:useStream:using:eparator:)|下載模型| |loadIntoMemory(api:isLoad:type:using:)|載入模型到記憶體的設定 - 開 / 關| |generate(prompt:context:type:timeout:format:images:options:useStream:using:)|一次性回應 (每次請求都是獨立的)| |talk(content:type:timeout:format:useStream:images:options:tools:using:)|說話模式 (會記住之前的對話內容)| |chat(messages:type:timeout:format:useStream:options:images:tools:using:)|對話模式 (會記住之前的對話內容)| |create(newModel:from:personality:type:useStream:using)|建立客製化模型| |embed(model:inputs:type:timeout:using:separator:)|從模型生成嵌入文字|

[Example](https://ezgif.com/video-to-webp)

import UIKit
import WWHUD
import WWEventSource
import WWSimpleAI_Ollama

final class ViewController: UIViewController {
    
    @IBOutlet weak var modelTextField: UITextField!
    @IBOutlet weak var resultTextView: UITextView!
    
    private let baseURL = "http://localhost:11434"
    
    private var isDismiss = false
    private var responseString: String = ""
    
    @IBAction func configureModel(_ sender: UIButton) {
        Task { await initLoadModelIntoMemory() }
    }
    
    @IBAction func generateDemo(_ sender: UIButton) {
        Task { await generate(prompt: "\(sender.title(for: .normal)!)") }
    }
    
    @IBAction func talkDemo(_ sender: UIButton) {
        Task { await talk(content: "\(sender.title(for: .normal)!)") }
    }
        
    @IBAction func generateLiveDemo(_ sender: UIButton) {
        liveGenerate(prompt: "\(sender.title(for: .normal)!)")
    }
}

// MARK: - WWEventSourceDelegate
extension ViewController: WWEventSource.Delegate {
    
    func serverSentEventsConnectionStatus(_ eventSource: WWEventSource, result: Result<WWEventSource.ConnectionStatus, any Error>) {
        sseStatusAction(eventSource: eventSource, result: result)
    }
    
    func serverSentEventsRawData(_ eventSource: WWEventSource, result: Result<WWEventSource.RawInformation, any Error>) {
        
        switch result {
        case .failure(let error): displayText(error)
        case .success(let rawInformation): sseRawString(eventSource: eventSource, rawInformation: rawInformation)
        }
    }
    
    func serverSentEvents(_ eventSource: WWEventSource, eventValue: WWEventSource.EventValue) {
        print(eventValue)
    }
}

private extension ViewController {
    
    func initLoadModelIntoMemory() async {
        
        displayHUD()
        configure()
        
        let result = await WWSimpleAI.Ollama.shared.loadIntoMemory(api: .generate)
        
        switch result {
        case .failure(let error): displayText(error.localizedDescription)
        case .success(let responseType): displayResponse(type: responseType)
        }
        
        WWHUD.shared.dismiss()
    }
    
    func generate(prompt: String) async {
        
        displayHUD()
        
        let result = await WWSimpleAI.Ollama.shared.generate(prompt: prompt)
        
        switch result {
        case .failure(let error): displayText(error.localizedDescription)
        case .success(let responseType): displayResponse(type: responseType)
        }
        
        WWHUD.shared.dismiss()
    }
    
    func talk(content: String) async {
        
        displayHUD()
        
        let result = await WWSimpleAI.Ollama.shared.talk(content: content)
        
        switch result {
        case .failure(let error): displayText(error.localizedDescription)
        case .success(let responseType): displayResponse(type: responseType)
        }
        
        WWHUD.shared.dismiss()
    }
    
    func liveGenerate(prompt: String) {
        
        displayHUD()
        
        let urlString = WWSimpleAI.Ollama.API.generate.url(for: baseURL)
        let json = """
        {
          "model": "\(WWSimpleAI.Ollama.shared.model)",
          "prompt": "\(prompt)",
          "stream": true
        }
        """
        
        _ = WWEventSource.shared.connect(httpMethod: .POST, delegate: self, urlString: urlString, httpBodyType: .string(json))
    }
}

// MARK: - 小工具
private extension ViewController {
    
    func configure() {
        
        guard let model = modelTextField.text else { return }
        
        WWSimpleAI.Ollama.shared.baseURL = baseURL
        WWSimpleAI.Ollama.shared.model = model
    }
    
    func displayResponse(type: WWSimpleAI.Ollama.ResponseType) {
        
        switch type {
        case .string(let string): displayText(string)
        case .data(let data): displayText(data)
        case .ndjson(let ndjson): displayText(ndjson)
        }
    }
    
    func displayHUD() {
        resultTextView.text = ""
        WWHUD.shared.display()
    }
    
    func displayText(_ value: Any?) {
        resultTextView.text = "\(value ?? "")"
    }
}

private extension ViewController {
    
    func sseStatusAction(eventSource: WWEventSource, result: Result<WWEventSource.ConnectionStatus, any Error>) {
        
        switch result {
        case .failure(let error):
            
            WWHUD.shared.dismiss()
            displayText(error.localizedDescription)
            isDismiss = true
            responseString = ""
            
        case .success(let status):
            
            switch status {
            case .connecting: isDismiss = false
            case .open: if !isDismiss { WWHUD.shared.dismiss(); isDismiss = true }
            case .closed: responseString = ""; isDismiss = false
            }
        }
    }
    
    func sseRawString(eventSource: WWEventSource, rawInformation: WWEventSource.RawInformation) {
        
        defer {
            resultTextView.text = responseString
            resultTextView._autoScrollToBottom()
        }
        
        if rawInformation.response.statusCode != 200 {
            responseString = rawInformation.data._string() ?? "\(rawInformation.response.statusCode)"; return
        }
        
        guard let jsonObject = rawInformation.data._jsonObject() as? [String: Any],
              let _response = jsonObject["response"] as? String
        else {
            return
        }
        
        responseString += _response
    }
}

Package Metadata

Repository: william-weng/wwsimpleai_ollama

Default branch: main

README: README.md