시맨틱 검색 시작하기

ai.google.dev에서 보기 Colab 노트북 사용해 보기 GitHub에서 노트북 보기

개요

대규모 언어 모델 (LLM)은 새로운 기능에 대해 직접 학습하지 않고도 새로운 기능을 학습할 수 있습니다. 그러나 LLM은 학습하지 않은 질문에 대한 답변을 제공하는 작업을 수행할 때 '환각'을 일으키는 것으로 알려져 있습니다. 이는 LLM이 학습 후 이벤트를 인식하지 못하기 때문입니다. 또한 LLM이 대답을 가져오는 소스를 추적하는 것도 매우 어렵습니다. 안정적이고 확장 가능한 애플리케이션의 경우 LLM이 사실에 근거하고 정보 출처를 인용할 수 있는 응답을 제공하는 것이 중요합니다.

이러한 제약조건을 극복하는 데 사용되는 일반적인 접근 방식은 검색 증강 생성 (RAG)이라고 하며, 이는 정보 검색 (IR) 메커니즘을 통해 외부 기술 자료에서 검색된 관련 데이터로 LLM에 전송된 프롬프트를 보강합니다. 기술 자료는 문서, 데이터베이스 또는 API의 자체 코퍼스가 될 수 있습니다.

이 노트북에서는 외부 텍스트 자료로 지식을 보강하고 생성형 언어 API의 Semantic Retriever 및 AQA (Attributed Question & Answering) API를 사용하여 질문에 답변하기 위한 시맨틱 정보 검색을 실행하여 LLM의 응답을 개선하는 워크플로를 안내합니다.

설정

Generative Language API 가져오기

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

인증

Semantic Retriever API를 사용하면 자체 데이터에 시맨틱 검색을 실행할 수 있습니다. 사용자의 데이터이므로 API 키보다 더 엄격한 액세스 제어가 필요합니다. 서비스 계정 또는 사용자 인증 정보를 통해 OAuth로 인증합니다.

이 빠른 시작에서는 테스트 환경을 위한 간소화된 인증 접근 방식을 사용하며, 서비스 계정 설정은 일반적으로 더 쉽게 시작할 수 있습니다. 프로덕션 환경의 경우 앱에 적합한 액세스 사용자 인증 정보를 선택하기 전에 인증 및 승인에 관해 알아보세요.

서비스 계정을 사용하여 OAuth 설정

서비스 계정을 사용하여 OAuth를 설정하려면 다음 단계를 따르세요.

  1. Generative Language API를 사용 설정합니다.

  1. 문서에 따라 서비스 계정을 만듭니다.

    • 서비스 계정을 만든 후 서비스 계정 키를 생성합니다.

  1. 아래 스크린샷과 같이 왼쪽 사이드바의 파일 아이콘과 업로드 아이콘을 차례로 사용하여 서비스 계정 파일을 업로드합니다.

    • 업로드한 파일의 이름을 service_account_key.json로 바꾸거나 아래 코드에서 service_account_file_name 변수를 변경합니다.

pip install -U google-auth-oauthlib
service_account_file_name = 'service_account_key.json'

from google.oauth2 import service_account

credentials = service_account.Credentials.from_service_account_file(service_account_file_name)

scoped_credentials = credentials.with_scopes(
    ['https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/generative-language.retriever'])

서비스 계정 사용자 인증 정보를 사용하여 클라이언트 라이브러리를 초기화합니다.

import google.ai.generativelanguage as glm
generative_service_client = glm.GenerativeServiceClient(credentials=scoped_credentials)
retriever_service_client = glm.RetrieverServiceClient(credentials=scoped_credentials)
permission_service_client = glm.PermissionServiceClient(credentials=scoped_credentials)

코퍼스 만들기

Semantic Retriever API를 사용하면 프로젝트당 최대 5개의 커스텀 텍스트 코퍼스를 정의할 수 있습니다. 코퍼스를 정의할 때 다음 필드 중 하나를 지정할 수 있습니다.

  • name: Corpus 리소스 이름 (ID)입니다. 영숫자 문자 최대 40자(영문 기준)만 포함할 수 있습니다. 생성 시 name가 비어 있으면 최대 40자(영문 기준)의 고유 이름이 생성되며 display_name의 접두사와 12자리 임의 접미사가 추가됩니다.
  • display_name: 사람이 읽을 수 있는 Corpus의 표시 이름입니다. 영숫자, 공백, 대시를 포함하여 최대 512자(영문 기준)만 포함할 수 있습니다.
example_corpus = glm.Corpus(display_name="Google for Developers Blog")
create_corpus_request = glm.CreateCorpusRequest(corpus=example_corpus)

# Make the request
create_corpus_response = retriever_service_client.create_corpus(create_corpus_request)

# Set the `corpus_resource_name` for subsequent sections.
corpus_resource_name = create_corpus_response.name
print(create_corpus_response)
name: "corpora/google-for-developers-blog-dqrtz8rs0jg"
display_name: "Google for Developers Blog"
create_time {
  seconds: 1713497533
  nanos: 587977000
}
update_time {
  seconds: 1713497533
  nanos: 587977000
}

생성된 코퍼스 가져오기

GetCorpusRequest 메서드를 사용하여 위에서 만든 Corpus에 프로그래매틱 방식으로 액세스합니다. name 매개변수의 값은 Corpus의 전체 리소스 이름을 참조하며 위 셀에서 corpus_resource_name로 설정됩니다. 예상되는 형식은 corpora/corpus-123입니다.

get_corpus_request = glm.GetCorpusRequest(name=corpus_resource_name)

# Make the request
get_corpus_response = retriever_service_client.get_corpus(get_corpus_request)

# Print the response
print(get_corpus_response)

문서 새로 만들어 줘

Corpus는 최대 10,000개의 Document를 포함할 수 있습니다. 문서를 정의할 때 다음 필드 중 하나를 지정할 수 있습니다.

  • name: Document 리소스 이름 (ID)입니다. 최대 40자(영문 기준)(영숫자 또는 대시만)를 포함해야 합니다. ID는 대시로 시작하거나 끝날 수 없습니다. 생성 시 이름이 비어 있으면 display_name에서 12자 길이의 임의의 접미사와 함께 고유한 이름이 파생됩니다.
  • display_name: 인간이 읽을 수 있는 표시 이름입니다. 영숫자, 공백, 대시를 포함하여 최대 512자(영문 기준)만 포함해야 합니다.

Document는 키-값 쌍으로 지정된 사용자 지정 custom_metadata 필드를 최대 20개까지 지원합니다. 커스텀 메타데이터는 문자열, 문자열 목록 또는 숫자일 수 있습니다. 문자열 목록은 최대 10개의 값을 지원할 수 있으며 숫자 값은 API에서 부동 소수점 수로 표시됩니다.

# Create a document with a custom display name.
example_document = glm.Document(display_name="Introducing Project IDX, An Experiment to Improve Full-stack, Multiplatform App Development")

# Add metadata.
# Metadata also supports numeric values not specified here
document_metadata = [
    glm.CustomMetadata(key="url", string_value="https://developers.googleblog.com/2023/08/introducing-project-idx-experiment-to-improve-full-stack-multiplatform-app-development.html")]
example_document.custom_metadata.extend(document_metadata)

# Make the request
# corpus_resource_name is a variable set in the "Create a corpus" section.
create_document_request = glm.CreateDocumentRequest(parent=corpus_resource_name, document=example_document)
create_document_response = retriever_service_client.create_document(create_document_request)

# Set the `document_resource_name` for subsequent sections.
document_resource_name = create_document_response.name
print(create_document_response)

생성된 문서 가져오기

GetDocumentRequest 메서드를 사용하여 위에서 만든 문서에 프로그래매틱 방식으로 액세스합니다. name 매개변수의 값은 문서의 전체 리소스 이름을 참조하며 위의 셀에서 document_resource_name로 설정됩니다. 예상되는 형식은 corpora/corpus-123/documents/document-123입니다.

get_document_request = glm.GetDocumentRequest(name=document_resource_name)

# Make the request
# document_resource_name is a variable set in the "Create a document" section.
get_document_response = retriever_service_client.get_document(get_document_request)

# Print the response
print(get_document_response)

문서 처리 및 청크 처리

시맨틱 검색 중에 벡터 데이터베이스에서 반환되는 콘텐츠의 관련성을 개선하려면 문서를 처리하는 동안 대규모 문서를 더 작은 부분 또는 청크로 분할합니다.

Chunk는 벡터 표현 및 저장을 위해 독립된 단위로 취급되는 Document의 하위 부분입니다. Chunk는 최대 2,043개의 토큰을 보유할 수 있습니다. Corpus는 최대 100만 개의 Chunk를 보유할 수 있습니다.

Document와 마찬가지로 Chunks는 키-값 쌍으로 지정된 최대 20개의 사용자 지정 custom_metadata 필드도 지원합니다. 맞춤 메타데이터는 문자열, 문자열 목록 또는 숫자일 수 있습니다. 문자열 목록은 최대 10개의 값을 지원할 수 있으며 숫자 값은 API에서 부동 소수점 수로 표시됩니다.

이 가이드에서는 Google의 오픈소스 HtmlChunker를 사용합니다.

사용할 수 있는 다른 청커로는 LangChain 또는 LlamaIndex가 있습니다.

HtmlChunker를 통해 HTML 처리 및 청크 처리

!pip install google-labs-html-chunker

from google_labs_html_chunker.html_chunker import HtmlChunker

from urllib.request import urlopen

웹사이트의 HTML DOM을 가져옵니다. 여기서는 HTML이 직접 읽히지만 document.documentElement.innerHTML와 같은 JavaScript 삽입 HTML을 포함하도록 HTML 렌더링 후를 가져오는 것이 좋습니다.

with(urlopen("https://developers.googleblog.com/2023/08/introducing-project-idx-experiment-to-improve-full-stack-multiplatform-app-development.html")) as f:
  html = f.read().decode("utf-8")

텍스트 문서를 구절로 나누고 이러한 구절에서 Chunk를 만듭니다. 이 단계에서는 Chunk 객체 자체를 만들고 다음 섹션에서는 이를 Semantic Retriever API에 업로드합니다.

# Chunk the file using HtmlChunker
chunker = HtmlChunker(
    max_words_per_aggregate_passage=200,
    greedily_aggregate_sibling_nodes=True,
    html_tags_to_exclude={"noscript", "script", "style"},
)
passages = chunker.chunk(html)
print(passages)


# Create `Chunk` entities.
chunks = []
for passage in passages:
    chunk = glm.Chunk(data={'string_value': passage})
    # Optionally, you can add metadata to a chunk
    chunk.custom_metadata.append(glm.CustomMetadata(key="tags",
                                                    string_list_value=glm.StringList(
                                                        values=["Google For Developers", "Project IDX", "Blog", "Announcement"])))
    chunk.custom_metadata.append(glm.CustomMetadata(key="chunking_strategy",
                                                    string_value="greedily_aggregate_sibling_nodes"))
    chunk.custom_metadata.append(glm.CustomMetadata(key = "publish_date",
                                                    numeric_value = 20230808))
    chunks.append(chunk)
print(chunks)

청크 일괄 생성

청크를 일괄로 만듭니다. 일괄 요청당 최대 100개의 청크를 지정할 수 있습니다.

단일 단위 생성에는 CreateChunk()를 사용합니다.

# Option 1: Use HtmlChunker in the section above.
# `chunks` is the variable set from the section above.
create_chunk_requests = []
for chunk in chunks:
  create_chunk_requests.append(glm.CreateChunkRequest(parent=document_resource_name, chunk=chunk))

# Make the request
request = glm.BatchCreateChunksRequest(parent=document_resource_name, requests=create_chunk_requests)
response = retriever_service_client.batch_create_chunks(request)
print(response)

또는 HtmlChunker를 사용하지 않고도 청크를 만들 수 있습니다.

# Add up to 100 CreateChunk requests per batch request.
# document_resource_name is a variable set in the "Create a document" section.
chunks = []
chunk_1 = glm.Chunk(data={'string_value': "Chunks support user specified metadata."})
chunk_1.custom_metadata.append(glm.CustomMetadata(key="section",
                                                  string_value="Custom metadata filters"))
chunk_2 = glm.Chunk(data={'string_value': "The maximum number of metadata supported is 20"})
chunk_2.custom_metadata.append(glm.CustomMetadata(key = "num_keys",
                                                  numeric_value = 20))
chunks = [chunk_1, chunk_2]
create_chunk_requests = []
for chunk in chunks:
  create_chunk_requests.append(glm.CreateChunkRequest(parent=document_resource_name, chunk=chunk))

# Make the request
request = glm.BatchCreateChunksRequest(parent=document_resource_name, requests=create_chunk_requests)
response = retriever_service_client.batch_create_chunks(request)
print(response)

Chunk 나열 및 상태 가져오기

ListChunksRequest 메서드를 사용하여 사용 가능한 모든 Chunk를 페이지당 최대 100개의 Chunk로 제한된 페이지로 나뉘는 목록으로 가져오고 Chunk.create_time의 오름차순으로 정렬합니다. 한도를 지정하지 않으면 최대 10개의 Chunk가 반환됩니다.

ListChunksRequest 응답에서 반환된 next_page_token를 다음 요청의 인수로 제공하여 다음 페이지를 가져옵니다. 페이지로 나누는 경우, ListChunks에 제공하는 다른 모든 매개변수가 페이지 토큰을 제공한 호출과 일치해야 합니다.

모든 Chunkstate를 반환합니다. Corpus를 쿼리하기 전에 Chunks의 상태를 확인하는 데 사용합니다. Chunk 상태에는 UNSPECIFIED, PENDING_PROCESSING, ACTIVE, FAILED가 포함됩니다. ACTIVE Chunk만 쿼리할 수 있습니다.

# Make the request
request = glm.ListChunksRequest(parent=document_resource_name)
list_chunks_response = retriever_service_client.list_chunks(request)
for index, chunks in enumerate(list_chunks_response.chunks):
  print(f'\nChunk # {index + 1}')
  print(f'Resource Name: {chunks.name}')
  # Only ACTIVE chunks can be queried.
  print(f'State: {glm.Chunk.State(chunks.state).name}')

다른 문서 처리

HtmlChunker를 통해 Document를 추가하고 필터를 추가합니다.

# Create a document with a custom display name.
example_document = glm.Document(display_name="How it’s Made: Interacting with Gemini through multimodal prompting")

# Add document metadata.
# Metadata also supports numeric values not specified here
document_metadata = [
    glm.CustomMetadata(key="url", string_value="https://developers.googleblog.com/2023/12/how-its-made-gemini-multimodal-prompting.html")]
example_document.custom_metadata.extend(document_metadata)

# Make the CreateDocument request
# corpus_resource_name is a variable set in the "Create a corpus" section.
create_document_request = glm.CreateDocumentRequest(parent=corpus_resource_name, document=example_document)
create_document_response = retriever_service_client.create_document(create_document_request)

# Set the `document_resource_name` for subsequent sections.
document_resource_name = create_document_response.name
print(create_document_response)

# Chunks - add another webpage from Google for Developers
with(urlopen("https://developers.googleblog.com/2023/12/how-its-made-gemini-multimodal-prompting.html")) as f:
  html = f.read().decode("utf-8")

# Chunk the file using HtmlChunker
chunker = HtmlChunker(
    max_words_per_aggregate_passage=100,
    greedily_aggregate_sibling_nodes=False,
)
passages = chunker.chunk(html)

# Create `Chunk` entities.
chunks = []
for passage in passages:
    chunk = glm.Chunk(data={'string_value': passage})
    chunk.custom_metadata.append(glm.CustomMetadata(key="tags",
                                                    string_list_value=glm.StringList(
                                                        values=["Google For Developers", "Gemini API", "Blog", "Announcement"])))
    chunk.custom_metadata.append(glm.CustomMetadata(key="chunking_strategy",
                                                    string_value="no_aggregate_sibling_nodes"))
    chunk.custom_metadata.append(glm.CustomMetadata(key = "publish_date",
                                                    numeric_value = 20231206))
    chunks.append(chunk)

# Make the request
create_chunk_requests = []
for chunk in chunks:
  create_chunk_requests.append(glm.CreateChunkRequest(parent=document_resource_name, chunk=chunk))
request = glm.BatchCreateChunksRequest(parent=document_resource_name, requests=create_chunk_requests)
response = retriever_service_client.batch_create_chunks(request)
print(response)

코퍼스 쿼리

QueryCorpusRequest 메서드를 사용하여 시맨틱 검색을 수행하여 관련 구절을 가져옵니다.

  • results_count: 반환할 구절 수를 지정합니다. 최대는 100입니다. 지정하지 않으면 API는 최대 10개의 Chunk를 반환합니다.
  • metadata_filters: chunk_metadata 또는 document_metadata로 필터링합니다. 각 MetadataFilter는 고유한 키에 해당해야 합니다. 여러 개의 MetadataFilter 객체는 논리적 AND로 조인됩니다. 유사한 메타데이터 필터 조건이 논리적 OR로 조인됩니다. 예를 들면 다음과 같습니다.
(year >= 2020 OR year < 2010) AND (genre = drama OR genre = action)

metadata_filter = [
  {
    key = "document.custom_metadata.year"
    conditions = [
      {int_value = 2020, operation = GREATER_EQUAL},
      {int_value = 2010, operation = LESS}]
  },
  {
    key = "document.custom_metadata.genre"
    conditions = [
      {string_value = "drama", operation = EQUAL},
      {string_value = "action", operation = EQUAL} }]
  }]

숫자 값만 동일한 키에 'AND'를 지원합니다. 문자열 값은 동일한 키에 대해서만 'OR'을 지원합니다.

("Google for Developers" in tags) and (20230314 > publish_date)

metadata_filter = [
 {
    key = "chunk.custom_metadata.tags"
    conditions = [
    {string_value = 'Google for Developers', operation = INCLUDES},
  },
  {
    key = "chunk.custom_metadata.publish_date"
    conditions = [
    {numeric_value = 20230314, operation = GREATER_EQUAL}]
  }]
user_query = "What is the purpose of Project IDX?"
results_count = 5

# Add metadata filters for both chunk and document.
chunk_metadata_filter = glm.MetadataFilter(key='chunk.custom_metadata.tags',
                                           conditions=[glm.Condition(
                                              string_value='Google For Developers',
                                              operation=glm.Condition.Operator.INCLUDES)])

# Make the request
# corpus_resource_name is a variable set in the "Create a corpus" section.
request = glm.QueryCorpusRequest(name=corpus_resource_name,
                                 query=user_query,
                                 results_count=results_count,
                                 metadata_filters=[chunk_metadata_filter])
query_corpus_response = retriever_service_client.query_corpus(request)
print(query_corpus_response)

기여 질문-답변

GenerateAnswer 메서드를 사용하여 문서, 자료 또는 구절 집합에 대해 저자 표시 질문-답변을 실행합니다.

기여 질의응답(AQA)이란 할루시네이션을 최소화하면서 주어진 맥락에 근거한 질문에 답하고 출처를 제공하는 것을 의미합니다.

GenerateAnswer는 AQA가 필요한 경우 조정되지 않은 LLM을 사용하는 것보다 몇 가지 이점이 있습니다.

  • 기본 모델은 제공된 컨텍스트에 기반한 답변만 반환하도록 학습되었습니다.
  • 기여 분석 (답변에 기여한 제공된 컨텍스트의 세그먼트)을 식별합니다. 저작자 표시를 통해 사용자는 답변을 확인할 수 있습니다.
  • 주어진 (질문, 컨텍스트) 쌍의 answerable_probability를 추정하여 반환된 답변이 근거가 있고 올바를 가능성에 따라 제품 동작을 전환할 수 있습니다.

answerable_probability 및 '모르겠음' 문제

경우에 따라 질문에 대한 가장 좋은 대답은 '모릅니다'일 수 있습니다. 예를 들어 제공된 맥락에 질문에 대한 답변이 포함되지 않은 경우 질문은 '답변할 수 없는 질문'으로 간주됩니다.

AQA 모델은 이러한 케이스를 매우 잘 인식합니다. 심지어 응답 가능성과 응답 불가능 정도를 구분할 수도 있습니다.

그러나 GenerateAnswer API를 사용하면 다음과 같이 최종 결정권을 가질 수 있습니다.

  • 근거가 있고 올바를 가능성이 상대적으로 낮은 답변이라도 항상 근거가 있는 답변을 반환하려고 시도합니다.
  • answerable_probability 반환 - 답변이 근거가 있고 올바를 확률에 대한 모델의 추정치입니다.

낮은 answerable_probability는 다음 요인 중 하나 이상으로 설명될 수 있습니다.

  • 모델이 답변이 정확하다고 확신하지 못합니다.
  • 모델이 해당 답변이 인용된 문구를 근거로 한다고 확신하지 않습니다. 답은 세계 지식에서 도출된 것일 수 있습니다. 예: question="1+1=?", passages=["2+2=4”]answer=2, answerable_probability=0.02
  • 모델이 질문에 완벽하게 답변하지 않는 관련 정보를 제공했습니다. 예: question="Is it available in my size?, passages=["Available in sizes 5-11"]answer="Yes it is available in sizes 5-11", answerable_probability=0.03"
  • GenerateAnswerRequest에 올바른 형식의 질문이 포함되지 않았습니다.

answerable_probability가 낮으면 GenerateAnswerResponse.answer가 잘못되었거나 근거가 없는 것일 수 있으므로 answerable_probability를 검사하여 응답을 추가로 처리하는 것이 좋습니다.

answerable_probability이 낮으면 일부 클라이언트는 다음을 수행할 수 있습니다.

  • 최종 사용자에게 '이 질문에 답변할 수 없습니다'와 같은 메시지를 표시합니다.
  • 세계 지식에서 질문에 답하는 범용 LLM으로 대체합니다. 이러한 대체의 기준점과 특성은 개별 사용 사례에 따라 다릅니다. answerable_probability 값이 0.5 이하인 것이 좋습니다.

AQA 유용한 도움말

전체 API 사양은 GenerateAnswerRequest API 참조를 참고하세요.

  • 문구 길이: 문구당 최대 300개의 토큰이 권장됩니다.
  • 구절 정렬:
  • 제한사항: AQA 모델은 질문 답변에 특화되어 있습니다. 창의적 작문, 요약 등 다른 사용 사례의 경우 GenerateContent를 통해 범용 모델을 호출하세요.
    • 채팅: 사용자 입력이 특정 맥락에서 답변할 수 있는 질문인 것으로 알려진 경우 AQA는 채팅 쿼리에 답변할 수 있습니다. 하지만 사용자 입력이 어떤 유형의 항목이든 될 수 있다면 범용 모델이 더 나은 선택일 수 있습니다.
  • 온도:
    • 일반적으로 정확한 AQA를 위해 상대적으로 낮은 (~0.2) 온도를 사용하는 것이 좋습니다.
    • 사용 사례에서 확정적인 출력을 사용하는 경우 temperature=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)

추가 옵션: 인라인 구문 사용 AQA

또는 inline_passages를 전달하여 Semantic Retriever API를 사용하지 않고 AQA 엔드포인트를 직접 사용할 수 있습니다.

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

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

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

코퍼스 공유

CreatePermissionRequest API를 사용하여 자료 모음을 다른 사용자와 공유할 수 있습니다.

제약조건:

  • 공유에는 READEREDITOR의 2가지 역할이 있습니다.
    • READER는 코퍼스를 쿼리할 수 있습니다.
    • WRITER에는 읽기 권한이 있으며 추가로 코퍼스를 수정하고 공유할 수 있습니다.
  • EVERYONEuser_type 읽기 액세스 권한을 부여하여 자료집을 공개할 수 있습니다.
# Replace your-email@gmail.com with the email added as a test user in the OAuth Quickstart
shared_user_email = "TODO-your-email@gmail.com" #  @param {type:"string"}
user_type = "USER"
role = "READER"

# Make the request
# corpus_resource_name is a variable set in the "Create a corpus" section.
request = glm.CreatePermissionRequest(
    parent=corpus_resource_name,
    permission=glm.Permission(grantee_type=user_type,
                              email_address=shared_user_email,
                              role=role))
create_permission_response = permission_service_client.create_permission(request)
print(create_permission_response)

자료 삭제

DeleteCorpusRequest를 사용하여 사용자 자료와 연결된 모든 DocumentChunk를 삭제합니다.

비어 있지 않은 자료집은 force=True 플래그를 지정하지 않으면 오류가 발생합니다. force=True를 설정하면 이 Document와 관련된 모든 Chunk 및 객체도 삭제됩니다.

force=False (기본값) 및 DocumentChunk가 포함되어 있으면 FAILED_PRECONDITION 오류가 반환됩니다.

# Set force to False if you don't want to delete non-empty corpora.
req = glm.DeleteCorpusRequest(name=corpus_resource_name, force=True)
delete_corpus_response = retriever_service_client.delete_corpus(req)
print("Successfully deleted corpus: " + corpus_resource_name)

요약 및 추가 자료

이 가이드에서는 생성형 언어 API의 Semantic Retriever 및 AQA (Attributed Question & Answering) API를 소개하고 이를 사용하여 맞춤 텍스트 데이터에서 의미 정보 검색을 실행하는 방법을 설명했습니다. 이 API는 LlamaIndex 데이터 프레임워크에서도 작동합니다. 자세한 내용은 튜토리얼을 참고하세요.

사용 가능한 다른 기능에 대한 자세한 내용은 API 문서를 참고하세요.

부록: 사용자 사용자 인증 정보로 OAuth 설정

OAuth 빠른 시작의 아래 단계에 따라 OAuth 인증을 설정합니다.

  1. OAuth 동의 화면 구성

  2. 데스크톱 애플리케이션의 사용자 인증 정보 승인 Colab에서 이 노트북을 실행하려면 먼저 사용자 인증 정보 파일 (일반적으로 client_secret_*.json)의 이름을 client_secret.json로 바꿉니다. 그런 다음 아래 스크린샷과 같이 왼쪽 사이드바의 파일 아이콘과 업로드 아이콘을 차례로 사용하여 파일을 업로드합니다.

# Replace TODO-your-project-name with the project used in the OAuth Quickstart
project_name = "TODO-your-project-name" #  @param {type:"string"}
# Replace TODO-your-email@gmail.com with the email added as a test user in the OAuth Quickstart
email = "TODO-your-email@gmail.com" #  @param {type:"string"}
# Rename the uploaded file to `client_secret.json` OR
# Change the variable `client_file_name` in the code below.
client_file_name = "client_secret.json"

# IMPORTANT: Follow the instructions from the output - you must copy the command
# to your terminal and copy the output after authentication back here.
!gcloud config set project $project_name
!gcloud config set account $email

# NOTE: The simplified project setup in this tutorial triggers a "Google hasn't verified this app." dialog.
# This is normal, click "Advanced" -> "Go to [app name] (unsafe)"
!gcloud auth application-default login --no-browser --client-id-file=$client_file_name --scopes="https://www.googleapis.com/auth/generative-language.retriever,https://www.googleapis.com/auth/cloud-platform"

클라이언트 라이브러리를 초기화하고 코퍼스 만들기부터 노트북을 다시 실행합니다.

import google.ai.generativelanguage as glm

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