Carregador de JSON
- O JSON (JavaScript Object Notation) é um formato de arquivo padrão aberto e formato de troca de dados que utiliza texto legível para armazenar e transmitir objetos de dados compostos por pares de atributos e valores e arrays (ou outros valores serializáveis).
JSON Lines é um formato de arquivo onde cada linha é um valor JSON válido.
O JSONLoader analisa arquivos JSON usando um padrão jq especificado e utiliza o pacote jq Python. Para documentação detalhada sobre a sintaxe jq, consulte a documentação relevante do Python.
from langchain_community.document_loaders import JSONLoader
import json
from pathlib import Path
from pprint import pprint
caminho_arquivo = './exemplo_dados/conversa_facebook.json'
dados = json.loads(Path(caminho_arquivo).read_text())
pprint(dados)
{'image': {'creation_timestamp': 1675549016, 'uri': 'imagem_do_chat.jpg'},
'is_still_participant': True,
'joinable_mode': {'link': '', 'mode': 1},
'magic_words': [],
'messages': [{'content': 'Tchau!',
'sender_name': 'Usuário 2',
'timestamp_ms': 1675597571851},
{'content': 'Ah, sem problemas! Tchau',
'sender_name': 'Usuário 1',
'timestamp_ms': 1675597435669},
{'content': 'Não, desculpe, foi meu erro, o azul não está à '
'venda',
'sender_name': 'Usuário 2',
'timestamp_ms': 1675596277579},
{'content': 'Eu pensei que você estava vendendo o azul!',
'sender_name': 'Usuário 1',
'timestamp_ms': 1675595140251},
{'content': 'Não estou interessado nesta bolsa. Estou interessado '
'na azul!',
'sender_name': 'Usuário 1',
'timestamp_ms': 1675595109305},
{'content': 'Aqui está $129',
'sender_name': 'Usuário 2',
'timestamp_ms': 1675595068468},
{'photos': [{'creation_timestamp': 1675595059,
'uri': 'url_de_alguma_imagem.jpg'}],
'sender_name': 'Usuário 2',
'timestamp_ms': 1675595060730},
{'content': 'Online está pelo menos $100',
'sender_name': 'Usuário 2',
'timestamp_ms': 1675595045152},
{'content': 'Quanto você quer?',
'sender_name': 'Usuário 1',
'timestamp_ms': 1675594799696},
{'content': 'Bom dia! $50 é muito pouco.',
'sender_name': 'Usuário 2',
'timestamp_ms': 1675577876645},
{'content': 'Oi! Estou interessado na sua bolsa. Estou oferecendo '
'$50. Me avise se você estiver interessado. Obrigado!',
'sender_name': 'Usuário 1',
'timestamp_ms': 1675549022673}],
'participants': [{'name': 'Usuário 1'}, {'name': 'Usuário 2'}],
'thread_path': 'inbox/Conversa entre Usuário 1 e Usuário 2',
'title': 'Conversa entre Usuário 1 e Usuário 2'}
Usando JSONLoader
Suponha que queremos extrair os valores do campo conteúdo
sob a chave mensagens
nos dados JSON. Utilizando o JSONLoader
, podemos facilmente realizar essa tarefa.
loader = JSONLoader(
file_path='./exemplo_dados/conversa_facebook.json',
jq_schema='.mensagens[].conteúdo')
dados = loader.load()
pprint(dados)
[Documento(conteúdo_da_página='Tchau!', metadados={'fonte': '/Usuários/avsolatorio/WBG/langchain/docs/módulos/índices/carregadores_de_documento/exemplos/exemplo_dados/conversa_facebook.json', 'num_seq': 1}),
Documento(conteúdo_da_página='Ah, sem problemas! Tchau', metadados={'fonte': '/Usuários/avsolatorio/WBG/langchain/docs/módulos/índices/carregadores_de_documento/exemplos/exemplo_dados/conversa_facebook.json', 'num_seq': 2}),
Documento(conteúdo_da_página='Não, desculpe, foi meu erro, o azul não está à venda', metadados={'fonte': '/Usuários/avsolatorio/WBG/langchain/docs/módulos/índices/carregadores_de_documento/exemplos/exemplo_dados/conversa_facebook.json', 'num_seq': 3}),
Documento(conteúdo_da_página='Pensei que você estava vendendo o azul!', metadados={'fonte': '/Usuários/avsolatorio/WBG/langchain/docs/módulos/índices/carregadores_de_documento/exemplos/exemplo_dados/conversa_facebook.json', 'num_seq': 4}),
Documento(conteúdo_da_página='Não tenho interesse nessa bolsa. Estou interessado no azul!', metadados={'fonte': '/Usuários/avsolatorio/WBG/langchain/docs/módulos/índices/carregadores_de_documento/exemplos/exemplo_dados/conversa_facebook.json', 'num_seq': 5}),
Documento(conteúdo_da_página='Aqui está $129', metadados={'fonte': '/Usuários/avsolatorio/WBG/langchain/docs/módulos/índices/carregadores_de_documento/exemplos/exemplo_dados/conversa_facebook.json', 'num_seq': 6}),
Documento(conteúdo_da_página='', metadados={'fonte': '/Usuários/avsolatorio/WBG/langchain/docs/módulos/índices/carregadores_de_documento/exemplos/exemplo_dados/conversa_facebook.json', 'num_seq': 7}),
Documento(conteúdo_da_página='Online está pelo menos $100', metadados={'fonte': '/Usuários/avsolatorio/WBG/langchain/docs/módulos/índices/carregadores_de_documento/exemplos/exemplo_dados/conversa_facebook.json', 'num_seq': 8}),
Documento(conteúdo_da_página='Quanto você quer?', metadados={'fonte': '/Usuários/avsolatorio/WBG/langchain/docs/módulos/índices/carregadores_de_documento/exemplos/exemplo_dados/conversa_facebook.json', 'num_seq': 9}),
Documento(conteúdo_da_página='Bom dia! $50 é muito pouco.', metadados={'fonte': '/Usuários/avsolatorio/WBG/langchain/docs/módulos/índices/carregadores_de_documento/exemplos/exemplo_dados/conversa_facebook.json', 'num_seq': 10}),
Documento(conteúdo_da_página='Oi! Estou interessado na sua bolsa. Estou oferecendo $50. Me avise se você estiver interessado. Obrigado!', metadados={'fonte': '/Usuários/avsolatorio/WBG/langchain/docs/módulos/índices/carregadores_de_documento/exemplos/exemplo_dados/conversa_facebook.json', 'num_seq': 11})]
Ficheiro de linhas JSON
Se deseja carregar documentos de um ficheiro de linhas JSON, precisa de passar json_lines=True
e especificar o jq_schema
para extrair o page_content
de um único objeto JSON.
file_path = './example_data/facebook_chat_messages.jsonl'
pprint(Path(file_path).read_text())
('{"sender_name": "Utilizador 2", "timestamp_ms": 1675597571851, "content": "Adeus!"}\n'
'{"sender_name": "Utilizador 1", "timestamp_ms": 1675597435669, "content": "Oh, não se preocupe! Adeus"}\n'
'{"sender_name": "Utilizador 2", "timestamp_ms": 1675596277579, "content": "Não, desculpe, foi meu erro, o azul não está à venda"}\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='Adeus!', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 1}),
Document(page_content='Oh, não se preocupe! Adeus', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 2}),
Document(page_content='Não, desculpe, foi meu erro, o azul não está à venda', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 3})]
Outra opção é definir jq_schema='.'
e fornecer a 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='Utilizador 2', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 1}),
Document(page_content='Utilizador 1', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 2}),
Document(page_content='Utilizador 2', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat_messages.jsonl', 'seq_num': 3})]
Extração de Metadados
Normalmente, gostaríamos de incluir os metadados de um arquivo JSON no documento que criamos a partir do conteúdo.
A seguir, demonstra-se como usar o JSONLoader
para extrair metadados.
No exemplo anterior, não coletamos metadados, mas conseguimos especificar no esquema a localização da qual o valor page_content
pode ser extraído diretamente.
.messages[].content
No exemplo atual, precisamos dizer ao carregador para iterar sobre os registros no campo messages
. Em seguida, o jq_schema
deve ser:
.messages[]
Isso nos permite passar os registros (dicionários) para a "metadata_func" que deve ser implementada. A "metadata_func" é responsável por identificar quais informações de registro devem ser incluídas nos metadados a serem armazenados no objeto "Document" final.
Além disso, agora temos que especificar explicitamente o parâmetro content_key
no carregador para extrair o valor "page_content" de qual chave no registro.
def metadata_func(registro: dict, metadados: dict) -> dict:
metadados["nome_remetente"] = registro.get("nome_remetente")
metadados["timestamp_ms"] = registro.get("timestamp_ms")
return metadados
carregador = JSONLoader(
file_path='./exemplo_dados/conversa_facebook.json',
jq_schema='.messages[]',
content_key="content",
metadata_func=metadata_func
)
dados = carregador.load()
pprint(dados)
[Documento(conteúdo_da_página='Tchau!', metadados={'origem': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1, 'nome_do_remetente': 'Usuário 2', 'timestamp_ms': 1675597571851}),
Documento(conteúdo_da_página='Ah, não se preocupe! Tchau', metadados={'origem': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2, 'nome_do_remetente': 'Usuário 1', 'timestamp_ms': 1675597435669}),
Documento(conteúdo_da_página='Não, desculpe, foi meu engano. O azul não está à venda', metadados={'origem': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 3, 'nome_do_remetente': 'Usuário 2', 'timestamp_ms': 1675596277579}),
Documento(conteúdo_da_página='Pensei que você estava vendendo o azul!', metadados={'origem': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 4, 'nome_do_remetente': 'Usuário 1', 'timestamp_ms': 1675595140251}),
Documento(conteúdo_da_página='Não estou interessado nesta bolsa. Estou interessado na azul!', metadados={'origem': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 5, 'nome_do_remetente': 'Usuário 1', 'timestamp_ms': 1675595109305}),
Documento(conteúdo_da_página='Aqui está $129', metadados={'origem': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 6, 'nome_do_remetente': 'Usuário 2', 'timestamp_ms': 1675595068468}),
Documento(conteúdo_da_página='', metadados={'origem': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 7, 'nome_do_remetente': 'Usuário 2', 'timestamp_ms': 1675595060730}),
Documento(conteúdo_da_página='Online está pelo menos $100', metadados={'origem': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 8, 'nome_do_remetente': 'Usuário 2', 'timestamp_ms': 1675595045152}),
Documento(conteúdo_da_página='Quanto você quer?', metadados={'origem': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 9, 'nome_do_remetente': 'Usuário 1', 'timestamp_ms': 1675594799696}),
Documento(conteúdo_da_página='Bom dia! $50 é muito pouco.', metadados={'origem': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 10, 'nome_do_remetente': 'Usuário 2', 'timestamp_ms': 1675577876645}),
Documento(conteúdo_da_página='Oi! Estou interessado na sua bolsa. Estou oferecendo $50. Me avise se estiver interessado. Obrigado!', metadados={'origem': '/Users/avsolatorio/WBG/langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 11, 'nome_do_remetente': 'Usuário 1', 'timestamp_ms': 1675549022673})]
Aqui podemos ver que esses arquivos já contêm metadados relacionados ao conteúdo que extraímos.
Função metadata_func
Como mostrado acima, a função metadata_func
recebe os metadados padrão gerados pelo JSONLoader
. Isso permite que os usuários tenham controle total sobre o formato dos metadados.
Por exemplo, os metadados padrão contêm as chaves source
e seq_num
. No entanto, os dados JSON também podem conter essas chaves. Os usuários podem usar a função metadata_func
para renomear as chaves padrão e usar as chaves dos dados JSON.
O exemplo a seguir demonstra como modificar o source
para incluir apenas informações de origem do arquivo relacionadas ao diretório 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='Tchau!', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 1, 'sender_name': 'Usuário 2', 'timestamp_ms': 1675597571851}),
Document(page_content='Ah, sem problemas! Tchau', metadata={'source': 'langchain/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json', 'seq_num': 2, 'sender_name': 'Usuário 1', 'timestamp_ms': 1675597435669}),
...
...
... (restante do conteúdo inalterado por brevidade) ...
...
...
]
Estruturas comuns de JSON para uso de padrões jq
A lista a seguir fornece possíveis jq_schema
que os usuários podem usar como referência para extrair conteúdo de dados JSON com base na estrutura.
JSON -> [{"text": ...}, {"text": ...}, {"text": ...}]
jq_schema -> ".[].text"
JSON -> {"key": [{"text": ...}, {"text": ...}, {"text": ...}]}
jq_schema -> ".key[].text"
JSON -> ["...", "...", "..."]
jq_schema -> ".[]"