محمل 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

مسار_الملف = './بيانات_المثال/دردشة_فيسبوك.json'
البيانات = json.loads(Path(مسار_الملف).read_text())
pprint(البيانات)
{'صورة': {'وقت_الإنشاء_الفرعي': 1675549016، 'رابط': 'صورة_للدردشة.jpg'},
     'هو_مازال_مشاركا': صحيح،
     'وضع_قابل_للانضمام': {'رابط': ''، 'وضع': 1}،
     'كلمات_سحرية': [],
     'الرسائل': [{'المحتوى': 'وداعًا!'،
                   'اسم_المرسل': 'المستخدم 2'،
                   'وقت_الطابعة_بالميللي ثانية': 1675597571851}،
                  {'المحتوى': 'آه لا تقلق! وداعًا'،
                   'اسم_المرسل': 'المستخدم 1'،
                   'وقت_الطابعة_بالميللي ثانية': 1675597435669}،
                  {'المحتوى': 'لا، أنا آسف. كانت غلطتي، الزرقاء ليست معروضة '
                              'للبيع'،
                   'اسم_المرسل': 'المستخدم 2'،
                   'وقت_الطابعة_بالميللي ثانية': 1675596277579}،
                  {'المحتوى': 'اعتقدت أنك تبيع الزرقاء!'،
                   'اسم_المرسل': 'المستخدم 1'،
                   'وقت_الطابعة_بالميللي ثانية': 1675595140251}،
                  {'المحتوى': 'لا أنا غير مهتم بهذه الحقيبة. أنا مهتم بالزرقاء!'،
                   'اسم_المرسل': 'المستخدم 1'،
                   'وقت_الطابعة_بالميللي ثانية': 1675595109305}،
                  {'المحتوى': 'ها هنا 129 دولار'،
                   'اسم_المرسل': 'المستخدم 2'،
                   'وقت_الطابعة_بالميللي ثانية': 1675595068468}،
                  {'الصور': [{'وقت_الإنشاء_الفرعي': 1675595059،
                               'رابط': 'رابط_صورة_ما'}]،
                   'اسم_المرسل': 'المستخدم 2'،
                   'وقت_الطابعة_بالميللي ثانية': 1675595060730}،
                  {'المحتوى': 'على الإنترنت بأقل شيء 100 دولار'،
                   'اسم_المرسل': 'المستخدم 2'،
                   'وقت_الطابعة_بالميللي ثانية': 1675595045152}،
                  {'المحتوى': 'كم تريد؟'،
                   'اسم_المرسل': 'المستخدم 1'،
                   'وقت_الطابعة_بالميللي ثانية': 1675594799696}،
                  {'المحتوى': 'صباح الخير! 50 دولار قليل جدًا.'،
                   'اسم_المرسل': 'المستخدم 2'،
                   'وقت_الطابعة_بالميللي ثانية': 1675577876645}،
                  {'المحتوى': 'مرحبا! أنا مهتم بحقيبتك. أنا أقدم 50 دولارًا. اسمح '
                              'لي أن أعرف إذا كنت مهتمًا. شكرًا!'،
                   'اسم_المرسل': 'المستخدم 1'،
                   'وقت_الطابعة_بالميللي ثانية': 1675549022673}]،
     'المشاركون': [{'الاسم': 'المستخدم 1'}، {'الاسم': 'المستخدم 2'}]،
     'مسار_المحادثة': 'صندوق الوارد/دردشة المستخدم 1 والمستخدم 2'،
     'العنوان': 'دردشة المستخدم 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 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": "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" مسؤولة عن تحديد المعلومات التي يجب تضمينها في البيانات الوصفية التي سيتم تخزينها في الكائن النهائي "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}),
     ...
     ...
     ... (بقية المحتوى لم يتغير لأسباب الإيجاز) ...
     ...
     ...
]

الهياكل الشائعة لبيانات JSON لاستخدام أنماط jq

يقدم القائمة التالية أمثلة لـ jq_schema التي يمكن للمستخدمين استخدامها كمرجع لاستخراج المحتوى من بيانات JSON استنادًا إلى الهيكل.

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

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

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