AI generatif determenistik dengan panggilan fungsi Gemini di Java

1. Pengantar

Model AI generatif luar biasa dalam memahami dan merespons bahasa alami. Namun, bagaimana jika Anda memerlukan output yang tepat dan dapat diprediksi untuk tugas penting seperti standardisasi alamat? Model generatif tradisional terkadang dapat memberikan respons yang berbeda pada waktu yang berbeda untuk perintah yang sama, yang berpotensi menyebabkan inkonsistensi. Di sinilah kemampuan Panggilan Fungsi Gemini bersinar, sehingga Anda dapat mengontrol elemen respons AI secara determenistik.

Codelab ini menggambarkan konsep ini dengan kasus penggunaan penyelesaian alamat dan standardisasi. Untuk itu, kita akan membangun Java Cloud Function yang melakukan tugas-tugas berikut:

  1. Mengambil koordinat lintang dan bujur
  2. Memanggil Google Maps Geocoding API untuk mendapatkan alamat yang sesuai
  3. Menggunakan fitur Panggilan Fungsi Gemini 1.0 Pro untuk menstandarkan dan meringkas alamat tersebut secara pasti yang kita butuhkan

Ayo kita mulai!

2. Panggilan fungsi Gemini

Panggilan Fungsi Gemini menarik perhatian di era AI Generatif karena memungkinkan Anda memadukan fleksibilitas model bahasa generatif dengan presisi pemrograman tradisional.

Berikut tugas yang perlu Anda selesaikan untuk menerapkan panggilan fungsi Gemini:

  1. Mendefinisikan fungsi: mendeskripsikan fungsi dengan jelas. Deskripsi harus menyertakan informasi berikut:
  • Nama fungsi, seperti getAddress.
  • Parameter yang diharapkan oleh fungsi, seperti latlng sebagai string.
  • Jenis data yang ditampilkan fungsi, seperti daftar string alamat.
  1. Buat alat untuk Gemini: memaketkan deskripsi fungsi dalam bentuk spesifikasi API ke dalam alat. Anggaplah alat ini sebagai toolbox khusus yang dapat digunakan Gemini untuk memahami fungsi API.
  2. Orkestrasi API menggunakan Gemini: saat Anda mengirim perintah ke Gemini, perintah tersebut dapat menganalisis permintaan Anda dan mengenali di mana perintah tersebut dapat menggunakan alat yang Anda sediakan. Gemini kemudian bertindak sebagai orkestrator cerdas dengan melakukan tugas-tugas berikut:
  • Menghasilkan parameter API yang diperlukan untuk memanggil fungsi yang Anda tentukan. Gemini tidak memanggil API untuk Anda. Anda harus memanggil API berdasarkan parameter dan tanda tangan yang telah dihasilkan oleh panggilan fungsi Gemini untuk Anda.
  • Gemini memproses hasilnya dengan memasukkan hasil dari panggilan API Anda kembali ke pembuatannya, dan memasukkan informasi terstruktur ke dalam respons akhirnya. Anda dapat memproses informasi ini dengan cara yang Anda inginkan untuk permohonan Anda.

Gambar berikut menunjukkan alur data, langkah-langkah yang terlibat dalam implementasi, dan pemilik untuk setiap langkah, seperti aplikasi, LLM, atau API:

b9a39f55567072d3.png

Yang akan Anda bangun

Anda akan membuat dan men-deploy Java Cloud Function yang melakukan hal berikut:

  • Mengambil koordinat lintang dan bujur.
  • Memanggil Google Maps Geocoding API untuk mendapatkan alamat yang sesuai.
  • Menggunakan fitur panggilan fungsi Gemini 1.0 Pro untuk menstandarkan dan meringkas alamat tersebut secara pasti dalam format tertentu.

3. Persyaratan

  • Browser, seperti Chrome atau Firefox.
  • Project Google Cloud dengan penagihan diaktifkan.

4. Sebelum memulai

  1. Di Konsol Google Cloud, di halaman pemilih project, pilih atau buat project Google Cloud.
  2. Pastikan penagihan diaktifkan untuk project Google Cloud Anda. Pelajari cara memeriksa apakah penagihan telah diaktifkan pada suatu project.
  3. Aktifkan Cloud Shell dari Konsol Google Cloud. Untuk mengetahui informasi selengkapnya, lihat Menggunakan Cloud Shell.
  4. Jika project Anda belum ditetapkan, gunakan perintah berikut untuk menetapkan project:
gcloud config set project <YOUR_PROJECT_ID>
  1. Di Cloud Shell, tetapkan variabel lingkungan berikut:
export GCP_PROJECT=<YOUR_PROJECT_ID>
export GCP_REGION=us-central1
  1. Aktifkan Google Cloud API yang diperlukan dengan menjalankan perintah berikut di 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. Buka Cloud Shell Editor, klik Ekstensi, lalu instal ekstensi Gemini + Google Cloud Code.

5. Mengimplementasikan Cloud Function

  1. Luncurkan Cloud Shell Editor.
  2. Klik Cloud Code, lalu luaskan bagian Cloud Functions.
  3. Klik ikon Create Function (+).
  4. Pada dialog Create New Application, pilih opsi Java: Hello World.
  5. Beri nama project di jalur project, seperti GeminiFunctionCalling.
  6. Klik Explorer untuk melihat struktur project, lalu buka file pom.xml. Gambar berikut menunjukkan struktur project:

bdf07515f413dd9e.png

  1. Tambahkan dependensi yang diperlukan dalam tag <dependencies>... </dependencies> di file pom.xml. Anda dapat mengakses seluruh pom.xml dari repositori github project ini. Salin pom.xml dari sana ke file pom.xml project saat ini yang sedang Anda edit.
  2. Salin class HelloWorld.java dari link github GeminiFunctionCalling. Anda harus memperbarui API_KEY dan project_id dengan kunci API geocoding dan ID Project Google Cloud.

6. Memahami panggilan fungsi menggunakan class HelloWorld.java

Input perintah

Dalam contoh ini, berikut adalah prompt input: What's the address for the latlong value 40.714224,-73.961452.

Berikut adalah cuplikan kode yang sesuai dengan perintah input dalam file:

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

Spesifikasi API

Reverse Geocoding API digunakan dalam contoh ini. Berikut adalah spesifikasi 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();

Mengorkestrasi perintah dengan Gemini

Input perintah dan spesifikasi API dikirim ke 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();

Respons dari hal ini adalah parameter JSON terorkestrasi ke API. Berikut adalah contoh output:

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

Teruskan parameter berikut ke Reverse Geocoding API: "latlng=40.714224,-73.961452"

Cocokkan hasil orkestrasi dengan format "latlng=VALUE".

Memanggil API

Berikut adalah bagian kode yang memanggil 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();

String jsonResult menyimpan respons dari Geocoding API terbalik. Berikut adalah versi output berformat:

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

Memproses respons API dan menyiapkan perintah

Kode berikut memproses respons dari API dan menyiapkan prompt dengan petunjuk tentang cara memproses respons:

// 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()
   );

Memanggil Gemini dan menampilkan alamat yang distandardisasi

Kode berikut akan meneruskan output yang diproses dari langkah sebelumnya sebagai perintah ke 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);

Variabel finalAnswer memiliki alamat standar dalam format JSON. Berikut adalah contoh output:

{"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}"]}

Setelah Anda memahami cara kerja Panggilan Fungsi Gemini dengan kasus penggunaan standardisasi alamat, Anda dapat melanjutkan dan men-deploy Cloud Function.

7. Men-deploy dan menguji

  1. Jika Anda telah membuat project GeminiFunctionCalling dan mengimplementasikan Cloud Function, lanjutkan ke langkah 2. Jika Anda belum membuat project, buka terminal Cloud Shell, clone repo ini: git clone https://github.com/AbiramiSukumaran/GeminiFunctionCalling
  2. Buka folder project: cd GeminiFunctionCalling
  3. Jalankan pernyataan berikut untuk membangun dan men-deploy Cloud Function:
gcloud functions deploy gemini-fn-calling --gen2 --region=us-central1 --runtime=java11 --source=. --entry-point=cloudcode.helloworld.HelloWorld --trigger-http

Berikut adalah format URL setelah deployment: https://us-central1-YOUR_PROJECT_ID.cloudfunctions.net/gemini-fn-calling

  1. Uji Cloud Function dengan menjalankan perintah berikut dari terminal:
gcloud functions call gemini-fn-calling --region=us-central1 --gen2 --data '{"calls":[["40.714224,-73.961452"]]}'

Berikut adalah respons untuk contoh perintah acak: '{"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. Pembersihan

Agar tidak menimbulkan biaya pada akun Google Cloud Anda untuk resource yang digunakan dalam posting ini, ikuti langkah-langkah berikut:

  1. Di konsol Google Cloud, buka halaman Manage resource.
  2. Dalam daftar project, pilih project yang ingin Anda hapus, lalu klik Delete.
  3. Pada dialog, ketik project ID, lalu klik Shut Down untuk menghapus project.
  4. Jika Anda ingin menyimpan project, lewati langkah-langkah di atas dan hapus Cloud Function dengan membuka Cloud Functions. Dari daftar fungsi, centang fungsi yang ingin dihapus, lalu klik DELETE.

9. Selamat

Selamat! Anda telah berhasil menggunakan fitur panggilan fungsi Gemini di aplikasi Java dan mengubah tugas AI generatif menjadi proses yang determenistik dan andal. Untuk mempelajari lebih lanjut model yang tersedia, lihat dokumentasi produk LLM Vertex AI.