Найти тему

Как с помощью LangChain научить ИИ делать что-то полезное

Оглавление
На начальном этапе социализма разделение труда необходимо для повышения производительности и создания изобилия продуктов. Но на высшей фазе коммунизма оно должно быть преодолено, чтобы труд перестал быть тяжким бременем для человека.
К сожалению, в своих работах я не затрагивал эту тему в контексте возникновения «думающих машин», поскольку в то время технологии ещё не достигли такого уровня развития. Однако, на мой взгляд, автоматизация определённых процессов с использованием таких машин может сыграть положительную роль в освобождении людей от тяжёлого физического и монотонного умственного труда. Это позволит рабочим больше времени уделять творческой, интересной деятельности, а учёным и инженерам - сосредоточиться на самых сложных интеллектуальных задачах.
Применение «думающих машин» способно приблизить нас к такому общественному устройству, где различия между людьми физического и умственного труда будут стираться. Хотя, конечно, для полного решения этой задачи потребуется более фундаментальные изменения в экономических отношениях и всём укладе общественной жизни при социализме.
(С) ЛЕНИН, модель ИИ от группы «Свободное время».
FUSION BRAIN: Ленин размышляет о роли «думающих машин» в  преодолении разницы между людьми физического и умственного труда
FUSION BRAIN: Ленин размышляет о роли «думающих машин» в преодолении разницы между людьми физического и умственного труда

В чём затруднения для широкого применения существующих моделей ИИ в полезной практической деятельности сейчас? На мой взгляд - в недостаточно хорошей предсказуемости получаемых результатов. Любая модель время-от времени может выдавать информацию не соответствующую действительности и здравому смыслу. Для этого явления даже появилось название "галлюцинации моделей ИИ". Чем-то эта информация, извлеченная из груды весовых коэффициентов, похожа на обрывки сновидений, которые соединены самым причудливым образом.

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

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

Сплав таких подходов воплощается в таком понятии, как "агент". И эта концепция уже некоторое время активно развивается. Одна из наиболее развитых платформ-конструкторов такого рода на сегодня - это LangChain, открытый набор библиотек для создания приложений на основе больших языковых моделей (LLM) с использованием языка программирования Python.

FUSION BRAIN: Агент LangChain в застенках дата-центра
FUSION BRAIN: Агент LangChain в застенках дата-центра

Предоставленная разработчиком документация весьма обширна - многие сотни страниц текста на английском языке и, разумеется, в одной статье такую сложную тему должным образом отразить нельзя. Здесь я уделю внимание только некоторым основам, отталкиваясь от которых можно изучать материал дальше и создавать собственные проекты. Я и сам нахожусь в процессе изучения темы создания "агентов" и данная статья - "итерация 0" на этом пути.

Начиналось всё с опробования работы из программы на python с моделями для локального развёртывания. Для этой цели существуют разные библиотеки, я остановился на GPT4All, потому что она затем легко интегрируется с LangChain.

Немного о GPT4All.

Особенность, привлекшая меня - возможность локальной работы с моделями весовых коэффициентов на мощностях обычного микропроцессора, без необходимости использования видеокарты. Это не так быстро, но зато значительно дешевле, если у вас ещё нет видеокарты хотя бы с 8, а лучше 16 или 24 Гб оперативной памяти на борту (и желательно NVIDIA).

Компания-разработчик этой библиотеки - Nomic AI поддерживает и развивает экосистему, регулярно добавляя новые функции. На её сайте представлена подборка наиболее подходящих для этой библиотеки моделей. Хотя можно скачать и опробовать и многие другие (с Hugging Face, разумеется). Для работы без видеокарты нужно искать там модели в формате GGML (новая версия - GGUF). И большая коллекция файлов в таком формате представлена у Тома Джоббинса (TheBloke)

Файлы весовых коэффициентов, рекомендуемые для работы с GPT4All разработчиком
Файлы весовых коэффициентов, рекомендуемые для работы с GPT4All разработчиком

Основные компоненты пакета:
gpt4all-backend — бэкенд на языке Си, который поддерживает универсальный API для запуска LLM;
gpt4all-bindings — обвязки для разных языков программирования (Python, C++, Go и др.), которые работают с API бэкенда;
gpt4all-chat — кроссплатформенное настольное приложение для чата с LLM;
gpt4all-api — REST API для взаимодействия с моделями.

Чтобы начать работать с GPT4All в Python, нужно обзавестись моделью ggml и выполнить следующие шаги:

1. Установить пакет gpt4all:
pip install gpt4all

2. Импортировать библиотеку:
import gpt4all

3. Создать экземпляр модели, указав путь к файлу модели на диске:
model = gpt4all.GPT4All("/home/AI/model.ggml")

4. Сгенерировать текст с помощью модели:
output = model.generate("Hello, my name is…")
print(output)

5. Можно настроить параметры генерации, например максимальное количество токенов:
output = model.generate("Hello, my name is…", max_tokens=2)

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

Для более тонкой настройки генерации нужно узнать какие ещё параметры можно передать методу generate(). Для этого можно заглянуть в исходник gpt4all.py и выполнить поиск в нём строчки «def generate(»

Вот что там имеется:

self, prompt: str, max_tokens: int = 200, temp: float = 0.7, top_k: int = 40, top_p: float = 0.4, repeat_penalty: float = 1.18, repeat_last_n: int = 64, n_batch: int = 8, n_predict: Optional[int] = None, streaming: bool = False, callback: pyllmodel.ResponseCallbackType = pyllmodel.empty_response_callback,

Большинство параметров имеют значения по умолчанию, благодаря чему их и можно не указывать при вызове функции. Но если надо, можно указать и другие. Нужно только предварительно разобраться за что они отвечают.

prompt - строка, содержащая подсказку для модели, на которую нужно сгенерировать ответ.

max_tokens - максимальное количество токенов для генерации ответа.
temp - температура модели. Чем выше, тем более творческие, но менее фактически точные ответы. При значении от 0 до 1 вероятность получения лучших токенов-кандидатов максимальная, при больших значениях поле для выбора расширяется, а избирательность падает. Значение температуры 0 даёт наилучший токен, но делает выходные данные детерминированными. Значение 1 представляет собой нейтральное значение с точки зрения случайности процесса.

top_k — ограничивает количество токенов-кандидатов фиксированным числом после сортировки по вероятности. Установка значения выше размера словаря отключает это ограничение. В ответ попадает слово, случайным образом выбранное из top_k наиболее вероятных токенов на каждом шаге генерации.

top_p — альтернативный top_k подход, позволяющий выбирать выбирает токены, пока сумма их вероятностей не достигнет указанного значения. Например, значение 0.8 означает, что будут включены лучшие токены, совокупные вероятности которых достигают или просто превосходят 80%. Установка этого параметра равным 1 фактически отключает его.

repeat_penalty — наказание за повторение токенов. Чем выше, тем меньше повторов. По умолчанию 1.18.

repeat_last_n — как далеко в истории генерации можно применить штраф за повторение.

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

n_predict - макс. кол-во токенов для генерации, аналог max_tokens, существующий для обратной совместимости.
streaming - возвращать ли генератор токенов или сразу весь текст. Если установить значение этого параметра True, то токены будут передаваться по мере их генерации моделью.

callback - функция обратного вызова для обработки токенов по мере генерации. В качестве аргументов она получает token_id (целое число) и reponse (строка). Когда генерация завершается, функция возвращает значение False.

Пример программы на python для чата с моделью с помощью GPT4All
Пример программы на python для чата с моделью с помощью GPT4All

Кстати, модель xwincoder-13b имеет смысл попробовать тем, кто хочет сделать себе ассистента/помощника по вопросам программирования. Похоже обучающая выборка для этой модели была довольно основательной по этой теме. Вот примеры ответов, которые были с помощью неё получены.

 XwinCoder-13B знает 10 парадигм программирования.
XwinCoder-13B знает 10 парадигм программирования.

Можно было бы рассказать ещё много о этой библиотеке, но пора переходить к LangChain.

Введение в LangChain (понятия)

Платформа LangChain (языковая цепочка) обеспечивает основу для подключения языковых моделей к другим источникам данных и взаимодействия с различными API. Она спроектирован так, чтобы её было легко использовать даже разработчикам, не знакомым с языковыми моделями.

Как работает LangChain?
LangChain предоставляет набор абстракций, которые упрощают взаимодействие с языковыми моделями. Эти абстракции включают в себя:

  • Агенты (Agents): являются основными компонентами Langchain. Они отвечают за выполнение конкретных задач, таких как генерация текста, обобщение и ответы на вопросы.
  • Воспоминания (Memories): воспоминания используются для хранения состояния между вызовами агента. Это позволяет агентам учиться на опыте своих предыдущих взаимодействий и принимать более правильные решения в будущем.
  • Цепочки (Chains): - это последовательности агентов, которые используются для выполнения конкретных задач. Например, цепочку можно использовать для обобщения (суммаризации) длинного фрагмента текста или для ответа на вопрос по определённой теме.

Как начать работать с LangChain?
Для этого необходимо установить пакет LangChain. Вы можете сделать это выполнив следующую команду: pip install langchain

Ну а далее просто импортируйте нужные модули в свою программу на python и следуя документации используйте их в своём проекте.

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

Модули в LangChain
LangChain предлагает множество модулей, которые можно использовать для разработки приложений на основе языковых моделей. Некоторые из них включают в себя: память (memory), подсказка (prompt), цепочка (chain), обратные вызовы (call backs), агенты (agents), модели (models).

Основные компонеты платформы LangChain
Основные компонеты платформы LangChain

models
Содержимое «модели» преимущественно относится к работе с большими языковым моделями (LLM) различных типов, как локальных так и доступных как облачная услуга от таких компаний как OpenAI (ChatGPT) Google (PaLM, BERT, GPT-4) и других.

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

Шаблоны подсказок можно использовать для создания чат-ботов, которые могут понимать вводимые пользователем данные и генерировать ответы, соответствующие запросу пользователя, осуществлять обобщение текста (суммаризацию), генерировать код по описанию на естественном языке. Также подсказки/шаблоны подсказок можно использовать для создания систем вывода на естественном языке, которые могут определять взаимосвязь между двумя утверждениями.

memory
«Память» - в LangChain это способ отслеживания состояния разговора. Её можно использовать для повышения эффективности языковых моделей, предоставляя им контекст из предыдущих сообщений.

Предусмотрено множество разных способов реализации памяти в LangChain. Некоторые из наиболее распространённых методов:

  • Буферная память (Buffer memory). Это простейшая форма памяти, в которой просто хранится буфер всех предыдущих сообщений. - Сводная память (Summary memory). В памяти этого типа хранится сводная информация об истории разговоров, например, N последних сообщений или список упомянутых ключевых слов.
  • Память seq2seq. Этот тип памяти использует последовательность модели для изучения представления истории разговора. Это представление затем можно использовать для повышения производительности языковых моделей при выполнении последующих задач, таких как ответы на вопросы и обобщение.

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

Для истории сообщений чата имеется класс памяти ChatMessageHistory — один из важных классов в модулях langchain. Это удобная легкая оболочка, которая помогает сохранять сообщения людей и искусственного интеллекта, а затем извлекать их все. Этот класс обычно используется, если вы пытаетесь управлять памятью вне цепочки. С помощью оболчки этого класса, например, реализован разговорный буфер — класс ConversationBufferMemory, который извлекает сообщения в переменные.

Chains & Agents
Цепочки и агенты нужны в тех случаях, когда одного вызова API к LLM недостаточно для решения задачи. Например, нам может потребоваться получить информацию с какого-либо сайта, а затем предоставить эту информацию в качестве входных данных для модели. Этот модуль в LangChain позволяет объединить несколько инструментов для решения сложных задач.

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

Существуют два основных типа агентов:

  1. Агенты действий (Action agents): на каждом временном этапе принимают решение о следующем действии, используя результаты всех предыдущих действий.
  2. Агенты планирования и выполнения (Plan-and-execute agents): заранее определите полную последовательность действий, а затем выполните их все без обновления плана.

Но хватит общих слов. Пора уже посомтреть, как начать работать с этим набором инструментов на каком-нибудь примере.

Пишем первую программу с использованием LangChain

Запускаем Atom, создаём новый файл, сохраняем его с раширением .py и первым делом импортируем необходимые компоненты:

Импортируем компоненты из LangChain для создания шаблонов подсказок ИИ модели
Импортируем компоненты из LangChain для создания шаблонов подсказок ИИ модели

Для работы с моделью через бэкенд GPT4All в LangChain существует класс-обёртка. Его нам нужно тоже импортировать.

Импортируем компоненты из LangChain для создания диалогового агента на основе GPT4All
Импортируем компоненты из LangChain для создания диалогового агента на основе GPT4All

Инициализируем модель, передав GPT4All начальные параметры - путь к весовым коэффициентам на диске, размер контекста, температуру и суммарную вероятность токенов (top_p).

Инициализируем модель через GPT4All
Инициализируем модель через GPT4All

Шаблон для подсказок чата поручим формировать объекту класса ChatPromptTemplate. Его можно импортировать из langchain.prompts. С помощью него мы определим формат взаимодействия с агентом. Он будет строиться по шаблону, состоящему из системных сообщений, сообщений пользователя и местозаполнителя (MessagesPlaceholder) для истории диалога.

Определяем шаблон подсказки для ИИ модели
Определяем шаблон подсказки для ИИ модели

MessagesPlaceholder — это специальный класс в LangChain, который используется для того, чтобы вставлять историю сообщений чата в шаблон подсказки. Его мы также импортиртировали из langchain.prompts.

Когда мы создаём шаблон подсказки ChatPromptTemplate, то определяем несколько элементов:

  1. Системные сообщения (инструкции для модели).
  2. Сообщения пользователя.
  3. Местозаполнитель для истории сообщений.

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

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

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

Создаём память и цепочку диалога
Создаём память и цепочку диалога

За цепочку диалога будет отвечать класс ConversationChain и langchain.chains. Он объединит модель GPT4All, шаблон подсказки и память диалога. Вызывая метод predict() мы сможем получать ответы модели. На вход этому методу подаётся текст реплики пользователя и шаблон подсказки, который формируется с учётом истории диалога из памяти.

Полученный ответ сохраняется в памяти, и цикл повторяется для следующей реплики пользователя. Таким образом реализуется диалог с сохранением контекста беседы. Модель GPT4All генерирует человекоподобные ответы, следуя заданной ей роли помощника.

Итоговая программа диалогового агента, созданного с помощью LangChain
Итоговая программа диалогового агента, созданного с помощью LangChain

На этом пока всё. В следующий раз погрузимся в недра LangChain немного более основательно.

FUSION BRAIN: Агент LangChain в деле
FUSION BRAIN: Агент LangChain в деле

При подготовке материала были использованы ресурсы:
1. Подробное руководство по LangChain: создание мощных приложений с большими языковыми моделями (
ссылка).
2. Build Chatbot Webapp with LangChain (
ссылка)
3. LangChain Docs (
ссылка)
4. Сервис
https://you.com/
5. Сервис
https://youai.ai/