JSONローダー
- JSON(JavaScript Object Notation)は、属性と値のペアおよび配列(またはその他の直列化可能な値)からなるデータオブジェクトを格納および転送するために可読性の高いテキストを使用するオープン標準のファイル形式およびデータ交換形式です。
JSON Linesは、各行が有効なJSON値であるファイル形式です。
JSONLoaderは、指定されたjqパターンを使用してJSONファイルを解析し、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.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
の使用
JSONデータのmessages
キーの下のcontent
フィールドから値を抽出したいとします。JSONLoader
を使用することで、このタスクを簡単に達成できます。
loader = JSONLoader(
file_path='./example_data/facebook_chat.json',
jq_schema='.messages[].content')
data = loader.load()
pprint(data)
[Document(page_content='バイ!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1}),
Document(page_content='大丈夫です!バイ', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2}),
Document(page_content='いや、申し訳ありません。青い方は売り物ではありませんでした', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 3}),
Document(page_content='青い方を販売していると思っていました!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 4}),
Document(page_content='私はこのバッグに興味がありません。青い方に興味があります!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 5}),
Document(page_content='こちらは$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='オンラインでは少なくとも$100です', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 8}),
Document(page_content='いくらほしいですか?', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 9}),
Document(page_content='おはようございます!$50は低すぎます。', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 10}),
Document(page_content='こんにちは!あなたのバッグに興味があります。$50をオファーしています。興味があれば教えてください。ありがとうございます!', metadata={'source': '/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
を指定して単一のJSONオブジェクトからpage_content
を抽出する必要があります。
file_path = './example_data/facebook_chat_messages.jsonl'
pprint(Path(file_path).read_text())
('{"sender_name": "User 2", "timestamp_ms": 1675597571851, "content": "さようなら!"}\n'
'{"sender_name": "User 1", "timestamp_ms": 1675597435669, "content": "大丈夫、さようなら"}\n'
'{"sender_name": "User 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='User 2', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 1}),
Document(page_content='User 1', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 2}),
Document(page_content='User 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"に含めるべきレコード情報を識別します。"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)
[Document(page_content='さようなら!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1, 'sender_name': 'User 2', 'timestamp_ms': 1675597571851}),
Document(page_content='大丈夫です!さようなら', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2, 'sender_name': 'User 1', 'timestamp_ms': 1675597435669}),
Document(page_content='いいえ、私の間違いでした。青いのは販売していません', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 3, 'sender_name': 'User 2', 'timestamp_ms': 1675596277579}),
Document(page_content='青いのを販売していると思っていました!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 4, 'sender_name': 'User 1', 'timestamp_ms': 1675595140251}),
Document(page_content='このバッグには興味がありません。青いのに興味があります!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 5, 'sender_name': 'User 1', 'timestamp_ms': 1675595109305}),
Document(page_content='$129です', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 6, 'sender_name': 'User 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': 'User 2', 'timestamp_ms': 1675595060730}),
Document(page_content='オンラインでは少なくとも$100です', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 8, 'sender_name': 'User 2', 'timestamp_ms': 1675595045152}),
Document(page_content='いくらほしいですか?', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 9, 'sender_name': 'User 1', 'timestamp_ms': 1675594799696}),
Document(page_content='おはようございます!$50はあまりにも安いです。', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 10, 'sender_name': 'User 2', 'timestamp_ms': 1675577876645}),
Document(page_content='こんにちは!バッグに興味があります。$50で提供します。興味があれば知らせてください。ありがとうございます!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 11, 'sender_name': 'User 1', 'timestamp_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='Bye!', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1, 'sender_name': 'User 2', 'timestamp_ms': 1675597571851}),
Document(page_content='Oh no worries! Bye', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2, 'sender_name': 'User 1', 'timestamp_ms': 1675597435669}),
...
...
...(簡潔さのために残りのコンテンツは変更せずに省略されています)...
...
...
]
jqパターンを使用した一般的なJSON構造
以下のリストは、構造に基づいてJSONデータからコンテンツを抽出する際に参考にできる可能性のある jq_schema
を提供しています。
JSON -> [{"text": ...}, {"text": ...}, {"text": ...}]
jq_schema -> ".[].text"
JSON -> {"key": [{"text": ...}, {"text": ...}, {"text": ...}]}
jq_schema -> ".key[].text"
JSON -> ["...", "...", "..."]
jq_schema -> ".[]"