Логотип Зефирнет

Создайте агента кодирования искусственного интеллекта с помощью LangGraph от LangChain

Дата:

Введение

Произошел огромный всплеск приложений, использующих агенты кодирования ИИ. С ростом качества LLM и снижением стоимости вывода становится все проще создавать способных агентов ИИ. Кроме того, экосистема инструментов быстро развивается, что упрощает создание сложных агентов кодирования искусственного интеллекта. Фреймворк Langchain был лидером на этом фронте. В нем есть все необходимые инструменты и методы для создания готовых к использованию приложений искусственного интеллекта.

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

Цели обучения

  • Разберитесь, что такое LangGraph.
  • Изучите основы LangGraph для создания агентов с отслеживанием состояния.
  • Исследуйте TogetherAI, чтобы получить доступ к таким моделям открытого доступа, как DeepSeekCoder.
  • Создайте агент кодирования ИИ, используя LangGraph для написания модульных тестов.
Лангчейн

Эта статья была опубликована в рамках Блогатон по Data Science.

Содержание

Что такое Лангграф?

LangGraph — это расширение экосистемы LangChain. Хотя LangChain позволяет создавать агентов кодирования ИИ, которые могут использовать несколько инструментов для выполнения задач, он не может координировать несколько цепочек или участников на всех этапах. Это крайне важное поведение для создания агентов, выполняющих сложные задачи. LangGraph был задуман с учетом этих вещей. Он рассматривает рабочие процессы агента как циклическую структуру графа, где каждый узел представляет функцию или объект Langchain Runnable, а ребра — это соединения между узлами. 

Основные возможности LangGraph включают в себя 

  • Nodes: любая функция или объект Langchain Runnable, например инструмент.
  • Ребра: определяет направление между узлами.
  • Графы с состоянием: основной тип графика. Он предназначен для управления и обновления объектов состояния при обработке данных через свои узлы.

LangGraph использует это для облегчения циклического выполнения вызовов LLM с сохранением состояния, что имеет решающее значение для поведения агента. Архитектура черпает вдохновение из Преголя и Луч Апача

В этой статье мы создадим агент для написания модульных тестов Pytest для класса Python с методами. И это рабочий процесс.

Лангчейн

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

Но перед этим давайте настроим нашу среду разработки.

Установить зависимости

Первое первым. Как и в любом проекте Python, создайте виртуальную среду и активируйте ее.

python -m venv auto-unit-tests-writer
cd auto-unit-tests-writer
source bin/activate

Теперь установите зависимости.

!pip install langgraph langchain langchain_openai colorama

Импортируйте все библиотеки и их классы.

from typing import TypedDict, List
import colorama
import os

from langchain_openai import ChatOpenAI
from langchain_core.messages import SystemMessage
from langchain_core.messages import HumanMessage
from langchain_core.runnables import RunnableConfig

from langgraph.graph import StateGraph, END
from langgraph.pregel import GraphRecursionError

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

# Define the paths.
search_path = os.path.join(os.getcwd(), "app")
code_file = os.path.join(search_path, "src/crud.py")
test_file = os.path.join(search_path, "test/test_crud.py")

# Create the folders and files if necessary.
if not os.path.exists(search_path):
    os.mkdir(search_path)
    os.mkdir(os.path.join(search_path, "src"))
    os.mkdir(os.path.join(search_path, "test"))

Теперь обновите файл crud.py, добавив код для приложения CRUD в памяти. Мы будем использовать этот фрагмент кода для написания модульных тестов. Для этого вы можете использовать свою программу Python. Мы добавим приведенную ниже программу в наш файл code.py.

#crud.py
code = """class Item:
    def __init__(self, id, name, description=None):
        self.id = id
        self.name = name
        self.description = description

    def __repr__(self):
        return f"Item(id={self.id}, name={self.name}, description={self.description})"

class CRUDApp:
    def __init__(self):
        self.items = []

    def create_item(self, id, name, description=None):
        item = Item(id, name, description)
        self.items.append(item)
        return item

    def read_item(self, id):
        for item in self.items:
            if item.id == id:
                return item
        return None

    def update_item(self, id, name=None, description=None):
        for item in self.items:
            if item.id == id:
                if name:
                    item.name = name
                if description:
                    item.description = description
                return item
        return None

    def delete_item(self, id):
        for index, item in enumerate(self.items):
            if item.id == id:
                return self.items.pop(index)
        return None

    def list_items(self):
        return self.items"""
        
with open(code_file, 'w') as f:
  f.write(code)

Настроить LLM

Теперь мы укажем LLM, который будем использовать в этом проекте. Какую модель здесь использовать, зависит от задач и наличия ресурсов. Вы можете использовать собственные мощные модели, такие как GPT-4, Gemini Ultra или GPT-3.5. Также вы можете использовать модели открытого доступа, такие как Mixtral и Llama-2. В этом случае, поскольку речь идет о написании кода, мы можем использовать точно настроенную модель кодирования, такую ​​как кодер DeepSeekCoder-33B или Llama-2. Сейчас существует несколько платформ для вывода LLM, таких как Anayscale, Abacus и Together. Мы будем использовать Together AI, чтобы сделать вывод о DeepSeekCoder. Итак, получите Ключ API из «Вместе», прежде чем идти дальше. 

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(base_url="https://api.together.xyz/v1",
    api_key="your-key",
    model="deepseek-ai/deepseek-coder-33b-instruct")

Поскольку API Together совместим с OpenAI SDK, мы можем использовать OpenAI SDK Langchain для взаимодействия с моделями, размещенными на Together, изменив параметр base_url на «https://api.together.xyz/v1». В api_key передайте свой ключ API Together, а вместо моделей передайте название модели доступно на сайте Together.

Определить состояние агента

Это одна из важнейших частей LangGraph. Здесь мы определим AgentState, отвечающий за отслеживание состояний агентов на протяжении всего выполнения. В первую очередь это класс TypedDict с сущностями, которые поддерживают состояние агентов. Давайте определим наш AgentState

class AgentState(TypedDict):
    class_source: str
    class_methods: List[str]
    tests_source: str

В приведенном выше классе AgentState class_source хранит исходный класс Python, class_methods для хранения методов класса иtest_source для кодов модульных тестов. Мы определили их как AgentState, чтобы использовать их на этапах выполнения. 

Теперь определите график с помощью AgentState.

# Create the graph.
workflow = StateGraph(AgentState)

Как упоминалось ранее, это граф с состоянием, и теперь мы добавили наш объект состояния.

Определить узлы

Теперь, когда мы определили AgentState, нам нужно добавить узлы. Итак, что же такое узлы? В LangGraph узлы — это функции или любой исполняемый объект, например инструменты Langchain, которые выполняют одно действие. В нашем случае мы можем определить несколько узлов, например, функцию для поиска методов класса, функцию для вывода и обновления модульных тестов для объектов состояния и функцию для записи их в тестовый файл.

Нам также нужен способ извлечения кодов из сообщения LLM. Вот как.

def extract_code_from_message(message):
    lines = message.split("n")
    code = ""
    in_code = False
    for line in lines:
        if "```" in line:
            in_code = not in_code
        elif in_code:
            code += line + "n"
    return code

В приведенном здесь фрагменте кода предполагается, что коды заключены в тройные кавычки.

Теперь давайте определим наши узлы.

import_prompt_template = """Here is a path of a file with code: {code_file}.
Here is the path of a file with tests: {test_file}.
Write a proper import statement for the class in the file.
"""
# Discover the class and its methods.
def discover_function(state: AgentState):
    assert os.path.exists(code_file)
    with open(code_file, "r") as f:
        source = f.read()
    state["class_source"] = source

    # Get the methods.
    methods = []
    for line in source.split("n"):
        if "def " in line:
            methods.append(line.split("def ")[1].split("(")[0])
    state["class_methods"] = methods

    # Generate the import statement and start the code.
    import_prompt = import_prompt_template.format(
        code_file=code_file,
        test_file=test_file
    )
    message = llm.invoke([HumanMessage(content=import_prompt)]).content
    code = extract_code_from_message(message)
    state["tests_source"] = code + "nn"

    return state


# Add a node to for discovery.
workflow.add_node(
    "discover",
    discover_function
)

В приведенном выше фрагменте кода мы определили функцию для обнаружения кодов. Он извлекает коды из AgentState class_source элемент, разбивает класс на отдельные методы и передает его в LLM с подсказками. Вывод сохраняется в AgentState. test_source элемент. Мы заставляем его писать операторы импорта только для случаев модульного тестирования.

Мы также добавили первый узел в объект StateGraph.

Теперь переходим к следующему узлу. 

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

# System message template.

system_message_template = """You are a smart developer. You can do this! You will write unit 
tests that have a high quality. Use pytest.

Reply with the source code for the test only. 
Do not include the class in your response. I will add the imports myself.
If there is no test to write, reply with "# No test to write" and 
nothing more. Do not include the class in your response.

Example:

```
def test_function():
    ...
```

I will give you 200 EUR if you adhere to the instructions and write a high quality test. 
Do not write test classes, only methods.
"""

# Write the tests template.
write_test_template = """Here is a class:
'''
{class_source}
'''

Implement a test for the method "{class_method}".
"""

Теперь определите узел.

# This method will write a test.
def write_tests_function(state: AgentState):

    # Get the next method to write a test for.
    class_method = state["class_methods"].pop(0)
    print(f"Writing test for {class_method}.")

    # Get the source code.
    class_source = state["class_source"]

    # Create the prompt.
    write_test_prompt = write_test_template.format(
        class_source=class_source,
        class_method=class_method
    )
    print(colorama.Fore.CYAN + write_test_prompt + colorama.Style.RESET_ALL)

    # Get the test source code.
    system_message = SystemMessage(system_message_template)
    human_message = HumanMessage(write_test_prompt)
    test_source = llm.invoke([system_message, human_message]).content
    test_source = extract_code_from_message(test_source)
    print(colorama.Fore.GREEN + test_source + colorama.Style.RESET_ALL)
    state["tests_source"] += test_source + "nn"

    return state

# Add the node.
workflow.add_node(
    "write_tests",
    write_tests_function
)

Здесь мы заставим LLM записать тестовые примеры для каждого метода, обновим их до элементаtest_source AgentState и добавим их в объект StateGraph рабочего процесса.

Ребра

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

  • Условное ребро: Ход выполнения зависит от реакции агентов. Это имеет решающее значение для придания цикличности рабочим процессам. Агент может решить, какие узлы перемещать дальше, исходя из некоторых условий. Вернуться ли к предыдущему узлу, повторить текущий или перейти к следующему узлу.
  • Нормальный край: Это обычный случай, когда узел всегда вызывается после вызова предыдущих.

Нам не нужно условие для подключения Discover и Write_tests, поэтому мы будем использовать обычный Edge. Кроме того, определите точку входа, указывающую, где должно начаться выполнение.

# Define the entry point. This is where the flow will start.
workflow.set_entry_point("discover")

# Always go from discover to write_tests.
workflow.add_edge("discover", "write_tests")

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

# Write the file.
def write_file(state: AgentState):
    with open(test_file, "w") as f:
        f.write(state["tests_source"])
    return state

# Add a node to write the file.
workflow.add_node(
    "write_file",
    write_file)

Поскольку это наш последний узел, мы определим границу между write_tests и write_file. Вот как мы можем это сделать.

# Find out if we are done.
def should_continue(state: AgentState):
    if len(state["class_methods"]) == 0:
        return "end"
    else:
        return "continue"

# Add the conditional edge.
workflow.add_conditional_edges(
    "write_tests",
    should_continue,
    {
        "continue": "write_tests",
        "end": "write_file"
    }
)

Функция add_conditional_edge принимает функцию write_tests, функцию must_continue, которая решает, какой шаг предпринять на основе записей class_methods, и сопоставление со строками в качестве ключей и другими функциями в качестве значений.

Край начинается с write_tests и на основе вывода must_continue выполняет любую из опций сопоставления. Например, если состояние["class_methods"] не пусто, мы не написали тесты для всех методов; мы повторяем функцию write_tests, и когда мы закончим писать тесты, выполняется write_file.

Когда тесты для всех методов были выведены из LLM, тесты записываются в тестовый файл.

Теперь добавьте последнее ребро к объекту рабочего процесса для замыкания.

# Always go from write_file to end.
workflow.add_edge("write_file", END)

Выполните рабочий процесс

Последнее, что осталось — скомпилировать рабочий процесс и запустить его.

# Create the app and run it
app = workflow.compile()
inputs = {}
config = RunnableConfig(recursion_limit=100)
try:
    result = app.invoke(inputs, config)
    print(result)
except GraphRecursionError:
    print("Graph recursion limit reached.")

Это вызовет приложение. Предел рекурсии — это количество раз, когда LLM будет выведен для данного рабочего процесса. Рабочий процесс останавливается при превышении лимита.

Посмотреть логи можно на терминале или в блокноте. Это журнал выполнения простого CRUD-приложения.

Ленгчейн

Большую часть тяжелой работы будет выполнять базовая модель, это было демонстрационное приложение с моделью кодера Deepseek, для лучшей производительности вы можете использовать GPT-4 или Claude Opus, haiku и т. д.

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

LangChain против LangGraph

Теперь вопрос в том, когда использовать LangChain, а когда Лангграф.

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

Зачем использовать LangGraph?

LangGraph — это мощная платформа, которая может улучшить многие существующие решения. 

  • Улучшение конвейеров RAG: LangGraph может дополнить RAG своей структурой циклического графа. Мы можем ввести цикл обратной связи для оценки качества полученного объекта и, при необходимости, улучшить запрос и повторить процесс.
  • Многоагентные рабочие процессы: LangGraph предназначен для поддержки многоагентных рабочих процессов. Это имеет решающее значение для решения сложных задач, разделенных на более мелкие подзадачи. Разные агенты с общим состоянием и разными LLM и инструментами могут сотрудничать для решения одной задачи.
  • Человек-в-петля: LangGraph имеет встроенную поддержку рабочего процесса «человек в цикле». Это означает, что человек может просмотреть состояния перед переходом к следующему узлу.
  • Агент по планированию: LangGraph хорошо подходит для создания агентов планирования, где планировщик LLM планирует и разлагает запрос пользователя, исполнитель вызывает инструменты и функции, а LLM синтезирует ответы на основе предыдущих результатов.
  • Мультимодальные агенты: LangGraph может создавать мультимодальные агенты, например, с поддержкой машинного зрения. веб-навигаторы.

Реальные примеры использования

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

  1. Личный агентs: Представьте себе, что на ваших электронных устройствах есть собственный помощник, похожий на Джарвиса, готовый помочь с задачами по вашей команде, будь то с помощью текста, голоса или даже жеста. Это одно из самых захватывающих применений агентов ИИ!
  2. Инструкторы по искусственному интеллекту: Чат-боты — это здорово, но у них есть свои ограничения. Агенты ИИ, оснащенные необходимыми инструментами, могут выходить за рамки обычных разговоров. Преподаватели виртуального искусственного интеллекта, которые могут адаптировать свои методы обучения на основе отзывов пользователей, могут изменить правила игры.
  3. Программное обеспечение UX: удобство использования программного обеспечения можно улучшить с помощью агентов искусственного интеллекта. Вместо ручной навигации по приложениям агенты могут выполнять задачи с помощью голосовых команд или жестов.
  4. Пространственные вычисления: По мере роста популярности технологий AR/VR спрос на агентов искусственного интеллекта будет расти. Агенты могут обрабатывать окружающую информацию и выполнять задачи по требованию. В ближайшее время это может стать одним из лучших вариантов использования агентов ИИ.
  5. LLM ОС: операционные системы, ориентированные на искусственный интеллект, в которых агенты являются первоклассными гражданами. Агенты будут отвечать за выполнение как простых, так и сложных задач.

Заключение

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

Основные выводы

  • LangGraph — это расширение LangChain, которое позволяет нам создавать циклические многоакторные агентные системы с отслеживанием состояния.
  • Он реализует структуру графа с узлами и ребрами. Узлы — это функции или инструменты, а ребра — это связи между узлами.
  • Ребра бывают двух типов: условные и нормальные. Условные ребра имеют условия при переходе от одного к другому, что важно для придания цикличности рабочему процессу.
  • LangGraph предпочтителен для создания циклических многоакторных агентов, тогда как LangChain лучше подходит для создания цепочек или направленных ациклических систем.

Часто задаваемые вопросы

Вопрос 1. Что такое Лангграф?

Ответ. LangGraph — это библиотека с открытым исходным кодом для создания циклических многоакторных агентских систем с отслеживанием состояния. Он построен на основе экосистемы LangChain.

В2. Когда использовать LangGraph вместо LangChain?

Ответ. LangGraph предпочтителен для создания циклических многоакторных агентов, тогда как LangChain лучше подходит для создания цепочек или направленных ациклических систем.

Вопрос 3. Что такое ИИ-агент?

Ответ. Агенты ИИ — это программы, которые взаимодействуют со своей средой, принимают решения и действуют для достижения конечной цели.

В4. Какой LLM лучше всего использовать с ИИ-агентами?

Ответ. Это зависит от ваших вариантов использования и бюджета. GPT 4 — самый функциональный, но дорогой. Для кодирования DeepSeekCoder-33b — отличный более дешевый вариант. 

Вопрос 5. В чем разница между сетями и агентами?

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

Материалы, показанные в этой статье, не принадлежат Analytics Vidhya и используются по усмотрению Автора.

Spot_img

Последняя разведка

Spot_img