Использование вызова функций для создания более умных приложений на основе LLM
Большие языковые модели (LLM) больше не ограничиваются генерацией текста; теперь они справляются с более сложными задачами, зависящими от контекста. Ключевым достижением в этой области является вызов функций, который позволяет LLM взаимодействовать с внешними инструментами, базами данных и API для выполнения динамических операций. Это позволяет им выходить за рамки генерации текста и работать с реальными данными и сервисами.
На недавней Berlin Unstructured Data Meetup, организованной Zilliz, Николай Данильчик, customer engineer в Google, рассказал о том, как Gemini, современная LLM, использует вызов функций для расширения своих возможностей. В этом блоге мы кратко изложим его идеи и покажем, как использовать эту мощную функцию для создания продвинутых LLM-приложений. Если вы хотите узнать больше деталей, рекомендуем посмотреть запись выступления Николая на YouTube.
Понимание расширенного вызова функций в LLM
LLM значительно эволюционировали, но их истинный потенциал раскрывается при взаимодействии с внешними системами через вызовы функций. Эта возможность позволяет LLM выходить за пределы ограничений их статических обучающих данных, запрашивая актуальные базы данных, выполняя команды или производя расчеты в реальном времени. Интегрируя вызов функций, LLM могут бесшовно подключаться к другим системам, чтобы предоставлять более точные, актуальные и динамичные ответы. Давайте разберем, как работает вызов функций, на примере Gemini.
Рисунок 1 — Этапы вызова функций и компоненты, используемые во время выполнения
Рисунок 1: Этапы вызова функций и компоненты, используемые во время выполнения.
Процесс начинается, когда пользователь отправляет запрос в Gemini API. На этом этапе разработчик уже определил одно или несколько объявлений функций внутри инструмента, сообщив Gemini о доступных функциях и способе их выполнения. После получения пользовательского ввода Gemini API анализирует содержимое и промпт, возвращая ответ "Function Call". Этот ответ включает структурированные данные, такие как имя функции, которую нужно вызвать, и соответствующие параметры.
Следующий шаг происходит вне системы Gemini: приложение использует имя функции и параметры из ответа Gemini, чтобы выполнить API-запрос к внешнему сервису. Здесь в дело вступает разработчик, используя такие инструменты, как библиотека
requestsв Python, для вызова REST API или любую другую клиентскую библиотеку, подходящую для его задач.После того как внешняя система возвращает свой ответ, приложение отправляет эти данные обратно в Gemini. Затем модель использует эту новую информацию, чтобы сгенерировать окончательный ответ для пользователя. Если требуются дополнительные данные, Gemini может выполнить еще один вызов функции, продолжая цикл по мере необходимости.
Чтобы понять значимость этой расширенной возможности, рассмотрим традиционную LLM без функции вызова функций. Ее ответы генерируются на основе данных, на которых она была обучена, которые могут быть устаревшими или ограниченными по охвату. Однако с помощью вызовов функций LLM может отдавать команды для получения информации в реальном времени из базы данных, обновлять запись в системе управления взаимоотношениями с клиентами (CRM) или даже инициировать такие действия, как бронирование билета или размещение заказа. Такой подход расширяет применимость модели: от простого генерирования ответов до выполнения задач.
С технической точки зрения вызов функции в LLM представляет собой структурированное взаимодействие между моделью и внешним API или сервисом. Модель определяет подходящий сценарий, в котором требуется вызов функции, формирует параметры для вызова и выполняет его.
Например, если пользователь спрашивает: “Какая погода в Берлине?” Вызов функции запустит погодный API, получив данные в реальном времени для формирования ответа. В этом случае LLM выступает в роли интеллектуального посредника между пользователем и внешней системой, организуя более точное и полезное взаимодействие.
Теперь, когда мы рассмотрели базовую концепцию вызова функций, давайте посмотрим на практическую реализацию с использованием Gemini для взаимодействия с реальным API — получения курсов обмена валют.
Пример: использование вызова функций для получения курса обмена валют
Давайте посмотрим, как мы можем использовать API курса обмена валют через вызов функций Gemini:
Установка необходимых библиотек и настройка переменных проекта
Начнем с обновления и установки библиотеки google-cloud-aiplatform, которая необходима для взаимодействия с платформой Google Cloud Vertex AI. Затем укажите ID вашего проекта и местоположение в виде переменных.
!pip3 install --upgrade --user --quiet google-cloud-aiplatform
PROJECT_ID = "[your-project-id]" # @param {type:"string"}
LOCATION = "us-central1" # @param {type:"string"}
Это заполнители для определения того, с каким проектом и регионом в Google Cloud вы работаете.
Импорт необходимых модулей и определение генеративной модели
Затем импортируйте необходимые модули для определения и работы с генеративной моделью из Vertex AI. Библиотека requests будет использована позже для получения данных из внешнего API.
import requests
from vertexai.generative_models import (
Content,
FunctionDeclaration,
GenerativeModel,
Part,
Tool,
)
model = GenerativeModel("gemini-1.5-pro-001")
Последняя строка инициализирует генеративную модель, в данном случае gemini-1.5-pro-001. Позже вы будете использовать модель для генерации ответов на основе входного запроса.
Определение функции для курсов обмена валют и создание инструмента
Далее создайте функцию, которая описывает параметры, необходимые для получения курса обмена между двумя валютами, и оберните ее в инструмент.
get_exchange_rate_func = FunctionDeclaration(
name="get_exchange_rate",
description="Get the exchange rate for currencies between countries",
parameters={
"type": "object",
"properties": {
"currency_date": {
"type": "string",
"description": "A date that must always be in YYYY-MM-DD format or the value 'latest' if a time period is not specified"
},
"currency_from": {
"type": "string",
"description": "The currency to convert from in ISO 4217 format"
},
"currency_to": {
"type": "string",
"description": "The currency to convert to in ISO 4217 format"
}
},
"required": [
"currency_from",
"currency_date",
]
},
)
exchange_rate_tool = Tool(
function_declarations=[get_exchange_rate_func],
)
Параметры включают currency_date (в формате YYYY-MM-DD или ключевое слово latest), currency_from (код ISO 4217 валюты, из которой выполняется конвертация) и currency_to (код ISO 4217 валюты, в которую выполняется конвертация). Раздел required указывает, что currency_from и currency_date являются обязательными. Затем мы определяем инструмент с именем exchange_rate_tool, который оборачивает объявление функции get_exchange_rate. Позже мы передадим этот инструмент модели для обработки получения курсов обмена.
Генерация ответа с помощью модели и извлечение параметров из ответа
Теперь давайте вызовем ответ, передав модели запрос. Мы ожидаем, что модель выведет ответ, содержащий вызов функции с параметрами.
prompt = """What is the exchange rate from Australian dollars to Swedish krona?
How much is 500 Australian dollars worth in Swedish krona?"""
response = model.generate_content(
prompt,
tools=[exchange_rate_tool],
)
response.candidates[0].content
params = {}
for key, value in response.candidates[0].content.parts[0].function_call.args.items():
params[key[9:]] = value
params
Приведенный выше код определяет промпт, в котором запрашивается обменный курс между австралийскими долларами и шведскими кронами. Затем вызывается модель с использованием generate_content, куда передаются промпт вместе с exchange_rate_tool. Модель попытается сгенерировать ответ.
Затем ответ анализируется. Словарь params заполняется путем перебора ключей и значений function_call.args и удаления первых 9 символов ключа, чтобы они соответствовали ожидаемым именам параметров.
Получение обменных курсов из API и предоставление ответа пользователю
Теперь запросим Frankfurter API (бесплатный API курсов иностранных валют), используя параметры, извлеченные из предыдущего ответа, и сгенерируем ответ пользователю.
import requests
url = f"https://api.frankfurter.app/{params['date']}"
api_response = requests.get(url, params=params)
api_response.text
response = model.generate_content(
[
Content(role="user", parts=[
Part.from_text(prompt + """Give your answer in steps with lots of detail
and context, including the exchange rate and date."""),
]),
Content(role="function", parts=[
Part.from_dict({
"function_call": {
"name": "get_exchange_rate",
}
})
]),
Content(role="function", parts=[
Part.from_function_response(
name="get_exchange_rate",
response={
"content": api_response.text,
}
)
]),
],
tools=[exchange_rate_tool],
)
response.candidates[0].content.parts[0].text
В приведенном выше коде, после того как мы получаем ответ от API обменных курсов, мы снова вызываем метод generate_content, на этот раз передавая несколько содержимых элементов: один от пользователя (с запросом подробных шагов и контекста), вызов функции get_exchange_rate и ответ от Frankfurter API. Такая комбинация побуждает модель дать более подробный пошаговый ответ. В конце мы выводим текстовую часть сгенерированного моделью содержимого. Это ответ, который мы возвращаем пользователю.
Вот пример ответа:
Рисунок 2 — Вывод программы, показывающий обменный курс австралийских долларов к шведским кронам
Рисунок 2: Вывод программы, показывающий обменный курс австралийских долларов к шведским кронам
Ответ показывает, что вызов функции сработал и предоставил нам текущий обменный курс, указанный Frankfurter API.
До этого момента мы рассмотрели вызов функций — расширенную возможность Gemini и многих других LLM. Хотя один только вызов функций может выполнять сложные задачи, такие как получение данных о валютах, его истинный потенциал раскрывается при сочетании с другими мощными техниками, такими как Retrieval Augmented Generation (RAG).
Сочетание вызова функций с Retrieval-Augmented Generation (RAG) для повышения интерактивности
Retrieval Augmented Generation (RAG) стала одним из самых значимых трендов в обработке естественного языка (NLP). Системы RAG объединяют генеративные возможности LLM с эффективностью систем поиска, работающих на основе векторных баз данных, таких как Milvus и Zilliz Cloud (управляемый Milvus). В частности, в системе RAG векторная база данных извлекает контекстную информацию для LLM, а затем LLM генерирует более точный ответ на основе извлеченной информации. Вызов функций улучшает этот процесс, обеспечивая более динамичное взаимодействие между LLM и внешними базами данных или системами. Благодаря добавлению вызовов функций LLM могут расширять свои возможности, не только извлекая релевантные данные, но и обрабатывая их и взаимодействуя с ними в реальном времени.
Например, в приложении клиентской поддержки, использующем как RAG, так и вызов функций, LLM обеспечивает более насыщенное и персонализированное взаимодействие. Когда пользователь спрашивает: «Где мой недавний заказ?” Система сначала применяет RAG для извлечения общей информации об обработке заказов из векторной базы данных Milvus, предоставляя контекст. Например, извлеченная информация: “доставка заказов обычно занимает 3-5 рабочих дней.” Одновременно, с помощью вызова функций, она получает доступ к данным в реальном времени, выполняя запрос к учетной записи клиента. Итоговый ответ становится: “Ваш заказ #12345 был отправлен 10 сентября и ожидается к доставке 15 сентября.”
Эта интеграция RAG с вызовом функций создает динамичную систему, которая не только генерирует релевантные и информативные ответы, но и активно взаимодействует с актуальными данными и сервисами, привнося интерактивное измерение. Такое сочетание делает интеллектуальных агентов на базе LLM способными выполнять сложные взаимодействия в реальном мире.
- Обратитесь к этому руководству с пошаговой инструкцией о том, как использовать возможности вызова функций LLM для улучшения систем RAG.
Варианты использования сочетания RAG и вызова функций
Давайте рассмотрим несколько таких взаимодействий в реальном мире.
Здравоохранение: извлечение медицинских записей и запись на прием
В здравоохранении RAG в сочетании с вызовом функций позволяет LLM предоставлять высоко персонализированную поддержку на основе данных как пациентам, так и медицинским работникам. Врач может запросить у системы исторические данные пациента, а система извлечет релевантные медицинские записи с помощью RAG из векторной базы данных, такой как Milvus. В то же время, посредством вызова функций, LLM может взаимодействовать с внешними больничными системами, чтобы назначать последующие приемы или получать диагностические данные в реальном времени.
Пример: Врач спрашивает: «Каков последний результат анализа пациента X, и можете ли вы записать его на повторный прием на следующей неделе?” Система сначала запрашивает Milvus, чтобы извлечь связанные документы из истории пациента, предоставляя сведения о тенденциях и состояниях. Затем она использует вызов функций для доступа к API расписания больницы, чтобы записать пациента на прием.
Финансы: персонализированная инвестиционная аналитика и транзакции в реальном времени
В финансовом секторе RAG применяется для извлечения релевантной рыночной информации и исторических финансовых данных, хранящихся в векторных базах данных, таких как Milvus. В сочетании с вызовом функций LLM также может выполнять действия в реальном времени, такие как покупка или продажа акций, перевод средств или формирование индивидуальных рекомендаций по портфелю на основе актуальных данных.
Пример: Пользователь спрашивает: “Как мой портфель показал себя за последние шесть месяцев, и можешь ли ты купить акции Apple на сумму $1000?” Система сначала использует RAG, чтобы получить историю портфеля пользователя из Milvus, предоставляя сводку прошлой доходности. Затем, используя вызов функций, она взаимодействует с торговым API, чтобы выполнить покупку акций и подтвердить транзакцию пользователю.
E-Commerce: рекомендации продуктов и отслеживание заказов в реальном времени
В e-commerce RAG может помочь получать информацию о продуктах, отзывы или историю клиента из Milvus, чтобы персонализировать покупательский опыт. В сочетании с вызовом функций система может взаимодействовать с действующими системами учета запасов, чтобы предоставлять информацию о наличии товара, отслеживать заказы в реальном времени или даже обрабатывать платежи.
Пример: Клиент спрашивает: Можешь порекомендовать ноутбук, похожий на мою последнюю покупку, и сказать, когда прибудет мой текущий заказ? LLM извлекает информацию о предыдущих покупках клиента из Milvus и рекомендует похожий продукт. Затем используется вызов функций для запроса к API отслеживания заказов, чтобы предоставить обновления в реальном времени о статусе доставки текущего заказа.
Путешествия: предложения маршрутов и управление бронированиями
В сфере путешествий и гостеприимства RAG может извлекать сведения о направлениях, отелях и туристических маршрутах, хранящиеся в векторной базе данных, такой как Milvus. В сочетании с вызовом функций система может управлять бронированиями, предлагать персонализированные маршруты или предоставлять обновления в реальном времени о рейсах и бронированиях.
Пример: Путешественник спрашивает: Можешь предложить 5-дневный маршрут по Италии и перенести мое бронирование отеля на более раннюю дату? Система сначала извлекает предложения маршрутов из Milvus на основе предпочтений путешественника и прошлых поездок. Затем она использует вызов функций для взаимодействия с системой бронирования отеля, чтобы изменить бронирование и подтвердить изменение пользователю.
Поскольку мы видим, как вызов функций улучшает системы вроде RAG, важно понимать практические трудности и преимущества при внедрении таких технологий в реальные приложения.
Трудности и преимущества вызова функций в реальных сценариях использования
Хотя потенциал вызова функций огромен, у него есть собственный набор трудностей. Одна из основных проблем — обеспечение безопасности и конфиденциальности взаимодействий. Когда LLM инициирует вызовы функций, ему может потребоваться доступ к конфиденциальным данным, таким как учетные записи пользователей или финансовая информация. Крайне важно обеспечить безопасность этих транзакций и их соответствие нормам конфиденциальности данных.
Кроме того, сложность управления несколькими вызовами функций в одном рабочем процессе может привести к проблемам с задержкой. Например, если LLM выполняет несколько вызовов функций к разным системам, время ответа может увеличиться, что потенциально повлияет на пользовательский опыт. Это особенно важно в приложениях реального времени, где скорость имеет критическое значение.
С положительной стороны, вызов функций предлагает несколько преимуществ, включая улучшенную автоматизацию задач, более точные ответы в реальном времени и улучшенное взаимодействие с пользователем. В таких отраслях, как здравоохранение, финансы и обслуживание клиентов, вызов функций может оптимизировать операции за счет автоматизации рутинных задач. Например, в здравоохранении LLM мог бы получать медицинские карты пациентов, назначать приемы и отправлять напоминания через вызовы функций, освобождая время медицинских специалистов, чтобы они могли сосредоточиться на более сложных случаях.
Помимо практических преимуществ и трудностей, существуют этические и технические аспекты, которые нельзя упускать из виду, особенно в области безопасности данных и надежности системы.
Этические и технические соображения
С технической точки зрения мы, как разработчики, должны тщательно управлять тем, как реализуются вызовы функций, чтобы избежать потенциальных подводных камней. Одна из распространённых проблем — чрезмерная зависимость от внешних систем. Если LLM постоянно выполняет вызовы функций к сторонним сервисам, надёжность системы начинает зависеть от доступности и производительности этих сервисов. Необходимо обеспечить надлежащую обработку ошибок и механизмы резервного варианта, чтобы система продолжала работать бесперебойно, даже когда внешние сервисы недоступны.
С этической точки зрения вызов функций вызывает опасения в отношении прозрачности и согласия пользователя. Если LLM принимает решения или выполняет действия от имени пользователя, важно, чтобы пользователь полностью понимал, что делает система. Например, в финансовых услугах, если LLM выполняет сделки или переводит средства, пользователи должны быть проинформированы о предпринимаемых действиях и должны иметь возможность вмешаться при необходимости. Чёткая документация и механизмы получения согласия пользователя имеют критически важное значение для поддержания доверия к таким системам.
Ещё одна этическая проблема связана с использованием данных. Когда вызовы функций получают доступ к персональным или конфиденциальным данным, должны быть внедрены строгие меры для защиты конфиденциальности пользователей. Разработчикам необходимо обеспечить ответственную обработку данных и соответствие вызовов функций нормативным требованиям в области конфиденциальности, таким как GDPR или HIPAA.
Заключение
Nikolai проделал отличную работу, пролив свет на то, как вызов функций предлагает критически важное улучшение для больших языковых моделей, позволяя им выполнять задачи реального мира посредством взаимодействия с внешними системами и данными. Будь то получение курсов обмена валют или обеспечение более сложных взаимодействий с помощью Retrieval-Augmented Generation (RAG), вызов функций расширяет горизонты того, чего могут достичь LLM.
Дополнительная литература
Читать далее

We spent 8 years making vector databases faster. Then we stopped.
Rarely queried embeddings still need to stay searchable. See how Vector Lakebase enables on-demand vector search without always-on compute costs.

Zilliz Cloud Now Available in AWS Europe (Ireland)
Zilliz Cloud launches in AWS eu-west-1 (Ireland) — bringing low-latency vector search, EU data residency, and full GDPR-ready infrastructure to European AI teams. Now live across 30 regions on five cloud providers.

How Zilliz Saw the Future of Vector Databases—and Built for Production
An inside look at how Zilliz built vector databases for real-world use, focusing on scalability, stability, and running them reliably at scale.


