Недавно у нас произошел взрыв инструментов ИИ, и я подумал, можно ли создать простое приложение, достаточно хорошее, чтобы его можно было отправить в App Store. В этих сообщениях я предполагаю, что вы уже знаете Xcode, поэтому я могу сосредоточиться на творческой стороне вещей.

В первом посте было показано, как использовать ИИ для создания иконки приложения. В этом посте я собираюсь посмотреть, может ли другой ИИ написать код достаточно хорошо, чтобы он был практически полезен.

Честно говоря, я не ожидал многого, это не сработало сразу, потребовалось некоторое время, чтобы заставить его работать, но когда это произошло, это было более неожиданно, чем я ожидал, но временами разочаровывающим.

Сначала мне нужна идея простого приложения, есть несколько забавных бесплатных API. Хорошо это или плохо, но я решил попробовать создать приложение Цитата дня, используя chucknorris.io для собранных вручную фактов о Чаке Норрисе.

Инструмент, который я использовал для этого поста, находится в стадии бета-тестирования OpenAI, вы можете присоединиться к списку ожидания здесь. Как только у вас есть доступ, вам предоставляется игровая площадка, модель, которую я использовал, была text-devinci-002, температура 0.7 и максимальная длина увеличена до 2000. На их веб-сайте есть множество инструкций и примеров для начала работы.

Прежде чем мы начнем, стоит узнать, как работает этот инструмент.

ИИ — это, по сути, модель предсказания языка. Это означает, что он принимает текст в качестве входных данных и предсказывает наиболее полезный текстовый результат. Здесь нет концепции вопроса или ответа, а больше того, что, скорее всего, будет следующим в последовательности. Таким образом, вы можете задать вопрос ИИ, но исходя из того, что наиболее вероятно в последовательности, результатом, который вы получите, может быть ИИ, добавляющий к вашему вопросу, прежде чем вы получите ответ.

Поскольку ИИ в настоящее время находится в стадии бета-тестирования, иногда он не перестает задавать себе вопросы и никогда не создает никакого кода, надеюсь, эта проблема может быть исправлена ​​в будущем. Но если вы немного лучше понимаете это поведение, вы можете предотвратить это.

Таким образом, вы можете задать такой вопрос…

// Swift 
// create a function that requests data from https://api.chucknorris.io/jokes/random

Первая строка сообщает ИИ, на каком языке кодирования вы хотите получить ответ, а вторая строка — это запрос кода, который вы хотите, чтобы ИИ создал. Поскольку ИИ предсказывает наиболее вероятный результат, для приведенного выше текста наиболее вероятным текстом, следующим в последовательности, является не код, а фактически ответ на вопрос.

Подумайте об этом, сколько примеров кода вы видели, где функция просто загружает данные? Большинство примеров, которые вы встретите в Интернете, будут функциями, которые загружают данные, а затем что-то с ними делают.

Таким образом, для приведенного выше текста наиболее вероятным в последовательности является не код, а фактически добавление к вопросу, чтобы данные производили вывод.

На этот вопрос ИИ добавит что-то вроде // and print a "chuck Norris joke: in the console.

// Swift 
// create a function that requests data from https://api.chucknorris.io/jokes/random 
// and print a “Chuck Norris joke” in the console.

Как только у ИИ возникает вопрос, где написание кода, скорее всего, будет следующим в последовательности, за ним следует…

func chuckNorris() { 
   let url = URL(string: “https://api.chucknorris.io/jokes/random")! 
   let task = URLSession.shared.dataTask(with: url) { 
      (data, response, error) in guard 
      let data = data else { 
         print(String(describing: error)) return 
      } 
      let json = try? JSONSerialization.jsonObject(with: data, options: []) 
      if let dictionary = json as? [String: Any] {      
         print(dictionary[“value”] as! String) 
      }
   } task.resume() 
} 
chuckNorris()

Возьмите паузу

Прежде чем мы продолжим, давайте сделаем паузу и впитаем в себя то, что только что произошло. Предсказание ИИ заключалось в том, чтобы сначала добавить дополнительную информацию к моему вопросу. Вы можете проверить это самостоятельно, если у вас есть доступ к инструменту. Если вы зададите ему такие вопросы, как «Если A существует, то сделайте X», из которых ИИ добавит «если A не существует, сделайте Y» — это завершает логику вопроса, основанную на том, как большинство людей пишут код, удивительно.

Но он не только дополнил мой вопрос, чтобы сделать его более полезным, но и, просто используя предоставленный мною URL, ИИ довольно точно угадал имя функции. Но сначала меня застало врасплох то, что он точно предсказал, какое из json возвращает значение из URL, который я бы действительно хотел использовать, value. Я предполагаю, что, поскольку это бесплатный URL-адрес, и его легко найти, многие другие разработчики также использовали тот же URL-адрес и в основном используют свойство value в качестве информации, которую они, скорее всего, используют (мне нужно больше поиграть с ним, чтобы посмотрите, правда ли это).

Для тех из вас, у кого острый глаз, обратите внимание as! , что не будет или не должно проходить проверку производственного кода человеком, поскольку это может привести к сбою приложения, если ответ когда-либо изменится. Поэтому, если вы видите такие вещи, вам нужно изменить свой вопрос, включив в него что-то вроде if value exists print value else print "value does not exist" , что поможет ИИ использовать вместо этого что-то вроде as?.

Создание кода

То, что я хотел бы, чтобы ИИ создал, — это отображать представление в мобильном приложении с помощью счетчика загрузки, пока загружаются данные. После загрузки данных отобразите свойство данных value . Если value не существует, отобразите кнопку, чтобы повторить попытку и повторить процесс.

Честно говоря, у меня было довольно много неудачных попыток, которые стоит отметить. Один или два раза он изо всех сил пытался правильно проанализировать ответ json. В других случаях он создавал элементы пользовательского интерфейса, которых не было в SwiftUI — я думаю, это было связано с запросом SwiftUI , поскольку язык Swift имеет две основные библиотеки, которые он использует для рисования пользовательского интерфейса, UIKit и SwiftUI. Поскольку мой ввод запрашивал SwiftUI, и я упомянул «индикатор активности» для моего счетчика загрузки, поскольку этот «индикатор активности» — это вещь UIKit, и ИИ получил смесь UIKit и SwiftUI на выходе. Уловка, которую я нашел, заключалась в том, что при использовании SwiftUI не упоминались ключевые слова UIKit. Как только я переключил «индикатор активности» на «загрузку счетчика», я получил ответ, который хотел.

После нескольких неудачных попыток я захотел начать с чего-то простого, что можно было бы компилировать.

// SwiftUI
// create a swiftUI view ContentView
// display a loading spinner
// on view appear call request json from https://api.chucknorris.io/jokes/random and convert to a structure called Joke
// Joke structure that contains one property called value
// if value exist display Joke property value as text and hide loading spinner

ИИ сделал свое дело и изменил мой вопрос, добавив…

// if value does not exists hide spinner indicator and display “something went wrong”
// if loading is true, hide Joke property value and show loading spinner
// test if the loading is set to true at the correct time
// create a button to make a new joke request
// if the url fails display text “something went wrong” and display a button to make a new joke request

Снова пауза — я хотел начать с чего-то простого, я не просил кнопку. Но ИИ добавил кнопку, чтобы повторить запрос URL для меня 🤯.

Затем за измененным вопросом последовал следующий код, который компилирует…

import SwiftUI
struct Joke: Codable {
 let value: String
}
struct ContentView: View {
 @State private var loading = true
 @State private var joke = Joke(value: “”)
var body: some View {
 VStack {
   Text(joke.value)
   if loading {
     ActivityIndicator(isAnimating: $loading, style: .large)
   } else {
     Button(action: {
        self.loadJoke()
     }) {
       Text(“Load Joke”)
     }
    }
   }
   .onAppear {
     self.loadJoke()
   }
 }
func loadJoke() {
 loading = true
 guard let url = URL(string: “https://api.chucknorris.io/jokes/random") else { return }
 URLSession.shared.dataTask(with: url) { (data, _, _) in
   guard let data = data else { return }
   let joke = try! JSONDecoder().decode(Joke.self, from: data)
   DispatchQueue.main.async {
     self.joke = joke
     self.loading = false
   }
  }.resume()
 }
}
struct ContentView_Previews: PreviewProvider {
 static var previews: some View {
 ContentView()
 }
}
struct ActivityIndicator: UIViewRepresentable {
@Binding var isAnimating: Bool
 let style: UIActivityIndicatorView.Style
func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> UIActivityIndicatorView {
 return UIActivityIndicatorView(style: style)
 }
func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext<ActivityIndicator>) {
 isAnimating ? uiView.startAnimating() : uiView.stopAnimating()
 }
}

Копирование этого кода в приложение Xcode SwiftUI по умолчанию создает следующее изображение, и это не красиво, но работает.

Я провел хороший тест и обнаружил, что он не обрабатывает сбои сети. Итак, пришло время внести поправки в мой вклад и исправить это — легко, верно?

Теперь это стало немного раздражать

Я скопировал и вставил тот же вопрос, что и раньше, с небольшой поправкой на сетевые ошибки. Но вместо чего-то полезного я начал получать разные ответы, которые не компилировались. Он перестал понимать мой запрос на структуру и как обращаться со счетчиком загрузки.

Итак, примерно через 2 минуты игры, я остановился на этом входе, где я немного изменил свой запрос на загрузчик, и вместо разбора структуры я попросил использовать вместо этого простой словарь.

// SwiftUI
// create a swiftUI view ContentView 
// display a animating loading spinner 
// on view appear call request json from https://api.chucknorris.io/jokes/random and convert to dictionary 
// if dictionary key “value” exist print value as text and hide loading spinner 
// if there is a network request from the url or there is no key value display “something went wrong” and hide spinner 
// create a button to make a new joke request 
// if the url fails or cannot find the key display text “something went wrong” and display a button to make a new request

Он произвел код, который был так близок к работе, что я обнаружил одну ошибку, связанную с потерей сети и повторным подключением, но все, что мне нужно было сделать, это настроить одну строку, и это было достаточно хорошо для магазина приложений (добавьте комментарий ниже к строке, которую я добавил ).

import SwiftUI
struct ContentView: View {
  @State private var showSpinner = true
  @State private var joke = ""
  @State private var showError = false
  var body: some View {
    VStack {
      Spacer()
      if showSpinner {
        Spinner()
      } else {
        if showError {
          VStack {
            Text("Something went wrong")
            Button(action: {
              self.showSpinner = true
              self.getJoke()
            }) {
             Text("Try again")
            }
       } 
    } else {
      Text(joke)
      Button(action: {
        self.showSpinner = true
        self.getJoke()
      }) {
        Text("Get new joke")
      }
    }
  }
  Spacer()
  }
  .onAppear {
    self.getJoke()
  }
}
func getJoke() {
  guard let url = URL(string: "https://api.chucknorris.io/jokes/random") else {
   self.showSpinner = false
   self.showError = true
   return
  }
  URLSession.shared.dataTask(with: url) { data, response, error in
  DispatchQueue.main.async {
    if let data = data {
      do {
        let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
        if let value = json?["value"] as? String {
         self.joke = value
         self.showSpinner = false
         self.showError = false // human code here
        } else {
          self.showSpinner = false
          self.showError = true
        }
      } catch {
        self.showSpinner = false
        self.showError = true
      }
    } else {
      self.showSpinner = false
      self.showError = true
    }
  }
 }.resume()
 }
}
struct Spinner: UIViewRepresentable { ... same as before ...}

Я неоднократно пытался настроить ввод, но ничего лучше не получалось — во всяком случае, на данный момент.

Заключение

Мне удалось использовать ИИ для создания 99% кода, который мне был нужен, чтобы его можно было выпустить в App Store. Но я бы ни за что не продвинулся так далеко без терпения и хорошего понимания SwiftUI. Если бы я попробовал это на незнакомом языке, я уверен, что это был бы гораздо более разочаровывающий опыт.

Когда ИИ работал, он работал на удивление хорошо, лучше, чем я ожидал, но было так много попыток, когда он работал в одну минуту и ​​терпел неудачу в следующую с небольшими изменениями ввода.

Но это всего лишь один ИИ, а SwiftUI — не самый популярный язык. Я добился гораздо большего успеха со Swift сам по себе, и мне еще многое предстоит узнать об интерфейсе AI.

Все еще стремясь лучше изучить и понять такие инструменты, постараюсь продолжить этот пост с другими экспериментами в этой области.