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:
- Aktivieren Sie die Generative Language API.
Erstellen Sie das Dienstkonto gemäß der Dokumentation.
- Nachdem Sie das Dienstkonto erstellt haben, generieren Sie einen Dienstkontoschlüssel.
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 Variableservice_account_file_name
im folgenden Code.
- Benennen Sie die hochgeladene Datei in
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) derCorpus
-Ressource. Darf maximal 40 alphanumerische Zeichen enthalten. Wenn das Feldname
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 Felddisplay_name
und ein zufälliges Suffix mit 12 Zeichen.display_name
: Der visuell lesbare Anzeigename für dieCorpus
. 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) vonDocument
. 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 ausdisplay_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.
Document
s 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 Chunk
s 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 Chunk
s. 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)
Chunk
s auflisten und Status abrufen
Mit der ListChunksRequest
-Methode können Sie alle verfügbaren Chunk
s als paginaierte Liste mit einer maximalen Größe von 100 Chunk
s pro Seite abrufen, sortiert in aufsteigender Reihenfolge nach Chunk.create_time
. Wenn Sie kein Limit angeben, werden maximal 10 Chunk
s 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 Chunk
s 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
Chunk
s 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 10Chunk
zurück.metadata_filters
: Nachchunk_metadata
oderdocument_metadata
filtern. JederMetadataFilter
muss einem eindeutigen Schlüssel entsprechen. MehrereMetadataFilter
-Objekte sind durch logischeAND
s verbunden. Ähnliche Metadatenfilterbedingungen werden durch logischeOR
s 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:
- Wenn Sie
GenerateAnswerRequest.inline_passages
angeben, sollten die Passagen in absteigender Relevanz für die Suchanfrage sortiert werden. Wenn das Limit für die Kontextlänge des Modells überschritten wird, werden die letzten (am wenigsten relevanten) Passagen weggelassen. - Wenn Sie
GenerateAnswerRequest.semantic_retriever
angeben, erfolgt die Relevanzsortierung automatisch.
- Wenn Sie
- 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
undEDITOR
.- Ein
READER
kann den Korpus abfragen. - Ein
WRITER
hat Leseberechtigungen und kann den Korpus zusätzlich bearbeiten und freigeben.
- Ein
- Ein Corpus kann öffentlich sein, wenn Sie
EVERYONE
Lesezugriff alsuser_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 Document
s und Chunk
s zu löschen.
Bei nicht leeren Corpora wird ohne Angabe des force=True
-Flags ein Fehler ausgegeben. Wenn Sie force=True
festlegen, werden alle Chunk
s 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.
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
) inclient_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()