PaLM ve LangChain4J ile Java'da kullanıcılar ve dokümanlarla üretken yapay zeka destekli sohbet

1. Giriş

Last Updated: 2024-02-05

Üretken yapay zeka nedir?

Üretken yapay zeka, metin, resim, müzik, ses ve video gibi yeni içerikler oluşturmak için yapay zekanın kullanılmasını ifade eder.

Üretken yapay zeka, özetleme, soru-cevap ve sınıflandırma gibi kullanıma hazır görevleri yerine getirebilen ve çok görevli çalışabilen temel modeller (büyük yapay zeka modelleri) tarafından desteklenir. Ayrıca, temel modeller çok az örnek veriyle hedeflenen kullanım alanlarına uyarlanabilir ve minimum eğitim gerektirir.

Üretken yapay zeka nasıl çalışır?

Üretken yapay zeka, insan tarafından oluşturulan içeriklerden oluşan bir veri kümesindeki kalıpları ve ilişkileri öğrenmek için bir makine öğrenimi modeli kullanarak çalışır. Ardından, öğrendiği kalıpları kullanarak yeni içerikler üretir.

Üretken yapay zeka modellerini eğitmenin en yaygın yolu, gözetimli öğrenmeyi kullanmaktır. Bu yöntemde modele, insanlar tarafından oluşturulan bir dizi içerik ve bunlara karşılık gelen etiketler verilir. Ardından, kullanıcılar tarafından oluşturulan içeriklere benzer ve aynı etiketlerle etiketlenmiş içerikler oluşturmayı öğrenir.

Üretken yapay zekanın yaygın kullanım alanları nelerdir?

Üretken yapay zeka, metin, resim ve kullanıcı dostu formatlar aracılığıyla analizler ve yanıtlar oluşturarak büyük miktarda içeriği işler. Üretken yapay zeka şu amaçlarla kullanılabilir:

  • Gelişmiş sohbet ve arama deneyimleriyle müşteri etkileşimlerini iyileştirme
  • Sohbet arayüzleri ve özetler aracılığıyla büyük miktarda yapılandırılmamış veriyi keşfedin
  • Teklif isteklerine (RFP) yanıt verme, pazarlama içeriklerini beş dilde yerelleştirme ve müşteri sözleşmelerinin uygunluğunu kontrol etme gibi tekrarlayan görevlere yardımcı olma

Google Cloud'un sunduğu üretken yapay zeka teklifleri nelerdir?

Vertex AI ile temel modellerle etkileşim kurabilir, bunları özelleştirebilir ve uygulamalarınıza yerleştirebilirsiniz. Makine öğrenimi konusunda uzman olmanız gerekmez. Model Garden'daki temel modellere erişin, Generative AI Studio'daki basit bir kullanıcı arayüzü aracılığıyla modelleri ayarlayın veya modelleri bir veri bilimi not defterinde kullanın.

Vertex AI Arama ve Sohbet, geliştiricilere üretken yapay zeka destekli arama motorları ve chatbot'lar oluşturmanın en hızlı yolunu sunar.

Ayrıca, Duet AI, Google Cloud ve IDE'lerde kullanılabilen yapay zeka destekli ortak çalışma aracınızdır. Bu araç sayesinde daha fazla işi daha kısa sürede yapabilirsiniz.

Bu codelab neye odaklanıyor?

Bu codelab, tüm makine öğrenimi ürün ve hizmetlerini kapsayan Google Cloud Vertex AI'de barındırılan PaLM 2 Büyük Dil Modeli'ne (LLM) odaklanmaktadır.

PaLM API ile etkileşim kurmak için Java'yı ve LangChain4J LLM çerçevesi düzenleyicisini kullanacaksınız. Soru yanıtlama, fikir üretme, varlık ve yapılandırılmış içerik ayıklama ve özetleme için LLM'den yararlanmak üzere farklı somut örnekleri inceleyeceksiniz.

LangChain4J çerçevesi hakkında daha fazla bilgi ver.

LangChain4J çerçevesi, büyük dil modellerini Java uygulamalarınıza entegre etmek için kullanılan açık kaynaklı bir kitaplıktır. Bu kitaplık, LLM'nin kendisi gibi çeşitli bileşenlerin yanı sıra vektör veritabanları (semantik aramalar için), belge yükleyiciler ve ayırıcılar (belgeleri analiz etmek ve bunlardan bilgi edinmek için), çıkış ayrıştırıcılar gibi diğer araçları da düzenler.

c6d7f7c3fd0d2951.png

Neler öğreneceksiniz?

  • PaLM ve LangChain4J'yi kullanmak için Java projesi oluşturma
  • Yapılandırılmamış içerikten yararlı bilgileri çıkarma (varlık veya anahtar kelime çıkarma, JSON biçiminde çıktı)
  • Kullanıcılarınızla sohbet oluşturma
  • Kendi dokümanlarınızla ilgili sorular sormak için sohbet modelini kullanma

Gerekenler

  • Java programlama dili hakkında bilgi
  • Google Cloud projesi
  • Chrome veya Firefox gibi bir tarayıcı

2. Kurulum ve şartlar

Yönlendirmesiz ortam kurulumu

  1. Google Cloud Console'da oturum açın ve yeni bir proje oluşturun veya mevcut bir projeyi yeniden kullanın. Gmail veya Google Workspace hesabınız yoksa hesap oluşturmanız gerekir.

295004821bab6a87.png

37d264871000675d.png

96d86d3d5655cdbe.png

  • Proje adı, bu projenin katılımcıları için görünen addır. Google API'leri tarafından kullanılmayan bir karakter dizesidir. Bu bilgiyi istediğiniz zaman güncelleyebilirsiniz.
  • Proje kimliği, tüm Google Cloud projelerinde benzersizdir ve sabittir (ayarlandıktan sonra değiştirilemez). Cloud Console, benzersiz bir dizeyi otomatik olarak oluşturur. Genellikle bu dizenin ne olduğuyla ilgilenmezsiniz. Çoğu codelab'de proje kimliğinize (genellikle PROJECT_ID olarak tanımlanır) başvurmanız gerekir. Oluşturulan kimliği beğenmezseniz başka bir rastgele kimlik oluşturabilirsiniz. Dilerseniz kendi adınızı deneyerek kullanılabilir olup olmadığını kontrol edebilirsiniz. Bu adım tamamlandıktan sonra değiştirilemez ve proje süresince geçerli kalır.
  • Bazı API'lerin kullandığı üçüncü bir değer olan Proje Numarası da vardır. Bu üç değer hakkında daha fazla bilgiyi belgelerde bulabilirsiniz.
  1. Ardından, Cloud kaynaklarını/API'lerini kullanmak için Cloud Console'da faturalandırmayı etkinleştirmeniz gerekir. Bu codelab'i tamamlamak neredeyse hiç maliyetli değildir. Bu eğitimin ötesinde faturalandırılmayı önlemek için kaynakları kapatmak üzere oluşturduğunuz kaynakları veya projeyi silebilirsiniz. Yeni Google Cloud kullanıcıları 300 ABD doları değerinde ücretsiz deneme programından yararlanabilir.

Cloud Shell'i başlatma

Google Cloud, dizüstü bilgisayarınızdan uzaktan çalıştırılabilir ancak bu codelab'de bulutta çalışan bir komut satırı ortamı olan Cloud Shell'i kullanacaksınız.

Cloud Shell'i etkinleştirme

  1. Cloud Console'da Cloud Shell'i etkinleştir 'i d1264ca30785e435.png tıklayın.

cb81e7c8e34bc8d.png

Cloud Shell'i ilk kez başlatıyorsanız ne olduğunu açıklayan bir ara ekran gösterilir. Ara ekran gösterildiyse Devam'ı tıklayın.

d95252b003979716.png

Cloud Shell'in temel hazırlığı ve bağlanması yalnızca birkaç dakikanızı alır.

7833d5e1c5d18f54.png

Bu sanal makineye, ihtiyaç duyacağınız tüm geliştirme araçları yüklenmiştir. 5 GB boyutunda kalıcı bir ana dizin bulunur ve Google Cloud'da çalışır. Bu sayede ağ performansı ve kimlik doğrulama önemli ölçüde güçlenir. Bu codelab'deki çalışmalarınızın neredeyse tamamını tarayıcıyla yapabilirsiniz.

Cloud Shell'e bağlandıktan sonra kimliğinizin doğrulandığını ve projenin, proje kimliğinize ayarlandığını görürsünüz.

  1. Kimliğinizin doğrulandığını onaylamak için Cloud Shell'de şu komutu çalıştırın:
gcloud auth list

Komut çıkışı

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. gcloud komutunun projeniz hakkında bilgi sahibi olduğunu onaylamak için Cloud Shell'de aşağıdaki komutu çalıştırın:
gcloud config list project

Komut çıkışı

[core]
project = <PROJECT_ID>

Değilse şu komutla ayarlayabilirsiniz:

gcloud config set project <PROJECT_ID>

Komut çıkışı

Updated property [core/project].

3. Geliştirme ortamınızı hazırlama

Bu codelab'de, Java programlarınızı geliştirmek için Cloud Shell terminalini ve kod düzenleyiciyi kullanacaksınız.

Vertex AI API'lerini etkinleştirme

  1. Google Cloud Console'da proje adınızın Google Cloud Console'unuzun üst kısmında gösterildiğinden emin olun. Açılmıyorsa Proje seçin'i tıklayarak Proje Seçici'yi açın ve istediğiniz projeyi seçin.
  2. Google Cloud Console'un Vertex AI bölümünde değilseniz aşağıdakileri yapın:
  3. Arama bölümüne Vertex AI yazıp Enter tuşuna basın.
  4. Arama sonuçlarında Vertex AI'ı tıklayın. Vertex AI kontrol paneli görünür.
  5. Vertex AI kontrol panelinde Enable All Recommended APIs'i (Önerilen Tüm API'leri Etkinleştir) tıklayın.

Bu işlemle birkaç API etkinleştirilir. Ancak bu kod laboratuvarı için en önemlisi aiplatform.googleapis.com API'sidir. Bu API'yi komut satırında, Cloud Shell terminalinde aşağıdaki komutu çalıştırarak da etkinleştirebilirsiniz:

$ gcloud services enable aiplatform.googleapis.com

Gradle ile proje yapısını oluşturma

Java kodu örneklerinizi oluşturmak için Gradle derleme aracını ve Java'nın 17. sürümünü kullanacaksınız. Projenizi Gradle ile ayarlamak için Cloud Shell terminalinde bir dizin oluşturun (burada palm-workshop) ve bu dizinde gradle init komutunu çalıştırın:

$ 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

Alt projeleri kullanmadan (1. seçenek), Java dilini (3. seçenek) kullanarak uygulama (2. seçenek) oluşturacak, derleme dosyası için Groovy söz dizimini (1. seçenek) kullanacak, yeni derleme özelliklerini kullanmayacak (seçenek yok), JUnit Jupiter ile testler oluşturacak (4. seçenek) ve proje adı olarak palm-workshop'u, kaynak paketi olarak da palm.workshop'u kullanacaksınız.

Proje yapısı şu şekilde görünür:

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

Gerekli bazı bağımlılıkları eklemek için app/build.gradle dosyasını güncelleyelim. guava bağımlılığını kaldırabilir ve eksik günlükçü mesajlarının gösterilmesini önlemek için LangChain4J projesinin bağımlılıkları ve günlük kaydı kitaplığıyla değiştirebilirsiniz:

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'
}

LangChain4J için 2 bağımlılık vardır:

  • biri temel proje,
  • ve özel Vertex AI modülü için bir tane olmak üzere iki ayrı modül vardır.

Programlarımızı derlemek ve çalıştırmak için Java 17'yi kullanmak üzere aşağıdaki bloğu plugins {} bloğunun altına ekleyin:

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

Yapılacak bir değişiklik daha var: Kullanıcıların derleme aracını çağırırken komut satırında çalıştırılacak ana sınıfı geçersiz kılabilmesi için application app/build.gradle bloğunu güncelleyin:

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

Derleme dosyanızın uygulamanızı çalıştırmaya hazır olup olmadığını kontrol etmek için basit bir Hello World! mesajı yazdıran varsayılan ana sınıfı çalıştırabilirsiniz:

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

> Task :app:run
Hello World!

BUILD SUCCESSFUL in 3s
2 actionable tasks: 2 executed

Artık LangChain4J projesini kullanarak PaLM büyük dil metin modeliyle programlamaya başlayabilirsiniz.

Referans olarak, tam app/build.gradle derleme dosyasının artık nasıl görünmesi gerektiği aşağıda verilmiştir:

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. PaLM'nin sohbet modeline ilk çağrınızı yapma

Proje düzgün şekilde ayarlandığına göre artık PaLM API'yi çağırma zamanı.

app/src/main/java/palm/workshop dizininde (varsayılan App.java sınıfının yanında) ChatPrompts.java adlı yeni bir sınıf oluşturun ve aşağıdaki içeriği yazın:

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);
    }
}

Bu ilk örnekte, görüşmelerin çok turlu yönünü daha kolay yönetmek için VertexAiChatModel sınıfını ve LangChain4J ConversationalChain'yi içe aktarmanız gerekir.

Ardından, main yönteminde, VertexAiChatModel için oluşturucuyu kullanarak sohbet dil modelini yapılandıracak ve şunları belirteceksiniz:

  • uç nokta,
  • gösterir.
  • bölge,
  • yayıncı,
  • ve modelin adı (chat-bison@001).

Dil modeli hazır olduğuna göre ConversationalChain hazırlayabilirsiniz. Bu, LangChain4J tarafından sunulan daha yüksek düzeyde bir soyutlamadır. Sohbet dil modeli gibi bir sohbeti işlemek için farklı bileşenleri birlikte yapılandırmanın yanı sıra sohbetin geçmişini işlemek veya bilgi almak için alıcılar gibi diğer araçları vektör veritabanlarına bağlamak için de kullanılabilir. Ancak endişelenmeyin, bu konuya daha sonra bu codelab'de tekrar değineceğiz.

Ardından, birkaç ilişkili soru sormak için sohbet modeliyle çok adımlı bir görüşme yapacaksınız. Önce LLM'leri merak edersiniz, ardından onlarla neler yapabileceğinizi ve örneklerini sorarsınız. Kendinizi tekrar etmenize gerek kalmadığını fark edin. LLM, bu görüşme bağlamında "onlar "ın LLM'ler anlamına geldiğini biliyor.

Bu çok turlu görüşmeyi yapmak için zincirde execute() yöntemini çağırmanız yeterlidir. Bu yöntem, görüşmenin bağlamına eklenir. Sohbet modeli bir yanıt oluşturur ve bunu sohbet geçmişine de ekler.

Bu sınıfı çalıştırmak için Cloud Shell terminalinde aşağıdaki komutu çalıştırın:

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

Şuna benzer bir çıkış görürsünüz:

$ ./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, ilgili 3 sorunuzu yanıtladı.

VertexAIChatModel oluşturucu, geçersiz kılınabilecek bazı varsayılan değerlere sahip isteğe bağlı parametreler tanımlamanıza olanak tanır. Aşağıda bazı örnekler verilmiştir:

  • .temperature(0.2): Yanıtın ne kadar yaratıcı olmasını istediğinizi tanımlamak için kullanılır (0 değeri, yaratıcılığın düşük olduğu ve genellikle daha gerçekçi yanıtlar için, 1 değeri ise daha yaratıcı yanıtlar için kullanılır).
  • .maxOutputTokens(50) (Örnekte, oluşturulan yanıtın ne kadar uzun olmasını istediğinize bağlı olarak 400 jeton istenmiştir. 3 jeton yaklaşık 4 kelimeye eşittir.)
  • .topK(20): Metin tamamlama için olası kelimeler arasından rastgele bir kelime seçmek üzere kullanılır (1-40 arası).
  • .topP(0.95): Toplam olasılığı bu kayan noktalı sayıya (0 ile 1 arasında) ulaşan olası kelimeleri seçmek için kullanılır.
  • .maxRetries(3): Zaman başına istek kotasını aşıyorsanız modelin aramayı örneğin 3 kez yeniden denemesini sağlayabilirsiniz.

5. Karakter sahibi, faydalı bir chatbot

Önceki bölümde, LLM chatbot'a herhangi bir bağlam vermeden doğrudan soru sormaya başlamıştınız. Ancak bu tür bir chatbot'u belirli bir görevde veya konuda uzmanlaşacak şekilde özelleştirebilirsiniz.

Bunu nasıl yapıyorsunuz? Giriş yaparak: LLM'ye mevcut görevi, bağlamı açıklayarak, yapması gerekenler, hangi karakteri kullanması gerektiği, yanıtları hangi biçimde almak istediğiniz ve chatbot'un belirli bir şekilde davranmasını istiyorsanız üslup hakkında birkaç örnek vererek.

İstem oluşturma ile ilgili bu makalede, bu yaklaşım aşağıdaki grafik ile güzel bir şekilde açıklanmaktadır:

8a4c67679dcbd085.png

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

Bu noktayı açıklamak için prompts.chat web sitesinden ilham alalım. Bu sitede, aşağıdakiler gibi davranmalarını sağlamak için özel olarak tasarlanmış çok sayıda harika ve eğlenceli chatbot fikri listeleniyor:

LLM chatbot'u satranç oyuncusuna dönüştürmeyle ilgili bir örnek: Haydi bunu uygulayalım.

ChatPrompts sınıfını aşağıdaki şekilde güncelleyin:

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);
        }
    }
}

Adım adım inceleyelim:

  • Sohbetin belleğini yönetmek için bazı yeni içe aktarmalar gerekiyor.
  • Satranç üzerine bir tez değil, yalnızca bir sonraki hamleyi oluşturmak istediğimiz için sohbet modelini başlatırsınız ancak maksimum jeton sayısı azdır (burada 7).
  • Ardından, sohbet görüşmelerini kaydetmek için bir sohbet belleği deposu oluşturursunuz.
  • Son hamleleri saklamak için gerçek bir pencereli sohbet hafızası oluşturursunuz.
  • Sohbet belleğine, sohbet modeline kim olması gerektiği (ör. uzman bir satranç oyuncusu) konusunda talimat veren bir "sistem" mesajı eklersiniz. "Sistem" mesajı bağlam eklerken "kullanıcı" ve "yapay zeka" mesajları asıl tartışmayı oluşturur.
  • Belleği ve sohbet modelini birleştiren bir etkileşim zinciri oluşturursunuz.
  • Ardından, beyazın hamlelerinin listesini oluşturup bu liste üzerinde yineleme yaparsınız. Zincir, her seferinde bir sonraki beyaz hamleyle yürütülür ve sohbet modeli, bir sonraki en iyi hamleyle yanıt verir.

Bu sınıfı bu hareketlerle çalıştırdığınızda aşağıdaki çıkışı görmeniz gerekir:

$ ./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 

Vay canına! PaLM satranç oynamayı biliyor mu? Tam olarak değil ancak eğitim sırasında model, bazı satranç oyunu yorumlarını veya hatta geçmiş oyunların PGN (Portable Game Notation) dosyalarını görmüş olmalıdır. Ancak bu chatbot, AlphaZero'ya (en iyi Go, Shogi ve satranç oyuncularını yenen yapay zeka) karşı kazanamayabilir ve sohbet, model oyunun gerçek durumunu tam olarak hatırlamadığı için daha sonra rayından çıkabilir.

Sohbet modelleri çok güçlüdür. Kullanıcılarınızla zengin etkileşimler oluşturabilir ve çeşitli bağlamsal görevleri yerine getirebilir. Bir sonraki bölümde, metinden yapılandırılmış veri ayıklama gibi faydalı bir göreve göz atacağız.

6. Yapılandırılmamış metinlerden bilgi ayıklama

Önceki bölümde, bir kullanıcı ile sohbet dil modeli arasında görüşmeler oluşturmuştunuz. Ancak LangChain4J ile yapılandırılmamış metinlerden yapılandırılmış bilgiler ayıklamak için bir sohbet modeli de kullanabilirsiniz.

Bir kişinin biyografisi veya açıklaması verildiğinde bu kişinin adını ve yaşını çıkarmak istediğinizi varsayalım. Büyük dil modeline, akıllıca düzenlenmiş bir istemle JSON veri yapıları oluşturmasını söyleyebilirsiniz (bu işleme genellikle "istem mühendisliği" denir).

ChatPrompts sınıfını aşağıdaki gibi güncelleyeceksiniz:

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);
    }
}

Bu dosyadaki çeşitli adımlara göz atalım:

  • Bir Person sınıfı, bir kişiyi tanımlayan ayrıntıları (adı ve yaşı) temsil edecek şekilde tanımlanır.
  • PersonExtractor arayüzü, yapılandırılmamış bir metin dizesi verildiğinde oluşturulmuş bir Person örneğini döndüren bir yöntemle oluşturulur.
  • extractPerson(), istemi kendisiyle ilişkilendiren bir @UserMessage ek açıklamasıyla açıklanır. Bu istem, modelin bilgileri ayıklamak için kullanacağı istemdir. Ayrıntılar, sizin için ayrıştırılacak ve Person örneğine dönüştürülecek bir JSON belgesi biçiminde döndürülür.

Şimdi de main() yönteminin içeriğine bakalım:

  • Sohbet modeli oluşturulur.
  • LangChain4J'nin AiServices sınıfı sayesinde bir PersonExtractor nesnesi oluşturulur.
  • Ardından, yapılandırılmamış metinden kişinin ayrıntılarını çıkarmak için Person person = extractor.extractPerson(...)'ı arayabilir ve ad ile yaş bilgilerini içeren bir Person örneği alabilirsiniz.

Şimdi bu sınıfı aşağıdaki komutla çalıştırın:

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

> Task :app:run
Anna
23

Evet! Bu Anna, 23 yaşında.

Bu AiServices yaklaşımında özellikle dikkat çeken nokta, kesin olarak belirlenmiş türlere sahip nesnelerle çalışmanızdır. Doğrudan sohbet LLM'si ile etkileşimde bulunmuyorsunuz. Bunun yerine, çıkarılan kişisel bilgileri temsil etmek için Person sınıfı gibi somut sınıflarla çalışıyorsunuz ve bir Person örneği döndüren bir PersonExtractor sınıfınız var.extractPerson() LLM kavramı soyutlaştırılır ve bir Java geliştiricisi olarak yalnızca normal sınıfları ve nesneleri değiştirirsiniz.

7. Çok Formatlı Veriyle Artırılmış Üretim: Dokümanlarınızla sohbet etme

Görüşmelere geri dönelim. Bu kez dokümanlarınızla ilgili sorular sorabilirsiniz. Dokümanlarınızın alıntılarından oluşan bir veritabanından alakalı bilgileri alabilen bir chatbot oluşturacaksınız. Bu bilgiler, modelin yanıtlarını eğitiminden gelen yanıtlar oluşturmaya çalışmak yerine "temellendirmek" için kullanılacak. Bu kalıba RAG veya Almayla Artırılmış Üretim adı verilir.

Kısaca, Çok Formatlı Veriyle Artırılmış Üretim'de iki aşama vardır:

  1. Alım aşaması: Belgeler yüklenir, daha küçük parçalara bölünür ve bunların vektörel temsili ("vektör yerleştirme") semantik aramalar yapabilen bir "vektör veritabanında" saklanır.

6c5bb5cb2e3b8088.png

  1. Sorgu aşaması: Kullanıcılar artık chatbot'unuza dokümanlarla ilgili sorular sorabilir. Soru da vektöre dönüştürülür ve veritabanındaki diğer tüm vektörlerle karşılaştırılır. En benzer vektörler genellikle anlamsal olarak ilişkilidir ve vektör veritabanı tarafından döndürülür. Ardından, LLM'ye sohbetin bağlamı, veritabanı tarafından döndürülen vektörlere karşılık gelen metin snippet'leri verilir ve bu snippet'lere bakarak yanıtını temellendirmesi istenir.

2c279c506d7606cd.png

Belgelerinizi hazırlama

Bu yeni demoda, Google'ın öncülüğünü yaptığı "transformer" nöral ağ mimarisi hakkında sorular soracaksınız. Bu mimari, günümüzde tüm modern büyük dil modellerinin uygulanma şeklidir.

Bu mimariyi açıklayan araştırma makalesini ("Attention is all you need"), internetten PDF'yi indirmek için wget komutunu kullanarak alabilirsiniz:

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

Sohbet odaklı alma zinciri uygulama

Önce doküman alımı, ardından kullanıcılar dokümanla ilgili sorular sorduğunda sorgu zamanı olmak üzere 2 aşamalı yaklaşımı nasıl oluşturacağımızı adım adım inceleyelim.

Doküman besleme

Belge alımı aşamasının ilk adımı, indirdiğimiz PDF dosyasını bulmak ve okunması için PdfParser hazırlamaktır:

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

Normal sohbet dili modelini oluşturmak yerine, önce bir "gömme" modeli örneği oluşturacaksınız. Bu, metin parçalarının (kelimeler, cümleler veya paragraflar) vektör gösterimlerini oluşturmakla görevli özel bir model ve uç noktadır.

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

Ardından, birlikte çalışmak için birkaç sınıfa ihtiyacınız olacak:

  • PDF belgesini yükleyip parçalara ayırın.
  • Bu parçaların tümü için vektör yerleştirmeleri oluşturun.
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);

Vektör yerleştirmelerini depolamak için bellek içi vektör veritabanı olan InMemoryEmbeddingStore örneği oluşturulur.

Doküman, DocumentSplitters sınıfı sayesinde parçalara ayrılır. PDF dosyasının metnini 500 karakterlik snippet'lere böler. Kelimelerin veya cümlelerin kesilmesini önlemek için 100 karakterlik bir örtüşme (bir sonraki parçayla) olur.

Mağaza "ingestor"u, belge ayırıcıyı, vektörleri hesaplamak için kullanılan gömme modelini ve bellek içi vektör veritabanını birbirine bağlar. Ardından, ingest() yöntemi aktarma işlemini gerçekleştirir.

İlk aşama tamamlandı. Belge, ilişkili vektör yerleştirmeleriyle birlikte metin parçalarına dönüştürüldü ve vektör veritabanında saklandı.

Soru sorma

Soru sormaya hazırlanma zamanı! Görüşmeyi başlatmak için normal sohbet modeli oluşturulabilir:

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

Ayrıca, vektör veritabanını (embeddingStore değişkeninde) ve yerleştirme modelini bağlayacak bir "alıcı" sınıfına da ihtiyacınız olacaktır. Bu işlevin görevi, kullanıcının sorgusu için vektör yerleştirme işlemi yaparak vektör veritabanını sorgulamak ve veritabanında benzer vektörler bulmaktır:

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

Bu noktada, ConversationalRetrievalChain sınıfını örnekleyebilirsiniz (bu, yalnızca Retrieval Augmented Generation kalıbının farklı bir adıdır):

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

Bu "zincir" şunları birbirine bağlar:

  • Daha önce yapılandırdığınız sohbet dili modeli.
  • Alıcı, vektör yerleştirme sorgusunu veritabanındaki vektörlerle karşılaştırır.
  • İstem şablonu, sohbet modelinin yanıtını sağlanan bilgilere (ör. kullanıcının sorusunun vektörüne benzer vektör yerleştirmesi olan dokümanların alakalı alıntıları) dayandırarak vermesi gerektiğini açıkça belirtir.

Artık sorularınızı sormaya hazırsınız.

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

Programı şu şekilde çalıştırın:

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

Çıkışta sorularınızın yanıtlarını görürsünüz:

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.

Tam çözüm

Kopyalama ve yapıştırma işlemlerini kolaylaştırmak için ChatPrompts sınıfının tam içeriğini aşağıda bulabilirsiniz:

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. Tebrikler

Tebrikler! LangChain4J ve PaLM API'yi kullanarak Java'da ilk üretken yapay zeka sohbet uygulamanızı başarıyla oluşturdunuz. Bu süreçte, büyük dil modeli sohbet modellerinin oldukça güçlü olduğunu ve soru/cevap gibi çeşitli görevleri kendi dokümanlarınızda bile yerine getirebildiğini, veri ayıklama işlemini yapabildiğini ve hatta bir ölçüde satranç oynayabildiğini keşfettiniz.

Yapabilecekleriniz

Java'da PaLM ile daha fazlasını yapmak için aşağıdaki codelab'lere göz atın:

Daha fazla bilgi

Referans belgeleri