「Qiita × Fast DOCTOR Health Tech Hackathon」に参加して、SwiftとGASでChatGPTを用いたiOSアプリを作成したのですが、ただ感想を書いてもつまらないので、
開発中に引っかかったポイント(SwiftとGASを用いたアプリ開発で気をつけたい点)と、作成したGASやChatGPTを用いたiOSアプリを作る上で、汎用性の高いSwiftの関数をご紹介します。
開発には、GASとXcodeを使用しました。
1. SwiftとGASを用いたアプリ開発で気をつけたい点
1.1. 文字の型に気をつける
swiftからGASにリクエストして、スプレッドシートなどを参照する際に、数字を扱う場合、swiftのリクエストは文字列型ですが、GASが取得してくる数字は数値型なので、GASがスプレッドシートなどから取得した値を文字列型に変換してからswiftのリクエストを処理する必要があります。
1.2. 日本語を扱う場合、エンコードとデコードが必要
swiftからGASに日本語を送って処理を行う場合、swiftで日本語をエンコードしてGASに送り、GASで受け取った日本語をデコードする必要があります。そうしないと空の文字列として処理されます。
GASからswiftに日本語を送る場合には、そのままで良いようです。
2. GASやChatGPTを用いたiOSアプリを作る上で、汎用性の高いswiftの関数
2.1. HTTP POSTリクエストを行う関数
以下の関数を用いる事で、HTTP POSTリクエストをiOSアプリから行えます。
struct HTTPRequest {
static func post(url: String, params: [String: String], completion: @escaping (Data?, URLResponse?, Error?) -> Void) {
guard let url = URL(string: url) else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = params
.map { key, value in "\(key)=\(value)" }
.joined(separator: "&")
.data(using: .utf8)
URLSession.shared.dataTask(with: request, completionHandler: completion).resume()
}
}
2.2. ChatGPTでテキスト生成する関数
以下の関数を用いる事で、swiftからOpenAI APIにリクエストを行いChatGPTでテキスト生成が出来ます。
この関数には、ChatGPTに記憶を持たせるアシストを組み込んでいませんが、リクエスト部分に含めることで実装可能です。
struct GPT3Message: Codable {
let role: String
let content: String
}
struct GPT3Payload: Codable {
let model: String
let messages: [GPT3Message]
}
func chatWithGPT3(apiKey: String, system: String, text: String) async throws -> String {
let url = URL(string: "https://api.openai.com/v1/chat/completions")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let systemMessage = GPT3Message(role: "system", content: system)
let userMessage = GPT3Message(role: "user", content: text)
let payload = GPT3Payload(model: "gpt-3.5-turbo", messages: [systemMessage, userMessage])
do {
let jsonData = try JSONEncoder().encode(payload)
request.httpBody = jsonData
} catch {
print("Error: \(error)")
throw error
}
let (data, response) = try await URLSession.shared.data(for: request)
if let httpResponse = response as? HTTPURLResponse,
httpResponse.statusCode != 200 {
throw URLError(.badServerResponse)
}
do {
let jsonObject = try JSONSerialization.jsonObject(with: data, options: [])
if let jsonDict = jsonObject as? [String: Any],
let choices = jsonDict["choices"] as? [[String: Any]],
let firstChoice = choices.first,
let message = firstChoice["message"] as? [String: Any],
let content = message["content"] as? String {
return content
}
} catch {
print("Error: \(error)")
throw error
}
return ""
}
最後に
Qiita × Fast DOCTOR Health Tech Hackathonはとても楽しいイベントでした。
良い人ばかりで、尚且つ、頭も良い方が集まっていたので、心地良かったです。都合が合えば、また参加させて頂きたいと思ってます。