Building LangGraph — конспект и практическое резюме

Building LangGraph — конспект и практическое резюме


Руководство по LangGraph: Построение Структурированных AI-Агентов и Мульти-Агентных Систем

LangGraph — это мощная библиотека из экосистемы LangChain, предназначенная для создания сложных, $N$-шаговых рабочих процессов (workflows) и систем, состоящих из нескольких взаимодействующих AI-агентов. LangGraph позволяет точно определить, координировать и выполнять последовательности, циклы и разветвления логики, что делает его идеальным инструментом для разработки продвинутых приложений на базе больших языковых моделей (LLM) datacamp.com.

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


1. Основы LangGraph: Ключевые Строительные Блоки

LangGraph решает проблему управления состоянием и координации в сложных LLM-приложениях, особенно в сценариях с циклами (loops) и множеством агентов. Его архитектура основана на концепции направленного графа состояний (Stateful Graph) datacamp.com.

К основным элементам LangGraph относятся:

1.1. State (Состояние)

Состояние (State) — это центральный элемент LangGraph. Это общий объект памяти, который проходит через весь граф, объединяя информацию между различными узлами. Состояние хранит все релевантные данные: сообщения, переменные, промежуточные результаты и историю принятия решений. LangGraph автоматически управляет этим состоянием datacamp.com.

1.2. Nodes (Узлы)

Узлы (Nodes) представляют собой дискретные шаги обработки или действия в рабочем процессе. Это могут быть:

  • Функции, которые выполняют определенную логику (например, вызов LLM, использование инструмента, или форматирование данных).
  • Конкретные агенты в мульти-агентной системе.

1.3. Edges (Границы/Переходы)

Границы (Edges) определяют, как управление передается от одного узла к другому. Существует два основных типа переходов:

  1. Простые переходы (add_edge): Задают фиксированный путь: после выполнения Узла $A$ всегда выполняется Узел $B$.
  2. Условные переходы (add_conditional_edges): Позволяют графу принимать решения. После выполнения Узла $A$ вызывается функция (или агент), которая анализирует текущее State и возвращает имя следующего узла. Это позволяет создавать циклы и логику ветвления (например, “продолжить работу”, “использовать инструмент” или “завершить”) datacamp.com.

1.4. Graph Construction (Построение Графа)

LangGraph предоставляет два основных класса для построения графов:

  • Graph: Базовый класс для создания последовательных рабочих процессов без автоматического управления состоянием.
  • StateGraph: Наиболее часто используемый класс, который наследуется от Graph, но включает обязательный параметр State и управляет им, делая его идеальным для агентов и циклов.

2. Построение Одно-Агентной Системы с Использованием Циклов

Типичный LangGraph-агент использует условные переходы для создания цикла “Мыслить $\rightarrow$ Использовать Инструмент $\rightarrow$ Мыслить Снова”.

Шаг 1: Определение Состояния

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

from typing import TypedDict, Annotated
from langgraph.graph.message import AnyMessage, add_messages

# Определяем схему состояния
class AgentState(TypedDict):
    """
    Состояние графа. Messages - это список сообщений,
    которые добавляются и передаются между узлами.
    """
    messages: Annotated[list[AnyMessage], add_messages]
    # Дополнительные поля (например, history, tool_result) могут быть добавлены здесь.

Шаг 2: Создание Узлов (Агентов и Функций)

Узел агента будет отвечать за принятие решений и вызов LLM.

from langgraph.prebuilt import ToolExecutor, ToolInvocation
from langchain_core.tools import tool

# 1. Определим инструменты
@tool
def search_web(query: str) -> str:
    """Используйте это, чтобы найти информацию в интернете."""
    # Заглушка для реального вызова API
    return f"Результат поиска для '{query}': Данные о последних выборах."

tools = [search_web]
tool_executor = ToolExecutor(tools)

# 2. Узел для вызова LLM
def run_agent(state: AgentState):
    """Основной узел агента: вызывает LLM и получает решение."""
    messages = state["messages"]
    # Вызов LLM (LangChain Runnable)
    # response = llm.invoke(messages) 
    
    # Заглушка для ответа LLM
    response = ("thought", "action") 
    
    return {"messages": [response]} 

# 3. Узел для вызова инструмента
def execute_tool(state: AgentState):
    """Узел: выполняет инструмент, запрошенный агентом."""
    # Логика извлечения ToolInvocation из 'messages' и вызова tool_executor.invoke()
    # tool_call = state["messages"][-1].tool_calls[0]
    # tool_result = tool_executor.invoke(tool_call)
    
    # Заглушка для результата
    tool_result = {"key": "tool_result_data"} 
    
    # Добавляем результат обратно в сообщения
    return {"messages": [("tool_output", tool_result)]}

Шаг 3: Определение Условного Перехода

Это функция, которая определяет, должен ли агент использовать инструмент, или завершить выполнение.

def should_continue(state: AgentState) -> str:
    """Определяет, должен ли граф продолжать работу (использовать инструмент) 
    или завершить (дать финальный ответ)."""
    
    last_message = state["messages"][-1]

    # Если LLM запросил использование инструмента (в реальной системе)
    # if "tool_calls" in last_message: 
    #     return "continue_tool"
    
    # Если это заглушка, пусть завершает
    return "end" # Или "continue_tool" для цикла

Шаг 4: Построение и Компиляция Графа

Используем StateGraph для сборки нашего рабочего процесса.

from langgraph.graph import StateGraph, END

# Инициализация графа состояния
workflow = StateGraph(AgentState)

# 1. Добавление узлов
workflow.add_node("agent", run_agent)
workflow.add_node("call_tool", execute_tool)

# 2. Установка начальной точки
workflow.set_entry_point("agent")

# 3. Добавление условных переходов
workflow.add_conditional_edges(
    "agent",                 # Источник
    should_continue,         # Функция для принятия решения
    {
        "continue_tool": "call_tool", # Если нужно использовать инструмент, идем в call_tool
        "end": END                   # Если завершаем, переходим в END
    }
)

# 4. Добавление простого перехода (после инструмента, снова к агенту)
workflow.add_edge('call_tool', 'agent')

# 5. Компиляция
app = workflow.compile()

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


3. LangGraph для Мульти-Агентных Систем

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

В мульти-агентной системе LangGraph используется, чтобы:

  1. Роутинг: Направлять задачу соответствующему эксперту (узлу) в зависимости от текущего состояния или запроса.
  2. Параллелизм: Выполнять несколько узлов одновременно (хотя в базовом StateGraph обычно используется пошаговая передача управления).
  3. Передача эстафеты: Определять логику, по которой один агент передает результат своей работы другому.

Пример Архитектуры Мульти-Агента

Представим систему, где есть два агента: Генератор (Generator) и Редактор (Reviewer).

  1. Начальный Узел (Router): Получает запрос и направляет его Генератору.
  2. Генератор (Node A): Создает черновик ответа, используя свои инструменты.
  3. Условный Переход: Функция needs_review(state) проверяет качество черновика.
    • Если нужна доработка: Переход к Редактору (Node B).
    • Если готов: Переход к END.
  4. Редактор (Node B): Анализирует черновик и добавляет критические замечания или правки.
  5. Цикл: Редактор передает управление обратно Генератору для внесения исправлений, пока needs_review не вернет “готов”.

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

4. Продвинутые Возможности

A. Checkpointing (Контрольные Точки)

LangGraph поддерживает контрольные точки (checkpointing), что критически важно для долговременных, многоходовых бесед или процессов. Checkpointing сохраняет каждое состояние графа, позволяя возобновить выполнение с любого шага или агента после прерывания. Это также удобно для отладки и аудита datacamp.com.

B. Встроенные Агенты

LangGraph предлагает предварительно сконфигурированные агенты и графы, такие как create_react_agent, которые упрощают развертывание стандартных реактивных (ReAct) агентов.


Заключение

LangGraph предоставляет необходимый структурный каркас для перехода от простых LangChain-цепочек к сложным, надежным и масштабируемым AI-приложениям. Используя концепции узлов, состояния и условных переходов, разработчики могут создавать детерминированные циклы агентов и сложные системы оркестровки, которые были бы чрезвычайно сложны в реализации без явного управления графом состояний.


Хотите построить DWH на ClickHouse?

Мы проектируем и разворачиваем аналитические хранилища на ClickHouse. Настраиваем ETL, создаем витрины данных, интегрируем с BI-инструментами.

📞 +7 (924) 547-36-78 📧 info@bi-ai.ru 💬 Telegram: @bi_ai_team