Ładowacz JSON

  • JSON (JavaScript Object Notation) to otwarty standardowy format pliku i format wymiany danych, który używa czytelnego tekstu do przechowywania i przesyłania obiektów danych składających się z par atrybut-wartość oraz tablic (lub innych wartości do serializacji).

JSON Lines to format pliku, w którym każda linia jest poprawną wartością JSON.

JSONLoader analizuje pliki JSON za pomocą określonego wzorca jq i wykorzystuje pakiet jq w języku Python. Aby uzyskać szczegółową dokumentację dotyczącą składni jq, proszę odnieść się do odpowiedniej dokumentacji Pythona.

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

file_path = './example_data/facebook_chat.json'
data = json.loads(Path(file_path).read_text())
pprint(data)
{'image': {'creation_timestamp': 1675549016, 'uri': 'image_of_the_chat.jpg'},
     'is_still_participant': True,
     'joinable_mode': {'link': '', 'mode': 1},
     'magic_words': [],
     'messages': [{'content': 'Żegnaj!',
                   'sender_name': 'Użytkownik 2',
                   'timestamp_ms': 1675597571851},
                  {'content': 'O, nic się nie martw! Żegnaj',
                   'sender_name': 'Użytkownik 1',
                   'timestamp_ms': 1675597435669},
                  {'content': 'Nie, przepraszam, to był mój błąd, ten niebieski '
                              'nie jest na sprzedaż',
                   'sender_name': 'Użytkownik 2',
                   'timestamp_ms': 1675596277579},
                  {'content': 'Pomyślałem, że sprzedajesz ten niebieski!',
                   'sender_name': 'Użytkownik 1',
                   'timestamp_ms': 1675595140251},
                  {'content': 'Nie jestem zainteresowany tym workiem. Interesuje '
                              'mnie ten niebieski!',
                   'sender_name': 'Użytkownik 1',
                   'timestamp_ms': 1675595109305},
                  {'content': 'Oto 129 $',
                   'sender_name': 'Użytkownik 2',
                   'timestamp_ms': 1675595068468},
                  {'photos': [{'creation_timestamp': 1675595059,
                               'uri': 'adres_obrazka.jpg'}],
                   'sender_name': 'Użytkownik 2',
                   'timestamp_ms': 1675595060730},
                  {'content': 'Online jest co najmniej 100 $',
                   'sender_name': 'Użytkownik 2',
                   'timestamp_ms': 1675595045152},
                  {'content': 'Ile chcesz?',
                   'sender_name': 'Użytkownik 1',
                   'timestamp_ms': 1675594799696},
                  {'content': 'Dzień dobry! 50 $ to za mało.',
                   'sender_name': 'Użytkownik 2',
                   'timestamp_ms': 1675577876645},
                  {'content': 'Cześć! Jestem zainteresowany twoim workiem. Oferuję '
                              '50 $. Daj mi znać, jeśli jesteś zainteresowany. '
                              'Dzięki!',
                   'sender_name': 'Użytkownik 1',
                   'timestamp_ms': 1675549022673}],
     'participants': [{'name': 'Użytkownik 1'}, {'name': 'Użytkownik 2'}],
     'thread_path': 'skrzynka/Użytkownik 1 i Użytkownik 2 czat',
     'title': 'Użytkownik 1 i Użytkownik 2 czat'}

Korzystanie z JSONLoader

Załóżmy, że chcemy wydobyć wartości z pola content pod kluczem messages w danych JSON. Użycie JSONLoader może łatwo wykonać to zadanie.

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

data = loader.load()
pprint(data)
[Dokument(zawartość_strony='Żegnaj!', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1}),
     Dokument(zawartość_strony='O, nie martw się! Żegnaj', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2}),
     Dokument(zawartość_strony='Nie, przepraszam, to był mój błąd, niebieski nie jest na sprzedaż', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 3}),
     Dokument(zawartość_strony='Pomyślałem, że sprzedajesz ten niebieski!', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 4}),
     Dokument(zawartość_strony='Nie jestem zainteresowany tą torbą. Interesuje mnie ta niebieska!', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 5}),
     Dokument(zawartość_strony='Oto 129 $', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 6}),
     Dokument(zawartość_strony='', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 7}),
     Dokument(zawartość_strony='Online to przynajmniej 100 $', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 8}),
     Dokument(zawartość_strony='Ile chcesz?', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 9}),
     Dokument(zawartość_strony='Dzień dobry! 50 $ to za mało.', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 10}),
     Dokument(zawartość_strony='Cześć! Jestem zainteresowany twoją torebką. Oferuję 50 $. Daj mi znać, czy jesteś zainteresowany. Dzięki!', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 11})]

Plik w formacie JSON Lines

Jeśli chcesz załadować dokumenty z pliku w formacie JSON Lines, musisz przekazać json_lines=True i określić jq_schema, aby wyodrębnić page_content z pojedynczego obiektu JSON.

file_path = './example_data/facebook_chat_messages.jsonl'
pprint(Path(file_path).read_text())
('{"sender_name": "Użytkownik 2", "timestamp_ms": 1675597571851, "content": "Żegnaj!"}\n'
     '{"sender_name": "Użytkownik 1", "timestamp_ms": 1675597435669, "content": "Ach, nie martw się! Żegnaj"}\n'
     '{"sender_name": "Użytkownik 2", "timestamp_ms": 1675596277579, "content": "Nie, przepraszam, to był mój błąd, niebieski nie jest na sprzedaż"}\n')
loader = JSONLoader(
    file_path='./example_data/facebook_chat_messages.jsonl',
    jq_schema='.content',
    json_lines=True)

data = loader.load()
pprint(data)
[Dokument(page_content='Żegnaj!', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 1}),
     Dokument(page_content='Ach, nie martw się! Żegnaj', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 2}),
     Dokument(page_content='Nie, przepraszam, to był mój błąd, niebieski nie jest na sprzedaż', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 3})]

Inną opcją jest ustawienie jq_schema='.' i podanie content_key:

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

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

Wyodrębnianie metadanych

Zazwyczaj chcielibyśmy uwzględnić metadane z pliku JSON w dokumencie utworzonym na podstawie zawartości.

Poniżej przedstawiono, w jaki sposób użyć JSONLoader do wyodrębniania metadanych.

W poprzednim przykładzie nie zbieraliśmy metadanych, ale udało nam się określić w schemacie lokalizację, z której bezpośrednio można wyodrębnić wartość page_content.

.messages[].content

W bieżącym przykładzie musimy powiedzieć ładującemu, aby iterował przez rekordy w polu messages. Następnie jq_schema musi wyglądać tak:

.messages[]

Dzięki temu możemy przekazać rekordy (słowniki) do funkcji "metadata_func", która musi zostać zaimplementowana. "Metadata_func" jest odpowiedzialna za identyfikację informacji o rekordzie, które powinny zostać uwzględnione w metadanych przechowywanych w końcowym obiekcie "Document".

Dodatkowo teraz musimy wyraźnie określić parametr content_key w ładującym, aby wyodrębnić wartość "page_content" z którego klucza w rekordzie.

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(treść_strony='Pa!', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'numer_sekwencji': 1, 'nazwa_nadawcy': 'Użytkownik 2', 'znak_czasu_ms': 1675597571851}),
     Dokument(treść_strony='Spoko, bez problemu! Cześć', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'numer_sekwencji': 2, 'nazwa_nadawcy': 'Użytkownik 1', 'znak_czasu_ms': 1675597435669}),
     Dokument(treść_strony='Nie, przepraszam, to był mój błąd. Niebieska nie jest na sprzedaż', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'numer_sekwencji': 3, 'nazwa_nadawcy': 'Użytkownik 2', 'znak_czasu_ms': 1675596277579}),
     Dokument(treść_strony='Myślałem, że sprzedajesz tę niebieską!', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'numer_sekwencji': 4, 'nazwa_nadawcy': 'Użytkownik 1', 'znak_czasu_ms': 1675595140251}),
     Dokument(treść_strony='Nie jestem zainteresowany tym workiem. Interesuje mnie ten niebieski!', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'numer_sekwencji': 5, 'nazwa_nadawcy': 'Użytkownik 1', 'znak_czasu_ms': 1675595109305}),
     Dokument(treść_strony='Tutaj masz 129 dolarów', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'numer_sekwencji': 6, 'nazwa_nadawcy': 'Użytkownik 2', 'znak_czasu_ms': 1675595068468}),
     Dokument(treść_strony='', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'numer_sekwencji': 7, 'nazwa_nadawcy': 'Użytkownik 2', 'znak_czasu_ms': 1675595060730}),
     Dokument(treść_strony='Online to przynajmniej 100 dolarów', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'numer_sekwencji': 8, 'nazwa_nadawcy': 'Użytkownik 2', 'znak_czasu_ms': 1675595045152}),
     Dokument(treść_strony='Ile chcesz?', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'numer_sekwencji': 9, 'nazwa_nadawcy': 'Użytkownik 1', 'znak_czasu_ms': 1675594799696}),
     Dokument(treść_strony='Dzień dobry! 50 dolarów to za mało.', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'numer_sekwencji': 10, 'nazwa_nadawcy': 'Użytkownik 2', 'znak_czasu_ms': 1675577876645}),
     Dokument(treść_strony='Cześć! Jestem zainteresowany twoim workiem. Oferuję 50 dolarów. Daj mi znać, jeśli jesteś zainteresowany. Dzięki!', metadane={'źródło': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'numer_sekwencji': 11, 'nazwa_nadawcy': 'Użytkownik 1', 'znak_czasu_ms': 1675549022673})]

Tutaj można zobaczyć, że te pliki już zawierają metadane związane z zawartością, którą wyjęliśmy.

Funkcja metadata_func

Jak pokazano powyżej, funkcja metadata_func otrzymuje domyślne metadane wygenerowane przez JSONLoader. Pozwala to użytkownikom na pełną kontrolę nad formatem metadanych.

Na przykład domyślne metadane zawierają klucze source i seq_num. Jednak dane JSON mogą również zawierać te klucze. Użytkownicy mogą użyć funkcji metadata_func do zmiany nazw domyślnych kluczy i wykorzystania kluczy z danych JSON.

Poniższy przykład demonstruje, jak zmodyfikować source, aby zawierał tylko informacje o źródle pliku związane z katalogiem langchain.

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)
[Dokument(treść_strony='Bye!', metadane={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1, 'sender_name': 'Użytkownik 2', 'timestamp_ms': 1675597571851}),
     Dokument(treść_strony='Oh no worries! Bye', metadane={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2, 'sender_name': 'Użytkownik 1', 'timestamp_ms': 1675597435669}),
     ...
     ...
     ... (pozostała zawartość niezmieniona ze względu na zwięzłość) ...
     ...
     ...
]

Powszechne struktury JSON do używania schematów jq

Poniższa lista przedstawia możliwe jq_schema, które użytkownicy mogą użyć jako odniesienie do wyodrębniania zawartości z danych JSON na podstawie struktury.

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

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

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