LLM 기반 QA 시스템을 위한 새로운 문서 요약 색인

May 09 2023
이 블로그 게시물에서는 완전히 새로운 LlamaIndex 데이터 구조인 문서 요약 인덱스를 소개합니다. 전통적인 시맨틱 검색에 비해 더 나은 검색 성능을 제공하는 데 어떻게 도움이 되는지 설명하고 예제를 살펴봅니다.

이 블로그 게시물에서는 완전히 새로운 LlamaIndex 데이터 구조인 문서 요약 인덱스를 소개합니다. 전통적인 시맨틱 검색에 비해 더 나은 검색 성능을 제공하는 데 어떻게 도움이 되는지 설명하고 예제를 살펴봅니다.

배경

대규모 언어 모델(LLM)의 핵심 사용 사례 중 하나는 자신의 데이터에 대한 질문 답변입니다. 이를 위해 LLM을 지식 코퍼스에 대한 정보 검색을 수행할 수 있는 "검색" 모델과 페어링하고 LLM을 사용하여 검색된 텍스트에 대한 응답 합성을 수행합니다. 이 전체 프레임워크를 Retrieval-Augmented Generation이라고 합니다.

오늘날 LLM 기반 QA 시스템을 구축하는 대부분의 사용자는 다음과 같은 형식을 수행하는 경향이 있습니다.

  1. 소스 문서를 가져 와서 각각을 텍스트 덩어리로 나눕니다.
  2. 벡터 db에 텍스트 청크 저장
  3. 쿼리 시간 동안 유사성 및/또는 키워드 필터를 포함하여 텍스트 청크를 검색합니다.
  4. 응답 합성 수행

기존 접근법의 한계

텍스트 청크를 사용하여 임베딩 검색에는 몇 가지 제한 사항이 있습니다.

  • 텍스트 청크에는 전역 컨텍스트가 없습니다. 종종 질문에는 특정 청크에 인덱싱된 것 이상의 컨텍스트가 필요합니다.
  • top-k/유사성 점수 임계값을 신중하게 조정합니다. 값을 너무 작게 설정하면 컨텍스트를 놓치게 됩니다. 값을 너무 크게 설정하면 관련 없는 컨텍스트로 인해 비용/대기 시간이 증가할 수 있습니다.
  • 임베딩이 항상 질문에 대해 가장 관련성이 높은 컨텍스트를 선택하는 것은 아닙니다. 임베딩은 본질적으로 텍스트와 컨텍스트 간에 별도로 결정됩니다.

문서 요약 색인

문서 요약 색인에 대한 다이어그램

우리는 LlamaIndex 에서 각 문서에 대한 구조화되지 않은 텍스트 요약을 추출/인덱싱할 새 인덱스를 제안합니다 . 이 인덱스는 기존 검색 접근 방식을 넘어 검색 성능을 향상시키는 데 도움이 될 수 있습니다. 단일 텍스트 청크보다 더 많은 정보를 인덱싱하는 데 도움이 되며 키워드 태그보다 더 많은 의미론적 의미를 전달합니다. 또한 보다 유연한 형태의 검색이 가능합니다. LLM 검색과 임베딩 기반 검색을 모두 수행할 수 있습니다.

작동 방식

빌드 시간 동안 각 문서를 수집하고 LLM을 사용하여 각 문서에서 요약을 추출합니다. 또한 문서를 텍스트 청크(노드)로 분할합니다. 요약과 노드는 모두 문서 저장소 추상화 내에 저장됩니다. 요약에서 소스 문서/노드로의 매핑을 유지합니다.

쿼리 시간 동안 다음 접근 방식을 사용하여 요약을 기반으로 쿼리에 대한 관련 문서를 검색합니다.

  • LLM 기반 검색: LLM에 문서 요약 세트를 제공하고 LLM에 어떤 문서가 관련성이 있는지 + 해당 관련성 점수를 결정하도록 요청합니다.
  • 임베딩 기반 검색: 요약 임베딩 유사성(top-k 컷오프 포함)을 기반으로 관련 문서를 검색합니다.

문서 요약을 저장하면 LLM 기반 검색 도 가능합니다 . 처음에 전체 문서를 LLM에 공급하는 대신 먼저 LLM이 간결한 문서 요약을 검사하여 쿼리와 관련이 있는지 확인할 수 있습니다. 이는 임베딩 기반 조회보다 더 발전된 LLM의 추론 기능을 활용하지만 전체 문서를 LLM에 공급하는 비용/지연 시간을 방지합니다.

추가 통찰력

요약을 사용한 문서 검색은 모든 문서에서 시맨틱 검색과 무차별 대입 요약 사이의 "중간 지점"으로 생각할 수 있습니다. 주어진 쿼리로 요약 관련성을 기반으로 문서를 조회한 다음 검색된 문서에 해당하는 모든 *노드*를 반환합니다.

왜 우리가 이것을 해야 합니까? 이 검색 방법은 문서 수준에서 컨텍스트를 검색하여 사용자에게 텍스트 청크에 대한 top-k보다 더 많은 컨텍스트를 제공합니다. 그러나 주제 모델링보다 더 유연하고 자동적인 접근 방식이기도 합니다. 텍스트에 올바른 키워드 태그가 있는지 더 이상 걱정할 필요가 없습니다!

여러 도시에 대한 Wikipedia 기사에 대한 문서 요약 색인을 보여주는 예를 살펴보겠습니다.

이 가이드의 나머지 부분에서는 관련 코드 스니펫을 보여줍니다. 여기에서 전체 연습을 찾을 수 있습니다 (여기에 노트북 링크가 있습니다 ).

GPTDocumentSummaryIndex우리는 일련의 문서를 작성 하고 ResponseSynthesizer개체를 전달하여 문서에 대한 요약을 합성할 수 있습니다.

from llama_index import (
    SimpleDirectoryReader,
    LLMPredictor,
    ServiceContext,
    ResponseSynthesizer
)
from llama_index.indices.document_summary import GPTDocumentSummaryIndex
from langchain.chat_models import ChatOpenAI

# load docs, define service context
...

# build the index
response_synthesizer = ResponseSynthesizer.from_args(response_mode="tree_summarize", use_async=True)
doc_summary_index = GPTDocumentSummaryIndex.from_documents(
    city_docs, 
    service_context=service_context,
    response_synthesizer=response_synthesizer
)

summary = doc_summary_index.get_document_summary("Boston")

from llama_index.indices.document_summary import DocumentSummaryIndexRetriever

retriever = DocumentSummaryIndexRetriever(
    doc_summary_index,
    # choice_select_prompt=choice_select_prompt,
    # choice_batch_size=choice_batch_size,
    # format_node_batch_fn=format_node_batch_fn,
    # parse_choice_select_answer_fn=parse_choice_select_answer_fn,
    # service_context=service_context
)
retrieved_nodes = retriever.retrieve("What are the sports teams in Toronto?")
print(retrieved_nodes[0].score)
print(retrieved_nodes[0].node.get_text())The retriever will retrieve a set of relevant nodes for a given index.

8.0
Toronto ( (listen) tə-RON-toh; locally [təˈɹɒɾ̃ə] or [ˈtɹɒɾ̃ə]) is the capital city of the Canadian province of Ontario. With a recorded population of 2,794,356 in 2021, it is the most populous city in Canada...

높은 수준의 API

query_engine = doc_summary_index.as_query_engine(
  response_mode="tree_summarize", use_async=True
)
response = query_engine.query("What are the sports teams in Toronto?")
print(response)

# use retriever as part of a query engine
from llama_index.query_engine import RetrieverQueryEngine

# configure response synthesizer
response_synthesizer = ResponseSynthesizer.from_args()

# assemble query engine
query_engine = RetrieverQueryEngine(
    retriever=retriever,
    response_synthesizer=response_synthesizer,
)

# query
response = query_engine.query("What are the sports teams in Toronto?")
print(response)

모든 텍스트에 대한 자동 요약 접근 방식은 정말 흥미진진합니다. 다음 두 가지 영역에서 확장 기능을 개발하게 되어 기쁩니다.

  • 다른 계층에서 자동 요약을 계속 탐색합니다. 현재는 문서 수준이지만 큰 텍스트 덩어리를 작은 덩어리로 요약하는 것은 어떻습니까? (예: 한 줄짜리).
  • 요약이 잠금을 해제하는 데 도움이 되는 LLM 기반 검색을 계속 탐색하십시오.

문서 요약 가이드

노트북 링크