開始使用語意擷取

前往 ai.google.dev 查看 試用 Colab 筆記本 在 GitHub 中查看筆記本

總覽

大型語言模型 (LLM) 不需要直接訓練模型,就能學習新能力。不過,LLM 向來是「退休」而是針對他們未經訓練的問題提供回覆。部分原因是 LLM 在完成訓練後不知道相關事件。要掌握大型語言模型的回覆來源,也相當困難。為可靠的可擴充式應用程式,LLM 提供的內容必須以事實為依據,並能引用資訊來源。

用於克服這些限制的常見做法稱為「檢索增強生成」(RAG),透過資訊擷取 (IR) 機制從外部知識庫擷取相關資料,藉此擴增傳送至 LLM 的提示資料。知識庫可以是您自有的文件、資料庫或 API 語料庫。

這份筆記本會逐步引導您使用外部文字語料庫來強化 LLM 的知識,並執行語意資訊擷取作業,透過語意擷取器和歸因問題回答問題,生成式語言 API 的回答 (AQA) API。

設定

匯入生成式語言 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 個自訂文字語料庫。您可以在定義語料時指定下列其中一個欄位:

  • nameCorpus 資源名稱 (ID)。最多只能包含 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 方法,透過程式輔助方式存取您先前建立的 Corpusname 參數的值是指 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。您可以在定義文件時指定下列其中一個欄位:

  • nameDocument 資源名稱 (ID)。最多只能包含 40 個半形字元 (只能使用英數字元或破折號)。ID 的開頭或結尾不得為 。如果建立時沒有名稱,系統會從 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)

擷取與整理文件

如要在執行語意擷取期間,改善向量資料庫傳回的內容關聯性,請在擷取文件時將大型文件拆成較小的檔案或「區塊」

ChunkDocument 的子部分,系統會將其視為獨立單位,用於向量表示和儲存。一個 Chunk 最多可以有 2043 個符記。CorpusChunk 上限為 100 萬個。

Document 類似,Chunks 也支援最多 20 個使用者指定的 custom_metadata 欄位,並以鍵/值組合的形式指定。自訂中繼資料可以是字串、字串清單或數字。請注意,字串清單最多可以支援 10 個值,而數字值在 API 中會以浮點數表示。

本指南使用 Google 的開放原始碼 HtmlChunker

其他可用的切塊器包括 LangChainLlamaIndex

透過 HtmlChunker 擷取 HTML 和區塊

!pip install google-labs-html-chunker

from google_labs_html_chunker.html_chunker import HtmlChunker

from urllib.request import urlopen

取得網站的 HTML DOM。在這個範例中,系統會直接讀取 HTML,但會 HTML 檔案轉譯後,納入使用 JavaScript 插入的 HTML 例如 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)

或者,您也可以在不使用 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

提供 ListChunksRequest 回應中傳回的 next_page_token 做為引數,以便擷取下一個網頁。請注意,進行分頁時,提供至 ListChunks 的所有其他參數都必須與提供網頁權杖的呼叫相符。

所有 Chunk 都會傳回 state。請在查詢 Corpus 前使用這個項目檢查 Chunks 的狀態。Chunk 狀態包括 - UNSPECIFIEDPENDING_PROCESSINGACTIVEFAILED。您只能查詢 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}')

擷取其他文件

透過 HtmlChunker 新增其他 Document,並新增篩選器。

# 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」。字串 值僅支援同一個鍵的「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 模型擅於識別這類情況。甚至可區分答對度和不答題程度。

不過,GenerateAnswer API 可以透過以下方式,讓您最終做出決策權:

  • 務必嘗試傳回有基準的答案,即使答案較不太可能取得且正確的基準也是如此。
  • 傳回值 answerable_probability - 模型根據基準化和正確答案的可能性預估值。

下列 1 或多項因素都可能造成 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 偏低時,部分客戶可能會想:

  • 顯示「無法回答這個問題」的效果訊息供使用者參考
  • 改回使用一般用途的大型語言模型,從世界知識回答問題。這類備用的門檻和性質取決於個人用途。若值為 answerable_probability <= 0.5,是很好的起始門檻。

AQA 實用訣竅

如需完整的 API 規格,請參閱 GenerateAnswerRequest API 參考資料

  • 票證長度:建議每個段落最多 300 個符記。
  • 段落排序
  • 限制:AQA 模型專門用於回答問題。如果是廣告素材撰寫、摘要等其他用途,請透過 GenerateContent 呼叫一般用途模型。
    • 即時通訊:如果使用者輸入的問題是可在特定情境下回答的問題,品質確保團隊可以回答即時通訊查詢。但如果使用者輸入內容屬於任何類型,那麼一般用途模型可能就更適合。
  • 溫度
    • 一般來說,建議使用相對較低的 (約 0.2) 溫度,確保 AQA。
    • 如果你的用途仰賴確定性輸出,請將隨機性參數設為 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)

更多選項:使用內嵌通道進行品質確保

或者,您也可以藉由傳遞 inline_passages,直接使用 AQA 端點,而不使用 Semantic Retriever API。

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 種角色:READEREDITOR
    • 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 刪除使用者語料庫,以及所有相關聯的 DocumentChunk

請注意,非空白的語料庫會在未指定 force=True 旗標的情況下擲回錯誤。如果設定 force=True,與這個 Document 相關的所有 Chunk 和物件也會一併刪除。

如果 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 回答 (AQA) API 的回答,示範如何使用 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()