Найти в Дзене
Сам себе Data Scientist

🔥 Магия LangGraph: Секретная техника управления историей сообщений в LLM за 10 минут

Часто многие LLM требуют историю сообщений, чтобы лучше понимать контекст. Так как передача истории сообщений довольно частая ситуация, то рассмотрим на примере: Сперва установим библиотеки: Состоянием (State) в LangGraph может быть TypedDict, Pydantic model или dataclass. Ниже мы будем использовать TypedDict. В состоянии будем хранить историю сообщений. Давайте построим пример графа с одним узлом (node). Наш node - это просто функция Python, которая считывает состояние нашего графа и вносит в него изменения. Первым аргументом этой функции всегда будет состояние: Этот узел (node) просто добавляет сообщение в наш список сообщений и заполняет дополнительное поле. Как видим, мы храним всю историю сообщений и дополняем новым сообщением историю. Давайте далее определим простой граф, содержащий этот узел. Мы используем StateGraph для определения графа, который работает с этим состоянием. Затем мы используем add_node для заполнения нашего графа. Для удобства мы часто проверяем содержимое объ
Оглавление

Часто многие LLM требуют историю сообщений, чтобы лучше понимать контекст.

Так как передача истории сообщений довольно частая ситуация, то рассмотрим на примере:

  1. Как использовать State для определения схемы графа
  2. Как использовать reducers для управления обработкой обновлений состояния.

Сперва установим библиотеки:

pip install -U langgraph langchain
pip install -U langgraph langchain

Пример простого графа

Состоянием (State) в LangGraph может быть TypedDict, Pydantic model или dataclass. Ниже мы будем использовать TypedDict.

Определим State

-3

В состоянии будем хранить историю сообщений.

Определим структуру графа

Давайте построим пример графа с одним узлом (node). Наш node - это просто функция Python, которая считывает состояние нашего графа и вносит в него изменения. Первым аргументом этой функции всегда будет состояние:

-4

Этот узел (node) просто добавляет сообщение в наш список сообщений и заполняет дополнительное поле. Как видим, мы храним всю историю сообщений и дополняем новым сообщением историю.

Давайте далее определим простой граф, содержащий этот узел. Мы используем StateGraph для определения графа, который работает с этим состоянием. Затем мы используем add_node для заполнения нашего графа.

-5

Использование графа

-6
-7

Для удобства мы часто проверяем содержимое объектов сообщений с помощью pretty-print:

-8

Обновление состояния графа с помощью редьюсеров (reducers)

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

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

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

-9

Теперь наш узел можно упростить:

-10

Теперь наша объявленная функция add будет сама делать конкатенацию списков.

-11
-12

MessagesState

LangGraph имеет встроенный reducer add_messages, который обрабатывает эти соображения:

-13
-14
-15

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

-16

Таким образом, данный MessageState сам делает структуру:

-17

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

Основной Telegram-канал со всеми обновлениями

Вам также может понравиться:

✔️ Обучение Python с нуля за 9 месяцев 🔝

#ai #ии #langchain #langgraph #llm #openai