1. מבוא
עדכון אחרון:5 בפברואר 2024
מהי בינה מלאכותית גנרטיבית
בינה מלאכותית גנרטיבית או בינה מלאכותית (AI) גנרטיבית היא שימוש ב-AI ליצירת תוכן חדש, כמו טקסטים, תמונות, מוזיקה, אודיו וסרטונים.
בינה מלאכותית גנרטיבית מבוססת על מודלים בסיסיים (מודלים גדולים של בינה מלאכותית) שיכולים לבצע כמה משימות בו-זמנית ולבצע משימות שונות, כולל סיכום, שאלות ותשובות, סיווג ועוד. בנוסף, הודות לאימון מינימלי, ניתן להתאים מודלים בסיסיים לתרחישים לדוגמה ממוקדים, עם מעט מאוד נתוני דוגמה.
איך עובדת בינה מלאכותית גנרטיבית?
בינה מלאכותית גנרטיבית משתמשת במודל למידת מכונה (ML) כדי ללמוד את הדפוסים והקשרים במערך נתונים של תוכן שנוצר על ידי בני אדם. לאחר מכן היא משתמשת בדפוסים שנלמדו כדי ליצור תוכן חדש.
הדרך הנפוצה ביותר לאמן מודל של בינה מלאכותית גנרטיבית היא להשתמש בלמידה מונחית – נותנים למודל קבוצה של תוכן שנוצר על ידי בני אדם ותוויות תואמות. לאחר מכן, היא לומדת ליצור תוכן שדומה לתוכן שנוצר על ידי בני אדם ומתויג עם אותן תוויות.
מהן אפליקציות נפוצות של בינה מלאכותית גנרטיבית?
AI גנרטיבי מעבד תוכן נרחב, ויוצר תובנות ותשובות באמצעות טקסטים, תמונות ופורמטים ידידותיים למשתמש. אפשר להשתמש ב-AI גנרטיבי כדי:
- משפרים את האינטראקציה עם הלקוחות בעזרת חוויות משופרות בצ'אט ובחיפוש
- לחקור כמויות עצומות של נתונים לא מובנים באמצעות ממשקים שיחה וסיכומים
- סיוע במשימות שחוזרות על עצמן, כמו מענה לבקשות להצעות (RFP), לוקליזציה של תוכן שיווקי בחמש שפות, ובדיקת חוזים של לקוחות כדי לוודא שהם עומדים בדרישות ועוד.
אילו פתרונות של בינה מלאכותית גנרטיבית יש ל-Google Cloud?
ב-Vertex AI תוכלו לתקשר עם מודלים בסיסיים, להתאים אותם אישית ולהטמיע אותם באפליקציות שלכם – אין צורך במומחיות או במומחיות בכלל בלמידת מכונה. ב-Model Garden אפשר לגשת למודלים בסיסיים, לכוונן מודלים דרך ממשק משתמש פשוט ב-Generative AI Studio או להשתמש במודלים ב-notebook של מדעי נתונים.
חיפוש ושיחות על בסיס Vertex AI הם הדרך המהירה ביותר לפתח מנועי חיפוש וצ'אט בוטים שמבוססים על בינה מלאכותית גנרטיבית.
בנוסף, Duet AI הוא שותף מבוסס-AI, שזמין ב-Google Cloud ובסביבות פיתוח משולבות (IDE) כדי לעזור לך להספיק יותר, מהר יותר.
במה מתמקדים ב-Codelab?
ה-Codelab הזה מתמקד ב-PaLM 2 Large Language Model (LLM), שמתארח ב-Google Cloud Vertex AI, ומקיף את כל המוצרים והשירותים של למידת מכונה.
תשתמשו ב-Java כדי לנהל אינטראקציה עם PaLM API, בשילוב עם LangChain4J framework LLM, מתזמר. תקבלו דוגמאות קונקרטיות שונות כדי לנצל את ה-LLM למענה על שאלות, ליצירת רעיונות, לחילוץ תוכן מובנה ולחילוץ תוכן מובנה.
Tell me more about the LangChain4J framework!
ה-framework של LangChain4J הוא ספריית קוד פתוח לשילוב מודלים גדולים של שפה באפליקציות Java שלכם, על ידי תזמור רכיבים שונים, כמו ה-LLM עצמו, אלא גם כלים אחרים כמו מסדי נתונים וקטוריים (לחיפושים סמנטיים), מטענים ומפצלי מסמכים (כדי לנתח מסמכים וללמוד מהם), לנתחי פלט ועוד.
מה תלמדו
- איך להגדיר פרויקט Java כדי להשתמש ב-PaLM וב-LangChain4J
- איך לחלץ מידע שימושי מתוכן לא מובנה (חילוץ ישות או מילת מפתח, פלט ב-JSON)
- איך יוצרים שיחה עם המשתמשים
- איך להשתמש במודל הצ'אט כדי לשאול שאלות במסמכים שלכם
מה צריך להכין
- ידע בשפת התכנות Java
- פרויקט ב-Google Cloud
- דפדפן, כמו Chrome או Firefox
2. הגדרה ודרישות
הגדרת סביבה בקצב עצמאי
- נכנסים למסוף Google Cloud ויוצרים פרויקט חדש או עושים שימוש חוזר בפרויקט קיים. אם אין לכם עדיין חשבון Gmail או חשבון Google Workspace, עליכם ליצור חשבון.
- Project name הוא השם המוצג של המשתתפים בפרויקט. זו מחרוזת תווים שלא משמשת את Google APIs. תמיד אפשר לעדכן.
- Project ID הוא ייחודי בכל הפרויקטים ב-Google Cloud ואי אפשר לשנות אותו (אי אפשר לשנות אותו אחרי שמגדירים אותו). מסוף Cloud יוצר מחרוזת ייחודית באופן אוטומטי; בדרך כלל לא מעניין אותך מה זה. ברוב ה-codelabs תצטרכו להפנות למזהה הפרויקט שלכם (בדרך כלל מזוהה כ-
PROJECT_ID
). אם המזהה שנוצר לא מוצא חן בעיניכם, אתם יכולים ליצור מזהה אקראי אחר. לחלופין, אפשר לנסות שם משלך ולראות אם הוא זמין. לא ניתן לשנות אותו אחרי השלב הזה, והוא נשאר למשך הפרויקט. - לידיעתך, יש ערך שלישי, Project Number, שבו משתמשים בחלק מממשקי ה-API. מידע נוסף על כל שלושת הערכים האלה זמין במסמכי התיעוד.
- בשלב הבא צריך להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבים או בממשקי API של Cloud. מעבר ב-Codelab הזה לא יעלה הרבה כסף, אם בכלל. כדי להשבית משאבים ולא לצבור חיובים מעבר למדריך הזה, אתם יכולים למחוק את המשאבים שיצרתם או למחוק את הפרויקט. משתמשים חדשים ב-Google Cloud זכאים להשתתף בתוכנית תקופת ניסיון בחינם בשווי 1,200 ש"ח.
הפעלת Cloud Shell
אומנם אפשר להפעיל את Google Cloud מרחוק מהמחשב הנייד, אבל ב-Codelab הזה משתמשים ב-Cloud Shell, סביבת שורת הפקודה שפועלת ב-Cloud.
הפעלת Cloud Shell
- במסוף Cloud, לוחצים על 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.
הפעלת ממשקי API של Vertex AI
- במסוף Google Cloud, מוודאים ששם הפרויקט מוצג בחלק העליון של מסוף Google Cloud. אם לא, לוחצים על Select a project כדי לפתוח את Project Selector ובוחרים את הפרויקט הרצוי.
- אם אתם לא נמצאים בחלק של Vertex AI במסוף Google Cloud, עליכם לבצע את הפעולות הבאות:
- בקטע Search (חיפוש), מזינים Vertex AI, ואז מחזירים
- בתוצאות החיפוש, לוחצים על Vertex AI לוח הבקרה של Vertex AI.
- לוחצים על Enable AllRecommended APIs (הפעלת כל ממשקי ה-API המומלצים) במרכז הבקרה של Vertex AI.
הפעולה הזו תפעיל כמה ממשקי API, אבל המפתח החשוב ביותר ב-Codelab הוא aiplatform.googleapis.com
, ואפשר להפעיל אותו גם בשורת הפקודה בטרמינל של Cloud Shell באמצעות הפקודה הבאה:
$ gcloud services enable aiplatform.googleapis.com
יצירת מבנה הפרויקט באמצעות Gradle
כדי לבנות את הדוגמאות לקוד Java, משתמשים בכלי ה-build של Gradle ובגרסה 17 של Java. כדי להגדיר את הפרויקט באמצעות 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
מפתחים אפליקציה (אפשרות 2), באמצעות שפת Java (אפשרות 3), בלי להשתמש בפרויקטים משניים (אפשרות 1), באמצעות התחביר של Groovy לקובץ ה-build (אפשרות 1), לא להשתמש בתכונות build חדשות (אפשרות לא), ליצור בדיקות באמצעות 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
, כדי שמשתמשים יוכלו לשנות את המחלקה הראשית שתרוץ בשורת הפקודה כשמפעילים את כלי ה-build:
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
, מגדירים את מודל שפת הצ'אט באמצעות ה-builder של VertexAiChatModel
, כדי לציין:
- נקודת הקצה,
- את הפרויקט,
- את האזור,
- את בעל האתר,
- ושם המודל (
chat-bison@001
).
עכשיו, כשמודל השפה מוכן, אפשר להכין ConversationalChain
. זוהי הפשטה ברמה גבוהה יותר של LangChain4J להגדרה של רכיבים שונים לטיפול בשיחה, כמו מודל השפה של הצ'אט עצמו, אבל של רכיבים אחרים שיכולים לטפל בהיסטוריה של שיחת הצ'אט או לחבר כלים אחרים כמו רטריזרים לאחזור מידע ממסדי נתונים וקטוריים. אבל אל דאגה, נחזור לכך בהמשך ב-Codelab הזה.
לאחר מכן, אתם מתכננים לערוך שיחה מרובת תורות עם מודל הצ'אט, כדי לשאול כמה שאלות שקשורות זו לזו. קודם כול אתם תוהים לגבי מודלים מסוג 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 שאלות קשורות!
ה-builder של 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 שיביס את השחקנים הטובים ביותר ב-Go, ב-Shogi וב-Chesses), והשיחה עלולה לרדת בהמשך, והמודל לא ממש יזכור את המצב האמיתי של המשחק.
מודלים של צ'אט הם חזקים מאוד, והם יכולים ליצור אינטראקציות עשירות עם המשתמשים שלכם ולטפל במשימות שונות לפי הקשר. בקטע הבא נבחן משימה שימושית: חילוץ נתונים מובְנים מטקסט.
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
נוצר באמצעות method, שבה גם מחרוזת טקסט לא מובנית מחזירה מופע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
כן! קוראים לי דנה, היא בת 23!
מה שמעניין במיוחד בגישה הזו של AiServices
הוא שאתם פועלים עם אובייקטים מוקלדים מאוד. אין לכם אינטראקציה ישירה עם ה-LLM בצ'אט. במקום זאת, אתם עובדים עם מחלקות קונקרטיות, כמו המחלקה 'אדם' שמייצגת את המידע האישי שחולץ, ויש לכם מחלקה PersonExtractor
עם השיטה extractPerson()
שמחזירה מופע 'אדם'. המושג LLM מופשט, וכמפתח Java, אתה פשוט עושה מניפולציה על מחלקות ואובייקטים רגילים.
7. אחזור יצירה משופרת: צ'אט עם המסמכים שלך
נחזור לשיחות. הפעם תוכלו לשאול שאלות לגבי המסמכים. אנחנו בונים צ'אט בוט שיכול לאחזר מידע רלוונטי ממסד נתונים של חֶלֶצים (extracts) מהמסמכים שלכם, והמידע הזה ישמש את המודל כדי "ground" בתשובות שלו, במקום לנסות ליצור תשובות שמגיעות מהאימון שלו. הדפוס הזה נקרא RAG, או אחזור Augmented Generation.
בקיצור, יש שני שלבים באחזור Augmented Generation:
- שלב הטמעת נתונים — המסמכים נטענים ומפוצלים למקטעים קטנים יותר, וייצוג וקטורי שלהם ("הטמעה וקטורית") מאוחסן ב"מסד נתונים וקטורי" שניתן לבצע בו חיפושים סמנטיים.
- שלב השאילתה – עכשיו המשתמשים יכולים לשאול את הצ'אט בוט שאלות לגבי התיעוד. השאלה תומר גם לווקטור ותשוווה לכל הווקטורים האחרים במסד הנתונים. הווקטורים הדומים ביותר בדרך כלל קשורים סמנטיים, והם מוחזרים על ידי מסד הנתונים הווקטורי. לאחר מכן נותנים ל-LLM את ההקשר של השיחה, את קטעי הטקסט שתואמים לווקטורים שמסד הנתונים מחזיר, ומתבקשים להבין את התשובה שלו על ידי בחינת קטעי הטקסט האלה.
הכנת המסמכים
בהדגמה החדשה הזו נשאל שאלות על ארכיטקטורת רשת הנוירונים ה"טרנספורמר", שנוצרה על ידי Google, שמקדמת את אופן ההטמעה של כל מודלי השפה הגדולים (LLM) בימינו.
אפשר לאחזר את עבודת המחקר שתיאר את הארכיטקטורה הזו ("Attention is all 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")));
במקום ליצור את מודל השפה הרגיל של הצ'אט לפני כן, צריך ליצור מופע של מודל "embedding". יש מודל ונקודת קצה ספציפיים שתפקידם ליצור ייצוגים בווקטור של קטעי טקסט (מילים, משפטים ואפילו פסקאות).
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
(זהו רק שם שונה לדפוס האחזור של מדור קודם):
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) הם די רבי עוצמה ומסוגלים לטפל במשימות שונות כמו שאלות ומענה, אפילו במסמכים שלכם, חילוץ נתונים, ובמידה מסוימת, אפשר אפילו לשחק שחמט!
מה השלב הבא?
עיינו בכמה שיעורי Lab הבאים כדי להתקדם עוד יותר עם PaLM ב-Java:
קריאה נוספת
- תרחישים נפוצים לדוגמה לשימוש ב-AI גנרטיבי
- משאבי הדרכה על בינה מלאכותית גנרטיבית
- אינטראקציה עם PaLM דרך Generative AI Studio
- בינה מלאכותית (AI) אחראית