I am trying to display the response after making a post request to a GPT3 open ai endpoint.
Here is an example JSON response:
{
"id": "cmpl-4R7o3DcLSOGjjWHs5CrKXecNAoRDL",
"object": "text_completion",
"created": 1642370211,
"model": "davinci:2020-05-03",
"choices": [
{
"text": "\n\nA neutron star is a star that is so dense that it has collapsed into a sphere.\n\nA neutron star is the collapsed core of a massive supergiant star, which had a total mass of between 10 and 25 solar masses, possibly more if the star was especially metal-rich",
"index": 0,
"logprobs": null,
"finish_reason": "length"
}
]
}
I specifically want to display the text of the response. To do this i have created two structs in line with what https://app.quicktype.io/ returns for plain types.
struct Response: Codable, Identifiable{
var id = String()
var model = String()
var choices: [Choice]
}
struct Choice: Codable{
var finish_reason = String()
var index = Int()
var text = String()
}
I then created a class to call the endpoint, decode the JSON and return the data via a completion handler:
class GPT3TextComepletion: ObservableObject{
@Published var response = Response.self
func textCompletion(promptText:String, completion:@escaping (Response) -> ()) {
let token = "redacted"
let url = URL(string: "https://api.openai.com/v1/engines/davinci/completions")!
// prepare json data
var json: [String: Any] = [
"temperature": 0.7,
"max_tokens": 60,
"top_p": 1.0,
"frequency_penalty": 0,
"presence_penalty": 0]
json["prompt"] = promptText
let jsonData = try? JSONSerialization.data(withJSONObject: json)
// create post request
var request = URLRequest(url: url)
request.httpMethod = "POST"
// insert json data to the request
request.httpBody = jsonData
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.setValue( "Bearer \(token)", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
let response = try! JSONDecoder().decode(Response.self, from: data)
let choice = response.choices
print(choice)
DispatchQueue.main.async {
completion(response)
}
}
task.resume()
}
}
I can access any data that is not in choice array i.e model via this:
@State var response: Response? = nil
Button(action: {GPT3TextComepletion().textCompletion(promptText: prompt, completion: {(response) in self.response = response })})
Text(response?.model ?? "some data")
However I have not been able to access the data from the choice struct(i can print the data just not display it). The error I am recieving i:
Initializer 'init(_:)' requires that 'Choice' conform to 'StringProtocol'
Due to the Choice struct being an array i have tried iterating over it with no success or accessing the third element of the array:
Text(response!.choices[2])
I would like to display the data(specifically the text variable) from the choice struct if anyone can assist.
Thanks!
CodePudding user response:
Text(response!.choices[2])
This line returns a Choice struct which is not a string representable. You need to go a level deeper and access it's text property.
Text(response!.choices[2].text)
I assume you have hardcoded and forced unwrapped for the example's sake. Otherwise follow safe coding practices :)
