Большие языковые модели (LLM) в задачах
В этой статье на практических примерах рассмотрим какие задачи из коробки могут решать современные большие языковые модели (large language models, LLM).
Но сначала немного теории…
Что такое LLM?
Большая языковая модель — это тип модели глубокого обучения, которая понимает и генерирует текст на человеческом языке. Эти модели обучаются на огромных объемах текстовых данных (книги, статьи, сайты и др. источники) и содержат в себе большое число параметров.
Параметры — это переменные, присутствующие в модели, и которые изменяются в процессе обучения. Считается, что языковая модель является большой если содержит больше одного миллиарда параметров. Именно благодаря большому числу параметров LLM и способны распознавать, переводить, прогнозировать или генерировать текст или другой контент.
Обычно на вход таким моделям подается одно или несколько предложений. По которым модель пытается понять, что от нее хотят и генерирует ответ.
Под капотом у современных LLM-моделей используется архитектура трансформер.
Подопытный кролик
Теперь надо определится с инструментом, с помощью которого будем проводить эксперименты. Согласно лидерборду RussianSuperGLUE лучшая на текущий момент модель для работы с русским текстом — Mistral 7B LoRA. Ее и будем использовать для экспериментов.
Mistral 7B LoRA это SOTA на общих тестах. Возможно для каких-то ваших специфических задач окажутся более подходящими другие модели.
Mistral 7B LoRA это модель дообученная (на русских текстах) методом LoRA на основе LLM Mistral. Чтобы задействовать ее нам понадобится следующие библиотеки:
pip install transformers accelerate peft
Чтобы отправить запрос в Mistral 7B LoRA необходимо выполнить такой код:
import torch
from peft import PeftModel, PeftConfig
from transformers import AutoModelForCausalLM, AutoTokenizer, GenerationConfig
MODEL_NAME = "IlyaGusev/saiga_mistral_7b"
# Загружаем модель
config = PeftConfig.from_pretrained(MODEL_NAME)
model = AutoModelForCausalLM.from_pretrained(
config.base_model_name_or_path,
torch_dtype=torch.float16,
device_map="auto"
)
model = PeftModel.from_pretrained(
model,
MODEL_NAME,
torch_dtype=torch.float16
)
model.eval()
# Определяем токенайзер
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, use_fast=False)
generation_config = GenerationConfig.from_pretrained(MODEL_NAME)
# Функция для обработки запросов
def generate(model, tokenizer, prompt, generation_config):
data = tokenizer(prompt, return_tensors="pt", add_special_tokens=False)
data = {k: v.to(model.device) for k, v in data.items()}
output_ids = model.generate(
**data,
generation_config=generation_config
)[0]
output_ids = output_ids[len(data["input_ids"][0]):]
output = tokenizer.decode(output_ids, skip_special_tokens=True)
return output.strip()
# Формируем запрос
PROMT_TEMPLATE = 'system\nТы — Сайга, русскоязычный автоматический ассистент. Ты разговариваешь с людьми и помогаешь им.user\n{inp}bot\n'
inp = 'Какое расстояние до Луны?'
prompt = prompt_template.format(inp=inp)
# Отправляем запрос в llm
output = generate(model, tokenizer, prompt, generation_config)
print(output)
Что здесь происходит подробно расписывать не буду (статья не об этом). Все что нужно знать: чтобы поменять запрос к LLM — нужно изменить переменную inp
.
Задачи
А теперь рассмотрим различные задачи, которые могут выполнять LLM.
Почти все приведенные здесь задачи LLM умеет выполнять из коробки. Без хардкорного дообучения. Для этого достаточно правильно сформулировать запрос. Причем чем «точнее» вы сформулируете запрос тем качественнее получите результат.
Генеративные задачи
Генерация текста
Самый простой и очевидный вариант использования. Можно попросить модель сгенерировать текст на любую тему: сочинить стихи, написать песню, рассказ или маркетинговый материал и многое другое.
Пример запроса:
Напиши короткий рассказ как я провел лето в деревне. В стиле Гарри Поттера.
Ответ:
Лето в деревне было невероятно интересным и захватывающим. Мы жили в старинном доме, который напоминал о древних времен магии. Каждый день мы проводили в разных местах деревни, исследуя тайные уголки и открывая новые секреты.
Однажды мы нашли старый заброшенный сад, полный странных растений и цветов. Некоторые из них были похожи на те, что мы видели в книгах о Гарри Поттере. Мы решили, что это могут быть магические растения, которые могут помочь нам найти новые способы использования магии.
В другой день мы обнаружили старый замок, который был запущен и заросший деревьями. Мы решили, что это может быть место, где когда-то жили маги. Мы начали исследовать его, и нашли множество старых книг, записанных на языке магов.
Мы также нашли старый магический календарь, который помог нам понять, что лето — это время, когда магия становится особенно сильной. Мы решили, что это идеальное время для того, чтобы освоить новые заклинания и чары.
Каждый вечер мы собирались вместе и делились своими открытиями и знаниями. Мы научились создавать новые заклинания и чары, которые помогали нам в повседневной жизни. Например, мы научились создавать светильники из лучей солнца, которые помогали нам находить свой путь в темноте.
Когда лето закончилось, мы понимали, что наше лето в деревне было незабываемым и полным приключений. Мы вернулись домой, но с собой взяли много новых знаний и опыта, которые помогли нам стать более сильными и уверенными в себе.
И вот так, благодаря лету в деревне, мы стали магическими учениками, готовыми к новым приключениям и открытиям.
Чем больше контекста и больше деталей вы укажите в запросе, тем качественнее получите результат. Например, в этом запросе мы попросили сгенерировать текст в стиле Гарри Поттера.
Написание кода
Вариация предыдущего пункта. Но настолько более важная/полезная, что под нее обучают отдельные LLM и создают целые сервисы (например, https://github.com/features/copilot). Но писать код умеют и LLM общего назначения.
Пример запроса:
Напиши функцию Python для сортировки списка методом пузырьков.
Ответ:
Вот функция сортировки списка методом пузырька на языке Python:
```python
def bubble_sort (input_list):
# проверяем длину списка
if len (input_list) <= 1:
return input_list
# перебираем все элементы списка
for i in range (len (input_list)):
# перебираем все элементы списка, начиная с текущего индекса
for j in range (len (input_list) — i — 1):
# если следующий элемент больше текущего, меняем их местами
if input_list[j] > input_list[j + 1]:
temp = input_list[j]
input_list[j] = input_list[j + 1]
input_list[j + 1] = temp
return input_list
```Эта функция принимает список в качестве аргумента и возвращает отсортированный список.
Код может быть сгенерирован на разнообразных языках. Например, можно попросить написать SQL запрос и т.д. А чтобы улучшить запрос, укажите, что должна принимать функция, в каком виде формате и что должна возвращать и т.д.
Вопрос-ответ
Надоели гугл и яндекс? Спросите LLM:)
Пример запроса:
Сколько весит Луна?
Ответ:
Луна имеет средний диаметр около 3476 км (2159 миль) и массу около 7.34 × 10^22 кг (1.429 × 10^23 lb). Её гравитационное притяжение на поверхности Земли составляет примерно 1/6 от земного.
Вопрос, конечно же, можно задавать только на какие-то общие темы, которые модель видела во время обучения. Спрашивать ее про приватные данные вашей организации конечно же бесполезно (для этого нужно дообучать модель).
Чат (беседа)
Предыдущий вариант был обособленным. Т.е. каждый вопрос-ответ с т.з. модели существует сам по себе. Но с LLM можно вести осмысленный диалог (до определенной степени). Технически реализация диалога заключается в передаче всей предыдущей цепочки обсуждения вместе с новым сообщением. Шаблон в котором лучше всего подавать такую цепочку может отличатся для разных LLM.
Для Mistral 7B LoRA предложен такой шаблон:
system\nТы — Сайга, русскоязычный автоматический ассистент. Ты разговариваешь с людьми и помогаешь им.
user\n{вопрос_1}
bot\n{ответ_1}
user\n{вопрос_2}
bot\n{ответ_2}
user\n{новый_вопрос}
bot\n
Если с каждый запросом передавать предыдущую историю общения по такому шаблону, то можно получить примерно такой диалог:
Запрос:
Сколько весит луна?
Ответ:
Луна имеет средний диаметр около 3476 км (2159 миль) и массу около 7.34 × 10^22 кг (1.429 × 10^22 lb). Это примерно в 81-м раз меньше массы Земли.
Запрос:
А Марс?
Ответ:
Марс имеет средний диаметр около 6772 км (4212 миль) и массу около 6.39 × 10^23 кг (1.431 × 10^23 lb). Это примерно в 1/10 массы Земли.
Запрос:
А в фунтах?
Ответ:
Если вы хотите знать массу Луны или Марса в фунтах, то можно использовать следующие преобразования:
1 фунт = 0.453592 килограмма
Масса Луны = 7.34 × 10^22 кг = 7.34 × 10^22 × 0.453592 фунта = 3.30 × 10^23 фунтов
Масса Марса = 6.39 × 10^23 кг = 6.39 × 10^23 × 0.453592 фунта = 2.89 × 10^24 фунтов
Таким образом, масса Луны составляет около 3.30 × 10^23 фунта, а масса Марса составляет около 2.89 × 10^24 фунта.
З.Ы. В карточке модели Mistral 7B LoRA предложен отличный класс для управления цепочкой вопрос-ответ.
Аналитические задачи
Решение академических задач
Создатели LLM не забывают и о школьниках :) LLM может решать и математические (и не только) задачи. Правда точность вычислений иногда оставляет желать лучшего. Поэтому ответ нужно перепроверять.
Пример запроса:
Из автобуса на остановке вышло 6 пассажиров, а вошло 11. На следующей остановке вышло 8, вошло 9. Сколько пассажиров стало в автобусе, если вначале в автобусе было 24 пассажира?
Ответ:
В начале в автобусе было 24 пассажира. Затем вышли 6 пассажиров и вошли 11 пассажиров, поэтому их количество увеличилось на 5 (11 — 6 = 5).
На следующей остановке вышли 8 пассажиров и вошли 9 пассажиров, поэтому их количество увеличено на 1 (9 — 8 = 1).
В итоге, количество пассажиров в автобусе стало равным 24 + 5 + 1 = 30.
Классификация
LLM могут и в классическое машинное обучение:)
Пример запроса:
Отзыв: «Я ненавижу этот фильм!»
Какой это отзыв (положительный или отрицательный)?
Ответ:
Это отрицательный отзыв.
Обработка текста
Перепиши текст
Скомуниздили текст с просторов интернета и не знаете как безопасно вставить его в диплом? LLM вам поможет :)
Пример запроса:
Перепиши текст своими словами.
###
Предметом эконометрики являются количественные закономерности между экономическими явлениями. Однако, в отличие от экономической теории, эконометрика делает упор на количественные, а не на качественные аспекты этих явлений. Например, известно, что спрос на товар с ростом его цены падает. Однако, как быстро и по какому закону это происходит, в экономической теории не определяется. Это в каждом конкретном случае делает эконометрика. С другой стороны, математическая экономика строит и анализирует модели экономических процессов без использования реальных числовых значений. Эконометрика же изучает модели на базе эмпирических данных. Наконец, в эконометрике широко используется аппарат математической статистики, особенно при установлении связей между экономическими показателями. В то же время в экономике невозможно проведение управляемого эксперимента, и эконометристы используют свои собственные приемы анализа, которые в математической статистике не встречаются.
###
Ответ:
Эконометрика — это наука, которая изучает количественные закономерности между экономическими событиями. Она отличается от экономической теории тем, что она фокусируется на количественных, а не качественных аспектах этих событий. Например, если цена на товар растет, то спрос на этот товар обычно падает. Однако, сколько и как быстро это происходит, в экономической теории не описывается. Эконометрика же занимается изучением таких вопросов на основе реальных данных.
Математическая экономика, напротив, создает и анализирует модели экономических процессу без использования реальных чисел. Эконометрика же работает с реальными данными.
Кроме того, эконометрика активно использует методы математической статистики, особенно для исследования связей между экономическими показателями. В экономике невозможно провести контролируемый эксперимент, поэтому эконометристы используют свои собственные методы анализа, которые не встречаются в математической статистике.
Обратите внимание, что мы тут текст, над которым надо производить манипуляции, заключили в специальные символы. Модель так лучше понимает, с чем конкретно ей нужно работать.
Перевод
Современные LLM обучаются на множестве языков, поэтому могут и в перевод.
Пример запроса:
Переведи на русский.
###
The National Association for Stock Car Auto Racing, LLC (NASCAR) is an American auto racing sanctioning and operating company that is best known for stock car racing.[1] It is considered to be one of the top ranked motorsports organizations in the world, and is one of the largest spectator sports in America. The privately owned company was founded by Bill France Sr. in 1948,[2] and his son, Jim France, has been the CEO since August 2018.[3] The company is headquartered in Daytona Beach, Florida.[4] Each year, NASCAR sanctions over 1,500 races at over 100 tracks in 48 US states as well as in Canada, Mexico, Brazil and Europe.
###
Ответ:
Американская компания по проведению автомобильных гонок NASCAR (National Association for Stock Car Auto Racing, LLC) является одним из ведущих мировых моторных спортивных организаций и одним из самых популярных видов зрительских мероприятий в США. Она была основана Биллом Франсом-старшим в 1948 году и с тех пор стала известной прежде всего благодаря гонкам на автомобилях типа «stock car». В настоящее время компания возглавляется сыном основателя, Джимом Франсом, который занимает должность генерального директора с августа 2018 года. Головной офис NASCAR расположен в городе Дайтон-Бич, штат Флорида. Каждый год NASCAR проводит более 1500 гонок на более чем 100 трассах в 48 штатах США, а также в Канаде, Мексике, Бразилии и Европе.
Чтобы улучшить запрос укажите исходный и целевой язык перевода. Также можете указать, в каком тоне должен быть перевод, или укажите какой-то жаргон и т.д.
Суммаризация
Можно сократить исходный текст до каких-то удобоваримых размеров.
Пример запроса:
Сократи текст до одного предложения.
###
Вопрос, был ли тирекс охотником или падальщиком, до сих пор не решён. Но набор прогрессивных черт тираннозавра всё больше склоняет палеонтологов к охотничьему образу жизни. Рекс — обладатель хорошо развитого бинокулярного зрения. Бинокулярное зрение — способность фокусироваться на объекте обоими глазами, что даёт более точную оценку расстояния. Такое зрение более свойственно активным охотникам, нежели падальщикам. Отдел мозга тираннозавра, отвечающий за обоняние, также хорошо развит. Можно сослаться, что это свойственно падальщикам, но хорошее обоняние есть у всех плотоядных: как любителей падали, так и превосходных охотников. Также, тираннозавр — обладатель укреплённой челюсти и глубоко посаженных зубов. Что примечательно, челюсть имеет дополнительную подвижность, относительно других тиранозаврид, что обеспечивает повышенную устойчивость при боковых нагрузках. Такая адаптация тоже больше подходит охотнику на крупных животных, нежели падальщику, чья еда не сопротивляется и не может повредить челюсть. Челюсти и зубы тираннозавра будто специально созданы для удержания сопротивляющейся многотонной жертвы. Тираннозавр со своим весом, конечно же, не мог бегать за жертвой, что подтверждают свежие исследования, но выслеживать был вполне в состоянии. Правда тираннозавру и незачем было бегать: его основной рацион — медленные трицератопсы и гадрозавры с углом разворота как у поезда. Об этом свидетельствуют прижизненные следы укусов гигантских челюстей на воротниках и хвостах жертв.
###
Ответ:
Тираннозавр обладает хорошим бинокулярным зрением, хорошо развитым обонянием и укреплённой челюстью, что говорит о том, что он был активным охотником.
Поиск информации
LLM могут производить поиск и по каким-то приватным источникам.
Пример запроса:
Найди в тексте, из чего состоит система экранных представлений?
###
Система экранных представлений AutoCAD MEP управляет тем, как выглядят объекты в видовом экране. Задавая подлежащие отображению объекты и направление, в котором их нужно рассматривать, можно вывести на экран различные отображения, такие как планы, 3D модели, схемы стояков в изометрии и принципиальные схемы. Установка стандартных экранных представлений позволяет сохранить согласованность нескольких чертежей. Система экранных представлений AutoCAD MEP состоит из трех основных компонентов:
— Экранные представления на стр. 228 для управления способом отображения отдельных объектов
— Наборы экранных представлений на стр. 231 для группирования экранных представлений объектов
— Конфигурации экранных представлений на стр. 232 для связывания наборов экранных представлений и направлений взгляда
Эти компоненты имеют иерархическую природу. Каждая конфигурация экранных представлений содержит наборы экранных представлений, а каждый набор экранных представлений содержит экранные представления. Сочетание этих компонентов создает систему экранных представлений:
###
Ответ:
В тесте указано, что система экранных представлений AutoCAD MEP содержит три основных компонента:
— Экранные представления
— Наборы экранных представлений
— Конфигурации экранных представлений
Это наверное не самый полезный пример. Будет больше пользы от поиска по какой-либо базе данных или какому-нибудь документу. Для этого нужно строить хитрые пайплайны. А чтобы этого не делать ручками можно воспользоваться готовыми библиотеками. Например, LangChain или LlamaIndex.
Для LangChain код будет выглядеть примерно так:
from langchain.schema import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.document_loaders import Docx2txtLoader
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.prompts import PromptTemplate
from langchain.llms import HuggingFaceHub
# Загружаем документ
loader = Docx2txtLoader('user_guide.docx')
docs = loader.load()
# Разбиваем документ на части
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
# Переводим части документа в эмбединги и помещаем в хранилище
embedding = HuggingFaceEmbeddings(
model_name='sentence-transformers/distiluse-base-multilingual-cased',
model_kwargs={'device':'cuda:0'},
encode_kwargs={'normalize_embeddings': False}
)
vectorstore = Chroma.from_documents(documents=splits, embedding=embedding)
retriever = vectorstore.as_retriever()
# Подгружаем LLM с HF
llm = HuggingFaceHub(repo_id='lmsys/vicuna-13b-v1.5-16k')
# Формируем шаблон запроса к llm
template = """Используй следующие фрагменты контекста, чтобы в конце ответить на вопрос.
Если ты не нашел ответа, просто скажи, что не знаешь ответа. Не пытайся выдумывать ответ.
Используй максимум три предложения и старайся отвечать максимально кратко.
{context}
Вопрос: {question}
Полезный ответ: """
prompt = PromptTemplate.from_template(template)
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
# Формируем конвеер
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
# Задаем вопрос по документу
out = rag_chain.invoke("Какое назначение у ЛИС?")
print(out)
Здесь мы искали ответ в вордовском файле, но список поддерживаемых источников гораздо шире: это могут и ваши базы данных, и PDF файлы и даже веб-страницы, оперативно подгружаемые из интернета.
Извлечение структурированной информации
Частный случай предыдущего варианта. Информацию можно не просто искать, но и сразу отображать в каком-то структурированном виде. Например, таким образом можно обработать объявления с авито, чтобы вытащить полезную информацию.
Пример запроса:
Извлеки из объявления площадь участка и его стоимость.
Формат вывода:
###
Площадь: 10 соток
Стоимость: 10 000 рублей
###Объявление:
|###
Земельный участок площадью 955 кв.м., расположен в районе Седанки: г. Владивосток, в районе ул. Скатная, д. 40д. Участок обладает отличной транспортной доступностью и инвестиционной привлекательностью. В непосредственной близости находится торговый центр «Седанка Сити». Преимуществом такого расположения является экологически чистый район и минимальное удаление от города Владивостока. В 5-ти минутах езды остановка «Дом ветеранов». 10 минут езды до «Владивостокской международной средней общеобразовательной школы», детского сада «Василёк», «Маленький волшебник», «Вершина Монтессори». В 10-ти минутах езды «Станция Седанка». Земельный участок находится в границах населенного пункта (город Владивосток), что позволяет возводить объект капитального строительства (индивидуальный жилой дом с возможностью прописки). Участок не затапливаемый. Полный пакет документов. Имеется возможность изменения адреса земельного участка. Отсутствуют агентские и иные платежи. Земельный участок предоставлен в аренду сроком на 20 лет. Сумма арендной платы за полный год составляет 4.500 руб. При переуступке права аренды, стоимость арендных платежей не изменяется. Стоимость выкупа земельного участка в собственность — 5% от кадастровой стоимости = 75.208 руб. Плата за договор переуступки права аренды и иные документы отсутствует.
###
Ответ:
Площадь: 955 кв.м.
Стоимость: 75 208 рублей
Вместо заключения
Это далеко не полный перечень задач, которые можно решать с помощью LLM. Можно придумать еще много чего интересного. Конечно ответы которые дает LLM не всегда идеальны и порой их нужно подправлять. Также можно экспериментировать с запросом, меняя его формулировку, чтобы добиться нужного качества
Еще больше можно добиться от LLM дообучив ее. Но это уже совсем другая статья… не переключайтесь :)
З.Ы. Если есть интересные практические примеры использования LLM — пишите их в комментариях :)
---------------------
Мой телеграм-канал