May 12, 2023

Тестируем новые языковые модели. WizardLM.

Ещё до выхода "утёкшего" внутреннего документа от Google стало ясно, что желание OpenAI закрыть всю техническую информацию по моделям GPT-3.5 и GPT-4 вызывает у сообщества ещё больше желания иметь доступную открытую реализацию модели. Недавняя презентация Bard AI от Google, на базе модели PaLM 2, не показала каких-то новых прорывных сверх-возможностей и примерно равна возможностям уровня GPT-4.

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

Появляются модели, реализующие концепцию мультимодальности, близкой к GPT-4 (miniGPT-4, LLaVA) и мультимодальные датасеты для обучения таких моделей. Скорость улучшения качества доступных моделей растёт с невероятной скоростью.

Появляются открытые бенчмарки (lmsys, LLM Logic Tests, LLM Leaderboard) для тестирования качества ответов моделей.

Продолжают появляться комплексные датасеты с триллионом+ токенов и инициативы обучить с нуля аналоги LLaMA (OpenLLaMA, Cerebras, Pythia), при коммерческом использовании которых не будет юридических проблем.

Распределение данных в датасете RedPajama 1.2 trillion token

Важными составляющими начавшейся в этом году гонки больших языковых моделей, можно считать слив LLaMA и реализацию инференса через библиотеку ggml и llama.cpp на базе этой технологии, а так же технологию LoRa адаптеров с применением PeFt технологии.

PeFT technology example

Синергия этих составляющих дала настоящий буст в развитии LLM, благодаря снижению порога как для обучения, так и для инференса. Ведь теперь для запуска модели с 30 млрд параметров у себя на десктопе, достаточно не самого топового процессора и немного памяти. Исчезает необходимость в дорогостоящих GPU для взаимодействия с моделями. Причём llama.cpp сделала эту возможность кроссплатформенной.

Тот факт, что Bard AI от Google и Bing AI от Microsoft стали доступны публично так скоро, а так же "откровение" из недр Google может говорить о том, что корпорации видят большой потенциал и риски в том, что включившееся в гонку сообщество развивает открытые технологии LLM такими высокими темпами.

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

Сегодня я хочу поделиться результатами своих экспериментов с одной новой LLM, на базе дообученной LLaMA 7b: WizardLM.

WizardLM

WizardLM-7B - Empowering Large Pre-Trained Language Models to Follow Complex Instructions (Расширение возможностей больших предварительно обученных языковых моделей для выполнения сложных инструкций).

Модель дообученная LLaMA 7b на более чем 70к комплексных инструкциях с помощью Evol-Instruct, при котором используется GPT-3.5 для формирования инструкций. Сейчас идет дообучение еще одной модели уже на более чем 300к таких инструкций.

Evol-Instruct это новый метод, использующий языковые модели (в данном случае ChatGPT GPT-3.5) вместо людей для автоматического написания инструкций с открытым доменом различных уровней сложности и диапазона навыков. Конечная цель - улучшить навыки и производительность LLM.

Дообучение WizardLM проходило с использованием Llama-X. и следующими гиперпараметрами:

При сравнение результатов инференса авторами модели WizardLM с Alpaca и Vicuna, WizardLM показала значительно лучшие результаты, чем Alpaca и Vicuna-7b:

По мнению авторов, в части в тестировании модели с задачами высокой сложности из тестового набора, (уровень сложности >= 8) WizardLM превосходит даже ChatGPT, с коэффициентом побед на 7,9% больше, чем у ChatGPT (42,9% против 35,0%) и такой метод дообучения может значительно улучшить способность больших языковых моделей обрабатывать сложные инструкции.

Github: https://github.com/nlpxucan/WizardLM
Wallpaper: https://arxiv.org/abs/2304.12244
Weights: https://huggingface.co/TheBloke/wizardLM-7B-GGML/tree/main
В данном ресерче использовалась версия wizardLM-7B.ggml.q5_1.bin.

В первую очередь меня удивила способность "понимать" задачу и генерировать код на достаточно высоком уровне, при довольно узком размере контекста (2048) и относительно маленьком количестве параметров модели (7b).

Параметры запуска:

D:\Projects\LLaMA_cpp\main -m D:\Projects\LLaMA_cpp\wizardLM-7B.ggml.q5_1.bin -n -1 --ctx_size 2048 --batch_size 16 --keep 512 --repeat_penalty 1.0 -t 28 --temp 0.4 --top_k 30 --top_p 0.18 --interactive-first -ins --color -i main: seed = 1682938446 llama.cpp: loading model from D:\Projects\LLaMA_cpp\wizardLM-7B.ggml.q5_1.bin llama_model_load_internal: format = ggjt v1 (latest) llama_model_load_internal: n_vocab = 32001 llama_model_load_internal: n_ctx = 2048 llama_model_load_internal: n_embd = 4096 llama_model_load_internal: n_mult = 256 llama_model_load_internal: n_head = 32 llama_model_load_internal: n_layer = 32 llama_model_load_internal: n_rot = 128 llama_model_load_internal: ftype = 9 (mostly Q5_1) llama_model_load_internal: n_ff = 11008 llama_model_load_internal: n_parts = 1 llama_model_load_internal: model size = 7B llama_model_load_internal: ggml ctx size = 59.11 KB llama_model_load_internal: mem required = 6612.58 MB (+ 1026.00 MB per state) llama_init_from_file: kv self size = 1024.00 MB

system_info: n_threads = 28 / 36 | AVX = 1 | AVX2 = 1 | AVX512 = 1 | AVX512_VBMI = 0 | AVX512_VNNI = 0 | FMA = 1 | NEON = 0 | ARM_FMA = 0 | F16C = 1 | FP16_VA = 0 | WASM_SIMD = 0 | BLAS = 0 | SSE3 = 1 | VSX = 0 | main: interactive mode on. Reverse prompt: '### Instruction:

' sampling: temp = 0.400000, top_k = 30, top_p = 0.180000, repeat_last_n = 64, repeat_penalty = 1.000000 generate: n_ctx = 2048, n_batch = 16, n_predict = -1, n_keep = 2

Прошу модель написать код приложения To-Do App на Flutter, которое должно взаимодействовать с restapi бекендом c учётом персонализации пользователя:

>Write a flutter to-do app with api requests to backend restapi endpoint and user personalization

Sure, I can help you with that! Here's a basic outline of how you could create a flutter to-do app with api requests to a backend restapi endpoint and user personalization:

1. Set up a backend restapi endpoint: You'll need to create a server-side application that can handle api requests and return the appropriate response. You can use any programming language you like, but for simplicity, let's assume you're using Node.js. You'll also need to set up a database to store user data.

2. Create a flutter app: In flutter, you'll create a new project and add the necessary packages for making api requests. You'll also set up user authentication and storage.

3. Make api requests: In your flutter app, you'll make api requests to your backend restapi endpoint to add, edit, and delete to-do items. You'll also handle errors and handle responses appropriately.

4. Personalize the app: You can personalize the app by storing user data locally on the device, such as their name, photo, and favorite colors. You can also use this data to display personalized notifications and reminders.

Here's some sample code to get you started:

Flutter:

```
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:io'; // ... class ToDoApp extends StatefulWidget { @override _ToDoAppState createState() => _ToDoAppState(); } class _ToDoAppState extends State<ToDoApp> { List<String> toDoItems = []; String userName = ''; String userPhoto = ''; List<String> favoriteColors = []; @override void initState() { super.initState(); // ... // Make api request to get user data http.get('user.json').then((response) { userName = response.body; // ... // Make api request to get favorite colors http.get('favorite_colors.json').then((response) { favoriteColors = response.body; // ... }); }); } // ... // Add to-do item void addToDoItem(String item) { toDoItems.add(item); setState(() {}); // Make api request to save to-do item http.post('to_do_items.json', { 'item': item, 'user_name': userName }).then((response) { // ... }); } // ... // Edit to-do item void editToDoItem(int index, String item) { toDoItems[index] = item; setState(() {}); // Make api request to save to-do item http.put('to_do_items.json', { 'item': item, 'user_name': userName, 'index': index }).then((response) { // ... }); } // ... // Delete to-do item void deleteToDoItem(int index) { toDoItems.removeAt(index); setState(() {}); // Make api request to delete to-do item http.delete('to_do_items.json', { 'user_name': userName, 'index': index }).then((response) { // ... }); } }
```

Backend restapi endpoint:

```
// ... // Get user data get('/user', (req, res) => { res.json(req.user); }); // Get favorite colors get('/favorite_colors', (req, res) => { res.json(req.user.favorite_colors); }); // Add to-do item post('/to_do_items', (req, res) => { const item = req.body.item; const userName = req.user.name; const toDoItems = req.user.toDoItems.push(item); res.json({ success: true, message: 'To-do item added successfully!' }); }); // Edit to-do item put('/to_do_items', (req, res) => { const index = req.body.index; const item = req.body.item; const userName = req.user.name; const toDoItems = req.user.toDoItems.update(index, item); res.json({ success: true, message: 'To-do item edited successfully!' }); }); // Delete to-do item delete('/to_do_items', (req, res) => { const index = req.body.index; const userName = req.user.name; const toDoItems = req.user.toDoItems.removeAt(index); res.json({ success: true, message: 'To-do item deleted successfully!' }); });
```

Note that this is just a basic outline and you'll need to fill in the details and handle errors appropriately. You'll also need to handle authentication and authorization appropriately to ensure that only authorized users can access certain features.

Я не берусь утверждать о том, что этот код заведется с первого раза и всё в нем идеально. Посмотрим в целом на контекст её ответов. Хочу отметить, что это был мой первый запрос к этой модели и такие её ответы _сходу_ меня удивили.

На старте она сообщает о том, что может помочь с данной задачей и декомпозирует запрос на логические пункты:

  1. Развертывание бекенда для взаимодействия с приложением.
  2. Создание Flutter приложения
  3. Добавление функционала взаимодействия с бекендом.
  4. Развитие функционала приложения для добавления персонализации.

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

Что касается кода: модель учла базовые элементы функционала, такие как добавление записи, редактирование и удаление через взаимодействие с бекендом посредством запросов. Для кода бекенда модель сама выбрала node.js, как язык реализации и добавила обработку запоросов на добавление, редактирование, удаление записей, а так же минимульную персонализацию.

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

> Thanks. I like it! Now let's code a restapi code for our flutter frontend

Sure, I can help you with that. Do you have any specific requirements or features that you would like to include in your restapi?

> user reg and auth, create, edit and delete to-do items, statistics

Далее я прошу её реализовать код бекенда и расширить функционал с учетом её советов из первого ответа. Модель снова декомпиозировала мою задачу на более простые сущности и предложила переключиться на реализацию кода бекенда на Flask:

1. Установить Flask c помощью pip и создать новое Flask приложение.
2. Настроить роуты.
3. Реализовать регистрацию с помощью возможностей Flask.
4. Развернуть базу данных с помощью sqlite.
5. Прописать модели сущностей в базе данных.
6. Добавить авторизацию с проверкой и разграничением прав доступа.

Sure, I can help you with that. Here's a basic outline of how you could implement a restapi for a to-do list using Flask:

1. Set up Flask: First, you'll need to install Flask using pip. Run `pip install Flask` in your terminal. Then, create a new Flask app using `python -m Flask appname`.

2. Set up routes: Define your routes using the `app.route` decorator. For example, to create a new to-do item, you could define a route like this:

```
@app.route('/to-do/<int:id>', methods=['PUT']) def edit_to_do(id): to_do = get_to_do(id) if request.method == 'PUT': to_do = request.json['data'] update_to_do(to_do) return {'message': 'To-do item edited successfully.'} else: return {'message': 'Invalid request method.'}
```

This route accepts a `PUT` request with an `id` parameter, which represents the ID of the to-do item to edit. It retrieves the to-do item from the database using the `get_to_do` function, updates it with the data provided in the request, and returns a success message if the request is a `PUT` request. If the request is anything else, it returns an error message.

3. Set up authentication: To authenticate users, you could use Flask's built-in authentication features. For example, you could use sessions to store user data and require users to log in before accessing certain routes. Here's an example of how you could implement login:

```
from flask import Flask, request, redirect, url_for from flask_login import LoginManager, UserMixin, LoginFailed, UserMixin app = Flask(__name__) login_manager = LoginManager() login_manager.init_app(app)

class ToDoList(UserMixin): pass

login_manager.init_app(ToDoList())

@login_manager.user_loader def user_loader(id): return ToDoList()

@app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] user = UserMixin.authenticate(username, password) if user: return redirect(url_for('index')) return render_template('login.html')

@app.route('/logout') def logout(): login_manager.logout() return redirect(url_for('index'))

@app.route('/to-do') def index(): to_do_list = get_to_do_list() return render_template('index.html', to_do_list=to_do_list)
```

This code sets up a Flask app with a `ToDoList` class that implements the `UserMixin` from Flask-Login. It also defines a `user_loader` function that retrieves the user data from the database using the `UserMixin.authenticate` method.

The `login` route checks if the request method is `POST` and if the form data contains a username and password. If the user is authenticated, it redirects to the index page. If not, it renders the `login.html` template.

The `logout` route simply logs out the user using the `login_manager.logout` method.

4. Set up the database: To store the to-do items, you could use a database like SQLite or MySQL. Here's an example of how you could connect to a SQLite database using Flask-SQLAlchemy:

```
from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///to_do.db' db = SQLAlchemy(app)
```

This code sets up a Flask app with a SQLite database using Flask-SQLAlchemy. The `SQLAlchemy` class is used to create a database object that connects to the database using the `SQLALCHEMY_DATABASE_URI` configuration option.

5. Define the models: To define the models for the to-do items, you could use SQLAlchemy. Here's an example of how you could define a model for a to-do item:

```
from flask_sqlalchemy import Column, Integer, String from flask_login import UserMixin class ToDoItem(db.Model, UserMixin): id = Column(Integer, primary_key=True) title = Column(String(50)) completed = Column(Boolean, default=False) user_id = Column(Integer, ForeignKey('users.id')) user = db.relationship('UserMixin', backref='to_do_items')
```

This code defines a `ToDoItem` model that uses SQLAlchemy to define the columns for the to-do item. It also defines a `user_id` column that references the user ID in the database.

6. Define the views: To handle the HTTP requests, you could define the views using the `app.route` decorator. Here's an example of how you could define the views for the to-do list:

```
from flask import Flask, request, jsonify from flask_login import LoginManager, UserMixin, LoginFailed, UserMixin app = Flask(__name__) login_manager = LoginManager() login_manager.init_app(app)

class ToDoList(UserMixin): pass

login_manager.init_app(ToDoList())

@login_manager.user_loader def user_loader(id): return ToDoList()

@app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] user = UserMixin.authenticate(username, password) if user: return redirect(url_for('index')) return render_template('login.html')

@app.route('/logout') def logout(): login_manager.logout() return redirect(url_for('index'))

@app.route('/to-do') def index(): to_do_list = get_to_do_list() return render_template('index.html', to_do_list=to_do_list)

@app.route('/to-do/<int:id>', methods=['PUT']) def edit_to_do(id): to_do = get_to_do(id) if request.method == 'PUT': to_do = request.json['data'] update_to_do(to_do) return {'message': 'To-do item edited successfully'} return {'message': 'Invalid request method'}

@app.route('/to-do/<int:id>', methods=['DELETE']) def delete_to_do(id): to_do = get_to_do(id) if request.method == 'DELETE': delete_to_do(to_do) return {'message': 'To-do item deleted successfully'} return {'message': 'Invalid request method'}
```

This code defines the `ToDoList` class that implements the `UserMixin` from Flask-Login. It also defines the `login` route that checks if the request method is `POST` and if the form data contains a username and password. If the user is authenticated, it redirects to the index page. If not, it renders the `login.html` template.

The `logout` route simply logs out the user using the `login_manager.logout` method.

The `index` route retrieves the to-do list using the `get_to_do_list` function and renders the `index.html` template with the `to_do_list` parameter.

The `edit_to_do` and `delete_to_do` routes handle PUT and DELETE requests for a specific to-do item. The `edit_to_do` route updates the to-do item with the data provided in the request body. The `delete_to_do` route deletes the to-do item with the ID provided in the request body.

Дополнительно модель сопровождает свои рекомендации детальными комментариями и примерами кода.

Далее прошу модель написать лэндинг для этого проекта, она понимает буквально и пишет презентационный текст, добавляя в него своё представление о том, как могло бы выглядеть современное To-Do приложение с приминением ИИ ассистента:

> For now I want you to write a landing page of this project

Welcome to the AI Assistant Project!

Our project aims to create an AI assistant that can help people find information and complete tasks more efficiently. We believe that with the help of AI, people can save time and effort in completing their daily tasks.

Our AI assistant will be designed to understand natural language and respond accordingly. This means that users can speak to our assistant as they would to a human, and our assistant will be able to understand and respond appropriately.

We are currently in the development phase of our project and are excited to see the final product come to life. We will keep you updated on our progress and look forward to hearing your feedback.

Thank you for your interest in our project!

Прошу модель написать код для лэндинга:)

> write a html code for a landing page with this text

<!DOCTYPE html> <html> <head> <title>AI Assistant Project</title> </head> <body> <h1>AI Assistant Project</h1> <p>Our project aims to create an AI assistant that can help people find information and complete tasks more efficiently. With the help of AI, users can speak to our assistant as they would to a human, and our assistant will be able to understand and respond appropriately.</p> </body> </html>

Прошу модель написать запрос для midjorney, для создания интерфейса для приложения:

> Write a prompt for midjorney to draw a ui of to-do app

Design a user interface for a to-do app that helps users manage their daily tasks and goals. The app should have a clean and simple design, with clear labels and intuitive navigation. The home screen should display the user's daily tasks and goals, with the ability to add new tasks and view completed tasks. The app should also have a search bar to help users find specific tasks quickly. The navigation should include options to view upcoming tasks, completed tasks, and archived tasks. The app should be available on multiple devices, including smartphones and tablets.

Послесловие

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

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

Такими темпами, которые сейчас набирает открытое сообщество и при поддержке не финансовых организаций с финансовой точки зрения или на уровне оборудования для обучения (Cerebras, EleutherAI), свободную открытую модель качества GPT-3.5 (ChatGPT) мы можем увидеть уже в этом году, а уровень GPT-4 может открыться с движением в сторону увеличения окна контекста, мультимодальности, архитектурных улучшениях и новых прорывах в оптимизации инференса и обучения моделей.