Erste Schritte mit dem semantischen Abruf

Auf ai.google.dev ansehen Colab-Notebook testen Notebook auf GitHub ansehen

Übersicht

Large Language Models (LLMs) können neue Fähigkeiten erlernen, ohne sie direkt damit trainiert zu werden. Es ist jedoch bekannt, dass LLMs „halluzinieren“ wenn sie damit beauftragt wurden, Fragen zu beantworten, für die sie nicht geschult wurden. Das liegt unter anderem daran, dass LLMs nach dem Training keine Ahnung von Ereignissen haben. Außerdem ist es sehr schwierig, die Quellen zu verfolgen, aus denen LLMs ihre Antworten beziehen. Für zuverlässige, skalierbare Anwendungen ist es wichtig, dass ein LLM auf Fakten basierte Antworten gibt und in der Lage ist, seine Informationsquellen zu zitieren.

Ein gängiger Ansatz zur Überwindung dieser Einschränkungen ist Retrieval Augmented Generation (RAG). Dabei wird der an ein LLM gesendete Prompt mit relevanten Daten erweitert, die über einen Informationsabrufmechanismus (Information Retrieval, IR) aus einer externen Wissensdatenbank abgerufen wurden. Die Wissensdatenbank kann Ihre eigene Korpora von Dokumenten, Datenbanken oder APIs sein.

Dieses Notebook führt Sie durch einen Workflow zur Verbesserung der Reaktion eines LLM, indem sein Wissen mit externen Textkorpora erweitert und semantische Informationen abgerufen werden, um Fragen mit dem Semantic Retriever und den zugeordneten Fragen zu beantworten. Answering (AQA) APIs der Generative Language API

Einrichtung

Generative Language API importieren

# Install the Client library (Semantic Retriever is only supported for versions >0.4.0)
pip install -U google.ai.generativelanguage

Authentifizieren

Mit der Semantic Retriever API können Sie eine semantische Suche für Ihre eigenen Daten ausführen. Da es sich um Ihre Daten handelt, sind dafür strengere Zugriffssteuerungen als für API-Schlüssel erforderlich. Authentifizieren Sie sich mit OAuth über Dienstkonten oder über Ihre Nutzeranmeldedaten.

In dieser Kurzanleitung wird ein vereinfachter Authentifizierungsansatz für eine Testumgebung verwendet. Die Einrichtung von Dienstkonten ist in der Regel einfacher. Für eine Produktionsumgebung sollten Sie sich über die Authentifizierung und Autorisierung informieren, bevor Sie die für Ihre Anwendung geeigneten Anmeldedaten auswählen.

OAuth mit Dienstkonten einrichten

Führen Sie die folgenden Schritte aus, um OAuth mithilfe von Dienstkonten einzurichten:

  1. Aktivieren Sie die Generative Language API.

  1. Erstellen Sie das Dienstkonto gemäß der Dokumentation.

    • Generieren Sie nach dem Erstellen des Dienstkontos einen Dienstkontoschlüssel.

  1. Laden Sie Ihre Dienstkontodatei hoch, indem Sie auf das Dateisymbol in der linken Seitenleiste und dann auf das Uploadsymbol klicken, wie im Screenshot unten dargestellt.

    • Benennen Sie die hochgeladene Datei in service_account_key.json um oder ändern Sie die Variable service_account_file_name im Code unten.

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'])

Initialisieren Sie die Clientbibliothek mit den Anmeldedaten des Dienstkontos.

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)

Korpus erstellen

Mit der Semantic Retriever API können Sie bis zu fünf benutzerdefinierte Textkorpora pro Projekt definieren. Sie können beim Definieren Ihrer Korpora eines der folgenden Felder angeben:

  • name: Der Ressourcenname (ID) von Corpus. Darf maximal 40 alphanumerische Zeichen enthalten. Wenn name bei der Erstellung leer ist, wird ein eindeutiger Name mit einer maximalen Länge von 40 Zeichen mit einem Präfix aus display_name und einem zufälligen Suffix mit 12 Zeichen generiert.
  • display_name: Der visuell lesbare Anzeigename für die Corpus. Darf höchstens 512 Zeichen enthalten, einschließlich alphanumerischer Zeichen, Leerzeichen und Bindestriche.
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
}

Erstellten Korpus abrufen

Verwenden Sie die Methode GetCorpusRequest, um programmatisch auf die oben erstellte Corpus zuzugreifen. Der Wert des Parameters name bezieht sich auf den vollständigen Ressourcennamen der Corpus und wird in der Zelle darüber als corpus_resource_name festgelegt. Das erwartete Format ist 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)

Dokument erstellen

Ein Corpus kann bis zu 10.000 Documents enthalten. Sie können bei der Definition Ihrer Dokumente eines der folgenden Felder angeben:

  • name: Der Ressourcenname (ID) von Document. Darf höchstens 40 Zeichen enthalten (nur alphanumerische Zeichen oder Bindestriche). Die ID darf nicht mit einem Bindestrich. Wenn der Name bei der Erstellung leer ist, wird ein eindeutiger Name abgeleitet aus display_name und ein zufälliges Suffix mit 12 Zeichen.
  • display_name: Der für Menschen lesbare Anzeigename. Darf höchstens 512 Zeichen enthalten, einschließlich alphanumerischer Zeichen, Leerzeichen und Bindestriche.

Document unterstützen außerdem bis zu 20 benutzerdefinierte custom_metadata-Felder, die als Schlüssel/Wert-Paare angegeben werden. Benutzerdefinierte Metadaten können Strings, Stringlisten oder numerisch sein. Beachten Sie, dass Stringlisten maximal 10 Werte unterstützen können und numerische Werte im API als Gleitkommazahlen dargestellt werden.

# 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)

Erstelltes Dokument abrufen

Verwenden Sie die Methode GetDocumentRequest, um programmatisch auf das oben erstellte Dokument zuzugreifen. Der Wert des Parameters name bezieht sich auf den vollständigen Ressourcennamen des Dokuments und wird in der Zelle darüber als document_resource_name festgelegt. Das erwartete Format ist 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)

Daten aufnehmen und Dokument kopieren

Um die Relevanz der von der Vektordatenbank zurückgegebenen Inhalte beim semantischen Abruf zu verbessern, unterteilen Sie große Dokumente bei der Datenaufnahme in kleinere Teile oder Blöcke.

Eine Chunk ist ein Unterteil einer Document, die zum Zweck der Vektordarstellung und Speicherung als unabhängige Einheit behandelt wird. Ein Chunk kann maximal 2.043 Tokens haben. Ein Corpus kann maximal 1 Million Chunks haben.

Ähnlich wie Documents unterstützt Chunks auch bis zu 20 benutzerdefinierte custom_metadata-Felder, die als Schlüssel/Wert-Paare angegeben werden. Benutzerdefinierte Metadaten können Strings, Stringlisten oder numerisch sein. Beachten Sie, dass Stringlisten maximal 10 Werte unterstützen können und numerische Werte im API als Gleitkommazahlen dargestellt werden.

In diesem Leitfaden wird der Open-Source-HTMLChunker von Google verwendet.

Andere Chunker, die Sie verwenden können, sind zum Beispiel LangChain oder LlamaIndex.

HTML und Block über HTMLChunker aufnehmen

!pip install google-labs-html-chunker

from google_labs_html_chunker.html_chunker import HtmlChunker

from urllib.request import urlopen

HTML-DOM für eine Website abrufen Hier wird der HTML-Code direkt gelesen, Es ist besser, beim HTML-Post-Rendering mit JavaScript-Injection zu arbeiten. wie 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")

Teile das Textdokument in Abschnitte auf und erstelle aus diesen Abschnitten Chunks. Mit diesem Schritt werden die Chunk-Objekte selbst erstellt und im nächsten Abschnitt werden sie in die Semantic Retriever API hochgeladen.

# 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)

Erstellen Sie Blöcke im Batch

Erstellen Sie Blöcke in Batches. Sie können maximal 100 Blöcke pro Batchanfrage angeben.

Verwenden Sie CreateChunk() für die Erstellung eines einzelnen Blocks.

# 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)

Alternativ können Sie Blöcke ohne den HTMLChunker erstellen.

# 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)

Chunks auflisten und Status abrufen

Verwenden Sie die Methode ListChunksRequest, um alle verfügbaren Chunks als paginierte Liste mit einer maximalen Größenbeschränkung von 100 Chunks pro Seite, sortiert in aufsteigender Reihenfolge von Chunk.create_time, abzurufen. Wenn Sie kein Limit angeben, werden maximal 10 Chunks zurückgegeben.

Geben Sie das in der ListChunksRequest-Antwort zurückgegebene next_page_token als Argument für die nächste Anfrage an, um die nächste Seite abzurufen. Beim Paginieren müssen alle anderen für ListChunks bereitgestellten Parameter mit dem Aufruf übereinstimmen, der das Seitentoken bereitgestellt hat.

Alle Chunks geben ein state zurück. Hiermit können Sie den Status von Chunks prüfen, bevor Sie Corpus abfragen. Zu den Chunk Bundesstaaten gehören UNSPECIFIED, PENDING_PROCESSING, ACTIVE und FAILED. Du kannst nur ACTIVE Chunks abfragen.

# 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}')

Weiteres Dokument aufnehmen

Fügen Sie über HTMLChunker eine weitere Document hinzu und fügen Sie Filter hinzu.

# 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)

Korpus abfragen

Mit der Methode QueryCorpusRequest können Sie eine semantische Suche ausführen, um relevante Abschnitte zu erhalten.

  • results_count: Geben Sie die Anzahl der zurückzugebenden Abschnitte an. Der Höchstwert ist 100. Wenn kein Wert angegeben ist, gibt die API maximal 10 Chunks zurück.
  • metadata_filters: Nach chunk_metadata oder document_metadata filtern. Jeder MetadataFilter muss einem eindeutigen Schlüssel entsprechen. Mehrere MetadataFilter-Objekte sind durch logische ANDs verbunden. Ähnliche Metadatenfilterbedingungen werden durch logische ORs verbunden. Beispiele:
(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} }]
  }]

UND-Zeichen werden für denselben Schlüssel nur durch numerische Werte unterstützt. Zeichenfolge -Werte unterstützen nur OR-Werte für denselben Schlüssel.

("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)

Zugeordnete Fragenbeantwortung

Mit der Methode GenerateAnswer können Sie eine Zuordnung von Fragen für Ihr Dokument, Ihren Korpus oder mehrere Abschnitte ausführen.

Zugeordnete Question-Answering (AQA) bezieht sich auf die Beantwortung von Fragen, die auf einem bestimmten Kontext basieren, die Zuordnung(en) zur Verfügung stellen und dabei KI-Halluzinationen minimieren.

GenerateAnswer bietet mehrere Vorteile gegenüber einem nicht abgestimmten LLM, wenn eine AQA gewünscht wird:

  • Das zugrunde liegende Modell wurde so trainiert, dass nur Antworten zurückgegeben werden, die auf dem bereitgestellten Kontext basieren.
  • Es identifiziert Attributionen (Segmente des bereitgestellten Kontexts, die zur Antwort beigetragen haben). Attributionen ermöglichen es dem Nutzer, die Antwort zu bestätigen.
  • Dabei wird die answerable_probability für ein bestimmtes (Frage, Kontext)-Paar geschätzt. Dies gibt Ihnen die Möglichkeit, das Produktverhalten abhängig davon umzuleiten, wie wahrscheinlich es ist, dass die zurückgegebene Antwort begründet und korrekt ist.

answerable_probability und das Problem „Ich weiß nicht“

In einigen Fällen lautet die beste Antwort auf die Frage tatsächlich „Ich weiß nicht“. Wenn der bereitgestellte Kontext beispielsweise keine Antwort auf die Frage enthält, wird die Frage als „nicht beantwortbar“ erachtet.

Das AQA-Modell erkennt solche Fälle sehr gut. Er kann sogar zwischen dem Grad der Antwortbarkeit und dem Unbeantwortungsgrad unterscheiden.

Die GenerateAnswer API gibt jedoch die endgültige Entscheidungsgewalt in Ihren Händen:

  • Immer versuchen, eine fundierte Antwort zurückzugeben, auch wenn es unwahrscheinlich ist, dass diese Antwort begründet und richtig ist.
  • Rückgabe eines Werts answerable_probability: Die Schätzung des Modells für die Wahrscheinlichkeit, dass die Antwort begründet und richtig ist.

Ein niedriger answerable_probability kann durch einen oder mehrere der folgenden Faktoren erklärt werden:

  • Das Modell ist nicht davon überzeugt, dass seine Antwort richtig ist.
  • Das Modell ist nicht sicher, ob seine Antwort auf den zitierten Textabschnitten fußt. Die Antwort kann sich stattdessen aus dem Weltwissen ergeben. Beispiel: question="1+1=?", passages=["2+2=4”]answer=2, answerable_probability=0.02
  • Das Modell lieferte relevante Informationen, die die Frage nicht vollständig beantworten. Beispiel: 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"
  • In GenerateAnswerRequest wurde keine korrekt formulierte Frage gestellt.

Da ein niedriger answerable_probability-Wert darauf hindeutet, dass die GenerateAnswerResponse.answer wahrscheinlich falsch oder grundlos ist, wird dringend empfohlen, die Antwort durch Prüfen von answerable_probability weiter zu verarbeiten.

Wenn answerable_probability niedrig ist, möchten einige Kunden möglicherweise Folgendes tun:

  • Nachricht mit dem Hinweis „Diese Frage konnte nicht beantwortet werden“ anzeigen für die Endanwendenden.
  • Nutzen Sie ein allgemeines LLM, das die Frage nach dem Weltwissen beantwortet. Der Grenzwert und die Art dieser Fallbacks hängen vom jeweiligen Anwendungsfall ab. Ein Wert von answerable_probability <= 0,5 ist ein guter Startgrenzwert.

Hilfreiche Tipps zur AQA

Die vollständigen API-Spezifikationen finden Sie in der GenerateAnswerRequest API-Referenz.

  • Durchgangslänge: Es werden bis zu 300 Tokens pro Passage empfohlen.
  • Durchgangssortierung: <ph type="x-smartling-placeholder">
      </ph>
    • Wenn Sie GenerateAnswerRequest.inline_passages angeben, sollten die Abschnitte in absteigender Reihenfolge nach Relevanz für die Abfrage sortiert werden. Wenn die Kontextlängenbeschränkung des Modells überschritten wird, werden die letzten (am wenigsten relevanten) Abschnitte weggelassen.
    • Wenn Sie GenerateAnswerRequest.semantic_retriever angeben, erfolgt die Sortierung nach Relevanz automatisch.
  • Einschränkungen: Das AQA-Modell ist auf die Beantwortung von Fragen spezialisiert. Für andere Anwendungsfälle wie kreatives Schreiben, Zusammenfassen usw. rufen Sie bitte über GenerateContent ein allgemeines Modell auf.
    • Chat: Wenn bekannt ist, dass es sich bei der Nutzereingabe um eine Frage handelt, die in einem bestimmten Kontext beantwortet werden kann, kann das AQA Chatanfragen beantworten. Wenn die Nutzereingabe jedoch eine beliebige Art von Eintrag sein kann, ist ein Allzweckmodell möglicherweise die bessere Wahl.
  • Temperatur: <ph type="x-smartling-placeholder">
      </ph>
    • Für eine genaue AQA wird im Allgemeinen eine relativ niedrige Temperatur (~0, 2) empfohlen.
    • Wenn Ihr Anwendungsfall auf deterministische Ausgaben beruht, legen Sie Temperatur=0 fest.
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)

Mehr Optionen: AQA mit Inline-Durchgängen

Alternativ können Sie den AQA-Endpunkt direkt und ohne die Semantic Retriever API verwenden, indem Sie inline_passages übergeben.

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)

Korpus freigeben

Sie können den Korpus über die CreatePermissionRequest API für andere freigeben.

Einschränkungen:

  • Es gibt zwei Rollen für die Freigabe: READER und EDITOR.
    • Ein READER kann den Korpus abfragen.
    • Ein WRITER hat Leseberechtigungen und kann den Korpus zusätzlich bearbeiten und freigeben.
  • Ein Korpus kann öffentlich sein, wenn Sie EVERYONE als user_type Lesezugriff gewähren.
# 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)

Korpus löschen

Verwenden Sie DeleteCorpusRequest, um einen Nutzerkorpus und alle zugehörigen Documents und Chunk Sek.

Beachten Sie, dass nicht leere Korpora einen Fehler ausgeben, ohne ein force=True-Flag anzugeben. Wenn Sie force=True festlegen, werden alle Chunks und Objekte im Zusammenhang mit dieser Document ebenfalls gelöscht.

Wenn force=False (Standardeinstellung) und Document Chunk-Werte enthält, wird der Fehler FAILED_PRECONDITION zurückgegeben.

# 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)

Zusammenfassung und weitere Informationen

In diesem Leitfaden wurden der Semantic Retriever, zugeordnete Fragen und Answering (AQA) der Generative Language API und zeigte, wie Sie damit semantische Informationen zu Ihren benutzerdefinierten Textdaten abrufen können. Die API funktioniert auch mit dem Datenframework LlamaIndex. Weitere Informationen finden Sie in dieser Anleitung.

In der API-Dokumentation finden Sie Informationen zu den anderen verfügbaren Funktionen.

Anhang: OAuth mit Nutzeranmeldedaten einrichten

Folgen Sie der Anleitung unten im OAuth-Schnellstart, um die OAuth-Authentifizierung einzurichten.

  1. Konfigurieren Sie den OAuth-Zustimmungsbildschirm.

  2. Anmeldedaten für eine Desktopanwendung autorisieren Um dieses Notebook in Colab auszuführen, benennen Sie zuerst Ihre Anmeldedatendatei (in der Regel client_secret_*.json) in client_secret.json um. Laden Sie dann die Datei hoch, indem Sie das Dateisymbol in der linken Seitenleiste und dann das Upload-Symbol verwenden, wie im Screenshot unten dargestellt.

# 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"

Initialisieren Sie die Clientbibliothek und führen Sie das Notebook noch einmal aus, beginnend mit Korpus erstellen.

import google.ai.generativelanguage as glm

generative_service_client = glm.GenerativeServiceClient()
retriever_service_client = glm.RetrieverServiceClient()
permission_service_client = glm.PermissionServiceClient()