להצגה ב-ai.google.dev | כדאי לנסות notebook של Colab | הצגת notebook ב-GitHub |
סקירה כללית
מודלים גדולים של שפה (LLMs) יכולים ללמוד יכולות חדשות בלי לאמן אותם ישירות. עם זאת, מודלים גדולים של שפה נקראו כשהם התבקשו לתת תשובות לשאלות שהם לא אומנו. אחת הסיבות לכך היא שמודלים מסוג LLM לא מודעים לאירועים אחרי האימון. בנוסף, קשה מאוד לזהות את המקורות שמהם מודלים מסוג LLM מקבלים את התשובות שלהם. באפליקציות אמינות וניתנות להתאמה, חשוב ש-LLM יענה על בסיס עובדות ויוכל לצטט את מקורות המידע שלו.
שיטה נפוצה שמשמשת כדי להתגבר על המגבלות האלה נקראת Retrieval Augmented Generation (RAG), שמרחיבה את ההנחיה שנשלחת ל-LLM בנתונים רלוונטיים שאוחזרו ממאגר ידע חיצוני באמצעות מנגנון לאחזור מידע (IR). מאגר הידע יכול להיות מאגר משלכם של מסמכים, מסדי נתונים או ממשקי API.
ה-notebook הזה ידריך אתכם בתהליך העבודה לשיפור התשובה של מודל שפה גדול (LLM), על ידי הרחבת הידע שלו בעזרת מאגר טקסט חיצוני ואחזור של מידע סמנטי כדי לענות על שאלות באמצעות הכלי האחזור הסמנטי והשאלה המיוחסת, ממשקי API של תשובות (AQA) ב-Generative Language API.
הגדרה
ייבוא של Generative Language API
# Install the Client library (Semantic Retriever is only supported for versions >0.4.0)
pip install -U google.ai.generativelanguage
אמת
באמצעות ממשק ה-API של האחזור הסמנטי תוכלו לבצע חיפוש סמנטי על הנתונים שלכם. מכיוון שאלו הנתונים שלך, אמצעי בקרת גישה מחמירים יותר ממפתחות API. כדאי לבצע אימות באמצעות OAuth באמצעות חשבונות שירות או באמצעות פרטי הכניסה של המשתמש.
המדריך למתחילים הזה משתמש בגישת אימות פשוטה שמיועדת לסביבת בדיקה, ובדרך כלל קל יותר להתחיל בהגדרה של חשבונות השירות. בסביבת ייצור מומלץ לעיין במידע על אימות והרשאה לפני שבוחרים פרטי כניסה לגישה שמתאימים לאפליקציה.
הגדרת OAuth באמצעות חשבונות שירות
כדי להגדיר OAuth באמצעות חשבונות שירות:
- מפעילים את Generative Language API.
יוצרים את חשבון השירות לפי מסמכי התיעוד.
- אחרי יצירת חשבון השירות, יוצרים מפתח לחשבון השירות.
כדי להעלות את קובץ חשבון השירות, לוחצים על סמל הקובץ בסרגל הצד שמימין ואז על סמל ההעלאה, כמו בצילום המסך שמוצג בהמשך.
- משנים את השם של הקובץ שהועלה ל-
service_account_key.json
או משנים את המשתנהservice_account_file_name
בקוד שלמטה.
- משנים את השם של הקובץ שהועלה ל-
pip install -U google-auth-oauthlib
service_account_file_name = 'service_account_key.json'
from google.oauth2 import service_account
credentials = service_account.Credentials.from_service_account_file(service_account_file_name)
scoped_credentials = credentials.with_scopes(
['https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/generative-language.retriever'])
מפעילים את ספריית הלקוח באמצעות פרטי הכניסה של חשבון השירות.
import google.ai.generativelanguage as glm
generative_service_client = glm.GenerativeServiceClient(credentials=scoped_credentials)
retriever_service_client = glm.RetrieverServiceClient(credentials=scoped_credentials)
permission_service_client = glm.PermissionServiceClient(credentials=scoped_credentials)
יצירת קורפוס
ממשק ה-API של האחזור הסמנטי מאפשר להגדיר עד 5 מאגרי טקסט מותאמים אישית לכל פרויקט. ניתן לציין כל אחד מהשדות הבאים בזמן הגדרת הקורפורה:
name
: שם המשאבCorpus
(מזהה). חייב להכיל עד 40 תווים אלפאנומריים. אם השדהname
ריק בזמן היצירה, המערכת תיצור שם ייחודי באורך מקסימלי של 40 תווים עם קידומת מ-display_name
וסיומת אקראית של 12 תווים.display_name
: השם המוצג שלCorpus
בפורמט קריא לאנשים. חייב להכיל עד 512 תווים, כולל תווים אלפאנומריים, רווחים ומקפים.
example_corpus = glm.Corpus(display_name="Google for Developers Blog")
create_corpus_request = glm.CreateCorpusRequest(corpus=example_corpus)
# Make the request
create_corpus_response = retriever_service_client.create_corpus(create_corpus_request)
# Set the `corpus_resource_name` for subsequent sections.
corpus_resource_name = create_corpus_response.name
print(create_corpus_response)
name: "corpora/google-for-developers-blog-dqrtz8rs0jg" display_name: "Google for Developers Blog" create_time { seconds: 1713497533 nanos: 587977000 } update_time { seconds: 1713497533 nanos: 587977000 }
קבלת הקורפוס שנוצר
משתמשים בשיטה GetCorpusRequest
כדי לגשת באופן פרוגרמטי ל-Corpus
שיצרתם למעלה. הערך של הפרמטר name
מתייחס לשם המשאב המלא של Corpus
, והוא מוגדר בתא שלמעלה כ-corpus_resource_name
. הפורמט הנדרש הוא corpora/corpus-123
.
get_corpus_request = glm.GetCorpusRequest(name=corpus_resource_name)
# Make the request
get_corpus_response = retriever_service_client.get_corpus(get_corpus_request)
# Print the response
print(get_corpus_response)
יצירת מסמך
Corpus
יכול להכיל עד 10,000 Document
. במהלך הגדרת המסמכים, ניתן לציין כל אחד מהשדות הבאים:
name
: שם המשאבDocument
(מזהה). חייב להכיל עד 40 תווים (אלפאנומריים או מקפים בלבד). המזהה לא יכול להתחיל או להסתיים ב- מקף. אם השם ריק ביצירה, נגזר שם ייחודיdisplay_name
עם סיומת אקראית באורך 12 תווים.display_name
: השם המוצג בפורמט קריא לאנשים. חייב להכיל עד 512 תווים, כולל תווים אלפאנומריים, רווחים ומקפים.
רכיבי Document
תומכים גם ב-20 שדות של custom_metadata
שצוינו על ידי המשתמש, המוגדרים כצמדי מפתח-ערך. מטא-נתונים בהתאמה אישית יכולים להיות מחרוזות, רשימות של מחרוזות או מספרים. שימו לב שרשימות של מחרוזות יכולות לתמוך ב-10 ערכים לכל היותר, וערכים מספריים מיוצגים כמספרים בנקודה צפה ב-API.
# Create a document with a custom display name.
example_document = glm.Document(display_name="Introducing Project IDX, An Experiment to Improve Full-stack, Multiplatform App Development")
# Add metadata.
# Metadata also supports numeric values not specified here
document_metadata = [
glm.CustomMetadata(key="url", string_value="https://developers.googleblog.com/2023/08/introducing-project-idx-experiment-to-improve-full-stack-multiplatform-app-development.html")]
example_document.custom_metadata.extend(document_metadata)
# Make the request
# corpus_resource_name is a variable set in the "Create a corpus" section.
create_document_request = glm.CreateDocumentRequest(parent=corpus_resource_name, document=example_document)
create_document_response = retriever_service_client.create_document(create_document_request)
# Set the `document_resource_name` for subsequent sections.
document_resource_name = create_document_response.name
print(create_document_response)
לקבלת המסמך שנוצר
משתמשים בשיטה GetDocumentRequest
כדי לגשת באופן פרוגרמטי למסמך שיצרתם למעלה. הערך של הפרמטר name
מתייחס לשם המלא של המשאב במסמך והוא מוגדר בתא שלמעלה כ-document_resource_name
. הפורמט הנדרש הוא corpora/corpus-123/documents/document-123
.
get_document_request = glm.GetDocumentRequest(name=document_resource_name)
# Make the request
# document_resource_name is a variable set in the "Create a document" section.
get_document_response = retriever_service_client.get_document(get_document_request)
# Print the response
print(get_document_response)
הטמעה ו יצירת מקטע של מסמך
כדי לשפר את הרלוונטיות של תוכן שמוחזר על ידי מסד נתונים וקטורי במהלך אחזור סמנטי, מומלץ לחלק מסמכים גדולים לחלקים או למקטעים קטנים יותר בזמן הטמעת המסמך.
Chunk
הוא תת-חלק של Document
שמתייחס כיחידה עצמאית למטרות ייצוג ואחסון של וקטורים. השדה Chunk
יכול להכיל עד 2,043 אסימונים. Corpus
יכול להיות עד מיליון Chunk
.
בדומה לשדות Document
, השדה Chunks
תומך גם ב-20 שדות של custom_metadata
שצוינו על ידי המשתמש, המוגדרים כצמדי מפתח-ערך. מטא-נתונים בהתאמה אישית יכולים להיות מחרוזות, רשימות של מחרוזות או מספרים. שימו לב שרשימות של מחרוזות יכולות לתמוך ב-10 ערכים לכל היותר, וערכים מספריים מיוצגים כמספרים בנקודה צפה ב-API.
במדריך הזה נעשה שימוש ב-Open Source HtmlChunker של Google.
מקטעי נתונים אחרים שבהם אפשר להשתמש: LangChain או LlamaIndex.
הטמעת נתוני HTML ומקטע נתונים באמצעות HtmlChunker
!pip install google-labs-html-chunker
from google_labs_html_chunker.html_chunker import HtmlChunker
from urllib.request import urlopen
מקבלים את ה-DOM DOM של אתר. כאן, קוד ה-HTML נקרא ישירות,
עדיף לקבל HTML אחרי עיבוד כדי לכלול HTML שהוצב ב-JavaScript.
כמו document.documentElement.innerHTML
.
with(urlopen("https://developers.googleblog.com/2023/08/introducing-project-idx-experiment-to-improve-full-stack-multiplatform-app-development.html")) as f:
html = f.read().decode("utf-8")
צריך לפצל את מסמך הטקסט לפסקאות וליצור Chunk
פסקאות. בשלב הזה יוצרים את האובייקטים Chunk
עצמם, ובקטע הבא הם מעלים אותם אל ה-API של האחזור הסמנטי.
# Chunk the file using HtmlChunker
chunker = HtmlChunker(
max_words_per_aggregate_passage=200,
greedily_aggregate_sibling_nodes=True,
html_tags_to_exclude={"noscript", "script", "style"},
)
passages = chunker.chunk(html)
print(passages)
# Create `Chunk` entities.
chunks = []
for passage in passages:
chunk = glm.Chunk(data={'string_value': passage})
# Optionally, you can add metadata to a chunk
chunk.custom_metadata.append(glm.CustomMetadata(key="tags",
string_list_value=glm.StringList(
values=["Google For Developers", "Project IDX", "Blog", "Announcement"])))
chunk.custom_metadata.append(glm.CustomMetadata(key="chunking_strategy",
string_value="greedily_aggregate_sibling_nodes"))
chunk.custom_metadata.append(glm.CustomMetadata(key = "publish_date",
numeric_value = 20230808))
chunks.append(chunk)
print(chunks)
יצירת מקטעי נתונים
יצירת מקטעים בכמות גדולה. אפשר לציין עד 100 מקטעים לכל בקשה באצווה.
כדי ליצור מקטע יחיד, צריך להשתמש ב-CreateChunk()
.
# Option 1: Use HtmlChunker in the section above.
# `chunks` is the variable set from the section above.
create_chunk_requests = []
for chunk in chunks:
create_chunk_requests.append(glm.CreateChunkRequest(parent=document_resource_name, chunk=chunk))
# Make the request
request = glm.BatchCreateChunksRequest(parent=document_resource_name, requests=create_chunk_requests)
response = retriever_service_client.batch_create_chunks(request)
print(response)
לחלופין, אפשר ליצור מקטעים בלי להשתמש ב-HtmlChunker.
# Add up to 100 CreateChunk requests per batch request.
# document_resource_name is a variable set in the "Create a document" section.
chunks = []
chunk_1 = glm.Chunk(data={'string_value': "Chunks support user specified metadata."})
chunk_1.custom_metadata.append(glm.CustomMetadata(key="section",
string_value="Custom metadata filters"))
chunk_2 = glm.Chunk(data={'string_value': "The maximum number of metadata supported is 20"})
chunk_2.custom_metadata.append(glm.CustomMetadata(key = "num_keys",
numeric_value = 20))
chunks = [chunk_1, chunk_2]
create_chunk_requests = []
for chunk in chunks:
create_chunk_requests.append(glm.CreateChunkRequest(parent=document_resource_name, chunk=chunk))
# Make the request
request = glm.BatchCreateChunksRequest(parent=document_resource_name, requests=create_chunk_requests)
response = retriever_service_client.batch_create_chunks(request)
print(response)
הצגת רשימה של Chunk
וקבלת מצב
אפשר להשתמש בשיטה ListChunksRequest
כדי לקבל את כל הפריטים מסוג 'Chunk
' כרשימה בחלוקה לדפים, עם מגבלת גודל של 100 שניות Chunk
בכל דף, שממוינים בסדר עולה לפי Chunk.create_time
. אם לא מציינים מגבלה, מוחזרים עד 10 יחידות מסוג Chunk
.
צריך לספק את ה-next_page_token
שהוחזר בתשובה של ListChunksRequest
כארגומנט לבקשה הבאה כדי לאחזר את הדף הבא. חשוב לשים לב שכאשר החלוקה לדפים, כל שאר הפרמטרים שסופקו ל-ListChunks
חייבים להתאים לקריאה שסיפקה את אסימון הדף.
כל הערכים של 'Chunk
' מחזירים state
. אפשר להשתמש במדד הזה כדי לבדוק את המצב של Chunks
לפני שליחת שאילתה על Corpus
. המצבים של Chunk
כוללים את – UNSPECIFIED
, PENDING_PROCESSING
, ACTIVE
ו-FAILED
. אפשר להריץ רק שאילתה על ACTIVE
Chunk
.
# Make the request
request = glm.ListChunksRequest(parent=document_resource_name)
list_chunks_response = retriever_service_client.list_chunks(request)
for index, chunks in enumerate(list_chunks_response.chunks):
print(f'\nChunk # {index + 1}')
print(f'Resource Name: {chunks.name}')
# Only ACTIVE chunks can be queried.
print(f'State: {glm.Chunk.State(chunks.state).name}')
להטמיע מסמך אחר
צריך להוסיף עוד Document
דרך HtmlChunker ולהוסיף פילטרים.
# Create a document with a custom display name.
example_document = glm.Document(display_name="How it’s Made: Interacting with Gemini through multimodal prompting")
# Add document metadata.
# Metadata also supports numeric values not specified here
document_metadata = [
glm.CustomMetadata(key="url", string_value="https://developers.googleblog.com/2023/12/how-its-made-gemini-multimodal-prompting.html")]
example_document.custom_metadata.extend(document_metadata)
# Make the CreateDocument request
# corpus_resource_name is a variable set in the "Create a corpus" section.
create_document_request = glm.CreateDocumentRequest(parent=corpus_resource_name, document=example_document)
create_document_response = retriever_service_client.create_document(create_document_request)
# Set the `document_resource_name` for subsequent sections.
document_resource_name = create_document_response.name
print(create_document_response)
# Chunks - add another webpage from Google for Developers
with(urlopen("https://developers.googleblog.com/2023/12/how-its-made-gemini-multimodal-prompting.html")) as f:
html = f.read().decode("utf-8")
# Chunk the file using HtmlChunker
chunker = HtmlChunker(
max_words_per_aggregate_passage=100,
greedily_aggregate_sibling_nodes=False,
)
passages = chunker.chunk(html)
# Create `Chunk` entities.
chunks = []
for passage in passages:
chunk = glm.Chunk(data={'string_value': passage})
chunk.custom_metadata.append(glm.CustomMetadata(key="tags",
string_list_value=glm.StringList(
values=["Google For Developers", "Gemini API", "Blog", "Announcement"])))
chunk.custom_metadata.append(glm.CustomMetadata(key="chunking_strategy",
string_value="no_aggregate_sibling_nodes"))
chunk.custom_metadata.append(glm.CustomMetadata(key = "publish_date",
numeric_value = 20231206))
chunks.append(chunk)
# Make the request
create_chunk_requests = []
for chunk in chunks:
create_chunk_requests.append(glm.CreateChunkRequest(parent=document_resource_name, chunk=chunk))
request = glm.BatchCreateChunksRequest(parent=document_resource_name, requests=create_chunk_requests)
response = retriever_service_client.batch_create_chunks(request)
print(response)
שליחת שאילתה לקורפוס
אפשר להשתמש בשיטה QueryCorpusRequest
כדי לבצע חיפוש סמנטי כדי לקבל פסקאות רלוונטיות.
results_count
: ציון מספר הפסקאות שצריך להחזיר. המקסימום הוא 100. אם לא צוין אחרת, ה-API יחזיר עד 10 שניותChunk
.metadata_filters
: סינון לפיchunk_metadata
אוdocument_metadata
. כלMetadataFilter
צריך להתאים למפתח ייחודי. אם יש כמה אובייקטים מסוגMetadataFilter
שמחוברים אליהם באמצעות תוויAND
לוגיים. תנאים דומים לסינון מטא-נתונים מצורפים באמצעות תוויOR
לוגיים. מספר דוגמאות:
(year >= 2020 OR year < 2010) AND (genre = drama OR genre = action)
metadata_filter = [
{
key = "document.custom_metadata.year"
conditions = [
{int_value = 2020, operation = GREATER_EQUAL},
{int_value = 2010, operation = LESS}]
},
{
key = "document.custom_metadata.genre"
conditions = [
{string_value = "drama", operation = EQUAL},
{string_value = "action", operation = EQUAL} }]
}]
הערה: רק ערכים מספריים תומכים בסימן 'AND' עבור אותו מפתח. מחרוזת (String) תומכים רק בערכי 'OR' עבור אותו מפתח.
("Google for Developers" in tags) and (20230314 > publish_date)
metadata_filter = [
{
key = "chunk.custom_metadata.tags"
conditions = [
{string_value = 'Google for Developers', operation = INCLUDES},
},
{
key = "chunk.custom_metadata.publish_date"
conditions = [
{numeric_value = 20230314, operation = GREATER_EQUAL}]
}]
user_query = "What is the purpose of Project IDX?"
results_count = 5
# Add metadata filters for both chunk and document.
chunk_metadata_filter = glm.MetadataFilter(key='chunk.custom_metadata.tags',
conditions=[glm.Condition(
string_value='Google For Developers',
operation=glm.Condition.Operator.INCLUDES)])
# Make the request
# corpus_resource_name is a variable set in the "Create a corpus" section.
request = glm.QueryCorpusRequest(name=corpus_resource_name,
query=user_query,
results_count=results_count,
metadata_filters=[chunk_metadata_filter])
query_corpus_response = retriever_service_client.query_corpus(request)
print(query_corpus_response)
מענה על שאלות משויכות
משתמשים בשיטה GenerateAnswer
כדי לבצע מענה לשאלות משויכות במסמך, במאגר הנתונים או בקבוצת פסקאות.
שיוך (AQA) למענה על שאלות(AQA) מתייחס למענה על שאלות שמתבססות על הקשר נתון ולמתן קרדיטים, תוך צמצום ההזות.
ל-GenerateAnswer
יש כמה יתרונות על פני שימוש ב-LLM לא מכוונן, במקרים שבהם רוצים לבצע בקרת איכות:
- המודל הבסיסי אומן להחזיר רק תשובות שמתבססות על ההקשר שסופק.
- היא מציינת את הייחוסים (קטעים מההקשר שסופק). ייחוס מאפשר למשתמש לאמת את התשובה.
- היא מבצעת הערכה של
answerable_probability
עבור צמד נתון (שאלה, הקשר), וכך מאפשרת לכם להפנות את התנהגות המוצר בהתאם הסבירות שהתשובה שמוחזרת תהיה מבוססת ונכונה.
answerable_probability
והבעיה 'אין לי מושג'
במקרים מסוימים, התשובה הטובה ביותר לשאלה היא למעשה "אין לי מושג". לדוגמה, אם ההקשר שצוין לא מכיל תשובה לשאלה, השאלה תיחשב כ'לא ניתנת לתשובה'.
למודל ה-AQA, יש מיומנות גבוהה בזיהוי מקרים כאלה. הוא יכול אפילו להבחין בין דרגות של עונים על בעיות ואי-יכולת לענות עליהן.
עם זאת, בזכות ה-API של GenerateAnswer
, כוח קבלת ההחלטות הסופי נמצא בידיים שלך:
- תמיד ניסיון להחזיר תשובה בסיסית – גם אם סביר יחסית שהתשובה הזו מבוססת על תשובה נכונה ונכונה.
- החזרת ערך
answerable_probability
– האומדן של המודל להסתברות, שהתשובה מבוססת על ביסוס ונכונה.
ערך נמוך של answerable_probability
עשוי לנבוע מאחד או יותר מהגורמים הבאים:
- המודל לא בטוח שהתשובה שלו נכונה.
- המודל לא בטוח שהתשובה שלו מבוססת על הפסקאות המצוטטות. ייתכן שהתשובה נגזרת מידע בעולם. לדוגמה:
question="1+1=?", passages=["2+2=4”]
←answer=2, answerable_probability=0.02
- המודל סיפק מידע רלוונטי שלא נתן תשובה מלאה לשאלה. דוגמה:
question="Is it available in my size?, passages=["Available in sizes 5-11"]
←answer="Yes it is available in sizes 5-11", answerable_probability=0.03"
- לא התקבלה שאלה בפורמט תקין ב-GenerateAnswerRequest.
מכיוון שערך answerable_probability
נמוך מצביע על כך שסביר להניח שה-GenerateAnswerResponse.answer שגוי או שאין בו יסוד כלשהו, מומלץ מאוד לעבד את התשובה על ידי בדיקה של answerable_probability
.
כאשר הערך של answerable_probability
נמוך, ייתכן שלקוחות מסוימים ירצו:
- הצגת הודעה עם הכיתוב 'לא ניתן לענות על השאלה הזו' למשתמש הקצה.
- נחזור ל-LLM לשימוש כללי שיענה על השאלה מתוך הידע העולמי. הסף והאופי של חלופות כאלה תלויים בתרחישים שונים לדוגמה. ערך של
answerable_probability
<= 0.5 הוא סף התחלה טוב.
טיפים מועילים בנושא AQA
המפרטים המלאים של ה-API זמינים בחומר העזר בנושא API של GenerateAnswerRequest
.
- אורך המעבר: מומלץ להשתמש ב-300 אסימונים לכל פסקה.
- מיון המעבר:
- אם מציינים
GenerateAnswerRequest.inline_passages
, צריך למיין את הפסקאות בסדר יורד לפי הרלוונטיות שלהן לשאילתה. אם המודל חורג ממגבלת אורך ההקשר, הפסקאות האחרונות (הכי פחות רלוונטיות) יושמטו. - אם תוסיפו
GenerateAnswerRequest.semantic_retriever
, המיון של הרלוונטיות יתבצע עבורכם באופן אוטומטי.
- אם מציינים
- מגבלות: מודל ה-AQA מתמחה במענה לשאלות. עבור תרחישים אחרים לדוגמה כמו כתיבה יצירתית, סיכום וכו', יש להפעיל מודל לשימוש כללי באמצעות GenerateContent.
- Chat: אם ידוע שהקלט של המשתמש הוא שאלה שעשויה להיות תשובה מהקשר מסוים, AQA יכול לענות על שאילתות צ'אט. עם זאת, אם קלט של משתמשים הוא סוג כלשהו של ערך, עדיף להשתמש במודל לשימוש כללי.
- טמפרטורה:
- באופן כללי, מומלץ להשתמש בטמפרטורה נמוכה יחסית (כ-0.2) כדי ליצור בקרת איכות מדויקת.
- אם התרחיש לדוגמה שלכם מסתמך על פלט דטרמיניסטי, מגדירים את הטמפרטורה=0.
user_query = "What is the purpose of Project IDX?"
answer_style = "ABSTRACTIVE" # Or VERBOSE, EXTRACTIVE
MODEL_NAME = "models/aqa"
# Make the request
# corpus_resource_name is a variable set in the "Create a corpus" section.
content = glm.Content(parts=[glm.Part(text=user_query)])
retriever_config = glm.SemanticRetrieverConfig(source=corpus_resource_name, query=content)
req = glm.GenerateAnswerRequest(model=MODEL_NAME,
contents=[content],
semantic_retriever=retriever_config,
answer_style=answer_style)
aqa_response = generative_service_client.generate_answer(req)
print(aqa_response)
# Get the metadata from the first attributed passages for the source
chunk_resource_name = aqa_response.answer.grounding_attributions[0].source_id.semantic_retriever_chunk.chunk
get_chunk_response = retriever_service_client.get_chunk(name=chunk_resource_name)
print(get_chunk_response)
אפשרויות נוספות: AQA (בקרת איכות) באמצעות מעברים מוטבעים
לחלופין, אפשר להשתמש ישירות בנקודת הקצה AQA, בלי להשתמש ב-Semant Retriever API על ידי העברת inline_passages
.
user_query = "What is AQA from Google?"
user_query_content = glm.Content(parts=[glm.Part(text=user_query)])
answer_style = "VERBOSE" # or ABSTRACTIVE, EXTRACTIVE
MODEL_NAME = "models/aqa"
# Create the grounding inline passages
grounding_passages = glm.GroundingPassages()
passage_a = glm.Content(parts=[glm.Part(text="Attributed Question and Answering (AQA) refers to answering questions grounded to a given corpus and providing citation")])
grounding_passages.passages.append(glm.GroundingPassage(content=passage_a, id="001"))
passage_b = glm.Content(parts=[glm.Part(text="An LLM is not designed to generate content grounded in a set of passages. Although instructing an LLM to answer questions only based on a set of passages reduces hallucination, hallucination still often occurs when LLMs generate responses unsupported by facts provided by passages")])
grounding_passages.passages.append(glm.GroundingPassage(content=passage_b, id="002"))
passage_c = glm.Content(parts=[glm.Part(text="Hallucination is one of the biggest problems in Large Language Models (LLM) development. Large Language Models (LLMs) could produce responses that are fictitious and incorrect, which significantly impacts the usefulness and trustworthiness of applications built with language models.")])
grounding_passages.passages.append(glm.GroundingPassage(content=passage_c, id="003"))
# Create the request
req = glm.GenerateAnswerRequest(model=MODEL_NAME,
contents=[user_query_content],
inline_passages=grounding_passages,
answer_style=answer_style)
aqa_response = generative_service_client.generate_answer(req)
print(aqa_response)
שיתוף הקורפוס
אפשר לשתף את הקורפוס עם אחרים באמצעות API של CreatePermissionRequest
.
מגבלות:
- יש 2 תפקידים שאפשר לשתף:
READER
ו-EDITOR
.READER
יכול לשלוח שאילתה לקורפוס.- ל-
WRITER
יש הרשאות קורא וגם אפשרות לערוך ולשתף את התוכן.
- אוסף יכול להיות ציבורי על ידי הענקת גישה ל-
EVERYONE
כ-user_type
גישת קריאה.
# Replace your-email@gmail.com with the email added as a test user in the OAuth Quickstart
shared_user_email = "TODO-your-email@gmail.com" # @param {type:"string"}
user_type = "USER"
role = "READER"
# Make the request
# corpus_resource_name is a variable set in the "Create a corpus" section.
request = glm.CreatePermissionRequest(
parent=corpus_resource_name,
permission=glm.Permission(grantee_type=user_type,
email_address=shared_user_email,
role=role))
create_permission_response = permission_service_client.create_permission(request)
print(create_permission_response)
מחיקת הקורפוס
שימוש ב-DeleteCorpusRequest
כדי למחוק קורפוס של משתמשים ואת כל קובצי ה-Document
המשויכים וגם Chunk
s.
חשוב לשים לב שאוסף שאינו ריק יקפיץ שגיאה בלי לציין דגל force=True
. אם מגדירים את force=True
, כל האובייקטים מסוג Chunk
והאובייקטים שקשורים לDocument
הזה יימחקו גם הם.
אם force=False
(ברירת המחדל) ו-Document
מכילים פונקציות Chunk
כלשהן, תוחזר שגיאה מסוג FAILED_PRECONDITION
.
# Set force to False if you don't want to delete non-empty corpora.
req = glm.DeleteCorpusRequest(name=corpus_resource_name, force=True)
delete_corpus_response = retriever_service_client.delete_corpus(req)
print("Successfully deleted corpus: " + corpus_resource_name)
סיכום וקריאה נוספת
במדריך הזה הצגנו את השאלה הסמנטית ואת השאלה המיוחסת, תשובות בממשקי API של Generative Language API והראו איך אפשר להשתמש בהם כדי לבצע אחזור סמנטי של הנתונים מהטקסט המותאם אישית. שימו לב שה-API הזה פועל גם עם מסגרת הנתונים LlamaIndex. מידע נוסף זמין במדריך.
מידע נוסף על הפונקציות הזמינות האחרות זמין גם במסמכי ה-API.
נספח: הגדרת OAuth עם פרטי כניסה של משתמשים
כדי להגדיר אימות OAuth, יש לבצע את השלבים הבאים מהמדריך למתחילים של OAuth.
מתן הרשאה לפרטי כניסה של אפליקציה למחשב. כדי להריץ את ה-notebook הזה ב-Colab, צריך קודם לשנות את השם של קובץ פרטי הכניסה (בדרך כלל
client_secret_*.json
) ל-client_secret.json
בלבד. לאחר מכן מעלים את הקובץ באמצעות סמל הקובץ בסרגל הצד שמימין, ואז על סמל ההעלאה, כפי שמוצג בצילום המסך למטה.
# Replace TODO-your-project-name with the project used in the OAuth Quickstart
project_name = "TODO-your-project-name" # @param {type:"string"}
# Replace TODO-your-email@gmail.com with the email added as a test user in the OAuth Quickstart
email = "TODO-your-email@gmail.com" # @param {type:"string"}
# Rename the uploaded file to `client_secret.json` OR
# Change the variable `client_file_name` in the code below.
client_file_name = "client_secret.json"
# IMPORTANT: Follow the instructions from the output - you must copy the command
# to your terminal and copy the output after authentication back here.
!gcloud config set project $project_name
!gcloud config set account $email
# NOTE: The simplified project setup in this tutorial triggers a "Google hasn't verified this app." dialog.
# This is normal, click "Advanced" -> "Go to [app name] (unsafe)"
!gcloud auth application-default login --no-browser --client-id-file=$client_file_name --scopes="https://www.googleapis.com/auth/generative-language.retriever,https://www.googleapis.com/auth/cloud-platform"
לאתחל את ספריית הלקוח ולהריץ מחדש את ה-notebook החל מיצירת קורפוס.
import google.ai.generativelanguage as glm
generative_service_client = glm.GenerativeServiceClient()
retriever_service_client = glm.RetrieverServiceClient()
permission_service_client = glm.PermissionServiceClient()