Um ein großes Sprachmodell zu trainieren, wird ein großer Datensatz verwendet. Die meisten großen Sprachmodelle haben
gemeinsam, dass diese zum Großteil auf Website-Daten trainiert werden.
Wir schauen uns den Datensatz des zurzeit bekanntesten Sprachmodells LLaMA von Meta/Facebook,
genauer an.
Die wichtigsten Fakten über den für das LLaMA-Training verwendeten Datensatz sind:
Zusammenfassend lässt sich sagen, dass der LLaMA-Trainingsdatensatz verschiedene Datensätze umfasst und diese aufwendige Aufbereitungsschritte durchlaufen, um einen qualitativ hochwertigen Datensatz zu erzeugen. Generell hat das Modell eine Kenntnis über verschiedenste Sprachen, wenn auch nur sehr begrenzt.
Die einzelnen Bestandteile des Datensatzes für das LLaMA-Training sind zwar frei verfügbar, der Datensatz selber nach der Aufbereitung jedoch nicht. Möchte man sich einen eigenen Datensatz zusammenstellen, folgen hier die Links zu den einzelnen Bestandteilen:
Datensatz | Links |
---|---|
CommonCrawl | CommonCrawl GitHub |
C4 | GitHub - Huggingface - Washington Post Analyse |
GitHub | Google BigQuery - Info Google Codelabs |
Wikipedia | Wikipedia Dumps - Huggingface |
Books | Huggingface Pile Books3 - Gutenberg - PG19 |
arXiv | arxiv |
StackExchange | archive - Huggingface |
Es gibt verschiedene Projekte, die einen vergleichbaren Datensatz zu dem des LLaMA-Netzes aufgebaut
haben:
RedPajama Datensatz auf Huggingface
Hier ist der Nachteil, dass ebenfalls wieder hauptsächlich englische Texte verwendet wurden. Lediglich
die
Wikipedia-Artikel hatten unterschiedliche Sprachen.
Darüber hinaus wurde ein vergleichbares Sprachmodell zu den LLaMA-Modellen trainiert namens Falcon, der
Datensatz hierzu wurde ebenfalls veröffentlicht: Huggingface
Der Vorteil gegenüber den oben vorgestellten Datensätzen ist, dass bei der großen Variante des Netzes ein weiterer (leider nicht
veröffentlichter) Datensatz verwendet wurde, bei dem europäische Sprachen mit 7 % Anteil
verwendet wurden. Hiervon sind 26 % der Daten Deutsch. Was einem Gesamtanteil von 1,82 %
entspricht. Dies entspricht immerhin einem Gesamtanteil von 1,82 % was aber natürlich immer noch eher gering ist.
Die Web-Datensätze werden durch Webscraping über Crawling erzeugt. Hierbei werden große Mengen an
Internetseiten heruntergeladen und der Text extrahiert. In Europa gibt es ebenfalls ein Projekt namens
OSCAR (Open Super-large Crawled Aggregated coRpus), welcher einen großen Open Source Datensatz
erzeugt.
Generell muss das Scraping bedacht angegangen werden und aktuell gibt es noch rechtliche Bedenken. Bei
StableDiffusion zum Beispiel (eine KI zur Bilderzeugung)
wurde erst vor kurzem ein mögliches opt out Verfahren eingeführt, damit die Bilder nicht für das Training
verwendet werden.
Außerdem zeigt sich, dass Scraping von den Websitebetreibern kritisch angesehen wird
und die Zugriffe nicht mehr kostenfrei erfolgen sollen.
,
Möchte man ein eigenes Webscraping aufbauen,
kann dies mit bereits
vorhandenen Tools wie Scrapy, StormCrawler o.ä. aufgebaut werden.
Wie können wir nun eigene Dokumente in die großen Sprachmodelle bringen? Generell gibt es unterschiedliche Herangehensweisen. Entweder können diese Texte in das Sprachmodell eintrainiert werden, oder man verwendet ein allgemeines Sprachmodell und nutzt Text-Embedding. Dabei werden ähnliche Textbausteine zu der Anfrage in vorhandenen Dokumenten gesucht und dem Sprachmodell zugeführt. Im ersten Schritt zeigen wir, wie man die Daten in das Sprachmodell eintrainieren kann.
import requests
from bs4 import BeautifulSoup
URL = "https://www.gutenberg.org/files/2229/2229-h/2229-h.htm"
# Herunterladen der .html Website
r = requests.get(URL)
soup = BeautifulSoup(r.content, "html.parser")
# Entfernen des Inhaltsverzeichnisses, der Überschriften, ...
text = soup.find_all("p")
text = [p.text for p in text]
# Entfernen der Einleitung am Anfang
text = text[5:]
print(" ".join(text[:1]))
DIREKTOR. Ihr beiden, die ihr mir so oft, In Not und Trübsal, beigestanden, Sagt, was ihr wohl in deutschen Landen Von unsrer Unternehmung hofft? [...]
Anschließende Datenaufbereitung:
# Filtern des Textes, damit nur die Konversationen und keine weiteren Einleitungen o.ä. verwendet wird:
final_text = []
for raw_text in text:
split_txt = raw_text.lstrip().split("\r\n", 1)
if split_txt[0].replace(".", "").isupper():
final_text.append("\n".join(split_txt))
final_text[:2]
['DIREKTOR.\nIhr beiden, die ihr mir so oft,\r\n [...]', 'DICHTER.\nIhr fühlet nicht, wie schlecht ein solches Handwerk sei!\r\n [...]']
import requests
import ebooklib
from ebooklib import epub
from bs4 import BeautifulSoup
URL = "https://www.gutenberg.org/ebooks/2229.epub.noimages"
r = requests.get(URL)
with open('Faust.epub', 'wb') as f:
f.write(r.content)
book = epub.read_epub("Faust.epub")
items = list(book.get_items_of_type(ebooklib.ITEM_DOCUMENT))
# Ab hier vergleichbar zu html-Dateien
final_text = []
for item in items:
soup = BeautifulSoup(item.get_body_content().decode('utf-8'), "html.parser")
# Entfernen des Inhaltsverzeichnisses, der Überschriften, ..., u.ä.
text = soup.find_all("p")
text = [p.text for p in text]
# Filtern des Textes, damit nur die Konversationen und keine weiteren Einleitungen o.ä. verwendet wird:
for raw_text in text:
split_txt = raw_text.lstrip().split("\n", 1)
if split_txt[0].isupper():
final_text.append("\n".join(split_txt))
final_text[:2]
['DIREKTOR.\nIhr beiden, die ihr mir so oft,\nIn Not und Trübsal, beigestanden,\n [...]', 'DICHTER.\nIhr fühlet nicht, wie schlecht ein solches Handwerk sei!\n [...]']
Für die PDF verwenden wir einen PDF-Ausdruck der bereits verwendeten Website. Hier wurde der Text nur relativ einfach extrahiert und manche Abschnitte zur Vereinfachung verworfen. Der Aufwand, PDF-Dateien aufzubereiten, ist deutlich größer, insbesondere wenn der Text nicht eingebettet ist. Hierbei müsste dann in einem ersten Schritt noch eine OCR-Umwandlung erfolgen.
def get_sprecher(text_list:list)->list:
"""Gibt die einzelnen Sprecher zurück. Der Anfang wird verworfen!"""
sprecher_list = []
for i, text in enumerate(text_list):
if text.isupper():
sprecher_list.append(i)
merged_sprecher = []
for sprecher, _ in enumerate(sprecher_list):
try:
merged_sprecher.append("\n".join(text_list[sprecher_list[sprecher]: sprecher_list[sprecher+1]]))
except IndexError:
merged_sprecher.append("\n".join(text_list[sprecher_list[sprecher]:]))
return merged_sprecher
import fitz
doc = fitz.open("Faust.pdf")
alle_konversationen = []
for page in range(3, 130):
text = doc[page].get_text()
text = text.split("/139")[1].lstrip().split("\n")
alle_konversationen.extend(get_sprecher(text))
alle_konversationen[:2]
['DIREKTOR.\nIhr beiden, die ihr mir so oft,\nIn Not und Trübsal, beigestanden,\n [...]', 'DICHTER.\nIhr fühlet nicht, wie schlecht ein solches Handwerk sei!\n [...]']