Детерминированный генеративный ИИ с вызовом функции Gemini на Java

1. Введение

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

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

  1. Принимает координаты широты и долготы
  2. Вызывает API геокодирования Google Maps для получения соответствующих адресов.
  3. Использует функцию вызова функций Gemini 1.0 Pro для детерминированной стандартизации и суммирования этих адресов в определенном формате, который нам нужен.

Давайте погрузимся!

2. Вызов функции Gemini

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

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

  1. Определите функции : четко опишите функции. Описания должны включать следующую информацию:
  • Имя функции, например getAddress .
  • Параметры, которые ожидает функция, например, latlng в виде строки.
  • Тип данных, возвращаемых функцией, например список адресных строк.
  1. Создавайте инструменты для Gemini : упаковывайте описания функций в виде спецификации API в инструменты. Думайте об инструменте как о специализированном наборе инструментов, который Gemini может использовать для понимания функциональности API.
  2. Организуйте API-интерфейсы с помощью Gemini : когда вы отправляете запрос в Gemini, он может проанализировать ваш запрос и определить, где он может использовать предоставленные вами инструменты. Затем Близнецы действуют как умный оркестратор, выполняя следующие задачи:
  • Генерирует необходимые параметры API для вызова определенных вами функций. Gemini не вызывает API от вашего имени. Вы должны вызвать API на основе параметров и подписи, сгенерированной для вас вызовом функции Gemini.
  • Gemini обрабатывает результаты, передавая результаты вызовов API обратно в свою генерацию, и включает структурированную информацию в свой окончательный ответ. Вы можете обрабатывать эту информацию так, как вам удобно для вашего приложения.

На следующем изображении показан поток данных, этапы реализации и владелец каждого шага, например приложение, LLM или API:

b9a39f55567072d3.png

Что ты построишь

Вы создадите и развернете облачную функцию Java, которая выполняет следующие действия:

  • Принимает координаты широты и долготы.
  • Вызывает API геокодирования Google Maps для получения соответствующих адресов.
  • Использует функцию вызова функций Gemini 1.0 Pro для детерминированной стандартизации и суммирования этих адресов в определенном формате.

3. Требования

  • Браузер, например Chrome или Firefox .
  • Проект Google Cloud с включенной оплатой.

4. Прежде чем начать

  1. В Google Cloud Console на странице выбора проекта выберите или создайте проект Google Cloud.
  2. Убедитесь, что для вашего проекта Google Cloud включена оплата. Узнайте, как проверить, включена ли оплата в проекте .
  3. Активируйте Cloud Shell из консоли Google Cloud. Дополнительную информацию см. в разделе Использование Cloud Shell .
  4. Если ваш проект не установлен, используйте следующую команду для настройки проекта:
gcloud config set project <YOUR_PROJECT_ID>
  1. В Cloud Shell установите следующие переменные среды:
export GCP_PROJECT=<YOUR_PROJECT_ID>
export GCP_REGION=us-central1
  1. Включите необходимые API Google Cloud, выполнив следующие команды в Cloud Shell:
gcloud services enable cloudbuild.googleapis.com cloudfunctions.googleapis.com run.googleapis.com logging.googleapis.com storage-component.googleapis.com cloudaicompanion.googleapis.com aiplatform.googleapis.com
  1. Откройте редактор Cloud Shell , нажмите «Расширения» , а затем установите расширение Gemini + Google Cloud Code .

5. Реализуйте функцию облака

  1. Запустите редактор Cloud Shell .
  2. Нажмите «Облачный код» , а затем разверните раздел «Облачные функции» .
  3. Нажмите значок «Создать функцию» (+).
  4. В диалоговом окне «Создание нового приложения» выберите вариант «Java: Hello World» .
  5. Укажите имя проекта в пути к проекту, например GeminiFunctionCalling .
  6. Нажмите «Проводник» , чтобы просмотреть структуру проекта, а затем откройте файл pom.xml. На следующем изображении показана структура проекта:

bdf07515f413dd9e.png

  1. Добавьте необходимые зависимости в теге <dependencies>... </dependencies> в файле pom.xml . Вы можете получить доступ ко всему pom.xml из репозитория GitHub этого проекта. Скопируйте файл pom.xml оттуда в файл pom.xml текущего проекта, который вы редактируете.
  2. Скопируйте класс HelloWorld.java из ссылки GeminiFunctionCalling на GitHub . Вам необходимо обновить API_KEY и project_id указав ключ API геокодирования и идентификатор проекта Google Cloud соответственно.

6. Понимание вызова функций с помощью класса HelloWorld.java.

Быстрый ввод

В этом примере следующее приглашение для ввода: Какой адрес для значения latlong 40.714224,-73.961452 .

Ниже приведен фрагмент кода, соответствующий приглашению ввода в файле:

String promptText = "What's the address for the latlong value '" + latlngString + "'?"; //40.714224,-73.961452

Спецификация API

В этом примере используется API обратного геокодирования. Ниже приводится спецификация API:

/* Declare the function for the API to invoke (Geo coding API) */ 
FunctionDeclaration functionDeclaration =
    FunctionDeclaration.newBuilder()
        .setName("getAddress")
        .setDescription("Get the address for the given latitude and longitude value.")
        .setParameters(
            Schema.newBuilder()
                .setType(Type.OBJECT)
                .putProperties(
                    "latlng",
                    Schema.newBuilder()
                        .setType(Type.STRING)
                        .setDescription("This must be a string of latitude and longitude coordinates separated by comma")
                        .build())
                .addRequired("latlng")
                .build())
        .build();

Организуйте подсказку вместе с Близнецами.

Ввод приглашения и спецификация API отправляются в Gemini:

// Add the function to a "tool"
Tool tool = Tool.newBuilder()
.addFunctionDeclarations(functionDeclaration)
.build();

// Invoke the Gemini model with the use of the tool to generate the API parameters from the prompt input.
GenerativeModel model = GenerativeModel.newBuilder()
.setModelName(modelName)
.setVertexAi(vertexAI)
.setTools(Arrays.asList(tool))
.build();
GenerateContentResponse response = model.generateContent(promptText);
Content responseJSONCnt = response.getCandidates(0).getContent();

Ответом на это являются оркестрованные параметры JSON для API. Вот пример вывода:

role: "model"
parts {
 function_call {
   name: "getAddress"
   args {
     fields {
       key: "latlng"
       value {
         string_value: "40.714224,-73.961452"
       }
     }
   }
 }
}

Передайте следующий параметр в API Reverse Geocoding : "latlng=40.714224,-73.961452"

Сопоставьте организованный результат с форматом "latlng=VALUE" .

Вызов API

Ниже приведен раздел кода, который вызывает API:

// Create a request
     String url = API_STRING + "?key=" + API_KEY + params;
     java.net.http.HttpRequest request = java.net.http.HttpRequest.newBuilder()
         .uri(URI.create(url))
         .GET()
         .build();
     // Send the request and get the response
     java.net.http.HttpResponse<String> httpresponse = client.send(request, java.net.http.HttpResponse.BodyHandlers.ofString());
     // Save the response
     String jsonResult =  httpresponse.body().toString();

Строка jsonResult содержит ответ от API обратного геокодирования. Ниже приведена форматированная версия вывода:

"...277 Bedford Ave, Brooklyn, NY 11211, USA; 279 Bedford Ave, Brooklyn, NY 11211, USA; 277 Bedford Ave, Brooklyn, NY 11211, USA;..."

Обработайте ответ API и подготовьте приглашение

Следующий код обрабатывает ответ от API и подготавливает приглашение с инструкциями по обработке ответа:

// Provide an answer to the model so that it knows what the result
     // of a "function call" is.
     String promptString =
     "You are an AI address standardizer for assisting with standardizing addresses accurately. Your job is to give the accurate address in the standard format as a JSON object containing the fields DOOR_NUMBER, STREET_ADDRESS, AREA, CITY, TOWN, COUNTY, STATE, COUNTRY, ZIPCODE, LANDMARK by leveraging the address string that follows in the end. Remember the response cannot be empty or null. ";

Content content =
         ContentMaker.fromMultiModalData(
             PartMaker.fromFunctionResponse(
                 "getAddress",
                 Collections.singletonMap("address", formattedAddress)));
     String contentString = content.toString();
     String address = contentString.substring(contentString.indexOf("string_value: \"") + "string_value: \"".length(), contentString.indexOf('"', contentString.indexOf("string_value: \"") + "string_value: \"".length()));

     List<SafetySetting> safetySettings = Arrays.asList(
       SafetySetting.newBuilder()
           .setCategory(HarmCategory.HARM_CATEGORY_HATE_SPEECH)
           .setThreshold(SafetySetting.HarmBlockThreshold.BLOCK_ONLY_HIGH)
           .build(),
       SafetySetting.newBuilder()
           .setCategory(HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT)
           .setThreshold(SafetySetting.HarmBlockThreshold.BLOCK_ONLY_HIGH)
           .build()
   );

Вызовите Gemini и верните стандартизированный адрес.

Следующий код передает обработанные выходные данные предыдущего шага в качестве приглашения Gemini:

GenerativeModel modelForFinalResponse = GenerativeModel.newBuilder()
     .setModelName(modelName)
     .setVertexAi(vertexAI)
     .build();
     GenerateContentResponse finalResponse = modelForFinalResponse.generateContent(promptString + ": " + address, safetySettings);
      System.out.println("promptString + content: " + promptString + ": " + address);
       // See what the model replies now
       System.out.println("Print response: ");
       System.out.println(finalResponse.toString());
       String finalAnswer = ResponseHandler.getText(finalResponse);
       System.out.println(finalAnswer);

Переменная finalAnswer имеет стандартизированный адрес в формате JSON. Ниже приведен пример вывода:

{"replies":["{ \"DOOR_NUMBER\": null, \"STREET_ADDRESS\": \"277 Bedford Ave\", \"AREA\": \"Brooklyn\", \"CITY\": \"New York\", \"TOWN\": null, \"COUNTY\": null, \"STATE\": \"NY\", \"COUNTRY\": \"USA\", \"ZIPCODE\": \"11211\", \"LANDMARK\": null} null}"]}

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

7. Развертывание и тестирование

  1. Если вы уже создали проект GeminiFunctionCalling и реализовали функцию Cloud, перейдите к шагу 2. Если вы еще не создали проект, перейдите в терминал Cloud Shell и клонируйте этот репозиторий: git clone https://github.com/AbiramiSukumaran/ БлизнецыФункцияВызов
  2. Перейдите в папку проекта: cd GeminiFunctionCalling
  3. Выполните следующий оператор, чтобы создать и развернуть облачную функцию:
gcloud functions deploy gemini-fn-calling --gen2 --region=us-central1 --runtime=java11 --source=. --entry-point=cloudcode.helloworld.HelloWorld --trigger-http

Ниже приведен формат URL-адреса после развертывания: https://us-central1-YOUR_PROJECT_ID.cloudfunctions.net/gemini-fn-calling .

  1. Проверьте функцию облака, выполнив следующую команду из терминала:
gcloud functions call gemini-fn-calling --region=us-central1 --gen2 --data '{"calls":[["40.714224,-73.961452"]]}'

Ниже приведен ответ на запрос случайной выборки: '{"replies":["{ "DOOR_NUMBER": "277", "STREET_ADDRESS": "Bedford Ave", "AREA": null, "CITY": "Brooklyn", "TOWN": null, "COUNTY": "Kings County", "STATE": "NY", "COUNTRY": "USA", "ZIPCODE": "11211", "LANDMARK": null}}```"]}'

8. Очистка

Чтобы избежать списания средств с вашей учетной записи Google Cloud за ресурсы, используемые в этом посте, выполните следующие действия:

  1. В консоли Google Cloud перейдите на страницу «Управление ресурсами» .
  2. В списке проектов выберите проект, который хотите удалить, и нажмите «Удалить».
  3. В диалоговом окне введите идентификатор проекта, а затем нажмите «Завершить работу», чтобы удалить проект.
  4. Если вы хотите сохранить свой проект, пропустите вышеуказанные шаги и удалите функцию облака, перейдя к функциям облака и в списке функций отметьте ту, которую хотите удалить, и нажмите УДАЛИТЬ.

9. Поздравления

Поздравляем! Вы успешно использовали функцию вызова функций Gemini в приложении Java и преобразовали генеративную задачу ИИ в детерминированный и надежный процесс. Дополнительную информацию о доступных моделях см. в документации по продукту Vertex AI LLM .