Загрузчик JSON
- JSON (JavaScript Object Notation) - это открытый стандартный формат файла и формат обмена данными, который использует читаемый текст для хранения и передачи объектов данных, состоящих из пар атрибут-значение и массивов (или других сериализуемых значений).
JSON Lines - это формат файла, в котором каждая строка является допустимым значением JSON.
JSONLoader разбирает JSON-файлы с использованием указанного шаблона jq и использует пакет jq Python. Для подробной документации по синтаксису jq обратитесь к соответствующей документации Python.
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': 'Пока!',
'sender_name': 'Пользователь 2',
'timestamp_ms': 1675597571851},
{'content': 'О, не беспокойся! Пока',
'sender_name': 'Пользователь 1',
'timestamp_ms': 1675597435669},
{'content': 'Нет, извини, это была моя ошибка, синяя не '
'продаётся',
'sender_name': 'Пользователь 2',
'timestamp_ms': 1675596277579},
{'content': 'Думал, ты продаёшь синюю!',
'sender_name': 'Пользователь 1',
'timestamp_ms': 1675595140251},
{'content': 'Мне не интересен этот мешок. Мне интересна '
'синяя сумка!',
'sender_name': 'Пользователь 1',
'timestamp_ms': 1675595109305},
{'content': 'Вот $129',
'sender_name': 'Пользователь 2',
'timestamp_ms': 1675595068468},
{'photos': [{'creation_timestamp': 1675595059,
'uri': 'url_of_some_picture.jpg'}],
'sender_name': 'Пользователь 2',
'timestamp_ms': 1675595060730},
{'content': 'Онлайн хотя бы $100',
'sender_name': 'Пользователь 2',
'timestamp_ms': 1675595045152},
{'content': 'Сколько хочешь?',
'sender_name': 'Пользователь 1',
'timestamp_ms': 1675594799696},
{'content': 'Доброе утро! $50 - слишком мало.',
'sender_name': 'Пользователь 2',
'timestamp_ms': 1675577876645},
{'content': 'Привет! Я заинтересован в твоей сумке. Предлагаю '
'$50. Дай знать, если заинтересован. Спасибо!',
'sender_name': 'Пользователь 1',
'timestamp_ms': 1675549022673}],
'participants': [{'name': 'Пользователь 1'}, {'name': 'Пользователь 2'}],
'thread_path': 'inbox/Чат Пользователь 1 и Пользователь 2',
'title': 'Чат Пользователь 1 и Пользователь 2'}
Использование JSONLoader
Предположим, что мы хотим извлечь значения из поля content
под ключом messages
в JSON-данных. Используя JSONLoader
, эту задачу легко можно выполнить.
loader = JSONLoader(
file_path='./example_data/facebook_chat.json',
jq_schema='.messages[].content')
data = loader.load()
pprint(data)
[Документ(содержание_страницы='Пока!', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1}),
Документ(содержание_страницы='О, не волнуйтесь! Пока', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2}),
Документ(содержание_страницы='Нет, извините, это была моя ошибка, синий не продаётся', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 3}),
Документ(содержание_страницы='Я думал, что вы продаёте синий!', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 4}),
Документ(содержание_страницы='Мне не интересна эта сумка. Мне интересен синий!', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 5}),
Документ(содержание_страницы='Вот $129', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 6}),
Документ(содержание_страницы='', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 7}),
Документ(содержание_страницы='Онлайн как минимум $100', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 8}),
Документ(содержание_страницы='Сколько вы хотите?', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 9}),
Документ(содержание_страницы='Доброе утро! $50 слишком мало.', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 10}),
Документ(содержание_страницы='Привет! Я заинтересован в вашей сумке. Я предлагаю $50. Скажите мне, если вас заинтересовало. Спасибо!', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 11})]
Файл JSON Lines
Если вы хотите загрузить документы из файла JSON Lines, вам нужно передать json_lines=True
и указать jq_schema
для извлечения page_content
из одного JSON-объекта.
file_path = './example_data/facebook_chat_messages.jsonl'
pprint(Path(file_path).read_text())
('{"sender_name": "Пользователь 2", "timestamp_ms": 1675597571851, "content": "Пока!"}\n'
'{"sender_name": "Пользователь 1", "timestamp_ms": 1675597435669, "content": "О, ничего страшного! Пока"}\n'
'{"sender_name": "Пользователь 2", "timestamp_ms": 1675596277579, "content": "Извини, это была моя ошибка, синяя не продается"}\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='Пока!', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 1}),
Document(page_content='О, ничего страшного! Пока', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 2}),
Document(page_content='Извини, это была моя ошибка, синяя не продается', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 3})]
Другой вариант - установить jq_schema='.'
и предоставить 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='Пользователь 2', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 1}),
Document(page_content='Пользователь 1', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 2}),
Document(page_content='Пользователь 2', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 3})]
Извлечение метаданных
Обычно мы хотим включить метаданные из файла JSON в документ, который мы создаем из контента.
Ниже приведен пример того, как использовать JSONLoader
для извлечения метаданных.
В предыдущем примере мы не собирали метаданные, но смогли указать в схеме местоположение, откуда можно извлечь значение page_content
напрямую.
.messages[].content
В текущем примере нам нужно указать загрузчику перебирать записи в поле messages
. Затем jq_schema
должна быть следующей:
.messages[]
Это позволит нам передавать записи (словари) в "metadata_func", который должен быть реализован. "metadata_func" отвечает за определение информации о записи, которая должна быть включена в метаданные, которые будут сохранены в итоговом объекте "Document".
Кроме того, теперь нам нужно явно указать параметр content_key
в загрузчике для извлечения значения "page_content" из ключа в записи.
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)
[Документ(page_content='Пока!', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1, 'отправитель': 'Пользователь 2', 'временная_отметка_ms': 1675597571851}),
Документ(page_content='О, ничего страшного! Пока', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2, 'отправитель': 'Пользователь 1', 'временная_отметка_ms': 1675597435669}),
Документ(page_content='Нет, извините, это была моя ошибка. Синий не продается', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 3, 'отправитель': 'Пользователь 2', 'временная_отметка_ms': 1675596277579}),
Документ(page_content='Я подумал, что вы продаёте синий!', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 4, 'отправитель': 'Пользователь 1', 'временная_отметка_ms': 1675595140251}),
Документ(page_content='Мне не интересна эта сумка. Мне интересен синий!', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 5, 'отправитель': 'Пользователь 1', 'временная_отметка_ms': 1675595109305}),
Документ(page_content='Вот $129', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 6, 'отправитель': 'Пользователь 2', 'временная_отметка_ms': 1675595068468}),
Документ(page_content='', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 7, 'отправитель': 'Пользователь 2', 'временная_отметка_ms': 1675595060730}),
Документ(page_content='Онлайн это по крайней мере $100', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 8, 'отправитель': 'Пользователь 2', 'временная_отметка_ms': 1675595045152}),
Документ(page_content='Сколько вы хотите?', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 9, 'отправитель': 'Пользователь 1', 'временная_отметка_ms': 1675594799696}),
Документ(page_content='Доброе утро! $50 это слишком мало.', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 10, 'отправитель': 'Пользователь 2', 'временная_отметка_ms': 1675577876645}),
Документ(page_content='Привет! Мне интересна ваша сумка. Предлагаю $50. Дайте знать, если заинтересованы. Спасибо!', метаданные={'источник': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 11, 'отправитель': 'Пользователь 1', 'временная_отметка_ms': 1675549022673})]
Здесь мы можем видеть, что эти файлы уже содержат метаданные, связанные с извлеченным содержимым.
Функция metadata_func
Как показано выше, функция metadata_func
получает метаданные по умолчанию, сгенерированные JSONLoader
. Это позволяет пользователям полностью контролировать формат метаданных.
Например, метаданные по умолчанию содержат ключи source
и seq_num
. Однако JSON-данные также могут содержать эти ключи. Пользователи могут использовать функцию metadata_func
для переименования ключей по умолчанию и использования ключей из JSON-данных.
В следующем примере показано, как изменить source
, чтобы включить информацию о исходном файле, относящуюся к каталогу 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='Пока!', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1, 'sender_name': 'Пользователь 2', 'timestamp_ms': 1675597571851}),
Document(page_content='О, не беспокойся! Пока', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2, 'sender_name': 'Пользователь 1', 'timestamp_ms': 1675597435669}),
...
...
... (оставшееся содержимое неизменно для краткости) ...
...
...
]
Общие структуры JSON для использования шаблонов jq
Нижеприведенный список предоставляет возможные jq_schema
, которые пользователи могут использовать в качестве справки для извлечения содержимого из JSON-данных на основе структуры.
JSON -> [{"text": ...}, {"text": ...}, {"text": ...}]
jq_schema -> ".[].text"
JSON -> {"key": [{"text": ...}, {"text": ...}, {"text": ...}]}
jq_schema -> ".key[].text"
JSON -> ["...", "...", "..."]
jq_schema -> ".[]"