問題点
- リクエストを送った後にトークンを書き換わってしまって再度入力が必要になる
説明
このコードは、SwiftUIで書かれたOpenAI APIへのPOSTリクエストを行うプログラムです。
makeOpenAIRequest関数は、OpenAIのAPIキーとニューステキストを受け取り、APIにリクエストを送信して生成されたテキストを返す非同期関数です。
ModalViewは、APIキーを入力するためのモーダルビューです。ユーザーがAPIキーを入力すると、キーが親ビューであるContentViewのtoken変数に保存されます。
ContentViewは、テキストエディタと2つのボタンを持つビューです。1つのボタンは、makeOpenAIRequest関数を呼び出して、APIから生成されたテキストを取得します。もう1つのボタンは、APIキーを入力するためのModalViewを表示します。
ContentViewには、UserDefaultsを使用して、ユーザーが以前に入力したAPIキーを保存するためのコードが含まれています。これにより、アプリケーションが再起動された場合でも、以前に使用されたAPIキーを保持することができます。
コード本体
import SwiftUI
import Foundation
func makeOpenAIRequest(news: String, api_key: String, completion: @escaping (String?, Error?) -> Void) {
let apiKey = api_key
let urlString = "https://api.openai.com/v1/completions"
guard let url = URL(string: urlString) else {
print("Invalid URL")
let error = NSError(domain: "Invalid URL", code: 0, userInfo: nil)
completion(nil, error)
return
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
let parameters: [String: Any] = [
"model": "text-davinci-003",
"prompt": "" + news,
"temperature": 0,
"max_tokens": 100,
"top_p": 1,
"frequency_penalty": 0.0,
"presence_penalty": 0.0,
"stop": ["\n"]
]
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: []) else {
print("Invalid parameters")
let error = NSError(domain: "Invalid parameters", code: 0, userInfo: nil)
completion(nil, error)
return
}
request.httpBody = httpBody
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForResource = 200 // increase to 2 minutes (120 seconds)
let session = URLSession(configuration: configuration)
let task = session.dataTask(with: request) { (data, response, error) in
if let error = error {
print("Error: \(error.localizedDescription)")
completion(nil, error)
return
}
guard let data = data else {
print("No data returned")
let error = NSError(domain: "No data returned", code: 0, userInfo: nil)
completion(nil, error)
return
}
guard let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let choices = json["choices"] as? [[String: Any]], let text = choices.first?["text"] as? String else {
// Log the JSON data to aid in debugging.
print("Unable to parse JSON: \(String(data: data, encoding: .utf8) ?? "")")
let error = NSError(domain: "Unable to parse JSON", code: 0, userInfo: nil)
completion(nil, error)
return
}
completion(text, nil)
}
task.resume()
}
struct ModalView: View {
@State private var name: String = ""
@Binding var token: String
@Binding var showModal: Bool
var body: some View {
NavigationView {
Form {
Section(header: Text("User Information")) {
TextField("Name", text: $name)
}
Section {
Button(action: {
// perform action here
self.token = self.name
self.showModal = false
}) {
Text("Submit")
}
}
}
.navigationBarTitle("Modal Form")
}
}
}
struct ContentView: View {
@State private var name: String = "a"
@State private var paragraph: String = "d"
@State private var text = "Hello, world!!!"
@State private var profileText = "Hello, world!!!"
@State private var token = ""
@State private var showModal: Bool = false
@State private var isModalPresented = false
init() {
let defaults = UserDefaults.standard
let savedParagraph = defaults.string(forKey: "savedParagraph")
if let savedParagraph = savedParagraph {
self.token = savedParagraph
print(savedParagraph)
token = savedParagraph
}
}
var body: some View {
VStack(spacing: 20) {
Spacer()
TextEditor(text: $paragraph)
.foregroundColor(.secondary)
.padding(.horizontal)
.navigationTitle("About you")
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.gray, lineWidth: 2)
)
Text(profileText)
.padding()
Spacer()
Button(action: {
let defaults = UserDefaults.standard
defaults.set(self.paragraph, forKey: "savedParagraph")
makeOpenAIRequest(news: paragraph, api_key: token) { response, error in
if let response = response {
DispatchQueue.main.async {
self.profileText = response
}
} else if let error = error {
// Handle error
print("")
}
}
}) {
Text("Generate Text")
}
.padding()
.background(Color.accentColor)
.foregroundColor(.white)
.cornerRadius(10)
Button(action: {
self.showModal = true
}) {
Text("Enter API Key")
}
.sheet(isPresented: $showModal) {
ModalView(token: self.$token, showModal: self.$showModal)
}
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
過程