Ł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 -> ".[]"