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 dass sie direkt darauf trainiert werden. LLMs können jedoch „halluzinieren“, wenn sie auf Fragen antworten sollen, für die sie nicht trainiert wurden. Das liegt zum Teil daran, dass LLMs nach dem Training keine Ereignisse kennen. Außerdem ist es sehr schwierig, die Quellen zu ermitteln, aus denen LLMs ihre Antworten beziehen. Für zuverlässige, skalierbare Anwendungen ist es wichtig, dass ein LLM Antworten liefert, die auf Fakten basieren und seine Informationsquellen zitieren kann.

Ein gängiger Ansatz, um diese Einschränkungen zu überwinden, wird als Retrieval-Augmented Generation (RAG) bezeichnet. Dabei wird der an ein LLM gesendete Prompt mit relevanten Daten erweitert, die über einen Informationsabrufmechanismus (Information Retrieval, IR) aus einer externen Wissensdatenbank abgerufen werden. Die Wissensdatenbank kann aus Ihren eigenen Dokumenten, Datenbanken oder APIs bestehen.

In diesem Notebook wird ein Workflow beschrieben, mit dem Sie die Antwort eines LLM verbessern können, indem Sie sein Wissen mit externen Textkorpora ergänzen und semantische Informationen abrufen, um Fragen mithilfe des Semantic Retriever und der AQA-APIs (Attributed Question and Answering) der Generative Language API zu beantworten.

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 semantische Suchanfragen auf Ihre eigenen Daten anwenden. Da es sich um Ihre Daten handelt, sind hier strengere Zugriffssteuerungen als bei API-Schlüsseln 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

So richten Sie OAuth mithilfe von Dienstkonten ein:

  1. Aktivieren Sie die Generative Language API.

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

    • Nachdem Sie das Dienstkonto erstellt haben, generieren Sie einen Dienstkontoschlüssel.

  1. Laden Sie die Datei Ihres Dienstkontos über das Dateisymbol in der linken Seitenleiste und dann über das Uploadsymbol hoch (siehe Screenshot unten).

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

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 pro Projekt bis zu fünf benutzerdefinierte Textkorpora definieren. Sie können beim Definieren Ihrer Korpora eines der folgenden Felder angeben:

  • name: Der Name (ID) der Corpus-Ressource. Darf maximal 40 alphanumerische Zeichen enthalten. Wenn das Feld name beim Erstellen leer ist, wird ein eindeutiger Name mit einer maximalen Länge von 40 Zeichen generiert. Er enthält ein Präfix aus dem Feld display_name und ein zufälliges Suffix mit 12 Zeichen.
  • display_name: Der visuell lesbare Anzeigename für die Corpus. Darf maximal 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 ist in der Zelle oben 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 Document enthalten. Sie können bei der Definition Ihrer Dokumente eines der folgenden Felder angeben:

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

Documents unterstützen außerdem bis zu 20 benutzerdefinierte custom_metadata-Felder, die als Schlüssel/Wert-Paare angegeben werden. Benutzerdefinierte Metadaten können Strings, Listen von Strings oder Zahlen sein. Listen von Strings können maximal 10 Werte enthalten. Numerische Werte werden in der API als Gleitkommazahlen dargestellt.

# 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 ist in der Zelle oben 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)

Dokumente aufnehmen und in Segmente unterteilen

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.

Ein Chunk ist ein Teil einer Document, der für die Vektordarstellung und ‑speicherung als unabhängige Einheit behandelt wird. Ein Chunk kann maximal 2.043 Token haben. Ein Corpus kann maximal 1 Million Chunks haben.

Ähnlich wie Document unterstützen auch Chunks bis zu 20 benutzerdefinierte custom_metadata-Felder, die als Schlüssel/Wert-Paare angegeben werden. Benutzerdefinierte Metadaten können Strings, Listen von Strings oder Zahlen sein. Listen von Strings können maximal 10 Werte enthalten. Numerische Werte werden in der API als Gleitkommazahlen dargestellt.

In dieser Anleitung wird der Open-Source-HtmlChunker von Google verwendet.

Weitere mögliche Chunker sind LangChain oder LlamaIndex.

HTML-Dateien über HtmlChunker aufnehmen und in kleinere Dateien aufteilen

!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 wäre jedoch besser, wenn der HTML-Code nach dem Rendering JavaScript-injiziertes HTML wie document.documentElement.innerHTML enthalten würde.

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

Teilen Sie das Textdokument in Absätze auf und erstellen Sie daraus Chunks. In diesem Schritt werden die Chunk-Objekte selbst erstellt und im nächsten Abschnitt 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)

Blöcke im Batch erstellen

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

Verwenden Sie CreateChunk(), um einen einzelnen Chunk zu erstellen.

# 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 auch ohne den HtmlChunker Chunks 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

Mit der ListChunksRequest-Methode können Sie alle verfügbaren Chunks als paginaierte Liste mit einer maximalen Größe von 100 Chunks pro Seite abrufen, sortiert in aufsteigender Reihenfolge nach Chunk.create_time. Wenn Sie kein Limit angeben, werden maximal 10 Chunks zurückgegeben.

Gib den in der ListChunksRequest-Antwort zurückgegebenen Wert 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 eine state zurück. So kannst du den Status der Chunks prüfen, bevor du eine Corpus abfragst. Zu den Chunk-Status 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üge über HtmlChunker eine weitere Document hinzu und füge 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 zu retournierenden Passagen an. Der Maximalwert ist 100. Wenn nicht angegeben, gibt die API maximal 10 Chunk 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 verknüpft. 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} }]
  }]

Beachten Sie, dass nur für numerische Werte „AND“ für denselben Schlüssel unterstützt wird. Bei Stringwerten wird für denselben Schlüssel nur „OR“ unterstützt.

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

Question Answering mit Quellenangabe

Verwenden Sie die Methode GenerateAnswer, um die Beantwortung von Fragen mit Quellenangaben für Ihr Dokument, Ihren Korpus oder eine Reihe von Textpassagen auszuführen.

Die Beantwortung von Fragen mit Quellenangaben (Attributed Question-Answering, AQA) bezieht sich auf das Beantworten von Fragen, die auf einem bestimmten Kontext basieren, und das Angeben von Quellenangaben, wobei die Halluzination minimiert wird.

GenerateAnswer bietet mehrere Vorteile gegenüber der Verwendung eines nicht abgestimmten LLM, wenn AQA gewünscht ist:

  • Das zugrunde liegende Modell wurde darauf trainiert, nur Antworten zurückzugeben, die auf dem angegebenen Kontext basieren.
  • Es werden Attributionen (Segmente des bereitgestellten Kontexts, die zur Antwort beigetragen haben) identifiziert. Mithilfe von Attributionen kann der Nutzer die Antwort überprüfen.
  • Er schätzt den answerable_probability für ein bestimmtes Paar (Frage, Kontext) und ermöglicht es Ihnen so, das Produktverhalten je nach Wahrscheinlichkeit zu ändern, dass die zurückgegebene Antwort fundiert und korrekt ist.

answerable_probability und das Problem „Ich weiß nicht“

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

Das AQA-Modell ist sehr gut darin, solche Fälle zu erkennen. Es kann sogar zwischen verschiedenen Graden der Beantwortbarkeit und Nichtbeantwortbarkeit unterscheiden.

Mit der GenerateAnswer API haben Sie jedoch die endgültige Entscheidungsgewalt:

  • Immer versuchen, eine fundierte Antwort zurückzugeben, auch wenn diese Antwort relativ unwahrscheinlich fundiert und richtig ist.
  • Wert answerable_probability zurückgeben: Die Schätzung des Modells für die Wahrscheinlichkeit, dass die Antwort fundiert und richtig ist.

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

  • Das Modell ist sich nicht sicher, ob seine Antwort richtig ist.
  • Das Modell ist sich nicht sicher, ob seine Antwort auf den zitierten Passagen basiert. Die Antwort kann stattdessen aus Weltwissen abgeleitet werden. Beispiel: question="1+1=?", passages=["2+2=4”] → answer=2, answerable_probability=0.02
  • Das Modell hat relevante Informationen geliefert, 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 Wert für answerable_probability darauf hinweist, dass die Antwort von GenerateAnswerResponse.answer wahrscheinlich falsch oder nicht begründet ist, wird dringend empfohlen, die Antwort durch Prüfung von answerable_probability weiterzuverarbeiten.

Wenn answerable_probability niedrig ist, können einige Kunden Folgendes tun:

  • Dem Endnutzer wird eine Nachricht mit dem Hinweis angezeigt, dass diese Frage nicht beantwortet werden konnte.
  • Nutzen Sie ein allgemeines LLM, das die Frage nach dem Weltwissen beantwortet. Der Schwellenwert und die Art solcher Fallbacks hängen von den einzelnen Anwendungsfällen ab. Ein Wert von answerable_probability <= 0,5 ist ein guter Ausgangspunkt.

Hilfreiche Tipps für die AQA

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

  • Abschnittslänge: Wir empfehlen bis zu 300 Token pro Abschnitt.
  • Durchgangssortierung:
  • Einschränkungen: Das AQA-Modell ist auf die Beantwortung von Fragen spezialisiert. Für andere Anwendungsfälle wie kreatives Schreiben oder Zusammenfassungen 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 AQA Chatanfragen beantworten. Wenn die Nutzereingabe jedoch beliebiger Art sein kann, ist ein allgemeines Modell möglicherweise die bessere Wahl.
  • Temperatur:
    • Für eine genaue AQA wird im Allgemeinen eine relativ niedrige Temperatur (etwa 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)

Weitere Optionen: AQA mit Inline-Passagen

Alternativ können Sie den AQA-Endpunkt direkt verwenden, ohne die Semantic Retriever API zu verwenden. Geben Sie dazu inline_passages ein.

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 mit anderen teilen, indem Sie die CreatePermissionRequest API verwenden.

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 Corpus kann öffentlich sein, wenn Sie EVERYONE Lesezugriff als user_type 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 Chunks zu löschen.

Bei nicht leeren Corpora wird ohne Angabe des force=True-Flags ein Fehler ausgegeben. 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 enthalten, wird ein FAILED_PRECONDITION-Fehler 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 weiterführende Literatur

In diesem Leitfaden wurden die APIs „Semantic Retriever“ und „Attributed Question & Answering“ (AQA) der Generative Language API vorgestellt. Außerdem wurde gezeigt, wie Sie damit semantische Informationen aus Ihren benutzerdefinierten Textdaten abrufen können. Diese API funktioniert auch mit dem LlamaIndex-Datenframework. Weitere Informationen finden Sie in der Anleitung.

Weitere Informationen zu den anderen verfügbaren Funktionen findest du in der API-Dokumentation.

Anhang: OAuth mit Nutzeranmeldedaten einrichten

Folgen Sie der OAuth-Kurzanleitung, um die OAuth-Authentifizierung einzurichten.

  1. Konfigurieren Sie den OAuth-Zustimmungsbildschirm.

  2. Anmeldedaten für eine Desktopanwendung autorisieren Wenn Sie dieses Notebook in Colab ausführen möchten, müssen Sie zuerst Ihre Anmeldedatendatei (normalerweise client_secret_*.json) in client_secret.json umbenennen. Laden Sie die Datei dann über das Dateisymbol in der linken Seitenleiste und dann über das Uploadsymbol hoch (siehe Screenshot unten).

# 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 Corpus erstellen.

import google.ai.generativelanguage as glm

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