Проблема LangChain/OpenAI с форматом текстового файла из веб-скрапинга, приводящая к сбою вызова API для «максимальной длины контекста»
Я пытаюсь использовать расширенную генерацию поиска, используя TextLoader и CharacterTextSplitter LangChain. Мои исходные данные — это текстовые данные, которые я собрал с веб-сайта клиента. При очистке без предварительной обработки данные становятся «грязными» и содержат символы Юникода и NBSP, а также разрывы строк («\n»). Вот мой скрипт веб-скрапинга:
for procedure_name in procedure_names:
url = f"{base_url}{procedure_name}/"
response = requests.get(url)
if response.status_code == 200:
soup = BeautifulSoup(response.content, "html.parser")
content_div = soup.find("div", class_="col-lg-8")
if content_div:
article = content_div.find("article", class_="singlepostinner")
if article:
paragraphs = article.find_all("p")
procedure_content = "\n".join(p.get_text() for p in paragraphs) # Extract content from paragraphs
# Cleaning process
cleaned_content = re.sub(r'[^\w\s]', '', procedure_content) # Remove punctuation
cleaned_content = cleaned_content.replace('\n', ' ') # Remove line breaks
cleaned_content = re.sub(r'\\u[0-9a-fA-F]+', '', cleaned_content) # Remove Unicode characters
cleaned_content = cleaned_content.replace('\xa0', ' ') # Replace non-breaking space with regular space
# Preserve original web formatting for certain non-breaking space characters (NBSP) such as superscript "TM"
cleaned_content = html.unescape(cleaned_content)
# Print the cleaned content for debugging
print("Cleaned Content:")
print(cleaned_content)
# Append the cleaned content to the text file
with open('webscraped_data.txt', 'a', encoding='utf-8') as txt_file:
txt_file.write(cleaned_content + '\n')
else:
print(f"No article found for {procedure_name}")
else:
print(f"No content div found for {procedure_name}")
else:
print(f"Failed to fetch {url}")
Теперь, когда я пытаюсь запустить цепочку LangChain, используя примеры с их веб-сайта, а также из других подобных руководств, именно здесь я вижу ошибку. Моя функция LangChain приведена ниже.
def demo(question):
'''
Takes in a question about medical treatments and returns the most relevant
part of the description.
Follow the steps below to fill out this function:
'''
# PART ONE:
loader = TextLoader('/Users/ty/repos/vee/App/webscraped_data_clean.txt')
documents = loader.load()
# PART TWO
# Split the document into chunks (you choose how and what size)
# text_splitter = CharacterTextSplitter.from_tiktoken_encoder(chunk_size=1000)
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(chunk_size=1000)
docs = text_splitter.split_documents(documents)
# PART THREE
# EMBED THE Documents (now in chunks) to a persisted ChromaDB
embedding_function = OpenAIEmbeddings()
db = Chroma.from_documents(docs, embedding_function, persist_directory='./Users/ty/repos/vee/App/.solution')
db.persist
# PART FOUR
# Use ChatOpenAI and ContextualCompressionRetriever to return the most
# relevant part of the documents.
llm = ChatOpenAI(temperature=0)
compressor = LLMChainExtractor.from_llm(llm)
compression_retreiver = ContextualCompressionRetriever(base_compressor=compressor,
base_retriever=db.as_retriever())
compressed_docs=compression_retreiver.get_relevant_documents(question)
print(compressed_docs[0].page_content)
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(chunk_size=1000)
Для устранения неполадок я использовал стандартный файл US_Constitution.txt, который представлен на сайте, а также в других туториалах. Это, конечно, работает. Я также измерил количество токенов для дальнейшего устранения неполадок:
Для документа Конституции США:
with open('some_data/US_Constitution.txt', 'r', encoding='utf-8') as text_file:
content = text_file.read()
estimated_tokens = estimate_tokens(content)
print(f"Estimated tokens in the content: {estimated_tokens}")
Я получаю 7497 жетонов.
Используя тот же подход, используя мои веб-данные, я получаю 9145. Итак, очевидно, что оба документа превышают предел в 4096 токенов. Но я думал, что, поскольку я векторизовал данные, мои локальные данные будут искаться ПЕРВЫМ семантически по вопросу («что такое розацеа») ПЕРЕД отправкой в OpenAI. Кажется, с Конституционным документом дело обстоит именно так. Однако, похоже, что мой веб-документ отправляет весь корпус, а не семантически похожую часть текста.
Кто-нибудь сталкивался с этой проблемой с веб-очисткой текста, и если да, то как вы ее исправили? Также обратите внимание, что я сократил файл до 852 токенов, но по-прежнему получаю ту же ошибку для вызова API (превышено 4096 токенов).
1 ответ
Ниже этих двух строк вашего кода вы можете добавить дополнительные функции для проверки количества токенов.
from tiktoken import Tokenizer, tokenizers
def count_tokens(text):
tokenizer = Tokenizer(tokenizers.ByteLevelBPETokenizer())
return sum(1 for _ in tokenizer.tokenize(text))
#Your existing code
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(chunk_size=1000)
docs = text_splitter.split_documents(documents)
#Here you can check token count and make sure its less than 4096
for idx, doc in enumerate(docs):
token_count = count_tokens(doc)
print(f"Document {idx} has {token_count} tokens.")
if token_count > 4096:
print("Warning: This document exceeds the token limit.")