ai-agents-for-beginners

Как проектировать хорошие AI-агенты

(Нажмите на изображение выше, чтобы посмотреть видео этого урока)

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

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

Введение

В этом уроке мы постараемся ответить на следующие вопросы:

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

После изучения этого урока вы сможете:

Что такое паттерн проектирования использования инструментов?

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

В каких случаях его можно применять?

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

Какие элементы/строительные блоки необходимы для реализации паттерна проектирования использования инструментов?

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

Далее рассмотрим более подробно вызов функций/инструментов.

Вызов функций/инструментов

Вызов функций — это основной способ, которым мы позволяем Большим Языковым Моделям (LLM) взаимодействовать с инструментами. Вы часто будете видеть, что термины «Функция» и «Инструмент» используются как синонимы, потому что «функции» (блоки многократно используемого кода) являются «инструментами», которые агенты используют для выполнения задач. Чтобы код функции был вызван, LLM должен сопоставить запрос пользователя с описанием функций. Для этого схема, содержащая описания всех доступных функций, отправляется LLM. Затем LLM выбирает наиболее подходящую функцию для задачи и возвращает её имя и аргументы. Выбранная функция вызывается, её ответ отправляется обратно LLM, которая использует эту информацию для ответа на запрос пользователя.

Для разработчиков, чтобы реализовать вызов функций для агентов, потребуется:

  1. LLM-модель, поддерживающая вызов функций
  2. Схема, содержащая описания функций
  3. Код для каждой описанной функции

Приведём пример получения текущего времени в городе:

  1. Инициализировать LLM, поддерживающую вызов функций:

    Не все модели поддерживают вызов функций, поэтому важно проверить, что используемая вами LLM это умеет. Azure OpenAI поддерживает вызов функций. Начать можно с инициализации клиента Azure OpenAI.

     # Инициализация клиента Azure OpenAI
     client = AzureOpenAI(
         azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"), 
         api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
         api_version="2024-05-01-preview"
     )
    
  2. Создать схему функции:

    Далее определим JSON-схему, которая содержит имя функции, описание того, что функция делает, а также имена и описания параметров функции. Затем передадим эту схему клиенту, созданному ранее, вместе с запросом пользователя о времени в Сан-Франциско. Важно отметить, что возвращается вызов инструмента, а не конечный ответ на вопрос. Как упоминалось ранее, LLM возвращает имя выбранной для задачи функции и аргументы, которые будут переданы ей.

     # Описание функции для чтения модели
     tools = [
         {
             "type": "function",
             "function": {
                 "name": "get_current_time",
                 "description": "Get the current time in a given location",
                 "parameters": {
                     "type": "object",
                     "properties": {
                         "location": {
                             "type": "string",
                             "description": "The city name, e.g. San Francisco",
                         },
                     },
                     "required": ["location"],
                 },
             }
         }
     ]
    
      
     # Начальное сообщение пользователя
     messages = [{"role": "user", "content": "What's the current time in San Francisco"}] 
      
     # Первый вызов API: Попросить модель использовать функцию
       response = client.chat.completions.create(
           model=deployment_name,
           messages=messages,
           tools=tools,
           tool_choice="auto",
       )
      
       # Обработка ответа модели
       response_message = response.choices[0].message
       messages.append(response_message)
      
       print("Model's response:")  
    
       print(response_message)
      
    
     Model's response:
     ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_pOsKdUlqvdyttYB67MOj434b', function=Function(arguments='{"location":"San Francisco"}', name='get_current_time'), type='function')])
    
  3. Код функции для выполнения задачи:

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

       def get_current_time(location):
         """Get the current time for a given location"""
         print(f"get_current_time called with location: {location}")  
         location_lower = location.lower()
            
         for key, timezone in TIMEZONE_DATA.items():
             if key in location_lower:
                 print(f"Timezone found for {key}")  
                 current_time = datetime.now(ZoneInfo(timezone)).strftime("%I:%M %p")
                 return json.dumps({
                     "location": location,
                     "current_time": current_time
                 })
          
         print(f"No timezone data found for {location_lower}")  
         return json.dumps({"location": location, "current_time": "unknown"})
    
      # Обработка вызовов функций
       if response_message.tool_calls:
           for tool_call in response_message.tool_calls:
               if tool_call.function.name == "get_current_time":
         
                   function_args = json.loads(tool_call.function.arguments)
         
                   time_response = get_current_time(
                       location=function_args.get("location")
                   )
         
                   messages.append({
                       "tool_call_id": tool_call.id,
                       "role": "tool",
                       "name": "get_current_time",
                       "content": time_response,
                   })
       else:
           print("No tool calls were made by the model.")  
      
       # Второй вызов API: Получение окончательного ответа от модели
       final_response = client.chat.completions.create(
           model=deployment_name,
           messages=messages,
       )
      
       return final_response.choices[0].message.content
    
       get_current_time called with location: San Francisco
       Timezone found for san francisco
       The current time in San Francisco is 09:24 AM.
    

Вызов функций лежит в основе большинства, если не всех, реализаций паттерна использования инструментов агентов, однако реализовать его с нуля иногда бывает сложно. Как мы узнали в Уроке 2, агентные фреймворки предоставляют нам готовые строительные блоки для реализации использования инструментов.

Примеры использования инструментов с агентными фреймворками

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

Semantic Kernel

Semantic Kernel — это open-source AI-фреймворк для разработчиков на .NET, Python и Java, работающих с Большими Языковыми Моделями (LLM). Он упрощает процесс использования вызова функций, автоматически описывая ваши функции и их параметры модели через процесс, называемый сериализацией. Он также управляет двусторонним взаимодействием между моделью и вашим кодом. Другим преимуществом использования агентного фреймворка, такого как Semantic Kernel, является возможность обращаться к готовым инструментам, таким как Поиск файлов и Интерпретатор кода.

Следующая диаграмма иллюстрирует процесс вызова функций с Semantic Kernel:

function calling

В Semantic Kernel функции/инструменты называются плагинами. Мы можем преобразовать функцию get_current_time, которую рассматривали ранее, в плагин, превратив её в класс с функцией внутри. Также можно импортировать декоратор kernel_function, который принимает описание функции. Когда вы создаёте kernel с GetCurrentTimePlugin, kernel автоматически сериализует функцию и её параметры, создавая схему для отправки в LLM в процессе.

from semantic_kernel.functions import kernel_function

class GetCurrentTimePlugin:
    async def __init__(self, location):
        self.location = location

    @kernel_function(
        description="Get the current time for a given location"
    )
    def get_current_time(location: str = ""):
        ...

from semantic_kernel import Kernel

# Создать ядро
kernel = Kernel()

# Создать плагин
get_current_time_plugin = GetCurrentTimePlugin(location)

# Добавить плагин в ядро
kernel.add_plugin(get_current_time_plugin)

Сервис агентов Azure AI

Azure AI Agent Service — более новый агентный фреймворк, предназначенный для того, чтобы позволить разработчикам безопасно создавать, развёртывать и масштабировать высококачественных и расширяемых AI-агентов без необходимости управлять базовыми вычислительными и хранилищными ресурсами. Он особенно полезен для корпоративных приложений, поскольку является полностью управляемым сервисом корпоративного уровня безопасности.

В сравнении с разработкой напрямую через API LLM Azure AI Agent Service предлагает следующие преимущества:

Инструменты, доступные в Azure AI Agent Service, делятся на две категории:

  1. Инструменты знаний:
  2. Инструменты действий:

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

Представьте, что вы менеджер по продажам в компании Contoso. Вы хотите разработать диалогового агента, который сможет отвечать на вопросы о ваших данных по продажам.

Следующее изображение иллюстрирует, как можно использовать Azure AI Agent Service для анализа ваших данных продаж:

Agentic Service In Action

Чтобы использовать любой из этих инструментов в сервисе, можно создать клиента и определить инструмент или набор инструментов. Для практической реализации можно использовать следующий код на Python. LLM сможет посмотреть на toolset и решить, использовать ли пользовательскую функцию fetch_sales_data_using_sqlite_query или предустановленный Интерпретатор кода в зависимости от запроса пользователя.

import os
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from fetch_sales_data_functions import fetch_sales_data_using_sqlite_query # функция fetch_sales_data_using_sqlite_query, которую можно найти в файле fetch_sales_data_functions.py.
from azure.ai.projects.models import ToolSet, FunctionTool, CodeInterpreterTool

project_client = AIProjectClient.from_connection_string(
    credential=DefaultAzureCredential(),
    conn_str=os.environ["PROJECT_CONNECTION_STRING"],
)

# Инициализация набора инструментов
toolset = ToolSet()

# Инициализация агента вызова функций с функцией fetch_sales_data_using_sqlite_query и добавление его в набор инструментов
fetch_data_function = FunctionTool(fetch_sales_data_using_sqlite_query)
toolset.add(fetch_data_function)

# Инициализация инструмента Code Interpreter и добавление его в набор инструментов.
code_interpreter = code_interpreter = CodeInterpreterTool()
toolset.add(code_interpreter)

agent = project_client.agents.create_agent(
    model="gpt-4o-mini", name="my-agent", instructions="You are helpful agent", 
    toolset=toolset
)

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

Распространённая проблема с динамически генерируемым LLM SQL — это безопасность, особенно риск SQL-инъекций или вредоносных действий, таких как удаление или повреждение базы данных. Хотя эти опасения обоснованы, их можно эффективно смягчить, правильно настроив права доступа к базе данных. Для большинства баз данных это включает настройку базы в режиме только для чтения. Для сервисов баз данных, таких как PostgreSQL или Azure SQL, приложению следует назначить роль только для чтения (SELECT). Запуск приложения в защищённой среде дополнительно повышает уровень защиты. В корпоративных сценариях данные обычно извлекаются и преобразуются из операционных систем в базу данных или хранилище данных только для чтения с удобной для пользователей схемой. Такой подход обеспечивает безопасность данных, оптимизацию производительности и доступности, а также ограниченный доступ приложения только для чтения.

Примеры кода

Есть ещё вопросы об использовании паттернов проектирования инструментов?

Присоединяйтесь к Discord Azure AI Foundry, чтобы встретиться с другими обучающимися, посетить часы приёмов и получить ответы на вопросы по AI Agents.

Дополнительные ресурсы

Предыдущий урок

Понимание агентных паттернов проектирования

Следующий урок

Agentic RAG


Отказ от ответственности:
Этот документ был переведен с использованием сервиса автоматического перевода Co-op Translator. Несмотря на наши усилия обеспечить точность, имейте в виду, что автоматический перевод может содержать ошибки или неточности. Оригинальный документ на языке оригинала следует считать авторитетным источником. Для критически важной информации рекомендуется профессиональный перевод человеком. Мы не несем ответственности за любые недоразумения или искажения смысла, возникшие вследствие использования этого перевода.