چت مولد مبتنی بر هوش مصنوعی با کاربران و اسناد در جاوا با PalM و LangChain4J

۱. مقدمه

آخرین به‌روزرسانی: 2024-02-05

هوش مصنوعی مولد چیست؟

هوش مصنوعی مولد یا هوش مصنوعی مولد به استفاده از هوش مصنوعی برای ایجاد محتوای جدید مانند متن، تصاویر، موسیقی، صدا و ویدیو اشاره دارد.

هوش مصنوعی مولد (Generative AI) توسط مدل‌های بنیادی (Foundation Models) (مدل‌های بزرگ هوش مصنوعی) پشتیبانی می‌شود که می‌توانند چندین کار را همزمان انجام دهند و وظایف آماده‌ای از جمله خلاصه‌سازی، پرسش و پاسخ، طبقه‌بندی و موارد دیگر را انجام دهند. به علاوه، با حداقل آموزش مورد نیاز، مدل‌های بنیادی را می‌توان برای موارد استفاده هدفمند با داده‌های نمونه بسیار کم تطبیق داد.

هوش مصنوعی مولد چگونه کار می‌کند؟

هوش مصنوعی مولد با استفاده از یک مدل ML (یادگیری ماشین) برای یادگیری الگوها و روابط موجود در مجموعه داده‌های محتوای ایجاد شده توسط انسان کار می‌کند. سپس از الگوهای آموخته شده برای تولید محتوای جدید استفاده می‌کند.

رایج‌ترین روش برای آموزش یک مدل هوش مصنوعی مولد، استفاده از یادگیری نظارت‌شده است - به این مدل مجموعه‌ای از محتوای ایجاد شده توسط انسان و برچسب‌های مربوطه داده می‌شود. سپس یاد می‌گیرد محتوایی تولید کند که مشابه محتوای ایجاد شده توسط انسان باشد و با همان برچسب‌ها برچسب‌گذاری شود.

کاربردهای رایج هوش مصنوعی مولد چیست؟

هوش مصنوعی مولد، محتوای گسترده‌ای را پردازش می‌کند و از طریق متن، تصاویر و قالب‌های کاربرپسند، بینش‌ها و پاسخ‌هایی ایجاد می‌کند. هوش مصنوعی مولد می‌تواند برای موارد زیر استفاده شود:

  • بهبود تعاملات با مشتری از طریق چت و تجربه جستجوی پیشرفته
  • کاوش حجم عظیمی از داده‌های بدون ساختار از طریق رابط‌های محاوره‌ای و خلاصه‌سازی‌ها
  • کمک به انجام وظایف تکراری مانند پاسخ به درخواست‌های پیشنهاد (RFP)، بومی‌سازی محتوای بازاریابی به پنج زبان و بررسی انطباق قراردادهای مشتری و موارد دیگر

گوگل کلود چه پیشنهاداتی در زمینه هوش مصنوعی مولد ارائه می‌دهد؟

با Vertex AI ، با مدل‌های پایه تعامل داشته باشید، آنها را سفارشی کنید و در برنامه‌های خود جاسازی کنید - به تخصص ML نیاز چندانی ندارید یا اصلاً نیازی به آن ندارید. به مدل‌های پایه در Model Garden دسترسی داشته باشید، مدل‌ها را از طریق یک رابط کاربری ساده در Generative AI Studio تنظیم کنید، یا از مدل‌ها در یک دفترچه یادداشت علوم داده استفاده کنید.

ابزار Vertex AI Search and Conversation سریع‌ترین راه برای ساخت موتورهای جستجو و چت‌بات‌های مبتنی بر هوش مصنوعی را در اختیار توسعه‌دهندگان قرار می‌دهد.

و Duet AI همکار مبتنی بر هوش مصنوعی شماست که در سراسر Google Cloud و IDEها در دسترس است تا به شما کمک کند کارهای بیشتری را سریع‌تر انجام دهید.

این codelab روی چه چیزی تمرکز دارد؟

این آزمایشگاه کد بر مدل زبان بزرگ (LLM) پال‌ام ۲ (PaLM 2) تمرکز دارد که بر روی هوش مصنوعی گوگل کلود ورتکس (Google Cloud Vertex AI) میزبانی می‌شود و شامل تمام محصولات و خدمات یادگیری ماشینی می‌شود.

شما از جاوا برای تعامل با API مربوط به PaLM، به همراه هماهنگ‌کننده‌ی چارچوب LangChain4J LLM، استفاده خواهید کرد. شما با مثال‌های عینی مختلف، از LLM برای پاسخ به سوالات، تولید ایده، استخراج محتوای موجودیت و ساختاریافته و خلاصه‌سازی بهره خواهید برد.

درباره چارچوب LangChain4J بیشتر توضیح دهید!

چارچوب LangChain4J یک کتابخانه متن‌باز برای ادغام مدل‌های زبانی بزرگ در برنامه‌های جاوای شما است که با هماهنگ‌سازی اجزای مختلف، مانند خود LLM، و همچنین ابزارهای دیگری مانند پایگاه‌های داده برداری (برای جستجوهای معنایی)، بارگذاری‌کننده‌ها و تقسیم‌کننده‌های سند (برای تجزیه و تحلیل اسناد و یادگیری از آنها)، تجزیه‌کننده‌های خروجی و موارد دیگر، انجام می‌شود.

c6d7f7c3fd0d2951.png

آنچه یاد خواهید گرفت

  • نحوه راه‌اندازی یک پروژه جاوا برای استفاده از PaLM و LangChain4J
  • نحوه استخراج اطلاعات مفید از محتوای بدون ساختار (استخراج موجودیت یا کلمه کلیدی، خروجی در JSON)
  • چگونه با کاربران خود گفتگو ایجاد کنید
  • نحوه استفاده از مدل چت برای پرسیدن سوال در مورد مستندات خودتان

آنچه نیاز دارید

  • آشنایی با زبان برنامه نویسی جاوا
  • یک پروژه ابری گوگل
  • یک مرورگر، مانند کروم یا فایرفاکس

۲. تنظیمات و الزامات

تنظیم محیط خودتنظیم

  1. وارد کنسول گوگل کلود شوید و یک پروژه جدید ایجاد کنید یا از یک پروژه موجود دوباره استفاده کنید. اگر از قبل حساب جیمیل یا گوگل ورک اسپیس ندارید، باید یکی ایجاد کنید .

۲۹۵۰۰۴۸۲۱bab6a87.png

37d264871000675d.png

۹۶d86d3d5655cdbe.png

  • نام پروژه، نام نمایشی برای شرکت‌کنندگان این پروژه است. این یک رشته کاراکتری است که توسط APIهای گوگل استفاده نمی‌شود. شما همیشه می‌توانید آن را به‌روزرسانی کنید.
  • شناسه پروژه در تمام پروژه‌های گوگل کلود منحصر به فرد است و تغییرناپذیر است (پس از تنظیم، قابل تغییر نیست). کنسول کلود به طور خودکار یک رشته منحصر به فرد تولید می‌کند؛ معمولاً برای شما مهم نیست که چه باشد. در اکثر آزمایشگاه‌های کد، باید شناسه پروژه خود را (که معمولاً با عنوان PROJECT_ID شناخته می‌شود) ارجاع دهید. اگر شناسه تولید شده را دوست ندارید، می‌توانید یک شناسه تصادفی دیگر ایجاد کنید. به عنوان یک جایگزین، می‌توانید شناسه خودتان را امتحان کنید و ببینید که آیا در دسترس است یا خیر. پس از این مرحله قابل تغییر نیست و در طول پروژه باقی می‌ماند.
  • برای اطلاع شما، یک مقدار سوم، شماره پروژه ، وجود دارد که برخی از APIها از آن استفاده می‌کنند. برای کسب اطلاعات بیشتر در مورد هر سه این مقادیر، به مستندات مراجعه کنید.
  1. در مرحله بعد، برای استفاده از منابع/API های ابری، باید پرداخت صورتحساب را در کنسول ابری فعال کنید . اجرای این آزمایشگاه کد هزینه زیادی نخواهد داشت، اگر اصلاً هزینه‌ای داشته باشد. برای خاموش کردن منابع به منظور جلوگیری از پرداخت صورتحساب پس از این آموزش، می‌توانید منابعی را که ایجاد کرده‌اید یا پروژه را حذف کنید. کاربران جدید Google Cloud واجد شرایط برنامه آزمایشی رایگان ۳۰۰ دلاری هستند.

شروع پوسته ابری

اگرچه می‌توان گوگل کلود را از راه دور و از طریق لپ‌تاپ شما مدیریت کرد، اما در این آزمایشگاه کد از Cloud Shell ، یک محیط خط فرمان که در فضای ابری اجرا می‌شود، استفاده خواهید کرد.

فعال کردن پوسته ابری

  1. از کنسول ابری، روی فعال کردن پوسته ابری کلیک کنید d1264ca30785e435.png .

cb81e7c8e34bc8d.png

اگر این اولین باری است که Cloud Shell را اجرا می‌کنید، یک صفحه میانی برای توضیح آن به شما نمایش داده می‌شود. اگر با یک صفحه میانی مواجه شدید، روی ادامه کلیک کنید.

d95252b003979716.png

آماده‌سازی و اتصال به Cloud Shell فقط چند لحظه طول می‌کشد.

7833d5e1c5d18f54.png

این ماشین مجازی مجهز به تمام ابزارهای توسعه مورد نیاز است. این ماشین یک دایرکتوری خانگی پایدار ۵ گیگابایتی ارائه می‌دهد و در فضای ابری گوگل اجرا می‌شود که عملکرد شبکه و احراز هویت را تا حد زیادی افزایش می‌دهد. بخش عمده‌ای از کار شما در این آزمایشگاه کد، اگر نگوییم همه، را می‌توان با یک مرورگر انجام داد.

پس از اتصال به Cloud Shell، باید ببینید که احراز هویت شده‌اید و پروژه روی شناسه پروژه شما تنظیم شده است.

  1. برای تأیید احراز هویت، دستور زیر را در Cloud Shell اجرا کنید:
gcloud auth list

خروجی دستور

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. دستور زیر را در Cloud Shell اجرا کنید تا تأیید کنید که دستور gcloud از پروژه شما اطلاع دارد:
gcloud config list project

خروجی دستور

[core]
project = <PROJECT_ID>

اگر اینطور نیست، می‌توانید با این دستور آن را تنظیم کنید:

gcloud config set project <PROJECT_ID>

خروجی دستور

Updated property [core/project].

۳. آماده‌سازی محیط توسعه

در این آزمایشگاه کد، شما از ترمینال و ویرایشگر کد Cloud Shell برای توسعه برنامه‌های جاوا خود استفاده خواهید کرد.

فعال کردن API های هوش مصنوعی Vertex

  1. در کنسول گوگل کلود، مطمئن شوید که نام پروژه شما در بالای کنسول گوگل کلود نمایش داده می‌شود. اگر اینطور نیست، روی «انتخاب یک پروژه» کلیک کنید تا « انتخابگر پروژه» باز شود و پروژه مورد نظر خود را انتخاب کنید.
  2. اگر در بخش Vertex AI کنسول Google Cloud نیستید، موارد زیر را انجام دهید:
  3. در قسمت جستجو ، عبارت Vertex AI را وارد کنید، سپس عبارت زیر را برگردانید.
  4. در نتایج جستجو، روی Vertex AI کلیک کنید. داشبورد Vertex AI نمایش داده می‌شود.
  5. در داشبورد Vertex AI، روی فعال کردن همه APIهای پیشنهادی کلیک کنید.

این کار چندین API را فعال می‌کند، اما مهم‌ترین آن‌ها برای codelab، aiplatform.googleapis.com است که می‌توانید آن را در خط فرمان، در ترمینال Cloud Shell، با اجرای دستور زیر فعال کنید:

$ gcloud services enable aiplatform.googleapis.com

ایجاد ساختار پروژه با Gradle

برای ساخت نمونه‌های کد جاوا، از ابزار ساخت Gradle و نسخه ۱۷ جاوا استفاده خواهید کرد. برای راه‌اندازی پروژه خود با Gradle، در ترمینال Cloud Shell، یک دایرکتوری (در اینجا، palm-workshop ) ایجاد کنید، دستور gradle init را در آن دایرکتوری اجرا کنید:

$ 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

شما یک برنامه خواهید ساخت (گزینه ۲)، با استفاده از زبان جاوا (گزینه ۳)، بدون استفاده از زیرپروژه‌ها (گزینه ۱)، با استفاده از سینتکس Groovy برای فایل ساخت (گزینه ۱)، از ویژگی‌های ساخت جدید استفاده نکنید (گزینه شماره)، تست‌ها را با JUnit Jupiter تولید کنید (گزینه ۴)، و برای نام پروژه می‌توانید از palm-workshop استفاده کنید، و به طور مشابه برای بسته منبع می‌توانید از palm.workshop استفاده کنید.

ساختار پروژه به شکل زیر خواهد بود:

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

بیایید فایل app/build.gradle را به‌روزرسانی کنیم تا برخی از وابستگی‌های مورد نیاز را اضافه کنیم. می‌توانید در صورت وجود، وابستگی guava را حذف کنید و آن را با وابستگی‌های پروژه LangChain4J و کتابخانه ثبت وقایع جایگزین کنید تا از پیام‌های مزاحم گم شدن logger جلوگیری شود:

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 وجود دارد:

  • یکی روی پروژه اصلی،
  • و یکی برای ماژول اختصاصی Vertex AI.

برای استفاده از جاوا ۱۷ برای کامپایل و اجرای برنامه‌هایمان، بلوک زیر را زیر بلوک plugins {} اضافه کنید:

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

یک تغییر دیگر که باید ایجاد شود: بلوک application app/build.gradle را به‌روزرسانی کنید تا کاربران بتوانند هنگام فراخوانی ابزار ساخت، کلاس اصلی را برای اجرا در خط فرمان بازنویسی کنند:

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

برای بررسی اینکه فایل ساخت شما آماده اجرای برنامه است، می‌توانید کلاس اصلی پیش‌فرض را اجرا کنید که یک پیام ساده Hello World! را چاپ می‌کند:

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

> Task :app:run
Hello World!

BUILD SUCCESSFUL in 3s
2 actionable tasks: 2 executed

اکنون شما آماده‌اید تا با استفاده از پروژه LangChain4J، با مدل متن زبان بزرگ PaLM برنامه‌نویسی کنید!

برای مرجع، فایل کامل ساخت app/build.gradle اکنون باید به این شکل باشد:

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

۴. اولین تماس خود را با مدل چت PaLM برقرار کنید

اکنون که پروژه به درستی راه‌اندازی شده است، زمان آن رسیده است که API مربوط به PaLM را فراخوانی کنیم.

یک کلاس جدید به نام ChatPrompts.java در دایرکتوری app/src/main/java/palm/workshop (در کنار کلاس پیش‌فرض App.java ) ایجاد کنید و محتوای زیر را در آن تایپ کنید:

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

در این مثال اول، باید کلاس VertexAiChatModel و LangChain4J ConversationalChain را وارد کنید تا مدیریت جنبه چند نوبتی مکالمات آسان‌تر شود.

در مرحله بعد، در متد main ، با استفاده از سازنده VertexAiChatModel ، مدل زبان چت را پیکربندی خواهید کرد تا موارد زیر را مشخص کنید:

  • نقطه پایانی،
  • پروژه،
  • منطقه،
  • ناشر،
  • و نام مدل ( chat-bison@001 ).

حالا که مدل زبان آماده است، می‌توانید یک ConversationalChain آماده کنید. این یک انتزاع سطح بالاتر است که توسط LangChain4J ارائه شده است تا اجزای مختلف را برای مدیریت یک مکالمه، مانند خود مدل زبان چت، پیکربندی کند، اما به طور بالقوه اجزای دیگری نیز برای مدیریت تاریخچه مکالمه چت یا اتصال ابزارهای دیگر مانند بازیابی‌کننده‌ها برای دریافت اطلاعات از پایگاه‌های داده برداری وجود دارد. اما نگران نباشید، بعداً در این آزمایشگاه کد به این موضوع باز خواهیم گشت.

سپس، شما قرار است یک مکالمه چند نوبتی با مدل چت ایجاد کنید تا چندین سوال مرتبط با هم بپرسید. ابتدا در مورد LLM ها کنجکاو می‌شوید، سپس می‌پرسید که با آنها چه کاری می‌توانید انجام دهید و چند نمونه از آنها را نام می‌برید. توجه کنید که لازم نیست خودتان را تکرار کنید، LLM می‌داند که منظور از "آنها" در متن آن مکالمه LLM ها هستند.

برای دریافت آن مکالمه چند نوبتی، فقط متد execute() را روی زنجیره فراخوانی می‌کنید، آن را به متن مکالمه اضافه می‌کند، مدل چت یک پاسخ ایجاد می‌کند و آن را به تاریخچه چت نیز اضافه می‌کند.

برای اجرای این کلاس، دستور زیر را در ترمینال Cloud Shell اجرا کنید:

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

شما باید خروجی مشابه این را ببینید:

$ ./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 به 3 سوال مرتبط شما پاسخ داد!

سازنده VertexAIChatModel به شما امکان می‌دهد پارامترهای اختیاری را تعریف کنید که از قبل دارای مقادیر پیش‌فرض هستند و می‌توانید آنها را لغو کنید. در اینجا چند مثال آورده شده است:

  • .temperature(0.2) — برای تعریف میزان خلاقیت مورد نظر شما در پاسخ (0 نشان‌دهنده‌ی خلاقیت کم و اغلب واقع‌گرایانه‌تر است، در حالی که 1 نشان‌دهنده‌ی خروجی‌های خلاقانه‌تر است)
  • .maxOutputTokens(50) ‎ - در این مثال، ۴۰۰ توکن درخواست شده است (۳ توکن تقریباً معادل ۴ کلمه است)، بسته به اینکه می‌خواهید پاسخ تولید شده چقدر طول داشته باشد.
  • .topK(20) ‎ - برای انتخاب تصادفی یک کلمه از بین حداکثر تعداد کلمات احتمالی برای تکمیل متن (از ۱ تا ۴۰)
  • .topP(0.95) ‎ - برای انتخاب کلمات ممکن که مجموع احتمال آنها برابر با آن عدد اعشاری (بین ۰ و ۱) باشد.
  • .maxRetries(3) ‎ - در صورتی که سهمیه درخواست در هر زمان از حد مجاز فراتر رود، می‌توانید مدل را طوری تنظیم کنید که مثلاً فراخوانی را ۳ بار دوباره امتحان کند.

۵. یک چت‌بات مفید با شخصیت!

در بخش قبلی، شما بلافاصله شروع به پرسیدن سوالات از ربات چت LLM کردید، بدون اینکه هیچ زمینه خاصی به آن بدهید. اما می‌توانید چنین ربات چتی را طوری تخصصی کنید که در یک کار خاص یا در یک موضوع خاص متخصص شود.

چگونه این کار را انجام می‌دهید؟ با آماده‌سازی زمینه: با توضیح وظیفه فعلی LLM، زمینه، شاید ارائه چند مثال از آنچه باید انجام دهد، شخصیت مورد نظر، فرمتی که می‌خواهید پاسخ‌ها را دریافت کنید و احتمالاً لحنی که می‌خواهید چت‌بات به شیوه خاصی رفتار کند، می‌توانید این کار را انجام دهید.

این مقاله در مورد ساخت دستورالعمل‌ها، این رویکرد را به خوبی با این تصویر نشان می‌دهد:

8a4c67679dcbd085.png

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

برای روشن شدن این نکته، بیایید از وب‌سایت‌های prompts.chat الهام بگیریم، که ایده‌های عالی و سرگرم‌کننده زیادی از چت‌بات‌های سفارشی‌سازی‌شده را فهرست می‌کند تا به آنها اجازه دهد مانند موارد زیر عمل کنند:

یک مثال برای تبدیل یک چت‌بات LLM به یک بازیکن شطرنج وجود دارد! بیایید آن را پیاده‌سازی کنیم!

کلاس ChatPrompts را به صورت زیر به‌روزرسانی کنید:

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

بیایید آن را گام به گام تجزیه کنیم:

  • برای مدیریت حافظه چت، به برخی ایمپورت‌های جدید نیاز است.
  • شما مدل چت را نمونه‌سازی می‌کنید، اما با تعداد کمی از حداکثر توکن‌ها (در اینجا ۷)، زیرا ما فقط می‌خواهیم حرکت بعدی را تولید کنیم، نه یک پایان‌نامه کامل در مورد شطرنج!
  • در مرحله بعد، یک حافظه چت برای ذخیره مکالمات چت ایجاد می‌کنید.
  • شما یک حافظه پنجره‌ای چت واقعی ایجاد می‌کنید تا آخرین حرکات را حفظ کند.
  • در حافظه چت، یک پیام «سیستم» اضافه می‌کنید که به مدل چت دستور می‌دهد چه کسی قرار است باشد (مثلاً یک بازیکن شطرنج حرفه‌ای). پیام «سیستم» زمینه‌ای را اضافه می‌کند، در حالی که پیام‌های «کاربر» و «هوش مصنوعی» بحث اصلی هستند.
  • شما یک زنجیره مکالمه ایجاد می‌کنید که حافظه و مدل چت را با هم ترکیب می‌کند.
  • سپس، ما لیستی از حرکات برای مهره سفید داریم که شما در حال تکرار آنها هستید. زنجیره هر بار با حرکت بعدی مهره سفید اجرا می‌شود و مدل چت با بهترین حرکت بعدی پاسخ می‌دهد.

وقتی این کلاس را با این حرکات اجرا می‌کنید، باید خروجی زیر را مشاهده کنید:

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

وای! PaLM می‌داند چطور شطرنج بازی کند؟ خب، نه دقیقاً، اما در طول آموزشش، مدل باید برخی از تفاسیر بازی‌های شطرنج یا حتی فایل‌های PGN (نمادگذاری بازی قابل حمل) بازی‌های گذشته را دیده باشد. با این حال، این چت‌بات احتمالاً در مقابل AlphaZero (هوش مصنوعی که بهترین بازیکنان Go، Shogi و Chess را شکست می‌دهد) پیروز نخواهد شد و ممکن است مکالمه در ادامه مسیر از مسیر اصلی خود خارج شود، زیرا مدل واقعاً وضعیت واقعی بازی را به خاطر نمی‌آورد.

مدل‌های چت بسیار قدرتمند هستند و می‌توانند تعاملات غنی با کاربران شما ایجاد کنند و وظایف زمینه‌ای مختلفی را انجام دهند. در بخش بعدی، نگاهی به یک وظیفه مفید خواهیم داشت: استخراج داده‌های ساختاریافته از متن .

۶. استخراج اطلاعات از متن بدون ساختار

در بخش قبلی، شما مکالماتی بین یک کاربر و یک مدل زبان چت ایجاد کردید. اما با LangChain4J، می‌توانید از یک مدل چت برای استخراج اطلاعات ساختاریافته از متن بدون ساختار نیز استفاده کنید.

فرض کنید می‌خواهید نام و سن یک شخص را با توجه به بیوگرافی یا توضیحات آن شخص استخراج کنید. می‌توانید به مدل زبان بزرگ دستور دهید تا ساختارهای داده JSON را با یک اعلان هوشمندانه تنظیم شده تولید کند (این معمولاً "مهندسی اعلان" نامیده می‌شود).

کلاس ChatPrompts را به صورت زیر به‌روزرسانی خواهید کرد:

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

بیایید نگاهی به مراحل مختلف این فایل بیندازیم:

  • کلاس Person برای نمایش جزئیات توصیف یک شخص (نام و سن آن) تعریف شده است.
  • رابط PersonExtractor با متدی ایجاد می‌شود که با دریافت یک رشته متنی بدون ساختار، یک نمونه Person نمونه‌سازی شده را برمی‌گرداند.
  • extractPerson() با حاشیه‌نویسی @UserMessage حاشیه‌نویسی شده است که یک اعلان را به آن مرتبط می‌کند. این اعلانی است که مدل برای استخراج اطلاعات از آن استفاده می‌کند و جزئیات را در قالب یک سند JSON برمی‌گرداند، که برای شما تجزیه و تحلیل می‌شود و در یک نمونه Person دسته‌بندی می‌شود.

حالا بیایید به محتوای متد main() نگاهی بیندازیم:

  • مدل چت نمونه‌سازی می‌شود.
  • یک شیء PersonExtractor به لطف کلاس AiServices از LangChain4J ایجاد می‌شود.
  • سپس، می‌توانید به سادگی Person person = extractor.extractPerson(...) را فراخوانی کنید تا جزئیات شخص را از متن بدون ساختار استخراج کنید و یک نمونه Person با نام و سن دریافت کنید.

حالا با دستور زیر این کلاس را اجرا کنید:

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

> Task :app:run
Anna
23

بله! این آنا است، او ۲۳ ساله است!

نکته جالب توجه در مورد این رویکرد AiServices این است که شما با اشیاء با نوع‌بندی قوی کار می‌کنید. شما مستقیماً با LLM چت تعامل ندارید. در عوض، شما با کلاس‌های واقعی، مانند کلاس Person برای نمایش اطلاعات شخصی استخراج‌شده، کار می‌کنید و یک کلاس PersonExtractor با متد extractPerson() دارید که یک نمونه Person را برمی‌گرداند. مفهوم LLM انتزاعی شده است و شما به عنوان یک توسعه‌دهنده جاوا، فقط کلاس‌ها و اشیاء معمولی را دستکاری می‌کنید.

۷. بازیابی نسل افزوده: چت با اسناد شما

بیایید به مکالمات برگردیم. این بار، شما قادر خواهید بود در مورد اسناد خود سؤال بپرسید. شما یک چت‌بات خواهید ساخت که قادر به بازیابی اطلاعات مرتبط از پایگاه داده‌ای از گزیده‌های اسناد شما است و این اطلاعات توسط مدل برای «مبناگذاری» پاسخ‌هایش استفاده می‌شود، نه اینکه سعی کند پاسخ‌هایی را از آموزش خود تولید کند. این الگو RAG یا Retrieval Augmented Generation نامیده می‌شود.

به طور خلاصه، در بازیابی نسل افزوده، دو مرحله وجود دارد:

  1. مرحله‌ی دریافت - اسناد بارگذاری می‌شوند، به قطعات کوچک‌تر تقسیم می‌شوند و یک نمایش برداری از آن‌ها ( "تعبیه برداری" ) در یک "پایگاه داده برداری" ذخیره می‌شود که قادر به انجام جستجوهای معنایی است.

6c5bb5cb2e3b8088.png

  1. مرحله پرس‌وجو - کاربران اکنون می‌توانند از ربات چت شما در مورد مستندات سوال بپرسند. این سوال نیز به یک بردار تبدیل می‌شود و با سایر بردارهای موجود در پایگاه داده مقایسه می‌شود. بردارهای مشابه معمولاً از نظر معنایی مرتبط هستند و توسط پایگاه داده بردار بازگردانده می‌شوند. سپس، به LLM زمینه مکالمه، قطعات متنی که با بردارهای بازگردانده شده توسط پایگاه داده مطابقت دارند، داده می‌شود و از او خواسته می‌شود تا با نگاه کردن به آن قطعات، پاسخ خود را ارائه دهد.

2c279c506d7606cd.png

آماده‌سازی مدارک شما

برای این نسخه آزمایشی جدید، شما سوالاتی در مورد معماری شبکه عصبی «ترانسفورماتور» که توسط گوگل پیشگام شده است، خواهید پرسید، که امروزه نحوه پیاده‌سازی تمام مدل‌های زبان بزرگ مدرن بر اساس آن است.

شما می‌توانید با استفاده از دستور wget برای دانلود فایل PDF از اینترنت، مقاله تحقیقاتی که این معماری را توصیف کرده است ("توجه، تنها چیزی است که نیاز دارید") را بازیابی کنید:

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

پیاده‌سازی زنجیره بازیابی مکالمه‌ای

بیایید به صورت مرحله به مرحله، نحوه ساخت رویکرد دو مرحله‌ای را بررسی کنیم، ابتدا با دریافت سند، و سپس زمان پرس‌وجو زمانی که کاربران در مورد سند سؤال می‌پرسند.

بلعیدن سند

اولین مرحله از فاز دریافت سند، یافتن فایل PDF مورد نظر برای دانلود و آماده‌سازی یک PdfParser برای خواندن آن است:

PdfDocumentParser pdfParser = new PdfDocumentParser();
Document document = pdfParser.parse(
    new FileInputStream(new File("/home/YOUR_USER_NAME/palm-workshop/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();

در مرحله بعد، به چند کلاس برای همکاری با یکدیگر نیاز دارید تا:

  • سند PDF را بارگیری و به قطعات تقسیم کنید.
  • برای همه این تکه‌ها، جاسازی‌های برداری ایجاد کنید.
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);

یک نمونه از InMemoryEmbeddingStore ، یک پایگاه داده برداری درون حافظه، برای ذخیره جاسازی‌های برداری ایجاد می‌شود.

این سند به لطف کلاس DocumentSplitters به ​​قطعاتی تقسیم شده است. این کلاس متن فایل PDF را به قطعات ۵۰۰ کاراکتری تقسیم می‌کند که ۱۰۰ کاراکتر آن با هم همپوشانی دارند (با قطعه بعدی، برای جلوگیری از بریدن کلمات یا جملات، به صورت تکه تکه).

تابع "ingestor" در حافظه، تقسیم‌کننده سند، مدل جاسازی برای محاسبه بردارها و پایگاه داده بردار درون حافظه را به هم متصل می‌کند. سپس، متد ingest() عملیات ingestion را انجام می‌دهد.

اکنون، مرحله اول به پایان رسیده است، سند به تکه‌های متنی با جاسازی‌های برداری مرتبط با آنها تبدیل شده و در پایگاه داده برداری ذخیره شده است.

پرسیدن سوال

وقت آن است که برای پرسیدن سوال آماده شوید! می‌توانید برای شروع مکالمه، از مدل چت معمول استفاده کنید:

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

همچنین به یک کلاس "retriever" نیاز خواهید داشت که پایگاه داده بردار (در متغیر embeddingStore ) و مدل جاسازی را به هم پیوند دهد. وظیفه آن جستجوی پایگاه داده بردار با محاسبه جاسازی بردار برای جستجوی کاربر است تا بردارهای مشابه را در پایگاه داده پیدا کند:

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

در این مرحله، می‌توانید کلاس ConversationalRetrievalChain نمونه‌سازی کنید (این فقط نام متفاوتی برای الگوی Retrieval Augmented Generation است):

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

برنامه را با دستور زیر اجرا کنید:

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

در خروجی، باید پاسخ سوالات خود را ببینید:

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.

راه حل کامل

برای تسهیل کپی و پیست، محتوای کامل کلاس 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);
    }
}

۸. تبریک

تبریک می‌گویم، شما با موفقیت اولین برنامه چت Generative AI خود را در جاوا با استفاده از LangChain4J و PaLM API ساختید! در طول مسیر متوجه شدید که مدل‌های چت زبان‌های بزرگ بسیار قدرتمند هستند و قادر به انجام وظایف مختلفی مانند پرسش و پاسخ، حتی در مستندات خودتان، استخراج داده‌ها و تا حدی، حتی قادر به بازی شطرنج نیز بودند!

بعدش چی؟

برای آشنایی بیشتر با PaLM در جاوا، به برخی از آزمایشگاه‌های کد زیر نگاهی بیندازید:

مطالعه بیشتر

اسناد مرجع