-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOCR - Azure Document Intelligence.step
executable file
·1 lines (1 loc) · 112 KB
/
OCR - Azure Document Intelligence.step
1
{"creationTimeStamp":"2024-02-19T17:31:29.328Z","modifiedTimeStamp":"2024-02-22T07:53:00.072Z","createdBy":"gerjch","modifiedBy":"gerjch","name":"OCR - Azure Document Intelligence.step","displayName":"OCR - Azure Document Intelligence.step","localDisplayName":"OCR - Azure Document Intelligence.step","properties":{},"links":[{"method":"GET","rel":"self","href":"/dataFlows/steps/354f56d5-aa72-452d-b419-f398261deed7","uri":"/dataFlows/steps/354f56d5-aa72-452d-b419-f398261deed7","type":"application/vnd.sas.data.flow.step"},{"method":"GET","rel":"alternate","href":"/dataFlows/steps/354f56d5-aa72-452d-b419-f398261deed7","uri":"/dataFlows/steps/354f56d5-aa72-452d-b419-f398261deed7","type":"application/vnd.sas.data.flow.step.summary"},{"method":"GET","rel":"up","href":"/dataFlows/steps","uri":"/dataFlows/steps","type":"application/vnd.sas.collection","itemType":"application/vnd.sas.data.flow.step.summary"},{"method":"PUT","rel":"update","href":"/dataFlows/steps/354f56d5-aa72-452d-b419-f398261deed7","uri":"/dataFlows/steps/354f56d5-aa72-452d-b419-f398261deed7","type":"application/vnd.sas.data.flow.step","responseType":"application/vnd.sas.data.flow.step"},{"method":"DELETE","rel":"delete","href":"/dataFlows/steps/354f56d5-aa72-452d-b419-f398261deed7","uri":"/dataFlows/steps/354f56d5-aa72-452d-b419-f398261deed7"},{"method":"GET","rel":"transferExport","href":"/dataFlows/steps/354f56d5-aa72-452d-b419-f398261deed7","uri":"/dataFlows/steps/354f56d5-aa72-452d-b419-f398261deed7","responseType":"application/vnd.sas.transfer.object"},{"method":"PUT","rel":"transferImportUpdate","href":"/dataFlows/steps/354f56d5-aa72-452d-b419-f398261deed7","uri":"/dataFlows/steps/354f56d5-aa72-452d-b419-f398261deed7","type":"application/vnd.sas.transfer.object","responseType":"application/vnd.sas.summary"}],"metadataVersion":0.0,"version":2,"type":"code","flowMetadata":{"inputPorts":[{"name":"input_table_name","displayName":"input_table_name","localDisplayName":"input_table_name","minEntries":0,"maxEntries":1,"defaultEntries":0,"type":"table"}],"outputPorts":[{"name":"outputtable1","displayName":"ocr_output","localDisplayName":"ocr_output","description":"Containing OCR results. Structure varies with different options like the type of extraction performed.","localDescription":"Containing OCR results. Structure varies with different options like the type of extraction performed.","minEntries":1,"maxEntries":1,"defaultEntries":0,"type":"table","supportsView":false,"requiresStructure":false},{"name":"outputtable2","displayName":"status_output","localDisplayName":"status_output","description":"Optional table. Contains status information of the OCR processing on a document level. ","localDescription":"Optional table. Contains status information of the OCR processing on a document level. ","minEntries":0,"maxEntries":1,"defaultEntries":0,"type":"table","supportsView":false,"requiresStructure":false}]},"ui":"{\n\t\"showPageContentOnly\": true,\n\t\"pages\": [\n\t\t{\n\t\t\t\"id\": \"pageSettings\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"label\": \"Settings\",\n\t\t\t\"children\": [\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"extractions_settings\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"OCR Settings\",\n\t\t\t\t\t\"open\": true,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"ocr_type\",\n\t\t\t\t\t\t\t\"type\": \"dropdown\",\n\t\t\t\t\t\t\t\"label\": \"OCR-Type:\",\n\t\t\t\t\t\t\t\"items\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"value\": \"text\",\n\t\t\t\t\t\t\t\t\t\"label\": \"Text\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"value\": \"form\",\n\t\t\t\t\t\t\t\t\t\"label\": \"Forms\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"value\": \"query\",\n\t\t\t\t\t\t\t\t\t\"label\": \"Queries\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"value\": \"table\",\n\t\t\t\t\t\t\t\t\t\"label\": \"Tables\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"placeholder\": \"\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"text_settings\",\n\t\t\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\t\t\"label\": \"Text\",\n\t\t\t\t\t\t\t\"open\": true,\n\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\"$ocr_type\",\n\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\"text\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"text_granularity\",\n\t\t\t\t\t\t\t\t\t\"type\": \"dropdown\",\n\t\t\t\t\t\t\t\t\t\"label\": \"Extraction Level:\",\n\t\t\t\t\t\t\t\t\t\"items\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"value\": \"document\",\n\t\t\t\t\t\t\t\t\t\t\t\"label\": \"Document\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"value\": \"page\",\n\t\t\t\t\t\t\t\t\t\t\t\"label\": \"Page\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"value\": \"paragraph\",\n\t\t\t\t\t\t\t\t\t\t\t\"label\": \"Paragraph\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"value\": \"line\",\n\t\t\t\t\t\t\t\t\t\t\t\"label\": \"Line\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"value\": \"word\",\n\t\t\t\t\t\t\t\t\t\t\t\"label\": \"Word\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"placeholder\": \"\",\n\t\t\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\t\t\"$ocr_type\",\n\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\"text\"\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"extract_pragraph_roles\",\n\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\"label\": \"Extract Paragraph Roles\",\n\t\t\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\t\t\"$text_granularity\",\n\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\"paragraph\"\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"extract_paragraph_role_info\",\n\t\t\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\t\t\"text\": \"Enabling this option might have cost implication. Links with more information about Azure Document Intelligent pricing can be found in the About page of this custom step. \",\n\t\t\t\t\t\t\t\t\t\"visible\": \"$extract_pragraph_roles\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"query_settings\",\n\t\t\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\t\t\"label\": \"Query\",\n\t\t\t\t\t\t\t\"open\": true,\n\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\"$ocr_type\",\n\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\"query\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"ocr_query_fields\",\n\t\t\t\t\t\t\t\t\t\"type\": \"textfield\",\n\t\t\t\t\t\t\t\t\t\"label\": \"Query Fields:\",\n\t\t\t\t\t\t\t\t\t\"placeholder\": \"seperate, your, fields_with, commas\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\t\t\"$ocr_type\",\n\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\"query\"\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"enabled\": [\n\t\t\t\t\t\t\t\t\t\t\"$ocr_type\",\n\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\"query\"\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"query_keys_info\",\n\t\t\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\t\t\"text\": \"Make sure your keys are regex compliant by substituting blanks with underscores ('_'). Do not add quotes.\",\n\t\t\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\t\t\"$ocr_type\",\n\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\"query\"\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"query_exclude_metadata\",\n\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\"label\": \"Only Output Query Results\",\n\t\t\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"query_exclude_metadata_info\",\n\t\t\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\t\t\"text\": \"When unselected, the ouput will be a key-value table including OCR metadata like field location, etc...\",\n\t\t\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\t\t\"$ocr_type\",\n\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\"query\"\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"table_settings\",\n\t\t\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\t\t\"label\": \"Table\",\n\t\t\t\t\t\t\t\"open\": true,\n\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\"$ocr_type\",\n\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\"table\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"table_output_format\",\n\t\t\t\t\t\t\t\t\t\"type\": \"dropdown\",\n\t\t\t\t\t\t\t\t\t\"label\": \"Extraction Mode:\",\n\t\t\t\t\t\t\t\t\t\"items\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"value\": \"map\",\n\t\t\t\t\t\t\t\t\t\t\t\"label\": \"Mapping-Table\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"value\": \"reference\",\n\t\t\t\t\t\t\t\t\t\t\t\"label\": \"Reference-Table\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"value\": \"table\",\n\t\t\t\t\t\t\t\t\t\t\t\"label\": \"One Table\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"placeholder\": \"\",\n\t\t\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"table_settings_map_info\",\n\t\t\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\t\t\"text\": \"Outputs one table containing all cells of every processed document in the following format [row_id, column_id, cell_content]\",\n\t\t\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\t\t\"$table_output_format\",\n\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\"map\"\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"table_settings_table_info\",\n\t\t\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\t\t\"text\": \"Outputs table in its original form. NOTE: ONLY SUPPORTS THE OUTPUT OF A SINGLE TABLE! \\nFor more information please refer to the About section of the custom step.\",\n\t\t\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\t\t\"$table_output_format\",\n\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\"table\"\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"table_settings_reference_info\",\n\t\t\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\t\t\"text\": \"Saves all extracted tables in the defined librarary and outputs a reference table. \",\n\t\t\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\t\t\"$table_output_format\",\n\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\"reference\"\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"table_output_library\",\n\t\t\t\t\t\t\t\t\t\"type\": \"textfield\",\n\t\t\t\t\t\t\t\t\t\"label\": \"Output Library:\",\n\t\t\t\t\t\t\t\t\t\"placeholder\": \"\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\t\t\"$table_output_format\",\n\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\"reference\"\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"enabled\": [\n\t\t\t\t\t\t\t\t\t\t\"$table_output_format\",\n\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\"reference\"\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"select_table\",\n\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\"label\": \"Enable Table Selection\",\n\t\t\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\t\t\"$table_output_format\",\n\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\"reference\"\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"table_filter_settings\",\n\t\t\t\t\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\t\t\t\t\"label\": \"Filter Settings\",\n\t\t\t\t\t\t\t\t\t\"open\": true,\n\t\t\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\t\"$select_table\",\n\t\t\t\t\t\t\t\t\t\t\t\"|\",\n\t\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\t\t\"$table_output_format\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"table\"\n\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\"&\",\n\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\t\"$table_output_format\",\n\t\t\t\t\t\t\t\t\t\t\t\"!=\",\n\t\t\t\t\t\t\t\t\t\t\t\"map\"\n\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"id\": \"tabel_selection_method\",\n\t\t\t\t\t\t\t\t\t\t\t\"type\": \"dropdown\",\n\t\t\t\t\t\t\t\t\t\t\t\"label\": \"Selection Method:\",\n\t\t\t\t\t\t\t\t\t\t\t\"items\": [\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"value\": \"index\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"Index\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"value\": \"size\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"Table Size\"\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\"required\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"placeholder\": \"\",\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"id\": \"table_selection_idx\",\n\t\t\t\t\t\t\t\t\t\t\t\"type\": \"numberfield\",\n\t\t\t\t\t\t\t\t\t\t\t\"label\": \"Table-Index:\",\n\t\t\t\t\t\t\t\t\t\t\t\"placeholder\": \"\",\n\t\t\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"max\": null,\n\t\t\t\t\t\t\t\t\t\t\t\"min\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"excludemin\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\"$tabel_selection_method\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"index\"\n\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\"integer\": true\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"id\": \"table_filtering_size_info\",\n\t\t\t\t\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"Selects the largest table. \",\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\"$tabel_selection_method\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"size\"\n\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"input_settings\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Input Settings\",\n\t\t\t\t\t\"open\": true,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"input_mode\",\n\t\t\t\t\t\t\t\"type\": \"dropdown\",\n\t\t\t\t\t\t\t\"label\": \"Input Mode:\",\n\t\t\t\t\t\t\t\"items\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"value\": \"batch\",\n\t\t\t\t\t\t\t\t\t\"label\": \"A list of files (table)\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"value\": \"single\",\n\t\t\t\t\t\t\t\t\t\"label\": \"Single file (path)\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"placeholder\": \"\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"input_type\",\n\t\t\t\t\t\t\t\"type\": \"radiogroup\",\n\t\t\t\t\t\t\t\"label\": \"Input Type:\",\n\t\t\t\t\t\t\t\"items\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"value\": \"file\",\n\t\t\t\t\t\t\t\t\t\"label\": \"Local File(s)\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"value\": \"url\",\n\t\t\t\t\t\t\t\t\t\"label\": \"URL(s)\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"input_table_name\",\n\t\t\t\t\t\t\t\"type\": \"inputtable\",\n\t\t\t\t\t\t\t\"label\": \"Input Table:\",\n\t\t\t\t\t\t\t\"required\": false,\n\t\t\t\t\t\t\t\"placeholder\": \"Table containing file paths\",\n\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\"$input_mode\",\n\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\"batch\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"enabled\": [\n\t\t\t\t\t\t\t\t\"$input_mode\",\n\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\"batch\"\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"path_column\",\n\t\t\t\t\t\t\t\"type\": \"columnselector\",\n\t\t\t\t\t\t\t\"label\": \"File path/URL Column:\",\n\t\t\t\t\t\t\t\"order\": false,\n\t\t\t\t\t\t\t\"columntype\": \"c\",\n\t\t\t\t\t\t\t\"max\": 1,\n\t\t\t\t\t\t\t\"min\": null,\n\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t\"$input_mode\",\n\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\"batch\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"readonly\": false,\n\t\t\t\t\t\t\t\"table\": \"input_table_name\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"file_path\",\n\t\t\t\t\t\t\t\"type\": \"path\",\n\t\t\t\t\t\t\t\"label\": \"File Path:\",\n\t\t\t\t\t\t\t\"pathtype\": \"file\",\n\t\t\t\t\t\t\t\"placeholder\": \"sasserver:/path/to/file/on/saserver\",\n\t\t\t\t\t\t\t\"required\": false,\n\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\"$input_mode\",\n\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\"single\"\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\"&\",\n\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\"$input_type\",\n\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\"file\"\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"file_url\",\n\t\t\t\t\t\t\t\"type\": \"textfield\",\n\t\t\t\t\t\t\t\"label\": \"File URL: \",\n\t\t\t\t\t\t\t\"placeholder\": \"https://www.example.com/image.jpg\",\n\t\t\t\t\t\t\t\"required\": false,\n\t\t\t\t\t\t\t\"visible\": [\n\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\"$input_mode\",\n\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\"single\"\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\"&\",\n\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\"$input_type\",\n\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\"url\"\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"textInputSettings\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"text\": \"Hint: You can find language related settings on the Advanced Settings page.\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"output_settings\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Output Settings\",\n\t\t\t\t\t\"open\": true,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"outputtable1\",\n\t\t\t\t\t\t\t\"type\": \"outputtable\",\n\t\t\t\t\t\t\t\"label\": \"OCR Output Table:\",\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"placeholder\": \"Table to output OCR results\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"output_status_table\",\n\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\"label\": \"Output Processing Status Table\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"outputtable2\",\n\t\t\t\t\t\t\t\"type\": \"outputtable\",\n\t\t\t\t\t\t\t\"label\": \"Status Output Table:\",\n\t\t\t\t\t\t\t\"required\": false,\n\t\t\t\t\t\t\t\"placeholder\": \"\",\n\t\t\t\t\t\t\t\"visible\": \"$output_status_table\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"id\": \"pageConnection\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"label\": \"Azure Connection\",\n\t\t\t\"children\": [\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"azure_endpoint\",\n\t\t\t\t\t\"type\": \"textfield\",\n\t\t\t\t\t\"label\": \"Azure Resource Endpoint:\",\n\t\t\t\t\t\"placeholder\": \"https://your-resource.cognitiveservices.azure.com/\",\n\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\"visible\": \"!$local_ocr\",\n\t\t\t\t\t\"enabled\": \"!$local_ocr\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"azure_key\",\n\t\t\t\t\t\"type\": \"textfield\",\n\t\t\t\t\t\"label\": \"Azure Secret Key:\",\n\t\t\t\t\t\"placeholder\": \"SECRET_KEY\",\n\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\"visible\": \"!$local_ocr\",\n\t\t\t\t\t\"enabled\": \"!$local_ocr\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"local_endpoint\",\n\t\t\t\t\t\"type\": \"textfield\",\n\t\t\t\t\t\"label\": \"Local Container Endpoint\",\n\t\t\t\t\t\"placeholder\": \"https://localhost:5000\",\n\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\"visible\": \"$local_ocr\",\n\t\t\t\t\t\"enabled\": \"$local_ocr\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"local_ocr\",\n\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\"label\": \"Use local Document Intelligence Container\",\n\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"textAzureConnection\",\n\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\"text\": \"For more information about the creation of Azure AI Document Intelligence ressources and access, follow the documentation linked in the about page. \",\n\t\t\t\t\t\"visible\": \"!$local_ocr\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"textAzureLocalContainer\",\n\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\"text\": \"PLEASE NOTE:\\n- Enabling this option does not create a container. You can find information regarding deployment in the about page.\\n- Local document intelligence container do not support query extraction. \\n- Only the 'General Document' container is supported\\n- For more info read the documentation linked in the about page\",\n\t\t\t\t\t\"visible\": \"$local_ocr\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"id\": \"pageAdvanced\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"label\": \"Advanced Settings\",\n\t\t\t\"children\": [\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"advanced_language\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Language\",\n\t\t\t\t\t\"open\": false,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"locale_info_text\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"text\": \"NOTE: Languages are detected automatically. Only select a language if you want to force Document Intelligence to use only this language for detection. For more information follow the link in the About page. \",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"ocr_locale\",\n\t\t\t\t\t\t\t\"type\": \"dropdown\",\n\t\t\t\t\t\t\t\"label\": \"Force Language for OCR:\",\n\t\t\t\t\t\t\t\"items\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Abaza\",\n\t\t\t\t\t\t\t\t\t\"value\": \"abq\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Abkhazian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ab\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Achinese\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ace\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Acoli\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ach\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Adangme\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ada\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Adyghe\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ady\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Afar\",\n\t\t\t\t\t\t\t\t\t\"value\": \"aa\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Afrikaans\",\n\t\t\t\t\t\t\t\t\t\"value\": \"af\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Akan\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ak\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Albanian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sq\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Algonquin\",\n\t\t\t\t\t\t\t\t\t\"value\": \"alq\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Angika (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"anp\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Arabic\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ar\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Asturian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ast\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Asu (Tanzania)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"asa\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Avaric\",\n\t\t\t\t\t\t\t\t\t\"value\": \"av\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Awadhi-Hindi (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"awa\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Aymara\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ay\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Azerbaijani (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"az\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Bafia\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ksf\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Bagheli\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bfy\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Bambara\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bm\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Bashkir\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ba\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Basque\",\n\t\t\t\t\t\t\t\t\t\"value\": \"eu\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Belarusian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"be\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Bemba (Zambia)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bem\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Bena (Tanzania)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bez\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Bhojpuri-Hindi (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bho\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Bikol\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bik\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Bini\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bin\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Bislama\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bi\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Bodo (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"brx\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Bosnian (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bs\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Brajbha\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bra\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Breton\",\n\t\t\t\t\t\t\t\t\t\"value\": \"br\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Bulgarian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bg\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Bundeli\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bns\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Buryat (Cyrillic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bua\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Catalan\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ca\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Cebuano\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ceb\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Chamling\",\n\t\t\t\t\t\t\t\t\t\"value\": \"rab\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Chamorro\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ch\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Chechen\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ce\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Chhattisgarhi (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"hne\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Chiga\",\n\t\t\t\t\t\t\t\t\t\"value\": \"cgg\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Chinese Simplified\",\n\t\t\t\t\t\t\t\t\t\"value\": \"zh-Hans\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Chinese Traditional\",\n\t\t\t\t\t\t\t\t\t\"value\": \"zh-Hant\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Choctaw\",\n\t\t\t\t\t\t\t\t\t\"value\": \"cho\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Chukot\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ckt\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Chuvash\",\n\t\t\t\t\t\t\t\t\t\"value\": \"cv\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Cornish\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kw\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Corsican\",\n\t\t\t\t\t\t\t\t\t\"value\": \"co\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Cree\",\n\t\t\t\t\t\t\t\t\t\"value\": \"cr\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Creek\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mus\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Crimean Tatar (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"crh\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Croatian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"hr\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Crow\",\n\t\t\t\t\t\t\t\t\t\"value\": \"cro\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Czech\",\n\t\t\t\t\t\t\t\t\t\"value\": \"cs\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Danish\",\n\t\t\t\t\t\t\t\t\t\"value\": \"da\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Dargwa\",\n\t\t\t\t\t\t\t\t\t\"value\": \"dar\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Dari\",\n\t\t\t\t\t\t\t\t\t\"value\": \"prs\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Dhimal (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"dhi\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Dogri (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"doi\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Duala\",\n\t\t\t\t\t\t\t\t\t\"value\": \"dua\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Dungan\",\n\t\t\t\t\t\t\t\t\t\"value\": \"dng\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Dutch\",\n\t\t\t\t\t\t\t\t\t\"value\": \"nl\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Efik\",\n\t\t\t\t\t\t\t\t\t\"value\": \"efi\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"English\",\n\t\t\t\t\t\t\t\t\t\"value\": \"en\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Erzya (Cyrillic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"myv\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Estonian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"et\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Faroese\",\n\t\t\t\t\t\t\t\t\t\"value\": \"fo\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Fijian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"fj\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Filipino\",\n\t\t\t\t\t\t\t\t\t\"value\": \"fil\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Finnish\",\n\t\t\t\t\t\t\t\t\t\"value\": \"fi\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Fon\",\n\t\t\t\t\t\t\t\t\t\"value\": \"fon\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"French\",\n\t\t\t\t\t\t\t\t\t\"value\": \"fr\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Friulian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"fur\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Ga\",\n\t\t\t\t\t\t\t\t\t\"value\": \"gaa\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Gagauz (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"gag\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Galician\",\n\t\t\t\t\t\t\t\t\t\"value\": \"gl\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Ganda\",\n\t\t\t\t\t\t\t\t\t\"value\": \"lg\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Gayo\",\n\t\t\t\t\t\t\t\t\t\"value\": \"gay\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"German\",\n\t\t\t\t\t\t\t\t\t\"value\": \"de\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Gilbertese\",\n\t\t\t\t\t\t\t\t\t\"value\": \"gil\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Gondi (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"gon\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Greek\",\n\t\t\t\t\t\t\t\t\t\"value\": \"el\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Greenlandic\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kl\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Guarani\",\n\t\t\t\t\t\t\t\t\t\"value\": \"gn\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Gurung (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"gvr\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Gusii\",\n\t\t\t\t\t\t\t\t\t\"value\": \"guz\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Haitian Creole\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ht\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Halbi (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"hlb\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Hani\",\n\t\t\t\t\t\t\t\t\t\"value\": \"hni\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Haryanvi\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bgc\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Hawaiian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"haw\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Hebrew\",\n\t\t\t\t\t\t\t\t\t\"value\": \"he\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Herero\",\n\t\t\t\t\t\t\t\t\t\"value\": \"hz\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Hiligaynon\",\n\t\t\t\t\t\t\t\t\t\"value\": \"hil\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Hindi\",\n\t\t\t\t\t\t\t\t\t\"value\": \"hi\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Hmong Daw (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mww\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Ho (Devanagiri)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"hoc\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Hungarian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"hu\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Iban\",\n\t\t\t\t\t\t\t\t\t\"value\": \"iba\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Icelandic\",\n\t\t\t\t\t\t\t\t\t\"value\": \"is\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Igbo\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ig\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Iloko\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ilo\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Inari Sami\",\n\t\t\t\t\t\t\t\t\t\"value\": \"smn\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Indonesian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"id\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Ingush\",\n\t\t\t\t\t\t\t\t\t\"value\": \"inh\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Interlingua\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ia\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Inuktitut (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"iu\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Irish\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ga\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Italian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"it\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Japanese\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ja\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Jaunsari (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"Jns\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Javanese\",\n\t\t\t\t\t\t\t\t\t\"value\": \"jv\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Jola-Fonyi\",\n\t\t\t\t\t\t\t\t\t\"value\": \"dyo\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"K'iche'\",\n\t\t\t\t\t\t\t\t\t\"value\": \"quc\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kabardian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kbd\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kabuverdianu\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kea\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kachin (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kac\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kalenjin\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kln\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kalmyk\",\n\t\t\t\t\t\t\t\t\t\"value\": \"xal\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kangri (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"xnr\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kanuri\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kr\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kara-Kalpak (Cyrillic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kaa-cyrl\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kara-Kalpak (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kaa\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Karachay-Balkar\",\n\t\t\t\t\t\t\t\t\t\"value\": \"krc\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kashubian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"csb\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kazakh (Cyrillic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kk-cyrl\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kazakh (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kk-latn\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Khakas\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kjh\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Khaling\",\n\t\t\t\t\t\t\t\t\t\"value\": \"klr\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Khasi\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kha\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kikuyu\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ki\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kildin Sami\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sjd\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kinyarwanda\",\n\t\t\t\t\t\t\t\t\t\"value\": \"rw\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Komi\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kv\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kongo\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kg\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Korean\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ko\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Korku\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kfq\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Koryak\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kpy\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kosraean\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kos\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kpelle\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kpe\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kuanyama\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kj\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kumyk (Cyrillic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kum\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kurdish (Arabic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ku-arab\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kurdish (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ku-latn\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kurukh (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kru\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Kyrgyz (Cyrillic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ky\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Lak\",\n\t\t\t\t\t\t\t\t\t\"value\": \"lbe\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Lakota\",\n\t\t\t\t\t\t\t\t\t\"value\": \"lkt\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Latin\",\n\t\t\t\t\t\t\t\t\t\"value\": \"la\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Latvian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"lv\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Lezghian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"lex\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Lingala\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ln\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Lithuanian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"lt\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Lower Sorbian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"dsb\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Lozi\",\n\t\t\t\t\t\t\t\t\t\"value\": \"loz\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Lule Sami\",\n\t\t\t\t\t\t\t\t\t\"value\": \"smj\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Luo (Kenya and Tanzania)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"luo\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Luxembourgish\",\n\t\t\t\t\t\t\t\t\t\"value\": \"lb\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Luyia\",\n\t\t\t\t\t\t\t\t\t\"value\": \"luy\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Macedonian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mk\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Machame\",\n\t\t\t\t\t\t\t\t\t\"value\": \"jmc\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Madurese\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mad\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Mahasu Pahari (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bfz\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Makhuwa-Meetto\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mgh\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Makonde\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kde\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Malagasy\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mg\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Malay (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ms\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Maltese\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mt\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Malto (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"kmj\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Mandinka\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mnk\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Manx\",\n\t\t\t\t\t\t\t\t\t\"value\": \"gv\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Maori\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mi\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Mapudungun\",\n\t\t\t\t\t\t\t\t\t\"value\": \"arn\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Marathi\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mr\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Mari (Russia)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"chm\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Masai\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mas\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Mende (Sierra Leone)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"men\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Meru\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mer\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Meta'\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mgo\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Minangkabau\",\n\t\t\t\t\t\t\t\t\t\"value\": \"min\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Mohawk\",\n\t\t\t\t\t\t\t\t\t\"value\": \"moh\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Mongolian (Cyrillic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mn\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Mongondow\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mog\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Montenegrin (Cyrillic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"cnr-cyrl\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Montenegrin (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"cnr-latn\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Morisyen\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mfe\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Mundang\",\n\t\t\t\t\t\t\t\t\t\"value\": \"mua\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Nahuatl\",\n\t\t\t\t\t\t\t\t\t\"value\": \"nah\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Navajo\",\n\t\t\t\t\t\t\t\t\t\"value\": \"nv\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Ndonga\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ng\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Neapolitan\",\n\t\t\t\t\t\t\t\t\t\"value\": \"nap\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Nepali\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ne\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Ngomba\",\n\t\t\t\t\t\t\t\t\t\"value\": \"jgo\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Niuean\",\n\t\t\t\t\t\t\t\t\t\"value\": \"niu\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Nogay\",\n\t\t\t\t\t\t\t\t\t\"value\": \"nog\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"North Ndebele\",\n\t\t\t\t\t\t\t\t\t\"value\": \"nd\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Northern Sami (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sme\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Norwegian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"no\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Nyanja\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ny\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Nyankole\",\n\t\t\t\t\t\t\t\t\t\"value\": \"nyn\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Nzima\",\n\t\t\t\t\t\t\t\t\t\"value\": \"nzi\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Occitan\",\n\t\t\t\t\t\t\t\t\t\"value\": \"oc\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Ojibwa\",\n\t\t\t\t\t\t\t\t\t\"value\": \"oj\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Oromo\",\n\t\t\t\t\t\t\t\t\t\"value\": \"om\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Ossetic\",\n\t\t\t\t\t\t\t\t\t\"value\": \"os\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Pampanga\",\n\t\t\t\t\t\t\t\t\t\"value\": \"pam\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Pangasinan\",\n\t\t\t\t\t\t\t\t\t\"value\": \"pag\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Papiamento\",\n\t\t\t\t\t\t\t\t\t\"value\": \"pap\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Pashto\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ps\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Pedi\",\n\t\t\t\t\t\t\t\t\t\"value\": \"nso\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Persian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"fa\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Polish\",\n\t\t\t\t\t\t\t\t\t\"value\": \"pl\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Portuguese\",\n\t\t\t\t\t\t\t\t\t\"value\": \"pt\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Punjabi (Arabic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"pa\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Quechua\",\n\t\t\t\t\t\t\t\t\t\"value\": \"qu\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Ripuarian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ksh\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Romanian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ro\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Romansh\",\n\t\t\t\t\t\t\t\t\t\"value\": \"rm\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Rundi\",\n\t\t\t\t\t\t\t\t\t\"value\": \"rn\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Russian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ru\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Rwa\",\n\t\t\t\t\t\t\t\t\t\"value\": \"rwk\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Sadri (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sck\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Sakha\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sah\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Samburu\",\n\t\t\t\t\t\t\t\t\t\"value\": \"saq\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Samoan (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sm\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Sango\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sg\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Sangu (Gabon)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"snq\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Sanskrit (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sa\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Santali(Devanagiri)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sat\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Scots\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sco\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Scottish Gaelic\",\n\t\t\t\t\t\t\t\t\t\"value\": \"gd\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Sena\",\n\t\t\t\t\t\t\t\t\t\"value\": \"seh\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Serbian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sr\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Serbian (Cyrillic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sr-cyrl\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Shambala\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ksb\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Shona\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sn\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Siksika\",\n\t\t\t\t\t\t\t\t\t\"value\": \"bla\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Sirmauri (Devanagari)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"srx\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Skolt Sami\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sms\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Slovak\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sk\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Slovenian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sl\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Soga\",\n\t\t\t\t\t\t\t\t\t\"value\": \"xog\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Somali (Arabic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"so\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Somali (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"so-latn\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Songhai\",\n\t\t\t\t\t\t\t\t\t\"value\": \"son\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"South Ndebele\",\n\t\t\t\t\t\t\t\t\t\"value\": \"nr\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Southern Altai\",\n\t\t\t\t\t\t\t\t\t\"value\": \"alt\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Southern Sami\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sma\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Southern Sotho\",\n\t\t\t\t\t\t\t\t\t\"value\": \"st\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Spanish\",\n\t\t\t\t\t\t\t\t\t\"value\": \"es\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Sundanese\",\n\t\t\t\t\t\t\t\t\t\"value\": \"su\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Swahili (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sw\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Swati\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ss\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Swedish\",\n\t\t\t\t\t\t\t\t\t\"value\": \"sv\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Tabassaran\",\n\t\t\t\t\t\t\t\t\t\"value\": \"tab\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Tachelhit\",\n\t\t\t\t\t\t\t\t\t\"value\": \"shi\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Tahitian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ty\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Taita\",\n\t\t\t\t\t\t\t\t\t\"value\": \"dav\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Tajik (Cyrillic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"tg\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Tamil\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ta\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Tatar (Cyrillic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"tt-cyrl\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Tatar (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"tt\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Teso\",\n\t\t\t\t\t\t\t\t\t\"value\": \"teo\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Tetum\",\n\t\t\t\t\t\t\t\t\t\"value\": \"tet\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Thai\",\n\t\t\t\t\t\t\t\t\t\"value\": \"th\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Thangmi\",\n\t\t\t\t\t\t\t\t\t\"value\": \"thf\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Tok Pisin\",\n\t\t\t\t\t\t\t\t\t\"value\": \"tpi\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Tongan\",\n\t\t\t\t\t\t\t\t\t\"value\": \"to\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Tsonga\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ts\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Tswana\",\n\t\t\t\t\t\t\t\t\t\"value\": \"tn\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Turkish\",\n\t\t\t\t\t\t\t\t\t\"value\": \"tr\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Turkmen (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"tk\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Tuvan\",\n\t\t\t\t\t\t\t\t\t\"value\": \"tyv\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Udmurt\",\n\t\t\t\t\t\t\t\t\t\"value\": \"udm\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Uighur (Cyrillic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ug-cyrl\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Ukrainian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"uk\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Upper Sorbian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"hsb\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Urdu\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ur\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Uyghur (Arabic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"ug\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Uzbek (Arabic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"uz-arab\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Uzbek (Cyrillic)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"uz-cyrl\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Uzbek (Latin)\",\n\t\t\t\t\t\t\t\t\t\"value\": \"uz\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Vietnamese\",\n\t\t\t\t\t\t\t\t\t\"value\": \"vi\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Volapük\",\n\t\t\t\t\t\t\t\t\t\"value\": \"vo\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Vunjo\",\n\t\t\t\t\t\t\t\t\t\"value\": \"vun\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Walser\",\n\t\t\t\t\t\t\t\t\t\"value\": \"wae\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Welsh\",\n\t\t\t\t\t\t\t\t\t\"value\": \"cy\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Western Frisian\",\n\t\t\t\t\t\t\t\t\t\"value\": \"fy\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Wolof\",\n\t\t\t\t\t\t\t\t\t\"value\": \"wo\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Xhosa\",\n\t\t\t\t\t\t\t\t\t\"value\": \"xh\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Yucatec Maya\",\n\t\t\t\t\t\t\t\t\t\"value\": \"yua\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Zapotec\",\n\t\t\t\t\t\t\t\t\t\"value\": \"zap\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Zarma\",\n\t\t\t\t\t\t\t\t\t\"value\": \"dje\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Zhuang\",\n\t\t\t\t\t\t\t\t\t\"value\": \"za\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"label\": \"Zulu\",\n\t\t\t\t\t\t\t\t\t\"value\": \"zu\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"required\": false,\n\t\t\t\t\t\t\t\"placeholder\": \"\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"advanced_connection\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Connection\",\n\t\t\t\t\t\"open\": false,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"timeout_seconds\",\n\t\t\t\t\t\t\t\"type\": \"numstepper\",\n\t\t\t\t\t\t\t\"label\": \"Timeout (seconds):\",\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"integer\": true,\n\t\t\t\t\t\t\t\"min\": 1,\n\t\t\t\t\t\t\t\"max\": null,\n\t\t\t\t\t\t\t\"stepsize\": 1\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"timeout_info\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"text\": \"Seconds to wait for the OCR processing to finish before timing out. \",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"n_connection_retries\",\n\t\t\t\t\t\t\t\"type\": \"numstepper\",\n\t\t\t\t\t\t\t\"label\": \"Number of Retries:\",\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"integer\": true,\n\t\t\t\t\t\t\t\"min\": 1,\n\t\t\t\t\t\t\t\"max\": null,\n\t\t\t\t\t\t\t\"stepsize\": 1\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"retry_delay\",\n\t\t\t\t\t\t\t\"type\": \"numstepper\",\n\t\t\t\t\t\t\t\"label\": \"Seconds between Retry Attempts:\",\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"integer\": true,\n\t\t\t\t\t\t\t\"min\": 1,\n\t\t\t\t\t\t\t\"max\": 10,\n\t\t\t\t\t\t\t\"stepsize\": 1\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"advanced_Processing\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Processing\",\n\t\t\t\t\t\"open\": false,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"n_threads\",\n\t\t\t\t\t\t\t\"type\": \"numstepper\",\n\t\t\t\t\t\t\t\"label\": \"Number of Threads:\",\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"integer\": false,\n\t\t\t\t\t\t\t\"min\": 1,\n\t\t\t\t\t\t\t\"max\": 64,\n\t\t\t\t\t\t\t\"stepsize\": 1\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"advanced_output\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Output\",\n\t\t\t\t\t\"open\": false,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"save_json_info_text\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"text\": \"Saves the raw OCR result as JSON files at the specified location.\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"save_files\",\n\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\"label\": \"Save as JSON\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"json_output_folder\",\n\t\t\t\t\t\t\t\"type\": \"path\",\n\t\t\t\t\t\t\t\"label\": \"Output Folder:\",\n\t\t\t\t\t\t\t\"pathtype\": \"folder\",\n\t\t\t\t\t\t\t\"placeholder\": \"Folder to save the unparsed OCR results\",\n\t\t\t\t\t\t\t\"required\": false,\n\t\t\t\t\t\t\t\"visible\": \"$save_files\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"id\": \"pageAbout\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"label\": \"About\",\n\t\t\t\"children\": [\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"textAbout\",\n\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\"text\": \"OCR - Azure AI Document Intelligence\\n=========================\\n\\nThis custom step uses the Azure Document Intelligence service to perform different types of OCR\\n\\nNOTE: The usage of this step requires an Azure AI Document Intelligence Resource. For more information, check the documentation below.\\n\\nSupported OCR types: \\n * Text (word, line, paragraph, page)\\n * Form (key-value pairs)\\n * Query (specific keys)\\n * Tables\\n\\nSupported file types:\\n * Images: .png, .jpg / .jpeg, .bmp, .tiff, .heif\\n * Documents: .pdf\\n\",\n\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"sectionPrereqs\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Pre-requisites\",\n\t\t\t\t\t\"open\": false,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"textPrereqs\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"text\": \"Tested on Viya version Stable 2024.1\\n\\nGeneral:\\n * Python 3\\n * Azure AI Document Intelligence Resource\\n\\nPython Packages:\\n * pandas\\n * numpy\\n\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"sectionDocumentation\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Documentation\",\n\t\t\t\t\t\"open\": false,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"link1\",\n\t\t\t\t\t\t\t\"type\": \"link\",\n\t\t\t\t\t\t\t\"label\": \"Custom Step Repository & Documentation\",\n\t\t\t\t\t\t\t\"url\": \"https://github.com/sassoftware/sas-studio-custom-steps/tree/main/OCR%20-%20Azure%20Document%20Intelligence\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"link2\",\n\t\t\t\t\t\t\t\"type\": \"link\",\n\t\t\t\t\t\t\t\"label\": \"Azure AI Document Intelligence documentation\",\n\t\t\t\t\t\t\t\"url\": \"https://learn.microsoft.com/en-US/azure/ai-services/document-intelligence/?view=doc-intel-4.0.0\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"link3\",\n\t\t\t\t\t\t\t\"type\": \"link\",\n\t\t\t\t\t\t\t\"label\": \"Language Support\",\n\t\t\t\t\t\t\t\"url\": \"https://learn.microsoft.com/en-GB/azure/ai-services/document-intelligence/language-support-ocr?view=doc-intel-4.0.0&tabs=read-print%2Clayout-print%2Cgeneral\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"link4\",\n\t\t\t\t\t\t\t\"type\": \"link\",\n\t\t\t\t\t\t\t\"label\": \"Pricing\",\n\t\t\t\t\t\t\t\"url\": \"https://azure.microsoft.com/en-us/pricing/details/ai-document-intelligence/#pricing\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"link5\",\n\t\t\t\t\t\t\t\"type\": \"link\",\n\t\t\t\t\t\t\t\"label\": \"Pricing\",\n\t\t\t\t\t\t\t\"url\": \"https://azure.microsoft.com/en-us/pricing/details/ai-document-intelligence/#pricing\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"link6\",\n\t\t\t\t\t\t\t\"type\": \"link\",\n\t\t\t\t\t\t\t\"label\": \"Data Privacy\",\n\t\t\t\t\t\t\t\"url\": \"https://learn.microsoft.com/en-us/legal/cognitive-services/document-intelligence/data-privacy-security\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"link7\",\n\t\t\t\t\t\t\t\"type\": \"link\",\n\t\t\t\t\t\t\t\"label\": \"Install Local Document Intelligence Container\",\n\t\t\t\t\t\t\t\"url\": \"https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/containers/install-run?view=doc-intel-3.0\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"link8\",\n\t\t\t\t\t\t\t\"type\": \"link\",\n\t\t\t\t\t\t\t\"label\": \"Proc Python documentation\",\n\t\t\t\t\t\t\t\"url\": \"https://go.documentation.sas.com/doc/en/pgmsascdc/default/proc/p1iycdzbxw2787n178ysea5ghk6l.htm\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"sectionChangelog\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Changelog\",\n\t\t\t\t\t\"open\": false,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"textChangelog\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"text\": \"* Version: 1.0 (08JAN2024)\\n - Initial version\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"textAuthor\",\n\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\"text\": \"This custom step was created by <name> (<email>).\",\n\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t],\n\t\"syntaxversion\": \"1.3.0\",\n\t\"values\": {\n\t\t\"ocr_type\": {\n\t\t\t\"value\": \"text\",\n\t\t\t\"label\": \"Text\"\n\t\t},\n\t\t\"text_granularity\": {\n\t\t\t\"value\": \"paragraph\",\n\t\t\t\"label\": \"Paragraph\"\n\t\t},\n\t\t\"extract_pragraph_roles\": false,\n\t\t\"ocr_query_fields\": \"\",\n\t\t\"query_exclude_metadata\": true,\n\t\t\"table_output_format\": {\n\t\t\t\"value\": \"map\",\n\t\t\t\"label\": \"Mapping-Table\"\n\t\t},\n\t\t\"table_output_library\": \"WORK\",\n\t\t\"select_table\": false,\n\t\t\"tabel_selection_method\": {\n\t\t\t\"value\": \"index\",\n\t\t\t\"label\": \"Index\"\n\t\t},\n\t\t\"table_selection_idx\": 0,\n\t\t\"input_mode\": {\n\t\t\t\"value\": \"batch\",\n\t\t\t\"label\": \"A list of files (table)\"\n\t\t},\n\t\t\"input_type\": {\n\t\t\t\"value\": \"file\",\n\t\t\t\"label\": \"Local File(s)\"\n\t\t},\n\t\t\"input_table_name\": {\n\t\t\t\"library\": \"\",\n\t\t\t\"table\": \"\"\n\t\t},\n\t\t\"path_column\": [],\n\t\t\"file_path\": \"\",\n\t\t\"file_url\": \"\",\n\t\t\"outputtable1\": {\n\t\t\t\"library\": \"\",\n\t\t\t\"table\": \"\"\n\t\t},\n\t\t\"output_status_table\": false,\n\t\t\"outputtable2\": {\n\t\t\t\"library\": \"\",\n\t\t\t\"table\": \"\"\n\t\t},\n\t\t\"azure_endpoint\": \"https://your-resource.cognitiveservices.azure.com/\",\n\t\t\"azure_key\": \"SECRET_KEY\",\n\t\t\"local_endpoint\": \"https://localhost:5000\",\n\t\t\"local_ocr\": false,\n\t\t\"ocr_locale\": null,\n\t\t\"timeout_seconds\": 30,\n\t\t\"n_connection_retries\": 3,\n\t\t\"retry_delay\": 2,\n\t\t\"n_threads\": 16,\n\t\t\"save_files\": false,\n\t\t\"json_output_folder\": \"\"\n\t}\n}","templates":{"SAS":"proc python restart;\nsubmit;\n# Imports\ntry:\n\timport pandas as pd\n\timport numpy as np\n\timport functools\n\timport requests\n\timport threading\n\timport base64\n\timport json\n\timport io\n\timport re\n\timport os\n\timport time\n\timport uuid\n\tfrom urllib.parse import urlparse\n\tfrom datetime import datetime\n\tfrom urllib.error import HTTPError\nexcept ImportError as e:\n\tSAS.logMessage(f'ImportError - {e}. Please install the required packages!', 'error')\n\texit()\n\n################### DEFINE PARAMETERS ###################\n# azure credentials & container\nazure_key = str(SAS.symget(\"azure_key\"))\nazure_endpoint = str(SAS.symget(\"azure_endpoint\"))\nlocal_ocr = bool(int(SAS.symget(\"local_ocr\"))) # whether to use a locally deployed document intelligence container, default = False\nlocal_ocr_endpoint = str(SAS.symget(\"local_endpoint\")) \t\t\t\t # endpoint of the locally deployed document intelligence container\n\nSERVICE_VERSION = '4.0' \t\t\t\t\t\t# 4.0 is in preview. Local containers are only supported in 3.0 (GA) thus far\nAPI_VERSION = '2023-10-31-preview' \t\t\t\t\t\t\t# default: '2023-10-31-preview'- to lock the API version, in case breaking change are introduced\nDEFAULT_MODEL_ID = 'prebuilt-layout'\nSUPPORTED_EXTENSIONS = ['jpeg', 'jpg', 'png', 'bmp', 'tiff', 'heif', 'pdf']\n\n# general\nocr_type = str(SAS.symget(\"ocr_type\")) \t\t# type of OCR: text, form, query, table\ninput_type = str(SAS.symget(\"input_type\")) \t\t# type of input: file, url \ninput_mode = str(SAS.symget(\"input_mode\")) \t\t# single or batch\nfile_path = str(SAS.symget(\"file_path\")) \t\t\t\t\t\t\t\t# path to a (single) file\nfile_url = str(SAS.symget(\"file_url\")) \ninput_table_name = str(SAS.symget(\"input_table_name\")) # name of table containing the file paths\npath_column = str(SAS.symget(\"path_column\")) # column that contains the file path\noutput_status_table = bool(int(SAS.symget(\"output_status_table\"))) # whether to output the status table\n\n# advanced\nlocale = str(SAS.symget(\"ocr_locale\")) \t# optional, language of the document. Support-list: https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/language-support-ocr?view=doc-intel-4.0.0&tabs=read-hand%2Clayout-print%2Cgeneral\nn_threads = int(SAS.symget(\"n_threads\")) \t# number of threads to use for parallel processing\nn_con_retry = int(SAS.symget(\"n_connection_retries\")) # number of retries if connection fails\nretry_delay = int(SAS.symget(\"retry_delay\")) # delay between retries\ntimeout_seconds = int(SAS.symget(\"timeout_seconds\")) # seconds waiting for ocr processing to finish before timing out\nsave_json = bool(int(SAS.symget(\"save_files\"))) # whether to save the json output\njson_output_folder = str(SAS.symget(\"json_output_folder\")) # folder to save the json output\n\n# for text extraction\ntext_granularity = str(SAS.symget(\"text_granularity\")) \t# level of detail: word, line, paragraph, page, document\nmodel_id = '' \t\t\t\t\t \t # Has cost implications. Layout more expensive but allows for more features: prebuilt-read, prebuilt-layout\nextract_pragraph_roles = bool(int(SAS.symget(\"extract_pragraph_roles\")))\n\n# for query extraction\nquery_fields = str(SAS.symget(\"ocr_query_fields\")) \t\t\t# string containing comma separated keys to extract\nquery_exclude_metadata = bool(int(SAS.symget(\"query_exclude_metadata\")))# if excluded, the resulting table will contain a column per query field (doesn't support ocr metadata like bounding boxes)\n\n# for table extraction\ntable_output_format = str(SAS.symget(\"table_output_format\")) # how the tables should be returned: map, reference*, table** *reference requires a cas\ntable_output_library = str(SAS.symget(\"table_output_library\")) # caslib to store the table (only relevant if table_output_format = 'reference')\nselect_table = bool(int(SAS.symget(\"select_table\"))) # whether to select a specific table or all tables (only relevant if table_output_format = 'reference')\ntable_selection_method = str(SAS.symget(\"table_selection_method\")) # how to select the table: size, index (only relevant if table_output_format = 'reference' and selected_table = True)\ntable_selection_idx = int(SAS.symget(\"table_selection_idx\")) # index of the table to extract (only relevant if table_output_format = 'table')\n\n\n##################### HELPER FUNCTIONS #####################\ndef retry_on_endpoint_connection_error(max_retries=3, delay=2):\n\t\"\"\"\n\tThis is a decorator function that allows a function to retry execution when an EndpointConnectionError occurs.\n\n\tParameters:\n\t-----------\n\tmax_retries (int): \n\t\tThe maximum number of retries if an EndpointConnectionError occurs. Default is 3.\n\tdelay (int): \n\t\tThe delay (in seconds) between retries. Default is 2.\n\n\tReturns:\n\twrapper function: \n\t\tThe decorated function that includes retry logic.\n\t\"\"\"\n\tdef decorator(func):\n\t\t@functools.wraps(func)\n\t\tdef wrapper(*args, **kwargs):\n\t\t\tretries = 0\n\t\t\twhile retries < max_retries:\n\t\t\t\ttry:\n\t\t\t\t\treturn func(*args, **kwargs)\n\t\t\t\t\t\"\"\" except EndpointConnectionError as e:\n\t\t\t\t\t\tSAS.logMessage(f'Retrying due to EndpointConnectionError: {e}')\n\t\t\t\t\t\tretries += 1\n\t\t\t\t\t\ttime.sleep(delay) \"\"\"\n\t\t\t\texcept Exception as e:\n\t\t\t\t\traise e # Let other exceptions be handled by the utility class\n\n\t\t\tif retries == max_retries:\n\t\t\t\tSAS.logMessage(f\"Max retries ({max_retries}) reached. Unable to complete operation.\", 'warning')\n\t\t\t\traise RuntimeError(\"Max retries to contact Azure endpoint reached. Unable to complete operation.\")\n\t\treturn wrapper\n\n\treturn decorator\n\ndef prepare_query(query_fields: str):\n\t\"\"\" Prepare the query string for the Azure Document Intelligence API\"\"\"\n\t# Split, strip, and replace spaces with underscores\n\tquery_list = query_fields.split(',')\n\tquery_list = [q.strip().replace(' ', '_') for q in query_list]\n\n\t# Check if query string is regex compatible\n\tfor q in query_list:\n\t\ttry:\n\t\t\tre.compile(q)\n\t\texcept re.error as e:\n\t\t\traise ValueError(f'Query string \"{q}\" is not regex compatible! Error: {e}')\n\n\t# Join back into a string with comma-separated values\n\tfinal_query_string = ','.join(query_list)\n\n\treturn final_query_string\n\ndef check_column_names(df):\n\t\"\"\"\n\tCheck dataframe column names for length (<=32) and truncate if needed to adhere to SAS table rules/limitations. \n\t\n\tArgs:\n\tdf (pd.DataFrame): The input DataFrame.\n\t\n\tReturns:\n\tpd.DataFrame: The DataFrame with truncated column names if necessary.\n\t\"\"\"\n\ttruncated_columns = {}\n\tfor col in df.columns:\n\t\tif len(col) > 32:\n\t\t\tnew_name = col[:29] + '...'\n\t\t\ttruncated_columns[col] = new_name\n\t\t\tSAS.logMessage(f\"Column '{col}' too long. Truncated to '{new_name}'.\", 'warning')\n\t\telse:\n\t\t\ttruncated_columns[col] = col\n\t\n\t# Rename the columns of the DataFrame\n\tdf.rename(columns=truncated_columns, inplace=True)\n\t\n\treturn df\n###################### OCR STRATEGIES #####################\n# parent class for the OCR strategies\nclass OCRStrategy:\n\t\"\"\" Base class for the OCR strategies \"\"\"\n\tdef __init__(self, kwargs):\n\t\tself.kwargs = kwargs\n\n\tdef parse_ocr_result(self, result) -> pd.DataFrame:\n\t\tpass\n\n\tdef analyze_document(self, document) -> pd.DataFrame:\n\t\tpass\n\n# implemented OCR strategies\nclass ExtractText(OCRStrategy): \n\tdef __init__(self, kwargs):\n\t\tself.endpoint = kwargs.get('endpoint', '')\n\t\tself.key = kwargs.get('key', '')\n\t\tself.model_id = kwargs.get('model_id', 'prebuilt-read')\n\t\tself.version = kwargs.get('version', '2023-10-31-preview')\n\t\tself.local_ocr = kwargs.get('local_ocr', False)\n\t\tself.input_type = kwargs.get('input_type', 'file')\n\t\tself.text_granularity = kwargs.get('text_granularity', 'line')\n\t\tself.file_location = kwargs.get('file_location', 'local')\n\t\tself.locale = kwargs.get('locale', '')\n\t\tself.model_id = kwargs.get('model_id', 'prebuilt-read')\n\n\t\tif self.local_ocr:\n\t\t\tself.endpoint = kwargs.get('endpoint', 'http://localhost:5000')\n\n\tdef parse_ocr_result(self,result) -> pd.DataFrame:\n\t\tparsed_result = pd.DataFrame()\n\n\t\t# set the text granularity\n\t\tlevel = self.text_granularity\n\t\tif (level.upper() == 'PAGE'):\n\t\t\tself.text_granularity = \"LINE\"\n\t\telse:\n\t\t\tself.text_granularity = level.upper()\n\t\t\n\t\tif self.text_granularity == \"DOCUMENT\":\n\t\t\tocr_data = []\n\t\t\t\n\t\t\t# check if the document contains handwriting\n\t\t\ttry:\n\t\t\t\tcontains_handwriting = result['styles'][0]['isHandwritten']\n\t\t\texcept:\n\t\t\t\tcontains_handwriting = False\n\n\t\t\tdocument_info = {\n\t\t\t\t\"text\": result['content'],\n\t\t\t\t\"contains_handwriting\": contains_handwriting,\n\t\t\t\t}\n\t\t\tocr_data.append(document_info)\n\t\t\tdf = pd.DataFrame(ocr_data)\n\t\t\tparsed_result = pd.concat([parsed_result, df], ignore_index=True)\n\n\t\telif self.text_granularity == \"PARAGRAPH\":\n\t\t\tocr_data = []\n\t\t\tprint('paragraph')\n\t\t\tfor paragraph_idx, paragraph in enumerate(result['paragraphs']):\n\t\t\t\tx1, y1, x2, y2, x3, y3, x4, y4 = paragraph['boundingRegions'][0]['polygon']\n\n\t\t\t\ttry: \n\t\t\t\t\trole = paragraph['role']\n\t\t\t\texcept:\n\t\t\t\t\trole = ''\n\n\t\t\t\tparagrpah_info = {\n\t\t\t\t\t\"page\": paragraph['boundingRegions'][0]['pageNumber'],\n\t\t\t\t\t\"paragraph\": paragraph_idx,\n\t\t\t\t\t\"role\": role,\n\t\t\t\t\t\"text\": paragraph['content'], \n\t\t\t\t\t\"bb_x1\": x1,\n\t\t\t\t\t\"bb_y1\": y1,\n\t\t\t\t\t\"bb_x2\": x2,\n\t\t\t\t\t\"bb_y2\": y2,\n\t\t\t\t\t\"bb_x3\": x3,\n\t\t\t\t\t\"bb_y3\": y3,\n\t\t\t\t\t\"bb_x4\": x4,\n\t\t\t\t\t\"bb_y4\": y4,\n\t\t\t\t\t\"offset\": paragraph['spans'][0]['offset'],\n\t\t\t\t\t\"length\": paragraph['spans'][0]['length'],\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tocr_data.append(paragrpah_info)\n\t\t\tdf = pd.DataFrame(ocr_data)\n\t\t\tparsed_result = pd.concat([parsed_result, df], ignore_index=True)\n\t\telse:\n\t\t\tfor page in result['pages']:\n\t\t\t\tocr_data = []\n\t\t\t\t\n\t\t\t\t# to calculate the average confidence\n\t\t\t\tif self.text_granularity != \"WORD\":\n\t\t\t\t\tword_confidences = [word['confidence'] for word in page['words']]\n\t\t\t\t\ttotal_confidence = sum(word_confidences)\n\t\t\t\t\ttotal_words = len(word_confidences)\n\t\t\t\t\taverage_confidence = total_confidence / total_words if total_words > 0 else 0\n\n\t\t\t\t# extraction on line level\n\t\t\t\tif self.text_granularity == \"LINE\":\n\t\t\t\t\tfor line_idx, line in enumerate(page['lines']):\n\t\t\t\t\t\tx1, y1, x2, y2, x3, y3, x4, y4 = line['polygon']\n\n\t\t\t\t\t\tline_info = {\n\t\t\t\t\t\t\t\"page\": page['pageNumber'],\n\t\t\t\t\t\t\t\"line\": line_idx,\n\t\t\t\t\t\t\t\"text\": line['content'],\n\t\t\t\t\t\t\t\"bb_x1\": x1,\n\t\t\t\t\t\t\t\"bb_y1\": y1,\n\t\t\t\t\t\t\t\"bb_x2\": x2,\n\t\t\t\t\t\t\t\"bb_y2\": y2,\n\t\t\t\t\t\t\t\"bb_x3\": x3,\n\t\t\t\t\t\t\t\"bb_y3\": y3,\n\t\t\t\t\t\t\t\"bb_x4\": x4,\n\t\t\t\t\t\t\t\"bb_y4\": y4,\n\t\t\t\t\t\t\t\"offset\": line['spans'][0]['offset'],\n\t\t\t\t\t\t\t\"length\": line['spans'][0]['length'],\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tocr_data.append(line_info)\n\n\t\t\t\t# extraction on word level\n\t\t\t\telif self.text_granularity == \"WORD\":\n\t\t\t\t\tfor word in page['words']:\n\t\t\t\t\t\tx1, y1, x2, y2, x3, y3, x4, y4 = word['polygon']\n\n\t\t\t\t\t\tword_info = {\n\t\t\t\t\t\t\t\"page\": page['pageNumber'],\n\t\t\t\t\t\t\t\"text\": word['content'],\n\t\t\t\t\t\t\t\"confidence\": word['confidence'],\n\t\t\t\t\t\t\t\"bb_x1\": x1,\n\t\t\t\t\t\t\t\"bb_y1\": y1,\n\t\t\t\t\t\t\t\"bb_x2\": x2,\n\t\t\t\t\t\t\t\"bb_y2\": y2,\n\t\t\t\t\t\t\t\"bb_x3\": x3,\n\t\t\t\t\t\t\t\"bb_y3\": y3,\n\t\t\t\t\t\t\t\"bb_x4\": x4,\n\t\t\t\t\t\t\t\"bb_y4\": y4,\n\t\t\t\t\t\t\t\"offset\": word['span']['offset'],\n\t\t\t\t\t\t\t\"length\": word['span']['length'],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tocr_data.append(word_info)\n\t\t\t\t\n\t\t\t\tdf = pd.DataFrame(ocr_data)\n\n\t\t\t\t# aggregation on page level\n\t\t\t\tif level.upper() == \"PAGE\":\n\t\t\t\t\tocr_data = []\n\t\t\t\t\tpage_info = {\n\t\t\t\t\t\t\t\"page\": page['pageNumber'],\n\t\t\t\t\t\t\t\"text\": \"\\n \".join(df['text']),\n\t\t\t\t\t\t\t\"avg_confidence\": average_confidence\n\t\t\t\t\t\t\t}\n\t\t\t\t\tocr_data.append(page_info)\n\t\t\t\t\t\n\t\t\t\t\tdf = pd.DataFrame(ocr_data)\n\n\t\t\t\tparsed_result = pd.concat([parsed_result, df], ignore_index=True)\n\n\t\tif self.model_id == 'prebuilt-read' and self.text_granularity.upper() == 'PARAGRAPH': # 'read' model doesn't provide semantic role, only 'layout' does\n\t\t\tparsed_result = parsed_result.drop(columns=['role'])\n\n\t\treturn parsed_result\n\n\t@retry_on_endpoint_connection_error(max_retries=n_con_retry, delay=retry_delay)\n\tdef analyze_document(self, document):\n\t\t\"\"\" Analyze the document and return the result\n\n\t\tParameters:\n\t\t-----------\n\t\tdocument:\n\t\t\tstr: document (base64) or url to document to analyze\n\t\t\n\t\tReturns:\n\t\t--------\n\t\tparsed_result:\n\t\t\tpd.DataFrame: OCR results\n\t\t \"\"\"\n\t\t# azure cloud\n\t\tif not self.local_ocr:\n\t\t\tif self.input_type.upper() == 'FILE':\n\t\t\t\tdata = {\n\t\t\t\t\t\"base64Source\": document\n\t\t\t\t}\n\t\t\telif self.input_type.upper() == 'URL':\n\t\t\t\tdata = {\n\t\t\t\t\t\"urlSource\": document\n\t\t\t\t}\n\n\t\t\turl = f\"{self.endpoint}documentintelligence/documentModels/{self.model_id}:analyze?_overload=analyzeDocument&api-version={self.version}\"\n\n\t\t\t# if a specific language was selected\n\t\t\tif self.locale != \"\":\n\t\t\t\turl = url + f'&locale={self.locale}'\n\n\t\t\theaders = {\n\t\t\t\t\"Ocp-Apim-Subscription-Key\": self.key,\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t}\n\n\t\t\tresponse = requests.post(url, headers=headers, json=data)\n\n\t\t\tif int(response.status_code) in {400, 403, 404}:\n\t\t\t\tSAS.logMessage(f'Error: {response.status_code} - {response.text}', 'error')\n\t\t\t\traise HTTPError(f'Error: {response.status_code} - {response.text}')\n\n\t\t\t# Check processing status\n\t\t\tresponse_url = response.headers.get('Operation-Location') # This is the URL you got from the POST response\n\t\t\theaders = {\n\t\t\t\t\"Ocp-Apim-Subscription-Key\": self.key\n\t\t\t}\n\n\t\t\titeration = 0\n\t\t\tstatus = ''\n\t\t\twhile status != 'succeeded' and iteration < timeout_seconds:\n\t\t\t\ttime.sleep(1)\n\t\t\t\tresponse = requests.get(response_url, headers=headers)\n\t\t\t\tstatus = response.json().get('status')\n\t\t\t\titeration += 1\n\n\t\t\t\tif status == 'succeeded':\n\t\t\t\t\tbreak\n\n\t\t\tif status != 'succeeded':\n\t\t\t\tSAS.logMessage(f'The request did not complete within the time limit. Iterations: {iteration}', 'error')\n\t\t\t\texit()\n\t\t\t\t\n\t\t\tresponse_json = json.loads(response.text)\n\t\t\tresult = response_json['analyzeResult'] \n\t\t\t\t\t\t\t\t\t\t\t \n\t\t# local ocr \n\t\telse:\n\t\t\turl = f\"{self.endpoint}/formrecognizer/documentModels/prebuilt-document:syncAnalyze?api-version=2022-08-31\"\n\t\t\theaders = {\n\t\t\t\t'accept': '*/*',\n\t\t\t\t'Content-Type': 'application/octet-stream',\n\t\t\t}\n\t\t\tresponse = requests.post(url, headers=headers, data=document)\n\t\t\tresponse_json = json.loads(response.text)\n\t\t\tresult = response_json['analyzeResult']\n\n\t\treturn result\n\nclass ExtractForm(OCRStrategy):\n\tdef __init__(self, kwargs):\n\t\tself.endpoint = kwargs.get('endpoint', '')\n\t\tself.key = kwargs.get('key', '')\n\t\tself.model_id = kwargs.get('model_id', 'prebuilt-layout')\n\t\tself.version = kwargs.get('version', '2023-10-31-preview')\n\t\tself.local_ocr = kwargs.get('local_ocr', False)\n\t\tself.input_type = kwargs.get('input_type', 'file')\n\t\tself.file_location = kwargs.get('file_location', 'local')\n\t\tself.locale = kwargs.get('locale', '')\n\n\t\tif self.local_ocr:\n\t\t\tself.endpoint = kwargs.get('endpoint', 'http://localhost:5000')\n\n\tdef parse_ocr_result(self, result) -> pd.DataFrame:\n\t\tkey_value_pairs = result['keyValuePairs']\n\t\tform_data = []\n\n\t\tfor pair in key_value_pairs:\n\t\t\tpage_number = pair['key']['boundingRegions'][0]['pageNumber']\n\t\t\tkey = pair['key']['content']\n\t\t\tkey_x1, key_y1, key_x2, key_y2, key_x3, key_y3, key_x4, key_y4 = pair['key']['boundingRegions'][0]['polygon']\n\t\t\tkey_offset = pair['key']['spans'][0]['offset']\n\t\t\tkey_length = pair['key']['spans'][0]['length']\n\n\t\t\ttry:\n\t\t\t\tvalue = pair['value']['content']\n\t\t\t\tvalue_x1, value_y1, value_x2, value_y2, value_x3, value_y3, value_x4, value_y4 = pair['value']['boundingRegions'][0]['polygon']\n\t\t\t\tvalue_offset = pair['value']['spans'][0]['offset']\n\t\t\t\tvalue_length = pair['value']['spans'][0]['length']\n\t\t\texcept KeyError as e:\n\t\t\t\tvalue_x1 = value_y1 = value_x2 = value_y2 = value_x3 = value_y3 = value_x4 = value_y4 = None\n\t\t\t\tvalue_offset = value_length = None\n\t\t\t\tvalue = None\n\n\t\t\tkey_value = {\n\t\t\t\t'page_number': page_number,\n\t\t\t\t'key': key,\n\t\t\t\t'value': value,\n\t\t\t\t'key_x1': key_x1,\n\t\t\t\t'key_y1': key_y1,\n\t\t\t\t'key_x2': key_x2,\n\t\t\t\t'key_y2': key_y2,\n\t\t\t\t'key_x3': key_x3,\n\t\t\t\t'key_y3': key_y3,\n\t\t\t\t'key_x4': key_x4,\n\t\t\t\t'key_y4': key_y4,\n\t\t\t\t'key_offset': key_offset,\n\t\t\t\t'key_length': key_length,\n\t\t\t\t'value_x1': value_x1,\n\t\t\t\t'value_y1': value_y1,\n\t\t\t\t'value_x2': value_x2,\n\t\t\t\t'value_y2': value_y2,\n\t\t\t\t'value_x3': value_x3,\n\t\t\t\t'value_y3': value_y3,\n\t\t\t\t'value_x4': value_x4,\n\t\t\t\t'value_y4': value_y4,\n\t\t\t\t'value_offset': value_offset,\n\t\t\t\t'value_length': value_length,\n\t\t\t}\n\n\t\t\tform_data.append(key_value)\n\t\t\n\t\tdf = pd.DataFrame(form_data)\n\n\t\treturn df\n\t\t\n\t@retry_on_endpoint_connection_error(max_retries=n_con_retry, delay=retry_delay)\n\tdef analyze_document(self, document):\n\t\tif not local_ocr:\n\t\t\tif self.input_type.upper() == 'FILE':\n\t\t\t\tdata = {\n\t\t\t\t\t\"base64Source\": document\n\t\t\t\t}\n\t\t\telif self.input_type.upper() == 'URL':\n\t\t\t\tdata = {\n\t\t\t\t\t\"urlSource\": document\n\t\t\t\t}\n\t\t\t\n\t\t\tfeatures = 'keyValuePairs'\n\t\t\turl = f\"{self.endpoint}documentintelligence/documentModels/{self.model_id}:analyze?_overload=analyzeDocument&api-version={self.version}&features={features}\"\n\n\t\t\t# if a specific language was selected\n\t\t\tif self.locale != \"\":\n\t\t\t\turl = url + f'&locale={self.locale}'\n\n\t\t\theaders = {\n\t\t\t\t\"Ocp-Apim-Subscription-Key\": self.key,\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t}\n\t\t\tresponse = requests.post(url, headers=headers, json=data)\n\t\t\tif int(response.status_code) in {400, 403, 404}:\n\t\t\t\tSAS.logMessage(f'Error: {response.status_code} - {response.text}', 'error')\n\t\t\t\traise HTTPError(f'Error: {response.status_code} - {response.text}')\n\n\t\t\t# Check processing status\n\t\t\tresponse_url = response.headers.get('Operation-Location') # This is the URL you got from the POST response\n\t\t\theaders = {\n\t\t\t\t\"Ocp-Apim-Subscription-Key\": self.key\n\t\t\t}\n\n\t\t\titeration = 0\n\t\t\tstatus = ''\n\n\t\t\twhile status != 'succeeded' and iteration < timeout_seconds:\n\t\t\t\ttime.sleep(1)\n\t\t\t\tresponse = requests.get(response_url, headers=headers)\n\t\t\t\tstatus = response.json().get('status')\n\t\t\t\titeration += 1\n\n\t\t\t\tif status == 'succeeded':\n\t\t\t\t\tbreak\n\n\t\t\tif status != 'succeeded':\n\t\t\t\tSAS.logMessage(f'The request did not complete within the time limit. Iterations: {iteration}', 'error')\n\t\t\t\texit()\n\t\t\t\t\n\t\t\tresponse_json = json.loads(response.text)\n\t\t\tresult = response_json['analyzeResult'] \n\t\telse:\n\t\t\turl = f\"{self.endpoint}/formrecognizer/documentModels/prebuilt-document:syncAnalyze?api-version=2022-08-31\"\n\t\t\theaders = {\n\t\t\t\t'accept': '*/*',\n\t\t\t\t'Content-Type': 'application/octet-stream',\n\t\t\t}\n\n\t\t\tresponse = requests.post(url, headers=headers, data=document)\n\t\t\tresponse_json = json.loads(response.text)\n\t\t\tresult = response_json['analyzeResult']\n\t\t\n\t\treturn result\n\nclass ExtractQuery(OCRStrategy):\n\tdef __init__(self, kwargs):\n\t\tself.endpoint = kwargs.get('endpoint', '')\n\t\tself.key = kwargs.get('key', '')\n\t\tself.model_id = kwargs.get('model_id', 'prebuilt-layout')\n\t\tself.version = kwargs.get('version', '2023-10-31-preview')\n\t\tself.input_type = kwargs.get('input_type', 'file')\n\t\tself.file_location = kwargs.get('file_location', 'local')\n\t\tself.locale = kwargs.get('locale', '')\n\t\tself.query_fields = kwargs.get('query_fields', '')\n\t\tself.query_exclude_metadata = kwargs.get('query_exclude_metadata', False)\n\n\tdef parse_ocr_result(self, result) -> pd.DataFrame:\n\t\tquery_data = []\n\t\tfor doc in result['documents']:\n\t\t\tfor field in doc['fields'].keys():\n\t\t\t\tif not self.query_exclude_metadata:\n\t\t\t\t\ttry:\n\t\t\t\t\t\tx1, y1, x2, y2, x3, y3, x4, y4 = doc['fields'][field]['boundingRegions'][0]['polygon']\n\t\t\t\t\t\tquery_info = {\n\t\t\t\t\t\t\t'page_number': doc['fields'][field]['boundingRegions'][0]['pageNumber'],\n\t\t\t\t\t\t\t'key': field,\n\t\t\t\t\t\t\t'value': doc['fields'][field]['content'],\n\t\t\t\t\t\t\t'confidence': doc['fields'][field]['confidence'],\n\t\t\t\t\t\t\t'type': doc['fields'][field]['type'],\n\t\t\t\t\t\t\t'x1': x1,\n\t\t\t\t\t\t\t'y1': y1,\n\t\t\t\t\t\t\t'x2': x2,\n\t\t\t\t\t\t\t'y2': y2,\n\t\t\t\t\t\t\t'x3': x3,\n\t\t\t\t\t\t\t'y3': y3,\n\t\t\t\t\t\t\t'x4': x4,\n\t\t\t\t\t\t\t'y4': y4,\n\t\t\t\t\t\t\t'offset': doc['fields'][field]['spans'][0]['offset'],\n\t\t\t\t\t\t\t'length': doc['fields'][field]['spans'][0]['length'],\n\t\t\t\t\t\t}\n\t\t\t\t\texcept KeyError as e:\n\t\t\t\t\t\tquery_info = {\n\t\t\t\t\t\t\t'page_number': None,\n\t\t\t\t\t\t\t'key': field,\n\t\t\t\t\t\t\t'value': None,\n\t\t\t\t\t\t\t'confidence': None,\n\t\t\t\t\t\t\t'type': None,\n\t\t\t\t\t\t\t'x1': None,\n\t\t\t\t\t\t\t'y1': None,\n\t\t\t\t\t\t\t'x2': None,\n\t\t\t\t\t\t\t'y2': None,\n\t\t\t\t\t\t\t'x3': None,\n\t\t\t\t\t\t\t'y3': None,\n\t\t\t\t\t\t\t'x4': None,\n\t\t\t\t\t\t\t'y4': None,\n\t\t\t\t\t\t\t'offset': None,\n\t\t\t\t\t\t\t'length': None,\n\t\t\t\t\t\t}\n\t\t\t\t\tquery_data.append(query_info)\n\t\t\t\telse:\n\t\t\t\t\ttry:\n\t\t\t\t\t\tquery_info = {\n\t\t\t\t\t\t\t'key': field,\n\t\t\t\t\t\t\t'value': doc['fields'][field]['content'],\n\t\t\t\t\t\t}\n\t\t\t\t\texcept KeyError as e:\n\t\t\t\t\t\tquery_info = {\n\t\t\t\t\t\t\t'key': field,\n\t\t\t\t\t\t\t'value': None,\n\t\t\t\t\t\t}\n\t\t\t\t\tquery_data.append(query_info)\n\n\t\tparsed_result = pd.DataFrame(query_data)\n\n\t\t# if query_exclude_metadata, transpose results\n\t\tif query_exclude_metadata:\n\t\t\tparsed_result = parsed_result.set_index('key').T\n\n\t\treturn parsed_result\n\t\t\n\t@retry_on_endpoint_connection_error(max_retries=n_con_retry, delay=retry_delay)\n\tdef analyze_document(self, document):\n\t\tif self.input_type.upper() == 'FILE':\n\t\t\tdata = {\n\t\t\t\t\"base64Source\": document\n\t\t\t}\n\t\telif self.input_type.upper() == 'URL':\n\t\t\tdata = {\n\t\t\t\t\"urlSource\": document\n\t\t\t}\n\t\t\n\t\tfeatures = 'queryFields'\n\t\turl = f\"{self.endpoint}/documentintelligence/documentModels/{self.model_id}:analyze?_overload=analyzeDocument&api-version={self.version}&features={features}&queryFields={self.query_fields}\"\n\t\theaders = {\n\t\t\t\"Ocp-Apim-Subscription-Key\": self.key,\n\t\t\t\"Content-Type\": \"application/json\"\n\t\t}\n\n\t\tresponse = requests.post(url, headers=headers, json=data)\n\n\t\tif int(response.status_code) in {400, 403, 404}:\n\t\t\tSAS.logMessage(f'Error: {response.status_code} - {response.text}', 'error')\n\t\t\traise HTTPError(f'Error: {response.status_code} - {response.text}')\n\n\n\t\t# Check processing status\n\t\tresponse_url = response.headers.get('Operation-Location') # This is the URL you got from the POST response\n\t\theaders = {\n\t\t\t\"Ocp-Apim-Subscription-Key\": self.key\n\t\t}\n\n\t\titeration = 0\n\t\tstatus = ''\n\n\t\twhile status != 'succeeded' and iteration < timeout_seconds:\n\t\t\ttime.sleep(1)\n\t\t\tresponse = requests.get(response_url, headers=headers)\n\t\t\tstatus = response.json().get('status')\n\t\t\titeration += 1\n\n\t\t\tif status == 'succeeded':\n\t\t\t\tbreak\n\n\t\tif status != 'succeeded':\n\t\t\tprint('The request did not complete within the time limit.')\n\t\t\texit()\n\t\t\t\n\t\t# return results\n\t\tresponse_json = json.loads(response.text)\n\t\tresult = response_json['analyzeResult'] \n\t\treturn result\n\nclass ExtractTable(OCRStrategy):\n\tdef __init__(self, kwargs): \n\t\tself.endpoint = kwargs.get('endpoint', '')\n\t\tself.key = kwargs.get('key', '')\n\t\tself.model_id = kwargs.get('model_id', 'prebuilt-layout')\n\t\tself.version = kwargs.get('version', '2023-10-31-preview')\n\t\tself.local_ocr = kwargs.get('local_ocr', False)\n\t\tself.input_type = kwargs.get('input_type', 'file')\n\t\tself.file_location = kwargs.get('file_location', 'local')\n\t\tself.locale = kwargs.get('locale', '')\n\t\tself.table_output_format = kwargs.get('table_output_format', 'map')\n\t\tself.select_table = kwargs.get('select_table', False)\n\t\tself.table_selection_method = kwargs.get('table_selection_method', 'index')\n\t\tself.table_selection_idx = kwargs.get('table_selection_idx', 0)\n\t\tself.table_output_caslib = kwargs.get('table_output_caslib', 'work')\n\n\t\tif self.local_ocr:\n\t\t\tself.endpoint = kwargs.get('endpoint', 'http://localhost:5000')\n\n\tdef result_to_dfs(self, result) -> list:\n\t\ttables = []\n\t\tfor table in result['tables']:\n\t\t\ttable_df = pd.DataFrame(columns=range(table['columnCount']), index=range(table['rowCount']))\n\n\t\t\tfor cell in table['cells']:\n\t\t\t\ttable_df.iloc[cell['rowIndex'], cell['columnIndex']] = cell['content']\n\n\t\t\t# use the first row as column names\n\t\t\ttable_df.columns = table_df.iloc[0]\n\t\t\ttable_df = table_df[1:]\n\t\t\t\n\t\t\ttables.append(table_df)\n\t\treturn tables\n\n\t# TABLE PARSING METHODS\n\tdef map_parsing(self, result) -> pd.DataFrame:\n\t\t\"\"\" Parses tables as a list of column/row index and cell content for later reconstruction.\"\"\"\n\t\ttables = []\n\n\t\t# extract all table data\n\t\tfor index, table in enumerate(result['tables']):\n\t\t\tif self.table_output_format.upper() == 'MAP':\n\n\t\t\t\tif not isinstance(table, dict):\n\t\t\t\t\ttable = table.as_dict()\n\n\t\t\t\tdf = pd.DataFrame.from_dict(table['cells'])\n\n\t\t\t\t# extract page_number and polygon coordinates\n\t\t\t\tdf['page'] = df['boundingRegions'].apply(lambda x: x[0]['pageNumber'])\n\t\t\t\tdf['table_index'] = index\n\t\t\t\tdf['polygon'] = df['boundingRegions'].apply(lambda x: x[0]['polygon'])\n\n\t\t\t\t# extract polygon coordinates\n\t\t\t\tdf['x1'] = df['polygon'].apply(lambda x: x[0])\n\t\t\t\tdf['y1'] = df['polygon'].apply(lambda x: x[1])\n\t\t\t\tdf['x2'] = df['polygon'].apply(lambda x: x[2])\n\t\t\t\tdf['y2'] = df['polygon'].apply(lambda x: x[3])\n\t\t\t\tdf['x3'] = df['polygon'].apply(lambda x: x[4])\n\t\t\t\tdf['y3'] = df['polygon'].apply(lambda x: x[5])\n\t\t\t\tdf['x4'] = df['polygon'].apply(lambda x: x[6])\n\t\t\t\tdf['y4'] = df['polygon'].apply(lambda x: x[7])\n\n\t\t\t\t# extract offset and length\n\t\t\t\tdf['offset'] = df['spans'].apply(lambda x: int(x[0]['offset']) if x else None)\n\t\t\t\tdf['length'] = df['spans'].apply(lambda x: int(x[0]['length']) if x else None)\n\n\t\t\t\t# drop unnecessary columns\n\t\t\t\tdf.drop(columns=['boundingRegions','spans', 'polygon'], inplace=True)\n\n\t\t\t\ttable_info = {\n\t\t\t\t\t'table_index': index,\n\t\t\t\t\t'row_count': table['rowCount'],\n\t\t\t\t\t'column_count': table['columnCount'],\n\t\t\t\t\t'cell_count': table['rowCount']*table['columnCount'],\n\t\t\t\t\t'table': df\n\t\t\t\t}\n\n\t\t\t\ttables.append(table_info)\n\n\t\t# select specific table (optional)\n\t\tif self.select_table:\n\t\t\tif self.table_selection_method.upper() == 'INDEX':\n\t\t\t\tparsed_result = tables[table_selection_idx]['table']\n\t\t\telif self.table_selection_method.upper() == 'SIZE':\n\t\t\t\t# Find the entry with the highest cell_count using max function\n\t\t\t\ttable_most_cells = max(tables, key=lambda x: x['cell_count'], default=None)\n\t\t\t\tparsed_result = table_most_cells['table'] if table_most_cells else None\n\n\t\telse:\n\t\t\t# combine all extracted tables (only works for output type 'map')\n\t\t\tparsed_result = pd.concat([table['table'] for table in tables], ignore_index=True)\n\n\t\treturn parsed_result\n\n\tdef reference_parsing(self, result) -> pd.DataFrame: \n\t\t\"\"\" Parses and stores every table to specified SAS Library and returns a generated reference ID.\"\"\"\n\t\ttables = self.result_to_dfs(result)\n\t\ttable_info = []\n\n\t\tfor table in tables:\n\t\t\treference = uuid.uuid4()\n\t\t\treference = re.sub(r'^\\w{3}', 'tbl', str(reference))\n\t\t\treference = reference.replace('-', '')\n\t\t\ttable = check_column_names(table)\n\n\t\t\t# save table to caslib\n\t\t\ttry:\n\t\t\t\tSAS.df2sd(table, f\"{self.table_output_caslib}.{reference}\")\n\t\t\t\tSAS.logMessage(f\"Save Table {reference} to {self.table_output_caslib}\")\n\t\t\texcept Exception as e:\n\t\t\t\tSAS.logMessage(f'{e} Failed to save table {reference} to caslib {self.table_output_caslib}', 'error')\n\t\t\t\traise e\n\t\t\t\n\t\t\ttable_info.append({\n\t\t\t\t'out_library': self.table_output_caslib,\n\t\t\t\t'table_reference': reference,\n\t\t\t\t'row_count': table.shape[0],\n\t\t\t\t'column_count': table.shape[1],\n\t\t\t})\n\n\t\tparsed_result = pd.DataFrame(table_info)\n\t\treturn parsed_result\n\n\tdef table_parsing(self, result) -> pd.DataFrame:\n\t\t\"\"\" For a given document parses and returns one table. For multiple tables: Selection by size or index\"\"\"\n\t\ttables = self.result_to_dfs(result)\n\t\tself.select_table = True\n\n\t\t# select specific table \n\t\tif self.select_table:\n\t\t\tif self.table_selection_method.upper() == 'INDEX': # Table with index == table_selection_idx\n\t\t\t\tparsed_result = tables[table_selection_idx]\n\t\t\telif self.table_selection_method.upper() == 'SIZE': # Table with most cells\n\t\t\t\ttable_most_cells = max(tables, key=lambda x: x.size, default=None)\n\t\t\t\ttry:\n\t\t\t\t\tparsed_result = table_most_cells\n\t\t\t\texcept:\n\t\t\t\t\tparsed_result = None\n\n\t\t\telse:\n\t\t\t\traise ValueError(f'Invalid table selection method: {self.table_selection_method}')\n\n\t\tparsed_result = check_column_names(parsed_result)\n\n\t\treturn parsed_result\n\n\t# TABLE PARSING METHODS MAPPING\n\tparsing_methods = {\n\t\t'MAP': map_parsing,\n\t\t'REFERENCE': reference_parsing,\n\t\t'TABLE': table_parsing\n\t}\n\n\tdef parse_ocr_result(self, result) -> pd.DataFrame:\n\t\t# call one of the parsing methods depending on the output format\n\t\tparsing_method = table_output_format.upper()\n\t\tparsed_result = self.parsing_methods.get(parsing_method)(self,result = result)\n\n\t\treturn parsed_result\n\n\t@retry_on_endpoint_connection_error(max_retries=n_con_retry, delay=retry_delay)\n\tdef analyze_document(self, document):\n\t\tif not self.local_ocr: \n\t\t\tif self.input_type.upper() == 'FILE':\n\t\t\t\tdata = {\n\t\t\t\t\t\"base64Source\": document\n\t\t\t\t}\n\t\t\telif self.input_type.upper() == 'URL':\n\t\t\t\tdata = {\n\t\t\t\t\t\"urlSource\": document\n\t\t\t\t}\n\t\t\t\n\t\t\turl = f\"{self.endpoint}documentintelligence/documentModels/{self.model_id}:analyze?_overload=analyzeDocument&api-version={self.version}\"\n\n\t\t\t# if a specific language was selected\n\t\t\tif self.locale != \"\":\n\t\t\t\turl = url + f'&locale={self.locale}'\n\n\t\t\theaders = {\n\t\t\t\t\"Ocp-Apim-Subscription-Key\": self.key,\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t}\n\n\t\t\tresponse = requests.post(url, headers=headers, json=data)\n\n\t\t\tif int(response.status_code) in {400, 403, 404}:\n\t\t\t\tSAS.logMessage(f'Error: {response.status_code} - {response.text}', 'error')\n\t\t\t\traise HTTPError(f'Error: {response.status_code} - {response.text}')\n\n\t\t\t# Check processing status\n\t\t\tresponse_url = response.headers.get('Operation-Location') # This is the URL you got from the POST response\n\t\t\theaders = {\n\t\t\t\t\"Ocp-Apim-Subscription-Key\": self.key\n\t\t\t}\n\n\t\t\titeration = 0\n\t\t\tstatus = ''\n\n\t\t\twhile status != 'succeeded' and iteration < timeout_seconds:\n\t\t\t\ttime.sleep(1)\n\t\t\t\tresponse = requests.get(response_url, headers=headers)\n\t\t\t\tstatus = response.json().get('status')\n\t\t\t\titeration += 1\n\n\t\t\t\tif status == 'succeeded':\n\t\t\t\t\tbreak\n\n\t\t\tif status != 'succeeded':\n\t\t\t\tprint('The request did not complete within the time limit.')\n\t\t\t\texit()\n\t\t\t\t\n\t\t\tresponse_json = json.loads(response.text)\n\t\t\tresult = response_json['analyzeResult'] \n\t\telse:\n\t\t\turl = f\"{self.endpoint}/formrecognizer/documentModels/prebuilt-document:syncAnalyze?api-version=2022-08-31\"\n\n\t\t\theaders = {\n\t\t\t\t'accept': '*/*',\n\t\t\t\t'Content-Type': 'application/octet-stream',\n\t\t\t}\n\n\t\t\tresponse = requests.post(url, headers=headers, data=document)\n\t\t\tresponse_json = json.loads(response.text)\n\t\t\tresult = response_json['analyzeResult']\n\t\t\n\t\treturn result\n\n# class that processes the OCR\nclass OCRProcessor:\n\t\"\"\" Class that processes the OCR depending on the strategy\"\"\"\n\tdef __init__(self, ocr_type:str, **kwargs):\n\t\tself.ocr_type = ocr_type\n\t\tself.kwargs = kwargs\n\n\t\t# Define the strategy mapping\n\t\tself.strategy_mapping = {\n\t\t\t('text'): ExtractText,\n\t\t\t('form'): ExtractForm,\n\t\t\t('query'): ExtractQuery,\n\t\t\t('table'): ExtractTable\n\t\t}\n\n\t\t# Get the strategy class, parameters and initiate strategy\n\t\tstrategy_class = self.strategy_mapping[(self.ocr_type)]\n\t\tself.strategy = strategy_class(kwargs = self.kwargs)\n\n\tdef analyze_document(self, document):\n\t\t\"\"\" Analyze the document and return the result\n\t\t\n\t\tParameters:\n\t\t-----------\n\t\tdocument:\n\t\t\tstr: document (base64) or document url to analyze\n\t\t\t\n\t\tReturns:\n\t\t--------\n\t\tresult:\n\t\t\tAnalyzeResult: OCR results\"\"\"\n\n\t\treturn self.strategy.analyze_document(document)\n\t\n\tdef parse_ocr_result(self, result) -> pd.DataFrame:\n\t\t\"\"\" Parse the OCR result and return the result\n\n\t\tParameters:\n\t\t-----------\n\t\tresult:\n\t\t\tAnalyzeResult: OCR results\n\n\t\tReturns:\n\t\t--------\n\t\tparsed_result:\n\t\t\tpd.DataFrame: parsed OCR results\n\t\t\"\"\"\n\t\treturn self.strategy.parse_ocr_result(result)\n\t\n###################### PREPARATION ######################\nif input_mode.upper() == 'BATCH': # When input_mode = 'batch' try to load the file list using the input_table_name\n\ttry:\n\t\tfile_list = SAS.sd2df(input_table_name)\n\texcept Exception as e:\n\t\tSAS.logMessage('No input table was provided!', 'error')\n\t\texit()\n\n\t\"\"\"if path_column not in file_list.columns:\n\t\tSAS.logMessage(f'Path column not found in input table! Provided path column: {path_column}', 'error')\n\t\texit()\"\"\"\nelse:\n\tfile_list = ''\n\nif ocr_type.upper() == 'QUERY': # prepare the query string to the right format\n\ttry:\n\t\tquery_fields = prepare_query(query_fields)\n\texcept ValueError as e:\n\t\tprint(f'REGEX ERROR: {e}')\n\t\texit()\n\texcept Exception as e:\n\t\tprint(f'ERROR: {e}')\n\t\texit()\n\nif input_mode.upper() == 'SINGLE': # if input_mode = 'single', create a dataframe with the file path\n\tif file_path.startswith('sasserver:'):\n\t\tfile_path = (file_path[len('sasserver:'):])\n\telif file_path.startswith('sascontent:'):\n\t\tSAS.logMessage(\"Please select a valid path. Files have to be located on SAS Server (not SAS Content)!\", 'error')\n\t\texit()\n\tif input_type.upper() == 'URL': \n\t\tfile_path = file_url\n\tfile_list = pd.DataFrame({'file_path': [file_path]})\n\tpath_column = 'file_path'\n\nif save_json: # check if output folder should be created (if save_json = True)\n\t# remove 'sasserver:'\n\tif json_output_folder.startswith('sasserver:'):\n\t\tjson_output_folder = (json_output_folder[len('sasserver:'):])\n\n\t# check if output folder exists\n\tif not os.path.exists(json_output_folder):\n\t\ttry:\n\t\t\tos.makedirs(json_output_folder)\n\t\t\tSAS.logMessage(f'Created output folder {json_output_folder}!')\n\t\texcept OSError as e:\n\t\t\tSAS.logMessage(f'OSError - Could not create output folder {json_output_folder}!', 'error')\n\t\t\texit()\n\t\n\t# check if output folder is writable\n\tif not os.access(json_output_folder, os.W_OK):\n\t\tSAS.logMessage(f'OSError - Output folder {json_output_folder} is not writable!', 'error')\n\t\texit()\n\nif local_ocr: # check if local ocr container is running and reachable\n\tfor check in ['status', 'ready', 'containerliveness']:\n\t\turl = f'{local_ocr_endpoint}/{check}'\n\t\theaders = {\n\t\t\t'accept': '*/*',\n\t\t}\n\t\tresponse = requests.get(url, headers=headers)\n\t\tif response.status_code != 200:\n\t\t\tSAS.logMessage(f\"Local OCR container is not running or can't be reached! {check}: {response.status_code}\", 'error')\n\t\t\texit()\n\t\n\tSAS.logMessage('Local OCR container is running!')\n\nif ocr_type.upper() != 'TEXT': \n\tmodel_id = DEFAULT_MODEL_ID\nelse:\n\tif extract_pragraph_roles:\n\t\tmodel_id = DEFAULT_MODEL_ID\n\telse:\n\t\tmodel_id = 'prebuilt-read'\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n###################### PRE-CHECKS ######################\nif ocr_type.upper() == 'TABLE' and table_output_format.upper() == 'TABLE' and file_list.shape[0] > 1: # if table_output_format = 'table', check if only one row in the file_list\n\tSAS.logMessage('Only one file as input is supported if output format = \"table\"!')\n\texit()\n\nif input_mode.upper() == 'BATCH':\n\tif file_list.shape[0] < 1: # if input_mode = 'batch' and input_type = 'file', check if the file list is not empty\n\t\tSAS.logMessage('Provided file list is empty!', 'error')\n\t\texit()\n\nif local_ocr: # Local OCR doesn't support Query extraction \n\tif ocr_type.upper() == 'QUERY':\n\t\tSAS.logMessage('Local OCR container does not support query extraction!', 'error')\n\t\texit()\n\nif not local_ocr: \n\tif azure_endpoint == 'https://your-resource.cognitiveservices.azure.com/' or azure_endpoint == '': # If no endpoint was provided\n\t\tSAS.logMessage('ERROR - No Azure Document Intelligence Endpoint Provided!', 'error')\n\t\texit()\n\tif azure_key == 'SECRET_KEY' or azure_key == '': # If no azure key was provided\n\t\tSAS.logMessage('ERROR - No Azure Document Intelligence Secret Key Provided!', 'error')\n\t\texit()\n\n\n###################### EXECUTION ######################\nSAS.logMessage(f\"START PROCESSING - Type: {ocr_type}, Mode: {input_mode}, Input Type: {input_type}\")\n# define all possible parameters for the OCR\nocr_params = {\n\t\t\t # general\n\t\t\t 'locale': locale,\n\t\t\t 'input_type': input_type,\n\t\t\t 'local_ocr': local_ocr,\n\t\t\t 'endpoint': azure_endpoint,\n\t\t\t 'key': azure_key,\n\t\t\t 'model_id': model_id,\n\t\t\t 'version': API_VERSION,\n\t\t\t # for text extraction\n\t\t\t 'text_granularity': text_granularity,\n\t\t\t # for query extraction\n\t\t\t 'query_fields': query_fields,\n\t\t\t 'query_exclude_metadata': query_exclude_metadata,\n\t\t\t # for table extraction\n\t\t\t 'table_output_format': table_output_format,\n\t\t\t 'selected_table': select_table,\n\t\t\t 'selection_method': table_selection_method,\n\t\t\t 'table_selection_idx': table_selection_idx,\n\t\t\t 'table_output_caslib': table_output_library,\n\t\t\t }\n\n# initiate dataframe to store results and status\nocr_results = pd.DataFrame()\nstatus = pd.DataFrame()\n\n# initiate the OCR client and processor\nocr_processor = OCRProcessor(ocr_type = ocr_type, \n\t\t\t\t\t\t\t **ocr_params\n\t\t\t\t\t\t\t )\n\ndef process_files(file_list, ocr_processor, path_column):\n\t\"\"\" Process the files in the file_list using the ocr_processor\n\n\tParameters:\n\t-----------\n\tfile_list:\n\t\tpd.DataFrame: dataframe containing the file paths\n\tocr_processor:\n\t\tOCRProcessor: OCR processor\n\tpath_column:\n\t\tstr: column that contains the file path\n\t\"\"\"\n\t# go through every document in the list\n\tglobal ocr_results, status, SUPPORTED_EXTENSIONS\n\n\tfor _, row in file_list.iterrows():\n\t\tSAS.logMessage(f'Processing file: {row[path_column]}')\n\t\tfile_ok = True\n\t\tdone = False\n\t\tn_rows = 0\n\t\terror_type = ''\n\t\tmessage = ''\n\t\tstart = datetime.now()\n\n\t\t# perform the OCR\n\t\tif input_type.upper() == 'FILE':\n\t\t\ttry:\n\t\t\t\tfile_extension = row[path_column].split('.')[-1].lower()\n\t\t\t\tif file_extension not in SUPPORTED_EXTENSIONS:\n\t\t\t\t\tSAS.logMessage(f\"Unsupported file type: '.{file_extension}'. Supported file types are: {', '.join(SUPPORTED_EXTENSIONS)}\", 'warning')\n\t\t\t\t\terror_type = 'UnsupportedFileType'\n\t\t\t\t\tmessage = f\"Unsupported file type: {file_extension}. Supported file types are: {', '.join(SUPPORTED_EXTENSIONS)}\"\n\t\t\t\t\tfile_ok = False\n\t\t\t\twith open(row[path_column], 'rb') as file:\n\t\t\t\t\tdoc_data = file.read()\n\t\t\t\t\tbase64_encoded_data = base64.b64encode(doc_data)\n\t\t\t\t\tdocument = base64_encoded_data.decode('utf-8')\n\t\t\texcept FileNotFoundError as e:\n\t\t\t\tSAS.logMessage(f\"FILE NOT FOUND: {row[path_column]}. Please make sure the file paths are correct and the files are located on 'sasserver'. SAS Content is not supported!\", 'error')\n\t\t\t\terror_type = type(e).__name__\n\t\t\t\tmessage = str(e)\n\t\t\t\tfile_ok = False\n\n\t\telif input_type.upper() == 'URL':\n\t\t\tdocument = row[path_column]\n\n\t\tif file_ok == True:\n\t\t\ttry:\n\t\t\t\t# run ocr processing on the document\n\t\t\t\tSAS.logMessage(f'Start Processing of: {row[path_column]}')\n\t\t\t\tresult = ocr_processor.analyze_document(document=document)\n\t\t\t\tSAS.logMessage(f'Received OCR Result for file: {row[path_column]}')\n\n\t\t\t\t# parse the ocr result\n\t\t\t\tparsed_result = ocr_processor.parse_ocr_result(result=result)\n\t\t\t\tSAS.logMessage(f'Parsed Result Shape: {ocr_results.shape}, for file: {row[path_column]}')\n\n\t\t\t\t# add the file path to the result\n\t\t\t\tif not parsed_result.empty:\n\t\t\t\t\tparsed_result[path_column] = row[path_column]\n\n\t\t\t\t# append result to the overall result table\n\t\t\t\tif not parsed_result.empty:\n\t\t\t\t\tocr_results = pd.concat(\n\t\t\t\t\t\t[ocr_results, parsed_result], ignore_index=True)\n\t\t\t\t\tn_rows = parsed_result.shape[0]\n\t\t\t\tdone = True\n\n\t\t\texcept Exception as e:\n\t\t\t\terror_type = type(e).__name__\n\t\t\t\tmessage = str(e)\n\t\t\t\tSAS.logMessage(f'Warning: {error_type} - {message} - for {row[path_column]}', 'warning')\n\n\t\t# Post processing\n\t\t# if output_table_format = 'table', drop the path_column\n\t\tif ocr_type.upper() == 'TABLE' and table_output_format.upper() == 'TABLE':\n\t\t\tocr_results.drop(columns=[path_column], inplace=True)\n\n\t\t# save raw ocr results as json if save_json = True\n\t\tif done and save_json: # if save_json = True, save the azure ocr result as json\n\t\t\ttry:\n\t\t\t\twith open(f'{json_output_folder}/{os.path.basename(row[path_column]).split(\".\")[0]}_{ocr_type}OCR.json', 'w') as f:\n\t\t\t\t\tjson.dump(result, f)\n\t\t\texcept Exception as e:\n\t\t\t\terror_type = type(e).__name__\n\t\t\t\tmessage = str(e)\n\t\t\t\tSAS.logMessage(f'Warning: {error_type} - {message} for {row[path_column]}', 'warning')\n\n\t\t# update the status\n\t\tdoc_status = {'file': row[path_column],\n\t\t\t\t\t 'done': done,\n\t\t\t\t\t 'num_rows': n_rows,\n\t\t\t\t\t 'error_type': error_type,\n\t\t\t\t\t 'message': message,\n\t\t\t\t\t 'start': start,\n\t\t\t\t\t 'end': datetime.now(),\n\t\t\t\t\t 'duration_seconds': round((datetime.now() - start).total_seconds(), 3)\n\t\t\t\t\t }\n\n\t\tstatus = pd.concat([status, pd.DataFrame(\n\t\t\tdoc_status, index=[0])], ignore_index=True)\n\n\n# Parallel processing of the files\ndf_split = np.array_split(file_list, n_threads)\nthreads = []\n\nif file_list.shape[0] < n_threads:\n\tn_threads = file_list.shape[0]\n\nfor i in range(n_threads):\n\tpaths = df_split[i]\n\tthread = threading.Thread(target=process_files, args=(paths, ocr_processor, path_column))\n\tthreads.append(thread)\n\tthread.start()\n\tSAS.logMessage(f'Started thread {i+1} of {n_threads}!', 'info')\n\n# Wait for all threads to complete\nfor index, thread in enumerate(threads):\n\tthread.join()\n\tSAS.logMessage(f'Thread {index+1} of {n_threads} completed!', 'info')\n\nSAS.logMessage(f'FINISHED - Successfully processed {status[\"done\"].sum()} / {status.shape[0]} files!', 'info')\n\n# Output the results\nSAS.df2sd(ocr_results, SAS.symget(\"outputtable1\"))\nif output_status_table:\n\tSAS.logMessage(f'Output status table with {status.shape[0]} rows!', 'info')\n\tSAS.df2sd(status, SAS.symget(\"outputtable2\"))\n\tpass\n\nendsubmit;\nrun;\n\nproc python terminate; quit; "}}