AI generatif determenistik dengan panggilan fungsi Gemini di Java

1. Pengantar

Model AI generatif sangat baik dalam memahami dan merespons bahasa alami. Namun, bagaimana jika Anda memerlukan output yang presisi 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, sehingga berpotensi menyebabkan inkonsistensi. Di sinilah kemampuan Panggilan Fungsi Gemini berperan, yang memungkinkan Anda mengontrol elemen respons AI secara deterministik.

Codelab ini mengilustrasikan konsep ini dengan kasus penggunaan penyelesaian dan standardisasi alamat. Untuk itu, kita akan membangun Java Cloud Function yang melakukan 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 menstandardisasi dan meringkas alamat tersebut secara deterministik dalam format tertentu yang kita butuhkan

Ayo kita mulai!

2. Panggilan fungsi Gemini

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

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

  1. Tentukan fungsi: deskripsikan fungsi dengan jelas. Deskripsi harus menyertakan informasi berikut:
  • Nama fungsi, seperti getAddress.
  • Parameter yang diharapkan fungsi, seperti latlng sebagai string.
  • Jenis data yang ditampilkan fungsi, seperti daftar string alamat.
  1. Membuat alat untuk Gemini: mengemas deskripsi fungsi dalam bentuk spesifikasi API ke dalam alat. Anggap alat sebagai kotak peralatan khusus yang dapat digunakan Gemini untuk memahami fungsi API.
  2. Mengatur API menggunakan Gemini: saat Anda mengirim perintah ke Gemini, Gemini dapat menganalisis permintaan Anda dan mengenali tempat Gemini dapat menggunakan alat yang telah Anda berikan. Kemudian, Gemini bertindak sebagai pengelola cerdas dengan melakukan tugas berikut:
  • Membuat parameter API yang diperlukan untuk memanggil fungsi yang Anda tentukan. Gemini tidak memanggil API atas nama Anda. Anda harus memanggil API berdasarkan parameter dan tanda tangan yang telah dihasilkan oleh panggilan fungsi Gemini untuk Anda.
  • Gemini memproses hasil dengan memasukkan kembali hasil dari panggilan API Anda ke dalam proses pembuatannya, dan menggabungkan informasi terstruktur ke dalam respons akhirnya. Anda dapat memproses informasi ini sesuai keinginan untuk aplikasi Anda.

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

b9a39f55567072d3.png

Yang akan Anda bangun

Anda akan membuat dan men-deploy Cloud Function Java 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 menstandardisasi dan meringkas alamat tersebut secara deterministik dalam format tertentu.

3. Persyaratan

  • Browser, seperti Chrome atau Firefox.
  • Project Google Cloud yang mengaktifkan penagihan.

4. Sebelum memulai

  1. Di Konsol Google Cloud, di halaman pemilih project, pilih atau buat project Google Cloud.
  2. Pastikan penagihan telah 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 Anda:
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 Extensions, 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. Berikan nama untuk 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 GeminiFunctionCalling github. Anda harus memperbarui API_KEY dan project_id dengan kunci API geocoding dan ID Project Google Cloud Anda.

6. Memahami panggilan fungsi menggunakan class HelloWorld.java

Input perintah

Dalam contoh ini, perintah inputnya adalah: Apa alamat untuk nilai latlong 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();

Mengatur 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 ini adalah JSON parameter yang diatur ke API. Berikut contoh outputnya:

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 yang diatur 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 reverse Geocoding API. Berikut adalah versi output yang diformat:

"...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 perintah 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 standar

Kode berikut 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 memahami cara kerja Panggilan Fungsi Gemini dengan kasus penggunaan standarisasi alamat, Anda dapat melanjutkan dan men-deploy Cloud Function.

7. Men-deploy dan menguji

  1. Jika Anda telah membuat project GeminiFunctionCalling dan menerapkan 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 perintah sampel 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 resources.
  2. Dalam daftar project, pilih project yang ingin Anda hapus, lalu klik Hapus.
  3. Pada dialog, ketik project ID, lalu klik Shut down untuk menghapus project.
  4. Jika Anda ingin mempertahankan project, lewati langkah-langkah di atas dan hapus Cloud Function dengan membuka Cloud Functions, lalu dari daftar fungsi, centang fungsi yang ingin Anda hapus dan klik HAPUS.

9. Selamat

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