Суммирование текста на языке Python с использованием LangChain

Различные большие языковые модели (Large Language Models, LLM) имеют разные ограничения на длину входных слов в запросе. Если нам нужно сжать большую статью, но длина статьи превышает максимальный предельный лимит модели, мы не можем напрямую передавать всю статью модели искусственного интеллекта. В таких сценариях LangChain предоставляет стратегии и инкапсуляцию для решения этой проблемы. В этой главе в основном рассматривается, как LangChain решает задачу суммирования текста.

Предварительная обработка данных

Сначала подготавливаем тестовые данные. В этом примере мы загружаем длинный документ, а затем разбиваем его на несколько небольших фрагментов документа.

  • Примечание: Загрузка локальных данных файлов здесь приведена только для иллюстрации. В реальных бизнес-сценариях вы можете загружать данные документа из своей собственной базы данных.
from langchain import OpenAI, PromptTemplate, LLMChain
from langchain.text_splitter import CharacterTextSplitter
from langchain.chains.mapreduce import MapReduceChain
from langchain.prompts import PromptTemplate

llm = OpenAI(temperature=0)

text_splitter = CharacterTextSplitter()
with open("../../state_of_the_union.txt") as f:
    state_of_the_union = f.read()
texts = text_splitter.split_text(state_of_the_union)
from langchain.docstore.document import Document

docs = [Document(page_content=t) for t in texts[:3]]

Начало работы

Самый простой способ сжать длинный текст - использовать задачу load_summarize_chain, предоставляемую LangChain, для выполнения задачи суммирования текста.

from langchain.chains.summarize import load_summarize_chain
chain = load_summarize_chain(llm, chain_type="map_reduce")
chain.run(docs)

Использование инкапсулированной цепочки суммирования текста, предоставленной LangChain, просто. Однако, если вам нужно настроить некоторые параметры, обратитесь к следующему содержимому. Например, в приведенном выше примере используется встроенный шаблон слов-подсказок, который может быть неудобен для русского языка. Вы можете изменить его на свой собственный шаблон слов-подсказок и т. д.

Объяснение параметра chain_type

LangChain разработала 4 метода обработки случая, когда подсказочное слово задачи Chain превышает длину токена LLM.

4 типа chain_type следующие:

  • stuff
  • map_reduce
  • refine
  • map_rerank

Тип stuff

Это тип по умолчанию в LangChain, который отправляет весь содержимый документа в модель LLM для суммирования сразу. Поэтому его называют режим упаковки. Если содержимое документа слишком длинное, оно определенно превысит предел токенов LLM.

Тип map_reduce

Этот метод сначала отправляет каждый фрагмент документа в модель LLM для индивидуального суммирования, затем объединяет все суммарные данные и, наконец, предоставляет общее резюме для искусственного интеллекта, что аналогично концепции библиотек функций map-reduce во многих языках программирования.

Тип refine

Этот метод генерирует текстовое резюме путем суммирования. Сначала он отправляет содержимое первого документа в модель llm для суммирования, затем отправляет содержание резюме первого документа + содержание второго документа в модель llm для суммирования и так далее, чтобы получить окончательное резюме для длинного текста.

Тип map_rerank

Это используется в задачах вопросно-ответного формата. Он выбирает фрагменты документа с высокой релевантностью к вопросу, а затем отправляет их в модель llm для ответа на вопрос.

Пример задачи stuff

Вот пример сжатия статьи с использованием типа stuff, который подходит для статей, не превышающих ограничение по количеству токенов LLM:

chain = load_summarize_chain(llm, chain_type="stuff")
chain.run(docs)

Пользовательские слова-подсказки

Для типа stuff вот пример пользоватских слов-подсказок:

prompt_template = """Сжать следующее содержание:

{text}

Резюме:"""
PROMPT = PromptTemplate(template=prompt_template, input_variables=["text"])
chain = load_summarize_chain(llm, chain_type="stuff", prompt=PROMPT)
chain.run(docs)

Пример задачи map_reduce

map_reduce подводит итоги статьи, и, конечно же, данный метод приведет к нескольким вызовам моделей искусственного интеллекта.

chain = load_summarize_chain(llm, chain_type="map_reduce")
chain.run(docs)

Пользовательские слова-подсказки для задачи map_reduce

prompt_template = """Подведите итог следующего содержания:

{text}

Итог:"""
PROMPT = PromptTemplate(template=prompt_template, input_variables=["text"])
chain = load_summarize_chain(OpenAI(temperature=0), chain_type="map_reduce", return_intermediate_steps=True, map_prompt=PROMPT, combine_prompt=PROMPT)
chain({"input_documents": docs}, return_only_outputs=True)

Пример задачи refine

Просто измените параметр chain_type на refine.

chain = load_summarize_chain(llm, chain_type="refine")
chain.run(docs)

Шаблон пользовательских слов-подсказок для задачи refine

Вот пример пользовательских слов-подсказок для задачи refine:

prompt_template = """Подведите итог следующего содержания:

{text}

Итог:"""

PROMPT = PromptTemplate(template=prompt_template, input_variables=["text"])

refine_template = (
    "Ваша задача - создать окончательное текстовое резюме\n"
    "Вот существующая информация о резюме: {existing_answer}\n"
    "Улучшите существующее резюме на основе новой информации\n"
    "Фоновая информация следующая\n"
    "------------\n"
    "{text}\n"
    "------------\n"
    "Основываясь на фоновой информации, улучшите существующее резюме\n"
    "Верните существующую информацию о резюме, если фоновая информация не является полезной."
)

refine_prompt = PromptTemplate(
    input_variables=["existing_answer", "text"],
    template=refine_template,
)
chain = load_summarize_chain(OpenAI(temperature=0), chain_type="refine", return_intermediate_steps=True, question_prompt=PROMPT, refine_prompt=refine_prompt)
chain({"input_documents": docs}, return_only_outputs=True)