JSON-Lader

  • JSON (JavaScript Object Notation) ist ein offenes Standard-Dateiformat und Dateninterchange-Format, das lesbarer Text verwendet, um Datenobjekte, die aus Attribut-Wert-Paaren und Arrays (oder anderen serialisierbaren Werten) bestehen, zu speichern und zu übertragen.

JSON Lines ist ein Dateiformat, bei dem jede Zeile einen gültigen JSON-Wert darstellt.

JSONLoader analysiert JSON-Dateien mithilfe eines angegebenen jq-Musters und verwendet das Python-Paket jq. Für ausführliche Dokumentation zur jq-Syntax siehe die entsprechende Python-Dokumentation.

from langchain_community.document_loaders import JSONLoader
import json
from pathlib import Path
from pprint import pprint

file_path = './beispiel_daten/facebook_chat.json'
data = json.loads(Path(file_path).read_text())
pprint(data)
{'image': {'creation_timestamp': 1675549016, 'uri': 'bild_des_chats.jpg'},
     'is_still_participant': True,
     'joinable_mode': {'link': '', 'mode': 1},
     'magic_words': [],
     'messages': [{'content': 'Tschüss!',
                   'sender_name': 'Benutzer 2',
                   'timestamp_ms': 1675597571851},
                  {'content': 'Ach, mach dir keine Sorgen! Tschüss',
                   'sender_name': 'Benutzer 1',
                   'timestamp_ms': 1675597435669},
                  {'content': 'Nein, tut mir leid, das war mein Fehler, der blaue ist nicht '
                              'zum Verkauf',
                   'sender_name': 'Benutzer 2',
                   'timestamp_ms': 1675596277579},
                  {'content': 'Ich dachte, du verkaufst den blauen!',
                   'sender_name': 'Benutzer 1',
                   'timestamp_ms': 1675595140251},
                  {'content': 'Ich bin nicht an dieser Tasche interessiert. Ich bin an der '
                              'blauen interessiert!',
                   'sender_name': 'Benutzer 1',
                   'timestamp_ms': 1675595109305},
                  {'content': 'Hier sind $129',
                   'sender_name': 'Benutzer 2',
                   'timestamp_ms': 1675595068468},
                  {'photos': [{'creation_timestamp': 1675595059,
                               'uri': 'url_des_einigen_bildes.jpg'}],
                   'sender_name': 'Benutzer 2',
                   'timestamp_ms': 1675595060730},
                  {'content': 'Online kostet es mindestens $100',
                   'sender_name': 'Benutzer 2',
                   'timestamp_ms': 1675595045152},
                  {'content': 'Wie viel willst du?',
                   'sender_name': 'Benutzer 1',
                   'timestamp_ms': 1675594799696},
                  {'content': 'Guten Morgen! $50 sind zu wenig.',
                   'sender_name': 'Benutzer 2',
                   'timestamp_ms': 1675577876645},
                  {'content': 'Hallo! Ich bin an deiner Tasche interessiert. Ich biete $50 an. Lass '
                              'mich wissen, ob du interessiert bist. Danke!',
                   'sender_name': 'Benutzer 1',
                   'timestamp_ms': 1675549022673}],
     'participants': [{'name': 'Benutzer 1'}, {'name': 'Benutzer 2'}],
     'thread_path': 'inbox/Benutzer 1 and Benutzer 2 chat',
     'title': 'Benutzer 1 und Benutzer 2 chat'}

Verwendung von JSONLoader

Angenommen, wir möchten Werte aus dem Feld content unter dem Schlüssel messages in den JSON-Daten extrahieren. Mit Hilfe von JSONLoader kann diese Aufgabe leicht erledigt werden.

loader = JSONLoader(
    file_path='./example_data/facebook_chat.json',
    jq_schema='.messages[].content')

data = loader.load()
pprint(data)
[Dokument(seiteninhalt='Tschüss!', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1}),
     Dokument(seiteninhalt='Ach, keine Sorge! Tschüss', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2}),
     Dokument(seiteninhalt='Entschuldigung, mein Fehler. Der blaue ist nicht zum Verkauf', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 3}),
     Dokument(seiteninhalt='Ich dachte, du verkaufst den blauen!', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 4}),
     Dokument(seiteninhalt='Ich bin nicht an dieser Tasche interessiert. Ich interessiere mich für den blauen!', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 5}),
     Dokument(seiteninhalt='Hier sind 129 Dollar', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 6}),
     Dokument(seiteninhalt='', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 7}),
     Dokument(seiteninhalt='Online sind es mindestens 100 Dollar', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 8}),
     Dokument(seiteninhalt='Wie viel möchtest du haben?', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 9}),
     Dokument(seiteninhalt='Guten Morgen! 50 Dollar sind zu wenig.', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 10}),
     Dokument(seiteninhalt='Hallo! Ich interessiere mich für deine Tasche. Ich biete 50 Dollar an. Lass mich wissen, wenn du interessiert bist. Danke!', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 11})]

JSON-Lines-Datei

Wenn du Dokumente aus einer JSON-Lines-Datei laden möchtest, musst du json_lines=True übergeben und das jq_schema spezifizieren, um den page_content aus einem einzelnen JSON-Objekt zu extrahieren.

file_path = './BeispielDaten/facebook_chat_messages.jsonl'
pprint(Path(file_path).read_text())
('{"sender_name": "Benutzer 2", "timestamp_ms": 1675597571851, "content": "Tschüss!"}\n'
     '{"sender_name": "Benutzer 1", "timestamp_ms": 1675597435669, "content": "Ach '
     'mach dir keine Sorgen! Tschüss"}\n'
     '{"sender_name": "Benutzer 2", "timestamp_ms": 1675596277579, "content": "Nein, Entschuldigung, mein Fehler. Der blaue ist nicht zum Verkauf"}\n')
loader = JSONLoader(
    file_path='./BeispielDaten/facebook_chat_messages.jsonl',
    jq_schema='.content',
    json_lines=True)

data = loader.load()
pprint(data)
[Dokument(page_content='Tschüss!', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 1}),
     Dokument(page_content='Ach mach dir keine Sorgen! Tschüss', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 2}),
     Dokument(page_content='Nein, Entschuldigung, mein Fehler. Der blaue ist nicht zum Verkauf', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 3})]

Eine andere Option ist es, jq_schema='.' zu setzen und content_key zu definieren:

loader = JSONLoader(
    file_path='./BeispielDaten/facebook_chat_messages.jsonl',
    jq_schema='.',
    content_key='sender_name',
    json_lines=True)

data = loader.load()
pprint(data)
[Dokument(page_content='Benutzer 2', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 1}),
     Dokument(page_content='Benutzer 1', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 2}),
     Dokument(page_content='Benutzer 2', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 3})]

Metadaten extrahieren

Normalerweise möchten wir die Metadaten aus einer JSON-Datei im Dokument einschließen, das wir aus dem Inhalt erstellen.

Im Folgenden wird gezeigt, wie man JSONLoader verwendet, um Metadaten zu extrahieren.

Im vorherigen Beispiel haben wir keine Metadaten gesammelt, aber es ist uns gelungen, im Schema anzugeben, wo der Wert page_content direkt extrahiert werden kann.

.messages[].content

Im aktuellen Beispiel müssen wir dem Loader mitteilen, dass er über die Datensätze im Feld messages iterieren soll. Dann muss das jq_schema lauten:

.messages[]

Dadurch können wir die Datensätze (Dictionaries) an die "metadata_func" übergeben, die implementiert werden muss. Die "metadata_func" ist dafür verantwortlich, zu identifizieren, welche Datensatzinformationen in den Metadaten enthalten sein sollen, die im finalen "Document"-Objekt gespeichert werden.

Zusätzlich müssen wir nun explizit den Parameter content_key im Loader angeben, um den Wert "page_content" aus dem Schlüssel im Datensatz zu extrahieren.

def metadata_func(record: dict, metadata: dict) -> dict:

    metadata["sender_name"] = record.get("sender_name")
    metadata["timestamp_ms"] = record.get("timestamp_ms")

    return metadata

loader = JSONLoader(
    file_path='./example_data/facebook_chat.json',
    jq_schema='.messages[]',
    content_key="content",
    metadata_func=metadata_func
)

data = loader.load()
pprint(data)
[Dokument(page_content='Tschüss!', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1, 'sender_name': 'Benutzer 2', 'timestamp_ms': 1675597571851}),
     Dokument(page_content='Ach, keine Sorge! Tschüss', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2, 'sender_name': 'Benutzer 1', 'timestamp_ms':1675597435669}),
     Dokument(page_content='Nein, es tut mir leid, es war mein Fehler. Der Blaue ist nicht zum Verkauf', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 3, 'sender_name': 'Benutzer 2', 'timestamp_ms': 1675596277579}),
     Dokument(page_content='Ich dachte, du wolltest den blauen kaufen!', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 4, 'sender_name': 'Benutzer 1', 'timestamp_ms': 1675595140251}),
     Dokument(page_content='Ich bin nicht an dieser Tasche interessiert. Ich möchte die blaue haben!', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 5, 'sender_name': 'Benutzer 1', 'timestamp_ms': 1675595109305}),
     Dokument(page_content='Hier sind $129', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 6, 'sender_name': 'Benutzer 2', 'timestamp_ms': 1675595068468}),
     Dokument(page_content='', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 7, 'sender_name': 'Benutzer 2', 'timestamp_ms': 1675595060730}),
     Dokument(page_content='Online kostet es mindestens $100', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 8, 'sender_name': 'Benutzer 2', 'timestamp_ms': 1675595045152}),
     Dokument(page_content='Wie viel möchtest du?', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 9, 'sender_name': 'Benutzer 1', 'timestamp_ms': 1675594799696}),
     Dokument(page_content='Guten Morgen! 50$ ist zu wenig.', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 10, 'sender_name': 'Benutzer 2', 'timestamp_ms': 1675577876645}),
     Dokument(page_content='Hi! Ich interessiere mich für deine Tasche. Ich biete 50$. Lass mich wissen, ob du interessiert bist. Danke!', metadaten={'quelle': '/Benutzer/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 11, 'sender_name': 'Benutzer 1', 'timestamp_ms': 1675549022673})]

Hier können wir sehen, dass diese Dateien bereits Metadaten zum Inhalt enthalten, den wir extrahiert haben.

Funktion metadata_func

Wie oben gezeigt, erhält metadata_func die Standardmetadaten, die von JSONLoader generiert wurden. Dies ermöglicht es den Benutzern, die vollständige Kontrolle über das Format der Metadaten zu haben.

Beispielsweise enthält die Standardmetadaten die Schlüssel source und seq_num. Allerdings kann die JSON-Daten auch diese Schlüssel enthalten. Benutzer können metadata_func verwenden, um die Standard-Schlüssel umzubenennen und die Schlüssel aus den JSON-Daten zu verwenden.

Das folgende Beispiel zeigt, wie man die source ändert, um nur die Dateiquelleinformationen des Verzeichnisses langchain einzuschließen.

def metadata_func(record: dict, metadata: dict) -> dict:

    metadata["sender_name"] = record.get("sender_name")
    metadata["timestamp_ms"] = record.get("timestamp_ms")

    if "source" in metadata:
        source = metadata["source"].split("/")
        source = source[source.index("langchain"):]
        metadata["source"] = "/".join(source)

    return metadata

loader = JSONLoader(
    file_path='./example_data/facebook_chat.json',
    jq_schema='.messages[]',
    content_key="content",
    metadata_func=metadata_func
)

data = loader.load()
pprint(data)
[Document(page_content='Bye!', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1, 'sender_name': 'Benutzer 2', 'timestamp_ms': 1675597571851}),
     Document(page_content='Kein Problem! Tschüss', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2, 'sender_name': 'Benutzer 1', 'timestamp_ms': 1675597435669}),
     ...
     ...
     ... (restlicher Inhalt unverändert der Kürze halber) ...
     ...
     ...
]

Gemeinsame JSON-Strukturen für die Verwendung von jq-Mustern

Die folgende Liste bietet mögliche jq_schema, die Benutzer als Referenz für das Extrahieren von Inhalten aus JSON-Daten basierend auf der Struktur verwenden können.

JSON        -> [{"text": ...}, {"text": ...}, {"text": ...}]
jq_schema   -> ".[].text"

JSON        -> {"key": [{"text": ...}, {"text": ...}, {"text": ...}]}
jq_schema   -> ".key[].text"

JSON        -> ["...", "...", "..."]
jq_schema   -> ".[]"