Я работаю с LLMChain от LangChain для обработки больших документов. Я вижу довольно много проблем, когда входной текст превышает лимит токенов языковой модели. Для длинного ввода текста он имеет значительные подтормаживания и даже иногда может давать сбой из-за переполнения токенов.
Это пример кода,
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI
prompt = PromptTemplate("Analyze the following text and summarize it: {text}")
llm_chain = LLMChain(llm=OpenAI(model = "gpt-3.5-turbo"), prompt=prompt)
long_text = "This is a very long document..." # Assume this text is extremely long
response = llm_chain.run(text=long_text)
print(response)
Проблема в том, что когда long_text слишком длинный, цепочка либо терпит неудачу по причине ограничения токенов, либо работает абсурдно долго. Я имею в виду, что в таких моделях, как GPT-3.5-turbo, установлен лимит токенов, но все же мне не хотелось бы делать это вручную при каждом использовании моей функции.
Можно ли динамически настраивать входную токенизацию LangChain, чтобы она оставалась эффективной при обработке длинных текстов?
Вы можете попробовать использовать встроенную утилиту:
from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
from langchain.text_splitter import RecursiveCharacterTextSplitter
prompt = PromptTemplate("Analyze the following text and summarize it: {text}")
llm_chain = LLMChain(llm=OpenAI(model = "gpt-3.5-turbo"), prompt=prompt)
long_text = "This is a very long document..." # Assume this text is extremely long
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
text_chunks = splitter.split_text(long_text)
response_chunks = []
for text_chunk in text_chunks :
response_chunk = llm_chain.run(text=text_chunk)
response_chunks.append(chunk_response)
response = "\n".join(response_chunks)
print(response)
Для обработки длинных входных текстов в LangChain и динамического управления работами по токенизации вы можете рассчитать доступные токены для текста, учитывая длину приглашения и любой дополнительный фиксированный текст, который может быть частью ввода.
Ответ Кароля Змиевского хорош, но я бы добавил функцию process_dynamic_tokenization
дополнительно для решения этой проблемы.
from transformers import GPT2Tokenizer
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
llm_chain = LLMChain(
llm=OpenAI(model = "gpt-3.5-turbo"),
prompt=PromptTemplate("Analyze the following text and summarize it: {text}")
)
def split_text_into_chunks(text, max_tokens):
tokens = tokenizer.tokenize(text)
chunks = []
for i in range(0, len(tokens), max_tokens):
chunk_tokens = tokens[i:i + max_tokens]
chunk_text = tokenizer.convert_tokens_to_string(chunk_tokens)
chunks.append(chunk_text)
return chunks
def process_long_text(text, max_tokens):
chunks = split_text_into_chunks(text, max_tokens)
summaries = []
for chunk in chunks:
response = llm_chain.run(text=chunk)
summaries.append(response)
return " ".join(summaries)
def process_dynamic_tokenization(text, prompt_template, llm_chain, max_model_tokens=4096):
prompt_tokens = len(tokenizer.tokenize(prompt_template.template.format(text = "")))
available_tokens = max_model_tokens - prompt_tokens
if available_tokens <= 0:
raise ValueError("Prompt template is too long for the model's token limit.")
return process_long_text(text, max_tokens=available_tokens)
long_text = "This is a very long document..."
final_summary = process_dynamic_tokenization(
text=long_text,
prompt_template=PromptTemplate("Analyze the following text and summarize it: {text}"),
llm_chain=llm_chain,
max_model_tokens=4096
)
print(final_summary)
Да, это недостающая часть. @DAR Извините, я не ответил сразу, в любом случае Лисан Аль Гаиб, кажется, правильно решает проблему.
Помимо непосредственного разделения текста на фрагменты, вы также можете использовать встроенные возможности langchain для обобщения:
Чтобы дать вам предварительный просмотр, любой конвейер можно обернуть в один объект:
load_summarize_chain
.Предположим, мы хотим подвести итог записи в блоге. Мы можем создать это за несколько строки кода.
from langchain.chains.summarize import load_summarize_chain
from langchain_community.document_loaders import WebBaseLoader
from langchain_openai import ChatOpenAI
loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
docs = loader.load()
llm = ChatOpenAI(temperature=0, model_name = "gpt-3.5-turbo-1106")
chain = load_summarize_chain(llm, chain_type = "stuff")
result = chain.invoke(docs)
print(result["output_text"])
Или
Когда мы используем
load_summarize_chain
сchain_type = "stuff"
, мы будем использоватьStuffDocumentsChain
.Цепочка возьмет список документов, вставит их все в подсказку и передайте ее LLM:
from langchain.chains.combine_documents.stuff import StuffDocumentsChain
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
# Define prompt
prompt_template = """Write a concise summary of the following:
"{text}"
CONCISE SUMMARY:"""
prompt = PromptTemplate.from_template(prompt_template)
# Define LLM chain
llm = ChatOpenAI(temperature=0, model_name = "gpt-3.5-turbo-16k")
llm_chain = LLMChain(llm=llm, prompt=prompt)
# Define StuffDocumentsChain
stuff_chain = StuffDocumentsChain(llm_chain=llm_chain, document_variable_name = "text")
docs = loader.load()
print(stuff_chain.invoke(docs)["output_text"])
Обратите внимание, что GPT-4o Mini (gpt-4o-mini
) почти в 3 раза дешевле по сравнению с GPT-3.5 Turbo и поддерживает токены 128k
по сравнению с 3.5 Turbo, которая поддерживает токены 4096
. Reference
Кроме того, у меня возникли проблемы с запуском вашего кода, возможно, из-за несовместимости версии langchain
— я использую последнюю версию 0.2.14, поэтому мне пришлось изменить API openai с v1/completions
на v1/chat/completions
следующим образом:
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
prompt = PromptTemplate(template = "Analyze the following text and summarize it: {text}")
llm_chain = LLMChain(llm=ChatOpenAI(model = "gpt-4o-mini"), prompt=prompt)
long_text = "This is a very long document..." # Assume this text is extremely long
response = llm_chain.run(text=long_text)
print(response)
Спасибо за подробный ответ, помог мне получить больше знаний по этой теме. Я уже получил необходимый результат из принятого ответа.
Я попробовал это, но дробление меняет требуемый результат, поэтому я не стал продолжать и разместил вопрос здесь.