Veröffentlicht am

LLM-LangChain-Texte-zusammenfassen

Zusammenfassungen mit LLM und LangChain

Automatisch Texte zusammenfassen, selbst in deutscher Sprache, dank der Large Language Models und APIs wie LangChain ist das einfacher denn je. Der Artikel zeigt ein konkretes Codebeispiel, das dank der Map-Reduce-Technik auch für lange Texte funktioniert.

Dienste wie ChatGPT und Gemini bietet zwar eine einfache Möglichkeit, Dokumente zusammenfassen zu lassen, jedoch stellt sich bei vertraulichen Inhalten die Frage nach Datenschutz und Datensicherheit. Es ist unklar, wie die Daten während der Übertragung und Verarbeitung geschützt werden und ob sie möglicherweise für andere Zwecke verwendet werden könnten.

Wir können ein Large Language Model auch in-house deployen und in unsere Anwendungsprogramme integrieren. Mit einer geeigneten Bibliothek wie LangChain gelingt auch das. Der Artikel zeigt wie’s geht am Beispiel der Textzusammenfassung.

Attention Windows beschränken die Möglichkeiten

Wollen wir mit einem API wie beispielsweise LangChain mit längeren Texten arbeiten, dann lernen wir sehr schnell die Beschränkungen kennen, die das Attention Window auferlegt. Einem LLM können wir nur beschränkt viele Token übergeben. Die Anzahl dieser Tokens, heißt Attention Window.

Ein Token ist ein Wort oder ein Subwort, je nach eingesetzter natürlicher Sprache und je nach Modell.

Beim Programmieren mit LLMs brauchen wir uns nicht so sehr um Tokens zu kümmern, wir treffen jedoch immer wieder auf sie. Spätestens bei der Abrechnung, wenn wir ein LLM as a Service verwenden, denn diese erfolgt aufgrund der Anzahl verarbeiteter Tokens.

Attention Windows sind nicht allzu groß – 2048 Tokens sind nicht unüblich.

Wollen wir einen längeren Text zusammenfassen, dann sind 2048 Wörter eher bescheiden. Für die deutsche Sprache mit ihren oft langen Wörtern, dürften 2048 Tokens deutlich weniger Wörter sein. Und doch gibt es eine Möglichkeit, trotz beschränktem Attention Window auch längere Texte automatisch zusammenzufassen.

Map Reduce für Textzusammenfassung

Das MapReduce Konzept kennen wir aus der Analyse großer Datenmengen und wir begegnen ihm hier wieder. Die Idee ist bestechend einfach:

  • Wir zerlegen den Text in kleinere Fragmente, oder Textbausteine.
  • Dann fassen wir die Bausteine zusammen – das entspricht dem Map-Schritt.
  • Danach vereinen wir einige der Zusammenfassungen zu einem neuen etwas größeren Textbaustein.
  • Und diesen fassen wir wieder zusammen.
  • Das wiederholen wir, bis wir eine einzige Zusammenfassung erhalten.

Die folgende Animation verdeutlicht das Prinzip:

Map Reduce Textzusammenfassung mit LangChain

LangChain und Textzusammenfassungen

LangChain bringt eine ganze Reihe nützlicher Funktionen mit, so auch mehrere Varianten, um Texte zusammenzufassen.

Imports

from langchain.chains.summarize import load_summarize_chain
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate

Falls wir nicht ein OpenAI-Modell verwenden, importieren wir die entsprechende LangChain-Klasse.

Konstanten und Keys

Die Variable file enthält den Pfad zum Dokument, das wir zusammenfassen wollen.

Das Beispiel funktioniert mit einen OpenAI-Modell. Dazu benötigen wir einen OpenAI API Key. Wer an anderes Modell nutzt, braucht einen anderen API-Key oder kommt möglicherweise auch ohne API-Key aus, beispielsweise, wenn das Modell in-house deployed ist.

Mit load_dotenv laden wir den OPENAI_API_KEY, den wir sicher im .env-Verzeichnis untergebracht haben.

file = 'test.pdf'
from dotenv import load_dotenv
load_dotenv()

Das Modell initialisieren

Die Klasse für das Modell haben wir ja schon importiert.

Jetzt initialisieren wir das Modell. Das Beispiel funktioniert mit OpenAI’s gpt-3.5-turbo-Modell. Dies ersetzen wir, falls wir ein anderes Modell verwenden wollen.

OpenAI-Modelle erlauben, mit Hilfe der Temperatur-Angabe zu steuern, wie viel Probabilität bei der Erzeugung der Zusammenfassung im Spiel sein darf. Mit 0.0 schalten wir die Probabilität weitgehend aus.

Wir verwenden max_tokens von 2048 – das Attention-Window soll also nicht größer als diese Anzahl Tokens sein.

openai_chat_model = ChatOpenAI(model='gpt-3.5-turbo',
  temperature=0.0,
  max_tokens=2048,
)

Text laden und splitten

Im folgenden Code-Snippet laden wir die PDF-Datei und zerhacken sie in Chunks (Textbausteine).

loader = PyPDFLoader(file)
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
texts = text_splitter.split_documents(documents)

Die Zusammenfassung erstellen

Jetzt führen wir die Zusammenfassung durch und lassen das Ergebnis anzeigen.

Die Variable openai_chat_model ersetzen wir, falls wir ein anderes Modell einsetzen.

chain=load_summarize_chain(openai_chat_model,chain_type='map_reduce')
summary = chain.invoke(texts)['output_text']
summary

Die Erstellung der Zusammenfassung kann auch mehrere Minuten dauern, ganz abhängig von der Größe der PDF-Datei und derjenigen der Chunks, die wir gewählt haben.

Deutschsprachige Texte

Der Code ist verblüffend einfach und leistungsfähig. Doch es gibt einen Haken an der Geschichte – jedenfalls zum Zeitpunkt des Verfassens dieses Artikels: Die Zusammenfassung deutscher Texte ist english.

Um dem Abhilfe zu verschaffen, müssen wir die Prompts, die im Code von load_summarize_chain hinterlegt sind, ebenfalls in deutscher Sprache verfassen.

Das nächste Code-Snippet zeigt, wie es geht:

Deutschsprachige Prompts ergänzen

Bevor wir die Chain aufrufen, bauen wir zwei deutschsprachige Prompts ein, einen für Map und einen für Reduce. Diese geben wir beim Aufruf der Chain mit. Das Ergebnis ist eine Zusammenfassung in deutscher Sprache.

# Map Prompt Template
map_prompt_template = """Fasse den folgenden Textbaustein zusammen:

{text}

TEXTBAUSTEIN ZUSAMMENFASSUNG:"""

map_prompt = PromptTemplate(template=map_prompt_template, input_variables=["text"])

# Reduce Prompt Template
reduce_prompt_template = """Vereine diese Zusammenfassungen zu einer einzigen, präzisen Zusammenfassung:

{text}

PRÄZISE ZUSAMMENFASSUNG:"""

reduce_prompt = PromptTemplate(template=reduce_prompt_template, input_variables=["text"])

chain = load_summarize_chain(
    openai_chat_model,
    chain_type="map_reduce",
    map_prompt=map_prompt,
    combine_prompt=reduce_prompt# For LangChain versions < 0.0.147
    )

summary = chain.invoke(texts)['output_text']
summary

Stellschrauben

Die Code-Snippets zeigen die Mächtigkeit von LangChain an einem einfachen Beispiel. Das Snippet setzt das Modell gpt-3.5-turbo ein. Wir könnten dieses durch ein anderes Modell ersetzen, das trainiert oder fine-tuned wurde, um einerseits Texte zusammenzufassen und andererseits mit deutschsprachigen Texten zu arbeiten.

Wir könnten dieses Modell auch selbst hosten oder weiter auf unsere Bedürfnisse anpassen.

Wir können experimentieren mit der Chunk-Größe und der Überlappung und auch mit der Temperatur des Modells und damit die erzeugten Zusammenfassungen weiter beeinflussen.

Fazit

Jahrzehnte lang forschte man nach Möglichkeiten, Texte automatisch zusammenzufassen. Noch nie war das so einfach. Ob wirklich die relevantesten Inhalte in die Zusammenfassung aufgenommen werden, das müssen wir im Detail untersuchen.

  • LLM-Tipps & Fachglossar

    Abonniere meinen Newsletter, erhalte regelmäßig Tipps und Tricks über den produktiven Einsatz von LLMs und ich schenke dir mein umfangreiches Fachglossar Von AI-Engineering bis Zero-Shot

  • Chatbot als Lernassistent
  • Prompt Engineering Personas und Wiederholungen
  • AI-Engineering-Fachglossar
  • EBook Tutorial: Cluster aus virtuellen Maschinen
  • Ebook: Apache ZooKeeper
  • Ebook: Realtime Streaming Pipelines
  • LSM-Trees: Log Structured Merge Trees
  • Aufbau einer Enterprise Search
  • Zeit Stream Analytics
  • B-Tree-Index in Datenbanken
  • Ordering Guarantee in Apache Kafka
  • CAP Theorem
  • MapReduce Funktionale Programmierung
  • Konzepte des HDFS
  • Optimistisches Concurrency Control