เริ่มต้นใช้งานการดึงข้อมูลความหมาย

ดูใน 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 โดยใช้บัญชีบริการ

  1. เปิดใช้ Generative Language API

  1. สร้างบัญชีบริการโดยทําตามเอกสารประกอบ

    • หลังจากสร้างบัญชีบริการแล้ว ให้สร้างคีย์ของบัญชีบริการ

  1. อัปโหลดไฟล์บัญชีบริการโดยใช้ไอคอนไฟล์ในแถบด้านข้างซ้าย แล้วคลิกไอคอนอัปโหลดดังที่แสดงในภาพหน้าจอด้านล่าง

    • เปลี่ยนชื่อไฟล์ที่อัปโหลดเป็น 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

  1. กำหนดค่าหน้าจอขอความยินยอม OAuth

  2. ให้สิทธิ์ข้อมูลเข้าสู่ระบบสำหรับแอปพลิเคชันบนเดสก์ท็อป หากต้องการเรียกใช้สมุดบันทึกนี้ใน 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()