시맨틱 검색 시작하기

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

개요

대규모 언어 모델 (LLM)은 직접 학습을 받지 않고도 새로운 기능을 학습할 수 있습니다. 하지만 LLM은 '할루시네이션'이라고 알려져 있다. 할 수 있습니다. 이는 LLM이 학습 후에 이벤트를 인식하지 못하기 때문입니다. 또한 LLM이 응답을 가져오는 출처를 추적하는 것도 매우 어렵습니다. 안정적이고 확장 가능한 애플리케이션의 경우 LLM이 사실에 근거하고 정보 출처를 인용할 수 있는 응답을 제공하는 것이 중요합니다.

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

이 노트북은 외부 텍스트 코퍼스로 지식을 보강하고 시맨틱 정보 검색을 수행하여 시맨틱 검색기 및 기여 분석 질문 및 Generative Language API의 Answering (AQA) API입니다.

설정

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는 키-값 쌍으로 지정된 사용자 지정 custom_metadata 필드를 최대 20개까지 지원합니다. 커스텀 메타데이터는 문자열, 문자열 목록 또는 숫자일 수 있습니다. 문자열 목록은 최대 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을 직접 읽지만 렌더링 후 HTML을 가져와 JavaScript가 삽입된 HTML을 포함시키는 것이 더 나음 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")

텍스트 문서를 여러 문구로 나누고 이 문구에서 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를 페이지당 최대 크기 제한이 100Chunk이고 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개의 토큰이 권장됩니다.
  • 문구 정렬: <ph type="x-smartling-placeholder">
  • 제한사항: AQA 모델은 질문 답변에 특화되어 있습니다. 창의적 글쓰기, 요약과 같은 다른 사용 사례의 경우 GenerateContent를 통해 범용 모델을 호출하세요.
    • 채팅: 사용자 입력이 특정 맥락에서 답변할 수 있는 질문인 것으로 알려진 경우 AQA는 채팅 쿼리에 답변할 수 있습니다. 그러나 사용자 입력이 어떤 유형이든 간에 가능하다면 범용 모델이 더 나은 선택일 수 있습니다.
  • 온도: <ph type="x-smartling-placeholder">
      </ph>
    • 일반적으로 정확한 AQA를 위해 상대적으로 낮은 (~0.2) 온도가 권장됩니다.
    • 사용 사례가 확정적인 출력을 사용하는 경우 강도=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)

요약 및 추가 자료

이 가이드에서는 시맨틱 검색기와 기여 질문 및 Generative Language API의 Answering (AQA) 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()