Files
wehub-resource-sync 86db9aae8e
Documentation / build (push) Has been cancelled
Documentation / deploy (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:34:55 +08:00

149 lines
6.1 KiB
Python

""" This script illustrates options for parsing JSON and JSONL files into a Library in LLMWare, including the ability
to provide a custom configured mapping intended for use with 'pseudo-db' structured JSON and JSONL files
Option # 1- Standard JSON/JSON parsing -
-- when using a bulk ingest Parsing method, the parser will route json and jsonl files to the 'standard'
TextParser - which will look for a "text" key in the JSON/JSONL to extract as the intended text
-- if no 'text' key found, then the parse will return an empty output list []
-- you can provide an optional key_list parameter to TextParser, which will then by default capture the
selected fields and aggregate to form the text input, e.g.,
TextParser().jsonl_file_handler(fp,fn, key_list=["context", "source", "ID"]
... where "context", "source" and "ID" represent keys found in the source json/jsonl file
-- the standard TextParser() is designed for ad hoc extraction of text content, not to preserve the keys
-- use of this method is shown in the first example below
Option # 2- Custom Configured JSON/JSONL parsing -
-- in addition to the standard parsing method, there is the ability to customize the mappings for a
JSON/JSONL file in which the keys are intended to be used for follow-up lookup and retrieval
-- Parser().parse_json_config method - this is shown in the second and third examples below
"""
from llmware.parsers import Parser, TextParser
from llmware.library import Library
from llmware.retrieval import Query
from llmware.configs import LLMWareConfig
import time
import ast
# All three text databases supported (mongo, postgres, and sqlite)
# if it is highly varied unstructured content, we would recommend Mongo given its flexibility
# if any validation errors with Postgres or SQLite, then we would recommend either preprocessing the json or
# ... trying with Mongo
LLMWareConfig().set_active_db("mongo")
def standard_json_parsing(fp, fn):
""" This example shows the 'standard' text handler for json/jsonl """
# the selected keys should map to dictionary keys found in the JSON/JSONL
# if no keys passed, then by default, parser will only look for a "text" key
# the parser objective is extracting/aggregating the content of the file, not using the 'structure' of the keys
# if interpret_as_table is True, then returns each row as a LIST of elements, corresponding to the selected keys
# if interpret_as_table is False, then returns a text string, which is concatenation of the text found in each
# key, and will use the value of the separator to combine each key,
# e.g., value1 + separator + value2 + separator ...
selected_keys = ["key1", "key2", "key3"] # e.g., "context", "source", "ID" or other keys in json
output = TextParser().jsonl_file_handler(fp,fn,key_list=selected_keys,interpret_as_table=False,separator="\n")
return output
def configured_json_parsing(fp, fn, library_name):
""" This example shows how to use mappings for a customized json/jsonl """
# metadata is a dictionary mapping of key names to keys in the json file
# the 'keys' correspond to the keys that will be added to the library
# the 'values' correspond to the keys that will be found in the JSON/JSONL source file
# metadata must have "text" mapping
# if "doc_ID" or "block_ID" mapping provided, then will "over-write" the default doc_ID and block_ID and
# use the mapping provided in the source JSON/JSONL
# for all other attributes (e.g., not text, doc_ID, block_ID), the keys will be stored in "special_field1" of
# the database. For Mongo, the keys will be stored directly as a dictionary, while for Postgres and SQLite,
# it will be stored as text string, which must be converted upon use back into a dictionary (see below for
# retrieval example)
# step 1 - create metadata mapping
# -- must have 'text' key mapped to key in json source
# -- all other keys are 'optional' and can be any number from 0 - N
# -- generally, key2, etc. should map to the name of the key in the JSON file, although you are free to re-name
metadata= {"text": "json_source_key_mapping_to_main_text_input",
"key2": "json_source_key2",
"key3": "key3"}
# step 2 - create new library
lib = Library().create_new_library(library_name)
parser = Parser(lib)
# step 3 - invoke parse_json_config method
print("step 1 - parsing")
t0 = time.time()
parser_output = parser.parse_json_config(fp, fn, mapping_dict=metadata)
print(f"done parsing - time - {time.time() - t0} - summary - {parser_output}")
return parser_output
def run_query_configured_input (library_name=None,query=""):
""" Once the custom json/jsonl is parsed into a Library, it can be used like any other content with the
additional json/jsonl attributes available in special_field1- which can be retrieved as demonstrated below.
-- note: the example below illustrates a 'text_query' but will apply exactly the same for a 'semantic_query'
"""
# run query
lib = Library().load_library(library_name)
q = Query(lib).text_query(query)
for j, results in enumerate(q):
meta = ""
doc_id = -1
# the mapped keys from the json file are all stored in "special_field1" of the library dictionary entry
# and can be retrieved as a string that can be mapped back into a dictionary as outlined below
if "special_field1" in results:
meta = results["special_field1"]
if isinstance(meta,str):
try:
meta = ast.literal_eval(meta)
except:
print(f"could not convert meta string back into dictionary - {meta}")
if "doc_ID" in results:
doc_id = results["doc_ID"]
text = results["text"]
print(f"\nresults - {j} - query - {query}")
print(f"results - text - {text}")
print(f"results - doc_ID - {doc_id} - metadata - {meta}")
print("done")
return 0