Новости и статьи об искусственном интеллекте и нейросетях. Мы собираем и обрабатываем самую актуальную информацию из мира AI. О проекте

Статьи

Создание инструментов для ИИ-агентов

Статья объясняет, почему инструменты критичны для ИИ-агентов и как их правильно определять для повышения эффективности. Рассматриваются аспекты создания четких определений, специализированных функций, чистого вывода данных, обработки ошибок и предоставления инструментов в контексте агента. Правильная реализация инструментов позволяет агентам лучше справляться с задачами, минимизируя ошибки и оптимизируя производительность.

15 октября 2025 г.
7 мин
9

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

Цель этой статьи — подчеркнуть ключевые аспекты при создании инструментов для ИИ-агентов. Качественные инструменты необходимы для высокоэффективных агентов, поэтому мы углубимся в использование инструментов в агентных системах. Рассмотрим такие темы, как правильные определения и описания инструментов, а также оптимальные способы их предоставления агенту.

Почему инструменты важны для ИИ-агентов

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

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

  • Инструменты должны быть четко определены с подходящими названиями и описаниями
  • Каждый инструмент должен иметь одну конкретную цель
  • Необходимо обеспечивать правильные типы данных как для входных, так и для выходных параметров инструмента

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

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

Этот принцип часто применяется в машинном обучении, например, при анализе подсказок, подаваемых большим языковым моделям. Всегда стоит задаваться вопросом: сможет ли человек понять поставленную в подсказке задачу? Если нет, подсказку требуется уточнить.

Правильные определения инструментов

Правильные определения инструментов — это простое улучшение для ИИ-агентов. Под этим подразумевается:

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

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

# неудачное определение инструмента
def search(query):
    results = search_database()
    return results

Это неудачное определение по следующим причинам:

  • Название инструмента неинформативно. Search неоднозначно; оно может подразумевать, например, семантический поиск
  • Отсутствует docstring с определением типов входных и выходных данных, а также описанием функций инструмента
  • Нет типов для входных и выходных параметров. Модель, использующая этот инструмент, вероятно, сможет вывести, что query — это строка. Но ей придется тратить время на разбор формата вывода при использовании инструмента

Вместо этого инструмент следует определять следующим образом:

from dataclasses import dataclass

@dataclass
class KeywordSearchResult:
    id: str
    filename: str
    document_content: str

# хорошее определение инструмента
def keyword_search(query: str) -> list[KeywordSearchResult]:
    """
    Выполняет поиск по ключевым словам в базе данных.
    Входные параметры:
    query: str - ключевые слова для поиска
    Выход: Список всех результатов поиска по ключевым словам, где каждый результат содержит:
    - id (str) - идентификатор документа в базе данных
    - filename (str) - имя файла документа
    - document_content (str) - текстовое содержимое документа
    """
    results = search_database()
    return results

В этом примере создали отдельный класс данных для представления формата вывода инструмента. Это упрощает понимание работы инструмента агентом и обработку результатов. Кроме того, добавили подходящую docstring с описанием функций инструмента, входных и выходных параметров. Название инструмента сделали более точным, назвав его keyword_search вместо простого search.

Такие простые доработки инструментов значительно повышают производительность агентов. Однако существуют и другие методы улучшения определений инструментов, которые делают агента еще эффективнее.

Функциональность инструментов

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

Создание специализированных инструментов

Инструменты должны быть максимально конкретными. Размытые инструменты усложняют модели понимание, когда их применять. В результате модель чаще ошибается в использовании инструмента. Это может проявляться как:

  • Применение инструмента в неподходящий момент. Например, использование keyword_search, когда нужен semantic_search
  • Передача инструменту неверных параметров
  • Неправильная обработка вывода инструмента

Поэтому инструменты всегда должны иметь четкую, единственную цель.

Предоставление чистых выходных данных

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

Создадим инструмент parse_keyword_search_output, который принимает результаты поиска по ключевым словам и преобразует их в структурированную строку. В примере также указано, что KeywordSearchResult содержит лишние поля. Эти поля естественно исключаются при парсинге вывода.

@dataclass
class KeywordSearchResult:
    id: str
    filename: str
    document_content: str
    unnecessary_field_a: str
    unnecessary_field_b: str

def _parse_keyword_search_output(keyword_search_results: list[KeywordSearchResult]) -> str:
    """
    Парсит вывод инструмента поиска по ключевым словам в структурированную строку, содержащую только необходимую информацию
    """
    output_string = ""
    tot_num_documents = len(keyword_search_results)
    for i, result in enumerate(keyword_search_results):
        document_id, filename, document_content = result["id"], result["filename"], result["document_content"]
        output_string += f"""

Document {i+1}/{tot_num_documents}:
ID: {document_id}
filename: {filename}
content: {document_content}
"""
    return output_string

def keyword_search(query: str, url: str) -> list[KeywordSearchResult]:
    """
    <docstring>
    """
    results = search_database()
    return parse_results(results)

Такой парсинг вывода сильно упрощает обработку результатов поиска по ключевым словам для агента. Не забудьте указать в docstring инструмента keyword_search формат вывода, который предоставит инструмент парсинга поиска по ключевым словам.

Избегание возврата всех результатов

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

def keyword_search(query: str, url: str, sort_ascending=True, max_return_items=10) -> list[KeywordSearchResult]:
    """
    <docstring>
    """
    results = search_database()
    if sort_ascending:
        results = sort(results, ascending=True)
    else:
        results = sort(results, ascending=False)
    results = parse_results(results)
    if max_return_items < len(results):
        return results[:max_return_items]
    return results

Обычно модели достаточно увидеть 10 или 20 лучших результатов, чтобы извлечь наиболее полезную информацию (в поиске по ключевым словам верхние результаты обычно самые релевантные) и понять формат вывода.

Информативная обработка ошибок

Информативная обработка ошибок — это критическая мера предосторожности, когда агенты неизбежно сталкиваются с проблемами. Такие проблемы могут возникать из-за:

  • Неправильного использования инструмента агентом, в этом случае стоит сообщить агенту, почему использование было неверным, и возможно, как это исправить
  • Сбоев API по вине внешнего провайдера, тогда можно посоветовать модели подождать или уведомить пользователя о проблеме
  • Отсутствующих пакетов, в таком случае уведомите агента об установке необходимых пакетов
def keyword_search(query: str, url: str) -> list[KeywordSearchResult]:
    """
    <docstring>
    """
    try:
        results = search_database()
        return parse_results(results)
    except RatelimitError as e:
        raise RuntimeError(
            f"Rate limit error: {e}. "
            f"Wait before retrying. If this error persists, contact support."
        )
    except APINotAvailableError as e:
        raise RuntimeError(
            f"API not available: {e}. "
            f"Check that the provided URL is correct and the endpoint is operational."
        )
    except Exception as e:
        raise RuntimeError(
            f"Unexpected error: {e}. Please try again."
        )

Такая информативная обработка ошибок сильно упрощает реакцию агента на сбои инструментов. В общем, в обработке ошибок следует обеспечивать:

  • Возврат описательного сообщения об ошибке, включая трассировку ошибки и строку с объяснением
  • Идеально — указание агенту, как действовать после получения ошибки. Например, при ошибке лимита скорости модель должна вызвать time.sleep(), если это первый раз, иначе уведомить пользователя

Предоставление инструментов агентам

Теперь, когда у вас есть функциональные и правильно определенные инструменты, пора предоставить их агентам. Однако при этом остаются некоторые нюансы.

  • Сколько инструментов поместится в контекст?
  • Когда предоставлять инструменты?
  • Как предоставлять инструменты в контексте?

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

Продолжая эту тему, можно также подумать, когда предоставлять инструменты. Например, инструмент keyword_search может быть нерелевантен при выполнении агентом простых задач суммирования для пользователя. Вы можете адаптировать контекст агента, чтобы некоторые инструменты были доступны только в подходящих ситуациях.

Наконец, учтите, как предоставлять инструменты. В подсказке создайте отдельный раздел для инструментов, используя заголовок в markdown или отдельный XML-тег. Затем разместите там все инструменты и описания, как и когда их использовать.

Заключение

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