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

Недавно мы все увидели новость:

10 апреля «Яндекс» представил «Алису нового поколения» —  и про-подписку,  где собраны продвинутые функции.

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

В своей работе я часто использую сервис ChatGPT, но это не всегда удобно, особенно из-за необходимости включать VPN. Давайте попробуем ответить на вопрос: может ли разработчик мобильных приложений, например на платформе iOS, использовать Yandex GPT в своей ежедневной работе?

Небольшое отступление. Как я понимаю, в этом году все компании по всему миру в срочном порядке ищут способы монетизации ИИ-сервисов, так как все понимают, что это "круто", но пока неясно, где деньги =)

Итак, заходим на https://a.ya.ru

Помощь с кодом

Представим, что мы мобильные разработчики, которые каждый день пишут на языке Swift. Мы хотим использовать YaGPT ежедневно в своей работе. Для этого проверим его компетентность по сравнению с GPT 4o от компании OpenAI.

Наше собеседование на роль AI-ассистента будет проходить в три этапа:

  1. Алгоритмическая сессия. Дадим несколько задачек с leetcode.

  2. Исправление кода. Дадим небольшой кусочек кода и попросим его улучшить.

  3. Теоретические вопросы. Попробуем задать несколько теоретических вопросов.

Берем первую задачку с уров��ем "просто" с leetcode 

leetcode
leetcode

Переводим текст задачи на русский, чтобы было честно, все же работаем с YaGPT

Текст промпта

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

Пример 1:

Ввод: nums = [2,7,11,15], target = 9
Вывод: [0,1]
Пояснение: Поскольку nums[0] + nums[1] == 9, мы возвращаем [0, 1].
Пример 2:

Ввод: nums = [3,2,4], target = 6
Вывод: [1,2]
Пример 3:

Ввод: nums = [3,3], target = 6
Вывод: [0,1]

Ограничения:
2 <= длина массива nums <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
Существует только один правильный ответ.

Начальный код

class Solution {
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {}

}

Получаем результаты

YaGPT

Проверяем ответ в leetcode 

А теперь сравним с решением ChatGPT 4o

Ответ от GPT 4o оказался более оптимизированным, но в целом обе сети справились с решением. 

Давайте возьмем еще одну задачку для проверки

Текст промпта

Дано целое число x. Вернуть true, если x является палиндромом, и false в противном случае. Целое число является палиндромом, когда оно читается одинаково как слева направо, так и справа налево. Например, 121 является палиндромом, в то время как 123 не является палиндромом.

Пример 1: Ввод: x = 121 Вывод: true

Пояснение: 121 читается одинаково слева направо и справа налево.

Пример 2: Ввод: x = -121 Вывод: false

Пояснение: Слева направо оно читается как -121. Справа налево оно становится 121-. Поэтому это не палиндром.

Пример 3: Ввод: x = 10 Вывод: false

Пояснение: Справа налево оно читается как 01. Поэтому это не палиндром.

Ограничения: -2^31 <= x <= 2^31 - 1

Начальный код class Solution { func isPalindrome(_ x: Int) -> Bool { } }

Пробуем

Пробуем отправить код на проверку и видим ошибку к сожалению =(

Проверяем код, который отдает GPT 4o. Результаты говорят сами за себя

Исправление кода

Дадим небольшой кусочек кода и попросим его улучшить. 

Примечание

Изначально я не знал, что у YaGPT есть ограничение на количество символов. Когда я начал проверять его, я подумал, что можно заменить задачу на более простую. Но задача с версткой очень базовая, и действительно ИИ может помочь в этом. Поэтому я решил не менять задачу и о��тавить ее как есть.

Давайте предположим что у вас есть вот такой экран в приложении

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

Экран поехал, никто не предполагал, что там будет столько текста. Скролла, конечно же, нет. Что нужно сделать? Правильно, нужно добавить скролл на данный экран, чтобы все элеме��ты могли скролиться, но кнопку "Поделиться" давайте оставим фиксированной за пределами скролла. Итак, попробуем отправить эту задачку в Алису и в GPT.

Текст промпта
import UIKit
import SnapKit

class ViewController: UIViewController {
    
    let headerBlockView: UIView = {
        let view = UIView()
        view.backgroundColor = .lightGray
        return view
    }()
    
    let linkContainerView: UIView = {
        let view = UIView()
        view.backgroundColor = .lightGray
        view.layer.cornerRadius = 10
        return view
    }()
    
    let referralLinkLabel: UILabel = {
        let label = UILabel()
        label.text = "https://google.com"
        label.textColor = .systemBlue
        label.numberOfLines = 1
        label.textAlignment = .center
        return label
    }()
    
    let copyButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("Copy", for: .normal)
        button.addTarget(self, action: #selector(copyLink), for: .touchUpInside)
        return button
    }()
    
    let shareButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("Поделиться", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.backgroundColor = .red
        button.layer.cornerRadius = 10
        button.addTarget(self, action: #selector(shareLink), for: .touchUpInside)
        return button
    }()
    
    let descriptionLabel: UILabel = {
        let label = UILabel()
        label.text = """
        Искусственный интеллект (ИИ) о потенциал уже сейчас меняет мир, открывая новые возможности во всех сферах нашей жизни. ИИ способен анализировать огромные объемы данных за считанные секунды, находя в них закономерности и выводы, которые были бы недоступны человеку. Это приводит к улучшению решений в медицине, финансах, производстве и других областях.
        """
        label.numberOfLines = 0
        label.textAlignment = .center
        label.font = UIFont.systemFont(ofSize: 14)
        return label
    }()
    
    let agreementLabel: UILabel = {
        let label = UILabel()
        label.text = """
        Нажимая "Поделиться", ты соглашаешься с правилами программы.
        """
        label.numberOfLines = 0
        label.textAlignment = .center
        label.font = UIFont.systemFont(ofSize: 12)
        label.textColor = .gray
        return label
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .white
        
        setupUI()
    }
    
    func setupUI() {
        view.addSubview(headerBlockView)
        view.addSubview(linkContainerView)
        linkContainerView.addSubview(referralLinkLabel)
        linkContainerView.addSubview(copyButton)
        view.addSubview(descriptionLabel)
        view.addSubview(shareButton)
        view.addSubview(agreementLabel)
        
        headerBlockView.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
            make.leading.trailing.equalToSuperview()
            make.height.equalTo(200)
        }
        
        linkContainerView.snp.makeConstraints { make in
            make.top.equalTo(headerBlockView.snp.bottom).offset(16)
            make.leading.trailing.equalToSuperview().inset(16)
            make.height.equalTo(50)
        }
        
        referralLinkLabel.snp.makeConstraints { make in
            make.centerY.equalTo(linkContainerView.snp.centerY)
            make.leading.equalTo(linkContainerView.snp.leading).offset(16)
        }
        
        copyButton.snp.makeConstraints { make in
            make.centerY.equalTo(linkContainerView.snp.centerY)
            make.leading.equalTo(referralLinkLabel.snp.trailing).offset(8)
            make.trailing.equalTo(linkContainerView.snp.trailing).inset(16)
        }
        
        descriptionLabel.snp.makeConstraints { make in
            make.top.equalTo(linkContainerView.snp.bottom).offset(16)
            make.leading.trailing.equalToSuperview().inset(16)
        }
        
        shareButton.snp.makeConstraints { make in
            make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom).offset(-16)
            make.leading.trailing.equalToSuperview().inset(16)
            make.height.equalTo(50)
        }
        
        agreementLabel.snp.makeConstraints { make in
            make.bottom.equalTo(shareButton.snp.top).offset(-8)
            make.leading.trailing.equalToSuperview().inset(16)
        }
    }
    
    @objc func copyLink() {
        UIPasteboard.general.string = referralLinkLabel.text
        let alert = UIAlertController(title: "Copied", message: "Referral link copied to clipboard.", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        present(alert, animated: true, completion: nil)
    }
    
    @objc func shareLink() {
        let activityVC = UIActivityViewController(activityItems: [referralLinkLabel.text ?? ""], applicationActivities: nil)
        present(activityVC, animated: true, completion: nil)
    }
}


Положи все объекты на скрол вью, чтобы все элементы скролились так как в label может быть много текста
Кнопка поделится должна быть над scollview чтобы она не скролилась

Что у нас получилось с GPT 4o

Пробуем использовать YaGPT, и к сожалению видим ограничению по вводимому тексту, и весь экран у нас не помещается в ответ(даже половина)

Ничего, подумал я. Давайте попрбуем зайти в Yandex Cloud, возможно там нет такого ограничения на ввод. Но нет, к сожалению мы видим такое же ограничение.

По итоге в этом тесте ставим YaGPT минус.

Теоретический вопрос

Попробуем задать базовый вопрос про работу с памятью в swift ИИ

Вопрос

Расскажи как в swift работать с памятью

YaGPT

В Swift управление памятью осуществляется через два основных механизма: 
Automatic Reference Counting (ARC) и Manual Memory Management.Automatic Reference Counting (ARC)ARC является предпочтительным 
и дефолтным механизмом управления памятью в Swift.
Он автоматизирует процесс выделения и освобождения памяти, упрощая работу 
разработчика. 

ARC отслеживает количество сильных ссылок на объекты и освобождает память,
когда количество ссылок становится равным нулю.Manual Memory ManagementНесмотря на то, 
что ARC является основным механизмом управления памятью в Swift, иногда требуется более точный контроль над выделением и освобождением памяти.
Для этого используются технологии вроде UnsafeMutablePointer и UnsafeBufferPointer, 
которые позволяют напрямую управлять памятью.

Пример работы с памятью в SwiftРассмотрим пример использования
ARC:class 

University {
 var title: String
 init(title: String) {
 self.title = title
 print("\(title) has been initialized.")
 }
 deinit {
 print("\(title) has been deallocated.")
 }
}

func assignTitle() {
 _ = University(title: "Cambridge")
}

assignTitle()

В этом примере создается класс University с одним свойством title типа String. При создании экземпляра класса University с помощью метода init печатается сообщение о инициализации объекта. После того как экземпляр выходит из области видимости, вызывается метод deinit, который печатает сообщение о деинициализации объекта.Этот пример демонстрирует, как ARC автоматически управляет памятью, освобождая ее после того, как экземпляр класса University выходит из области видимости.

GPT 4o

Работа с памятью в Swift в основном управляется автоматически с помощью механизма ARC (Automatic Reference Counting). Однако, чтобы эффективно использовать память и избегать проблем, таких как утечки памяти и циклические ссылки, важно понимать, как ARC работает и как управлять ссылками на объекты. Вот подробное руководство по работе с памятью в Swift:

### Основные концепции ARC

#### Сильные ссылки (Strong References)

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

```swift
class Person {
    var name: String
    
    init(name: String) {
        self.name = name
    }
}

var john: Person? = Person(name: "John") // Сильная ссылка на объект Person
```

#### Слабые ссылки (Weak References)

Слабые ссылки не удерживают объект в памяти. Они используются, чтобы избежать циклическ��х ссылок. Слабые ссылки объявляются с помощью ключевого слова `weak`.

```swift
class Apartment {
    weak var tenant: Person?
}

class Person {
    var name: String
    var apartment: Apartment?
    
    init(name: String) {
        self.name = name
    }
}

var john: Person? = Person(name: "John")
var unit4A: Apartment? = Apartment()

john?.apartment = unit4A
unit4A?.tenant = john

john = nil // Объект Person освобождается, так как единственная сильная ссылка на него установлена в nil
```

#### Несоблюдающие ссылки (Unowned References)

Несоблюдающие ссылки (`unowned`) также не удерживают объект в памяти, но в отличие от слабых ссылок они предполагают, что объект всегда будет существовать при обращении к нему. Несоблюдающие ссылки используются, когда обе стороны взаимосвязи всегда существуют одновременно.

```swift
class Customer {
    var creditCard: CreditCard?
    
    init() {
        self.creditCard = CreditCard(customer: self)
    }
}

class CreditCard {
    unowned let customer: Customer
    
    init(customer: Customer) {
        self.customer = customer
    }
}

var customer = Customer()
// customer имеет сильную ссылку на creditCard, а creditCard имеет несоблюдающую ссылку на customer
```

### Избегание циклических ссылок

Циклические ссылки возникают, когда два объекта удерживают друг друга, создавая цикл. Это приводит к утечкам памяти, так как ARC не может освободить такие объекты. Использование слабых и несоблюдающих ссылок помогает избежать циклических ссылок.

#### Пример циклической ссылки

```swift
class Person {
    var name: String
    var apartment: Apartment?
    
    init(name: String) {
        self.name = name
    }
}

class Apartment {
    var tenant: Person?
}

var john: Person? = Person(name: "John")
var unit4A: Apartment? = Apartment()

john?.apartment = unit4A
unit4A?.tenant = john

john = nil // john и unit4A не освобождаются из памяти из-за циклической ссылки
```

#### Исправление циклической ссылки с использованием слабых ссылок

```swift
class Apartment {
    weak var tenant: Person?
}

// Остальная часть кода остается без изменений
```

### Управление памятью с помощью замыканий (Closures)

Замыкания в Swift захватывают ссылки на любые переменные и объекты, которые они используют внутри себя. Это может привести к циклическим ссылкам, если замыкание и захваченные объекты ссылаются друг на друга.

#### Пример замыкания, создающего циклическую ссылку

```swift
class HTMLElement {
    let name: String
    let text: String?
    
    lazy var asHTML: () -> String = {
        if let text = self.text {
            return "<\(self.name)>\(text)</\(self.name)>"
        } else {
            return "<\(self.name) />"
        }
    }
    
    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }
    
    deinit {
        print("\(name) is being deinitialized")
    }
}

var heading: HTMLElement? = HTMLElement(name: "h1", text: "Hello, world!")
print(heading!.asHTML())
heading = nil // HTMLElement не освобождается из памяти
```

#### Использование захватывающих списков (Capture Lists) для предотвращения циклических ссылок

```swift
lazy var asHTML: () -> String = { [weak self] in
    guard let self = self else { return "" }
    if let text = self.text {
        return "<\(self.name)>\(text)</\(self.name)>"
    } else {
        return "<\(self.name) />"
    }
}
```

### Вывод

Работа с памятью в Swift с помощью ARC позволяет автоматизировать управление памятью и уменьшить количество ошибок, связанных с ручным управлением памятью. Однако важно понимать, как работают сильные, слабые и несоблюдающие ссылки, чтобы эффективно предотвращать утечки памяти и избегать циклических ссылок.

Выводы делайте сами =)

Итог

Очень круто, что у нас создаются такие продукты, как YandexGPT и Gigachat. Они определенно движутся в правильном направлении. Но, к сожалению, как инструменты для разработчиков, которые можно использовать уже сейчас, они пока не подходят.

А используете ли вы ИИ в своей работе?

Если вам интересно больше узнать об ИИ, подписывайтесь на мой телеграм‑канал.