Chat yang didukung AI generatif dengan pengguna dan dokumen di Java dengan PaLM dan LangChain4J

1. Pengantar

Terakhir diperbarui: 05-02-2024

Apa itu AI Generatif

AI generatif atau kecerdasan buatan generatif mengacu pada penggunaan AI untuk membuat konten baru, seperti teks, gambar, musik, audio, dan video.

AI generatif didukung oleh model dasar (model AI besar) yang dapat melakukan beberapa tugas sekaligus dan melakukan tugas siap pakai, termasuk perangkuman, tanya jawab, klasifikasi, dan sebagainya. Selain itu, dengan sedikit pelatihan, model dasar dapat diadaptasikan untuk kasus penggunaan tertarget dengan data contoh yang sangat sedikit.

Bagaimana cara kerja AI Generatif?

AI generatif bekerja menggunakan model ML (Machine Learning) untuk mempelajari pola dan hubungan dalam sebuah set data yang terdiri dari konten buatan manusia. Sistem ini kemudian menggunakan pola-pola yang telah dipelajarinya untuk membuat konten baru.

Cara yang paling umum digunakan untuk melatih model AI generatif adalah dengan menggunakan pembelajaran yang diawasi atau supervised learning, yakni model AI generatif diberi satu set konten buatan manusia dan label yang sesuai. AI generatif kemudian belajar membuat konten yang serupa dengan konten buatan manusia tersebut dan diberi label yang sama.

Apa saja aplikasi AI Generatif yang umum?

AI generatif memproses konten yang sangat banyak, membuat insight dan jawaban melalui teks, gambar, dan format yang mudah digunakan. AI generatif dapat digunakan untuk:

  • Meningkatkan interaksi pelanggan melalui chat dan pengalaman penelusuran yang ditingkatkan kualitasnya
  • Menjelajahi jumlah data tak terstruktur yang sangat banyak melalui antarmuka percakapan dan perangkuman
  • Membantu pelaksanaan tugas berulang, seperti membalas permintaan proposal (RFP), melokalkan konten pemasaran dalam lima bahasa, dan memeriksa kontrak pelanggan terkait kepatuhan, dan banyak lagi

Penawaran AI Generatif apa yang dimiliki Google Cloud?

Dengan Vertex AI, Anda dapat berinteraksi dengan model dasar, menyesuaikan model tersebut, dan menyematkannya ke aplikasi Anda tanpa memerlukan keahlian ML. Anda dapat mengakses model dasar di Model Garden, menyesuaikan berbagai model melalui UI yang sederhana di Generative AI Studio, atau menggunakan model dalam notebook data science.

Vertex AI Search and Conversation menawarkan cara tercepat bagi para developer untuk membangun mesin telusur dan chatbot yang didukung teknologi AI generatif.

Selain itu, Duet AI adalah kolaborator Anda dengan teknologi AI yang tersedia di Google Cloud dan IDE untuk membantu Anda menyelesaikan lebih banyak hal dengan lebih cepat.

Apa yang difokuskan oleh codelab ini?

Codelab ini berfokus pada PaLM 2 Large Language Model (LLM), yang dihosting di Vertex AI Google Cloud dan mencakup semua produk dan layanan machine learning.

Anda akan menggunakan Java untuk berinteraksi dengan PaLM API, bersama dengan orkestrasi framework LLM LangChain4J. Anda akan mempelajari berbagai contoh konkret untuk memanfaatkan LLM ini guna menjawab pertanyaan, pembuatan ide, ekstraksi entitas dan konten terstruktur, serta perangkuman.

Ceritakan lebih banyak tentang framework LangChain4J.

Framework LangChain4J adalah library open source untuk mengintegrasikan model bahasa besar (LLM) di aplikasi Java, dengan mengorkestrasi berbagai komponen, seperti LLM itu sendiri, serta alat lain seperti database vektor (untuk penelusuran semantik), loader dokumen, dan pemisah (untuk menganalisis dokumen dan belajar darinya), parser output, dan banyak lagi.

c6d7f7c3fd0d2951.png

Yang akan Anda pelajari

  • Cara menyiapkan project Java untuk menggunakan PaLM dan LangChain4J
  • Cara mengekstrak informasi bermanfaat dari konten tidak terstruktur (ekstraksi entitas atau kata kunci, output di JSON)
  • Cara membuat percakapan dengan pengguna
  • Cara menggunakan model chat untuk mengajukan pertanyaan terkait dokumentasi Anda sendiri

Yang Anda butuhkan

  • Pengetahuan tentang bahasa pemrograman Java
  • Project Google Cloud
  • Browser, seperti Chrome atau Firefox

2. Penyiapan dan persyaratan

Penyiapan lingkungan mandiri

  1. Login ke Google Cloud Console dan buat project baru atau gunakan kembali project yang sudah ada. Jika belum memiliki akun Gmail atau Google Workspace, Anda harus membuatnya.

295004821bab6a87.pngS

37d264871000675d.png

96d86d3d5655cdbe.pngS

  • Project name adalah nama tampilan untuk peserta project ini. String ini adalah string karakter yang tidak digunakan oleh Google API. Anda dapat memperbaruinya kapan saja.
  • Project ID bersifat unik di semua project Google Cloud dan tidak dapat diubah (tidak dapat diubah setelah ditetapkan). Cloud Console otomatis membuat string unik; biasanya Anda tidak mementingkan kata-katanya. Di sebagian besar codelab, Anda harus merujuk Project ID-nya (umumnya diidentifikasi sebagai PROJECT_ID). Jika tidak suka dengan ID yang dibuat, Anda dapat membuat ID acak lainnya. Atau, Anda dapat mencobanya sendiri, dan lihat apakah ID tersebut tersedia. ID tidak dapat diubah setelah langkah ini dan tersedia selama durasi project.
  • Sebagai informasi, ada nilai ketiga, Project Number, yang digunakan oleh beberapa API. Pelajari lebih lanjut ketiga nilai ini di dokumentasi.
  1. Selanjutnya, Anda harus mengaktifkan penagihan di Konsol Cloud untuk menggunakan resource/API Cloud. Menjalankan operasi dalam codelab ini tidak akan memakan banyak biaya, bahkan mungkin tidak sama sekali. Guna mematikan resource agar tidak menimbulkan penagihan di luar tutorial ini, Anda dapat menghapus resource yang dibuat atau menghapus project-nya. Pengguna baru Google Cloud memenuhi syarat untuk mengikuti program Uji Coba Gratis senilai $300 USD.

Mulai Cloud Shell

Meskipun Google Cloud dapat dioperasikan secara jarak jauh dari laptop Anda, dalam codelab ini Anda akan menggunakan Cloud Shell, yakni lingkungan command line yang berjalan di Cloud.

Mengaktifkan Cloud Shell

  1. Dari Cloud Console, klik Aktifkan Cloud Shell d1264ca30785e435.png.

cb81e7c8e34bc8d.png

Jika ini pertama kalinya Anda memulai Cloud Shell, Anda akan melihat layar perantara yang menjelaskan apa itu Cloud Shell. Jika Anda melihat layar perantara, klik Lanjutkan.

d95252b003979716.png

Perlu waktu beberapa saat untuk penyediaan dan terhubung ke Cloud Shell.

7833d5e1c5d18f54.pngS

Mesin virtual ini dimuat dengan semua alat pengembangan yang diperlukan. Layanan ini menawarkan direktori beranda tetap sebesar 5 GB dan beroperasi di Google Cloud, sehingga sangat meningkatkan performa dan autentikasi jaringan. Sebagian besar pekerjaan Anda dalam codelab ini dapat dilakukan dengan browser.

Setelah terhubung ke Cloud Shell, Anda akan melihat bahwa Anda telah diautentikasi dan project sudah ditetapkan ke project ID Anda.

  1. Jalankan perintah berikut di Cloud Shell untuk mengonfirmasi bahwa Anda telah diautentikasi:
gcloud auth list

Output perintah

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Jalankan perintah berikut di Cloud Shell untuk mengonfirmasi bahwa perintah gcloud mengetahui project Anda:
gcloud config list project

Output perintah

[core]
project = <PROJECT_ID>

Jika tidak, Anda dapat menyetelnya dengan perintah ini:

gcloud config set project <PROJECT_ID>

Output perintah

Updated property [core/project].

3. Menyiapkan lingkungan pengembangan Anda

Dalam codelab ini, Anda akan menggunakan terminal dan editor kode Cloud Shell untuk mengembangkan program Java.

Mengaktifkan Vertex AI API

  1. Di konsol Google Cloud, pastikan nama project Anda ditampilkan di bagian atas Konsol Google Cloud. Jika tidak, klik Select a project untuk membuka Project Selector, lalu pilih project yang Anda inginkan.
  2. Jika Anda tidak berada dalam bagian Vertex AI pada Konsol Google Cloud, lakukan hal berikut:
  3. Di Search, masukkan Vertex AI, lalu kembali
  4. Di hasil penelusuran, klik Vertex AI. Dasbor Vertex AI akan muncul.
  5. Klik Enable All Recommended APIs di dasbor Vertex AI.

Tindakan ini akan mengaktifkan beberapa API, tetapi yang paling penting untuk codelab adalah aiplatform.googleapis.com, yang juga dapat Anda aktifkan pada command line, di terminal Cloud Shell, menjalankan perintah berikut:

$ gcloud services enable aiplatform.googleapis.com

Membuat struktur project dengan Gradle

Untuk membuat contoh kode Java, Anda akan menggunakan alat build Gradle, dan Java versi 17. Untuk menyiapkan project dengan Gradle, di terminal Cloud Shell, buat direktori (di sini, palm-workshop), jalankan perintah gradle init di direktori tersebut:

$ mkdir palm-workshop
$ cd palm-workshop

$ gradle init

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 2

Select implementation language:
  1: C++
  2: Groovy
  3: Java
  4: Kotlin
  5: Scala
  6: Swift
Enter selection (default: Java) [1..6] 3

Split functionality across multiple subprojects?:
  1: no - only one application project
  2: yes - application and library projects
Enter selection (default: no - only one application project) [1..2] 1

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] 

Select test framework:
  1: JUnit 4
  2: TestNG
  3: Spock
  4: JUnit Jupiter
Enter selection (default: JUnit Jupiter) [1..4] 4

Project name (default: palm-workshop): 
Source package (default: palm.workshop): 

> Task :init
Get more help with your project: https://docs.gradle.org/7.4/samples/sample_building_java_applications.html

BUILD SUCCESSFUL in 51s
2 actionable tasks: 2 executed

Anda akan membuat aplikasi (opsi 2), menggunakan bahasa Java (opsi 3), tanpa menggunakan subproject (opsi 1), menggunakan sintaksis Groovy untuk file build (opsi 1), jangan gunakan fitur build baru (opsi tidak), menghasilkan pengujian dengan JUnit Jupiter (opsi 4), dan untuk nama project, Anda dapat menggunakan paket workpalm-workpalm., dan juga dapat menggunakan paket workpalm.

Struktur project akan terlihat seperti berikut:

├── gradle 
│   └── ...
├── gradlew 
├── gradlew.bat 
├── settings.gradle 
└── app
    ├── build.gradle 
    └── src
        ├── main
        │   └── java 
        │       └── palm
        │           └── workshop
        │               └── App.java
        └── test
            └── ...

Mari kita update file app/build.gradle untuk menambahkan beberapa dependensi yang diperlukan. Anda dapat menghapus dependensi guava jika ada, dan menggantinya dengan dependensi untuk project LangChain4J, dan library logging untuk menghindari gangguan pesan logger yang hilang:

dependencies {
    // Use JUnit Jupiter for testing.
    testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1'

    // Logging library
    implementation 'org.slf4j:slf4j-jdk14:2.0.9'

    // This dependency is used by the application.
    implementation 'dev.langchain4j:langchain4j-vertex-ai:0.24.0'
    implementation 'dev.langchain4j:langchain4j:0.24.0'
}

Ada 2 dependensi untuk LangChain4J:

  • satu di proyek inti,
  • dan satu lagi untuk modul Vertex AI khusus.

Agar dapat menggunakan Java 17 untuk mengompilasi dan menjalankan program, tambahkan blok berikut di bawah blok plugins {}:

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

Satu perubahan lagi yang harus dilakukan: perbarui blok application dari app/build.gradle, agar pengguna dapat mengganti class utama untuk dijalankan di command line saat memanggil alat build:

application {
    mainClass = providers.systemProperty('javaMainClass')
                         .orElse('palm.workshop.App')
}

Untuk memeriksa apakah file build siap menjalankan aplikasi, Anda dapat menjalankan class utama default yang mencetak pesan Hello World! sederhana:

$ ./gradlew run -DjavaMainClass=palm.workshop.App

> Task :app:run
Hello World!

BUILD SUCCESSFUL in 3s
2 actionable tasks: 2 executed

Sekarang Anda siap memprogram dengan model teks bahasa besar PaLM menggunakan project LangChain4J.

Sebagai referensi, berikut adalah tampilan file build app/build.gradle lengkap sekarang:

plugins {
    // Apply the application plugin to add support for building a CLI application in Java.
    id 'application'
}

java {
    toolchain {
        // Ensure we compile and run on Java 17
        languageVersion = JavaLanguageVersion.of(17)
    }
}

repositories {
    // Use Maven Central for resolving dependencies.
    mavenCentral()
}

dependencies {
    // Use JUnit Jupiter for testing.
    testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1'

    // This dependency is used by the application.
    implementation 'dev.langchain4j:langchain4j-vertex-ai:0.24.0'
    implementation 'dev.langchain4j:langchain4j:0.24.0'
    implementation 'org.slf4j:slf4j-jdk14:2.0.9'
}

application {
    mainClass = providers.systemProperty('javaMainClass').orElse('palm.workshop.App')
}

tasks.named('test') {
    // Use JUnit Platform for unit tests.
    useJUnitPlatform()
}

4. Melakukan panggilan pertama ke model chat PaLM

Setelah project disiapkan dengan benar, sekarang saatnya memanggil PaLM API.

Buat class baru bernama ChatPrompts.java di direktori app/src/main/java/palm/workshop (bersama class App.java default), lalu ketik konten berikut:

package palm.workshop;

import dev.langchain4j.model.vertexai.VertexAiChatModel;
import dev.langchain4j.chain.ConversationalChain;

public class ChatPrompts {
    public static void main(String[] args) {
        VertexAiChatModel model = VertexAiChatModel.builder()
            .endpoint("us-central1-aiplatform.googleapis.com:443")
            .project("YOUR_PROJECT_ID")
            .location("us-central1")
            .publisher("google")
            .modelName("chat-bison@001")
            .maxOutputTokens(400)
            .maxRetries(3)
            .build();

        ConversationalChain chain = ConversationalChain.builder()
            .chatLanguageModel(model)
            .build();

        String message = "What are large language models?";
        String answer = chain.execute(message);
        System.out.println(answer);

        System.out.println("---------------------------");

        message = "What can you do with them?";
        answer = chain.execute(message);
        System.out.println(answer);

        System.out.println("---------------------------");

        message = "Can you name some of them?";
        answer = chain.execute(message);
        System.out.println(answer);
    }
}

Pada contoh pertama ini, Anda perlu mengimpor class VertexAiChatModel, dan ConversationalChain LangChain4J untuk mempermudah penanganan aspek multiturn pada percakapan.

Selanjutnya, dalam metode main, Anda akan mengonfigurasi model bahasa chat, menggunakan builder untuk VertexAiChatModel, guna menentukan:

  • endpoint,
  • menyelesaikan proyek tersebut.
  • wilayah tersebut,
  • penerbit,
  • dan nama model (chat-bison@001).

Setelah model bahasa siap, Anda dapat menyiapkan ConversationalChain. Ini adalah abstraksi level lebih tinggi yang ditawarkan oleh LangChain4J untuk mengonfigurasi bersama-sama berbagai komponen untuk menangani percakapan, seperti model bahasa obrolan itu sendiri, tetapi berpotensi komponen lain untuk menangani riwayat percakapan obrolan, atau untuk menghubungkan alat lain seperti retriever untuk mengambil informasi dari database vektor. Namun jangan khawatir, kita akan kembali membahasnya nanti di codelab ini.

Kemudian, Anda akan melakukan percakapan bolak-balik dengan model chat untuk mengajukan beberapa pertanyaan yang saling terkait. Pertama-tama, Anda ingin tahu tentang LLM, lalu Anda bertanya apa yang dapat Anda lakukan dengan LLM tersebut, dan apa saja contohnya. Perhatikan, Anda tidak perlu mengulang dari awal, LLM tahu bahwa "mereka" berarti LLM, dalam konteks percakapan tersebut.

Untuk melakukan percakapan bolak-balik, Anda cukup memanggil metode execute() di rantai, menambahkannya ke konteks percakapan, model chat akan menghasilkan balasan dan juga menambahkannya ke histori chat.

Untuk menjalankan class ini, jalankan perintah berikut di terminal Cloud Shell:

./gradlew run -DjavaMainClass=palm.workshop.ChatPrompts

Anda akan melihat output yang mirip dengan output ini:

$ ./gradlew run -DjavaMainClass=palm.workshop.ChatPrompts
Starting a Gradle Daemon, 2 incompatible and 2 stopped Daemons could not be reused, use --status for details

> Task :app:run
Large language models (LLMs) are artificial neural networks that are trained on massive datasets of text and code. They are designed to understand and generate human language, and they can be used for a variety of tasks, such as machine translation, question answering, and text summarization.
---------------------------
LLMs can be used for a variety of tasks, such as:

* Machine translation: LLMs can be used to translate text from one language to another.
* Question answering: LLMs can be used to answer questions posed in natural language.
* Text summarization: LLMs can be used to summarize text into a shorter, more concise form.
* Code generation: LLMs can be used to generate code, such as Python or Java code.
* Creative writing: LLMs can be used to generate creative text, such as poems, stories, and scripts.

LLMs are still under development, but they have the potential to revolutionize a wide range of industries. For example, LLMs could be used to improve customer service, create more personalized marketing campaigns, and develop new products and services.
---------------------------
Some of the most well-known LLMs include:

* GPT-3: Developed by OpenAI, GPT-3 is a large language model that can generate text, translate languages, write different kinds of creative content, and answer your questions in an informative way.
* LaMDA: Developed by Google, LaMDA is a large language model that can chat with you in an open-ended way, answering your questions, telling stories, and providing different kinds of creative content.
* PaLM 2: Developed by Google, PaLM 2 is a large language model that can perform a wide range of tasks, including machine translation, question answering, and text summarization.
* T5: Developed by Google, T5 is a large language model that can be used for a variety of tasks, including text summarization, question answering, and code generation.

These are just a few examples of the many LLMs that are currently being developed. As LLMs continue to improve, they are likely to play an increasingly important role in our lives.

BUILD SUCCESSFUL in 25s
2 actionable tasks: 2 executed

PaLM membalas 3 pertanyaan terkait Anda.

Builder VertexAIChatModel memungkinkan Anda menentukan parameter opsional yang sudah memiliki beberapa nilai default yang dapat Anda ganti. Berikut beberapa contohnya:

  • .temperature(0.2) — untuk menentukan seberapa kreatifkah respons yang Anda inginkan (0 jika materi iklan rendah dan sering kali lebih faktual, sedangkan 1 untuk output materi iklan yang lebih banyak)
  • .maxOutputTokens(50) — dalam contoh, 400 token diminta (3 token kira-kira setara dengan 4 kata), bergantung pada berapa lama Anda ingin jawaban yang dihasilkan
  • .topK(20) — untuk memilih kata secara acak dari jumlah maksimum kata yang mungkin untuk pelengkapan teks (dari 1 sampai 40)
  • .topP(0.95) — untuk memilih kemungkinan kata yang total probabilitasnya menjumlahkan bilangan floating point tersebut (antara 0 dan 1)
  • .maxRetries(3) — jika Anda melampaui kuota permintaan per waktu, Anda dapat meminta model untuk mencoba kembali panggilan 3 kali, misalnya

5. Chatbot yang berguna dengan kepribadian.

Di bagian sebelumnya, Anda langsung mengajukan pertanyaan ke chatbot LLM tanpa memberikan konteks tertentu. Namun, Anda dapat mengkhususkan chatbot semacam itu untuk menjadi pakar pada tugas tertentu, atau pada topik tertentu.

Bagaimana Anda melakukannya? Dengan menjelaskan: dengan menjelaskan tugas yang ada pada LLM, konteks, mungkin memberikan beberapa contoh tentang apa yang harus dilakukan, persona apa yang harus dimiliki, dalam format apa Anda ingin mendapatkan respons, dan mungkin nada, jika Anda ingin chatbot berperilaku dengan cara tertentu.

Artikel tentang membuat perintah ini menggambarkan pendekatan ini dengan baik melalui grafik berikut:

8a4c67679dcbd085.png

https://medium.com/@eldatero/master-the-perfect-chatgpt-prompt-formula-c776adae8f19

Untuk menggambarkan hal ini, mari dapatkan beberapa inspirasi dari situs prompts.chat, yang mencantumkan banyak ide keren dan seru dari chatbot kustom yang disesuaikan agar dapat berfungsi sebagai:

Ada satu contoh untuk mengubah chatbot LLM menjadi pemain catur. Mari kita terapkan.

Update class ChatPrompts sebagai berikut:

package palm.workshop;

import dev.langchain4j.chain.ConversationalChain;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.vertexai.VertexAiChatModel;
import dev.langchain4j.store.memory.chat.InMemoryChatMemoryStore;

public class ChatPrompts {
    public static void main(String[] args) {
        VertexAiChatModel model = VertexAiChatModel.builder()
            .endpoint("us-central1-aiplatform.googleapis.com:443")
            .project("YOUR_PROJECT_ID")
            .location("us-central1")
            .publisher("google")
            .modelName("chat-bison@001")
            .maxOutputTokens(7)
            .maxRetries(3)
            .build();

        InMemoryChatMemoryStore chatMemoryStore = new InMemoryChatMemoryStore();

        MessageWindowChatMemory chatMemory = MessageWindowChatMemory.builder()
            .chatMemoryStore(chatMemoryStore)
            .maxMessages(200)
            .build();

        chatMemory.add(SystemMessage.from("""
            You're an expert chess player with a high ELO ranking.
            Use the PGN chess notation to reply with the best next possible move.
            """
        ));


        ConversationalChain chain = ConversationalChain.builder()
            .chatLanguageModel(model)
            .chatMemory(chatMemory)
            .build();

        String pgn = "";
        String[] whiteMoves = { "Nf3", "c4", "Nc3", "e3", "Dc2", "Cd5"};
        for (int i = 0; i < whiteMoves.length; i++) {
            pgn += " " + (i+1) + ". " + whiteMoves[i];
            System.out.println("Playing " + whiteMoves[i]);
            pgn = chain.execute(pgn);
            System.out.println(pgn);
        }
    }
}

Mari kita uraikan langkah demi langkah:

  • Beberapa impor baru diperlukan untuk menangani memori chat.
  • Anda membuat instance model chat, tetapi dengan sejumlah kecil token maksimum (di sini 7), karena kita hanya ingin membuat langkah berikutnya, bukan seluruh disertasi tentang catur!
  • Selanjutnya, Anda akan membuat penyimpanan memori chat untuk menyimpan percakapan chat.
  • Anda membuat memori chat berjendela yang sebenarnya untuk mempertahankan gerakan terakhir.
  • Di memori chat, Anda menambahkan "sistem" pesan yang menginstruksikan model chat tentang siapa yang seharusnya (yaitu pemain catur ahli). "Sistem" menambahkan konteks, sedangkan "pengguna" dan "AI" pesan adalah diskusi yang sebenarnya.
  • Anda membuat rantai percakapan yang menggabungkan memori dan model chat.
  • Kemudian, kita memiliki daftar gerakan untuk warna putih, yang akan Anda ulangi. Rantai tersebut dieksekusi dengan gerakan putih berikutnya setiap kali, dan model chat membalas dengan gerakan terbaik berikutnya.

Saat menjalankan class ini dengan gerakan ini, Anda akan melihat output berikut:

$ ./gradlew run -DjavaMainClass=palm.workshop.ChatPrompts
Starting a Gradle Daemon (subsequent builds will be faster)

> Task :app:run
Playing Nf3
1... e5
Playing c4
2... Nc6
Playing Nc3
3... Nf6
Playing e3
4... Bb4
Playing Dc2
5... O-O
Playing Cd5
6... exd5 

Wah! PaLM tahu cara bermain catur? Sebenarnya tidak. Namun, selama pelatihan, model ini pasti telah melihat beberapa komentar game catur, atau bahkan file PGN (Portable Game Notation) dari game sebelumnya. Chatbot ini kemungkinan tidak akan menang dari AlphaZero (AI yang mengalahkan pemain Go, Shogi, dan Catur terbaik) dan percakapan mungkin akan mengacaukan di kemudian hari, karena model tidak benar-benar mengingat keadaan game yang sebenarnya.

Model chat sangat canggih dan dapat membuat interaksi yang kaya dengan pengguna Anda, dan menangani berbagai tugas kontekstual. Pada bagian selanjutnya, kita akan melihat tugas yang berguna: mengekstrak data terstruktur dari teks.

6. Mengekstrak informasi dari teks yang tidak terstruktur

Di bagian sebelumnya, Anda telah membuat percakapan antara pengguna dan model bahasa chat. Namun dengan LangChain4J, Anda juga dapat menggunakan model chat untuk mengekstrak informasi terstruktur dari teks yang tidak terstruktur.

Misalkan Anda ingin mengekstrak nama dan usia seseorang, berdasarkan biografi atau deskripsi orang tersebut. Anda dapat menginstruksikan model bahasa besar (LLM) untuk menghasilkan struktur data JSON dengan perintah yang disesuaikan dengan cerdas (ini biasanya disebut "prompt engineering").

Anda akan mengupdate class ChatPrompts sebagai berikut:

package palm.workshop;

import dev.langchain4j.model.vertexai.VertexAiChatModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.UserMessage;

public class ChatPrompts {

    static class Person {
        String name;
        int age;
    }

    interface PersonExtractor {
        @UserMessage("""
            Extract the name and age of the person described below.
            Return a JSON document with a "name" and an "age" property, \
            following this structure: {"name": "John Doe", "age": 34}
            Return only JSON, without any markdown markup surrounding it.
            Here is the document describing the person:
            ---
            {{it}}
            ---
            JSON: 
            """)
        Person extractPerson(String text);
    }

    public static void main(String[] args) {
        VertexAiChatModel model = VertexAiChatModel.builder()
            .endpoint("us-central1-aiplatform.googleapis.com:443")
            .project("YOUR_PROJECT_ID")
            .location("us-central1")
            .publisher("google")
            .modelName("chat-bison@001")
            .maxOutputTokens(300)
            .build();
        
        PersonExtractor extractor = AiServices.create(PersonExtractor.class, model);

        Person person = extractor.extractPerson("""
            Anna is a 23 year old artist based in Brooklyn, New York. She was born and 
            raised in the suburbs of Chicago, where she developed a love for art at a 
            young age. She attended the School of the Art Institute of Chicago, where 
            she studied painting and drawing. After graduating, she moved to New York 
            City to pursue her art career. Anna's work is inspired by her personal 
            experiences and observations of the world around her. She often uses bright 
            colors and bold lines to create vibrant and energetic paintings. Her work 
            has been exhibited in galleries and museums in New York City and Chicago.    
            """
        );

        System.out.println(person.name);
        System.out.println(person.age);
    }
}

Mari kita lihat berbagai langkah dalam file ini:

  • Class Person ditentukan untuk mewakili detail yang mendeskripsikan seseorang (nama dan usianya).
  • Antarmuka PersonExtractor dibuat dengan metode yang, dengan string teks tidak terstruktur, menampilkan instance Person yang dibuat instance.
  • extractPerson() dianotasi dengan anotasi @UserMessage yang mengaitkan perintah dengannya. Itulah perintah yang akan digunakan model untuk mengekstrak informasi, dan menampilkan detail dalam bentuk dokumen JSON, yang akan diurai untuk Anda, dan dibatalkan susunannya menjadi instance Person.

Sekarang mari kita lihat konten metode main():

  • Model chat dibuat instance-nya.
  • Objek PersonExtractor dibuat berkat class AiServices LangChain4J.
  • Kemudian, Anda cukup memanggil Person person = extractor.extractPerson(...) untuk mengekstrak detail orang dari teks yang tidak terstruktur, dan mendapatkan kembali instance Person dengan nama dan usia.

Sekarang, jalankan class ini dengan perintah berikut:

$ ./gradlew run -DjavaMainClass=palm.workshop.ChatPrompts

> Task :app:run
Anna
23

Ya. Ini Anna, dia berusia 23 tahun!

Yang menarik dengan pendekatan AiServices ini adalah Anda beroperasi dengan objek dengan jenis yang kuat. Anda tidak berinteraksi langsung dengan LLM chat. Sebagai gantinya, Anda sedang mengerjakan class konkret, seperti class Person untuk menampilkan informasi pribadi yang diekstrak, dan Anda memiliki class PersonExtractor dengan metode extractPerson() yang menampilkan instance Person. Konsep LLM diabstraksi, dan sebagai developer Java, Anda hanya memanipulasi class dan objek normal.

7. Mengambil Augmented Generation: melakukan chat dengan dokumen Anda

Mari kita kembali ke percakapan. Kali ini, Anda akan dapat mengajukan pertanyaan tentang dokumen Anda. Anda akan membuat chatbot yang dapat mengambil informasi yang relevan dari database ekstrak dokumen, dan informasi tersebut akan digunakan oleh model untuk "mendasarkan" jawabannya, bukan mencoba menghasilkan respons yang berasal dari pelatihannya. Pola ini disebut RAG, atau Retrieval Augmented Generation.

Dalam Retrieval Augmented Generation, secara ringkasnya, ada dua fase:

  1. Fase penyerapan — Dokumen dimuat, dibagi menjadi potongan-potongan yang lebih kecil, dan representasi vektor ("penyematan vektor") disimpan dalam "database vektor" yang mampu melakukan penelusuran semantik.

6c5bb5cb2e3b8088.pngS

  1. Fase kueri — Pengguna kini dapat mengajukan pertanyaan tentang dokumentasi ke chatbot Anda. Pertanyaan juga akan diubah menjadi vektor, dan dibandingkan dengan semua vektor lain dalam database. Vektor yang paling mirip biasanya terkait secara semantik, dan ditampilkan oleh database vektor. Kemudian, LLM diberi konteks percakapan, cuplikan teks yang sesuai dengan vektor yang ditampilkan oleh database, dan diminta untuk mendasarkan jawabannya dengan melihat cuplikan tersebut.

2c279c506d7606cd.pngS

Mempersiapkan dokumen Anda

Untuk demo baru ini, Anda akan mengajukan pertanyaan tentang arsitektur jaringan neural "transformer", yang dipelopori oleh Google, yang merupakan cara penerapan semua model bahasa besar modern saat ini.

Anda dapat mengambil makalah riset yang mendeskripsikan arsitektur ini ("Attention is all you need"), dengan menggunakan perintah wget untuk mendownload PDF dari internet:

wget -O attention-is-all-you-need.pdf \
    https://proceedings.neurips.cc/paper_files/paper/2017/file/3f5ee243547dee91fbd053c1c4a845aa-Paper.pdf

Mengimplementasikan rantai pengambilan percakapan

Mari kita pelajari, sepotong demi sepotong, cara membangun pendekatan 2 fase, pertama dengan penyerapan dokumen, lalu waktu kueri saat pengguna mengajukan pertanyaan tentang dokumen.

Penyerapan dokumen

Langkah pertama dari fase penyerapan dokumen adalah menemukan file PDF yang kita download, dan menyiapkan PdfParser untuk membacanya:

PdfDocumentParser pdfParser = new PdfDocumentParser();
Document document = pdfParser.parse(
    new FileInputStream(new File("/home/YOUR_USER_NAME/palm-workshop/attention-is-all-you-need.pdf")));

Daripada membuat model bahasa chat biasa, sebelum itu, Anda akan membuat instance model "embedding". Model ini adalah model dan endpoint tertentu yang perannya adalah membuat representasi vektor dari potongan teks (kata, kalimat, atau bahkan paragraf).

VertexAiEmbeddingModel embeddingModel = VertexAiEmbeddingModel.builder()
    .endpoint("us-central1-aiplatform.googleapis.com:443")
    .project("YOUR_PROJECT_ID")
    .location("us-central1")
    .publisher("google")
    .modelName("textembedding-gecko@001")
    .maxRetries(3)
    .build();

Selanjutnya, Anda memerlukan beberapa kelas untuk dikerjakan bersama guna:

  • Muat dan bagi dokumen PDF dalam beberapa bagian.
  • Membuat embedding vektor untuk semua potongan ini.
InMemoryEmbeddingStore<TextSegment> embeddingStore = 
    new InMemoryEmbeddingStore<>();

EmbeddingStoreIngestor storeIngestor = EmbeddingStoreIngestor.builder()
    .documentSplitter(DocumentSplitters.recursive(500, 100))
    .embeddingModel(embeddingModel)
    .embeddingStore(embeddingStore)
    .build();
storeIngestor.ingest(document);

EmbeddingStoreRetriever retriever = EmbeddingStoreRetriever.from(embeddingStore, embeddingModel);

Instance InMemoryEmbeddingStore, yang merupakan database vektor dalam memori, dibuat untuk menyimpan embedding vektor.

Dokumen ini dibagi menjadi beberapa bagian berkat class DocumentSplitters. Ini akan membagi teks file PDF menjadi cuplikan 500 karakter, dengan tumpang tindih 100 karakter (dengan potongan berikut, untuk menghindari pemotongan kata atau kalimat, menjadi per bagian).

"Inestor" toko menautkan pemisah dokumen, model embedding untuk menghitung vektor, dan database vektor dalam memori. Kemudian, metode ingest() akan menangani penyerapan.

Sekarang, fase pertama selesai, dokumen telah diubah menjadi potongan teks dengan embedding vektor terkait, dan disimpan dalam database vektor.

Mengajukan pertanyaan

Saatnya bersiap mengajukan pertanyaan! Model chat biasa dapat dibuat untuk memulai percakapan:

VertexAiChatModel model = VertexAiChatModel.builder()
    .endpoint("us-central1-aiplatform.googleapis.com:443")
    .project("YOUR_PROJECT_ID")
    .location("us-central1")
    .publisher("google")
    .modelName("chat-bison@001")
    .maxOutputTokens(1000)
    .build();

Anda juga memerlukan class "fetchr" yang akan menghubungkan database vektor (dalam variabel embeddingStore) dan model embedding. Tugasnya adalah mengkueri database vektor dengan menghitung embedding vektor untuk kueri pengguna, untuk menemukan vektor serupa dalam database:

EmbeddingStoreRetriever retriever = 
    EmbeddingStoreRetriever.from(embeddingStore, embeddingModel);

Pada tahap ini, Anda dapat membuat instance class ConversationalRetrievalChain (ini hanya nama yang berbeda untuk pola Pembuatan Augmented Pengambilan):

ConversationalRetrievalChain rag = ConversationalRetrievalChain.builder()
    .chatLanguageModel(model)
    .retriever(retriever)
    .promptTemplate(PromptTemplate.from("""
        Answer to the following query the best as you can: {{question}}
        Base your answer on the information provided below:
        {{information}}
        """
    ))
    .build();

"Rantai" ini saling mengikat:

  • Model bahasa chat yang Anda konfigurasi sebelumnya.
  • Pengambil membandingkan kueri penyematan vektor dengan vektor dalam database.
  • Template perintah secara eksplisit menyatakan bahwa model chat harus membalas dengan mendasarkan responsnya pada informasi yang diberikan (yaitu cuplikan relevan dari dokumentasi yang penyematan vektornya mirip dengan vektor pertanyaan pengguna).

Dan sekarang Anda akhirnya siap mengajukan pertanyaan!

String result = rag.execute("What neural network architecture can be used for language models?");
System.out.println(result);
System.out.println("------------");

result = rag.execute("What are the different components of a transformer neural network?");
System.out.println(result);
System.out.println("------------");

result = rag.execute("What is attention in large language models?");
System.out.println(result);
System.out.println("------------");

result = rag.execute("What is the name of the process that transforms text into vectors?");
System.out.println(result);

Jalankan program dengan:

$ ./gradlew run -DjavaMainClass=palm.workshop.ChatPrompts

Di output, Anda akan melihat jawaban atas pertanyaan Anda:

The Transformer is a neural network architecture that can be used for 
language models. It is based solely on attention mechanisms, dispensing 
with recurrence and convolutions. The Transformer has been shown to 
outperform recurrent neural networks and convolutional neural networks on 
a variety of language modeling tasks.
------------
The Transformer is a neural network architecture that can be used for 
language models. It is based solely on attention mechanisms, dispensing 
with recurrence and convolutions. The Transformer has been shown to 
outperform recurrent neural networks and convolutional neural networks on a 
variety of language modeling tasks. The Transformer consists of an encoder 
and a decoder. The encoder is responsible for encoding the input sequence 
into a fixed-length vector representation. The decoder is responsible for 
decoding the output sequence from the input sequence. The decoder uses the 
attention mechanism to attend to different parts of the input sequence when 
generating the output sequence.
------------
Attention is a mechanism that allows a neural network to focus on specific 
parts of an input sequence. In the context of large language models, 
attention is used to allow the model to focus on specific words or phrases 
in a sentence when generating output. This allows the model to generate 
more relevant and informative output.
------------
The process of transforming text into vectors is called word embedding. 
Word embedding is a technique that represents words as vectors in a 
high-dimensional space. The vectors are typically learned from a large 
corpus of text, and they capture the semantic and syntactic relationships 
between words. Word embedding has been shown to be effective for a variety 
of natural language processing tasks, such as machine translation, question 
answering, and sentiment analysis.

Solusi lengkap

Untuk memfasilitasi penyalinan dan penempelan, berikut adalah konten lengkap class ChatPrompts:

package palm.workshop;

import dev.langchain4j.chain.ConversationalRetrievalChain;
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.parser.PdfDocumentParser;
import dev.langchain4j.data.document.splitter.DocumentSplitters;
import dev.langchain4j.data.segment.TextSegment; 
import dev.langchain4j.model.input.PromptTemplate;
import dev.langchain4j.model.vertexai.VertexAiChatModel;
import dev.langchain4j.model.vertexai.VertexAiEmbeddingModel;
import dev.langchain4j.retriever.EmbeddingStoreRetriever;
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class ChatPrompts {
    public static void main(String[] args) throws IOException {
        PdfDocumentParser pdfParser = new PdfDocumentParser();
        Document document = pdfParser.parse(new FileInputStream(new File("/ABSOLUTE_PATH/attention-is-all-you-need.pdf")));

        VertexAiEmbeddingModel embeddingModel = VertexAiEmbeddingModel.builder()
            .endpoint("us-central1-aiplatform.googleapis.com:443")
            .project("YOUR_PROJECT_ID")
            .location("us-central1")
            .publisher("google")
            .modelName("textembedding-gecko@001")
            .maxRetries(3)
            .build();

        InMemoryEmbeddingStore<TextSegment> embeddingStore = 
            new InMemoryEmbeddingStore<>();

        EmbeddingStoreIngestor storeIngestor = EmbeddingStoreIngestor.builder()
            .documentSplitter(DocumentSplitters.recursive(500, 100))
            .embeddingModel(embeddingModel)
            .embeddingStore(embeddingStore)
            .build();
        storeIngestor.ingest(document);

        EmbeddingStoreRetriever retriever = EmbeddingStoreRetriever.from(embeddingStore, embeddingModel);

        VertexAiChatModel model = VertexAiChatModel.builder()
            .endpoint("us-central1-aiplatform.googleapis.com:443")
            .project("genai-java-demos")
            .location("us-central1")
            .publisher("google")
            .modelName("chat-bison@001")
            .maxOutputTokens(1000)
            .build();

        ConversationalRetrievalChain rag = ConversationalRetrievalChain.builder()
            .chatLanguageModel(model)
            .retriever(retriever)
            .promptTemplate(PromptTemplate.from("""
                Answer to the following query the best as you can: {{question}}
                Base your answer on the information provided below:
                {{information}}
                """
            ))
            .build();

        String result = rag.execute("What neural network architecture can be used for language models?");
        System.out.println(result);
        System.out.println("------------");

        result = rag.execute("What are the different components of a transformer neural network?");
        System.out.println(result);
        System.out.println("------------");

        result = rag.execute("What is attention in large language models?");
        System.out.println(result);
        System.out.println("------------");

        result = rag.execute("What is the name of the process that transforms text into vectors?");
        System.out.println(result);
    }
}

8. Selamat

Selamat, Anda berhasil membangun aplikasi chat AI Generatif pertama Anda di Java menggunakan LangChain4J dan PaLM API. Dalam prosesnya, Anda telah mendapati bahwa model chat bahasa besar cukup canggih dan mampu menangani berbagai tugas seperti tanya jawab, bahkan pada dokumentasi Anda sendiri, ekstraksi data, dan sampai batas tertentu, ia bahkan dapat bermain Catur!

Apa selanjutnya?

Lihat beberapa codelab berikut untuk melanjutkan dengan PaLM di Java:

Bacaan lebih lanjut

Dokumen referensi