概要
OpenAI APIの中でChatGPTが利用できるので、そちらを利用してAIとチャットできるiOSアプリを試しに作ってみました。その中で作り方やpromptの調整による変化などを簡単に検証してみたので紹介したいと思います。
またPythonのみで簡単にWebアプリを作成できる方法については以下の記事で紹介されていますのでよければそちらもご覧ください。
環境
この記事は以下のバージョン環境のもと作成されたものです。
【Xcode】14.2
【iOS】16.2
【macOS】Ventuta
前置き
ChatGPTに関しては昨年の12月ごろに「ChatGPTを使ったiOSアプリの開発方法をChatGPTに聞いて作ってみる」と言う事を試してみました。
ChatGPT使ったiOSアプリ作ろうと思いましたのでChatGPTに聞いてみました。
— Yuji Oka (@oka_yuuji) 2022年12月15日
という事で週末頑張ってみますw pic.twitter.com/ebpIJB7oGw
ただ思ったような回答は得られず、結果OpenAISwiftというライブラリを導入する事で検証することができました。
おっ!いい感じにできている気がする!
— Yuji Oka (@oka_yuuji) 2022年12月17日
ブログ書きながら試してみたので、もう少し整理して実装方法やサンプルコード掲載したテックブログリリースしたいと思います!良かったらみてください!(見て良かったらいいねや拡散してくれると嬉しいっす!) pic.twitter.com/rVOPL6caH5
OpenAISwiftの使用方法は以下リンク先のREADMEに記載されていますのでそちらを参考にして頂ければと思いますが、準備としてOpenAIにてアカウント登録を行い、画面右上のPersonal -> View API keys -> Create new secret keyよりsecret keyを発行する必要があります。
発行したkeyはlet openAI = OpenAISwift(authToken: "TOKEN")
のTOKEN部分に代入して使用します。
今回は上記のサードパーティのライブラリを使用せず作成してみました。
ドキュメントを見る
ChatGPTを使用したい場合のドキュメントは以下のリンク先にあります。
チャット形式のAPIを利用するにはhttps://api.openai.com/v1/chat/completions
をPOSTする事で利用できそうです。
他にも画像やオーディオなどもあるのでまたどこかで触ってみたいと思います。
パラメーターにmodelがあり、その中でgpt-3.5-turbo
かgpt-3.5-turbo-0301
を指定するようです。
ちなみに今回使用するのはgpt-3.5-turbo
を使用しますが、gpt-3.5-turbo-0301
との違いについては以下を参照ください。
実際に検証してみる
今回検証するにあたり以下のリポジトリのコードを参考にさせていただきました。
OpenAISwiftではなくChatGPTSwiftのリポジトリを参考にした理由はiOSだけでなく、macOSやWatchOSでも使用できる状態にあったのでこちらを参考にさせていただきました。
コード全体としては上記のリポジトリを参考にして頂ければと思いますが、主要な部分は以下となります。
リクエストのプロパティは以下の通りです。
private var urlRequest: URLRequest { let url = URL(string: "https://api.openai.com/v1/chat/completions")! var urlRequest = URLRequest(url: url) urlRequest.httpMethod = "POST" headers.forEach { urlRequest.setValue($1, forHTTPHeaderField: $0) } return urlRequest }
headersのプロパティ。
private var headers: [String: String] { [ "Content-Type": "application/json", "Authorization": "Bearer \(apiKey)" ] }
apiKeyやmodel、promptなどについてはinitで定義しています。
init(apiKey: String, model: String = "gpt-3.5-turbo", systemPrompt: String = "あなたは優秀なアシスタントです。話し方は関西弁で返します。", temperature: Double = 0.5) { self.apiKey = apiKey self.model = model self.systemMessage = .init(role: "system", content: systemPrompt) self.temperature = temperature }
OpenAI APIにリクエストを送信し、生成されたテキストを受け取る処理は以下の通りです。
func sendMessageStream(text: String) async throws -> AsyncThrowingStream<String, Error> { var urlRequest = self.urlRequest urlRequest.httpBody = try jsonBody(text: text) let (result, response) = try await urlSession.bytes(for: urlRequest) guard let httpResponse = response as? HTTPURLResponse else { throw "Invalid response" } guard 200...299 ~= httpResponse.statusCode else { var errorText = "" for try await line in result.lines { errorText += line } if let data = errorText.data(using: .utf8), let errorResponse = try? jsonDecoder.decode(ErrorRootResponse.self, from: data).error { errorText = "\n\(errorResponse.message)" } throw "Bad Response: \(httpResponse.statusCode), \(errorText)" } return AsyncThrowingStream<String, Error> { continuation in Task(priority: .userInitiated) { [weak self] in guard let self else { return } do { var responseText = "" for try await line in result.lines { if line.hasPrefix("data: "), let data = line.dropFirst(6).data(using: .utf8), let response = try? self.jsonDecoder.decode(StreamCompletionResponse.self, from: data), let text = response.choices.first?.delta.content { responseText += text continuation.yield(text) } } self.appendToHistoryList(userText: text, responseText: responseText) continuation.finish() } catch { continuation.finish(throwing: error) } } } }
主要な部分は以上です。
後は適当に画面を作るだけでできます。
検証の様子
適当にチャット形式で会話を行ってみました。
内容はともかく、promptにて関西弁で返すように追記していますので関西弁で返してきます。
またpromptを少し調整してUnitTestのサンプルコードを返すようにしてみました。
まとめ
今回はここまでとなります。非常に簡単にアプリにAIアシスタントを組み込むことができる点や、promptを調整する事で好みのAIアシスタントに近づけることができる点など非常に面白いと思いました。
また既存のコードよりUnitTestを生成させる事については、promptの調整はもちろん、環境やコードを渡す際に一工夫必要かもしれません。まだ深く検証できてませんが、非常に便利な機能になりそうだなと思いましたので今後作ってみたいなと思いました。
更にGPT-4も執筆中にリリースされ(日本時間3月15日の深夜2時ぐらいにメールが来ていた)、非常に成長がはやく、精度もどんどん良くなってきているので引き続き上手く付き合っていく方向を探っていきたいと思います。
以上ChatGPTを利用してAIチャットアプリを作ってみるでした。