Новый индекс сводки документов для систем контроля качества на базе LLM
В этом сообщении блога мы представляем совершенно новую структуру данных LlamaIndex: указатель сводки документов. Мы описываем, как это может помочь повысить производительность поиска по сравнению с традиционным семантическим поиском, а также рассмотрим пример.
Фон
Одним из основных вариантов использования больших языковых моделей (LLM) является ответ на вопрос о ваших собственных данных. Для этого мы объединяем LLM с «поисковой» моделью, которая может выполнять поиск информации по корпусу знаний и выполнять синтез ответов по извлеченным текстам с использованием LLM. Эта общая структура называется Retrieval-Augmented Generation.
Большинство пользователей, создающих сегодня системы контроля качества на основе LLM, как правило, делают следующее:
- Возьмите исходные документы, разделите каждый на текстовые фрагменты
- Хранить текстовые фрагменты в векторной базе данных
- Во время запроса извлекайте фрагменты текста, встраивая фильтры сходства и/или ключевых слов.
- Выполнить синтез ответа
Ограничения существующих подходов
Есть несколько ограничений на встраивание поиска с использованием фрагментов текста.
- Фрагментам текста не хватает глобального контекста. Часто вопрос требует контекста, выходящего за рамки того, что индексируется в конкретном фрагменте.
- Тщательная настройка порогов оценки топ-k/сходства. Сделайте значение слишком маленьким, и вы упустите контекст. Сделайте значение слишком большим, и стоимость/задержка могут увеличиться с более нерелевантным контекстом.
- Вложения не всегда выбирают наиболее релевантный контекст для вопроса. Вложения по своей сути определяются отдельно между текстом и контекстом.
Указатель сводки документов

Мы предлагаем новый индекс в LlamaIndex , который будет извлекать/индексировать неструктурированное текстовое резюме для каждого документа . Этот индекс может помочь повысить производительность поиска по сравнению с существующими подходами к поиску. Он помогает индексировать больше информации, чем отдельный фрагмент текста, и несет больше семантического значения, чем теги ключевых слов. Это также позволяет использовать более гибкую форму поиска: мы можем выполнять как поиск LLM, так и поиск на основе встраивания.
Как это работает
Во время сборки мы получаем каждый документ и используем LLM для извлечения сводки из каждого документа. Мы также разбиваем документ на текстовые фрагменты (узлы). И сводка, и узлы хранятся в нашей абстракции хранилища документов . Мы поддерживаем сопоставление сводки с исходным документом/узлами.
Во время запроса мы извлекаем соответствующие документы для запроса на основе их резюме, используя следующие подходы:
- Поиск на основе LLM: мы представляем наборы резюме документов LLM и просим LLM определить, какие документы релевантны + их оценка релевантности.
- Поиск на основе встраивания: мы извлекаем релевантные документы на основе сводного сходства встраивания (с отсечкой top-k).
Хранение сводок по документу также позволяет выполнять поиск на основе LLM . Вместо того, чтобы сначала передавать весь документ LLM, мы можем сначала попросить LLM проверить краткую сводку документа, чтобы увидеть, имеет ли она вообще отношение к запросу. Это использует возможности рассуждений LLM, которые более продвинуты, чем поиск на основе встраивания, но позволяет избежать затрат/задержек, связанных с передачей всего документа в LLM.
Дополнительные сведения
Поиск документов с резюме можно рассматривать как «золотую середину» между семантическим поиском и резюмированием грубой силы по всем документам. Мы ищем документы на основе сводной релевантности заданному запросу, а затем возвращаем все *узлы*, соответствующие извлеченным документам.
Почему мы должны это делать? Этот метод извлечения дает пользователю больше контекста, чем top-k по фрагменту текста, путем извлечения контекста на уровне документа. Но это также более гибкий/автоматический подход, чем тематическое моделирование; больше не нужно беспокоиться о том, есть ли в вашем тексте правильные теги ключевых слов!
Пример
Давайте рассмотрим пример, демонстрирующий индекс сводки документов по статьям Википедии о разных городах.
Остальная часть этого руководства демонстрирует соответствующие фрагменты кода. Вы можете найти полное пошаговое руководство здесь (и вот ссылка на блокнот ).
Мы можем построить 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, который помогает раскрыть обобщение.
Краткое руководство по документу
Ссылка на блокнот