1. מבוא
העדכון האחרון: 2024-02-05
מהי בינה מלאכותית גנרטיבית
בינה מלאכותית גנרטיבית היא שימוש ב-AI כדי ליצור תוכן חדש, כמו טקסט, תמונות, מוזיקה, אודיו וסרטונים.
ה-AI הגנרטיבי מבוסס על מודלים בסיסיים (מודלים גדולים של AI) שיכולים לבצע כמה משימות בו-זמנית ומשימות מוכנות לשימוש, כולל סיכום, שאלות ותשובות, סיווג ועוד. בנוסף, מודלי בסיס דורשים אימון מינימלי, ולכן אפשר להתאים אותם לתרחישי שימוש ממוקדים עם מעט מאוד נתונים לדוגמה.
איך פועלת בינה מלאכותית גנרטיבית?
בינה מלאכותית גנרטיבית פועלת באמצעות מודל ML (למידת מכונה) כדי ללמוד את הדפוסים והקשרים במערך נתונים של תוכן שנוצר על ידי בני אדם. לאחר מכן היא משתמשת בדפוסים שנלמדו כדי ליצור תוכן חדש.
הדרך הנפוצה ביותר לאמן מודל AI גנרטיבי היא באמצעות למידה מפוקחת – המודל מקבל קבוצה של תוכן שנוצר על ידי בני אדם ותוויות תואמות. לאחר מכן, היא לומדת ליצור תוכן שדומה לתוכן שנוצר על ידי בני אדם וסומן באותן תוויות.
מהם יישומים נפוצים של AI גנרטיבי?
AI גנרטיבי מעבד כמויות גדולות של תוכן, ויוצר תובנות ותשובות באמצעות טקסט, תמונות ופורמטים ידידותיים למשתמש. אפשר להשתמש ב-AI גנרטיבי כדי:
- שיפור האינטראקציות עם הלקוחות באמצעות חוויות משופרות בצ'אט ובחיפוש
- עיון בכמויות גדולות של נתונים לא מובנים באמצעות ממשקי שיחה וסיכומים
- עזרה במשימות חוזרות כמו מענה לבקשות להצעות מחיר (RFP), התאמת תוכן שיווקי לשוק המקומי בחמש שפות, בדיקת חוזים עם לקוחות לצורך עמידה בדרישות ועוד
אילו מוצרים מבוססי-AI גנרטיבי זמינים ב-Google Cloud?
עם Vertex AI, אתם יכולים ליצור אינטראקציה עם מודלים בסיסיים, להתאים אותם אישית ולהטמיע אותם באפליקציות שלכם – בלי צורך בידע רב בלמידת מכונה. אפשר לגשת למודלים בסיסיים ב-Model Garden, לכוונן מודלים באמצעות ממשק משתמש פשוט ב-Generative AI Studio או להשתמש במודלים במחברת של מדעי הנתונים.
חיפוש ושיחות על בסיס Vertex AI מציע למפתחים את הדרך המהירה ביותר ליצור מנועי חיפוש וצ'אטבוטים שמבוססים על AI גנרטיבי.
בנוסף, Duet AI הוא שותף מבוסס-AI שזמין ב-Google Cloud ובסביבות פיתוח משולבות (IDE), ועוזר לכם לבצע יותר משימות מהר יותר.
מה הנושא המרכזי של ה-Codelab הזה?
ה-codelab הזה מתמקד במודל השפה הגדול (LLM) PaLM 2, שמארח ב-Google Cloud Vertex AI את כל מוצרי למידת המכונה והשירותים.
תשתמשו ב-Java כדי ליצור אינטראקציה עם PaLM API, בשילוב עם כלי התזמור של LangChain4J LLM framework. תעברו על דוגמאות קונקרטיות שונות כדי ללמוד איך להשתמש ב-LLM למענה על שאלות, ליצירת רעיונות, לחילוץ ישויות ותוכן מובנה ולסיכום.
אני רוצה עוד פרטים על המסגרת LangChain4J
המסגרת LangChain4J היא ספרייה בקוד פתוח לשילוב מודלים גדולים של שפה באפליקציות Java. היא מאפשרת לתזמן רכיבים שונים, כמו מודל שפה גדול, אבל גם כלים אחרים כמו מסדי נתונים וקטוריים (לחיפושים סמנטיים), טוענים ומפצלים של מסמכים (לניתוח מסמכים ולמידה מהם), מנתחי פלט ועוד.

מה תלמדו
- איך מגדירים פרויקט Java לשימוש ב-PaLM וב-LangChain4J
- איך לחלץ מידע שימושי מתוכן לא מובנה (חילוץ ישויות או מילות מפתח, פלט בפורמט JSON)
- איך יוצרים שיחה עם המשתמשים
- איך משתמשים במודל הצ'אט כדי לשאול שאלות על מסמכים משלכם
מה תצטרכו
- ידע בשפת התכנות Java
- פרויקט ב-Google Cloud
- דפדפן, כמו Chrome או Firefox
2. הגדרה ודרישות
הגדרת סביבה בקצב אישי
- נכנסים ל-מסוף Google Cloud ויוצרים פרויקט חדש או משתמשים בפרויקט קיים. אם עדיין אין לכם חשבון Gmail או Google Workspace, אתם צריכים ליצור חשבון.



- שם הפרויקט הוא השם המוצג של הפרויקט הזה למשתתפים. זו מחרוזת תווים שלא נמצאת בשימוש ב-Google APIs. תמיד אפשר לעדכן את המיקום.
- מזהה הפרויקט הוא ייחודי לכל הפרויקטים ב-Google Cloud ואי אפשר לשנות אותו אחרי שהוא מוגדר. מסוף Cloud יוצר באופן אוטומטי מחרוזת ייחודית, ובדרך כלל לא צריך לדעת מה היא. ברוב ה-Codelabs, תצטרכו להפנות למזהה הפרויקט (בדרך כלל מסומן כ-
PROJECT_ID). אם אתם לא אוהבים את המזהה שנוצר, אתם יכולים ליצור מזהה אקראי אחר. אפשר גם לנסות שם משתמש משלכם ולבדוק אם הוא זמין. אי אפשר לשנות את ההגדרה הזו אחרי השלב הזה, והיא תישאר לאורך הפרויקט. - לידיעתכם, יש ערך שלישי, מספר פרויקט, שחלק מממשקי ה-API משתמשים בו. במאמרי העזרה מפורט מידע נוסף על שלושת הערכים האלה.
- בשלב הבא, תצטרכו להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבי Cloud או בממשקי API של Cloud. השלמת ה-codelab הזה לא תעלה לכם הרבה, אם בכלל. כדי להשבית את המשאבים ולמנוע חיובים נוספים אחרי שתסיימו את המדריך הזה, תוכלו למחוק את המשאבים שיצרתם או למחוק את הפרויקט. משתמשים חדשים ב-Google Cloud זכאים לתוכנית תקופת ניסיון בחינם בשווי 300$.
מפעילים את Cloud Shell
אפשר להפעיל את Google Cloud מרחוק מהמחשב הנייד, אבל ב-codelab הזה תשתמשו ב-Cloud Shell, סביבת שורת פקודה שפועלת בענן.
הפעלת Cloud Shell
- ב-Cloud Console, לוחצים על Activate Cloud Shell
.

אם זו הפעם הראשונה שאתם מפעילים את Cloud Shell, יוצג לכם מסך ביניים עם תיאור של השירות. אם הוצג לכם מסך ביניים, לחצו על המשך.

הקצאת המשאבים והחיבור ל-Cloud Shell נמשכים רק כמה רגעים.

המכונה הווירטואלית הזו כוללת את כל הכלים הדרושים למפתחים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר מאוד את הביצועים והאימות ברשת. אפשר לבצע את רוב העבודה ב-codelab הזה, אם לא את כולה, באמצעות דפדפן.
אחרי שמתחברים ל-Cloud Shell, אמור להופיע אימות ושהפרויקט מוגדר לפי מזהה הפרויקט.
- מריצים את הפקודה הבאה ב-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`
- מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שפקודת gcloud מכירה את הפרויקט:
gcloud config list project
פלט הפקודה
[core] project = <PROJECT_ID>
אם לא, אפשר להגדיר אותו באמצעות הפקודה הבאה:
gcloud config set project <PROJECT_ID>
פלט הפקודה
Updated property [core/project].
3. הכנת סביבת הפיתוח
ב-codelab הזה תשתמשו בטרמינל ובכלי לעריכת קוד של Cloud Shell כדי לפתח את תוכניות ה-Java.
הפעלת ממשקי Vertex AI API
- במסוף Google Cloud, מוודאים ששם הפרויקט מוצג בראש מסוף Google Cloud. אם לא, לוחצים על בחירת פרויקט כדי לפתוח את בורר הפרויקטים, ובוחרים את הפרויקט הרצוי.
- אם אתם לא בחלק של Vertex AI במסוף Google Cloud, מבצעים את הפעולות הבאות:
- בקטע חיפוש, מזינים Vertex AI ולוחצים על Return.
- בתוצאות החיפוש, לוחצים על Vertex AI. לוח הבקרה של Vertex AI מופיע.
- לוחצים על Enable All Recommended APIs (הפעלת כל ממשקי ה-API המומלצים) במרכז הבקרה של Vertex AI.
הפעולה הזו תפעיל כמה ממשקי API, אבל החשוב ביותר מביניהם ל-codelab הוא aiplatform.googleapis.com, שאפשר להפעיל גם בשורת הפקודה, במסוף Cloud Shell, על ידי הפעלת הפקודה הבאה:
$ gcloud services enable aiplatform.googleapis.com
יצירת מבנה הפרויקט באמצעות Gradle
כדי ליצור את דוגמאות הקוד של Java, תשתמשו בכלי הבנייה Gradle ובגרסה 17 של Java. כדי להגדיר את הפרויקט באמצעות Gradle, יוצרים ספרייה (במקרה הזה, palm-workshop) בטרמינל של Cloud Shell ומריצים את הפקודה 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
תבנו אפליקציה (אפשרות 2) באמצעות שפת Java (אפשרות 3), בלי להשתמש בפרויקטים משניים (אפשרות 1), באמצעות תחביר Groovy לקובץ הבנייה (אפשרות 1), בלי להשתמש בתכונות חדשות של בנייה (אפשרות no), יצירת בדיקות באמצעות JUnit Jupiter (אפשרות 4), ובשם הפרויקט אפשר להשתמש ב-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 ובספריית הרישום ביומן כדי להימנע מהודעות חוזרות על חוסר ביומן:
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'
}
יש 2 יחסי תלות ב-LangChain4J:
- אחד בפרויקט הליבה,
- ואחד למודול הייעודי של Vertex AI.
כדי להשתמש ב-Java 17 לצורך קומפילציה והרצה של התוכניות שלנו, מוסיפים את הבלוק הבא מתחת לבלוק plugins {}:
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
צריך לבצע עוד שינוי אחד: לעדכן את הבלוק application של app/build.gradle, כדי לאפשר למשתמשים לעקוף את המחלקה הראשית ולהריץ אותה בשורת הפקודה כשמפעילים את כלי הבנייה:
application {
mainClass = providers.systemProperty('javaMainClass')
.orElse('palm.workshop.App')
}
כדי לוודא שקובץ ה-build מוכן להרצת האפליקציה, אפשר להריץ את מחלקת ברירת המחדל הראשית שמדפיסה הודעה פשוטה Hello World!:
$ ./gradlew run -DjavaMainClass=palm.workshop.App > Task :app:run Hello World! BUILD SUCCESSFUL in 3s 2 actionable tasks: 2 executed
עכשיו אפשר לתכנת באמצעות מודל הטקסט של שפת PaLM, באמצעות פרויקט LangChain4J.
לעיון, כך צריך להיראות עכשיו קובץ ה-build המלא: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()
}
4. ביצוע השיחה הראשונה למודל הצ'אט של PaLM
אחרי שהפרויקט מוגדר בצורה נכונה, הגיע הזמן לקרוא ל-PaLM API.
יוצרים כיתה חדשה בשם 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 כדי להגדיר יחד רכיבים שונים לניהול שיחה, כמו מודל שפה של צ'אט, אבל גם רכיבים אחרים לניהול ההיסטוריה של שיחת הצ'אט, או כדי לחבר כלים אחרים כמו כלי אחזור לחיפוש מידע במסדי נתונים וקטוריים. אל דאגה, נחזור לזה בהמשך ה-codelab.
לאחר מכן, תנהלו שיחה מרובת תפניות עם מודל הצ'אט, כדי לשאול כמה שאלות שקשורות זו לזו. קודם תרצה לדעת מהם מודלי שפה גדולים, אחר כך תרצה לדעת מה אפשר לעשות איתם, ואז תרצה לראות כמה דוגמאות. שימו לב שלא צריך לחזור על עצמכם. המודל הגדול של השפה יודע ש'אותם' מתייחס למודלים גדולים של שפה, בהקשר של השיחה הזו.
כדי להמשיך את השיחה המורכבת הזו, פשוט קוראים למתודה 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)– בדוגמה, נדרשו 400 אסימונים (3 אסימונים שווים בערך ל-4 מילים), בהתאם לאורך התשובה שרוצים ליצור -
.topK(20)– כדי לבחור באופן אקראי מילה מתוך מספר מקסימלי של מילים אפשריות להשלמת הטקסט (מ-1 עד 40) -
.topP(0.95)– כדי לבחור את המילים האפשריות שהסבירות הכוללת שלהן מסתכמת למספר הנקודה הצפה הזה (בין 0 ל-1) -
.maxRetries(3)— אם אתם חורגים מהמכסה של בקשות לשעה, אתם יכולים להגדיר למודל לנסות שוב לבצע את הקריאה 3 פעמים, למשל
5. צ'אטבוט שימושי עם אישיות!
בקטע הקודם, התחלתם לשאול שאלות את צ'אטבוט ה-LLM בלי לתת לו הקשר מסוים. אבל אפשר להתאים אישית צ'אטבוט כזה כדי שיהיה מומחה במשימה מסוימת או בנושא מסוים.
איך עושים את זה? הכנת הבמה: מסבירים ל-LLM מה המשימה, מה ההקשר, אולי נותנים כמה דוגמאות למה שצריך לעשות, איזו אישיות צריכה להיות לו, באיזה פורמט רוצים לקבל תשובות, ואולי גם טון, אם רוצים שצ'אטבוט יתנהג בצורה מסוימת.
במאמר הזה על יצירת הנחיות מוסבר על הגישה הזו באמצעות הגרפיקה הבאה:

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);
}
}
}
הנה פירוט של השלבים:
- כדי לטפל בזיכרון של הצ'אט, צריך לבצע כמה ייבואים חדשים.
- אתם יוצרים מופע של מודל הצ'אט, אבל עם מספר קטן של טוקנים מקסימליים (כאן 7), כי אנחנו רוצים רק ליצור את המהלך הבא, ולא חיבור שלם על שחמט.
- בשלב הבא, יוצרים מאגר זיכרון של הצ'אט כדי לשמור את שיחות הצ'אט.
- אתם יוצרים זיכרון צ'אט בחלון, כדי לשמור את המהלכים האחרונים.
- בזיכרון הצ'אט, מוסיפים הודעת "מערכת" שמנחה את מודל הצ'אט לגבי הזהות שלו (למשל, שחקן שחמט מומחה). ההודעה 'מערכת' מוסיפה קצת הקשר, ואילו ההודעות 'משתמש' ו'AI' הן הדיון עצמו.
- אתם יוצרים שרשרת שיחה שמשלבת את הזיכרון ואת מודל הצ'אט.
- אחר כך יש רשימה של מהלכים ללבן, שאתם חוזרים עליהם שוב ושוב. השרשרת מופעלת עם המהלך הלבן הבא בכל פעם, ומודל הצ'אט משיב עם המהלך הטוב ביותר הבא.
אם מריצים את המחלקה הזו עם המהלכים האלה, אמור להתקבל הפלט הבא:
$ ./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 (Portable Game Notation) של משחקים קודמים. סביר להניח שצ'אטבוט כזה לא ינצח את AlphaZero (ה-AI שמנצח את שחקני הגו, השוגי והשחמט הטובים ביותר), והשיחה עלולה לסטות מהנושא בהמשך, כשהמודל לא באמת זוכר את המצב בפועל של המשחק.
מודלים של צ'אט הם חזקים מאוד, והם יכולים ליצור אינטראקציות עשירות עם המשתמשים ולטפל במשימות שונות בהקשרים שונים. בקטע הבא נראה משימה שימושית: חילוץ נתונים מובְנים מטקסט.
6. חילוץ מידע מטקסט לא מובנה
בקטע הקודם יצרתם שיחות בין משתמש לבין מודל שפה לצ'אט. אבל עם LangChain4J, אפשר גם להשתמש במודל צ'אט כדי לחלץ מידע מובנה מטקסט לא מובנה.
נניח שאתם רוצים לחלץ את השם והגיל של אדם מסוים, מתוך ביוגרפיה או תיאור של אותו אדם. אפשר להנחות את המודל הגדול של השפה (LLM) ליצור מבני נתונים בפורמט 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, שינותח עבורכם ויבוטל ה-marshaling שלו למופעPerson.
עכשיו נסתכל על התוכן של השיטה main():
- מודל הצ'אט מופעל.
- אובייקט
PersonExtractorנוצר באמצעות המחלקהAiServicesשל LangChain4J. - לאחר מכן, תוכלו פשוט להתקשר אל
Person person = extractor.extractPerson(...)כדי לחלץ את פרטי האדם מהטקסט הלא מובנה, ולקבל בחזרה מופע שלPersonעם השם והגיל.
עכשיו מריצים את המחלקה הזו באמצעות הפקודה הבאה:
$ ./gradlew run -DjavaMainClass=palm.workshop.ChatPrompts > Task :app:run Anna 23
כן! קוראים לי אנה, ואני בת 23.
מה שמעניין במיוחד בגישה של AiServices הוא שאתם פועלים עם אובייקטים עם הקלדה חזקה. אתם לא מקיימים אינטראקציה ישירה עם מודל שפה גדול (LLM) של הצ'אט. במקום זאת, אתם עובדים עם מחלקות קונקרטיות, כמו המחלקה Person שמייצגת את המידע האישי שחולץ, ויש לכם מחלקה PersonExtractor עם שיטה extractPerson() שמחזירה מופע של Person. מושג ה-LLM מופשט, ומפתחי Java יכולים לתפעל רק מחלקות ואובייקטים רגילים.
7. Retrieval Augmented Generation: chatting with your docs
בוא נחזור לשיחות. בפעם הזו, תוכלו לשאול שאלות לגבי המסמכים שלכם. תבנו צ'אטבוט שיכול לאחזר מידע רלוונטי ממסד נתונים של תמציות מהמסמכים שלכם, והמידע הזה ישמש את המודל כדי "להצדיק" את התשובות שלו, במקום לנסות ליצור תשובות שמגיעות מהאימון שלו. הדפוס הזה נקרא RAG, או Retrieval Augmented Generation (יצירה משולבת-אחזור).
ב-Retrieval Augmented Generation, בקצרה, יש שני שלבים:
- שלב ההטמעה – המסמכים נטענים, מפצלים אותם לחלקים קטנים יותר, ומאחסנים ייצוג וקטורי שלהם ('הטמעה וקטורית') ב'מסד נתונים וקטורי' שיכול לבצע חיפושים סמנטיים.

- שלב השאילתה – המשתמשים יכולים עכשיו לשאול את הצ'אטבוט שאלות לגבי התיעוד. גם השאלה תומר לווקטור, והיא תושווה לכל הווקטורים האחרים במסד הנתונים. הווקטורים הדומים ביותר קשורים בדרך כלל מבחינה סמנטית, ומוחזרים על ידי מסד הנתונים הווקטורי. לאחר מכן, מודל ה-LLM מקבל את ההקשר של השיחה, את קטעי הטקסט שתואמים לווקטורים שמוחזרים ממסד הנתונים, ומבקשים ממנו לבסס את התשובה שלו על קטעי הטקסט האלה.

הכנת המסמכים
בסרטון ההדגמה החדש הזה, תוכלו לשאול שאלות על ארכיטקטורת הרשת הנוירונית 'טרנספורמר', שפותחה על ידי Google, ועל האופן שבו מיושמים כיום כל מודלי השפה הגדולים המודרניים.
אפשר לאחזר את מאמר המחקר שמתאר את הארכיטקטורה הזו (Attention is all you need) באמצעות הפקודה 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 לקטעים של 500 תווים, עם חפיפה של 100 תווים (עם החלק הבא, כדי להימנע מחיתוך מילים או משפטים, לחתיכות קטנות).
החנות 'ingestor' מקשרת בין מפצל המסמכים, מודל ההטמעה לחישוב הווקטורים ומסד הנתונים הווקטורי בזיכרון. לאחר מכן, הפונקציה ingest() תדאג להעברת הנתונים.
השלב הראשון הסתיים, המסמך עבר טרנספורמציה לחלקים של טקסט עם הטמעות וקטוריות משויכות, והוא נשמר במסד הנתונים הווקטורי.
איך שואלים שאלות
הגיע הזמן להתכונן לשאול שאלות! אפשר ליצור את מודל הצ'אט הרגיל כדי להתחיל את השיחה:
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);
}
}
8. מזל טוב
מזל טוב, הצלחת ליצור את אפליקציית הצ'אט הראשונה שלך מבוססת-AI גנרטיבי ב-Java באמצעות LangChain4J ו-PaLM API! במהלך הדרך גיליתם שמודלים גדולים של שפה (LLM) לצ'אט הם די חזקים ויכולים לבצע משימות שונות כמו מענה על שאלות, אפילו על בסיס התיעוד שלכם, חילוץ נתונים, ובמידה מסוימת, אפילו לשחק שחמט!
מה השלב הבא?
כדי להמשיך ללמוד על PaLM ב-Java, אפשר לעיין ב-Codelabs הבאים:
קריאה נוספת
- תרחישים נפוצים לשימוש ב-AI גנרטיבי
- מקורות מידע להדרכה בנושא AI גנרטיבי
- איך מתקשרים עם PaLM באמצעות Generative AI Studio
- אתיקה של בינה מלאכותית