Проблема 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.")
Другие вопросы по тегам