iOS에서 OpenAI API 사용하기

  • iOS에서 SwiftUI 예시를 통해 OpenAI API를 사용하는 방법에 대해 알아보겠습니다.
  • 예시에서는 OpenAI GPT 모델을 통해 Chat 기능을 구현하지만, 다른 API도 비슷하게 사용하면됩니다.
  • MacPaw의 OpenAI SPM을 통해 보다 쉽게 구현 할 수 있었습니다.

OpenAI SPM 설치

ios-openai-gpt-api

OpenAI API 키 설정

ios-openai-gpt-api
  • 별도 plist 파일을 생성해 해당 Key를 넣어줍니다.
// Keys.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>openai</key>
    <string>APIKEY</string>
</dict>
</plist>
  • 민감한 정보이기에 gitignore에 추가해 git에 포함되지 않도록 합니다.
// .gitignore
Keys.plist

GPT로 Chat 기능 구현

  • 키값 디코딩을 위해 간단하게 모델을 만들어줍니다.
struct AiModel: Decodable {
    let openai: String
}
  • ViewModel의 init에서 OpenAI API Key를 다음과 같이 plist에서 불러오고, OpenAI 객체를 만듭니다.
  • OpenAI 객체로 GPT에 Request를 보내는 함수도 추가합니다.
@Observable class AiViewModel {
    var openAI: OpenAI?
    var respond = ""
    
    init() {
        guard let url = Bundle.main.url(forResource: "Keys", withExtension: "plist") else { return }
        
        do {
            let data = try Data(contentsOf: url)
            let keys = try PropertyListDecoder().decode(AiModel.self, from: data)
            openAI = OpenAI(apiToken: keys.openai)
        } catch {
            "Decoding error: \(error)".debug()
        }
    }

    func request(prompt: String) async {
        let query = ChatQuery(model: .gpt3_5Turbo_16k, messages: [
            Chat(role: .system, content: "사용자를 응원해줘"),
            Chat(role: .user, content: prompt)
        ])
        
        do {
            let result = try await openAI?.chats(query: query)
            respond = result?.choices.first?.message.content ?? ""
        } catch {
            print("AI error: \(error)")
        }
    }
}
  • 이제 View에서 ViewModel을 통해 OpenAI API를 사용합니다.
struct AiView: View {
    @State private var aiViewModel = AiViewModel()

    var body: some View {
        Text(aiViewModel.respond)
            .task {
                aiViewModel.request(prompt: "OpenAI API 사용하는 방법을 설명해줘")
            }
    }
}

OpenAI 패키지

  struct ChatQuery: Codable {
     public let model: Model
     public let messages: [Chat]
     public let functions: [ChatFunctionDeclaration]?
     public let temperature: Double?
     public let topP: Double?
     public let n: Int?
     public let stop: [String]?
     public let maxTokens: Int?
     public let presencePenalty: Double?
     public let frequencyPenalty: Double?
     public let logitBias: [String:Int]?
     public let user: String?
}
struct ChatResult: Codable, Equatable {
    public struct Choice: Codable, Equatable {
        public let index: Int
        public let message: Chat
        public let finishReason: String
    }
    
    public struct Usage: Codable, Equatable {
        public let promptTokens: Int
        public let completionTokens: Int
        public let totalTokens: Int
    }
    
    public let id: String
    public let object: String
    public let created: TimeInterval
    public let model: Model
    public let choices: [Choice]
    public let usage: Usage
}