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_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
사용하기
만약 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
를 전달하고 단일 JSON 객체에서 page_content
를 추출하기 위해 jq_schema
를 지정해야합니다.
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)
[문서(page_content='잘 가!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1, 'sender_name': '사용자 2', 'timestamp_ms': 1675597571851}),
문서(page_content='아니 괜찮아! 잘 가', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2, 'sender_name': '사용자 1', 'timestamp_ms': 1675597435669}),
문서(page_content='안녕, 죄송해요. 저의 실수였어요. 파란색은 판매 대상이 아니에요', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 3, 'sender_name': '사용자 2', 'timestamp_ms': 1675596277579}),
문서(page_content='파란 걸 판다고 생각했어요!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 4, 'sender_name': '사용자 1', 'timestamp_ms': 1675595140251}),
문서(page_content='이 가방에는 관심 없어요. 파란 건에 관심이 있어요!', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 5, 'sender_name': '사용자 1', 'timestamp_ms': 1675595109305}),
문서(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': '사용자 2', 'timestamp_ms': 1675595068468}),
문서(page_content='', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 7, 'sender_name': '사용자 2', 'timestamp_ms': 1675595060730}),
문서(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': '사용자 2', 'timestamp_ms': 1675595045152}),
문서(page_content='얼마에 팔려고 해요?', metadata={'source': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 9, 'sender_name': '사용자 1', 'timestamp_ms': 1675594799696}),
문서(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': '사용자 2', 'timestamp_ms': 1675577876645}),
문서(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': '사용자 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 -> ".[]"