Pierwsze kroki z pobieraniem semantycznym

Wyświetl na ai.google.dev Wypróbuj notatnik Colab Wyświetl notatnik na GitHubie

Omówienie

Duże modele językowe (LLM) mogą uczyć się nowych umiejętności bez konieczności ich bezpośredniego trenowania. Znane są jednak modele LLM „hallucynacyjne” których zadaniem jest udzielanie odpowiedzi na pytania, na których nie uczestniczą w szkoleniu. Wynika to częściowo z tego, że duże modele językowe nie wiedzą o zdarzeniach po trenowaniu. Bardzo trudno jest też wyśledzić źródła, z których modele LLM czerpią swoje odpowiedzi. W przypadku niezawodnych, skalowalnych aplikacji LLM musi udzielać odpowiedzi, które są oparte na faktach i potrafią zacytować źródła informacji.

Powszechnym podejściem stosowanym do pokonywania tych ograniczeń jest tzw. Retrieval Augmented Generation (RAG), w ramach którego prompt wysyłany do LLM uzupełnia odpowiednie dane pobrane z zewnętrznej bazy wiedzy przy użyciu mechanizmu pozyskiwania informacji (IR). Baza wiedzy może być Twoim własnym zbiorem dokumentów, baz danych lub interfejsów API.

Ten notatnik przedstawia przepływ pracy mający na celu poprawę odpowiedzi LLM przez rozszerzenie jego wiedzy o zewnętrzne korpusy tekstowe i pobieranie informacji semantycznych w celu uzyskania odpowiedzi na pytania za pomocą modułu odbioru semantycznego oraz przypisanego pytania Interfejsy API do odpowiadania (AQA) interfejsu Generative Language API.

Konfiguracja

Importowanie interfejsu Generative Language API

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

Uwierzytelnij

Interfejs Semantic retriever API umożliwia wyszukiwanie semantyczne własnych danych. Ponieważ to Twoje dane, wymaga to bardziej rygorystycznej kontroli dostępu niż klucze interfejsu API. Uwierzytelniaj za pomocą protokołu OAuth, używając kont usługi lub danych logowania użytkownika.

W tym krótkim wprowadzeniu wykorzystano uproszczone podejście do uwierzytelniania przeznaczone do środowiska testowego, a konfigurację konta usługi zwykle łatwiej jest rozpocząć od konfiguracji. Jeśli używasz środowiska produkcyjnego, dowiedz się więcej o uwierzytelnianiu i autoryzacji, zanim wybierzesz dane logowania odpowiednie dla Twojej aplikacji.

Skonfiguruj protokół OAuth przy użyciu kont usługi

Aby skonfigurować OAuth za pomocą kont usługi, wykonaj te czynności:

  1. Włącz Generative Language API.

  1. Utwórz konto usługi, postępując zgodnie z dokumentacją.

    • Po utworzeniu konta usługi wygeneruj klucz konta usługi.

  1. Prześlij plik konta usługi, klikając ikonę pliku na lewym pasku bocznym, a potem ikonę przesyłania (jak na zrzucie ekranu poniżej).

    • Zmień nazwę przesłanego pliku na service_account_key.json lub zmienną service_account_file_name w kodzie poniżej.

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

Zainicjuj bibliotekę klienta za pomocą danych logowania konta usługi.

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)

Tworzenie korpusu

Interfejs Semantic retriever API umożliwia zdefiniowanie do 5 niestandardowych korpusów tekstowych w projekcie. Podczas definiowania korpusów możesz określić jedno z poniższych pól:

  • name: nazwa (identyfikator) zasobu Corpus. Może zawierać maksymalnie 40 znaków alfanumerycznych. Jeśli podczas tworzenia element name będzie pusty, zostanie wygenerowana unikalna nazwa o maksymalnej długości 40 znaków z prefiksem z display_name i 12-znakowym losowym sufiksem.
  • display_name: czytelna dla człowieka nazwa wyświetlana elementu Corpus. Może zawierać maksymalnie 512 znaków, w tym znaki alfanumeryczne, spacje i myślniki.
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
}

Pobieranie utworzonego korpusu

Aby uzyskać programowy dostęp do elementu Corpus utworzonego powyżej, użyj metody GetCorpusRequest. Wartość parametru name odnosi się do pełnej nazwy zasobu Corpus i jest ustawiona w komórce powyżej jako corpus_resource_name. Oczekiwany format to 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)

Utwórz dokument

Element Corpus może zawierać do 10 000 elementów Document. Podczas definiowania dokumentów możesz określić jedno z tych pól:

  • name: nazwa (identyfikator) zasobu Document. Może zawierać maksymalnie 40 znaków (tylko znaki alfanumeryczne i myślniki). Identyfikator nie może zaczynać się ani kończyć znakiem myślnik. Jeśli podczas tworzenia nazwa będzie pusta, zostanie ona pobrana z display_name wraz z 12-znakowym losowym sufiksem.
  • display_name: wyświetlana nazwa zrozumiała dla człowieka. Może zawierać maksymalnie 512 znaków, w tym znaki alfanumeryczne, spacje i myślniki.

Document obsługują też do 20 określonych przez użytkownika pól custom_metadata określonych jako pary klucz-wartość. Metadane niestandardowe mogą być ciągami znaków, listami ciągów znaków lub wartościami liczbowymi. Listy ciągów znaków mogą zawierać maksymalnie 10 wartości, a wartości liczbowe są w interfejsie API przedstawiane jako liczby zmiennoprzecinkowe.

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

Pobieranie utworzonego dokumentu

Aby automatycznie uzyskać dostęp do utworzonego powyżej dokumentu, użyj metody GetDocumentRequest. Wartość parametru name odnosi się do pełnej nazwy zasobu dokumentu i jest ustawiona w komórce powyżej jako document_resource_name. Oczekiwany format to 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)

Przetwarzaj i Podziel dokument na fragmenty

Aby poprawić trafność treści zwracanych przez bazę danych wektorowych podczas pobierania semantycznego, podczas przetwarzania dokumentu podziel duże dokumenty na mniejsze lub fragmenty.

Element Chunk jest podczęść elementu Document, która jest traktowana jako niezależna jednostka na potrzeby reprezentacji wektorowej i przechowywania danych. Chunk może mieć maksymalnie 2043 tokeny. W elemencie Corpus maksymalna liczba elementów typu Chunk to 1 milion.

Podobnie jak w przypadku komponentów Document, Chunks obsługuje również do 20 określonych przez użytkownika pól custom_metadata, określonych jako pary klucz-wartość. Metadane niestandardowe mogą być ciągami znaków, listami ciągów znaków lub wartościami liczbowymi. Listy ciągów znaków mogą zawierać maksymalnie 10 wartości, a wartości liczbowe są w interfejsie API przedstawiane jako liczby zmiennoprzecinkowe.

Ten przewodnik korzysta z oprogramowania Google Open Source htmlChunker.

Inne fragmenty, których możesz użyć, to LangChain i LlamaIndex.

Pozyskaj kod HTML i fragment za pomocą htmlChunker

!pip install google-labs-html-chunker

from google_labs_html_chunker.html_chunker import HtmlChunker

from urllib.request import urlopen

Pobieranie modelu HTML DOM witryny. W tym przypadku kod HTML jest odczytywany bezpośrednio, ale lepiej korzystać z funkcji postrenderowania HTML, by uwzględnić kod HTML wstrzykiwany JavaScript na przykład 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")

Podziel dokument tekstowy na fragmenty i utwórz z nich elementy Chunk. W tym kroku same obiekty Chunk są tworzone, a następna sekcja przesyła je do interfejsu 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)

Utwórz zbiorczo fragmenty

Utwórz fragmenty partiami. Możesz określić maksymalnie 100 fragmentów na żądanie zbiorcze.

Aby utworzyć pojedynczy fragment, użyj 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)

Możesz też tworzyć fragmenty bez korzystania z mechanizmu 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)

Wyświetl listę Chunk i pobierz stan

Użyj metody ListChunksRequest, aby wyświetlić wszystkie dostępne elementy Chunk w formie podzielonej na strony listy. Limit rozmiaru wynosi 100 elementów Chunk na stronę, posortowany w kolejności rosnącej według wartości Chunk.create_time. Jeśli nie określisz limitu, zwrócony zostanie maksymalnie 10 elementów Chunk.

Podaj next_page_token zwrócony w odpowiedzi ListChunksRequest jako argument następnego żądania, które pozwala pobrać następną stronę. Pamiętaj, że podczas dzielenia na strony wszystkie pozostałe parametry podane w polu ListChunks muszą być zgodne z wywołaniem, które dostarczyło token strony.

Wszystkie elementy typu Chunk zwracają wartość state. Pozwala sprawdzić stan elementu Chunks przed wysłaniem zapytania do Corpus. Chunk stanu to m.in. UNSPECIFIED, PENDING_PROCESSING, ACTIVE i FAILED. Maksymalna liczba zapytań, które możesz wysłać (Chunk), to ACTIVE.

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

Przetwórz kolejny dokument

Dodaj kolejne Document za pomocą htmlChunker i dodaj filtry.

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

Tworzenie zapytania do korpusu

Użyj metody QueryCorpusRequest, aby przeprowadzić wyszukiwanie semantyczne i uzyskać odpowiednie fragmenty.

  • results_count: określ liczbę fragmentów do zwrócenia. Maksymalna wartość to 100. Jeśli nie określono inaczej, interfejs API zwraca maksymalnie 10 elementów Chunk.
  • metadata_filters: filtruj według chunk_metadata lub document_metadata. Każdy element MetadataFilter musi odpowiadać niepowtarzalnemu kluczowi. Wiele obiektów MetadataFilter jest połączonych logicznymi AND. Podobne warunki filtra metadanych są połączone za pomocą logicznych elementów OR. Oto kilka przykładów:
(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} }]
  }]

Pamiętaj, że tylko wartości liczbowe obsługują operatory „ORAZ” dla tego samego klucza. Ciąg znaków obsługują tylko operator „LUB” dla tego samego klucza.

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

Przypisana odpowiedź na pytanie

Użyj metody GenerateAnswer, aby wykonać przypisane pytanie do swojego dokumentu, korpusu lub zbioru fragmentów.

Przypisywanie pytań i odpowiedzi (AQA) odnosi się do odpowiadania na pytania oparte na konkretnym kontekście i podawania informacji o źródłach przy jednoczesnym minimalizowaniu halucynacji.

GenerateAnswer ma kilka zalet w porównaniu z niedostrojonym LLM w przypadkach, gdy potrzebna jest AQA:

  • Bazowy model został wytrenowany tak, aby zwracał tylko odpowiedzi umocowane w podanym kontekście.
  • Identyfikuje źródła (segmenty podanego kontekstu, które przyczyniły się do odpowiedzi). Dzięki atrybucji użytkownik może zweryfikować odpowiedź.
  • Szacuje wartość answerable_probability dla danej pary (pytanie, kontekst), co pozwala dodatkowo dostosować działanie usługi w zależności od tego, jak bardzo prawdopodobna jest uzasadniona i prawidłowa odpowiedź.
.

answerable_probability i problem „Nie wiem”

W niektórych przypadkach najlepszą odpowiedzią na pytanie jest w rzeczywistości „Nie wiem”. Jeśli np. podany kontekst nie zawiera odpowiedzi na pytanie, zostanie ono uznane za „brak odpowiedzi”.

Model AQA świetnie sobie radzi z rozpoznawaniem takich przypadków. Potrafi nawet rozróżniać stopnie odpowiedzi i braku odpowiedzi.

Interfejs GenerateAnswer API daje jednak pełną kontrolę nad procesem decyzyjnym przez:

  • Zawsze staraj się zwrócić uzasadnioną odpowiedź – nawet jeśli jest mało prawdopodobne, aby była ona uzasadniona i prawidłowa.
  • Zwracanie wartości answerable_probability – oszacowane przez model prawdopodobieństwo, że odpowiedź jest ustalona i prawidłowa.

Niski wskaźnik answerable_probability może być spowodowany co najmniej jednym z tych czynników:

  • Model nie ma pewności, że jego odpowiedź jest poprawna.
  • Model nie ma pewności, że jego odpowiedź jest ugruntowana na cytowanych fragmentach. Odpowiedź może pochodzić zamiast od wiedzy o świecie. Na przykład: question="1+1=?", passages=["2+2=4”]answer=2, answerable_probability=0.02
  • Model dostarczył istotne informacje, które nie udzieliły pełnej odpowiedzi na pytanie. Przykład: 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"
  • W żądaniu GenerateAnswerRequest zadano poprawnie sformułowane pytanie.

Niska wartość answerable_probability wskazuje, że odpowiedź GenerateAnswer.answer jest prawdopodobnie nieprawidłowa lub nieuzasadniona, dlatego zdecydowanie zalecamy dalsze przetworzenie odpowiedzi przez sprawdzenie answerable_probability.

Gdy answerable_probability jest niski, niektórzy klienci mogą chcieć:

  • Wyświetla komunikat z komunikatem „Nie udało się odpowiedzieć na to pytanie” do użytkownika.
  • Wróćmy do ogólnego przeznaczenia LLM, które stanowi odpowiedź na pytanie wynikające z wiedzy z całego świata. Próg i charakter takich wartości zastępczych zależą od indywidualnych przypadków użycia. Wartość answerable_probability <= 0,5 jest dobrym progiem początkowym.

Przydatne wskazówki dotyczące AQA

Pełne specyfikacje interfejsu API znajdziesz w dokumentacji interfejsu API GenerateAnswerRequest.

  • Długość fragmentu: zalecamy użycie maksymalnie 300 tokenów na fragment.
  • Sortowanie fragmentów:
    • Jeśli podasz GenerateAnswerRequest.inline_passages, fragmenty powinny zostać posortowane w kolejności malejącej trafności względem zapytania. Jeśli limit długości kontekstu modelu zostanie przekroczony, ostatnie (najmniej istotne) fragmenty zostaną pominięte.
    • Jeśli podasz wartość GenerateAnswerRequest.semantic_retriever, sortowanie według trafności zostanie wykonane automatycznie.
  • Ograniczenia: model AQA jest przeznaczony do odpowiadania na pytania. Do innych zastosowań, takich jak pisanie kreatywne, streszczanie itp., wywołaj model ogólnego przeznaczenia w GenerateContent.
    • Google Chat: jeśli wiadomo, że dane wejściowe użytkownika są pytaniami, na które można odpowiedzieć w określonym kontekście, AQA może odpowiadać na pytania na czacie. Jeśli jednak dane wejściowe użytkownika mogą dotyczyć dowolnego typu wpisu, lepszym wyborem może być model ogólnego przeznaczenia.
  • Temperatura:
    • Aby uzyskać dokładną ocenę AQA, zalecana jest względnie niska temperatura (ok.0,2).
    • Jeśli Twój przypadek użycia zależy od danych wyjściowych, ustaw temperaturę=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)

Więcej opcji: AQA z użyciem ścieżek w tekście

Możesz też użyć punktu końcowego AQA bezpośrednio, bez użycia interfejsu Semantic retriever API, przekazując parametr inline_passages.

user_query = "What is AQA from Google?"
user_query_content = glm.Content(parts=[glm.Part(text=user_query)])
answer_style = "VERBOSE" # or ABSTRACTIVE, EXTRACTIVE
MODEL_NAME = "models/aqa"

# Create the grounding inline passages
grounding_passages = glm.GroundingPassages()
passage_a = glm.Content(parts=[glm.Part(text="Attributed Question and Answering (AQA) refers to answering questions grounded to a given corpus and providing citation")])
grounding_passages.passages.append(glm.GroundingPassage(content=passage_a, id="001"))
passage_b = glm.Content(parts=[glm.Part(text="An LLM is not designed to generate content grounded in a set of passages. Although instructing an LLM to answer questions only based on a set of passages reduces hallucination, hallucination still often occurs when LLMs generate responses unsupported by facts provided by passages")])
grounding_passages.passages.append(glm.GroundingPassage(content=passage_b, id="002"))
passage_c = glm.Content(parts=[glm.Part(text="Hallucination is one of the biggest problems in Large Language Models (LLM) development. Large Language Models (LLMs) could produce responses that are fictitious and incorrect, which significantly impacts the usefulness and trustworthiness of applications built with language models.")])
grounding_passages.passages.append(glm.GroundingPassage(content=passage_c, id="003"))

# Create the request
req = glm.GenerateAnswerRequest(model=MODEL_NAME,
                                contents=[user_query_content],
                                inline_passages=grounding_passages,
                                answer_style=answer_style)
aqa_response = generative_service_client.generate_answer(req)
print(aqa_response)

Udostępnianie korpusu

Możesz udostępnić korpus innym osobom za pomocą interfejsu API CreatePermissionRequest.

Ograniczenia:

  • Dostępne są 2 role: READER i EDITOR.
    • READER może wysyłać zapytania do korpusu.
    • WRITER ma uprawnienia odczytującego, a dodatkowo może edytować i udostępniać korpus.
  • Korpus może być publiczny, jeśli przyznasz EVERYONE jako user_type uprawnienia do odczytu.
# 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)

Usuwanie korpusu

Użyj narzędzia DeleteCorpusRequest, aby usunąć korpus użytkownika wraz ze wszystkimi powiązanymi zbiorami Document i Chunk s

Pamiętaj, że niepusty korpus wywoła błąd bez określenia flagi force=True. Jeśli ustawisz force=True, wszystkie Chunk i obiekty powiązane z tym Document również zostaną usunięte.

Jeśli force=False (domyślna) i Document zawiera wartości Chunk, zostanie zwrócony błąd 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)

Podsumowanie i dalsze materiały

W tym przewodniku przedstawiliśmy moduł odbioru danych semantycznych oraz przypisane pytania Interfejsy API odpowiedzi (AQA) interfejsu Generative Language API oraz sposoby pobierania informacji semantycznych z niestandardowych danych tekstowych. Pamiętaj, że ten interfejs API współpracuje też z platformą danych LlamaIndex. Więcej informacji znajdziesz w samouczku.

Więcej informacji o innych dostępnych funkcjach znajdziesz w dokumentacji interfejsu API.

Dodatek: skonfiguruj protokół OAuth z danymi logowania użytkownika

Wykonaj czynności opisane poniżej w krótkim wprowadzeniu do protokołu OAuth, aby skonfigurować uwierzytelnianie OAuth.

  1. Skonfiguruj ekran zgody OAuth

  2. Autoryzuj dane logowania w aplikacji komputerowej. Aby uruchomić ten notatnik w Colab, najpierw zmień nazwę pliku danych logowania (zwykle client_secret_*.json) na client_secret.json. Następnie prześlij plik, klikając ikonę pliku na lewym pasku bocznym, a następnie ikonę przesyłania (jak widać na zrzucie ekranu poniżej).

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

Zainicjuj bibliotekę klienta i ponownie uruchom notatnik, zaczynając od tworzenia korpusu.

import google.ai.generativelanguage as glm

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