بارگذاری کننده 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': 'آدرس_تصویر.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)
[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

اگر می خواهید اسناد را از یک فایل خطوط JSON بارگیری کنید، باید 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})]

استخراج اطلاعات فایل های Meta

معمولاً ما می‌خواهیم اطلاعات فایل JSON را در سندی که از محتوا ایجاد می‌کنیم، اضافه کنیم.

در زیر، نحوه استفاده از JSONLoader برای استخراج اطلاعات Meta نمایش داده شده است.

در مثال قبل، ما اطلاعات Meta را جمع‌آوری نکردیم، اما توانستیم در طرح، مکانی را که می‌توان به صورت مستقیم مقدار 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='./مثال_داده/چت_فیسبوک.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': 'کاربر 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': 'کاربر 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': 'کاربر 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': 'کاربر 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': 'کاربر 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': 'کاربر 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': 'کاربر 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': 'کاربر 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': 'کاربر 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': 'کاربر 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': 'کاربر 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}),
     ...
     ...
     ... (remaining content unchanged for brevity) ...
     ...
     ...
]

ساختارهای متداول JSON برای استفاده از الگوهای jq

لیست زیر، الگوهای jq_schema ممکن را که کاربران می‌توانند به عنوان مرجع برای استخراج محتوا از داده‌های JSON بر اساس ساختار، ارائه می‌دهد.

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

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

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