Chargeur JSON

  • JSON (JavaScript Object Notation) est un format de fichier standard ouvert et un format d'échange de données qui utilise un texte lisible pour stocker et transmettre des objets de données composés de paires attribut-valeur et de tableaux (ou d'autres valeurs sérialisables).

JSON Lines est un format de fichier où chaque ligne est une valeur JSON valide.

JSONLoader analyse les fichiers JSON à l'aide d'un motif jq spécifié et utilise le package jq Python. Pour une documentation détaillée sur la syntaxe jq, veuillez vous référer à la documentation Python pertinente.

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

chemin_fichier = './exemple_donnees/discussion_facebook.json'
donnees = json.loads(Path(chemin_fichier).read_text())
pprint(donnees)
{'image': {'creation_timestamp': 1675549016, 'uri': 'image_de_la_discussion.jpg'},
     'is_still_participant': True,
     'joinable_mode': {'link': '', 'mode': 1},
     'magic_words': [],
     'messages': [{'content': 'Au revoir!',
                   'sender_name': 'Utilisateur 2',
                   'timestamp_ms': 1675597571851},
                  {'content': 'Oh, pas de soucis ! Au revoir',
                   'sender_name': 'Utilisateur 1',
                   'timestamp_ms': 1675597435669},
                  {'content': 'Non, désolé, c'était mon erreur, le bleu n'est pas '
                              'à vendre',
                   'sender_name': 'Utilisateur 2',
                   'timestamp_ms': 1675596277579},
                  {'content': 'Je pensais que vous vendiez le bleu !',
                   'sender_name': 'Utilisateur 1',
                   'timestamp_ms': 1675595140251},
                  {'content': 'Je ne suis pas intéressé par ce sac. Je suis '
                              'intéressé par le bleu !',
                   'sender_name': 'Utilisateur 1',
                   'timestamp_ms': 1675595109305},
                  {'content': 'Voici 129 $',
                   'sender_name': 'Utilisateur 2',
                   'timestamp_ms': 1675595068468},
                  {'photos': [{'creation_timestamp': 1675595059,
                               'uri': 'url_de_une_image.jpg'}],
                   'sender_name': 'Utilisateur 2',
                   'timestamp_ms': 1675595060730},
                  {'content': 'En ligne, c'est au moins 100 $',
                   'sender_name': 'Utilisateur 2',
                   'timestamp_ms': 1675595045152},
                  {'content': 'Combien en voulez-vous ?',
                   'sender_name': 'Utilisateur 1',
                   'timestamp_ms': 1675594799696},
                  {'content': 'Bonjour ! 50 $, c'est trop peu.',
                   'sender_name': 'Utilisateur 2',
                   'timestamp_ms': 1675577876645},
                  {'content': 'Salut ! Je suis intéressé par votre sac. Je propose '
                              '50 $. Faites-moi savoir si vous êtes intéressé. '
                              'Merci!',
                   'sender_name': 'Utilisateur 1',
                   'timestamp_ms': 1675549022673}],
     'participants': [{'name': 'Utilisateur 1'}, {'name': 'Utilisateur 2'}],
     'thread_path': 'boîte de réception/discussion Utilisateur 1 et Utilisateur 2',
     'title': 'Discussion Utilisateur 1 et Utilisateur 2'}

Utilisation de JSONLoader

Supposons que nous voulons extraire les valeurs du champ content sous la clé messages dans les données JSON. L'utilisation de JSONLoader peut facilement accomplir cette tâche.

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

data = loader.load()
pprint(data)
[Document(page_content='Au revoir!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1}),
     Document(page_content='Oh non, pas de soucis! Au revoir', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2}),
     Document(page_content='Non, désolé, c'était mon erreur, le bleu n'est pas à vendre', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 3}),
     Document(page_content='Je pensais que vous vendiez le bleu!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 4}),
     Document(page_content='Je ne suis pas intéressé par ce sac. Je suis intéressé par le bleu!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 5}),
     Document(page_content='Voici 129 $', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 6}),
     Document(page_content='', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 7}),
     Document(page_content='En ligne, c'est au moins 100 $', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 8}),
     Document(page_content='Combien en voulez-vous?', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 9}),
     Document(page_content='Bonjour! 50 $, c'est trop peu.', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 10}),
     Document(page_content='Salut! Je suis intéressé par votre sac. Je propose 50 $. Faites-moi savoir si vous êtes intéressé. Merci!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 11})]

Fichier JSON Lines

Si vous souhaitez charger des documents à partir d'un fichier JSON Lines, vous devez passer json_lines=True et spécifier le jq_schema pour extraire le page_content à partir d'un objet JSON unique.

file_path = './example_data/facebook_chat_messages.jsonl'
pprint(Path(file_path).read_text())
('{"sender_name": "Utilisateur 2", "timestamp_ms": 1675597571851, "content": "Au revoir !"}\n'
     '{"sender_name": "Utilisateur 1", "timestamp_ms": 1675597435669, "content": "Oh pas de soucis ! Au revoir"}\n'
     '{"sender_name": "Utilisateur 2", "timestamp_ms": 1675596277579, "content": "Non, désolé, c'était mon erreur, le bleu n'est pas à vendre"}\n')
loader = JSONLoader(
    file_path='./example_data/facebook_chat_messages.jsonl',
    jq_schema='.content',
    json_lines=True)

data = loader.load()
pprint(data)
[Document(page_content='Au revoir !', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 1}),
     Document(page_content='Oh pas de soucis ! Au revoir', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 2}),
     Document(page_content="Non, désolé, c'était mon erreur, le bleu n'est pas à vendre", metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 3})]

Une autre option est de définir jq_schema='.' et de fournir 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)
[Document(page_content='Utilisateur 2', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 1}),
     Document(page_content='Utilisateur 1', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 2}),
     Document(page_content='Utilisateur 2', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 3})]

Extraction de métadonnées

En général, nous aimerions inclure les métadonnées d'un fichier JSON dans le document que nous créons à partir du contenu.

Ce qui suit montre comment utiliser JSONLoader pour extraire des métadonnées.

Dans l'exemple précédent, nous n'avons pas collecté de métadonnées, mais nous avons réussi à spécifier dans le schéma l'emplacement à partir duquel la valeur page_content peut être extraite directement.

.messages[].content

Dans l'exemple actuel, nous devons indiquer au chargeur d'itérer sur les enregistrements dans le champ messages. Ensuite, le jq_schema doit être :

.messages[]

Cela nous permet de transmettre les enregistrements (dictionnaires) à la "metadata_func" qui doit être implémentée. La "metadata_func" est responsable d'identifier quelles informations d'enregistrement doivent être incluses dans les métadonnées à stocker dans l'objet "Document" final.

De plus, nous devons maintenant spécifier explicitement le paramètre content_key dans le chargeur pour extraire la valeur "page_content" à partir de quelle clé dans l'enregistrement.

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)
[Document(page_content='Au revoir!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1, 'sender_name': 'Utilisateur 2', 'timestamp_ms': 1675597571851}),
     Document(page_content='Oh, pas de soucis! Au revoir', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2, 'sender_name': 'Utilisateur 1', 'timestamp_ms': 1675597435669}),
     Document(page_content='Non, je suis désolé, c'était mon erreur. Le bleu n'est pas à vendre', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 3, 'sender_name': 'Utilisateur 2', 'timestamp_ms': 1675596277579}),
     Document(page_content='Je pensais que vous vendiez le bleu!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 4, 'sender_name': 'Utilisateur 1', 'timestamp_ms': 1675595140251}),
     Document(page_content='Je ne suis pas intéressé par ce sac. Je m'intéresse au bleu!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 5, 'sender_name': 'Utilisateur 1', 'timestamp_ms': 1675595109305}),
     Document(page_content='Voici 129$', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 6, 'sender_name': 'Utilisateur 2', 'timestamp_ms': 1675595068468}),
     Document(page_content='', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 7, 'sender_name': 'Utilisateur 2', 'timestamp_ms': 1675595060730}),
     Document(page_content='En ligne, c'est au moins 100$', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 8, 'sender_name': 'Utilisateur 2', 'timestamp_ms': 1675595045152}),
     Document(page_content='Combien en voulez-vous?', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 9, 'sender_name': 'Utilisateur 1', 'timestamp_ms': 1675594799696}),
     Document(page_content='Bonjour! 50$ c'est trop peu.', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 10, 'sender_name': 'Utilisateur 2', 'timestamp_ms': 1675577876645}),
     Document(page_content='Salut! Je suis intéressé par votre sac. Je propose 50$. Faites-moi savoir si cela vous intéresse. Merci!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 11, 'sender_name': 'Utilisateur 1', 'timestamp_ms': 1675549022673})]

Ici, nous pouvons voir que ces fichiers contiennent déjà des métadonnées liées au contenu que nous avons extrait.

Fonction metadata_func

Comme indiqué ci-dessus, metadata_func reçoit les métadonnées par défaut générées par JSONLoader. Cela permet aux utilisateurs d'avoir un contrôle complet sur le format des métadonnées.

Par exemple, les métadonnées par défaut contiennent les clés source et seq_num. Cependant, les données JSON peuvent également contenir ces clés. Les utilisateurs peuvent utiliser metadata_func pour renommer les clés par défaut et utiliser les clés des données JSON.

L'exemple suivant montre comment modifier la clé source pour inclure uniquement les informations source du fichier liées au répertoire 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)
[Document(page_content='Bye!', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1, 'sender_name': 'Utilisateur 2', 'timestamp_ms': 1675597571851}),
     Document(page_content='Oh, pas de soucis! Au revoir', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2, 'sender_name': 'Utilisateur 1', 'timestamp_ms': 1675597435669}),
     ...
     ...
     ... (contenu restant inchangé par souci de concision) ...
     ...
     ...
]

Structures JSON courantes pour l'utilisation de motifs jq

La liste suivante fournit des jq_schema possibles que les utilisateurs peuvent utiliser comme référence pour extraire du contenu à partir de données JSON en fonction de la structure.

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

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

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