ดูใน ai.google.dev | ลองใช้ Colab Notebook | ดูสมุดบันทึกใน GitHub |
ภาพรวม
โมเดลภาษาขนาดใหญ่ (LLM) สามารถเรียนรู้ความสามารถใหม่ๆ ได้โดยไม่ต้องได้รับการฝึกฝนโดยตรง อย่างไรก็ตาม LLM เป็นที่รู้กันว่า "ความไม่สมเหตุสมผล" เมื่อได้รับมอบหมายให้ตอบคำถามที่ไม่ได้รับการฝึก ส่วนหนึ่งเป็นเพราะ LLM ไม่รู้เหตุการณ์หลังจากการฝึก นอกจากนี้ การติดตามแหล่งที่มาของคำตอบที่ LLM ดึงมายังเป็นเรื่องยากมาก สําหรับแอปพลิเคชันที่เชื่อถือได้และปรับขนาดได้ LLM จะต้องให้คําตอบที่อิงตามข้อเท็จจริงและสามารถอ้างอิงแหล่งข้อมูลได้
แนวทางทั่วไปที่ใช้เพื่อเอาชนะข้อจำกัดเหล่านี้เรียกว่า Retrieval Augmented Generation (RAG) ซึ่งจะเพิ่มพรอมต์ที่ส่งไปยัง LLM ด้วยข้อมูลที่เกี่ยวข้องซึ่งดึงมาจากฐานความรู้ภายนอกผ่านกลไกการดึงข้อมูล (IR) ฐานความรู้อาจเป็นคลังเอกสาร ฐานข้อมูล หรือ API ของคุณเอง
สมุดบันทึกนี้จะแนะนำเวิร์กโฟลว์ในการปรับปรุงคำตอบของ LLM ด้วยการเพิ่มความรู้ด้วยคลังข้อความภายนอก และการดึงข้อมูลเชิงความหมายเพื่อตอบคำถามโดยใช้ Semantic Retriever และ Attributed Question & Answering (AQA) API ของ 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
ตรวจสอบสิทธิ์
Semantic Retriever 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)
สร้างคลังข้อความ
Semantic Retriever 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
มี Document
ได้สูงสุด 10,000 รายการ คุณสามารถระบุฟิลด์ใดฟิลด์หนึ่งต่อไปนี้ขณะกำหนดเอกสารได้
name
: ชื่อทรัพยากรDocument
(รหัส) ต้องมีอักขระไม่เกิน 40 ตัว (ตัวอักษรและตัวเลขหรือเครื่องหมายขีดกลางเท่านั้น) รหัสต้องไม่ขึ้นต้นหรือลงท้ายด้วยขีดกลาง หากชื่อว่างเปล่าเมื่อสร้าง ระบบจะสร้างชื่อที่ไม่ซ้ำจากdisplay_name
พร้อมกับคำต่อแบบสุ่ม 12 อักขระdisplay_name
: ชื่อที่แสดงที่มนุษย์อ่านได้ ต้องมีอักขระไม่เกิน 512 ตัว ซึ่งรวมถึงตัวอักษรและตัวเลข การเว้นวรรค และเครื่องหมายขีดกลาง
Document
ยังรองรับช่อง custom_metadata
ที่ผู้ใช้ระบุได้สูงสุด 20 ช่อง ซึ่งระบุเป็นคู่คีย์-ค่า โดยอาจเป็นสตริง รายการสตริง หรือตัวเลข โปรดทราบว่ารายการสตริงรองรับค่าได้สูงสุด 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
ได้สูงสุด 1 ล้านรายการ
เช่นเดียวกับ Document
Chunks
ยังรองรับช่อง custom_metadata
ที่ผู้ใช้ระบุได้สูงสุด 20 ช่อง ซึ่งระบุเป็นคู่คีย์-ค่า โดยอาจเป็นสตริง รายการสตริง หรือตัวเลข โปรดทราบว่ารายการของสตริงรองรับค่าได้สูงสุด 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
รับ HTML 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
เอง และส่วนถัดไปจะอัปโหลดออบเจ็กต์เหล่านั้นไปยัง Semantic Retriever 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)
หรือจะสร้างข้อมูลโค้ด HTML หลายส่วนโดยไม่ต้องใช้ 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
หากไม่ระบุขีดจํากัด ระบบจะแสดงผล Chunk
สูงสุด 10 รายการ
ระบุ 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 จะแสดงผลChunk
สูงสุด 10 รายการ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" สำหรับคีย์เดียวกัน ค่าสตริงรองรับเฉพาะ "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) หมายถึงการตอบคำถามโดยอิงตามบริบทที่ระบุและระบุแหล่งที่มา พร้อมทั้งลดการคาดเดา
GenerateAnswer
มีข้อดีหลายประการเหนือกว่าการใช้ LLM ที่ไม่ได้ปรับแต่ง ในกรณีที่ต้องการ AQA ดังนี้
- โมเดลพื้นฐานได้รับการฝึกให้แสดงเฉพาะคำตอบที่อิงตามบริบทที่ระบุ
- โดยจะระบุแหล่งที่มา (ส่วนของบริบทที่ระบุซึ่งมีส่วนทำให้เกิดคำตอบ) การระบุแหล่งที่มาช่วยให้ผู้ใช้ยืนยันคำตอบได้
- โดยจะประมาณค่า
answerable_probability
สำหรับคู่ (คำถาม บริบท) ที่ระบุ ซึ่งจะช่วยเพิ่มประสิทธิภาพให้คุณเบี่ยงเบนลักษณะการทำงานของผลิตภัณฑ์ โดยขึ้นอยู่กับแนวโน้มของคำตอบที่แสดงว่ามีความถูกต้องและเหมาะสม
answerable_probability
และปัญหา "ฉันไม่รู้"
ในบางกรณี คําตอบที่ดีที่สุดสำหรับคำถามคือ "ฉันไม่ทราบ" ตัวอย่างเช่น หากบริบทที่ระบุไม่มีคําตอบสําหรับคําถาม จะถือว่าคําถามนั้น "ตอบไม่ได้"
โมเดล AQA จะจดจำในกรณีเหล่านั้นได้เป็นอย่างดี ทั้งยังแยกแยะระดับความสามารถในการตอบและไม่สามารถตอบได้
แต่ GenerateAnswer
API จะเป็นผู้มีอำนาจตัดสินใจขั้นสุดท้ายโดยดำเนินการดังนี้
- พยายามเสมอที่จะแสดงคำตอบที่อิงตามข้อมูลจริง แม้ว่าคำตอบนั้นจะมีแนวโน้มที่จะไม่อิงตามข้อมูลจริงและถูกต้องก็ตาม
- การส่งคืนค่า
answerable_probability
- ค่าประมาณของโมเดลเกี่ยวกับความน่าจะเป็นที่คำตอบจะอิงตามความเป็นจริงและถูกต้อง
answerable_probability
ที่ต่ำอาจเกิดจากปัจจัยต่อไปนี้อย่างน้อย 1 ข้อ
- โมเดลไม่มั่นใจว่าคำตอบที่แสดงนั้นถูกต้อง
- โมเดลไม่มั่นใจว่าคำตอบดังกล่าวมาจากข้อความที่อ้างอิง คำตอบอาจได้มาจากความรู้ทางโลก เช่น
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 ในGenerateAnswerRequest
ข้อมูลอ้างอิง API
- ความยาวของข้อความ: แนะนำให้ใช้โทเค็นไม่เกิน 300 รายการต่อข้อความ
- การจัดเรียงข้อความ:
- หากคุณระบุ
GenerateAnswerRequest.inline_passages
ระบบจะจัดเรียงข้อความตามลำดับความเกี่ยวข้องที่ลดลงกับการค้นหา หากเกินขีดจำกัดความยาวบริบทของโมเดล ระบบจะละเว้นข้อความสุดท้าย (เกี่ยวข้องน้อยที่สุด) - หากคุณระบุ
GenerateAnswerRequest.semantic_retriever
ระบบจะจัดเรียงตามความเกี่ยวข้องให้คุณโดยอัตโนมัติ
- หากคุณระบุ
- ข้อจํากัด: รูปแบบ AQA ออกแบบมาเพื่อตอบคําถามโดยเฉพาะ สำหรับกรณีการใช้งานอื่นๆ เช่น การเขียนเชิงสร้างสรรค์ การสรุป ฯลฯ โปรดเรียกใช้โมเดลอเนกประสงค์ผ่าน GenerateContent
- แชท: หากทราบว่าอินพุตของผู้ใช้คือคำถามที่อาจตอบได้จากบริบทหนึ่งๆ AQA จะตอบคำถามในแชทได้ แต่หากอินพุตของผู้ใช้อาจเป็นรายการประเภทใดก็ได้ รูปแบบเอนกประสงค์อาจเป็นตัวเลือกที่ดีกว่า
- อุณหภูมิ:
- โดยทั่วไป เราขอแนะนำให้ใช้อุณหภูมิที่ค่อนข้างต่ำ (~0.2) เพื่อให้ได้ AQA ที่แม่นยำ
- หาก Use Case ของคุณใช้เอาต์พุตแบบกำหนดได้ ให้ตั้งค่า temperature=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 โดยตรงโดยไม่ต้องใช้ Semantic 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)
แชร์ชุดข้อความ
คุณสามารถเลือกที่จะแชร์คลังข้อมูลกับผู้อื่นโดยใช้ CreatePermissionRequest
API
ข้อจำกัด
- การแชร์มี 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
ทั้งหมดที่เกี่ยวข้อง
โปรดทราบว่าคอร์ปัสที่ไม่ใช่ค่าว่างจะแสดงข้อผิดพลาดหากไม่ได้ระบุ Flag 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)
สรุปและการอ่านเพิ่มเติม
คู่มือนี้แนะนำ Semantic Retriever และ API ของคำถามและการตอบกลับ (AQA) ที่มีแหล่งที่มาของ Generative Language API และแสดงวิธีใช้เพื่อดึงข้อมูลเชิงความหมายในข้อมูลข้อความที่กําหนดเอง โปรดทราบว่า API นี้ใช้งานได้กับเฟรมเวิร์กข้อมูล LlamaIndex ด้วย ดูข้อมูลเพิ่มเติมได้ในบทแนะนำ
นอกจากนี้ โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับฟังก์ชันอื่นๆ ที่มีอยู่ในเอกสารประกอบ API
ภาคผนวก: ตั้งค่า OAuth ด้วยข้อมูลเข้าสู่ระบบของผู้ใช้
ทำตามขั้นตอนด้านล่างจากการเริ่มต้นใช้งาน OAuth อย่างรวดเร็วเพื่อตั้งค่าการตรวจสอบสิทธิ์ OAuth
ให้สิทธิ์ข้อมูลเข้าสู่ระบบสำหรับแอปพลิเคชันบนเดสก์ท็อป หากต้องการเรียกใช้สมุดบันทึกนี้ใน 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"
เริ่มการกําหนดค่าคลังไลบรารีไคลเอ็นต์และเรียกใช้โน้ตบุ๊กอีกครั้งโดยเริ่มจากสร้างชุดข้อความ
import google.ai.generativelanguage as glm
generative_service_client = glm.GenerativeServiceClient()
retriever_service_client = glm.RetrieverServiceClient()
permission_service_client = glm.PermissionServiceClient()