So fassen Sie große Dokumente mit LangChain und OpenAI zusammen

Bei der Zusammenfassung sehr großer Dokumente gibt es noch einige Einschränkungen. Hier sind einige Möglichkeiten, diese Auswirkungen abzumildern.

Übersetzt aus „ How to Summarize Large Documents with LangChain and OpenAI“ , Autor Usama Jamil.

Große Sprachmodelle erleichtern viele Aufgaben, z. B. die Erstellung von Chatbots, Sprachübersetzungen, Textzusammenfassungen usw. Früher haben wir Modelle geschrieben, um Zusammenfassungen vorzunehmen, und dann gab es immer Leistungsprobleme. Jetzt können wir dies einfach mithilfe großer Sprachmodelle (LLM) tun. Beispielsweise können LLMs auf dem neuesten Stand der Technik (SOTA) bereits ganze Bücher innerhalb ihres Kontextfensters verarbeiten. Bei der Zusammenfassung sehr großer Dokumente gibt es jedoch noch einige Einschränkungen.

LLM-Einschränkungen bei der Zusammenfassung großer Dokumente

Das Kontextlimit oder die Kontextlänge bezieht sich in LLM auf die Anzahl der Token, die das Modell verarbeiten kann. Jedes Modell hat seine eigene Kontextlänge, die auch als maximale Markierung oder Markierungsgrenze bezeichnet wird. Beispielsweise beträgt die Kontextlänge des Standard-GPT-4-Modells 128.000 Token. Bei mehr als dieser Anzahl von Tags gehen Informationen verloren. Einige SOTA-LLMs haben Kontextbeschränkungen von bis zu 1 Million Tags. Mit zunehmenden kontextuellen Einschränkungen leidet LLM jedoch unter Einschränkungen wie Aktualität und Vorrang. Wir können auch nach Möglichkeiten suchen, diese Auswirkungen abzumildern.

  • Der Primateffekt im LLM bedeutet, dass das Modell mehr Wert auf die Informationen legt, die zu Beginn der Sequenz präsentiert werden.
  • Der Aktualitätseffekt liegt vor, wenn ein Modell die neuesten Informationen hervorhebt, die es verarbeitet.

Beide Effekte verzerren das Modell auf bestimmte Teile der Eingabedaten. Das Modell überspringt möglicherweise wichtige Informationen mitten in der Sequenz.

Das zweite Problem sind die Kosten. Wir können das erste Problem der Kontextbeschränkungen lösen, indem wir den Text aufteilen, aber wir können nicht das gesamte Buch direkt an das Modell übergeben. Das wird viel kosten. Wenn wir beispielsweise ein Buch mit 1 Million Tags hätten und es direkt an das GPT4-Modell übergeben würden, würden unsere Gesamtkosten etwa 90 US-Dollar betragen (Hinweis- und Vervollständigungs-Tags). Wir mussten einen vielseitigen Weg finden, unseren Text zusammenzufassen und dabei den Preis, kontextuelle Einschränkungen und den gesamten Kontext des Buches zu berücksichtigen.

In diesem Tutorial erfahren Sie, wie Sie ein ganzes Buch unter Berücksichtigung der Preis- und Kontextbeschränkungen eines Modells zusammenfassen. Lasst uns beginnen.

Richten Sie die Umgebung ein

Um diesem Tutorial folgen zu können, benötigen Sie Folgendes:

  • Python installiert
  • Eine IDE (VS-Code funktioniert)

Um Abhängigkeiten zu installieren, öffnen Sie Ihr Terminal und geben Sie den folgenden Befehl ein:

pip install langchain openai tiktoken fpdf2 pandas

Dieser Befehl installiert alle erforderlichen Abhängigkeiten.

Bücher laden

Sie verwenden David Copperfield von Charles Dickens, der für die Verwendung in diesem Projekt veröffentlicht wurde. Laden wir dieses Buch mit PyPDFLoader von LangChain.

from langchain.document_loaders import PyPDFLoader

# Load the book
loader = PyPDFLoader("David-Copperfield.pdf")
pages = loader.load_and_split()

Es wird das gesamte Buch geladen, uns interessiert jedoch nur der Inhaltsteil. Wir können Seiten wie das Vorwort und die Einleitung überspringen.

# Cut out the open and closing parts
pages = pages[6:1308]
# Combine the pages, and replace the tabs with spaces
text = ' '.join([page.page_content.replace('\t', ' ') for page in pages]

Jetzt haben wir Inhalte. Lassen Sie uns die ersten 200 Zeichen drucken.

Vorverarbeitung

Entfernen wir unnötige Inhalte aus dem Text, wie z. B. nicht druckbare Zeichen, zusätzliche Leerzeichen usw.

import re
def clean_text(text):
   # Remove the specific phrase 'Free eBooks at Planet eBook.com' and surrounding whitespace
   cleaned_text = re.sub(r'\s*Free eBooks at Planet eBook\.com\s*', '', text, flags=re.DOTALL)
   # Remove extra spaces
   cleaned_text = re.sub(r' +', ' ', cleaned_text)
   # Remove non-printable characters, optionally preceded by 'David Copperfield'
   cleaned_text = re.sub(r'(David Copperfield )?[\x00-\x1F]', '', cleaned_text)
   # Replace newline characters with spaces
   cleaned_text = cleaned_text.replace('\n', ' ')
   # Remove spaces around hyphens
   cleaned_text = re.sub(r'\s*-\s*', '', cleaned_text)
   return cleaned_text
clean_text=clean_text(text)

Nachdem wir die Daten bereinigt haben , können wir uns mit dem Zusammenfassungsproblem befassen.

Laden Sie die OpenAI-API

Bevor wir die OpenAI-API verwenden, müssen wir sie hier konfigurieren und Anmeldeinformationen bereitstellen.

import os
os.environ["OPENAI_API_KEY"] = "your-openai-key-here"

Geben Sie hier Ihren API-Schlüssel ein und die Umgebungsvariable wird festgelegt.

Mal sehen, wie viele Tags es in diesem Buch gibt:

from langchain import OpenAI
llm = OpenAI()
Tokens = llm.get_num_tokens(clean_text)
print (f"We have {Tokens} tokens in the book")

Das Buch enthält über 466.000 Markierungen, und wenn wir sie alle direkt an LLM weitergeben würden, würden uns hohe Kosten entstehen. Um die Kosten zu senken, werden wir daher K-Means-Clustering implementieren, um wichtige Teile aus dem Buch zu extrahieren.

Hinweis : Die Entscheidung, K-Means-Clustering zu verwenden, wurde durch ein Tutorial des Datenexperten Greg Kamradt inspiriert .

Um die wichtigen Teile des Buches zu verstehen, teilen wir das Buch zunächst in verschiedene Abschnitte auf.

Inhalte in Dokumente aufteilen

Wir werden das SemanticChunker-Dienstprogramm von LangChain verwenden, um den Buchinhalt in Dokumente aufzuteilen.

from langchain_experimental.text_splitter import SemanticChunker
from langchain_openai.embeddings import OpenAIEmbeddings
text_splitter = SemanticChunker(
   OpenAIEmbeddings(), breakpoint_threshold_type="interquartile"
)
docs = text_splitter.create_documents([clean_text])

SemanticChunker empfängt zwei Parameter, der erste ist das Einbettungsmodell. Die von diesem Modell generierten Einbettungen werden verwendet, um Text basierend auf der Semantik aufzuteilen. Der zweite ist breakpoint_threshold_type, der den Punkt bestimmt, an dem der Text basierend auf semantischer Ähnlichkeit in verschiedene Abschnitte aufgeteilt werden soll.

Hinweis: Durch die Verarbeitung dieser kleineren, semantisch ähnlichen Blöcke wollen wir Aktualitäts- und Primateffekte in LLM minimieren. Diese Strategie ermöglicht es unserem Modell, jeden kleinen Kontext effizienter zu verarbeiten und so eine ausgewogenere Interpretation und Antwortgenerierung sicherzustellen.

Finden Sie Einbettungen für jedes Dokument

Lassen Sie uns nun jedes generierte Dokument einbetten. Sie verwenden die OpenAI-Standardmethode, um die Einbettung zu erhalten.

import numpy as np
import openai
def get_embeddings(text):
   response = openai.embeddings.create(
       model="text-embedding-3-small",
       input=text
   )
   return response.data
embeddings=get_embeddings([doc.page_content for doc in docs]

get_embeddingsDie Methode kann uns Einbettungen für alle Dokumente liefern.

OpenAI hat speziell die Methode text-embedding-3-small veröffentlicht, die als billiger und schneller gilt.

Neuordnung der Daten

Als nächstes konvertieren wir die Dokumentinhaltsliste und ihre Einbettungen in einen Pandas DataFrame zur einfachen Datenverarbeitung und -analyse .

import pandas as pd
content_list = [doc.page_content for doc in docs]
df = pd.DataFrame(content_list, columns=['page_content'])
vectors = [embedding.embedding for embedding in embeddings]
array = np.array(vectors)
embeddings_series = pd.Series(list(array))
df['embeddings'] = embeddings_series

Effizientes Clustering mit Faiss

Wir konvertieren nun die Dokumentvektoren in ein Faiss- kompatibles Format, gruppieren sie mithilfe von K-Means in 50 Gruppen und erstellen dann einen Faiss-Index für effiziente Ähnlichkeitssuchen zwischen Dokumenten.

import numpy as np
import faiss
# Convert to float32 if not already
array = array.astype('float32') 
num_clusters = 50
# Vectors dimensionality
dimension = array.shape[1] 
# Train KMeans with Faiss
kmeans = faiss.Kmeans(dimension, num_clusters, niter=20, verbose=True)
kmeans.train(array)
# Directly access the centroids
centroids = kmeans.centroids 
# Create a new index for the original dataset
index = faiss.IndexFlatL2(dimension)
# Add original dataset to the index
index.add(array) 

Dieses K-Mittel bedeutet, dass beim Clustering Dokumente in 50 Gruppen gruppiert werden.

Hinweis : Der Grund für die Wahl von K-Means-Clustering besteht darin, dass jeder Cluster einen ähnlichen Inhalt oder einen ähnlichen Kontext hat, da alle Dokumente im Cluster verwandte Einbettungen haben und wir das Dokument auswählen, das dem Kern am nächsten liegt.

Importdokument auswählen

Jetzt werden wir nur die wichtigsten Dokumente aus jedem Cluster auswählen. Dazu wählen wir nur den ersten Vektor aus, der dem Schwerpunkt am nächsten liegt.

D, I = index.search(centroids, 1)

Dieser Code verwendet eine Suchmethode für den Index, um das Dokument zu finden, das jedem Schwerpunkt in einer Liste von Schwerpunkten am nächsten liegt. Es werden zwei Arrays zurückgegeben:

  • D, das den Abstand des nächstgelegenen Dokuments zu seinem jeweiligen Schwerpunkt enthält, und
  • I, das den Index dieser neueren Dokumente enthält. Der zweite Parameter 1 in der Suchmethode gibt an, dass für jeden Schwerpunkt nur das nächstgelegene Dokument gefunden wird.

Jetzt müssen wir den ausgewählten Dokumentenindex sortieren, da die Dokumente in Buchreihenfolge vorliegen.

sorted_array = np.sort(I, axis=0)
sorted_array=sorted_array.flatten()
extracted_docs = [docs[i] for i in sorted_array]

Erhalten Sie eine Zusammenfassung jedes Dokuments

Der nächste Schritt besteht darin, das GPT-4-Modell zu verwenden, um eine Zusammenfassung jedes Dokuments zu erhalten und so Geld zu sparen. Um GPT-4 zu verwenden, definieren wir das Modell.

model = ChatOpenAI(temperature=0,model="gpt-4")

Definieren Sie Hinweise und verwenden Sie LangChain, um Hinweisvorlagen zu erstellen und diese an das Modell zu übergeben.

from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_template("""
You will be given different passages from a book one by one. Provide a summary of the following text. Your result must be detailed and atleast 2 paragraphs. When summarizing, directly dive into the narrative or descriptions from the text without using introductory phrases like 'In this passage'. Directly address the main events, characters, and themes, encapsulating the essence and significant details from the text in a flowing narrative. The goal is to present a unified view of the content, continuing the story seamlessly as if the passage naturally progresses into the summary.
Passage:
```{text}```
SUMMARY:
"""
)

Diese Eingabeaufforderungsvorlage hilft dem Modell, das Dokument effektiver und effizienter zusammenzufassen.

Der nächste Schritt besteht darin, die LangChain-Kette mithilfe der LangChain Expression Language (LCEL) zu definieren.

chain= (
    prompt
   | model
   |StrOutputParser() )

Die Zusammenfassungskette verwendet StrOutputParser, um die Ausgabe zu analysieren. Es stehen weitere Ausgabeparser zum Erkunden zur Verfügung.

Schließlich können Sie auf jedes Dokument eine definierte Kette anwenden, um die Zusammenfassung zu erhalten.

from tqdm import tqdm
final_summary = ""

for doc in tqdm(extracted_docs, desc="Processing documents"):
   # Get the new summary.
   new_summary = chain2.invoke({"text": doc.page_content})
   # Update the list of the last two summaries: remove the first one and add the new one at the end.
   final_summary+=new_summary

Der obige Code wendet die Kette einzeln auf jedes Dokument an und verbindet jede Zusammenfassung mit der final_summary.

Zusammenfassung als PDF speichern

Der nächste Schritt besteht darin, die Zusammenfassung zu formatieren und als PDF zu speichern.

from fpdf import FPDF

class PDF(FPDF):
   def header(self):
       # Select Arial bold 15
       self.set_font('Arial', 'B', 15)
       # Move to the right
       self.cell(80)
       # Framed title
       self.cell(30, 10, 'Summary', 1, 0, 'C')
       # Line break
       self.ln(20)

   def footer(self):
       # Go to 1.5 cm from bottom
       self.set_y(-15)
       # Select Arial italic 8
       self.set_font('Arial', 'I', 8)
       # Page number
       self.cell(0, 10, 'Page %s' % self.page_no(), 0, 0, 'C')

# Instantiate PDF object and add a page
pdf = PDF()
pdf.add_page()
pdf.set_font("Arial", size=12)

# Ensure the 'last_summary' text is treated as UTF-8
# Replace 'last_summary' with your actual text variable if different
# Make sure your text is a utf-8 encoded string
last_summary_utf8 = last_summary.encode('latin-1', 'replace').decode('latin-1')
pdf.multi_cell(0, 10, last_summary_utf8)

# Save the PDF to a file
pdf_output_path = "s_output1.pdf"
pdf.output(pdf_output_path)

Hier finden Sie die vollständige Zusammenfassung des Buches im PDF-Format.

abschließend

In diesem Tutorial untersuchen wir die Komplexität der Verwendung von LLM zum Zusammenfassen großer Texte, beispielsweise ganzer Bücher, und gehen gleichzeitig auf Herausforderungen im Zusammenhang mit Kontextbeschränkungen und Kosten ein. Wir haben die Schritte der Textvorverarbeitung gelernt und eine Strategie implementiert, die semantisches Chunking und K-Means-Clustering kombiniert, um die kontextuellen Einschränkungen des Modells effektiv zu verwalten.

Durch effizientes Clustering extrahieren wir wichtige Absätze effektiv und reduzieren so den Aufwand für die direkte Verarbeitung riesiger Textmengen. Dieser Ansatz reduziert nicht nur die Kosten erheblich, indem die Anzahl der verarbeiteten Token minimiert wird, sondern mildert auch die mit LLM verbundenen Aktualitäts- und Primatseffekte ab und sorgt so für eine ausgewogene Berücksichtigung aller Textpassagen.

Die Entwicklung von KI-Anwendungen über die API von LLM hat große Aufmerksamkeit auf sich gezogen, wobei Vektordatenbanken eine wichtige Rolle spielen, indem sie eine effiziente Speicherung und Abfrage der Kontexteinbettung ermöglichen.

MyScaleDB ist eine Vektordatenbank, die speziell für KI-Anwendungen entwickelt wurde und alle Faktoren wie Kosten, Genauigkeit und Geschwindigkeit berücksichtigt. Dank der SQL-freundlichen Schnittstelle können Entwickler mit der Entwicklung ihrer KI-Anwendungen beginnen, ohne sich neue Kenntnisse aneignen zu müssen.

Dieser Artikel wurde zuerst auf Yunyunzhongsheng ( https://yylives.cc/ ) veröffentlicht, jeder ist herzlich willkommen.

Ich habe beschlossen, Open-Source-Hongmeng aufzugeben . Wang Chenglu, der Vater von Open-Source-Hongmeng: Open-Source-Hongmeng ist die einzige Architekturinnovations- Industriesoftwareveranstaltung im Bereich Basissoftware in China – OGG 1.0 wird veröffentlicht, Huawei steuert den gesamten Quellcode bei Google Reader wird vom „Code-Scheißberg“ getötet Ubuntu 24.04 LTS wird offiziell veröffentlicht Vor der offiziellen Veröffentlichung von Fedora Linux 40 Microsoft-Entwickler: Die Leistung von Windows 11 ist „lächerlich schlecht“, Ma Huateng und Zhou Hongyi geben sich die Hand, „beseitigen den Groll“ Namhafte Spielefirmen haben neue Vorschriften erlassen: Hochzeitsgeschenke an Mitarbeiter dürfen 100.000 Yuan nicht überschreiten. Pinduoduo wurde wegen unlauteren Wettbewerbs zu einer Entschädigung von 5 Millionen Yuan verurteilt
{{o.name}}
{{m.name}}

Ich denke du magst

Origin my.oschina.net/u/6919515/blog/11054174
Empfohlen
Rangfolge