From 754194c958937baf387e1885c276aa4481a39449 Mon Sep 17 00:00:00 2001 From: "Zhang, Chaojun" Date: Wed, 20 Dec 2023 10:39:39 +0000 Subject: [PATCH 01/59] Refine rag pipeline --- .../llmutils/rag_cnvrg_pipeline.ipynb | 203 +-- .../rag_cnvrg_pipeline_step_by_step.ipynb | 1181 +++++++++-------- .../pyrecdp/primitives/operations/__init__.py | 2 +- .../primitives/operations/doc_loader.py | 130 +- .../primitives/operations/text_ingestion.py | 28 +- RecDP/tests/test_llmutils_pipelines.py | 4 +- 6 files changed, 871 insertions(+), 677 deletions(-) diff --git a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb index f2cf8c20..8d55cec5 100644 --- a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb +++ b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb @@ -67,7 +67,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 2, "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a", "metadata": { "colab": { @@ -82,39 +82,37 @@ "name": "stdout", "output_type": "stream", "text": [ - "\u001B[32m2023-12-13 11:30:37.277\u001B[0m | \u001B[1mINFO \u001B[0m | \u001B[36mpyrecdp.core.import_utils\u001B[0m:\u001B[36mcheck_availability_and_install\u001B[0m:\u001B[36m45\u001B[0m - \u001B[1mcheck_availability_and_install ['unstructured']\u001B[0m\n", - "\u001B[32m2023-12-13 11:30:37.281\u001B[0m | \u001B[1mINFO \u001B[0m | \u001B[36mpyrecdp.core.import_utils\u001B[0m:\u001B[36mcheck_availability_and_install\u001B[0m:\u001B[36m45\u001B[0m - \u001B[1mcheck_availability_and_install ['ftfy', 'selectolax']\u001B[0m\n", - "\u001B[32m2023-12-13 11:30:37.284\u001B[0m | \u001B[1mINFO \u001B[0m | \u001B[36mpyrecdp.core.import_utils\u001B[0m:\u001B[36mcheck_availability_and_install\u001B[0m:\u001B[36m45\u001B[0m - \u001B[1mcheck_availability_and_install ['langchain']\u001B[0m\n", - "\u001B[32m2023-12-13 11:30:37.341\u001B[0m | \u001B[1mINFO \u001B[0m | \u001B[36mpyrecdp.core.import_utils\u001B[0m:\u001B[36mcheck_availability_and_install\u001B[0m:\u001B[36m45\u001B[0m - \u001B[1mcheck_availability_and_install ['unstructured']\u001B[0m\n", - "\u001B[32m2023-12-13 11:30:37.344\u001B[0m | \u001B[1mINFO \u001B[0m | \u001B[36mpyrecdp.core.import_utils\u001B[0m:\u001B[36mcheck_availability_and_install\u001B[0m:\u001B[36m45\u001B[0m - \u001B[1mcheck_availability_and_install ['ftfy', 'selectolax']\u001B[0m\n", - "\u001B[32m2023-12-13 11:30:37.347\u001B[0m | \u001B[1mINFO \u001B[0m | \u001B[36mpyrecdp.core.import_utils\u001B[0m:\u001B[36mcheck_availability_and_install\u001B[0m:\u001B[36m45\u001B[0m - \u001B[1mcheck_availability_and_install ['langchain']\u001B[0m\n", + "\u001b[32m2023-12-19 16:55:34.829\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['bs4', 'langchain']\u001b[0m\n", + "\u001b[32m2023-12-19 16:55:34.833\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['ftfy', 'selectolax']\u001b[0m\n", + "\u001b[32m2023-12-19 16:55:34.836\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['langchain']\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[32m2023-12-19 16:55:34.894\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['bs4', 'langchain']\u001b[0m\n", + "\u001b[32m2023-12-19 16:55:34.897\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['ftfy', 'selectolax']\u001b[0m\n", + "\u001b[32m2023-12-19 16:55:34.900\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['langchain']\u001b[0m\n", "init ray\n", - "execute with ray started ...\n", - "\u001B[32m2023-12-13 11:30:50.901\u001B[0m | \u001B[1mINFO \u001B[0m | \u001B[36mpyrecdp.core.import_utils\u001B[0m:\u001B[36mcheck_availability_and_install\u001B[0m:\u001B[36m45\u001B[0m - \u001B[1mcheck_availability_and_install ['farm-haystack', 'farm-haystack[elasticsearch7]']\u001B[0m\n" + "execute with ray started ...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.\n", - "Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.\n", - "To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.\n" + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:55:38,001 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 456495104; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:55:48,016 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 456441856; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:55:58,028 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 456417280; capacity: 422146228224. Object creation will fail if spilling is required.\n" ] }, { - "data": { - "text/html": [ - "
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n",
-       "
\n" - ], - "text/plain": [ - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001B[0m\u001B[33m\n", - "\u001B[0m" - ] - }, - "metadata": {}, - "output_type": "display_data" + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[32m2023-12-19 16:56:00.001\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['farm-haystack', 'farm-haystack[elasticsearch7]']\u001b[0m\n" + ] }, { "name": "stderr", @@ -132,8 +130,8 @@ "\n" ], "text/plain": [ - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001B[0m\u001B[33m\n", - "\u001B[0m" + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n", + "\u001b[0m" ] }, "metadata": {}, @@ -143,22 +141,21 @@ "name": "stderr", "output_type": "stream", "text": [ - "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", - " warnings.warn(message, category=ElasticsearchWarning)\n", - "2023-12-13 11:31:01,645\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Map()->FlatMap()->Filter()->FlatMap()]\n", - "2023-12-13 11:31:01,649\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", - "2023-12-13 11:31:01,652\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:56:08,042 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 456359936; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.\n", + "Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.\n", + "To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.\n" ] }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "52053bfce56a451a85c7811a8a6a2e87", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n",
+       "
\n" + ], "text/plain": [ - "Running 0: 0%| | 0/4 [00:00 TaskPoolMapOperator[Map()->FlatMap()->Filter()->FlatMap()->Write]\n", - "2023-12-13 11:31:02,273\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", - "2023-12-13 11:31:02,274\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:56:18,054 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 455839744; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "2023-12-19 16:56:21,436\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Map()->FlatMap()->Filter()->FlatMap()->MapBatches()]\n", + "2023-12-19 16:56:21,438\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-19 16:56:21,439\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "a70f455b10144dce9da455ff0ebc90cb", + "model_id": "aaed7a3fc37b404198626b3247b75137", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "Running 0: 0%| | 0/4 [00:00 TaskPoolMapOperator[Map()->FlatMap()->Filter()->FlatMap()]\n", - "2023-12-13 11:31:02,686\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", - "2023-12-13 11:31:02,688\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "2023-12-19 16:56:26,361\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Map()->FlatMap()->Filter()->FlatMap()]\n", + "2023-12-19 16:56:26,363\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-19 16:56:26,366\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "98e0f8516b1f4bd7a819a98ae7d99ec3", + "model_id": "a9b523831f6c4c5fa0d23db8e5fb3f7b", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "Running 0: 0%| | 0/4 [00:00\n", " 0\n", " Welcome to cnvrg.io cnvrg.io is a machine lear...\n", - " {'source': 'https://app.cnvrg.io/docs/'}\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 1\n", " Dataset Use Datasets to manage data with versi...\n", - " {'source': 'https://app.cnvrg.io/docs/'}\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 2\n", " Use Papers to consolidate comparison across ex...\n", - " {'source': 'https://app.cnvrg.io/docs/'}\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 3\n", - " Easily update your running serving to keep it ...\n", - " {'source': 'https://app.cnvrg.io/docs/'}\n", + " Resource Management With our Dashboard, get a ...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 4\n", - " Tutorials and Examples To help you get started...\n", - " {'source': 'https://app.cnvrg.io/docs/collecti...\n", + " AI Library Continual learning and building mac...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " ...\n", @@ -274,71 +274,78 @@ " ...\n", " \n", " \n", - " 92\n", - " For example, gputype=v100 .To specify several,...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " 900\n", + " Delete a registry To delete a registry from th...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", - " 93\n", - " For example, gputype=v100 .To specify several,...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " 901\n", + " Create an image To create an image, use the fo...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", - " 94\n", - " For example, gputype=v100 .To specify several,...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " 902\n", + " Get an image To retrieve information about an ...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", - " 95\n", - " options are: cnvrg, dockerhub, gcr, acr, ecr, ...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " 903\n", + " when reffering to an image built from dockerfi...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", - " 96\n", - " options are: cnvrg, dockerhub, gcr, acr, ecr, ...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " 904\n", + " Delete an image To delete an image using its n...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", "\n", - "

97 rows × 2 columns

\n", + "

905 rows × 2 columns

\n", "" ], "text/plain": [ - " text \\\n", - "0 Welcome to cnvrg.io cnvrg.io is a machine lear... \n", - "1 Dataset Use Datasets to manage data with versi... \n", - "2 Use Papers to consolidate comparison across ex... \n", - "3 Easily update your running serving to keep it ... \n", - "4 Tutorials and Examples To help you get started... \n", - ".. ... \n", - "92 For example, gputype=v100 .To specify several,... \n", - "93 For example, gputype=v100 .To specify several,... \n", - "94 For example, gputype=v100 .To specify several,... \n", - "95 options are: cnvrg, dockerhub, gcr, acr, ecr, ... \n", - "96 options are: cnvrg, dockerhub, gcr, acr, ecr, ... \n", + " text \\\n", + "0 Welcome to cnvrg.io cnvrg.io is a machine lear... \n", + "1 Dataset Use Datasets to manage data with versi... \n", + "2 Use Papers to consolidate comparison across ex... \n", + "3 Resource Management With our Dashboard, get a ... \n", + "4 AI Library Continual learning and building mac... \n", + ".. ... \n", + "900 Delete a registry To delete a registry from th... \n", + "901 Create an image To create an image, use the fo... \n", + "902 Get an image To retrieve information about an ... \n", + "903 when reffering to an image built from dockerfi... \n", + "904 Delete an image To delete an image using its n... \n", "\n", - " metadata \n", - "0 {'source': 'https://app.cnvrg.io/docs/'} \n", - "1 {'source': 'https://app.cnvrg.io/docs/'} \n", - "2 {'source': 'https://app.cnvrg.io/docs/'} \n", - "3 {'source': 'https://app.cnvrg.io/docs/'} \n", - "4 {'source': 'https://app.cnvrg.io/docs/collecti... \n", - ".. ... \n", - "92 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "93 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "94 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "95 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "96 {'source': 'https://app.cnvrg.io/docs/core_con... \n", + " metadata \n", + "0 {'description': 'Documentation website for cnv... \n", + "1 {'description': 'Documentation website for cnv... \n", + "2 {'description': 'Documentation website for cnv... \n", + "3 {'description': 'Documentation website for cnv... \n", + "4 {'description': 'Documentation website for cnv... \n", + ".. ... \n", + "900 {'description': 'Documentation website for cnv... \n", + "901 {'description': 'Documentation website for cnv... \n", + "902 {'description': 'Documentation website for cnv... \n", + "903 {'description': 'Documentation website for cnv... \n", + "904 {'description': 'Documentation website for cnv... \n", "\n", - "[97 rows x 2 columns]" + "[905 rows x 2 columns]" ] }, "metadata": {}, "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:56:28,069 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 454561792; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] } ], "source": [ - "from pyrecdp.primitives.operations import DocumentLoader,RAGTextFix,CustomerDocumentSplit,TextCustomerFilter,DocumentIngestion\n", + "from pyrecdp.primitives.operations import RecursiveUrlLoader,RAGTextFix,CustomerDocumentSplit,TextCustomerFilter,DocumentIngestion\n", "from pyrecdp.LLM import TextPipeline\n", "import os\n", "\n", @@ -379,7 +386,7 @@ "\n", "pipeline = TextPipeline()\n", "ops = [\n", - " DocumentLoader(loader='UnstructuredURLLoader', loader_args={'urls': urls}, requirements=['unstructured']),\n", + " RecursiveUrlLoader(urls, max_depth=2),\n", " RAGTextFix(str_to_replace={'\\n###': '', '\\n##': '', '\\n#': ''}, remove_extra_whitespace=True),\n", " CustomerDocumentSplit(func=lambda text: text.split('# ')[1:]),\n", " TextCustomerFilter(custom_filter),\n", diff --git a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline_step_by_step.ipynb b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline_step_by_step.ipynb index 95e9e904..c947a913 100644 --- a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline_step_by_step.ipynb +++ b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline_step_by_step.ipynb @@ -71,21 +71,21 @@ " warnings.warn(\"Setuptools is replacing distutils.\")\n", "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/pyspark/pandas/__init__.py:50: UserWarning: 'PYARROW_IGNORE_TIMEZONE' environment variable was not set. It is required to set this environment variable to '1' in both driver and executor sides if you use pyarrow>=2.0.0. pandas-on-Spark will set it for you but it does not work if there is a Spark context already launched.\n", " warnings.warn(\n", - "\u001B[32m2023-12-13 11:22:36.363\u001B[0m | \u001B[1mINFO \u001B[0m | \u001B[36mpyrecdp.core.import_utils\u001B[0m:\u001B[36mcheck_availability_and_install\u001B[0m:\u001B[36m50\u001B[0m - \u001B[1mcheck_availability_and_install emoji==2.2.0\u001B[0m\n" + "\u001b[32m2023-12-19 16:28:23.864\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install emoji==2.2.0\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "\u001B[32m2023-12-13 11:22:36.397\u001B[0m | \u001B[1mINFO \u001B[0m | \u001B[36mpyrecdp.core.import_utils\u001B[0m:\u001B[36mcheck_availability_and_install\u001B[0m:\u001B[36m45\u001B[0m - \u001B[1mcheck_availability_and_install ['unstructured']\u001B[0m\n" + "\u001b[32m2023-12-19 16:28:23.958\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['bs4', 'langchain']\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "2023-12-13 11:22:58,390\tINFO worker.py:1642 -- Started a local Ray instance.\n" + "2023-12-19 16:28:50,843\tINFO worker.py:1642 -- Started a local Ray instance.\n" ] }, { @@ -116,44 +116,163 @@ " \n", " \n", " 0\n", - " # Welcome to cnvrg.io\\n\\ncnvrg.io is a machine...\n", - " {'source': 'https://app.cnvrg.io/docs/'}\n", + " \\n\\n\\n\\n\\nWelcome to cnvrg.io | cnvrg.io docs\\...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 1\n", - " # cnvrg SDK V2\\n\\n# Getting Started\\n\\nThe cnv...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " \\n\\n\\n\\n\\nProjects | cnvrg.io docs\\n\\n\\n\\n\\n\\n...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 2\n", - " # cnvrgv2 CLI\\n\\nAs data scientists, we use th...\n", - " {'source': 'https://app.cnvrg.io/docs/cli_v2/c...\n", + " \\n\\n\\n\\n\\nExperiments | cnvrg.io docs\\n\\n\\n\\n\\...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 3\n", - " # Tutorials and Examples\\n\\nTo help you get st...\n", - " {'source': 'https://app.cnvrg.io/docs/collecti...\n", + " \\n\\n\\n\\n\\nServing | cnvrg.io docs\\n\\n\\n\\n\\n\\n\\...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 4\n", + " \\n\\n\\n\\n\\nContainers | cnvrg.io docs\\n\\n\\n\\n\\n...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 5\n", + " \\n\\n\\n\\n\\nOrganization, Account, and Team Sett...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 6\n", + " \\n\\n\\n\\n\\nWorkspaces | cnvrg.io docs\\n\\n\\n\\n\\n...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 7\n", + " \\n\\n\\n\\n\\nCompute | cnvrg.io docs\\n\\n\\n\\n\\n\\n\\...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 8\n", + " \\n\\n\\n\\n\\nTutorials and Examples | cnvrg.io do...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 9\n", + " \\n\\n\\n\\n\\nRelease Notes | cnvrg.io docs\\n\\n\\n\\...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 10\n", + " \\n\\n\\n\\n\\nVideos | cnvrg.io docs\\n\\n\\n\\n\\n\\n\\n...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 11\n", + " \\n\\n\\n\\n\\nDistributed Jobs | cnvrg.io docs\\n\\n...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 12\n", + " \\n\\n\\n\\n\\nFlows | cnvrg.io docs\\n\\n\\n\\n\\n\\n\\n\\...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 13\n", + " \\n\\n\\n\\n\\nDashboard | cnvrg.io docs\\n\\n\\n\\n\\n\\...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 14\n", + " \\n\\n\\n\\n\\nAI Library | cnvrg.io docs\\n\\n\\n\\n\\n...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 15\n", + " \\n\\n\\n\\n\\nApps | cnvrg.io docs\\n\\n\\n\\n\\n\\n\\n\\n...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 16\n", + " \\n\\n\\n\\n\\nDatasets | cnvrg.io docs\\n\\n\\n\\n\\n\\n...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 17\n", + " \\n\\n\\n\\n\\ncnvrg SDK V2 | cnvrg.io docs\\n\\n\\n\\n...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 18\n", + " \\n\\n\\n\\n\\ncnvrgv2 CLI | cnvrg.io docs\\n\\n\\n\\n\\...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 19\n", + " \\n\\n\\n\\n\\nTutorials and Examples | cnvrg.io do...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", "\n", "" ], "text/plain": [ - " text \\\n", - "0 # Welcome to cnvrg.io\\n\\ncnvrg.io is a machine... \n", - "1 # cnvrg SDK V2\\n\\n# Getting Started\\n\\nThe cnv... \n", - "2 # cnvrgv2 CLI\\n\\nAs data scientists, we use th... \n", - "3 # Tutorials and Examples\\n\\nTo help you get st... \n", + " text \\\n", + "0 \\n\\n\\n\\n\\nWelcome to cnvrg.io | cnvrg.io docs\\... \n", + "1 \\n\\n\\n\\n\\nProjects | cnvrg.io docs\\n\\n\\n\\n\\n\\n... \n", + "2 \\n\\n\\n\\n\\nExperiments | cnvrg.io docs\\n\\n\\n\\n\\... \n", + "3 \\n\\n\\n\\n\\nServing | cnvrg.io docs\\n\\n\\n\\n\\n\\n\\... \n", + "4 \\n\\n\\n\\n\\nContainers | cnvrg.io docs\\n\\n\\n\\n\\n... \n", + "5 \\n\\n\\n\\n\\nOrganization, Account, and Team Sett... \n", + "6 \\n\\n\\n\\n\\nWorkspaces | cnvrg.io docs\\n\\n\\n\\n\\n... \n", + "7 \\n\\n\\n\\n\\nCompute | cnvrg.io docs\\n\\n\\n\\n\\n\\n\\... \n", + "8 \\n\\n\\n\\n\\nTutorials and Examples | cnvrg.io do... \n", + "9 \\n\\n\\n\\n\\nRelease Notes | cnvrg.io docs\\n\\n\\n\\... \n", + "10 \\n\\n\\n\\n\\nVideos | cnvrg.io docs\\n\\n\\n\\n\\n\\n\\n... \n", + "11 \\n\\n\\n\\n\\nDistributed Jobs | cnvrg.io docs\\n\\n... \n", + "12 \\n\\n\\n\\n\\nFlows | cnvrg.io docs\\n\\n\\n\\n\\n\\n\\n\\... \n", + "13 \\n\\n\\n\\n\\nDashboard | cnvrg.io docs\\n\\n\\n\\n\\n\\... \n", + "14 \\n\\n\\n\\n\\nAI Library | cnvrg.io docs\\n\\n\\n\\n\\n... \n", + "15 \\n\\n\\n\\n\\nApps | cnvrg.io docs\\n\\n\\n\\n\\n\\n\\n\\n... \n", + "16 \\n\\n\\n\\n\\nDatasets | cnvrg.io docs\\n\\n\\n\\n\\n\\n... \n", + "17 \\n\\n\\n\\n\\ncnvrg SDK V2 | cnvrg.io docs\\n\\n\\n\\n... \n", + "18 \\n\\n\\n\\n\\ncnvrgv2 CLI | cnvrg.io docs\\n\\n\\n\\n\\... \n", + "19 \\n\\n\\n\\n\\nTutorials and Examples | cnvrg.io do... \n", "\n", - " metadata \n", - "0 {'source': 'https://app.cnvrg.io/docs/'} \n", - "1 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "2 {'source': 'https://app.cnvrg.io/docs/cli_v2/c... \n", - "3 {'source': 'https://app.cnvrg.io/docs/collecti... " + " metadata \n", + "0 {'description': 'Documentation website for cnv... \n", + "1 {'description': 'Documentation website for cnv... \n", + "2 {'description': 'Documentation website for cnv... \n", + "3 {'description': 'Documentation website for cnv... \n", + "4 {'description': 'Documentation website for cnv... \n", + "5 {'description': 'Documentation website for cnv... \n", + "6 {'description': 'Documentation website for cnv... \n", + "7 {'description': 'Documentation website for cnv... \n", + "8 {'description': 'Documentation website for cnv... \n", + "9 {'description': 'Documentation website for cnv... \n", + "10 {'description': 'Documentation website for cnv... \n", + "11 {'description': 'Documentation website for cnv... \n", + "12 {'description': 'Documentation website for cnv... \n", + "13 {'description': 'Documentation website for cnv... \n", + "14 {'description': 'Documentation website for cnv... \n", + "15 {'description': 'Documentation website for cnv... \n", + "16 {'description': 'Documentation website for cnv... \n", + "17 {'description': 'Documentation website for cnv... \n", + "18 {'description': 'Documentation website for cnv... \n", + "19 {'description': 'Documentation website for cnv... " ] }, "metadata": {}, "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:28:59,723 E 184744 184762] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-28-47_846155_183468 is over 95% full, available space: 482947072; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] } ], "source": [ @@ -162,8 +281,8 @@ " 'https://app.cnvrg.io/docs/cli_v2/cnvrgv2_cli.html',\n", " 'https://app.cnvrg.io/docs/collections/tutorials.html']\n", "\n", - "from pyrecdp.primitives.operations import DocumentLoader\n", - "url_loader = DocumentLoader(loader='UnstructuredURLLoader', loader_args={'urls': urls}, requirements=['unstructured'])\n", + "from pyrecdp.primitives.operations import RecursiveUrlLoader\n", + "url_loader = RecursiveUrlLoader(urls, max_depth=2)\n", "\n", "ds = url_loader.process_rayds()\n", "display(ds.to_pandas())" @@ -185,36 +304,36 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\u001B[32m2023-12-13 11:23:32.657\u001B[0m | \u001B[1mINFO \u001B[0m | \u001B[36mpyrecdp.core.import_utils\u001B[0m:\u001B[36mcheck_availability_and_install\u001B[0m:\u001B[36m45\u001B[0m - \u001B[1mcheck_availability_and_install ['ftfy', 'selectolax']\u001B[0m\n", - "\u001B[32m2023-12-13 11:23:32.711\u001B[0m | \u001B[1mINFO \u001B[0m | \u001B[36mpyrecdp.core.import_utils\u001B[0m:\u001B[36mcheck_availability_and_install\u001B[0m:\u001B[36m50\u001B[0m - \u001B[1mcheck_availability_and_install nltk\u001B[0m\n", - "\u001B[32m2023-12-13 11:23:32.712\u001B[0m | \u001B[1mINFO \u001B[0m | \u001B[36mpyrecdp.core.model_utils\u001B[0m:\u001B[36mprepare_nltk_model\u001B[0m:\u001B[36m164\u001B[0m - \u001B[1mLoading nltk punkt split model...\u001B[0m\n" + "\u001b[32m2023-12-19 15:43:27.897\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['ftfy', 'selectolax']\u001b[0m\n", + "\u001b[32m2023-12-19 15:43:27.954\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install nltk\u001b[0m\n", + "\u001b[32m2023-12-19 15:43:28.263\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.model_utils\u001b[0m:\u001b[36mprepare_nltk_model\u001b[0m:\u001b[36m164\u001b[0m - \u001b[1mLoading nltk punkt split model...\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "2023-12-13 11:23:32,723\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Map()]\n", - "2023-12-13 11:23:32,724\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", - "2023-12-13 11:23:32,726\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + "2023-12-19 15:43:28,273\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Map()]\n", + "2023-12-19 15:43:28,274\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-19 15:43:28,276\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "4ea7514a2fd749ac8f64b49170e9d7b1", + "model_id": "a9fe241413bc403cb2e169ff5b7a3305", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "Running 0: 0%| | 0/4 [00:00) pid=1791147)\u001B[0m /root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", - "\u001B[2m\u001B[36m(Map() pid=1791147)\u001B[0m warnings.warn(\"Setuptools is replacing distutils.\")\n", - "\u001B[2m\u001B[36m(Map() pid=1791194)\u001B[0m 2023-12-13 11:23:34.531 | INFO | pyrecdp.core.import_utils:check_availability_and_install:50 - check_availability_and_install emoji==2.2.0\n" + "\u001b[2m\u001b[36m(Map() pid=109694)\u001b[0m /root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + "\u001b[2m\u001b[36m(Map() pid=109694)\u001b[0m warnings.warn(\"Setuptools is replacing distutils.\")\n", + "\u001b[2m\u001b[36m(Map() pid=109694)\u001b[0m 2023-12-19 15:43:30.292 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n" ] }, { @@ -257,40 +376,152 @@ " \n", " \n", " 0\n", - " # cnvrg SDK V2 Getting Started The cnvrg SDK w...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " Flows | cnvrg.io docs cnvrg.io docs Tutorials...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 1\n", - " # cnvrgv2 CLI As data scientists, we use the t...\n", - " {'source': 'https://app.cnvrg.io/docs/cli_v2/c...\n", + " Organization, Account, and Team Settings | cn...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 2\n", - " # Tutorials and Examples To help you get start...\n", - " {'source': 'https://app.cnvrg.io/docs/collecti...\n", + " Experiments | cnvrg.io docs cnvrg.io docs Tut...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 3\n", - " # Welcome to cnvrg.io cnvrg.io is a machine le...\n", - " {'source': 'https://app.cnvrg.io/docs/'}\n", + " Tutorials and Examples | cnvrg.io docs cnvrg....\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 4\n", + " Datasets | cnvrg.io docs cnvrg.io docs Tutori...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 5\n", + " Distributed Jobs | cnvrg.io docs cnvrg.io doc...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 6\n", + " cnvrgv2 CLI | cnvrg.io docs cnvrg.io docs Tut...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 7\n", + " Videos | cnvrg.io docs cnvrg.io docs Tutorial...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 8\n", + " Workspaces | cnvrg.io docs cnvrg.io docs Tuto...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 9\n", + " Projects | cnvrg.io docs cnvrg.io docs Tutori...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 10\n", + " Dashboard | cnvrg.io docs cnvrg.io docs Tutor...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 11\n", + " cnvrg SDK V2 | cnvrg.io docs cnvrg.io docs Tu...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 12\n", + " Welcome to cnvrg.io | cnvrg.io docs cnvrg.io ...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 13\n", + " Apps | cnvrg.io docs cnvrg.io docs Tutorials ...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 14\n", + " Serving | cnvrg.io docs cnvrg.io docs Tutoria...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 15\n", + " AI Library | cnvrg.io docs cnvrg.io docs Tuto...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 16\n", + " Release Notes | cnvrg.io docs cnvrg.io docs T...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 17\n", + " Containers | cnvrg.io docs cnvrg.io docs Tuto...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 18\n", + " Compute | cnvrg.io docs cnvrg.io docs Tutoria...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 19\n", + " Tutorials and Examples | cnvrg.io docs cnvrg....\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", "\n", "" ], "text/plain": [ - " text \\\n", - "0 # cnvrg SDK V2 Getting Started The cnvrg SDK w... \n", - "1 # cnvrgv2 CLI As data scientists, we use the t... \n", - "2 # Tutorials and Examples To help you get start... \n", - "3 # Welcome to cnvrg.io cnvrg.io is a machine le... \n", + " text \\\n", + "0 Flows | cnvrg.io docs cnvrg.io docs Tutorials... \n", + "1 Organization, Account, and Team Settings | cn... \n", + "2 Experiments | cnvrg.io docs cnvrg.io docs Tut... \n", + "3 Tutorials and Examples | cnvrg.io docs cnvrg.... \n", + "4 Datasets | cnvrg.io docs cnvrg.io docs Tutori... \n", + "5 Distributed Jobs | cnvrg.io docs cnvrg.io doc... \n", + "6 cnvrgv2 CLI | cnvrg.io docs cnvrg.io docs Tut... \n", + "7 Videos | cnvrg.io docs cnvrg.io docs Tutorial... \n", + "8 Workspaces | cnvrg.io docs cnvrg.io docs Tuto... \n", + "9 Projects | cnvrg.io docs cnvrg.io docs Tutori... \n", + "10 Dashboard | cnvrg.io docs cnvrg.io docs Tutor... \n", + "11 cnvrg SDK V2 | cnvrg.io docs cnvrg.io docs Tu... \n", + "12 Welcome to cnvrg.io | cnvrg.io docs cnvrg.io ... \n", + "13 Apps | cnvrg.io docs cnvrg.io docs Tutorials ... \n", + "14 Serving | cnvrg.io docs cnvrg.io docs Tutoria... \n", + "15 AI Library | cnvrg.io docs cnvrg.io docs Tuto... \n", + "16 Release Notes | cnvrg.io docs cnvrg.io docs T... \n", + "17 Containers | cnvrg.io docs cnvrg.io docs Tuto... \n", + "18 Compute | cnvrg.io docs cnvrg.io docs Tutoria... \n", + "19 Tutorials and Examples | cnvrg.io docs cnvrg.... \n", "\n", - " metadata \n", - "0 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "1 {'source': 'https://app.cnvrg.io/docs/cli_v2/c... \n", - "2 {'source': 'https://app.cnvrg.io/docs/collecti... \n", - "3 {'source': 'https://app.cnvrg.io/docs/'} " + " metadata \n", + "0 {'description': 'Documentation website for cnv... \n", + "1 {'description': 'Documentation website for cnv... \n", + "2 {'description': 'Documentation website for cnv... \n", + "3 {'description': 'Documentation website for cnv... \n", + "4 {'description': 'Documentation website for cnv... \n", + "5 {'description': 'Documentation website for cnv... \n", + "6 {'description': 'Documentation website for cnv... \n", + "7 {'description': 'Documentation website for cnv... \n", + "8 {'description': 'Documentation website for cnv... \n", + "9 {'description': 'Documentation website for cnv... \n", + "10 {'description': 'Documentation website for cnv... \n", + "11 {'description': 'Documentation website for cnv... \n", + "12 {'description': 'Documentation website for cnv... \n", + "13 {'description': 'Documentation website for cnv... \n", + "14 {'description': 'Documentation website for cnv... \n", + "15 {'description': 'Documentation website for cnv... \n", + "16 {'description': 'Documentation website for cnv... \n", + "17 {'description': 'Documentation website for cnv... \n", + "18 {'description': 'Documentation website for cnv... \n", + "19 {'description': 'Documentation website for cnv... " ] }, "metadata": {}, @@ -313,27 +544,27 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "2023-12-13 11:23:37,686\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Map()->FlatMap()]\n", - "2023-12-13 11:23:37,688\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", - "2023-12-13 11:23:37,689\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + "2023-12-19 15:43:33,682\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Map()->FlatMap()]\n", + "2023-12-19 15:43:33,683\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-19 15:43:33,684\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "00ad26cc09e54793a2a98af417fecbe2", + "model_id": "1d0c25ef14a845cbaedd7683b1a8aa12", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "Running 0: 0%| | 0/4 [00:00\n", " 0\n", " Welcome to cnvrg.io cnvrg.io is a machine lear...\n", - " {'source': 'https://app.cnvrg.io/docs/'}\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 1\n", - " cnvrgv2 CLI As data scientists, we use the ter...\n", - " {'source': 'https://app.cnvrg.io/docs/cli_v2/c...\n", + " Resource Management With our Dashboard, get a ...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 2\n", - " Tutorials and Examples To help you get started...\n", - " {'source': 'https://app.cnvrg.io/docs/collecti...\n", + " Apps cnvrg is a full-stack platform, designed ...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 3\n", - " cnvrg SDK V2 Getting Started The cnvrg SDK was...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " R Shiny Shiny is an R package that simplifies ...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 4\n", - " An array of numerical values values: [0.1, 0.0...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " Use R Shiny Complete the following steps to se...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", - " 5\n", - " An array of string values values: [\"linear\", \"...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " ...\n", + " ...\n", + " ...\n", " \n", " \n", - " 6\n", - " inclusive max: 20\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " 828\n", + " Tutorials and Examples To help you get started...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", - " 7\n", - " not inclusive scale: \"linear\" steps: 2\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " 829\n", + " Example Projects Build and Deploy an IMDB NLP ...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", - " 8\n", - " The number of linear steps to produce. \"\"\" e =...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " 830\n", + " Workspaces, Experiments and IDEs Run an Experi...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 831\n", + " Flows and Serving Processing your Dataset with...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 832\n", + " Other Setup Slack Integration for Experiments ...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", "\n", + "

833 rows × 2 columns

\n", "" ], "text/plain": [ - " text \\\n", - "0 Welcome to cnvrg.io cnvrg.io is a machine lear... \n", - "1 cnvrgv2 CLI As data scientists, we use the ter... \n", - "2 Tutorials and Examples To help you get started... \n", - "3 cnvrg SDK V2 Getting Started The cnvrg SDK was... \n", - "4 An array of numerical values values: [0.1, 0.0... \n", - "5 An array of string values values: [\"linear\", \"... \n", - "6 inclusive max: 20 \n", - "7 not inclusive scale: \"linear\" steps: 2 \n", - "8 The number of linear steps to produce. \"\"\" e =... \n", + " text \\\n", + "0 Welcome to cnvrg.io cnvrg.io is a machine lear... \n", + "1 Resource Management With our Dashboard, get a ... \n", + "2 Apps cnvrg is a full-stack platform, designed ... \n", + "3 R Shiny Shiny is an R package that simplifies ... \n", + "4 Use R Shiny Complete the following steps to se... \n", + ".. ... \n", + "828 Tutorials and Examples To help you get started... \n", + "829 Example Projects Build and Deploy an IMDB NLP ... \n", + "830 Workspaces, Experiments and IDEs Run an Experi... \n", + "831 Flows and Serving Processing your Dataset with... \n", + "832 Other Setup Slack Integration for Experiments ... \n", "\n", - " metadata \n", - "0 {'source': 'https://app.cnvrg.io/docs/'} \n", - "1 {'source': 'https://app.cnvrg.io/docs/cli_v2/c... \n", - "2 {'source': 'https://app.cnvrg.io/docs/collecti... \n", - "3 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "4 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "5 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "6 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "7 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "8 {'source': 'https://app.cnvrg.io/docs/core_con... " + " metadata \n", + "0 {'description': 'Documentation website for cnv... \n", + "1 {'description': 'Documentation website for cnv... \n", + "2 {'description': 'Documentation website for cnv... \n", + "3 {'description': 'Documentation website for cnv... \n", + "4 {'description': 'Documentation website for cnv... \n", + ".. ... \n", + "828 {'description': 'Documentation website for cnv... \n", + "829 {'description': 'Documentation website for cnv... \n", + "830 {'description': 'Documentation website for cnv... \n", + "831 {'description': 'Documentation website for cnv... \n", + "832 {'description': 'Documentation website for cnv... \n", + "\n", + "[833 rows x 2 columns]" ] }, "metadata": {}, "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:43:34,260 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 511860736; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] } ], "source": [ @@ -458,27 +713,27 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "2023-12-13 11:23:41,022\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Map()->FlatMap()->Filter()]\n", - "2023-12-13 11:23:41,023\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", - "2023-12-13 11:23:41,025\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + "2023-12-19 15:43:36,846\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Map()->FlatMap()->Filter()]\n", + "2023-12-19 15:43:36,847\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-19 15:43:36,848\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "27f9e634c5a741faa4ec740b223deeb9", + "model_id": "9973f7e8dcf64a059f1539515d619ed9", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "Running 0: 0%| | 0/4 [00:00\n", " 0\n", " Welcome to cnvrg.io cnvrg.io is a machine lear...\n", - " {'source': 'https://app.cnvrg.io/docs/'}\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 1\n", - " cnvrgv2 CLI As data scientists, we use the ter...\n", - " {'source': 'https://app.cnvrg.io/docs/cli_v2/c...\n", + " Resource Management With our Dashboard, get a ...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 2\n", - " Tutorials and Examples To help you get started...\n", - " {'source': 'https://app.cnvrg.io/docs/collecti...\n", + " Apps cnvrg is a full-stack platform, designed ...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 3\n", - " cnvrg SDK V2 Getting Started The cnvrg SDK was...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " R Shiny Shiny is an R package that simplifies ...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 4\n", - " An array of numerical values values: [0.1, 0.0...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " Use R Shiny Complete the following steps to se...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", - " 5\n", - " An array of string values values: [\"linear\", \"...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " ...\n", + " ...\n", + " ...\n", " \n", " \n", - " 6\n", - " The number of linear steps to produce. \"\"\" e =...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " 570\n", + " Delete a registry To delete a registry from th...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 571\n", + " Create an image To create an image, use the fo...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 572\n", + " Get an image To retrieve information about an ...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 573\n", + " when reffering to an image built from dockerfi...\n", + " {'description': 'Documentation website for cnv...\n", + " \n", + " \n", + " 574\n", + " Delete an image To delete an image using its n...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", "\n", + "

575 rows × 2 columns

\n", "" ], "text/plain": [ - " text \\\n", - "0 Welcome to cnvrg.io cnvrg.io is a machine lear... \n", - "1 cnvrgv2 CLI As data scientists, we use the ter... \n", - "2 Tutorials and Examples To help you get started... \n", - "3 cnvrg SDK V2 Getting Started The cnvrg SDK was... \n", - "4 An array of numerical values values: [0.1, 0.0... \n", - "5 An array of string values values: [\"linear\", \"... \n", - "6 The number of linear steps to produce. \"\"\" e =... \n", + " text \\\n", + "0 Welcome to cnvrg.io cnvrg.io is a machine lear... \n", + "1 Resource Management With our Dashboard, get a ... \n", + "2 Apps cnvrg is a full-stack platform, designed ... \n", + "3 R Shiny Shiny is an R package that simplifies ... \n", + "4 Use R Shiny Complete the following steps to se... \n", + ".. ... \n", + "570 Delete a registry To delete a registry from th... \n", + "571 Create an image To create an image, use the fo... \n", + "572 Get an image To retrieve information about an ... \n", + "573 when reffering to an image built from dockerfi... \n", + "574 Delete an image To delete an image using its n... \n", "\n", - " metadata \n", - "0 {'source': 'https://app.cnvrg.io/docs/'} \n", - "1 {'source': 'https://app.cnvrg.io/docs/cli_v2/c... \n", - "2 {'source': 'https://app.cnvrg.io/docs/collecti... \n", - "3 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "4 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "5 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "6 {'source': 'https://app.cnvrg.io/docs/core_con... " + " metadata \n", + "0 {'description': 'Documentation website for cnv... \n", + "1 {'description': 'Documentation website for cnv... \n", + "2 {'description': 'Documentation website for cnv... \n", + "3 {'description': 'Documentation website for cnv... \n", + "4 {'description': 'Documentation website for cnv... \n", + ".. ... \n", + "570 {'description': 'Documentation website for cnv... \n", + "571 {'description': 'Documentation website for cnv... \n", + "572 {'description': 'Documentation website for cnv... \n", + "573 {'description': 'Documentation website for cnv... \n", + "574 {'description': 'Documentation website for cnv... \n", + "\n", + "[575 rows x 2 columns]" ] }, "metadata": {}, @@ -598,27 +884,27 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "2023-12-13 11:23:46,037\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Map()->FlatMap()->Filter()->FlatMap()]\n", - "2023-12-13 11:23:46,039\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", - "2023-12-13 11:23:46,040\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + "2023-12-19 15:43:40,101\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Map()->FlatMap()->Filter()->FlatMap()]\n", + "2023-12-19 15:43:40,102\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-19 15:43:40,103\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "0f66bf68a4dd41529abd60577f2fda09", + "model_id": "aae393a41116471eb133d72df94c6815", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "Running 0: 0%| | 0/4 [00:00\n", " 0\n", " Welcome to cnvrg.io cnvrg.io is a machine lear...\n", - " {'source': 'https://app.cnvrg.io/docs/'}\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 1\n", " Dataset Use Datasets to manage data with versi...\n", - " {'source': 'https://app.cnvrg.io/docs/'}\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 2\n", " Use Papers to consolidate comparison across ex...\n", - " {'source': 'https://app.cnvrg.io/docs/'}\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 3\n", - " Easily update your running serving to keep it ...\n", - " {'source': 'https://app.cnvrg.io/docs/'}\n", + " Resource Management With our Dashboard, get a ...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " 4\n", - " Tutorials and Examples To help you get started...\n", - " {'source': 'https://app.cnvrg.io/docs/collecti...\n", + " Apps cnvrg is a full-stack platform, designed ...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", " ...\n", @@ -681,67 +967,74 @@ " ...\n", " \n", " \n", - " 92\n", - " For example, gputype=v100 .To specify several,...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " 900\n", + " Delete a registry To delete a registry from th...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", - " 93\n", - " For example, gputype=v100 .To specify several,...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " 901\n", + " Create an image To create an image, use the fo...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", - " 94\n", - " For example, gputype=v100 .To specify several,...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " 902\n", + " Get an image To retrieve information about an ...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", - " 95\n", - " options are: cnvrg, dockerhub, gcr, acr, ecr, ...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " 903\n", + " when reffering to an image built from dockerfi...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", - " 96\n", - " options are: cnvrg, dockerhub, gcr, acr, ecr, ...\n", - " {'source': 'https://app.cnvrg.io/docs/core_con...\n", + " 904\n", + " Delete an image To delete an image using its n...\n", + " {'description': 'Documentation website for cnv...\n", " \n", " \n", "\n", - "

97 rows × 2 columns

\n", + "

905 rows × 2 columns

\n", "" ], "text/plain": [ - " text \\\n", - "0 Welcome to cnvrg.io cnvrg.io is a machine lear... \n", - "1 Dataset Use Datasets to manage data with versi... \n", - "2 Use Papers to consolidate comparison across ex... \n", - "3 Easily update your running serving to keep it ... \n", - "4 Tutorials and Examples To help you get started... \n", - ".. ... \n", - "92 For example, gputype=v100 .To specify several,... \n", - "93 For example, gputype=v100 .To specify several,... \n", - "94 For example, gputype=v100 .To specify several,... \n", - "95 options are: cnvrg, dockerhub, gcr, acr, ecr, ... \n", - "96 options are: cnvrg, dockerhub, gcr, acr, ecr, ... \n", + " text \\\n", + "0 Welcome to cnvrg.io cnvrg.io is a machine lear... \n", + "1 Dataset Use Datasets to manage data with versi... \n", + "2 Use Papers to consolidate comparison across ex... \n", + "3 Resource Management With our Dashboard, get a ... \n", + "4 Apps cnvrg is a full-stack platform, designed ... \n", + ".. ... \n", + "900 Delete a registry To delete a registry from th... \n", + "901 Create an image To create an image, use the fo... \n", + "902 Get an image To retrieve information about an ... \n", + "903 when reffering to an image built from dockerfi... \n", + "904 Delete an image To delete an image using its n... \n", "\n", - " metadata \n", - "0 {'source': 'https://app.cnvrg.io/docs/'} \n", - "1 {'source': 'https://app.cnvrg.io/docs/'} \n", - "2 {'source': 'https://app.cnvrg.io/docs/'} \n", - "3 {'source': 'https://app.cnvrg.io/docs/'} \n", - "4 {'source': 'https://app.cnvrg.io/docs/collecti... \n", - ".. ... \n", - "92 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "93 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "94 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "95 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "96 {'source': 'https://app.cnvrg.io/docs/core_con... \n", + " metadata \n", + "0 {'description': 'Documentation website for cnv... \n", + "1 {'description': 'Documentation website for cnv... \n", + "2 {'description': 'Documentation website for cnv... \n", + "3 {'description': 'Documentation website for cnv... \n", + "4 {'description': 'Documentation website for cnv... \n", + ".. ... \n", + "900 {'description': 'Documentation website for cnv... \n", + "901 {'description': 'Documentation website for cnv... \n", + "902 {'description': 'Documentation website for cnv... \n", + "903 {'description': 'Documentation website for cnv... \n", + "904 {'description': 'Documentation website for cnv... \n", "\n", - "[97 rows x 2 columns]" + "[905 rows x 2 columns]" ] }, "metadata": {}, "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:43:44,274 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 511811584; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] } ], "source": [ @@ -794,203 +1087,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Dec 08, 2023 1:47:14 PM sun.util.locale.provider.LocaleProviderAdapter \n", - "WARNING: COMPAT locale provider will be removed in a future release\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:14,874Z\", \"level\": \"INFO\", \"component\": \"o.e.n.Node\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"version[7.17.15], pid[7], build[default/docker/0b8ecfb4378335f4689c4223d1f1115f16bef3ba/2023-11-10T22:03:46.987399016Z], OS[Linux/5.15.0-79-generic/amd64], JVM[Oracle Corporation/OpenJDK 64-Bit Server VM/21.0.1/21.0.1+12-29]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:14,877Z\", \"level\": \"INFO\", \"component\": \"o.e.n.Node\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"JVM home [/usr/share/elasticsearch/jdk], using bundled JDK [true]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:14,878Z\", \"level\": \"INFO\", \"component\": \"o.e.n.Node\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"JVM arguments [-Xshare:auto, -Des.networkaddress.cache.ttl=60, -Des.networkaddress.cache.negative.ttl=10, -XX:+AlwaysPreTouch, -Xss1m, -Djava.awt.headless=true, -Dfile.encoding=UTF-8, -Djna.nosys=true, -XX:-OmitStackTraceInFastThrow, -XX:+ShowCodeDetailsInExceptionMessages, -Dio.netty.noUnsafe=true, -Dio.netty.noKeySetOptimization=true, -Dio.netty.recycler.maxCapacityPerThread=0, -Dio.netty.allocator.numDirectArenas=0, -Dlog4j.shutdownHookEnabled=false, -Dlog4j2.disable.jmx=true, -Dlog4j2.formatMsgNoLookups=true, -Djava.locale.providers=SPI,COMPAT, --add-opens=java.base/java.io=ALL-UNNAMED, -Djava.security.manager=allow, -XX:+UseG1GC, -Djava.io.tmpdir=/tmp/elasticsearch-9317727528719022261, -XX:+HeapDumpOnOutOfMemoryError, -XX:+ExitOnOutOfMemoryError, -XX:HeapDumpPath=data, -XX:ErrorFile=logs/hs_err_pid%p.log, -Xlog:gc*,gc+age=trace,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m, -Des.cgroups.hierarchy.override=/, -Xms31744m, -Xmx31744m, -XX:MaxDirectMemorySize=16642998272, -XX:InitiatingHeapOccupancyPercent=30, -XX:G1ReservePercent=25, -Des.path.home=/usr/share/elasticsearch, -Des.path.conf=/usr/share/elasticsearch/config, -Des.distribution.flavor=default, -Des.distribution.type=docker, -Des.bundled_jdk=true]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,777Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [aggs-matrix-stats]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,778Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [analysis-common]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,778Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [constant-keyword]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,778Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [frozen-indices]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,778Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [ingest-common]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,778Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [ingest-geoip]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,779Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [ingest-user-agent]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,779Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [kibana]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,779Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [lang-expression]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,779Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [lang-mustache]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,779Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [lang-painless]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,779Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [legacy-geo]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,780Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [mapper-extras]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,780Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [mapper-version]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,780Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [parent-join]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,780Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [percolator]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,780Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [rank-eval]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,780Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [reindex]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,780Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [repositories-metering-api]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,781Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [repository-encrypted]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,781Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [repository-url]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,781Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [runtime-fields-common]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,781Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [search-business-rules]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,781Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [searchable-snapshots]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,782Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [snapshot-repo-test-kit]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,782Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [spatial]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,782Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [transform]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,782Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [transport-netty4]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,782Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [unsigned-long]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,782Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [vector-tile]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,783Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [vectors]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,783Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [wildcard]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,783Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-aggregate-metric]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,783Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-analytics]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,783Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-async]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,783Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-async-search]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,783Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-autoscaling]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,784Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-ccr]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,784Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-core]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,784Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-data-streams]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,784Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-deprecation]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,784Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-enrich]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,784Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-eql]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,784Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-fleet]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,785Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-graph]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,785Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-identity-provider]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,785Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-ilm]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,785Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-logstash]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,785Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-ml]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,785Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-monitoring]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,785Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-ql]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,786Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-rollup]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,786Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-security]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,786Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-shutdown]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,786Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-sql]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,786Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-stack]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,786Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-text-structure]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,786Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-voting-only-node]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,787Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"loaded module [x-pack-watcher]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,787Z\", \"level\": \"INFO\", \"component\": \"o.e.p.PluginsService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"no plugins loaded\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,845Z\", \"level\": \"INFO\", \"component\": \"o.e.e.NodeEnvironment\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"using [1] data paths, mounts [[/ (overlay)]], net usable_space [22.3gb], net total_space [393.1gb], types [overlay]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,846Z\", \"level\": \"INFO\", \"component\": \"o.e.e.NodeEnvironment\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"heap size [31gb], compressed ordinary object pointers [true]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:16,861Z\", \"level\": \"INFO\", \"component\": \"o.e.n.Node\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"node name [d36a0b817d49], node ID [H7-a5A5nS8eJMMZGU-tQgg], cluster name [docker-cluster], roles [transform, data_frozen, master, remote_cluster_client, data, ml, data_content, data_hot, data_warm, data_cold, ingest]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:20,796Z\", \"level\": \"INFO\", \"component\": \"o.e.x.m.p.l.CppLogMessageHandler\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"[controller/296] [Main.cc@122] controller (64 bit): Version 7.17.15 (Build 8285074a0b4035) Copyright (c) 2023 Elasticsearch BV\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:21,176Z\", \"level\": \"INFO\", \"component\": \"o.e.x.s.a.s.FileRolesStore\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"parsed [0] roles from file [/usr/share/elasticsearch/config/roles.yml]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:21,784Z\", \"level\": \"INFO\", \"component\": \"o.e.i.g.ConfigDatabases\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"initialized default databases [[GeoLite2-Country.mmdb, GeoLite2-City.mmdb, GeoLite2-ASN.mmdb]], config databases [[]] and watching [/usr/share/elasticsearch/config/ingest-geoip] for changes\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:21,785Z\", \"level\": \"INFO\", \"component\": \"o.e.i.g.DatabaseNodeService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"initialized database registry, using geoip-databases directory [/tmp/elasticsearch-9317727528719022261/geoip-databases/H7-a5A5nS8eJMMZGU-tQgg]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:22,318Z\", \"level\": \"INFO\", \"component\": \"o.e.t.NettyAllocator\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"creating NettyAllocator with the following configs: [name=elasticsearch_configured, chunk_size=1mb, suggested_max_allocation_size=1mb, factors={es.unsafe.use_netty_default_chunk_and_page_size=false, g1gc_enabled=true, g1gc_region_size=16mb}]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:22,348Z\", \"level\": \"INFO\", \"component\": \"o.e.i.r.RecoverySettings\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"using rate limit [40mb] with [default=40mb, read=0b, write=0b, max=0b]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:22,384Z\", \"level\": \"INFO\", \"component\": \"o.e.d.DiscoveryModule\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"using discovery type [single-node] and seed hosts providers [settings]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:22,817Z\", \"level\": \"INFO\", \"component\": \"o.e.g.DanglingIndicesState\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"gateway.auto_import_dangling_indices is disabled, dangling indices will not be automatically detected or imported and must be managed manually\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,385Z\", \"level\": \"INFO\", \"component\": \"o.e.n.Node\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"initialized\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,386Z\", \"level\": \"INFO\", \"component\": \"o.e.n.Node\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"starting ...\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,392Z\", \"level\": \"INFO\", \"component\": \"o.e.x.s.c.f.PersistentCache\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"persistent cache index loaded\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,393Z\", \"level\": \"INFO\", \"component\": \"o.e.x.d.l.DeprecationIndexingComponent\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"deprecation component started\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,481Z\", \"level\": \"INFO\", \"component\": \"o.e.t.TransportService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"publish_address {172.17.0.4:9300}, bound_addresses {0.0.0.0:9300}\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,491Z\", \"level\": \"INFO\", \"component\": \"o.e.x.m.Monitoring\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"creating template [.monitoring-alerts-7] with version [7]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,496Z\", \"level\": \"INFO\", \"component\": \"o.e.x.m.Monitoring\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"creating template [.monitoring-es] with version [7]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,498Z\", \"level\": \"INFO\", \"component\": \"o.e.x.m.Monitoring\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"creating template [.monitoring-kibana] with version [7]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,500Z\", \"level\": \"INFO\", \"component\": \"o.e.x.m.Monitoring\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"creating template [.monitoring-logstash] with version [7]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,503Z\", \"level\": \"INFO\", \"component\": \"o.e.x.m.Monitoring\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"creating template [.monitoring-beats] with version [7]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,603Z\", \"level\": \"INFO\", \"component\": \"o.e.c.c.Coordinator\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"setting initial configuration to VotingConfiguration{H7-a5A5nS8eJMMZGU-tQgg}\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,732Z\", \"level\": \"INFO\", \"component\": \"o.e.c.s.MasterService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"elected-as-master ([1] nodes joined)[{d36a0b817d49}{H7-a5A5nS8eJMMZGU-tQgg}{CAITPZlPRiqS087jqq9fNg}{172.17.0.4}{172.17.0.4:9300}{cdfhilmrstw} elect leader, _BECOME_MASTER_TASK_, _FINISH_ELECTION_], term: 1, version: 1, delta: master node changed {previous [], current [{d36a0b817d49}{H7-a5A5nS8eJMMZGU-tQgg}{CAITPZlPRiqS087jqq9fNg}{172.17.0.4}{172.17.0.4:9300}{cdfhilmrstw}]}\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,774Z\", \"level\": \"INFO\", \"component\": \"o.e.c.c.CoordinationState\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"cluster UUID set to [eSA1DR8kTta55tARlNN1XQ]\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,803Z\", \"level\": \"INFO\", \"component\": \"o.e.c.s.ClusterApplierService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"master node changed {previous [], current [{d36a0b817d49}{H7-a5A5nS8eJMMZGU-tQgg}{CAITPZlPRiqS087jqq9fNg}{172.17.0.4}{172.17.0.4:9300}{cdfhilmrstw}]}, term: 1, version: 1, reason: Publication{term=1, version=1}\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,865Z\", \"level\": \"INFO\", \"component\": \"o.e.h.AbstractHttpServerTransport\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"publish_address {172.17.0.4:9200}, bound_addresses {0.0.0.0:9200}\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,865Z\", \"level\": \"INFO\", \"component\": \"o.e.n.Node\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"started\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:23,938Z\", \"level\": \"INFO\", \"component\": \"o.e.g.GatewayService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"recovered [0] indices into cluster_state\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,118Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index template [.ml-stats] for index patterns [.ml-stats-*]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,217Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index template [.ml-anomalies-] for index patterns [.ml-anomalies-*]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,280Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index template [.ml-notifications-000002] for index patterns [.ml-notifications-000002]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,336Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index template [.ml-state] for index patterns [.ml-state*]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,393Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding component template [logs-settings]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,453Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding component template [synthetics-mappings]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,507Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding component template [logs-mappings]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,558Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding component template [metrics-mappings]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,607Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding component template [synthetics-settings]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,663Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding component template [data-streams-mappings]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,706Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding component template [metrics-settings]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,774Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index template [ilm-history] for index patterns [ilm-history-5*]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,840Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index template [.watch-history-13] for index patterns [.watcher-history-13*]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,884Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding component template [.deprecation-indexing-settings]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,936Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding component template [.deprecation-indexing-mappings]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:24,992Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index template [.slm-history] for index patterns [.slm-history-5*]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,042Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index template [logs] for index patterns [logs-*-*]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,094Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index template [synthetics] for index patterns [synthetics-*-*]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,146Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index template [metrics] for index patterns [metrics-*-*]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,192Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataIndexTemplateService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index template [.deprecation-indexing-template] for index patterns [.logs-deprecation.*]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,236Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.a.TransportPutLifecycleAction\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index lifecycle policy [ml-size-based-ilm-policy]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,288Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.a.TransportPutLifecycleAction\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index lifecycle policy [metrics]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,326Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.a.TransportPutLifecycleAction\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index lifecycle policy [synthetics]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,368Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.a.TransportPutLifecycleAction\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index lifecycle policy [logs]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,408Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.a.TransportPutLifecycleAction\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index lifecycle policy [365-days-default]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,462Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.a.TransportPutLifecycleAction\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index lifecycle policy [180-days-default]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,499Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.a.TransportPutLifecycleAction\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index lifecycle policy [30-days-default]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,540Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.a.TransportPutLifecycleAction\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index lifecycle policy [7-days-default]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,578Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.a.TransportPutLifecycleAction\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index lifecycle policy [90-days-default]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,615Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.a.TransportPutLifecycleAction\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index lifecycle policy [watch-history-ilm-policy]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,653Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.a.TransportPutLifecycleAction\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index lifecycle policy [ilm-history-ilm-policy]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,690Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.a.TransportPutLifecycleAction\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index lifecycle policy [slm-history-ilm-policy]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,727Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.a.TransportPutLifecycleAction\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index lifecycle policy [.deprecation-indexing-ilm-policy]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,766Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.a.TransportPutLifecycleAction\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding index lifecycle policy [.fleet-actions-results-ilm-policy]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,894Z\", \"level\": \"INFO\", \"component\": \"o.e.l.LicenseService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"license [2c8be2c9-13b1-402b-a385-31768507e22e] mode [basic] - valid\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,895Z\", \"level\": \"INFO\", \"component\": \"o.e.x.s.s.SecurityStatusChangeListener\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"Active license is now [BASIC]; Security is disabled\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,896Z\", \"level\": \"WARN\", \"component\": \"o.e.x.s.s.SecurityStatusChangeListener\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"deprecation.elasticsearch\", \"timestamp\": \"2023-12-08T13:47:25,898Z\", \"level\": \"CRITICAL\", \"component\": \"o.e.d.x.s.s.SecurityStatusChangeListener\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"The default behavior of disabling security on basic licenses is deprecated. In a later version of Elasticsearch, the value of [xpack.security.enabled] will default to \\\"true\\\" , regardless of the license level. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security, or explicitly disable security by setting [xpack.security.enabled] to false in elasticsearch.yml\", \"key\": \"security_implicitly_disabled\", \"category\": \"security\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,945Z\", \"level\": \"INFO\", \"component\": \"o.e.i.g.GeoIpDownloader\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"updating geoip databases\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:25,946Z\", \"level\": \"INFO\", \"component\": \"o.e.i.g.GeoIpDownloader\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"fetching geoip databases overview from [https://geoip.elastic.co/v1/database?elastic_geoip_service_tos=agree]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:26,816Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataCreateIndexService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"[.ds-.logs-deprecation.elasticsearch-default-2023.12.08-000001] creating index, cause [initialize_data_stream], templates [.deprecation-indexing-template], shards [1]/[1]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:26,826Z\", \"level\": \"INFO\", \"component\": \"o.e.c.r.a.AllocationService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"updating number_of_replicas to [0] for indices [.ds-.logs-deprecation.elasticsearch-default-2023.12.08-000001]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:26,838Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataCreateDataStreamService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding data stream [.logs-deprecation.elasticsearch-default] with write index [.ds-.logs-deprecation.elasticsearch-default-2023.12.08-000001], backing indices [], and aliases []\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:26,930Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.IndexLifecycleTransition\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"moving index [.ds-.logs-deprecation.elasticsearch-default-2023.12.08-000001] from [null] to [{\\\"phase\\\":\\\"new\\\",\\\"action\\\":\\\"complete\\\",\\\"name\\\":\\\"complete\\\"}] in policy [.deprecation-indexing-ilm-policy]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:26,983Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.IndexLifecycleTransition\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"moving index [.ds-.logs-deprecation.elasticsearch-default-2023.12.08-000001] from [{\\\"phase\\\":\\\"new\\\",\\\"action\\\":\\\"complete\\\",\\\"name\\\":\\\"complete\\\"}] to [{\\\"phase\\\":\\\"hot\\\",\\\"action\\\":\\\"unfollow\\\",\\\"name\\\":\\\"branch-check-unfollow-prerequisites\\\"}] in policy [.deprecation-indexing-ilm-policy]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:27,024Z\", \"level\": \"INFO\", \"component\": \"o.e.c.r.a.AllocationService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"Cluster health status changed from [YELLOW] to [GREEN] (reason: [shards started [[.ds-.logs-deprecation.elasticsearch-default-2023.12.08-000001][0]]]).\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:27,063Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.IndexLifecycleTransition\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"moving index [.ds-.logs-deprecation.elasticsearch-default-2023.12.08-000001] from [{\\\"phase\\\":\\\"hot\\\",\\\"action\\\":\\\"unfollow\\\",\\\"name\\\":\\\"branch-check-unfollow-prerequisites\\\"}] to [{\\\"phase\\\":\\\"hot\\\",\\\"action\\\":\\\"rollover\\\",\\\"name\\\":\\\"check-rollover-ready\\\"}] in policy [.deprecation-indexing-ilm-policy]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:27,208Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataMappingService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"[.ds-.logs-deprecation.elasticsearch-default-2023.12.08-000001/3PiFvL99TKCbcgpgC-K8xA] update_mapping [_doc]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:32,001Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataCreateIndexService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"[.ds-ilm-history-5-2023.12.08-000001] creating index, cause [initialize_data_stream], templates [ilm-history], shards [1]/[0]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:32,004Z\", \"level\": \"INFO\", \"component\": \"o.e.c.m.MetadataCreateDataStreamService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"adding data stream [ilm-history-5] with write index [.ds-ilm-history-5-2023.12.08-000001], backing indices [], and aliases []\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:32,061Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.IndexLifecycleTransition\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"moving index [.ds-ilm-history-5-2023.12.08-000001] from [null] to [{\\\"phase\\\":\\\"new\\\",\\\"action\\\":\\\"complete\\\",\\\"name\\\":\\\"complete\\\"}] in policy [ilm-history-ilm-policy]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:32,096Z\", \"level\": \"INFO\", \"component\": \"o.e.c.r.a.AllocationService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"Cluster health status changed from [YELLOW] to [GREEN] (reason: [shards started [[.ds-ilm-history-5-2023.12.08-000001][0]]]).\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:32,138Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.IndexLifecycleTransition\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"moving index [.ds-ilm-history-5-2023.12.08-000001] from [{\\\"phase\\\":\\\"new\\\",\\\"action\\\":\\\"complete\\\",\\\"name\\\":\\\"complete\\\"}] to [{\\\"phase\\\":\\\"hot\\\",\\\"action\\\":\\\"unfollow\\\",\\\"name\\\":\\\"branch-check-unfollow-prerequisites\\\"}] in policy [ilm-history-ilm-policy]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:32,175Z\", \"level\": \"INFO\", \"component\": \"o.e.x.i.IndexLifecycleTransition\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"moving index [.ds-ilm-history-5-2023.12.08-000001] from [{\\\"phase\\\":\\\"hot\\\",\\\"action\\\":\\\"unfollow\\\",\\\"name\\\":\\\"branch-check-unfollow-prerequisites\\\"}] to [{\\\"phase\\\":\\\"hot\\\",\\\"action\\\":\\\"rollover\\\",\\\"name\\\":\\\"check-rollover-ready\\\"}] in policy [ilm-history-ilm-policy]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:36,016Z\", \"level\": \"ERROR\", \"component\": \"o.e.i.g.GeoIpDownloader\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"exception during geoip databases update\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" , \n", - "\"stacktrace\": [\"java.net.SocketTimeoutException: Connect timed out\",\n", - "\"at sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:546) ~[?:?]\",\n", - "\"at sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:592) ~[?:?]\",\n", - "\"at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) ~[?:?]\",\n", - "\"at java.net.Socket.connect(Socket.java:751) ~[?:?]\",\n", - "\"at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:304) ~[?:?]\",\n", - "\"at sun.net.NetworkClient.doConnect(NetworkClient.java:178) ~[?:?]\",\n", - "\"at sun.net.www.http.HttpClient.openServer(HttpClient.java:531) ~[?:?]\",\n", - "\"at sun.net.www.http.HttpClient.openServer(HttpClient.java:636) ~[?:?]\",\n", - "\"at sun.net.www.protocol.https.HttpsClient.(HttpsClient.java:264) ~[?:?]\",\n", - "\"at sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:377) ~[?:?]\",\n", - "\"at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(AbstractDelegateHttpsURLConnection.java:193) ~[?:?]\",\n", - "\"at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1237) ~[?:?]\",\n", - "\"at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1123) ~[?:?]\",\n", - "\"at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:179) ~[?:?]\",\n", - "\"at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1675) ~[?:?]\",\n", - "\"at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1599) ~[?:?]\",\n", - "\"at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:531) ~[?:?]\",\n", - "\"at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:307) ~[?:?]\",\n", - "\"at org.elasticsearch.ingest.geoip.HttpClient.lambda$get$0(HttpClient.java:55) ~[ingest-geoip-7.17.15.jar:7.17.15]\",\n", - "\"at java.security.AccessController.doPrivileged(AccessController.java:571) ~[?:?]\",\n", - "\"at org.elasticsearch.ingest.geoip.HttpClient.doPrivileged(HttpClient.java:97) ~[ingest-geoip-7.17.15.jar:7.17.15]\",\n", - "\"at org.elasticsearch.ingest.geoip.HttpClient.get(HttpClient.java:49) ~[ingest-geoip-7.17.15.jar:7.17.15]\",\n", - "\"at org.elasticsearch.ingest.geoip.HttpClient.getBytes(HttpClient.java:40) ~[ingest-geoip-7.17.15.jar:7.17.15]\",\n", - "\"at org.elasticsearch.ingest.geoip.GeoIpDownloader.fetchDatabasesOverview(GeoIpDownloader.java:159) ~[ingest-geoip-7.17.15.jar:7.17.15]\",\n", - "\"at org.elasticsearch.ingest.geoip.GeoIpDownloader.updateDatabases(GeoIpDownloader.java:147) ~[ingest-geoip-7.17.15.jar:7.17.15]\",\n", - "\"at org.elasticsearch.ingest.geoip.GeoIpDownloader.runDownloader(GeoIpDownloader.java:284) [ingest-geoip-7.17.15.jar:7.17.15]\",\n", - "\"at org.elasticsearch.ingest.geoip.GeoIpDownloaderTaskExecutor.nodeOperation(GeoIpDownloaderTaskExecutor.java:100) [ingest-geoip-7.17.15.jar:7.17.15]\",\n", - "\"at org.elasticsearch.ingest.geoip.GeoIpDownloaderTaskExecutor.nodeOperation(GeoIpDownloaderTaskExecutor.java:46) [ingest-geoip-7.17.15.jar:7.17.15]\",\n", - "\"at org.elasticsearch.persistent.NodePersistentTasksExecutor$1.doRun(NodePersistentTasksExecutor.java:42) [elasticsearch-7.17.15.jar:7.17.15]\",\n", - "\"at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:777) [elasticsearch-7.17.15.jar:7.17.15]\",\n", - "\"at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:26) [elasticsearch-7.17.15.jar:7.17.15]\",\n", - "\"at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) [?:?]\",\n", - "\"at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) [?:?]\",\n", - "\"at java.lang.Thread.run(Thread.java:1583) [?:?]\"] }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:47:53,858Z\", \"level\": \"WARN\", \"component\": \"o.e.c.r.a.DiskThresholdMonitor\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"high disk watermark [90%] exceeded on [H7-a5A5nS8eJMMZGU-tQgg][d36a0b817d49][/usr/share/elasticsearch/data/nodes/0] free: 22.3gb[5.6%], shards will be relocated away from this node; currently relocating away shards totalling [0] bytes; the node is expected to continue to exceed the high disk watermark when these relocations are complete\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "^C\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:48:20,526Z\", \"level\": \"INFO\", \"component\": \"o.e.n.Node\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"stopping ...\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:48:20,530Z\", \"level\": \"INFO\", \"component\": \"o.e.x.w.WatcherService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"stopping watch service, reason [shutdown initiated]\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:48:20,530Z\", \"level\": \"INFO\", \"component\": \"o.e.x.m.p.l.CppLogMessageHandler\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"[controller/296] [Main.cc@174] ML controller exiting\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:48:20,531Z\", \"level\": \"INFO\", \"component\": \"o.e.x.m.p.NativeController\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"Native controller process has stopped - no new native processes can be started\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n", - "{\"type\": \"server\", \"timestamp\": \"2023-12-08T13:48:20,531Z\", \"level\": \"INFO\", \"component\": \"o.e.x.w.WatcherLifeCycleService\", \"cluster.name\": \"docker-cluster\", \"node.name\": \"d36a0b817d49\", \"message\": \"watcher has stopped and shutdown\", \"cluster.uuid\": \"eSA1DR8kTta55tARlNN1XQ\", \"node.id\": \"H7-a5A5nS8eJMMZGU-tQgg\" }\n" + "docker: Error response from daemon: driver failed programming external connectivity on endpoint admiring_meitner (af5f1498f190e509046ff0a13aa9a6254e94bbb3e8b6cf7e2a9f9df5d6ae882f): Bind for 127.0.0.1:9300 failed: port is already allocated.\n", + "\u001b[31mERRO\u001b[0m[0000] error waiting for container: \n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 14:39:30,703 E 4182447 4182465] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_14-38-38_780920_4181242 is over 95% full, available space: 563916800; capacity: 422146228224. Object creation will fail if spilling is required.\n" ] } ], @@ -1000,7 +1112,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [ { @@ -1008,9 +1120,9 @@ "output_type": "stream", "text": [ "{\n", - " \"name\" : \"efc38f135e49\",\n", + " \"name\" : \"ffeee69fabad\",\n", " \"cluster_name\" : \"docker-cluster\",\n", - " \"cluster_uuid\" : \"aevYlbdERfqS-jC8RXmeLw\",\n", + " \"cluster_uuid\" : \"QJVbm1Z1RAq7XNnxFdVMeA\",\n", " \"version\" : {\n", " \"number\" : \"7.17.15\",\n", " \"build_flavor\" : \"default\",\n", @@ -1040,201 +1152,170 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": {}, "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001B[32m2023-12-13 11:23:53.342\u001B[0m | \u001B[1mINFO \u001B[0m | \u001B[36mpyrecdp.core.import_utils\u001B[0m:\u001B[36mcheck_availability_and_install\u001B[0m:\u001B[36m45\u001B[0m - \u001B[1mcheck_availability_and_install ['langchain']\u001B[0m\n", - "\u001B[32m2023-12-13 11:23:53.346\u001B[0m | \u001B[1mINFO \u001B[0m | \u001B[36mpyrecdp.core.import_utils\u001B[0m:\u001B[36mcheck_availability_and_install\u001B[0m:\u001B[36m45\u001B[0m - \u001B[1mcheck_availability_and_install ['farm-haystack', 'farm-haystack[elasticsearch7]']\u001B[0m\n" - ] - }, { "name": "stderr", "output_type": "stream", "text": [ - "WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.\n", - "Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.\n", - "To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.\n" + "2023-12-19 15:43:49,797\tINFO dataset.py:2380 -- Tip: Use `take_batch()` instead of `take() / show()` to return records in pandas or numpy batch format.\n", + "2023-12-19 15:43:49,801\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[MapBatches(add_dog_years)] -> LimitOperator[limit=20]\n", + "2023-12-19 15:43:49,803\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-19 15:43:49,804\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" ] }, { "data": { - "text/html": [ - "
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n",
-       "
\n" - ], + "application/vnd.jupyter.widget-view+json": { + "model_id": "87eb8c5248fa44e592f3bdd9f7de875c", + "version_major": 2, + "version_minor": 0 + }, "text/plain": [ - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001B[0m\u001B[33m\n", - "\u001B[0m" + "Running 0: 0%| | 0/1 [00:00WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n", - "\n" - ], - "text/plain": [ - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001B[0m\u001B[33m\n", - "\u001B[0m" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, { "name": "stderr", "output_type": "stream", "text": [ - "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", - " warnings.warn(message, category=ElasticsearchWarning)\n" + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:43:54,288 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 519995392; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:44:04,302 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 519962624; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:44:14,317 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 519491584; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:44:24,331 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 519462912; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:44:34,343 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 519438336; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:44:44,356 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 519397376; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:44:54,367 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 510869504; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:45:04,380 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 510840832; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:45:14,394 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 510787584; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:45:24,407 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 510681088; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:45:34,421 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 510656512; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:45:44,435 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 510611456; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:45:54,448 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 510234624; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:46:04,462 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 510214144; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:46:14,474 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 509763584; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:46:24,487 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 509431808; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:46:34,501 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 509399040; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:46:44,514 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 509358080; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:46:54,526 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 509227008; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:47:04,538 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 509206528; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:47:14,550 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 508895232; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:47:24,563 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 508866560; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:47:34,578 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 508833792; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:47:44,592 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 517545984; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:47:54,606 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 517099520; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:48:04,618 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 517062656; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:48:14,631 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 516550656; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:48:24,645 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 516513792; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:48:34,658 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 516493312; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:48:44,673 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 516448256; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:48:54,686 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 516386816; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:49:04,699 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 516362240; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:49:14,712 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 515932160; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:49:24,726 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 515895296; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:49:34,739 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 515870720; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:49:44,752 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 515833856; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:49:54,766 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 507305984; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:50:04,780 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 507273216; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:50:14,794 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 507203584; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:50:24,807 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 507170816; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:50:34,821 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 507154432; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:50:44,835 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 507117568; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:50:54,848 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 506658816; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:51:04,862 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 506634240; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:51:14,876 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 515584000; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:51:24,888 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 515543040; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:51:34,903 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 515485696; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:51:44,916 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 515436544; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:51:54,930 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 515375104; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:52:04,942 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 515338240; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:52:14,955 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 514920448; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:52:24,968 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 514871296; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:52:34,980 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 514834432; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:52:44,993 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 514797568; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:52:55,006 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 514347008; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:53:05,021 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 514322432; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:53:15,035 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 514207744; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:53:25,049 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 514191360; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:53:35,063 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 514166784; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:53:45,077 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 514109440; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:53:55,091 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 513978368; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:54:05,106 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 513949696; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:54:15,120 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 513482752; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:54:25,133 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 513449984; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:54:35,146 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 513417216; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:54:45,160 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 513339392; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:54:55,177 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 513855488; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:55:05,190 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 513822720; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:55:15,204 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 513671168; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:55:25,217 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 513630208; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:55:35,232 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 513581056; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:55:45,246 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 513470464; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:55:55,261 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 513314816; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:56:05,275 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 513290240; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:56:15,288 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 512897024; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:56:25,302 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 512864256; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:56:35,317 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 512831488; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:56:45,332 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 512749568; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:56:55,345 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 512352256; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:57:05,359 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 512331776; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:57:15,373 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 511897600; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:57:25,388 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 511877120; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:57:35,403 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 511852544; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:57:45,416 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 511791104; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:57:55,430 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 511700992; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:58:05,442 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 511684608; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:58:15,457 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 511614976; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:58:25,472 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 511594496; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:58:35,489 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 511565824; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:58:45,503 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 511496192; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:58:55,518 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 511049728; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:59:05,532 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 511012864; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:59:15,546 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 510529536; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:59:25,560 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 510488576; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:59:35,573 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 510443520; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:59:45,587 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 510373888; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 15:59:55,599 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 510181376; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:00:05,612 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 510164992; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:00:15,626 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 509956096; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:00:25,638 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 509927424; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:00:35,650 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 509894656; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:00:45,663 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 509730816; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:00:55,676 E 109492 109513] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_15-37-41_942580_108415 is over 95% full, available space: 509583360; capacity: 422146228224. Object creation will fail if spilling is required.\n" ] - }, - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
textmetadata
0Welcome to cnvrg.io cnvrg.io is a machine lear...{'source': 'https://app.cnvrg.io/docs/'}
1Dataset Use Datasets to manage data with versi...{'source': 'https://app.cnvrg.io/docs/'}
2Use Papers to consolidate comparison across ex...{'source': 'https://app.cnvrg.io/docs/'}
3Easily update your running serving to keep it ...{'source': 'https://app.cnvrg.io/docs/'}
4Tutorials and Examples To help you get started...{'source': 'https://app.cnvrg.io/docs/collecti...
.........
92For example, gputype=v100 .To specify several,...{'source': 'https://app.cnvrg.io/docs/core_con...
93For example, gputype=v100 .To specify several,...{'source': 'https://app.cnvrg.io/docs/core_con...
94For example, gputype=v100 .To specify several,...{'source': 'https://app.cnvrg.io/docs/core_con...
95options are: cnvrg, dockerhub, gcr, acr, ecr, ...{'source': 'https://app.cnvrg.io/docs/core_con...
96options are: cnvrg, dockerhub, gcr, acr, ecr, ...{'source': 'https://app.cnvrg.io/docs/core_con...
\n", - "

97 rows × 2 columns

\n", - "
" - ], - "text/plain": [ - " text \\\n", - "0 Welcome to cnvrg.io cnvrg.io is a machine lear... \n", - "1 Dataset Use Datasets to manage data with versi... \n", - "2 Use Papers to consolidate comparison across ex... \n", - "3 Easily update your running serving to keep it ... \n", - "4 Tutorials and Examples To help you get started... \n", - ".. ... \n", - "92 For example, gputype=v100 .To specify several,... \n", - "93 For example, gputype=v100 .To specify several,... \n", - "94 For example, gputype=v100 .To specify several,... \n", - "95 options are: cnvrg, dockerhub, gcr, acr, ecr, ... \n", - "96 options are: cnvrg, dockerhub, gcr, acr, ecr, ... \n", - "\n", - " metadata \n", - "0 {'source': 'https://app.cnvrg.io/docs/'} \n", - "1 {'source': 'https://app.cnvrg.io/docs/'} \n", - "2 {'source': 'https://app.cnvrg.io/docs/'} \n", - "3 {'source': 'https://app.cnvrg.io/docs/'} \n", - "4 {'source': 'https://app.cnvrg.io/docs/collecti... \n", - ".. ... \n", - "92 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "93 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "94 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "95 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "96 {'source': 'https://app.cnvrg.io/docs/core_con... \n", - "\n", - "[97 rows x 2 columns]" - ] - }, - "metadata": {}, - "output_type": "display_data" } ], "source": [ - "from pyrecdp.primitives.operations import DocumentIngestion\n", - "indexer_op = DocumentIngestion(\n", - " rag_framework='haystack',\n", - " vector_store='elasticsearch',\n", - " vector_store_args={'host': 'localhost', 'port': 9200},\n", - ")\n", + "import ray\n", + "from typing import Dict\n", + "import numpy as np\n", "\n", - "ds = indexer_op.process_rayds(ds)\n", - "display(ds.to_pandas())" + "def add_dog_years(batch: Dict[str, np.ndarray]) -> Dict[str, np.ndarray]:\n", + " batch[\"age_in_dog_years\"] = 7 * batch[\"age\"]\n", + " return batch\n", + "\n", + "ds = (\n", + " ray.data.from_items([\n", + " {\"name\": \"Luna\", \"age\": 4},\n", + " {\"name\": \"Rory\", \"age\": 14},\n", + " {\"name\": \"Scout\", \"age\": 9},\n", + " ])\n", + " .map_batches(add_dog_years)\n", + ")\n", + "ds.show()\n" ] } ], diff --git a/RecDP/pyrecdp/primitives/operations/__init__.py b/RecDP/pyrecdp/primitives/operations/__init__.py index 523d4ff3..31ce03a4 100644 --- a/RecDP/pyrecdp/primitives/operations/__init__.py +++ b/RecDP/pyrecdp/primitives/operations/__init__.py @@ -65,7 +65,7 @@ from .text_perplexity_score import TextPerplexityScore from .random_select import RandomSelect from .text_ingestion import DocumentIngestion - from .doc_loader import DirectoryLoader, DocumentLoader, UrlLoader, YoutubeLoader + from .doc_loader import DirectoryLoader, DocumentLoader, UrlLoader, RecursiveUrlLoader, YoutubeLoader from .text_to_qa import TextToQA from .table_summary import TableSummary from .text_spell_correct import TextSpellCorrect diff --git a/RecDP/pyrecdp/primitives/operations/doc_loader.py b/RecDP/pyrecdp/primitives/operations/doc_loader.py index 1e1b8932..b8f896b2 100644 --- a/RecDP/pyrecdp/primitives/operations/doc_loader.py +++ b/RecDP/pyrecdp/primitives/operations/doc_loader.py @@ -1,16 +1,18 @@ import os -from typing import Optional, List, Callable +import re +from typing import Optional, List, Callable, Union, Sequence from urllib.parse import urlparse, urlunparse, urljoin import requests +from pyrecdp.core.import_utils import check_availability_and_install from pyrecdp.core.import_utils import import_langchain, import_markdownify, import_beautiful_soup from pyrecdp.primitives.llmutils.document.schema import Document -from pyrecdp.primitives.operations.base import BaseLLMOperation, LLMOPERATORS +from pyrecdp.primitives.operations.base import LLMOPERATORS from pyrecdp.primitives.operations.constant import DEFAULT_HEADER -from pyrecdp.primitives.operations.text_reader import TextReader from pyrecdp.primitives.operations.logging_utils import logger -from pyrecdp.core.import_utils import check_availability_and_install +from pyrecdp.primitives.operations.text_reader import TextReader + class DocumentLoader(TextReader): def __init__(self, @@ -143,8 +145,9 @@ def _get_loader(self) -> Callable[[], List[Document]]: LLMOPERATORS.register(DirectoryLoader) + class YoutubeLoader(TextReader): - def __init__(self, urls: List[str], save_dir: str = None, model = 'small', **kwargs): + def __init__(self, urls: List[str], save_dir: str = None, model='small', **kwargs): """ Loads documents from a directory or a list of Youtube URLs. @@ -152,7 +155,7 @@ def __init__(self, urls: List[str], save_dir: str = None, model = 'small', **kwa urls: The list of Youtube video urls. save_dir: The directory to save loaded Youtube audio, will remove the tmp file if save_dir is None. model: The name of the whisper model, check the available ones using whisper.available_models(). - """ + """ settings = { 'urls': urls, 'save_dir': save_dir, @@ -162,7 +165,7 @@ def __init__(self, urls: List[str], save_dir: str = None, model = 'small', **kwa self.urls = urls self.save_dir = save_dir self.model_name = model - + def _load(self): import os import tempfile @@ -181,7 +184,7 @@ def _load(self): audio_paths = {} for url, blob in zip(self.urls[::-1], loader.yield_blobs()): audio_paths[url] = str(blob.path) - import os + import os os.system("apt-get -qq -y install ffmpeg") check_availability_and_install('openai-whisper') import whisper @@ -192,9 +195,9 @@ def _load(self): finally: if use_temp_dir: shutil.rmtree(save_dir) - + return docs - + def load_documents(self): return [{'text': doc.text, 'metadata': doc.metadata} for doc in self._load()] @@ -211,8 +214,10 @@ def process_spark(self, spark, spark_df=None): self.cache = self.union_spark_df(spark_df, self.cache) return self.cache + LLMOPERATORS.register(YoutubeLoader) + def create_doc_from_html_to_md(page_url, html_text): import_markdownify() import markdownify @@ -382,3 +387,108 @@ def process_spark(self, spark, spark_df=None): LLMOPERATORS.register(UrlLoader) + + +class RecursiveUrlLoader(TextReader): + def __init__( + self, + urls: Union[str | List[str]], + max_depth: Optional[int] = 2, + use_async: Optional[bool] = None, + extractor: Optional[Callable[[str], str]] = None, + metadata_extractor: Optional[Callable[[str, str], str]] = None, + exclude_dirs: Optional[Sequence[str]] = (), + timeout: Optional[int] = 10, + prevent_outside: bool = True, + link_regex: Union[str, re.Pattern, None] = None, + headers: Optional[dict] = None, + check_response_status: bool = False, + requirements=None, + ) -> None: + """Initialize with URL to crawl and any subdirectories to exclude. + + Args: + urls: The URLS to crawl. + max_depth: The max depth of the recursive loading. + use_async: Whether to use asynchronous loading. + If True, this function will not be lazy, but it will still work in the + expected way, just not lazy. + extractor: A function to extract document contents from raw html. + When extract function returns an empty string, the document is + ignored. Default extractor will attempt to use BeautifulSoup4 to extract the text + metadata_extractor: A function to extract metadata from raw html and the + source url (args in that order). Default extractor will attempt + to use BeautifulSoup4 to extract the title, description and language + of the page. + exclude_dirs: A list of subdirectories to exclude. + timeout: The timeout for the requests, in the unit of seconds. If None then + connection will not timeout. + prevent_outside: If True, prevent loading from urls which are not children + of the root url. + link_regex: Regex for extracting sub-links from the raw html of a web page. + check_response_status: If True, check HTTP response status and skip + URLs with error responses (400-599). + """ + if requirements is None: + requirements = [] + + if extractor is None: + from bs4 import BeautifulSoup + extractor = lambda x: BeautifulSoup(x, "html.parser").text + + settings = { + 'urls': urls, + 'max_depth': max_depth, + 'use_async': use_async, + 'extractor': extractor, + 'metadata_extractor': metadata_extractor, + 'exclude_dirs': exclude_dirs, + 'timeout': timeout, + 'prevent_outside': prevent_outside, + 'link_regex': link_regex, + 'headers': headers, + 'check_response_status': check_response_status, + } + super().__init__(settings, requirements=['bs4', 'langchain']) + self.support_spark = True + self.support_ray = True + + from langchain.document_loaders import RecursiveUrlLoader as LCRecursiveURLLoader + if isinstance(urls, str): + urls = [urls] + + urls = set(urls) + + self.loaders = [LCRecursiveURLLoader( + url, + max_depth=max_depth, + use_async=use_async, + extractor=extractor, + metadata_extractor=metadata_extractor, + exclude_dirs=exclude_dirs, + timeout=timeout, + prevent_outside=prevent_outside, + link_regex=link_regex, + headers=headers, + check_response_status=check_response_status, + ) for url in urls] + + def load_documents(self): + return [{'text': doc.page_content, 'metadata': doc.metadata} for loader in self.loaders for doc in + loader.load()] + + def process_rayds(self, ds=None): + import ray + self.cache = ray.data.from_items(self.load_documents()) + if ds is not None: + self.cache = self.union_ray_ds(ds, self.cache) + return self.cache + + def process_spark(self, spark, spark_df=None): + self.cache = spark.createDataFrame(self.load_documents()) + if spark_df is not None: + self.cache = self.union_spark_df(spark_df, self.cache) + return self.cache + + +LLMOPERATORS.register(RecursiveUrlLoader) diff --git a/RecDP/pyrecdp/primitives/operations/text_ingestion.py b/RecDP/pyrecdp/primitives/operations/text_ingestion.py index 6e9b996d..711e4c0b 100644 --- a/RecDP/pyrecdp/primitives/operations/text_ingestion.py +++ b/RecDP/pyrecdp/primitives/operations/text_ingestion.py @@ -195,21 +195,17 @@ def do_persist(self, ds, **kwargs): exclude_keys = ['db_handler', 'return_db_handler'] vector_store_args = dict((k, v) for k, v in self.vector_store_args.items() if k not in exclude_keys) if isinstance(ds, Dataset): - class BatchIndexer: - def __init__(self, text_column: str, vector_store_args: Optional[Dict[str, Any]]): - from haystack.document_stores import ElasticsearchDocumentStore - self.text_column = text_column - self.vector_store_args = vector_store_args - self.elasticsearch = ElasticsearchDocumentStore( - **vector_store_args - ) - - def __call__(self, batch): - from haystack import Document as SDocument - documents = [SDocument(content=text) for text in batch[self.text_column]] - self.elasticsearch.write_documents(documents) - - ds.map_batches(BatchIndexer, fn_constructor_kwargs=vector_store_args) + def batch_index(batch, text_column,vector_store_args: Optional[Dict[str, Any]]): + from haystack.document_stores import ElasticsearchDocumentStore + elasticsearch = ElasticsearchDocumentStore( + **vector_store_args + ) + from haystack import Document as SDocument + documents = [SDocument(content=text) for text in batch[text_column]] + elasticsearch.write_documents(documents) + + return {} + ds.map_batches(lambda batch: batch_index(batch,self.text_column, vector_store_args)).count() else: def batch_index_with_var(batch, bv_value): from haystack import Document as SDocument @@ -223,7 +219,7 @@ def batch_index_with_var(batch, bv_value): ds = cast(DataFrame, ds) - bv = ds.sparkSession.sparkContext.broadcast((self.text_column, self.vector_store_args)) + bv = ds.sparkSession.sparkContext.broadcast((self.text_column, vector_store_args)) ds.foreachPartition(lambda p: batch_index_with_var(p, bv)) # share this document store only when rag retrieval want to use document store created from index stage diff --git a/RecDP/tests/test_llmutils_pipelines.py b/RecDP/tests/test_llmutils_pipelines.py index 5fa4706b..84aed09c 100644 --- a/RecDP/tests/test_llmutils_pipelines.py +++ b/RecDP/tests/test_llmutils_pipelines.py @@ -273,7 +273,7 @@ def test_llm_rag_pdf_use_existing_db_pipeline(self): display(ret) def test_llm_rag_pipeline_cnvrg(self): - from pyrecdp.primitives.operations import DocumentLoader,RAGTextFix,CustomerDocumentSplit,TextCustomerFilter,JsonlWriter + from pyrecdp.primitives.operations import RecursiveUrlLoader,RAGTextFix,CustomerDocumentSplit,TextCustomerFilter,JsonlWriter from pyrecdp.LLM import TextPipeline urls = ['https://app.cnvrg.io/docs/', @@ -313,7 +313,7 @@ def chunk_doc(text,max_num_of_words): pipeline = TextPipeline() ops = [ - DocumentLoader(loader='UnstructuredURLLoader', loader_args={'urls': urls}, requirements=['unstructured']), + RecursiveUrlLoader(urls, max_depth=2), RAGTextFix(str_to_replace={'\n###': '', '\n##': '', '\n#': ''}, remove_extra_whitespace=True), CustomerDocumentSplit(func=lambda text: text.split('# ')[1:]), TextCustomerFilter(custom_filter), From 22a33955543adc955f31317ab80bd40680926f96 Mon Sep 17 00:00:00 2001 From: "Zhang, Chaojun" Date: Tue, 19 Dec 2023 17:17:09 +0000 Subject: [PATCH 02/59] Add notebook for RecursiveUrlLoader --- .../examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb index 8d55cec5..41b3a5ae 100644 --- a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb +++ b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb @@ -340,7 +340,13 @@ "name": "stderr", "output_type": "stream", "text": [ - "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:56:28,069 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 454561792; capacity: 422146228224. Object creation will fail if spilling is required.\n" + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:56:28,069 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 454561792; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:56:38,082 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 454459392; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:56:48,096 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 454348800; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:56:58,109 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 454307840; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:57:08,122 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 454258688; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:57:18,135 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 454017024; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:57:28,149 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 453988352; capacity: 422146228224. Object creation will fail if spilling is required.\n" ] } ], From f9194ade3dc67e749caddde1139729c0ad05ef44 Mon Sep 17 00:00:00 2001 From: "Zhang, Chaojun" Date: Wed, 20 Dec 2023 10:46:06 +0000 Subject: [PATCH 03/59] add unit test for recursive url loader --- RecDP/tests/test_llmutils_operations.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/RecDP/tests/test_llmutils_operations.py b/RecDP/tests/test_llmutils_operations.py index 3418d004..dca34ac6 100644 --- a/RecDP/tests/test_llmutils_operations.py +++ b/RecDP/tests/test_llmutils_operations.py @@ -499,3 +499,22 @@ def test_spell_correct_spark(self): op = TextSpellCorrect() with SparkContext("tests/data/llm_data/tiny_c4_sample_10.jsonl") as ctx: ctx.show(op.process_spark(ctx.spark, ctx.ds)) + + + def test_recursive_url_loader_spark(self): + urls = ['https://app.cnvrg.io/docs/', + 'https://app.cnvrg.io/docs/core_concepts/python_sdk_v2.html', + 'https://app.cnvrg.io/docs/cli_v2/cnvrgv2_cli.html', + 'https://app.cnvrg.io/docs/collections/tutorials.html'] + op = RecursiveUrlLoader(urls, max_depth=2) + with SparkContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: + ctx.show(op.process_spark(ctx.spark)) + + def test_recursive_url_loader_ray(self): + urls = ['https://app.cnvrg.io/docs/', + 'https://app.cnvrg.io/docs/core_concepts/python_sdk_v2.html', + 'https://app.cnvrg.io/docs/cli_v2/cnvrgv2_cli.html', + 'https://app.cnvrg.io/docs/collections/tutorials.html'] + op = RecursiveUrlLoader(urls, max_depth=2) + with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: + ctx.show(op.process_rayds()) \ No newline at end of file From a176d7b95cf95808c3f6a86dabd3b954990336bb Mon Sep 17 00:00:00 2001 From: "Yao, Qing" Date: Wed, 20 Dec 2023 19:40:31 +0800 Subject: [PATCH 04/59] Add notebooks for new ops . --- .../llmutils/contraction_remove.ipynb | 173 ++++++++++++++++ .../notebooks/llmutils/rag_text_fix.ipynb | 194 ++++++++++++++++++ .../llmutils/spelling_correction.ipynb | 166 +++++++++++++++ .../notebooks/llmutils/url_loader.ipynb | 172 ++++++++++++++++ RecDP/pyrecdp/LLM/README.md | 10 + 5 files changed, 715 insertions(+) create mode 100644 RecDP/examples/notebooks/llmutils/contraction_remove.ipynb create mode 100644 RecDP/examples/notebooks/llmutils/rag_text_fix.ipynb create mode 100644 RecDP/examples/notebooks/llmutils/spelling_correction.ipynb create mode 100644 RecDP/examples/notebooks/llmutils/url_loader.ipynb diff --git a/RecDP/examples/notebooks/llmutils/contraction_remove.ipynb b/RecDP/examples/notebooks/llmutils/contraction_remove.ipynb new file mode 100644 index 00000000..04e540ad --- /dev/null +++ b/RecDP/examples/notebooks/llmutils/contraction_remove.ipynb @@ -0,0 +1,173 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "z_gVsK2fahsZ", + "metadata": { + "id": "z_gVsK2fahsZ" + }, + "source": [ + "# RecDP LLM - Expanding Contractions\n", + "\n", + "\n", + "Contractions are shortened versions of words or syllables. They are created by removing, one or more letters from words. Sometimes, multiple words are combined to create a contraction. For example, \"I will is contracted into I’ll, do not into don’t.\" Considering I will and I’ll differently might result in poor performance of the model. Hence, it’s a good practice to convert each contraction into its expanded form. Recdp use the contractions library to convert contractions into their expanded form.\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "lFH8BqLubYLI", + "metadata": { + "id": "lFH8BqLubYLI" + }, + "source": [ + "# Get started" + ] + }, + { + "cell_type": "markdown", + "id": "n35FAQmcbdY_", + "metadata": { + "id": "n35FAQmcbdY_" + }, + "source": [ + "## 1. Install pyrecdp and dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "wzlH_Ms3bnGM", + "metadata": { + "id": "wzlH_Ms3bnGM" + }, + "outputs": [], + "source": [ + "! DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-8-jre\n", + "! pip install pyrecdp --pre\n", + "# ! pip install 'git+https://github.com/intel/e2eAIOK.git#egg=pyrecdp&subdirectory=RecDP'" + ] + }, + { + "cell_type": "markdown", + "id": "LHPfbKs7be8l", + "metadata": { + "id": "LHPfbKs7be8l" + }, + "source": [ + "## 2. Prepare your own data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ED6Z8QPdbwoF", + "metadata": { + "id": "ED6Z8QPdbwoF" + }, + "outputs": [], + "source": [ + "%mkdir -p /content/test_data\n", + "%cd /content/test_data\n", + "!wget https://raw.githubusercontent.com/intel/e2eAIOK/main/RecDP/tests/data/llm_data/github_sample_50.jsonl" + ] + }, + { + "cell_type": "markdown", + "id": "iIZVijQ7cG1N", + "metadata": { + "id": "iIZVijQ7cG1N" + }, + "source": [ + "## 3. Expanding Contractions" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### 3.1 Process with Expanding Contractions\n", + "\n" + ], + "metadata": { + "id": "5EaDIIzQ0YiG" + }, + "id": "5EaDIIzQ0YiG" + }, + { + "cell_type": "code", + "execution_count": null, + "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a", + "metadata": { + "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a" + }, + "outputs": [], + "source": [ + "from pyrecdp.LLM import TextPipeline\n", + "from pyrecdp.primitives.operations import *\n", + "\n", + "input_path = \"/content/test_data/\"\n", + "output_path = \"TextPipeline_output\"\n", + "pipeline = TextPipeline()\n", + "ops = [\n", + " JsonlReader(input_path),\n", + " TextContractionRemove(),\n", + " ParquetWriter(output_path)\n", + "]\n", + "pipeline.add_operations(ops)\n", + "ret = pipeline.execute()\n", + "del pipeline\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### 3.2 View processed data" + ], + "metadata": { + "id": "J5Lv3IZw0TNG" + }, + "id": "J5Lv3IZw0TNG" + }, + { + "cell_type": "code", + "source": [ + "import pandas as pd\n", + "result_pd = pd.read_parquet(output_path)\n", + "result_pd.head()" + ], + "metadata": { + "id": "5wlprXy00gBf" + }, + "id": "5wlprXy00gBf", + "execution_count": null, + "outputs": [] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/RecDP/examples/notebooks/llmutils/rag_text_fix.ipynb b/RecDP/examples/notebooks/llmutils/rag_text_fix.ipynb new file mode 100644 index 00000000..e03d421e --- /dev/null +++ b/RecDP/examples/notebooks/llmutils/rag_text_fix.ipynb @@ -0,0 +1,194 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "z_gVsK2fahsZ", + "metadata": { + "id": "z_gVsK2fahsZ" + }, + "source": [ + "# RecDP LLM - RAG Text fixer\n", + "\n", + "Clean and refine the documents for RAG process.\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "lFH8BqLubYLI", + "metadata": { + "id": "lFH8BqLubYLI" + }, + "source": [ + "# Get started" + ] + }, + { + "cell_type": "markdown", + "id": "n35FAQmcbdY_", + "metadata": { + "id": "n35FAQmcbdY_" + }, + "source": [ + "## 1. Install pyrecdp and dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "wzlH_Ms3bnGM", + "metadata": { + "id": "wzlH_Ms3bnGM" + }, + "outputs": [], + "source": [ + "! DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-8-jre\n", + "! pip install pyrecdp --pre\n", + "# ! pip install 'git+https://github.com/intel/e2eAIOK.git#egg=pyrecdp&subdirectory=RecDP'" + ] + }, + { + "cell_type": "markdown", + "id": "LHPfbKs7be8l", + "metadata": { + "id": "LHPfbKs7be8l" + }, + "source": [ + "## 2. Usage" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### 2.1 Use UrlLoader to load a list of urls. Show results without using RAGTextFix.\n", + "\n", + "\n", + "\n" + ], + "metadata": { + "id": "5EaDIIzQ0YiG" + }, + "id": "5EaDIIzQ0YiG" + }, + { + "cell_type": "code", + "execution_count": null, + "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a", + "metadata": { + "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a" + }, + "outputs": [], + "source": [ + "from pyrecdp.LLM import TextPipeline\n", + "from pyrecdp.primitives.operations import *\n", + "\n", + "urls = ['https://app.cnvrg.io/docs/',\n", + " 'https://app.cnvrg.io/docs/core_concepts/python_sdk_v2.html',\n", + " 'https://app.cnvrg.io/docs/cli_v2/cnvrgv2_cli.html',\n", + " 'https://app.cnvrg.io/docs/collections/tutorials.html']\n", + "\n", + "loader = UrlLoader(urls=url, max_depth=2, extractor=lambda x: Soup(x, \"html.parser\").text)\n", + "ds = loader.process_rayds()\n", + "for row in ds.iter_rows():\n", + " print(row['text'])\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### 2.2 Use UrlLoader to load a list of urls recursively and use RAGTextFix to clean up documents.\n", + "\n", + "* Step 1: Fix unicode errors in text using ftfy\n", + "\n", + "* Step 2: Normalize different kinds of whitespaces to whitespace ' ' (0x20) in text. Different kinds of whitespaces can be found here: https://en.wikipedia.org/wiki/Whitespace_character\n", + "\n", + "* Step 3: Clean specific chars in text.\n", + "\n", + "* Step 4: Replace the specified string.\n", + "\n", + "* Step 5: Remove extra whitespaces.\n", + "\n", + "* Step 6: Re segment sentences in the text to avoid sentence segmentation errors caused by unnecessary line breaks." + ], + "metadata": { + "id": "J5Lv3IZw0TNG" + }, + "id": "J5Lv3IZw0TNG" + }, + { + "cell_type": "code", + "source": [ + "from pyrecdp.LLM import TextPipeline\n", + "from pyrecdp.primitives.operations import *\n", + "\n", + "output_path = \"TextPipeline_output\"\n", + "pipeline = TextPipeline()\n", + "ops = [\n", + " loader,\n", + " RAGTextFix(str_to_replace={'\\n###': '', '\\n##': '', '\\n#': ''}, remove_extra_whitespace=True),\n", + " ParquetWriter(output_path)\n", + "]\n", + "pipeline.add_operations(ops)\n", + "ret = pipeline.execute()\n", + "del pipeline" + ], + "metadata": { + "id": "5wlprXy00gBf" + }, + "id": "5wlprXy00gBf", + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "### 2.3 Show results after RAGTextFix" + ], + "metadata": { + "id": "HB2wZVn77v5u" + }, + "id": "HB2wZVn77v5u" + }, + { + "cell_type": "code", + "source": [ + "import pandas as pd\n", + "result_pd = pd.read_parquet(output_path)\n", + "result_pd.head()" + ], + "metadata": { + "id": "ZN8rnxGR7wbo" + }, + "id": "ZN8rnxGR7wbo", + "execution_count": null, + "outputs": [] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/RecDP/examples/notebooks/llmutils/spelling_correction.ipynb b/RecDP/examples/notebooks/llmutils/spelling_correction.ipynb new file mode 100644 index 00000000..0754752c --- /dev/null +++ b/RecDP/examples/notebooks/llmutils/spelling_correction.ipynb @@ -0,0 +1,166 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "z_gVsK2fahsZ", + "metadata": { + "id": "z_gVsK2fahsZ" + }, + "source": [ + "# RecDP LLM - Spelling Correction\n", + "Spelling Correction with library [TextBlob](https://textblob.readthedocs.io/en/dev/)\n" + ] + }, + { + "cell_type": "markdown", + "id": "lFH8BqLubYLI", + "metadata": { + "id": "lFH8BqLubYLI" + }, + "source": [ + "# Get started" + ] + }, + { + "cell_type": "markdown", + "id": "n35FAQmcbdY_", + "metadata": { + "id": "n35FAQmcbdY_" + }, + "source": [ + "## 1. Install pyrecdp and dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "wzlH_Ms3bnGM", + "metadata": { + "id": "wzlH_Ms3bnGM" + }, + "outputs": [], + "source": [ + "! DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-8-jre\n", + "# ! pip install pyrecdp --pre\n", + "! pip install 'git+https://github.com/intel/e2eAIOK.git#egg=pyrecdp&subdirectory=RecDP'" + ] + }, + { + "cell_type": "markdown", + "id": "LHPfbKs7be8l", + "metadata": { + "id": "LHPfbKs7be8l" + }, + "source": [ + "## 2. Prepare your own data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ED6Z8QPdbwoF", + "metadata": { + "id": "ED6Z8QPdbwoF" + }, + "outputs": [], + "source": [ + "%mkdir -p /content/test_data\n", + "%cd /content/test_data\n", + "!wget https://raw.githubusercontent.com/intel/e2eAIOK/main/RecDP/tests/data/llm_data/github_sample_50.jsonl" + ] + }, + { + "cell_type": "markdown", + "id": "iIZVijQ7cG1N", + "metadata": { + "id": "iIZVijQ7cG1N" + }, + "source": [ + "## 3. Spelling Correction" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### 3.1 Process with Spelling Correction\n" + ], + "metadata": { + "id": "5EaDIIzQ0YiG" + }, + "id": "5EaDIIzQ0YiG" + }, + { + "cell_type": "code", + "execution_count": null, + "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a", + "metadata": { + "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a" + }, + "outputs": [], + "source": [ + "from pyrecdp.LLM import TextPipeline\n", + "from pyrecdp.primitives.operations import *\n", + "\n", + "input_path = \"/content/test_data/\"\n", + "output_path = \"TextPipeline_output\"\n", + "pipeline = TextPipeline()\n", + "ops = [\n", + " JsonlReader(input_path),\n", + " TextSpellCorrect(),\n", + " ParquetWriter(output_path)\n", + "]\n", + "pipeline.add_operations(ops)\n", + "ret = pipeline.execute()\n", + "del pipeline\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### 3.2 View processed data" + ], + "metadata": { + "id": "J5Lv3IZw0TNG" + }, + "id": "J5Lv3IZw0TNG" + }, + { + "cell_type": "code", + "source": [ + "import pandas as pd\n", + "result_pd = pd.read_parquet(output_path)\n", + "result_pd.head()" + ], + "metadata": { + "id": "5wlprXy00gBf" + }, + "id": "5wlprXy00gBf", + "execution_count": null, + "outputs": [] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/RecDP/examples/notebooks/llmutils/url_loader.ipynb b/RecDP/examples/notebooks/llmutils/url_loader.ipynb new file mode 100644 index 00000000..845b368b --- /dev/null +++ b/RecDP/examples/notebooks/llmutils/url_loader.ipynb @@ -0,0 +1,172 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "z_gVsK2fahsZ", + "metadata": { + "id": "z_gVsK2fahsZ" + }, + "source": [ + "# RecDP LLM - UrlLoader\n", + "\n", + "\n", + "UrlLoader can load all text from HTML webpages into a document format or process load all URLs under a root directory.\n", + "\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "lFH8BqLubYLI", + "metadata": { + "id": "lFH8BqLubYLI" + }, + "source": [ + "# Get started" + ] + }, + { + "cell_type": "markdown", + "id": "n35FAQmcbdY_", + "metadata": { + "id": "n35FAQmcbdY_" + }, + "source": [ + "## 1. Install pyrecdp and dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "wzlH_Ms3bnGM", + "metadata": { + "id": "wzlH_Ms3bnGM" + }, + "outputs": [], + "source": [ + "! DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-8-jre\n", + "! pip install pyrecdp --pre\n", + "# ! pip install 'git+https://github.com/intel/e2eAIOK.git#egg=pyrecdp&subdirectory=RecDP'" + ] + }, + { + "cell_type": "markdown", + "id": "LHPfbKs7be8l", + "metadata": { + "id": "LHPfbKs7be8l" + }, + "source": [ + "## 2. Usage" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### 2.1 Use UrlLoader to load a list of urls.\n", + "\n" + ], + "metadata": { + "id": "5EaDIIzQ0YiG" + }, + "id": "5EaDIIzQ0YiG" + }, + { + "cell_type": "code", + "execution_count": null, + "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a", + "metadata": { + "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a" + }, + "outputs": [], + "source": [ + "from pyrecdp.LLM import TextPipeline\n", + "from pyrecdp.primitives.operations import *\n", + "\n", + "urls = ['https://app.cnvrg.io/docs/',\n", + " 'https://app.cnvrg.io/docs/core_concepts/python_sdk_v2.html',\n", + " 'https://app.cnvrg.io/docs/cli_v2/cnvrgv2_cli.html',\n", + " 'https://app.cnvrg.io/docs/collections/tutorials.html']\n", + "\n", + "loader = UrlLoader(urls=url)\n", + "ds = loader.process_rayds()\n", + "for row in ds.iter_rows():\n", + " print(row['text'])\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### 2.2 Use UrlLoader to load a list of urls recursively ." + ], + "metadata": { + "id": "J5Lv3IZw0TNG" + }, + "id": "J5Lv3IZw0TNG" + }, + { + "cell_type": "code", + "source": [ + "loader = UrlLoader(urls=url, max_depth=2)\n", + "ds = loader.process_rayds()\n", + "for row in ds.iter_rows():\n", + " print(row['text'])" + ], + "metadata": { + "id": "5wlprXy00gBf" + }, + "id": "5wlprXy00gBf", + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "### 2.3 Specify a function to extract the text of the document from the webpage for UrlLoader to load a list of urls" + ], + "metadata": { + "id": "HB2wZVn77v5u" + }, + "id": "HB2wZVn77v5u" + }, + { + "cell_type": "code", + "source": [ + "loader = UrlLoader(urls=url, max_depth=2, extractor=lambda x: Soup(x, \"html.parser\").text)\n", + "ds = loader.process_rayds()\n", + "for row in ds.iter_rows():\n", + " print(row['text'])" + ], + "metadata": { + "id": "ZN8rnxGR7wbo" + }, + "id": "ZN8rnxGR7wbo", + "execution_count": null, + "outputs": [] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/RecDP/pyrecdp/LLM/README.md b/RecDP/pyrecdp/LLM/README.md index 3e6c03fe..0b941388 100644 --- a/RecDP/pyrecdp/LLM/README.md +++ b/RecDP/pyrecdp/LLM/README.md @@ -37,6 +37,16 @@ RecDP LLM is a set of python components that enables quick and easy establish of | ![diversity](/RecDP/resources/diversity_analysis.png) | ![quality](/RecDP/resources/quality_scoring.png) | ![toxicity](/RecDP/resources/toxicity_analysis.png)| ![perxicity](/RecDP/resources/perplexity.png) | | [learn more](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/data_diversity_control.ipynb) | [learn more](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/text_quality_assessment.ipynb) | [learn more](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/toxicity_bias_control.ipynb) | [learn more](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/text_perplexity.ipynb) | + +## RAG Operators +| Type | notebook | Description | +|-------------------------------------------------------------------------------------------------------------| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |-----------------------------| +| [ UrlLoader ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/doc_loader.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/url_loader.ipynb) | extract text from web pages | +| [ RAGTextFix ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_fixer.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/rag_text_fix.ipynb) | Clean up text for LLM RAG to use. | +| [ TextContractionRemove ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_contraction_remove.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/contraction_remove.ipynb) | Expand contractions in the text using the contractions library. | +| [ TextSpellCorrect ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_spell_correct.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/spelling_correction.ipynb) | pelling correction for text using library [textblog](https://textblob.readthedocs.io/en/dev/) | + + ## Getting Start ### Deploy From 02fa82ff80d30fef8b46e697f99e404ed9a24afd Mon Sep 17 00:00:00 2001 From: "Zhang, Chaojun" Date: Wed, 20 Dec 2023 14:35:12 +0000 Subject: [PATCH 05/59] add prepare model before run nltk toenize --- RecDP/tests/test_llmutils_pipelines.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RecDP/tests/test_llmutils_pipelines.py b/RecDP/tests/test_llmutils_pipelines.py index 84aed09c..5ccac644 100644 --- a/RecDP/tests/test_llmutils_pipelines.py +++ b/RecDP/tests/test_llmutils_pipelines.py @@ -276,6 +276,12 @@ def test_llm_rag_pipeline_cnvrg(self): from pyrecdp.primitives.operations import RecursiveUrlLoader,RAGTextFix,CustomerDocumentSplit,TextCustomerFilter,JsonlWriter from pyrecdp.LLM import TextPipeline + def prepare_nltk_model(model, lang): + import nltk + nltk.download('punkt') + + from build.lib.pyrecdp.core.model_utils import prepare_model + prepare_model(model_type="nltk", model_key="nltk_rag_cnvrg", prepare_model_func=prepare_nltk_model) urls = ['https://app.cnvrg.io/docs/', 'https://app.cnvrg.io/docs/core_concepts/python_sdk_v2.html', 'https://app.cnvrg.io/docs/cli_v2/cnvrgv2_cli.html', From 3204fa25d4b8c4b92078af26b7d49b23582b9902 Mon Sep 17 00:00:00 2001 From: "Zhang, Chaojun" Date: Wed, 20 Dec 2023 15:15:40 +0000 Subject: [PATCH 06/59] add prepare model before run nltk toenize --- RecDP/tests/test_llmutils_pipelines.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecDP/tests/test_llmutils_pipelines.py b/RecDP/tests/test_llmutils_pipelines.py index 5ccac644..f4fa6693 100644 --- a/RecDP/tests/test_llmutils_pipelines.py +++ b/RecDP/tests/test_llmutils_pipelines.py @@ -280,7 +280,7 @@ def prepare_nltk_model(model, lang): import nltk nltk.download('punkt') - from build.lib.pyrecdp.core.model_utils import prepare_model + from pyrecdp.core.model_utils import prepare_model prepare_model(model_type="nltk", model_key="nltk_rag_cnvrg", prepare_model_func=prepare_nltk_model) urls = ['https://app.cnvrg.io/docs/', 'https://app.cnvrg.io/docs/core_concepts/python_sdk_v2.html', From cf34392356701d7376b1a0266a7befacfb2cf22a Mon Sep 17 00:00:00 2001 From: Xinyao Wang Date: Wed, 20 Dec 2023 23:42:42 +0800 Subject: [PATCH 07/59] add notebooks --- .../notebooks/llmutils/random_select.ipynb | 765 ++++++++++++++++++ .../notebooks/llmutils/table_summary.ipynb | 644 +++++++++++++++ .../notebooks/llmutils/text_to_qa.ipynb | 641 +++++++++++++++ RecDP/tests/data/llm_data/table.parquet | Bin 0 -> 4541 bytes RecDP/tests/data/llm_data/text.parquet | Bin 0 -> 11951 bytes 5 files changed, 2050 insertions(+) create mode 100644 RecDP/examples/notebooks/llmutils/random_select.ipynb create mode 100644 RecDP/examples/notebooks/llmutils/table_summary.ipynb create mode 100644 RecDP/examples/notebooks/llmutils/text_to_qa.ipynb create mode 100644 RecDP/tests/data/llm_data/table.parquet create mode 100644 RecDP/tests/data/llm_data/text.parquet diff --git a/RecDP/examples/notebooks/llmutils/random_select.ipynb b/RecDP/examples/notebooks/llmutils/random_select.ipynb new file mode 100644 index 00000000..ce09acf8 --- /dev/null +++ b/RecDP/examples/notebooks/llmutils/random_select.ipynb @@ -0,0 +1,765 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "xqO9S27psEaG", + "metadata": { + "id": "xqO9S27psEaG" + }, + "source": [ + "# RecDP LLM - random select\n", + "\n", + "This component select part of the given dataset." + ] + }, + { + "cell_type": "markdown", + "id": "x19WYyOQsdDq", + "metadata": { + "id": "x19WYyOQsdDq" + }, + "source": [ + "# Get Started" + ] + }, + { + "cell_type": "markdown", + "id": "hNOO3-I-Tgzd", + "metadata": { + "id": "hNOO3-I-Tgzd" + }, + "source": [ + "## 1. Install pyrecdp and dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a", + "metadata": { + "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a" + }, + "outputs": [], + "source": [ + "! DEBIAN_FRONTEND=noninteractive apt-get install -qq -y openjdk-8-jre\n", + "! pip install -q pyrecdp --pre\n", + "# ! pip install 'git+https://github.com/intel/e2eAIOK.git#egg=pyrecdp&subdirectory=RecDP'" + ] + }, + { + "cell_type": "markdown", + "id": "3UMkbvwwT2Vc", + "metadata": { + "id": "3UMkbvwwT2Vc" + }, + "source": [ + "## 2. Prepare your data" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "a368fff6-ef7d-45cd-a7ae-204dfe44aad3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/home/vmagent/app/work/LLM_datapre/e2eAIOK/RecDP/examples/notebooks/llmutils\n" + ] + } + ], + "source": [ + "!pwd" + ] + }, + { + "cell_type": "markdown", + "id": "G3wjx-yItOkR", + "metadata": { + "id": "G3wjx-yItOkR" + }, + "source": [ + "## 3. Random Select" + ] + }, + { + "cell_type": "markdown", + "id": "yAscO0gQWBKa", + "metadata": { + "id": "yAscO0gQWBKa" + }, + "source": [ + "### 3.1 Process with RandomSelect" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "q65vRbH7uJwC", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 396, + "referenced_widgets": [ + "db4260225b4f4c59a65491860c2cfd40", + "c617382f949f41a899a8891abae6ac05", + "793adfc9606547dd95e09534c6a8ee9c", + "53d09e33fd3b4532937a0d383fe28310", + "2910b4043048423b94958349a212d7b6", + "0c1a1de47d404194b50c571744337ab2", + "148574df54a94354a4978cf94be86a76", + "d67f914b86584956b643e5b017ebf2fd", + "9756942b4f9b426897fb92b6b353017d", + "e44de870690644f88c24a0afa74aa54d", + "cfe7ffb4c8194d88aed5c0564b25eef5" + ] + }, + "id": "q65vRbH7uJwC", + "outputId": "7ca9b420-4f1e-48a1-c539-fd5beb0907e7" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "JAVA_HOME is not set, use default value of /usr/lib/jvm/java-8-openjdk-amd64/\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/intel/oneapi/intelpython/latest/envs/llm_data/lib/python3.9/site-packages/pyspark/pandas/__init__.py:50: UserWarning: 'PYARROW_IGNORE_TIMEZONE' environment variable was not set. It is required to set this environment variable to '1' in both driver and executor sides if you use pyarrow>=2.0.0. pandas-on-Spark will set it for you but it does not work if there is a Spark context already launched.\n", + " warnings.warn(\n", + "\u001b[32m2023-12-20 15:31:56.052\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m50\u001b[0m - \u001b[1mcheck_availability_and_install emoji==2.2.0\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[DatasetReader, PerfileSourcedJsonlReader, RandomSelect, PerfileParquetWriter]\n", + "init ray with total mem of 324137904537\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-12-20 15:32:02,088\tWARNING services.py:1889 -- WARNING: The object store is using /tmp instead of /dev/shm because /dev/shm has only 67104768 bytes available. This will harm performance! You may be able to free up space by deleting files in /dev/shm. If you are inside a Docker container, you can increase /dev/shm size by passing '--shm-size=10.24gb' to 'docker run' (or add it to the run_options list in a Ray cluster config). Make sure to set this to more than 30% of available RAM.\n", + "2023-12-20 15:32:03,329\tINFO worker.py:1642 -- Started a local Ray instance.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[32m2023-12-20 15:32:09.036\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.primitives.operations.text_reader\u001b[0m:\u001b[36mget_files_with_subtask\u001b[0m:\u001b[36m136\u001b[0m - \u001b[1mLoad {'': ['tiny_c4_sample.jsonl']} as subtasks from /home/vmagent/app/work/LLM_datapre/e2eAIOK/RecDP/tests/data/llm_data/tiny_c4_sample.jsonl\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-12-20 15:32:10,219\tINFO read_api.py:406 -- To satisfy the requested parallelism of 192, each read task output is split into 192 smaller blocks.\n", + "2023-12-20 15:32:10,263\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[ReadJSON->SplitBlocks(192)] -> TaskPoolMapOperator[Map()->Map()->MapBatches()]\n", + "2023-12-20 15:32:10,266\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 15:32:10,268\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/json": { + "ascii": false, + "bar_format": null, + "colour": null, + "elapsed": 0.011101484298706055, + "initial": 0, + "n": 0, + "ncols": null, + "nrows": null, + "postfix": null, + "prefix": "Running 0", + "rate": null, + "total": 36864, + "unit": "it", + "unit_divisor": 1000, + "unit_scale": false + }, + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/36864 [00:00 TaskPoolMapOperator[ReadJSON->SplitBlocks(192)] -> TaskPoolMapOperator[Map()->Map()->MapBatches()->MapBatches(process_batch)->Write]\n", + "2023-12-20 15:32:15,602\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 15:32:15,604\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/json": { + "ascii": false, + "bar_format": null, + "colour": null, + "elapsed": 0.00648188591003418, + "initial": 0, + "n": 0, + "ncols": null, + "nrows": null, + "postfix": null, + "prefix": "Running 0", + "rate": null, + "total": 36864, + "unit": "it", + "unit_divisor": 1000, + "unit_scale": false + }, + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/36864 [00:00\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
textmetasource_id
0lorazepam nombre comercial mexico From an inte...{\"timestamp\":\"2019-04-24T02:17:53Z\",\"url\":\"htt...tiny_c4_sample.jsonl
1It is possible to love someone who does not lo...{\"timestamp\":\"2019-04-23T06:32:35Z\",\"url\":\"htt...tiny_c4_sample.jsonl
1After tipping 25 tokens in a day, you'll be ab...{\"timestamp\":\"2019-04-20T00:25:13Z\",\"url\":\"htt...tiny_c4_sample.jsonl
2When cute redhead Lola Fae gets caught flickin...{\"timestamp\":\"2019-04-19T10:57:45Z\",\"url\":\"htt...tiny_c4_sample.jsonl
2Judah Ben-Hur lives as a rich Jewish prince an...{\"timestamp\":\"2019-04-25T04:09:20Z\",\"url\":\"htt...tiny_c4_sample.jsonl
\n", + "" + ], + "text/plain": [ + " text \\\n", + "0 lorazepam nombre comercial mexico From an inte... \n", + "1 It is possible to love someone who does not lo... \n", + "1 After tipping 25 tokens in a day, you'll be ab... \n", + "2 When cute redhead Lola Fae gets caught flickin... \n", + "2 Judah Ben-Hur lives as a rich Jewish prince an... \n", + "\n", + " meta source_id \n", + "0 {\"timestamp\":\"2019-04-24T02:17:53Z\",\"url\":\"htt... tiny_c4_sample.jsonl \n", + "1 {\"timestamp\":\"2019-04-23T06:32:35Z\",\"url\":\"htt... tiny_c4_sample.jsonl \n", + "1 {\"timestamp\":\"2019-04-20T00:25:13Z\",\"url\":\"htt... tiny_c4_sample.jsonl \n", + "2 {\"timestamp\":\"2019-04-19T10:57:45Z\",\"url\":\"htt... tiny_c4_sample.jsonl \n", + "2 {\"timestamp\":\"2019-04-25T04:09:20Z\",\"url\":\"htt... tiny_c4_sample.jsonl " + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "import os\n", + "data_pd = pd.read_parquet(os.path.join(out_path,\"tiny_c4_sample.jsonl\"))\n", + "data_pd.head()" + ] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "0c1a1de47d404194b50c571744337ab2": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "148574df54a94354a4978cf94be86a76": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "2910b4043048423b94958349a212d7b6": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "53d09e33fd3b4532937a0d383fe28310": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_e44de870690644f88c24a0afa74aa54d", + "placeholder": "​", + "style": "IPY_MODEL_cfe7ffb4c8194d88aed5c0564b25eef5", + "value": " 0/0 [00:00<?, ?it/s]" + } + }, + "793adfc9606547dd95e09534c6a8ee9c": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_d67f914b86584956b643e5b017ebf2fd", + "max": 1, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_9756942b4f9b426897fb92b6b353017d", + "value": 0 + } + }, + "9756942b4f9b426897fb92b6b353017d": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "c617382f949f41a899a8891abae6ac05": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_0c1a1de47d404194b50c571744337ab2", + "placeholder": "​", + "style": "IPY_MODEL_148574df54a94354a4978cf94be86a76", + "value": "" + } + }, + "cfe7ffb4c8194d88aed5c0564b25eef5": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "d67f914b86584956b643e5b017ebf2fd": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": "20px" + } + }, + "db4260225b4f4c59a65491860c2cfd40": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_c617382f949f41a899a8891abae6ac05", + "IPY_MODEL_793adfc9606547dd95e09534c6a8ee9c", + "IPY_MODEL_53d09e33fd3b4532937a0d383fe28310" + ], + "layout": "IPY_MODEL_2910b4043048423b94958349a212d7b6" + } + }, + "e44de870690644f88c24a0afa74aa54d": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/RecDP/examples/notebooks/llmutils/table_summary.ipynb b/RecDP/examples/notebooks/llmutils/table_summary.ipynb new file mode 100644 index 00000000..d6eadfa4 --- /dev/null +++ b/RecDP/examples/notebooks/llmutils/table_summary.ipynb @@ -0,0 +1,644 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "xqO9S27psEaG", + "metadata": { + "id": "xqO9S27psEaG" + }, + "source": [ + "# RecDP LLM - Table Summary\n", + "\n", + "This component is using pretrained large language model to generate summary for a given table." + ] + }, + { + "cell_type": "markdown", + "id": "x19WYyOQsdDq", + "metadata": { + "id": "x19WYyOQsdDq" + }, + "source": [ + "# Get Started" + ] + }, + { + "cell_type": "markdown", + "id": "hNOO3-I-Tgzd", + "metadata": { + "id": "hNOO3-I-Tgzd" + }, + "source": [ + "## 1. Install pyrecdp and dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a", + "metadata": { + "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a" + }, + "outputs": [], + "source": [ + "! DEBIAN_FRONTEND=noninteractive apt-get install -qq -y openjdk-8-jre\n", + "! pip install -q pyrecdp --pre\n", + "# ! pip install 'git+https://github.com/intel/e2eAIOK.git#egg=pyrecdp&subdirectory=RecDP'" + ] + }, + { + "cell_type": "markdown", + "id": "3UMkbvwwT2Vc", + "metadata": { + "id": "3UMkbvwwT2Vc" + }, + "source": [ + "## 2. Prepare your data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d6fX0InLTTXt", + "metadata": { + "id": "d6fX0InLTTXt" + }, + "outputs": [], + "source": [ + "%mkdir -p /content/test_data\n", + "%cd /content/test_data\n", + "!wget https://raw.githubusercontent.com/intel/e2eAIOK/main/RecDP/tests/data/llm_data/table.parquet" + ] + }, + { + "cell_type": "markdown", + "id": "G3wjx-yItOkR", + "metadata": { + "id": "G3wjx-yItOkR" + }, + "source": [ + "## 3. Table Summary" + ] + }, + { + "cell_type": "markdown", + "id": "yAscO0gQWBKa", + "metadata": { + "id": "yAscO0gQWBKa" + }, + "source": [ + "### 3.1 Process with TableSummary" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "q65vRbH7uJwC", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 396, + "referenced_widgets": [ + "db4260225b4f4c59a65491860c2cfd40", + "c617382f949f41a899a8891abae6ac05", + "793adfc9606547dd95e09534c6a8ee9c", + "53d09e33fd3b4532937a0d383fe28310", + "2910b4043048423b94958349a212d7b6", + "0c1a1de47d404194b50c571744337ab2", + "148574df54a94354a4978cf94be86a76", + "d67f914b86584956b643e5b017ebf2fd", + "9756942b4f9b426897fb92b6b353017d", + "e44de870690644f88c24a0afa74aa54d", + "cfe7ffb4c8194d88aed5c0564b25eef5" + ] + }, + "id": "q65vRbH7uJwC", + "outputId": "7ca9b420-4f1e-48a1-c539-fd5beb0907e7" + }, + "outputs": [], + "source": [ + "from pyrecdp.LLM import TextPipeline, ResumableTextPipeline\n", + "from pyrecdp.primitives.operations import *\n", + "\n", + "pipeline = ResumableTextPipeline(engine_name=\"spark\")\n", + "pipeline.enable_statistics()\n", + "data_path=\"/content/test_data/table.parquet\"\n", + "text_key = \"text_prompt\"\n", + "model_name=\"openchat_3.5-7b\"\n", + "out_path = \"ResumableTextPipeline_output\"\n", + "ops = [\n", + " ParquetReader(data_path),\n", + " TextPrompt(dataset_name=\"text\", prompt_name=\"table_summary\",new_name=text_key),\n", + " TableSummary(model_name=model_name,text_key=text_key),\n", + " ParquetWriter(out_path)\n", + "]\n", + "pipeline.add_operations(ops)\n", + "ret = pipeline.execute()\n", + "del pipeline" + ] + }, + { + "cell_type": "markdown", + "id": "Lt5IM4guvKt6", + "metadata": { + "id": "Lt5IM4guvKt6" + }, + "source": [ + "### 3.2 View processed data" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "DWJpiKfzvQ0o", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 206 + }, + "id": "DWJpiKfzvQ0o", + "outputId": "a5e56303-68fc-492f-f89b-de34508bc15c" + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
texttext_promptsummary
0Business Unit Revenue and Trends Q4 2022 vs. Q...I will give you a table, please read and give ...\\n\\nThe table shows the revenue and trends of ...
1Key Business Unit Revenue and Trends Q3 2022 v...I will give you a table, please read and give ...\\n\\nIn Q3 2022, Intel Corporation reported a d...
\n", + "
" + ], + "text/plain": [ + " text \\\n", + "0 Business Unit Revenue and Trends Q4 2022 vs. Q... \n", + "1 Key Business Unit Revenue and Trends Q3 2022 v... \n", + "\n", + " text_prompt \\\n", + "0 I will give you a table, please read and give ... \n", + "1 I will give you a table, please read and give ... \n", + "\n", + " summary \n", + "0 \\n\\nThe table shows the revenue and trends of ... \n", + "1 \\n\\nIn Q3 2022, Intel Corporation reported a d... " + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "data_pd = pd.read_parquet(out_path)\n", + "data_pd.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "87a4fe83-3293-4260-8657-da087d99b2fd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Business Unit Revenue and Trends Q4 2022 vs. Q4 2021 2022 vs. 2021\\nClient Computing Group (CCG) $6.6 billion down 36% $31.7 billion down 23%\\nData Center and AI (DCAI) $4.3 billion down 33% $19.2 billion down 15%\\nNetwork and Edge (NEX) $2.1 billion down 1% $8.9 billion up11%\\nMobileye $565 million up59% $1.9 billion up35%\\nAccelerated Computing Systems and Graphics (AXG) $247 million up1% $837 million up8%\\nIntel Foundry Services (IFS) $319 million up30% $895 million up14%\\n'" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data_pd.iloc[0][\"text\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "72714596-f766-426b-be87-0a361ea779a6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "\"\\n\\nThe table shows the revenue and trends of Intel's business units for Q4 2022 and Q4 2021, as well as the yearly comparison between 2022 and 2021. The Client Computing Group (CCG) experienced a 36% decrease in revenue in Q4 2022 compared to Q4 2021, and a 23% decrease in revenue compared to 2021. The Data Center and AI (DCAI) unit saw a 33% drop in revenue in Q4 2022 compared to Q4 2021, and a 15% decrease compared to 2021. The Network and Edge (NEX) unit experienced a 1% decrease in revenue in Q4 2022 compared to Q4 2021, but a 11% increase compared to 2021. The Mobileye unit saw a 59% increase in revenue in Q4 2022 compared to Q4 2021, and a 35% increase compared to 2021. The Accelerated Computing Systems and Graphics (AXG) unit experienced a 1% increase in revenue in Q4 2022 compared to Q4 2021, and an 8% increase compared to 2021. The Intel Foundry Services (IFS) unit saw a 30% increase in revenue in Q4 2022 compared to Q4 2021, and a 14% increase compared to 2021. The Internet of Things Group (IOTG) experienced a 1% decrease in revenue in Q4 2022 compared to Q4 2021, and a 1% decrease compared to 2021. The total revenue for all business units was down 23% in Q4 2022 compared to Q4 2021, and down 10% compared to 2021.\\n\\nThe table provides a comprehensive overview of Intel's business unit performance for Q4 2022 and Q4 2021, as well as the yearly comparison between 2022 and 2021. The Client Computing Group and Data Center and AI units experienced significant revenue decreases, while the Network and Edge, Mobileye, Accelerated Computing Systems and Graphics, and Intel Foundry Services units saw varying degrees of growth. The Internet of Things Group remained relatively stable in terms of revenue. Overall, Intel's total revenue was down 23% in Q4 2022 compared to Q4 2021, and down 10% compared to 2021.\\n\\n\"" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data_pd.iloc[0][\"summary\"]" + ] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "0c1a1de47d404194b50c571744337ab2": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "148574df54a94354a4978cf94be86a76": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "2910b4043048423b94958349a212d7b6": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "53d09e33fd3b4532937a0d383fe28310": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_e44de870690644f88c24a0afa74aa54d", + "placeholder": "​", + "style": "IPY_MODEL_cfe7ffb4c8194d88aed5c0564b25eef5", + "value": " 0/0 [00:00<?, ?it/s]" + } + }, + "793adfc9606547dd95e09534c6a8ee9c": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_d67f914b86584956b643e5b017ebf2fd", + "max": 1, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_9756942b4f9b426897fb92b6b353017d", + "value": 0 + } + }, + "9756942b4f9b426897fb92b6b353017d": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "c617382f949f41a899a8891abae6ac05": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_0c1a1de47d404194b50c571744337ab2", + "placeholder": "​", + "style": "IPY_MODEL_148574df54a94354a4978cf94be86a76", + "value": "" + } + }, + "cfe7ffb4c8194d88aed5c0564b25eef5": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "d67f914b86584956b643e5b017ebf2fd": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": "20px" + } + }, + "db4260225b4f4c59a65491860c2cfd40": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_c617382f949f41a899a8891abae6ac05", + "IPY_MODEL_793adfc9606547dd95e09534c6a8ee9c", + "IPY_MODEL_53d09e33fd3b4532937a0d383fe28310" + ], + "layout": "IPY_MODEL_2910b4043048423b94958349a212d7b6" + } + }, + "e44de870690644f88c24a0afa74aa54d": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/RecDP/examples/notebooks/llmutils/text_to_qa.ipynb b/RecDP/examples/notebooks/llmutils/text_to_qa.ipynb new file mode 100644 index 00000000..66f7fbca --- /dev/null +++ b/RecDP/examples/notebooks/llmutils/text_to_qa.ipynb @@ -0,0 +1,641 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "xqO9S27psEaG", + "metadata": { + "id": "xqO9S27psEaG" + }, + "source": [ + "# RecDP LLM - TextToQA\n", + "\n", + "This component is using pretrained large language model to generate QA dataset for a given text" + ] + }, + { + "cell_type": "markdown", + "id": "x19WYyOQsdDq", + "metadata": { + "id": "x19WYyOQsdDq" + }, + "source": [ + "# Get Started" + ] + }, + { + "cell_type": "markdown", + "id": "hNOO3-I-Tgzd", + "metadata": { + "id": "hNOO3-I-Tgzd" + }, + "source": [ + "## 1. Install pyrecdp and dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a", + "metadata": { + "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a" + }, + "outputs": [], + "source": [ + "! DEBIAN_FRONTEND=noninteractive apt-get install -qq -y openjdk-8-jre\n", + "! pip install -q pyrecdp --pre\n", + "# ! pip install 'git+https://github.com/intel/e2eAIOK.git#egg=pyrecdp&subdirectory=RecDP'" + ] + }, + { + "cell_type": "markdown", + "id": "3UMkbvwwT2Vc", + "metadata": { + "id": "3UMkbvwwT2Vc" + }, + "source": [ + "## 2. Prepare your data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d6fX0InLTTXt", + "metadata": { + "id": "d6fX0InLTTXt" + }, + "outputs": [], + "source": [ + "%mkdir -p /content/test_data\n", + "%cd /content/test_data\n", + "!wget https://raw.githubusercontent.com/intel/e2eAIOK/main/RecDP/tests/data/llm_data/text.parquet" + ] + }, + { + "cell_type": "markdown", + "id": "G3wjx-yItOkR", + "metadata": { + "id": "G3wjx-yItOkR" + }, + "source": [ + "## 3. Generate QA from text" + ] + }, + { + "cell_type": "markdown", + "id": "yAscO0gQWBKa", + "metadata": { + "id": "yAscO0gQWBKa" + }, + "source": [ + "### 3.1 Process with TextToQA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "q65vRbH7uJwC", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 396, + "referenced_widgets": [ + "db4260225b4f4c59a65491860c2cfd40", + "c617382f949f41a899a8891abae6ac05", + "793adfc9606547dd95e09534c6a8ee9c", + "53d09e33fd3b4532937a0d383fe28310", + "2910b4043048423b94958349a212d7b6", + "0c1a1de47d404194b50c571744337ab2", + "148574df54a94354a4978cf94be86a76", + "d67f914b86584956b643e5b017ebf2fd", + "9756942b4f9b426897fb92b6b353017d", + "e44de870690644f88c24a0afa74aa54d", + "cfe7ffb4c8194d88aed5c0564b25eef5" + ] + }, + "id": "q65vRbH7uJwC", + "outputId": "7ca9b420-4f1e-48a1-c539-fd5beb0907e7" + }, + "outputs": [], + "source": [ + "from pyrecdp.LLM import TextPipeline, ResumableTextPipeline\n", + "from pyrecdp.primitives.operations import *\n", + "\n", + "pipeline = TextPipeline(engine_name=\"spark\")\n", + "data_path=\"/content/test_data/text.parquet\"\n", + "text_key = \"text_prompt\"\n", + "model_name=\"neural-chat-7b-v3\"\n", + "out_path = \"ResumableTextPipeline_output\"\n", + "ops = [\n", + " ParquetReader(data_path),\n", + " # TextPrompt(dataset_name=\"text\", prompt_name=\"generate_qa\",new_name=text_key),\n", + " TextToQA(outdir=out_path,model_name=model_name,text_key=text_key),\n", + " ParquetWriter(out_path)\n", + "]\n", + "pipeline.add_operations(ops)\n", + "ret = pipeline.execute()\n", + "del pipeline" + ] + }, + { + "cell_type": "markdown", + "id": "Lt5IM4guvKt6", + "metadata": { + "id": "Lt5IM4guvKt6" + }, + "source": [ + "### 3.2 View processed data" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "DWJpiKfzvQ0o", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 206 + }, + "id": "DWJpiKfzvQ0o", + "outputId": "a5e56303-68fc-492f-f89b-de34508bc15c" + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
text_promptQA_outputQuestionAnswer
0You will be provided an article. After reading...Question: What change in the estimated useful ...What change in the estimated useful life of c...In January 2023, Intel increased the estimate...
1You will be provided an article. After reading...Question: What change in the estimated useful ...How did this change affect Intel's financial ...The change is expected to reduce total deprec...
2You will be provided an article. After reading...Question: What change in the estimated useful ...What is the purpose of Intel's Q1 2023 outloo...Intel estimates a $350 million to $500 millio...
3You will be provided an article. After reading...Question: What change in the estimated useful ...When did Intel hold a public webcast to discu...Intel held a public webcast at 2 p.m. PST on ...
4You will be provided an article. After reading...Question: What change in the estimated useful ...Where can the live public webcast, earnings p...The live public webcast, earnings presentatio...
\n", + "
" + ], + "text/plain": [ + " text_prompt \\\n", + "0 You will be provided an article. After reading... \n", + "1 You will be provided an article. After reading... \n", + "2 You will be provided an article. After reading... \n", + "3 You will be provided an article. After reading... \n", + "4 You will be provided an article. After reading... \n", + "\n", + " QA_output \\\n", + "0 Question: What change in the estimated useful ... \n", + "1 Question: What change in the estimated useful ... \n", + "2 Question: What change in the estimated useful ... \n", + "3 Question: What change in the estimated useful ... \n", + "4 Question: What change in the estimated useful ... \n", + "\n", + " Question \\\n", + "0 What change in the estimated useful life of c... \n", + "1 How did this change affect Intel's financial ... \n", + "2 What is the purpose of Intel's Q1 2023 outloo... \n", + "3 When did Intel hold a public webcast to discu... \n", + "4 Where can the live public webcast, earnings p... \n", + "\n", + " Answer \n", + "0 In January 2023, Intel increased the estimate... \n", + "1 The change is expected to reduce total deprec... \n", + "2 Intel estimates a $350 million to $500 millio... \n", + "3 Intel held a public webcast at 2 p.m. PST on ... \n", + "4 The live public webcast, earnings presentatio... " + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "data_pd = pd.read_parquet(out_path)\n", + "data_pd.head()" + ] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "0c1a1de47d404194b50c571744337ab2": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "148574df54a94354a4978cf94be86a76": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "2910b4043048423b94958349a212d7b6": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "53d09e33fd3b4532937a0d383fe28310": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_e44de870690644f88c24a0afa74aa54d", + "placeholder": "​", + "style": "IPY_MODEL_cfe7ffb4c8194d88aed5c0564b25eef5", + "value": " 0/0 [00:00<?, ?it/s]" + } + }, + "793adfc9606547dd95e09534c6a8ee9c": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_d67f914b86584956b643e5b017ebf2fd", + "max": 1, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_9756942b4f9b426897fb92b6b353017d", + "value": 0 + } + }, + "9756942b4f9b426897fb92b6b353017d": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "c617382f949f41a899a8891abae6ac05": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_0c1a1de47d404194b50c571744337ab2", + "placeholder": "​", + "style": "IPY_MODEL_148574df54a94354a4978cf94be86a76", + "value": "" + } + }, + "cfe7ffb4c8194d88aed5c0564b25eef5": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "d67f914b86584956b643e5b017ebf2fd": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": "20px" + } + }, + "db4260225b4f4c59a65491860c2cfd40": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_c617382f949f41a899a8891abae6ac05", + "IPY_MODEL_793adfc9606547dd95e09534c6a8ee9c", + "IPY_MODEL_53d09e33fd3b4532937a0d383fe28310" + ], + "layout": "IPY_MODEL_2910b4043048423b94958349a212d7b6" + } + }, + "e44de870690644f88c24a0afa74aa54d": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/RecDP/tests/data/llm_data/table.parquet b/RecDP/tests/data/llm_data/table.parquet new file mode 100644 index 0000000000000000000000000000000000000000..8ab0965a764fbd5489e5fc8c4b34907737b92f43 GIT binary patch literal 4541 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 z Date: Wed, 20 Dec 2023 20:49:05 +0000 Subject: [PATCH 08/59] add notebook for document loader, document split and document ingestion --- .../notebooks/llmutils/document_extract.ipynb | 971 ++++++++++++-- .../llmutils/document_ingestion.ipynb | 944 ++++++++++++++ .../notebooks/llmutils/document_split.ipynb | 1130 ++++++++++++++++- RecDP/pyrecdp/LLM/README.md | 7 +- .../primitives/llmutils/document/reader.py | 15 +- .../primitives/operations/text_ingestion.py | 13 +- RecDP/tests/test_llmutils_operations.py | 7 +- 7 files changed, 2983 insertions(+), 104 deletions(-) create mode 100644 RecDP/examples/notebooks/llmutils/document_ingestion.ipynb diff --git a/RecDP/examples/notebooks/llmutils/document_extract.ipynb b/RecDP/examples/notebooks/llmutils/document_extract.ipynb index eb7eb627..d11cb112 100644 --- a/RecDP/examples/notebooks/llmutils/document_extract.ipynb +++ b/RecDP/examples/notebooks/llmutils/document_extract.ipynb @@ -95,7 +95,7 @@ "id": "dhrC92TbIriM" }, "source": [ - "## 3. convert data" + "## 3. load documents" ] }, { @@ -105,12 +105,12 @@ "id": "MLj8YsmXgKFa" }, "source": [ - "#### 3.1 convert pdf" + "#### 3.1 load pdf documents" ] }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 1, "id": "bKDlmC0CdlGY", "metadata": { "colab": { @@ -124,28 +124,63 @@ "name": "stdout", "output_type": "stream", "text": [ - "Document extract for '/content/test_data/document/layout-parser-paper.pdf' with [glob=**/*.pdf, required_exts=None, recursive=False, multithread=False] started ...\n" + "_get_loader\n", + "\u001b[32m2023-12-20 14:52:16.382\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pypdf\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "_get_loader\n", + "\u001b[32m2023-12-20 14:52:16.469\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pypdf\u001b[0m\n", + "init ray\n", + "init ray with total mem of 324413575987, total core of 48\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 1/1 [00:00<00:00, 3.16it/s]" + "2023-12-20 14:52:21,156\tINFO worker.py:1642 -- Started a local Ray instance.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "Document extract for '/content/test_data/document/layout-parser-paper.pdf' with [glob=**/*.pdf, required_exts=None, recursive=False, multithread=False] took 0.32126119174063206 sec\n" + "execute with ray started ...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\n" + "100%|██████████| 1/1 [00:00<00:00, 2.85it/s]\n", + "2023-12-20 14:52:22,927\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Write]\n", + "2023-12-20 14:52:22,932\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 14:52:22,933\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1defe0fb210a4084b4b8967891df4251", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/1 [00:00\n", " \n", " 0\n", - " LayoutParser : A Unified Toolkit for Deep\\nLear...\n", + " \\n\\n LayoutParser : A Unified Toolkit for Deep\\...\n", " {'source': '/content/test_data/document/layout...\n", " \n", " \n", @@ -184,27 +219,37 @@ "" ], "text/plain": [ - " text \\\n", - "0 LayoutParser : A Unified Toolkit for Deep\\nLear... \n", - "\n", - " metadata \n", - "0 {'source': '/content/test_data/document/layout... " + " text metadata\n", + "0 \\n\\n LayoutParser : A Unified Toolkit for Deep\\... {'source': '/content/test_data/document/layout..." ] }, "metadata": {}, "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 14:52:30,040 E 2010245 2010266] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_14-52-18_287180_2002748 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 14:52:40,054 E 2010245 2010266] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_14-52-18_287180_2002748 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 14:52:50,065 E 2010245 2010266] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_14-52-18_287180_2002748 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 14:53:00,079 E 2010245 2010266] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_14-52-18_287180_2002748 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 14:53:10,093 E 2010245 2010266] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_14-52-18_287180_2002748 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] } ], "source": [ - "from pyrecdp.primitives.llmutils.document_extractor import pdf_to_text\n", - "import pandas as pd\n", - "\n", - "file_name = \"layout-parser-paper.pdf\"\n", - "in_file = \"/content/test_data/document/\" + file_name\n", - "out_file = \"/content/doc_jsonl/\" + file_name + \".jsonl\"\n", - "pdf_to_text(in_file, out_file)\n", - "display(pd.read_json(out_file, lines=True))\n", + "from pyrecdp.primitives.operations import DirectoryLoader\n", "\n", + "from pyrecdp.LLM import TextPipeline\n", + " \n", + "pipeline = TextPipeline()\n", + "ops = [\n", + " DirectoryLoader(input_dir=\"/content/test_data/document\", glob=\"**/*.pdf\")\n", + "]\n", + "pipeline.add_operations(ops)\n", + "ds = pipeline.execute()\n", + "display(ds.to_pandas())\n", " " ] }, @@ -215,12 +260,12 @@ "id": "UAWi-jXFgXuy" }, "source": [ - "#### 3.2 convert docx" + "#### 3.2 load word documents" ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 2, "id": "pWl-ym01ga9D", "metadata": { "colab": { @@ -234,28 +279,57 @@ "name": "stdout", "output_type": "stream", "text": [ - "Document extract for '/content/test_data/document/handbook-872p.docx' with [glob=**/*.docx, required_exts=None, recursive=False, multithread=False] started ...\n" + "_get_loader\n", + "\u001b[32m2023-12-20 14:53:12.711\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install python-docx\u001b[0m\n", + "_get_loader\n", + "\u001b[32m2023-12-20 14:53:12.803\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install python-docx\u001b[0m\n", + "init ray\n", + "init ray with total mem of 324413575987, total core of 48\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 1/1 [00:00<00:00, 1.94it/s]" + "2023-12-20 14:53:17,517\tINFO worker.py:1642 -- Started a local Ray instance.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "Document extract for '/content/test_data/document/handbook-872p.docx' with [glob=**/*.docx, required_exts=None, recursive=False, multithread=False] took 0.520426164381206 sec\n" + "execute with ray started ...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\n" + "100%|██████████| 1/1 [00:00<00:00, 1.64it/s]\n", + "2023-12-20 14:53:19,445\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Write]\n", + "2023-12-20 14:53:19,448\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 14:53:19,450\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "34082bbc3a274e59961eea59b5059b3a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/1 [00:00\n", " \n", " 0\n", - " U.S. Department of Justice\\nExecutive Office f...\n", + " \\n\\n U.S. Department of Justice\\n\\n Executive ...\n", " {'source': '/content/test_data/document/handbo...\n", " \n", " \n", @@ -294,27 +368,33 @@ "" ], "text/plain": [ - " text \\\n", - "0 U.S. Department of Justice\\nExecutive Office f... \n", - "\n", - " metadata \n", - "0 {'source': '/content/test_data/document/handbo... " + " text metadata\n", + "0 \\n\\n U.S. Department of Justice\\n\\n Executive ... {'source': '/content/test_data/document/handbo..." ] }, "metadata": {}, "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 14:53:26,399 E 2015878 2015899] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_14-53-14_626786_2002748 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] } ], "source": [ - "from pyrecdp.primitives.llmutils.document_extractor import docx_to_text\n", - "import pandas as pd\n", - "\n", - "file_name = \"handbook-872p.docx\"\n", - "in_file = \"/content/test_data/document/\" + file_name\n", - "out_file = \"/content/doc_jsonl/\" + file_name + \".jsonl\"\n", - "docx_to_text(in_file, out_file)\n", + "from pyrecdp.primitives.operations import DirectoryLoader\n", "\n", - "display(pd.read_json(out_file, lines=True))" + "from pyrecdp.LLM import TextPipeline\n", + " \n", + "pipeline = TextPipeline()\n", + "ops = [\n", + " DirectoryLoader(input_dir=\"/content/test_data/document\", glob=\"**/*.docx\")\n", + "]\n", + "pipeline.add_operations(ops)\n", + "ds = pipeline.execute()\n", + "display(ds.to_pandas())" ] }, { @@ -324,12 +404,12 @@ "id": "fUrG8v1Og7Tb" }, "source": [ - "#### 3.3 convert images" + "#### 3.3 load images" ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 3, "id": "0bowqv7Ag7hI", "metadata": { "colab": { @@ -343,28 +423,130 @@ "name": "stdout", "output_type": "stream", "text": [ - "Document extract for '/content/test_data/document/layout-parser-paper-10p.jpg' with [glob=**/*.*, required_exts=['.jpeg', '.jpg', '.png'], recursive=False, multithread=False] started ...\n" + "_get_loader\n", + "Reading package lists...\n", + "Building dependency tree...\n", + "Reading state information...\n", + "tesseract-ocr is already the newest version (4.1.1-2.1build1).\n", + "0 upgraded, 0 newly installed, 0 to remove and 134 not upgraded.\n", + "\u001b[32m2023-12-20 14:53:36.861\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pillow\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.\n", + "Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.\n", + "To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.\n" + ] + }, + { + "data": { + "text/html": [ + "
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n", + "\u001b[0m" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[32m2023-12-20 14:53:46.379\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pytesseract\u001b[0m\n", + "_get_loader\n", + "Reading package lists...\n", + "Building dependency tree...\n", + "Reading state information...\n", + "tesseract-ocr is already the newest version (4.1.1-2.1build1).\n", + "0 upgraded, 0 newly installed, 0 to remove and 134 not upgraded.\n", + "\u001b[32m2023-12-20 14:53:46.933\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pillow\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 1/1 [00:31<00:00, 31.67s/it]" + "WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.\n", + "Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.\n", + "To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.\n" ] }, + { + "data": { + "text/html": [ + "
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n", + "\u001b[0m" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "name": "stdout", "output_type": "stream", "text": [ - "Document extract for '/content/test_data/document/layout-parser-paper-10p.jpg' with [glob=**/*.*, required_exts=['.jpeg', '.jpg', '.png'], recursive=False, multithread=False] took 31.676521027460694 sec\n" + "\u001b[32m2023-12-20 14:53:54.602\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pytesseract\u001b[0m\n", + "init ray\n", + "init ray with total mem of 324413575987, total core of 48\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\n" + "2023-12-20 14:53:59,250\tINFO worker.py:1642 -- Started a local Ray instance.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "execute with ray started ...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + " 0%| | 0/1 [00:00 TaskPoolMapOperator[Write]\n", + "2023-12-20 14:54:35,492\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 14:54:35,493\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "456480681a1143d7940f174694d8ddf1", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/1 [00:00\n", " \n", " 0\n", - " 2103.15348v2 [cs.CV] 21 Jun 2021\\n\\narXiv\\n\\nL...\n", + " 2103.15348v2 [cs.CV] 21 Jun 2021\\n\\narXiv\\n\\n...\n", " {'source': '/content/test_data/document/layout...\n", " \n", " \n", @@ -403,27 +585,33 @@ "" ], "text/plain": [ - " text \\\n", - "0 2103.15348v2 [cs.CV] 21 Jun 2021\\n\\narXiv\\n\\nL... \n", - "\n", - " metadata \n", - "0 {'source': '/content/test_data/document/layout... " + " text metadata\n", + "0 2103.15348v2 [cs.CV] 21 Jun 2021\\n\\narXiv\\n\\n... {'source': '/content/test_data/document/layout..." ] }, "metadata": {}, "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 14:54:38,262 E 2021288 2021308] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_14-53-56_430977_2002748 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] } ], "source": [ - "from pyrecdp.primitives.llmutils.document_extractor import image_to_text\n", - "import pandas as pd\n", - "\n", - "file_name = \"layout-parser-paper-10p.jpg\"\n", - "in_file = \"/content/test_data/document/\" + file_name\n", - "out_file = \"/content/doc_jsonl/\" + file_name + \".jsonl\"\n", - "image_to_text(in_file, out_file)\n", + "from pyrecdp.primitives.operations import DirectoryLoader\n", "\n", - "display(pd.read_json(out_file, lines=True))" + "from pyrecdp.LLM import TextPipeline\n", + " \n", + "pipeline = TextPipeline()\n", + "ops = [\n", + " DirectoryLoader(input_dir=\"/content/test_data/document\", glob=\"**/*.jpg\")\n", + "]\n", + "pipeline.add_operations(ops)\n", + "ds = pipeline.execute()\n", + "display(ds.to_pandas())" ] }, { @@ -433,12 +621,12 @@ "id": "yzrS5hVsl8QZ" }, "source": [ - "#### 3.4 convert entire directory" + "#### 3.4 load entire directory" ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 1, "id": "wXR8_zDUdy2w", "metadata": { "colab": { @@ -448,32 +636,221 @@ "outputId": "77c2a54d-509b-4c54-e3de-8b51fefff080" }, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/pyspark/pandas/__init__.py:50: UserWarning: 'PYARROW_IGNORE_TIMEZONE' environment variable was not set. It is required to set this environment variable to '1' in both driver and executor sides if you use pyarrow>=2.0.0. pandas-on-Spark will set it for you but it does not work if there is a Spark context already launched.\n", + " warnings.warn(\n", + "\u001b[32m2023-12-20 15:20:13.169\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install emoji==2.2.0\u001b[0m\n" + ] + }, { "name": "stdout", "output_type": "stream", "text": [ - "Document extract for '/content/test_data/document/' with [glob=**/*.*, required_exts=None, recursive=False, multithread=True] started ...\n" + "_get_loader\n", + "Reading package lists...\n", + "Building dependency tree...\n", + "Reading state information...\n", + "tesseract-ocr is already the newest version (4.1.1-2.1build1).\n", + "0 upgraded, 0 newly installed, 0 to remove and 134 not upgraded.\n", + "\u001b[32m2023-12-20 15:20:13.692\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pillow\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 40/40 [00:32<00:00, 1.22it/s]" + "WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.\n", + "Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.\n", + "To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.\n" ] }, + { + "data": { + "text/html": [ + "
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n", + "\u001b[0m" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "name": "stdout", "output_type": "stream", "text": [ - "Document extract for '/content/test_data/document/' with [glob=**/*.*, required_exts=None, recursive=False, multithread=True] took 32.91086395457387 sec\n" + "\u001b[32m2023-12-20 15:20:23.167\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pytesseract\u001b[0m\n", + "\u001b[32m2023-12-20 15:20:23.172\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pypdf\u001b[0m\n", + "\u001b[32m2023-12-20 15:20:23.382\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install python-docx\u001b[0m\n", + "Reading package lists...\n", + "Building dependency tree...\n", + "Reading state information...\n", + "tesseract-ocr is already the newest version (4.1.1-2.1build1).\n", + "0 upgraded, 0 newly installed, 0 to remove and 134 not upgraded.\n", + "\u001b[32m2023-12-20 15:20:23.902\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pillow\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\n" + "WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.\n", + "Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.\n", + "To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.\n" + ] + }, + { + "data": { + "text/html": [ + "
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n", + "\u001b[0m" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[32m2023-12-20 15:20:31.290\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pytesseract\u001b[0m\n", + "_get_loader\n", + "Reading package lists...\n", + "Building dependency tree...\n", + "Reading state information...\n", + "tesseract-ocr is already the newest version (4.1.1-2.1build1).\n", + "0 upgraded, 0 newly installed, 0 to remove and 134 not upgraded.\n", + "\u001b[32m2023-12-20 15:20:31.823\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pillow\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.\n", + "Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.\n", + "To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.\n" + ] + }, + { + "data": { + "text/html": [ + "
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n", + "\u001b[0m" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[32m2023-12-20 15:20:38.180\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pytesseract\u001b[0m\n", + "\u001b[32m2023-12-20 15:20:38.183\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pypdf\u001b[0m\n", + "\u001b[32m2023-12-20 15:20:38.185\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install python-docx\u001b[0m\n", + "Reading package lists...\n", + "Building dependency tree...\n", + "Reading state information...\n", + "tesseract-ocr is already the newest version (4.1.1-2.1build1).\n", + "0 upgraded, 0 newly installed, 0 to remove and 134 not upgraded.\n", + "\u001b[32m2023-12-20 15:20:38.670\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pillow\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.\n", + "Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.\n", + "To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.\n" + ] + }, + { + "data": { + "text/html": [ + "
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n", + "\u001b[0m" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[32m2023-12-20 15:20:52.243\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install pytesseract\u001b[0m\n", + "init ray\n", + "init ray with total mem of 324413575987, total core of 48\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-12-20 15:20:56,945\tINFO worker.py:1642 -- Started a local Ray instance.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "execute with ray started ...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + " 92%|█████████▎| 37/40 [00:00<00:00, 91.06it/s]\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:21:05,827 E 2140220 2140243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-20-54_049751_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:21:15,838 E 2140220 2140243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-20-54_049751_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + " 98%|█████████▊| 39/40 [00:19<00:00, 91.06it/s]\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:21:25,850 E 2140220 2140243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-20-54_049751_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "100%|██████████| 40/40 [00:35<00:00, 1.13it/s]\n", + "2023-12-20 15:21:33,755\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Write]\n", + "2023-12-20 15:21:33,757\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 15:21:33,758\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f83689225b41469a8d7c1b59f24f81bb", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/4 [00:00\n", " \n", " 0\n", - " RULES AND INSTRUCTIONS\\n\\n1. Template for day ...\n", + " \\n\\n RULES AND INSTRUCTIONS\\n\\n1. Template for...\n", " {'source': '/content/test_data/document/englis...\n", " \n", " \n", " 1\n", - " U.S. Department of Justice\\nExecutive Office f...\n", + " \\n\\n U.S. Department of Justice\\n\\n Executive ...\n", " {'source': '/content/test_data/document/handbo...\n", " \n", " \n", " 2\n", - " 2103.15348v2 [cs.CV] 21 Jun 2021\\n\\narXiv\\n\\nL...\n", + " 2103.15348v2 [cs.CV] 21 Jun 2021\\n\\narXiv\\n\\n...\n", " {'source': '/content/test_data/document/layout...\n", " \n", " \n", " 3\n", - " LayoutParser : A Unified Toolkit for Deep\\nLear...\n", + " \\n\\n LayoutParser : A Unified Toolkit for Deep\\...\n", " {'source': '/content/test_data/document/layout...\n", " \n", " \n", @@ -528,10 +905,10 @@ ], "text/plain": [ " text \\\n", - "0 RULES AND INSTRUCTIONS\\n\\n1. Template for day ... \n", - "1 U.S. Department of Justice\\nExecutive Office f... \n", - "2 2103.15348v2 [cs.CV] 21 Jun 2021\\n\\narXiv\\n\\nL... \n", - "3 LayoutParser : A Unified Toolkit for Deep\\nLear... \n", + "0 \\n\\n RULES AND INSTRUCTIONS\\n\\n1. Template for... \n", + "1 \\n\\n U.S. Department of Justice\\n\\n Executive ... \n", + "2 2103.15348v2 [cs.CV] 21 Jun 2021\\n\\narXiv\\n\\n... \n", + "3 \\n\\n LayoutParser : A Unified Toolkit for Deep\\... \n", "\n", " metadata \n", "0 {'source': '/content/test_data/document/englis... \n", @@ -542,15 +919,447 @@ }, "metadata": {}, "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:21:35,862 E 2140220 2140243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-20-54_049751_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:21:45,876 E 2140220 2140243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-20-54_049751_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] + } + ], + "source": [ + "from pyrecdp.primitives.operations import DirectoryLoader\n", + "\n", + "from pyrecdp.LLM import TextPipeline\n", + " \n", + "pipeline = TextPipeline()\n", + "ops = [\n", + " DirectoryLoader(input_dir=\"/content/test_data/document\")\n", + "]\n", + "pipeline.add_operations(ops)\n", + "ds = pipeline.execute()\n", + "display(ds.to_pandas())" + ] + }, + { + "cell_type": "markdown", + "id": "182fe042", + "metadata": {}, + "source": [ + "#### 3.5 Url Loaders with langchain RecusiverUrlLoader" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "71f1ead9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "init ray\n", + "init ray with total mem of 324413575987, total core of 48\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-12-20 15:28:21,062\tINFO worker.py:1642 -- Started a local Ray instance.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "execute with ray started ...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:28:30,032 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:28:40,047 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "2023-12-20 15:28:41,766\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Write]\n", + "2023-12-20 15:28:41,767\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 15:28:41,768\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f30151903fdf42978b4f2166f24e5ce9", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/17 [00:00\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
textmetadata
0<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
1<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
2<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
3<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
4<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
5<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
6<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
7<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
8<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
9<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
10<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
11<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
12<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
13<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
14<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
15<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
16<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
\n", + "" + ], + "text/plain": [ + " text \\\n", + "0 \\n\\n ... \n", + "1 \\n\\n ... \n", + "2 \\n\\n ... \n", + "3 \\n\\n ... \n", + "4 \\n\\n ... \n", + "5 \\n\\n ... \n", + "6 \\n\\n ... \n", + "7 \\n\\n ... \n", + "8 \\n\\n ... \n", + "9 \\n\\n ... \n", + "10 \\n\\n ... \n", + "11 \\n\\n ... \n", + "12 \\n\\n ... \n", + "13 \\n\\n ... \n", + "14 \\n\\n ... \n", + "15 \\n\\n ... \n", + "16 \\n\\n ... \n", + "\n", + " metadata \n", + "0 {'description': 'Documentation website for cnv... \n", + "1 {'description': 'Documentation website for cnv... \n", + "2 {'description': 'Documentation website for cnv... \n", + "3 {'description': 'Documentation website for cnv... \n", + "4 {'description': 'Documentation website for cnv... \n", + "5 {'description': 'Documentation website for cnv... \n", + "6 {'description': 'Documentation website for cnv... \n", + "7 {'description': 'Documentation website for cnv... \n", + "8 {'description': 'Documentation website for cnv... \n", + "9 {'description': 'Documentation website for cnv... \n", + "10 {'description': 'Documentation website for cnv... \n", + "11 {'description': 'Documentation website for cnv... \n", + "12 {'description': 'Documentation website for cnv... \n", + "13 {'description': 'Documentation website for cnv... \n", + "14 {'description': 'Documentation website for cnv... \n", + "15 {'description': 'Documentation website for cnv... \n", + "16 {'description': 'Documentation website for cnv... " + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:28:50,060 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:29:00,074 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:29:10,089 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:29:20,105 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:29:30,116 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:29:40,128 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:29:50,142 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:30:00,153 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:30:10,166 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:30:20,178 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:30:30,192 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:30:40,206 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:30:50,219 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:31:00,233 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:31:10,245 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:31:20,257 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:31:30,271 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:31:40,285 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:31:50,298 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:32:00,312 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:32:10,323 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:32:20,336 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:32:30,349 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:32:40,362 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:32:50,375 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:33:00,386 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:33:10,401 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:33:20,414 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:33:30,428 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:33:40,443 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:33:50,458 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:34:00,471 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:34:10,485 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:34:20,499 E 2159771 2159790] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-28-18_227590_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] } ], "source": [ - "from pyrecdp.primitives.llmutils.document_extractor import document_to_text\n", - "import pandas as pd\n", - "in_file = \"/content/test_data/document/\"\n", - "out_file = \"/content/doc_jsonl/\" + \"document.json\"\n", - "document_to_text(in_file, out_file, use_multithreading=True)\n", - "display(pd.read_json(out_file, lines=True))" + "url = 'https://app.cnvrg.io/docs/'\n", + "\n", + "from pyrecdp.LLM import TextPipeline\n", + "from pyrecdp.primitives.operations import DocumentLoader\n", + "\n", + "pipeline = TextPipeline()\n", + "ops = [\n", + " DocumentLoader(loader='RecursiveUrlLoader', loader_args={\"url\": url}),\n", + "]\n", + "pipeline.add_operations(ops)\n", + "ds = pipeline.execute()\n", + "display(ds.to_pandas())\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "198739a6", + "metadata": {}, + "source": [ + "#### 3.5 Online Pdf loader" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "514d9f03", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "init ray\n", + "init ray with total mem of 324413575987, total core of 48\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-12-20 15:37:49,289\tINFO worker.py:1642 -- Started a local Ray instance.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "execute with ray started ...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:37:58,263 E 2179392 2179417] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-37-46_470728_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "2023-12-20 15:37:58,360\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Write]\n", + "2023-12-20 15:37:58,362\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 15:37:58,363\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6d4d0dd6aa644a6fa584cb901dbad3e3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/1 [00:00\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
textmetadata
03 2 0 2\\n\\ng u A 2\\n\\n] L C . s c [\\n\\n7 v 2 6...{'source': '/tmp/tmp7lpqus0e/tmp.pdf'}
\n", + "" + ], + "text/plain": [ + " text \\\n", + "0 3 2 0 2\\n\\ng u A 2\\n\\n] L C . s c [\\n\\n7 v 2 6... \n", + "\n", + " metadata \n", + "0 {'source': '/tmp/tmp7lpqus0e/tmp.pdf'} " + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:38:08,277 E 2179392 2179417] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-37-46_470728_2138313 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] + } + ], + "source": [ + "attention_is_all_you_need_pdf = 'https://arxiv.org/pdf/1706.03762.pdf'\n", + "\n", + "from pyrecdp.LLM import TextPipeline\n", + "from pyrecdp.primitives.operations import DocumentLoader\n", + "\n", + "pipeline = TextPipeline()\n", + "ops = [\n", + " DocumentLoader(loader='OnlinePDFLoader', loader_args={\"file_path\": attention_is_all_you_need_pdf}),\n", + "]\n", + "pipeline.add_operations(ops)\n", + "ds = pipeline.execute()\n", + "display(ds.to_pandas())" ] } ], diff --git a/RecDP/examples/notebooks/llmutils/document_ingestion.ipynb b/RecDP/examples/notebooks/llmutils/document_ingestion.ipynb new file mode 100644 index 00000000..69f67b2d --- /dev/null +++ b/RecDP/examples/notebooks/llmutils/document_ingestion.ipynb @@ -0,0 +1,944 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "736fb211-dbe6-4ca9-a1b1-db2cff2d287a", + "metadata": {}, + "source": [ + "# RecDP LLM - Document Ingestion" + ] + }, + { + "cell_type": "markdown", + "id": "5046b222", + "metadata": {}, + "source": [ + "# Get started" + ] + }, + { + "cell_type": "markdown", + "id": "54ebdd0e", + "metadata": {}, + "source": [ + "## 1. Install pyrecdp and dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2411d13e", + "metadata": { + "ExecuteTime": { + "end_time": "2023-10-09T16:00:24.332535Z", + "start_time": "2023-10-09T16:00:19.320447Z" + }, + "pycharm": { + "is_executing": true + } + }, + "outputs": [], + "source": [ + "! DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-8-jre\n", + "! pip install pyrecdp --pre\n", + "# ! pip install 'git+https://github.com/intel/e2eAIOK.git#egg=pyrecdp&subdirectory=RecDP'" + ] + }, + { + "cell_type": "markdown", + "id": "efb80b18", + "metadata": {}, + "source": [ + "## 2. prepare your own data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16bdbeb3", + "metadata": {}, + "outputs": [], + "source": [ + "%mkdir -p /content/test_data\n", + "%cd /content/test_data\n", + "%mkdir -p /content/doc_jsonl\n", + "file_names = ['english-and-korean.png', 'handbook-872p.docx', 'layout-parser-paper-10p.jpg', 'layout-parser-paper.pdf']\n", + "file_list = [f\"https://raw.githubusercontent.com/intel/e2eAIOK/main/RecDP/tests/data/llm_data/document/{i}\" for i in file_names]\n", + "!wget -P /content/test_data/document/ {\" \".join(file_list)}" + ] + }, + { + "cell_type": "markdown", + "id": "641b4705", + "metadata": {}, + "source": [ + "## 3. DocumentIngestion" + ] + }, + { + "cell_type": "markdown", + "id": "bee64090", + "metadata": {}, + "source": [ + "### 3.1 Load document" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "0435bcf8", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/pyspark/pandas/__init__.py:50: UserWarning: 'PYARROW_IGNORE_TIMEZONE' environment variable was not set. It is required to set this environment variable to '1' in both driver and executor sides if you use pyarrow>=2.0.0. pandas-on-Spark will set it for you but it does not work if there is a Spark context already launched.\n", + " warnings.warn(\n", + "\u001b[32m2023-12-20 16:05:50.470\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m52\u001b[0m - \u001b[1mcheck_availability_and_install emoji==2.2.0\u001b[0m\n", + "2023-12-20 16:05:55,014\tINFO worker.py:1642 -- Started a local Ray instance.\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
textmetadata
0<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
\n", + "
" + ], + "text/plain": [ + " text \\\n", + "0 \\n\\n ... \n", + "\n", + " metadata \n", + "0 {'description': 'Documentation website for cnv... " + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:06:04,911 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:06:14,923 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:06:24,935 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:06:34,946 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:06:44,959 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:06:54,973 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:07:04,984 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:07:14,997 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:07:25,010 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:07:35,023 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:07:45,036 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:07:55,049 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:08:05,061 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:08:15,074 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:08:25,087 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:08:35,098 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:08:45,110 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:08:55,122 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:09:05,134 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:09:15,147 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:09:25,160 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:09:35,172 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:09:45,186 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:09:55,198 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:10:05,211 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:10:15,224 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:10:25,237 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:10:35,250 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:10:45,260 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:10:55,272 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:11:05,284 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:11:15,298 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:11:25,311 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:11:35,323 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:11:45,337 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:11:55,350 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:12:05,362 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:12:15,373 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:12:25,384 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] + } + ], + "source": [ + "from pyrecdp.primitives.operations import DocumentSplit,DocumentLoader\n", + "\n", + "loader = DocumentLoader(loader=\"RecursiveUrlLoader\", loader_args={\"url\": \"https://app.cnvrg.io/docs/core_concepts/python_sdk_v2.html\"})\n", + "\n", + "ds = loader.process_rayds()\n", + "display(ds.to_pandas())" + ] + }, + { + "cell_type": "markdown", + "id": "dfdd9850", + "metadata": {}, + "source": [ + "### 3.2 Embedding document\n", + "\n", + "we support ingest document into following document store:\n", + "- [faiss](https://github.com/facebookresearch/faiss) vector store\n", + "- [chroma](https://github.com/chroma-core/chroma) vector store\n", + "- [elasticsearch](https://github.com/elastic/elasticsearch)\n", + "\n", + "we provide the [DocumentIngestion](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_ingestion.py#L239) operator for ingest documents into document store" + ] + }, + { + "cell_type": "markdown", + "id": "4a608977", + "metadata": {}, + "source": [ + "#### 3.2.1 Ingest into FAISS vector store" + ] + }, + { + "cell_type": "markdown", + "id": "833d1ec3", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "77af99e4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[32m2023-12-20 16:17:21.188\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['langchain']\u001b[0m\n", + "\u001b[32m2023-12-20 16:17:25.209\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['langchain']\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:17:25,757 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "init ray\n", + "execute with ray started ...\n", + "\u001b[32m2023-12-20 16:17:31.848\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['faiss-cpu', 'faiss-gpu', 'langchain']\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.\n", + "Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.\n", + "To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.\n" + ] + }, + { + "data": { + "text/html": [ + "
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n", + "\u001b[0m" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:17:35,769 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.\n", + "Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.\n", + "To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:17:45,782 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:17:55,795 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] + }, + { + "data": { + "text/html": [ + "
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n", + "\u001b[0m" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:18:05,807 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "2023-12-20 16:18:07,819\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> ActorPoolMapOperator[FlatMap()->MapBatches(TextEmbedding)]\n", + "2023-12-20 16:18:07,820\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 16:18:07,822\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", + "2023-12-20 16:18:09,643\tINFO actor_pool_map_operator.py:106 -- FlatMap()->MapBatches(TextEmbedding): Waiting for 1 pool actors to start...\n", + "\u001b[2m\u001b[36m(_MapWorker pid=2276648)\u001b[0m /root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + "\u001b[2m\u001b[36m(_MapWorker pid=2276648)\u001b[0m warnings.warn(\"Setuptools is replacing distutils.\")\n", + "\u001b[2m\u001b[36m(_MapWorker pid=2276648)\u001b[0m 2023-12-20 16:18:11.695 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b021583f4b0e450b84c9971001a5efd9", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/1 [00:00 ActorPoolMapOperator[FlatMap()->MapBatches(TextEmbedding)]\n", + "2023-12-20 16:20:21,538\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 16:20:21,539\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", + "2023-12-20 16:20:23,482\tINFO actor_pool_map_operator.py:106 -- FlatMap()->MapBatches(TextEmbedding): Waiting for 1 pool actors to start...\n", + "\u001b[2m\u001b[36m(_MapWorker pid=2279978)\u001b[0m /root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + "\u001b[2m\u001b[36m(_MapWorker pid=2279978)\u001b[0m warnings.warn(\"Setuptools is replacing distutils.\")\n", + "\u001b[2m\u001b[36m(_MapWorker pid=2279978)\u001b[0m 2023-12-20 16:20:25.523 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:20:25,971 E 2251227 2251243] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-05-53_056733_2250766 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8c9f83114b9b4920a6907c8a77bc3c39", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/1 [00:00\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
textembedding
0<!DOCTYPE html>\\r\\n<html lang=\"en\">\\r\\n <he...[0.02279656007885933, -0.004381305538117886, -...
1<script type=\"text/javascript\">\\r\\n //c...[-0.013796613551676273, -0.04453909769654274, ...
2<a href=\"/news-events/press-releases\" >Press R...[0.009947280399501324, 0.010400775820016861, -...
3</li>\\r\\n <...[0.02152082696557045, 0.03438470885157585, -0....
4<div class=\"text\">\\r\\n ...[0.0012505522463470697, -0.03194170445203781, ...
.........
113</td>\\r\\n<td width=\"5\" valign=\"bottom\" style=\"...[-0.009348627179861069, -0.031560588628053665,...
114</svg>\\r\\n <span>Tear Sheet</sp...[-0.018031703308224678, -0.08937390893697739, ...
115</svg>\\r\\n <span>RSS News Feed<...[0.029551001265645027, -0.027967212721705437, ...
116</svg>\\r\\n </a>\\r\\n ...[0.031037108972668648, -0.05818837508559227, -...
117</div>\\r\\n <div id=\"footer-disc...[-0.014034147374331951, 0.020656155422329903, ...
\n", + "

118 rows × 2 columns

\n", + "" + ], + "text/plain": [ + " text \\\n", + "0 \\r\\n\\r\\n \\r\\n //c... \n", + "2 Press R... \n", + "3 \\r\\n <... \n", + "4 \\r\\n
TaskPoolMapOperator[FlatMap()]\n", + "2023-12-20 16:46:09,016\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 16:46:09,017\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ef3e706862394e318584750651e720be", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/1 [00:00) pid=2326233)\u001b[0m /root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + "\u001b[2m\u001b[36m(FlatMap() pid=2326233)\u001b[0m warnings.warn(\"Setuptools is replacing distutils.\")\n", + "\u001b[2m\u001b[36m(FlatMap() pid=2326233)\u001b[0m 2023-12-20 16:46:10.667 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:46:11,993 E 2326022 2326053] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-45-19_818714_2325066 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:46:22,005 E 2326022 2326053] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_16-45-19_818714_2325066 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "2023-12-20 16:46:25,523\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[FlatMap()]\n", + "2023-12-20 16:46:25,524\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 16:46:25,525\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c56994e5058e426da5bd33dc3520167e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/1 [00:00\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
textmetadata
0<!DOCTYPE html>\\r\\n<html lang=\"en\">\\r\\n <he...{'language': 'en', 'source': 'https://www.intc...
1<script type=\"text/javascript\">\\r\\n //c...{'language': 'en', 'source': 'https://www.intc...
2<a href=\"/news-events/press-releases\" >Press R...{'language': 'en', 'source': 'https://www.intc...
3</li>\\r\\n <...{'language': 'en', 'source': 'https://www.intc...
4<div class=\"text\">\\r\\n ...{'language': 'en', 'source': 'https://www.intc...
.........
113</td>\\r\\n<td width=\"5\" valign=\"bottom\" style=\"...{'language': 'en', 'source': 'https://www.intc...
114</svg>\\r\\n <span>Tear Sheet</sp...{'language': 'en', 'source': 'https://www.intc...
115</svg>\\r\\n <span>RSS News Feed<...{'language': 'en', 'source': 'https://www.intc...
116</svg>\\r\\n </a>\\r\\n ...{'language': 'en', 'source': 'https://www.intc...
117</div>\\r\\n <div id=\"footer-disc...{'language': 'en', 'source': 'https://www.intc...
\n", + "

118 rows × 2 columns

\n", + "
" + ], + "text/plain": [ + " text \\\n", + "0 \\r\\n\\r\\n \\r\\n //c... \n", + "2 Press R... \n", + "3 \\r\\n <... \n", + "4 \\r\\n
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
textmetadata
0<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
\n", + "
" + ], + "text/plain": [ + " text \\\n", + "0 \\n\\n ... \n", + "\n", + " metadata \n", + "0 {'description': 'Documentation website for cnv... " + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:51:12,627 E 2215683 2215698] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-49-40_736779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:51:22,638 E 2215683 2215698] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-49-40_736779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:51:32,651 E 2215683 2215698] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-49-40_736779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] + } + ], + "source": [ + "from pyrecdp.primitives.operations import DocumentSplit,DocumentLoader\n", + "\n", + "loader = DocumentLoader(loader=\"RecursiveUrlLoader\", loader_args={\"url\": \"https://app.cnvrg.io/docs/core_concepts/python_sdk_v2.html\"})\n", + "\n", + "ds = loader.process_rayds()\n", + "display(ds.to_pandas())\n" + ] + }, + { + "cell_type": "markdown", + "id": "18c82062", + "metadata": {}, + "source": [ + "### 4.2 split document with DocumentSplit operator" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "52c00663", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-12-20 15:52:00,384\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[FlatMap()]\n", + "2023-12-20 15:52:00,385\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 15:52:00,387\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "948ce35a60ef4a9a8c3e171de1ff79dc", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/1 [00:00\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
textmetadata
0<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
1<link rel=\"preload\" href=\"/docs/assets/css/0.s...{'description': 'Documentation website for cnv...
2rel=\"prefetch\" href=\"/docs/assets/js/18.698a17...{'description': 'Documentation website for cnv...
3rel=\"prefetch\" href=\"/docs/assets/js/78.75a8bd...{'description': 'Documentation website for cnv...
4<link rel=\"stylesheet\" href=\"/docs/assets/css/...{'description': 'Documentation website for cnv...
.........
101</code></pre></div><h3 id=\"update-an-existing-...{'description': 'Documentation website for cnv...
102</code></pre></div><p><strong>Available Parame...{'description': 'Documentation website for cnv...
103</code></pre></div><p><strong>Available Parame...{'description': 'Documentation website for cnv...
104</code></pre></div><p><strong>Available Parame...{'description': 'Documentation website for cnv...
105image<span class=\"token punctuation\">.</span>d...{'description': 'Documentation website for cnv...
\n", + "

106 rows × 2 columns

\n", + "" + ], + "text/plain": [ + " text \\\n", + "0 \\n\\n ... \n", + "1

Available Parame... \n", + "103

Available Parame... \n", + "104

Available Parame... \n", + "105 image.d... \n", + "\n", + " metadata \n", + "0 {'description': 'Documentation website for cnv... \n", + "1 {'description': 'Documentation website for cnv... \n", + "2 {'description': 'Documentation website for cnv... \n", + "3 {'description': 'Documentation website for cnv... \n", + "4 {'description': 'Documentation website for cnv... \n", + ".. ... \n", + "101 {'description': 'Documentation website for cnv... \n", + "102 {'description': 'Documentation website for cnv... \n", + "103 {'description': 'Documentation website for cnv... \n", + "104 {'description': 'Documentation website for cnv... \n", + "105 {'description': 'Documentation website for cnv... \n", + "\n", + "[106 rows x 2 columns]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:52:02,690 E 2215683 2215698] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-49-40_736779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:52:12,702 E 2215683 2215698] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-49-40_736779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:52:22,715 E 2215683 2215698] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-49-40_736779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:52:32,729 E 2215683 2215698] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-49-40_736779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:52:42,741 E 2215683 2215698] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-49-40_736779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] + } + ], + "source": [ + "spliter = DocumentSplit(text_splitter='RecursiveCharacterTextSplitter')\n", + "ds = spliter.process_rayds(ds)\n", + "display(ds.to_pandas())" + ] + }, + { + "cell_type": "markdown", + "id": "194089b0", + "metadata": {}, + "source": [ + "### 4.3 put DocumentSplit operator in a pipeline" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "52ced260", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:53:02,767 E 2215683 2215698] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-49-40_736779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "init ray\n", + "init ray with total mem of 324413575987, total core of 48\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-12-20 15:53:09,801\tINFO worker.py:1642 -- Started a local Ray instance.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "execute with ray started ...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-12-20 15:53:13,140\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[FlatMap()->Write]\n", + "2023-12-20 15:53:13,142\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 15:53:13,143\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6ec6c228e366434bb7df4357e56c0de7", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/1 [00:00)->Write pid=2224997)\u001b[0m /root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + "\u001b[2m\u001b[36m(FlatMap()->Write pid=2224997)\u001b[0m warnings.warn(\"Setuptools is replacing distutils.\")\n", + "\u001b[2m\u001b[36m(FlatMap()->Write pid=2224997)\u001b[0m 2023-12-20 15:53:14.774 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-20 15:53:15,081\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[FlatMap()]\n", + "2023-12-20 15:53:15,082\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 15:53:15,084\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6a50999c658c47e685b7c5955ad56351", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/1 [00:00\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
textmetadata
0<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
1<link rel=\"preload\" href=\"/docs/assets/css/0.s...{'description': 'Documentation website for cnv...
2rel=\"prefetch\" href=\"/docs/assets/js/18.698a17...{'description': 'Documentation website for cnv...
3rel=\"prefetch\" href=\"/docs/assets/js/78.75a8bd...{'description': 'Documentation website for cnv...
4<link rel=\"stylesheet\" href=\"/docs/assets/css/...{'description': 'Documentation website for cnv...
.........
101</code></pre></div><h3 id=\"update-an-existing-...{'description': 'Documentation website for cnv...
102</code></pre></div><p><strong>Available Parame...{'description': 'Documentation website for cnv...
103</code></pre></div><p><strong>Available Parame...{'description': 'Documentation website for cnv...
104</code></pre></div><p><strong>Available Parame...{'description': 'Documentation website for cnv...
105image<span class=\"token punctuation\">.</span>d...{'description': 'Documentation website for cnv...
\n", + "

106 rows × 2 columns

\n", + "" + ], + "text/plain": [ + " text \\\n", + "0 \\n\\n ... \n", + "1

Available Parame... \n", + "103

Available Parame... \n", + "104

Available Parame... \n", + "105 image.d... \n", + "\n", + " metadata \n", + "0 {'description': 'Documentation website for cnv... \n", + "1 {'description': 'Documentation website for cnv... \n", + "2 {'description': 'Documentation website for cnv... \n", + "3 {'description': 'Documentation website for cnv... \n", + "4 {'description': 'Documentation website for cnv... \n", + ".. ... \n", + "101 {'description': 'Documentation website for cnv... \n", + "102 {'description': 'Documentation website for cnv... \n", + "103 {'description': 'Documentation website for cnv... \n", + "104 {'description': 'Documentation website for cnv... \n", + "105 {'description': 'Documentation website for cnv... \n", + "\n", + "[106 rows x 2 columns]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:53:18,680 E 2224790 2224809] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-53-06_901719_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:53:28,693 E 2224790 2224809] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-53-06_901719_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:53:38,706 E 2224790 2224809] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-53-06_901719_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:53:48,720 E 2224790 2224809] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-53-06_901719_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:53:58,733 E 2224790 2224809] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-53-06_901719_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:54:08,745 E 2224790 2224809] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-53-06_901719_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:54:18,758 E 2224790 2224809] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-53-06_901719_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:54:28,770 E 2224790 2224809] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-53-06_901719_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:54:38,781 E 2224790 2224809] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-53-06_901719_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] + } + ], + "source": [ + "from pyrecdp.LLM import TextPipeline\n", + " \n", + "pipeline = TextPipeline()\n", + "ops = [\n", + " loader,\n", + " spliter\n", + "]\n", + "pipeline.add_operations(ops)\n", + "ds = pipeline.execute()\n", + "display(ds.to_pandas())" + ] + }, + { + "cell_type": "markdown", + "id": "c6f6b7da", + "metadata": {}, + "source": [ + "### 4.4 Split document with CustomerDocumentSplit operator in a pipeline" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "ae9f9516", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "init ray\n", + "init ray with total mem of 324413575987, total core of 48\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-12-20 15:56:00,827\tINFO worker.py:1642 -- Started a local Ray instance.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "execute with ray started ...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-12-20 15:56:03,800\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[FlatMap()->Write]\n", + "2023-12-20 15:56:03,802\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 15:56:03,803\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ecb828b7ef5c490fa55421dd1a51c672", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/1 [00:00)->Write pid=2233388)\u001b[0m /root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + "\u001b[2m\u001b[36m(FlatMap()->Write pid=2233388)\u001b[0m warnings.warn(\"Setuptools is replacing distutils.\")\n", + "\u001b[2m\u001b[36m(FlatMap()->Write pid=2233388)\u001b[0m 2023-12-20 15:56:05.399 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-20 15:56:06,464\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[FlatMap()]\n", + "2023-12-20 15:56:06,465\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-12-20 15:56:06,466\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "9b94044012184cffbed45277dacf088e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/1 [00:00\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
textmetadata
0<!DOCTYPE html>\\n<html lang=\"en-US\">\\n <head>...{'description': 'Documentation website for cnv...
1Through the SDK, you can create experiments, m...{'description': 'Documentation website for cnv...
2First, install WSL with following commands:</p...{'description': 'Documentation website for cnv...
3https://app.cnvrgdomain.com/</td> <td>Yes</td>...{'description': 'Documentation website for cnv...
4the token can be retrieved from the <strong>us...{'description': 'Documentation website for cnv...
.........
61For example, <code>value1=NoSchedule</code>.To...{'description': 'Documentation website for cnv...
62For example, <code>gputype=v100</code>.To spec...{'description': 'Documentation website for cnv...
63For example, <code>value1=NoSchedule</code>.To...{'description': 'Documentation website for cnv...
64options are: cnvrg, dockerhub, gcr, acr, ecr, ...{'description': 'Documentation website for cnv...
65options are: cnvrg, dockerhub, gcr, acr, ecr, ...{'description': 'Documentation website for cnv...
\n", + "

66 rows × 2 columns

\n", + "" + ], + "text/plain": [ + " text \\\n", + "0 \\n\\n ... \n", + "1 Through the SDK, you can create experiments, m... \n", + "2 First, install WSL with following commands: Yes... \n", + "4 the token can be retrieved from the us... \n", + ".. ... \n", + "61 For example, value1=NoSchedule.To... \n", + "62 For example, gputype=v100.To spec... \n", + "63 For example, value1=NoSchedule.To... \n", + "64 options are: cnvrg, dockerhub, gcr, acr, ecr, ... \n", + "65 options are: cnvrg, dockerhub, gcr, acr, ecr, ... \n", + "\n", + " metadata \n", + "0 {'description': 'Documentation website for cnv... \n", + "1 {'description': 'Documentation website for cnv... \n", + "2 {'description': 'Documentation website for cnv... \n", + "3 {'description': 'Documentation website for cnv... \n", + "4 {'description': 'Documentation website for cnv... \n", + ".. ... \n", + "61 {'description': 'Documentation website for cnv... \n", + "62 {'description': 'Documentation website for cnv... \n", + "63 {'description': 'Documentation website for cnv... \n", + "64 {'description': 'Documentation website for cnv... \n", + "65 {'description': 'Documentation website for cnv... \n", + "\n", + "[66 rows x 2 columns]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:56:09,706 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:56:19,719 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:56:29,731 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:56:39,741 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:56:49,752 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:56:59,764 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:57:09,778 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:57:19,789 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:57:29,799 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:57:39,812 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:57:49,826 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:57:59,838 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:58:09,851 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:58:19,864 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:58:29,877 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:58:39,889 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:58:49,902 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:58:59,915 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:59:09,929 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:59:19,942 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:59:29,955 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:59:39,968 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:59:49,982 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 15:59:59,994 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:00:10,007 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:00:20,021 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:00:30,035 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:00:40,049 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:00:50,060 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:01:00,073 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:01:10,087 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:01:20,100 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:01:30,114 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:01:40,128 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:01:50,140 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:02:00,153 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:02:10,168 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:02:20,182 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:02:30,196 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:02:40,210 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:02:50,225 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:03:00,239 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:03:10,252 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:03:20,263 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:03:30,276 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:03:40,290 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:03:50,304 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:04:00,318 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:04:10,330 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:04:20,343 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:04:30,355 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:04:40,370 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:04:50,384 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:05:00,398 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:05:10,410 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:05:20,424 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:05:30,439 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:05:40,453 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:05:50,464 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:06:00,475 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:06:10,487 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:06:20,501 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:06:30,512 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:06:40,525 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:06:50,537 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:07:00,551 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:07:10,564 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:07:20,578 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:07:30,591 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:07:40,604 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:07:50,617 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:08:00,630 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:08:10,640 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:08:20,653 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:08:30,666 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:08:40,680 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:08:50,694 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:09:00,708 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:09:10,722 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:09:20,736 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:09:30,749 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:09:40,763 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:09:50,775 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:10:00,788 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:10:10,801 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:10:20,814 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:10:30,828 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:10:40,841 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:10:50,853 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:11:00,866 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:11:10,880 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:11:20,894 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:11:30,908 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:11:40,922 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:11:50,935 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:12:00,947 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:12:10,961 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:12:20,974 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:12:30,987 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:12:41,002 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:12:51,015 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:13:01,027 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:13:11,041 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:13:21,054 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:13:31,067 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:13:41,079 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:13:51,093 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:14:01,107 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:14:11,120 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:14:21,133 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:14:31,145 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:14:41,157 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:14:51,168 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:15:01,178 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:15:11,192 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:15:21,204 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:15:31,218 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:15:41,230 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:15:51,242 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:16:01,255 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:16:11,269 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:16:21,281 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:16:31,293 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:16:41,306 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:16:51,318 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:17:01,332 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:17:11,343 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:17:21,355 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:17:31,365 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:17:41,376 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:17:51,388 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:18:01,401 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:18:11,414 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:18:21,424 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:18:31,435 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:18:41,446 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:18:51,457 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:19:01,469 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:19:11,481 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:19:21,493 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:19:31,505 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:19:41,516 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:19:51,527 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:20:01,537 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:20:11,547 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:20:21,560 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:20:31,571 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:20:41,583 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:20:51,596 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:21:01,608 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:21:11,620 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:21:21,632 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:21:31,644 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:21:41,657 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:21:51,669 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:22:01,682 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:22:11,694 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:22:21,706 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:22:31,717 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:22:41,730 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:22:51,743 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:23:01,755 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:23:11,768 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:23:21,781 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:23:31,795 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:23:41,808 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:23:51,821 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:24:01,834 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:24:11,847 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:24:21,860 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:24:31,874 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:24:41,886 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:24:51,897 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:25:01,910 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:25:11,923 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:25:21,937 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:25:31,950 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:25:41,962 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:25:51,975 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:26:01,986 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:26:11,997 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:26:22,008 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:26:32,020 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:26:42,033 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:26:52,046 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:27:02,058 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:27:12,071 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:27:22,083 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:27:32,097 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:27:42,108 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:27:52,121 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:28:02,133 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:28:12,148 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:28:22,162 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:28:32,175 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:28:42,187 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:28:52,200 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:29:02,212 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:29:12,225 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:29:22,238 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:29:32,249 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:29:42,264 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:29:52,277 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:30:02,290 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:30:12,302 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:30:22,315 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:30:32,328 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:30:42,343 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:30:52,357 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:31:02,371 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:31:12,384 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:31:22,397 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:31:32,410 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:31:42,423 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:31:52,436 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:32:02,447 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:32:12,461 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:32:22,475 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:32:32,488 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:32:42,502 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:32:52,516 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:33:02,529 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:33:12,541 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:33:22,553 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:33:32,566 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:33:42,578 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:33:52,591 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:34:02,605 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:34:12,618 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:34:22,632 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:34:32,645 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:34:42,658 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:34:52,671 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:35:02,686 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:35:12,700 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:35:22,713 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:35:32,726 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:35:42,740 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:35:52,753 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:36:02,766 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:36:12,780 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:36:22,793 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:36:32,807 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:36:42,819 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:36:52,831 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:37:02,843 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:37:12,855 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:37:22,868 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:37:32,882 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:37:42,893 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:37:52,906 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:38:02,918 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:38:12,930 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:38:22,945 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:38:32,956 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:38:42,968 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:38:52,980 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:39:02,992 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:39:13,003 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:39:23,016 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:39:33,028 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:39:43,042 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:39:53,055 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:40:03,069 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:40:13,081 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:40:23,095 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:40:33,106 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:40:43,120 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:40:53,134 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:41:03,146 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:41:13,159 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:41:23,173 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:41:33,183 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:41:43,196 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:41:53,206 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:42:03,217 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:42:13,231 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:42:23,244 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:42:33,256 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:42:43,268 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:42:53,280 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:43:03,291 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:43:13,303 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:43:23,315 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:43:33,329 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:43:43,341 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:43:53,353 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:44:03,367 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:44:13,379 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:44:23,390 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:44:33,402 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:44:43,413 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:44:53,424 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:45:03,435 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:45:13,447 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:45:23,460 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:45:33,472 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:45:43,485 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:45:53,499 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:46:03,513 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:46:13,525 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:46:23,537 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:46:33,549 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:46:43,560 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:46:53,573 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:47:03,586 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:47:13,599 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:47:23,613 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:47:33,626 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:47:43,637 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:47:53,647 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:48:03,661 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:48:13,673 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:48:23,685 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:48:33,697 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:48:43,710 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:48:53,721 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:49:03,734 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:49:13,746 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:49:23,760 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:49:33,773 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:49:43,785 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:49:53,795 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:50:03,808 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:50:13,820 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:50:23,832 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:50:33,844 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:50:43,857 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:50:53,869 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:51:03,882 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:51:13,893 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:51:23,903 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:51:33,913 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n", + "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-20 16:51:43,923 E 2233193 2233212] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-20_15-55-57_818779_2191522 is over 95% full, available space: 0; capacity: 422146228224. Object creation will fail if spilling is required.\n" + ] + } + ], + "source": [ + "from pyrecdp.LLM import TextPipeline\n", + "from pyrecdp.primitives.operations import CustomerDocumentSplit\n", + " \n", + "def chunk_doc(text,max_num_of_words):\n", + " from nltk.tokenize import word_tokenize,sent_tokenize\n", + " text= text.strip()\n", + " if len(word_tokenize(text)) <= max_num_of_words:\n", + " return [text]\n", + " else:\n", + " chunks = []\n", + " # split by sentence\n", + " sentences = sent_tokenize(text)\n", + " # print('number of sentences: ', len(sentences))\n", + " words_count = 0\n", + " temp_chunk = \"\"\n", + " for s in sentences:\n", + " temp_chunk+=(s+\" \")\n", + " words_count += len(word_tokenize(s))\n", + " if len(word_tokenize(temp_chunk))> max_num_of_words:\n", + " chunks.append(temp_chunk)\n", + " words_count = 0\n", + " temp_chunk = \"\"\n", + " \n", + " return chunks\n", + " \n", + "pipeline = TextPipeline()\n", + "ops = [\n", + " loader,\n", + " CustomerDocumentSplit(func=chunk_doc, max_num_of_words=50),\n", + "]\n", + "pipeline.add_operations(ops)\n", + "ds = pipeline.execute()\n", + "display(ds.to_pandas())" + ] } ], "metadata": { diff --git a/RecDP/pyrecdp/LLM/README.md b/RecDP/pyrecdp/LLM/README.md index 3e6c03fe..6198da04 100644 --- a/RecDP/pyrecdp/LLM/README.md +++ b/RecDP/pyrecdp/LLM/README.md @@ -9,8 +9,11 @@ RecDP LLM is a set of python components that enables quick and easy establish of | Type | notebook | Description | supports | Verified dataset & size | | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------- | -| [ DocumentExtract ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/llmutils/document_extractor.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/document_extract.ipynb) | extract text from unstructured format | jpg, png, pdf, docx, | RefinedWeb - 1.7 TB | -| [ Reader ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_reader.py#L16) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/reader.ipynb) | Read data from directory | jsonl, parquet, | RefinedWeb - 1.7 TB | +| [ Directory Loader ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/doc_loader.py#L77) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/document_extract.ipynb) | extract text from a directory | jpg, png, pdf, docx, | RefinedWeb - 1.7 TB | +| [ Document Loader ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/doc_loader.py#L15) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/document_extract.ipynb) | extract text from unstructured format | all [document loaders](https://python.langchain.com/docs/modules/data_connection/document_loaders/) provided in [langchain](https://python.langchain.com/) | RefinedWeb - 1.7 TB | +| [ Text Reader ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_reader.py#L16) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/reader.ipynb) | Read data from directory | jsonl, parquet, | RefinedWeb - 1.7 TB | +| [ Document Split ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_split.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/document_split.ipynb) | split documents | [text splitter](https://python.langchain.com/docs/modules/data_connection/document_transformers/#text-splitters) provided in [langchain](https://python.langchain.com/) and [customer document split](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_split.py#L278) | RefinedWeb - 1.7 TB | +| [ Document Ingestion ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_ingestion.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/document_ingestion.ipynb) | embedding documents and store into vector database | chroma,faiss,elasticsearch | RefinedWeb - 1.7 TB | | [ Converter ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_converter.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/convert.ipynb) | Read and convert unstructed data to unified format | html, document, image, pdf, ... | RefinedWeb - 1.7 TB | | [ Filter ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/filter.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/filter.ipynb) | Filter out document based on condition | profanity-based, black-list, url_based, length_based | RedPajama - 2 TB | | [ Text Bytesize ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_bytesize.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/bytesize.ipynb) | Get text bytes size | | RedPajama - 2 TB | diff --git a/RecDP/pyrecdp/primitives/llmutils/document/reader.py b/RecDP/pyrecdp/primitives/llmutils/document/reader.py index 25fca9df..05693788 100644 --- a/RecDP/pyrecdp/primitives/llmutils/document/reader.py +++ b/RecDP/pyrecdp/primitives/llmutils/document/reader.py @@ -312,17 +312,7 @@ def _load_file(self, input_file: Path, pbar): loader = self.file_extractor[file_suffix] return loader.load() else: - from pyrecdp.core.import_utils import import_langchain - import_langchain() - from langchain.document_loaders import UnstructuredFileLoader - loader = UnstructuredFileLoader(str(input_file)) - docs = [Document(text=doc.text, metadata=doc.metadata) for doc in loader.load()] - docs = list(filter(lambda d: (d.pa.strip() != ""), docs)) - if self.single_text_per_document: - text = self.page_separator.join([doc.text for doc in docs]) - return [Document(text=text, metadata={"source": str(input_file)})] - else: - return docs + return [] finally: if pbar: pbar.update(1) @@ -336,7 +326,8 @@ def load(self) -> List[Document]: from concurrent.futures import ThreadPoolExecutor with ThreadPoolExecutor(self.max_concurrency) as executor: for docs in executor.map(lambda i: self._load_file(i, pbar), self.input_files): - docs_result.extend(docs) + if len(docs)>0: + docs_result.extend(docs) else: for file in self.input_files: docs = self._load_file(file, pbar) diff --git a/RecDP/pyrecdp/primitives/operations/text_ingestion.py b/RecDP/pyrecdp/primitives/operations/text_ingestion.py index 6e9b996d..1ce026a0 100644 --- a/RecDP/pyrecdp/primitives/operations/text_ingestion.py +++ b/RecDP/pyrecdp/primitives/operations/text_ingestion.py @@ -157,6 +157,7 @@ def do_persist(self, ds, **kwargs): check_availability_and_install(["chromadb==0.4.15", "langchain"]) chroma = self.vector_store_args["db_handler"] + collection_name = self.vector_store_args.get("collection_name", 'langchain') rows = ds.iter_rows() if isinstance(ds, Dataset) else ds.collect() texts = [row[self.text_column] for row in rows] @@ -165,9 +166,15 @@ def do_persist(self, ds, **kwargs): if chroma is not None: chroma.add_texts(texts) return chroma - if "output_dir" not in self.vector_store_args: - raise ValueError(f"You must have `output_dir` option specify for Chroma vector store") - persist_directory = self.vector_store_args["output_dir"] + if "output_dir" not in self.vector_store_args and 'persist_directory' not in self.vector_store_args: + raise ValueError( + f"You must have `output_dir` or `persist_directory` option specify for Chroma vector store") + + if 'output_dir' in self.vector_store_args: + persist_directory = self.vector_store_args["output_dir"] + else: + persist_directory = self.vector_store_args["persist_directory"] + if not self.override and os.path.exists(persist_directory): chroma = Chroma(collection_name=collection_name, persist_directory=persist_directory, diff --git a/RecDP/tests/test_llmutils_operations.py b/RecDP/tests/test_llmutils_operations.py index 3418d004..516a248f 100644 --- a/RecDP/tests/test_llmutils_operations.py +++ b/RecDP/tests/test_llmutils_operations.py @@ -231,11 +231,16 @@ def test_gopherqualityfilter_ray(self): with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_rayds(ctx.ds)) - def test_document_load_ray(self): + def test_document_load_pdf_ray(self): op = DirectoryLoader("tests/data/llm_data/document", glob="**/*.pdf") with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_rayds()) + def test_document_load_ray(self): + op = DirectoryLoader("data/llm_data/document") + with RayContext("data/llm_data/tiny_c4_sample.jsonl") as ctx: + ctx.show(op.process_rayds()) + def test_url_load_ray(self): op = UrlLoader(["https://www.intc.com/news-events/press-releases?year=2023&category=all"], max_depth=1) with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: From 701e1ba9a84888657b0850c2a7a760a70ed00db8 Mon Sep 17 00:00:00 2001 From: "Yao, Qing" Date: Wed, 20 Dec 2023 16:48:00 +0800 Subject: [PATCH 09/59] Unify the implementation of UrlLoader. . --- RecDP/pyrecdp/core/import_utils.py | 10 - .../primitives/llmutils/rag_data_extractor.py | 2 +- .../operations/constant/__init__.py | 9 - .../primitives/operations/doc_loader.py | 196 ++---------------- RecDP/tests/test_llmutils_operations.py | 4 +- RecDP/tests/test_llmutils_pipelines.py | 9 +- 6 files changed, 21 insertions(+), 209 deletions(-) diff --git a/RecDP/pyrecdp/core/import_utils.py b/RecDP/pyrecdp/core/import_utils.py index 73a5c071..37ce2642 100644 --- a/RecDP/pyrecdp/core/import_utils.py +++ b/RecDP/pyrecdp/core/import_utils.py @@ -151,14 +151,4 @@ def import_pysbd(install_if_missing: bool = True): "`pip install pysbd`" ) -def import_markdownify(): - try: - import markdownify - except ImportError: - pip.main(['install', 'markdownify']) -def import_beautiful_soup(): - try: - from bs4 import BeautifulSoup - except ImportError: - pip.main(['install', 'bs4']) diff --git a/RecDP/pyrecdp/primitives/llmutils/rag_data_extractor.py b/RecDP/pyrecdp/primitives/llmutils/rag_data_extractor.py index ff2dced8..d6c97b3f 100644 --- a/RecDP/pyrecdp/primitives/llmutils/rag_data_extractor.py +++ b/RecDP/pyrecdp/primitives/llmutils/rag_data_extractor.py @@ -40,7 +40,7 @@ def rag_data_prepare( if bool(files_path): loader = DirectoryLoader(files_path, glob="**/*.pdf") elif bool(target_urls): - loader = UrlLoader(urls=target_urls, target_tag='div') + loader = UrlLoader(urls=target_urls) else: logger.error("You must specify at least one parameter in files_path and target_urls") exit(1) diff --git a/RecDP/pyrecdp/primitives/operations/constant/__init__.py b/RecDP/pyrecdp/primitives/operations/constant/__init__.py index abfaf601..0d75243d 100644 --- a/RecDP/pyrecdp/primitives/operations/constant/__init__.py +++ b/RecDP/pyrecdp/primitives/operations/constant/__init__.py @@ -4,12 +4,3 @@ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '​', '‌', '‍', '⁠', '', '„' } - -DEFAULT_HEADER = { - 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng, \ - */*;q=0.8,application/signed-exchange;v=b3;q=0.7', - 'Accept-Encoding': 'gzip, deflate, br', - 'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7', - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, \ - like Gecko) Chrome/113.0.0.0 Safari/537.36' -} \ No newline at end of file diff --git a/RecDP/pyrecdp/primitives/operations/doc_loader.py b/RecDP/pyrecdp/primitives/operations/doc_loader.py index b8f896b2..5bba870d 100644 --- a/RecDP/pyrecdp/primitives/operations/doc_loader.py +++ b/RecDP/pyrecdp/primitives/operations/doc_loader.py @@ -6,11 +6,9 @@ import requests from pyrecdp.core.import_utils import check_availability_and_install -from pyrecdp.core.import_utils import import_langchain, import_markdownify, import_beautiful_soup +from pyrecdp.core.import_utils import import_langchain from pyrecdp.primitives.llmutils.document.schema import Document from pyrecdp.primitives.operations.base import LLMOPERATORS -from pyrecdp.primitives.operations.constant import DEFAULT_HEADER -from pyrecdp.primitives.operations.logging_utils import logger from pyrecdp.primitives.operations.text_reader import TextReader @@ -218,182 +216,11 @@ def process_spark(self, spark, spark_df=None): LLMOPERATORS.register(YoutubeLoader) -def create_doc_from_html_to_md(page_url, html_text): - import_markdownify() - import markdownify - markdown_text = markdownify.markdownify(html_text) - return Document( - text=markdown_text, - metadata={"source": page_url}, - ) - - -def get_base_url(url): - result = urlparse(url) - base_name = os.path.basename(result.path) - if "." in base_name: - path = os.path.dirname(result.path) - else: - path = result.path - return urlunparse((result.scheme, result.netloc, path, '', '', '')) - - -def web_parse(html_data, target_tag: str = None, target_attrs: dict = None): - import_beautiful_soup() - from bs4 import BeautifulSoup - soup = BeautifulSoup(html_data, "html.parser") - if target_tag: - soup = soup.find(target_tag, target_attrs) - return soup - - -def web_fetch(url, headers=None, max_times=5): - if not headers: - headers = DEFAULT_HEADER - while max_times: - if not url.startswith('http') or not url.startswith('https'): - url = 'http://' + url - logger.info(f'start fetch {url}...') - try: - response = requests.get(url, headers=headers, verify=True) - if response.status_code != 200: - logger.info(f'fail to fetch {url}, response status code: {response.status_code}') - else: - return response - except Exception as e: - logger.info(f'fail to fetch {url}, cased by {e}') - max_times -= 1 - return None - - -def get_hyperlink(soup, url): - base_url = get_base_url(url) - base_url_parse = urlparse(base_url) - base_path = base_url_parse.path - - sub_links = set() - for links in soup.find_all('a'): - link = str(links.get('href')) - absolute_link = None - if link.startswith('#') or link is None or link == 'None' or link == base_path: - continue - if link.startswith("/") and base_path not in link: - continue - suffix = link.split('/')[-1] - if '.' in suffix and suffix.split('.')[-1] not in ['html', 'htmld']: - continue - link_parse = urlparse(link) - if link_parse.path == '': - continue - if link_parse.netloc != '': - # keep crawler works in the same domain - if link_parse.netloc != base_url_parse.netloc: - continue - absolute_link = link - else: - new_link = urljoin(url, link) - if new_link.startswith(base_url): - absolute_link = new_link - if absolute_link: - sub_links.add(absolute_link) - return sub_links - - -def fetch_data_and_sub_links(sub_url, headers=None, target_tag: str = None, target_attrs: dict = None): - response = web_fetch(sub_url, headers) - if response is None: - return None, None - soup = web_parse(response.text, target_tag, target_attrs) - - sub_links = get_hyperlink(soup, response.url) - web_doc = create_doc_from_html_to_md(sub_url, str(soup)) - return sub_links, web_doc - - class UrlLoader(TextReader): - def __init__(self, urls: list = None, max_depth: int = 0, target_tag: str = None, target_attrs: dict = None, - args_dict: Optional[dict] = None, headers: Optional[dict] = None): - """ - Loads documents from a directory or a list of files. - - Args: - urls: A list of urls need to be loaded. - max_depth: The depth of pages crawled. - target_tag: A filter on tag name. Default: None - target_attrs: A dictionary of filters on attribute values. Default: None - headers: Dictionary of HTTP Headers to send with the :class:`Request`. - """ - settings = { - 'urls': urls, - 'max_depth': max_depth, - 'target_tag': target_tag, - 'target_attrs': target_attrs, - 'headers': headers - } - settings.update(args_dict or {}) - super().__init__(settings) - self.urls = urls - self.target_tag = target_tag - self.target_attrs = target_attrs - self.support_ray = True - self.support_spark = True - self.fetched_pool = set() - if not headers: - self.headers = DEFAULT_HEADER - else: - self.headers = headers - self.max_depth = max_depth - - def crawl(self): - docs = [] - for url in self.urls: - sub_links, web_doc = fetch_data_and_sub_links(url, self.headers, self.target_tag, self.target_attrs) - self.fetched_pool.add(url) - docs.append(web_doc) - depth = 0 - next_urls = sub_links - - while depth < self.max_depth: - logger.info(f'current depth {depth} ...') - child_urls = next_urls - next_urls = set() - for sub_url in child_urls: - if sub_url not in self.fetched_pool: - self.fetched_pool.add(sub_url) - sub_links, web_doc = fetch_data_and_sub_links(sub_url, self.headers, self.target_tag, - self.target_attrs) - if sub_url and web_doc: - docs.append(web_doc) - next_urls.update(sub_links) - - depth += 1 - return docs - - def load_documents(self): - return [{'text': doc.text, 'metadata': doc.metadata} for doc in self.crawl()] - - def process_rayds(self, ds=None): - import ray - self.cache = ray.data.from_items(self.load_documents()) - if ds is not None: - self.cache = self.union_ray_ds(ds, self.cache) - return self.cache - - def process_spark(self, spark, spark_df=None): - self.cache = spark.createDataFrame(self.load_documents()) - if spark_df is not None: - self.cache = self.union_spark_df(spark_df, self.cache) - return self.cache - - -LLMOPERATORS.register(UrlLoader) - - -class RecursiveUrlLoader(TextReader): def __init__( self, - urls: Union[str | List[str]], - max_depth: Optional[int] = 2, + urls: Union[str, List[str]], + max_depth: Optional[int] = 1, use_async: Optional[bool] = None, extractor: Optional[Callable[[str], str]] = None, metadata_extractor: Optional[Callable[[str, str], str]] = None, @@ -403,6 +230,7 @@ def __init__( link_regex: Union[str, re.Pattern, None] = None, headers: Optional[dict] = None, check_response_status: bool = False, + text_to_markdown: bool = True, requirements=None, ) -> None: """Initialize with URL to crawl and any subdirectories to exclude. @@ -430,11 +258,15 @@ def __init__( URLs with error responses (400-599). """ if requirements is None: - requirements = [] + requirements = ['bs4', 'markdownify', 'langchain'] - if extractor is None: - from bs4 import BeautifulSoup - extractor = lambda x: BeautifulSoup(x, "html.parser").text + if text_to_markdown: + import markdownify + extractor = lambda x: markdownify.markdownify(x) + else: + if extractor is None: + from bs4 import BeautifulSoup + extractor = lambda x: BeautifulSoup(x, "html.parser").text settings = { 'urls': urls, @@ -449,7 +281,7 @@ def __init__( 'headers': headers, 'check_response_status': check_response_status, } - super().__init__(settings, requirements=['bs4', 'langchain']) + super().__init__(settings, requirements=requirements) self.support_spark = True self.support_ray = True @@ -491,4 +323,4 @@ def process_spark(self, spark, spark_df=None): return self.cache -LLMOPERATORS.register(RecursiveUrlLoader) +LLMOPERATORS.register(UrlLoader) diff --git a/RecDP/tests/test_llmutils_operations.py b/RecDP/tests/test_llmutils_operations.py index 1bad8f8b..4df110d7 100644 --- a/RecDP/tests/test_llmutils_operations.py +++ b/RecDP/tests/test_llmutils_operations.py @@ -511,7 +511,7 @@ def test_recursive_url_loader_spark(self): 'https://app.cnvrg.io/docs/core_concepts/python_sdk_v2.html', 'https://app.cnvrg.io/docs/cli_v2/cnvrgv2_cli.html', 'https://app.cnvrg.io/docs/collections/tutorials.html'] - op = RecursiveUrlLoader(urls, max_depth=2) + op = UrlLoader(urls, max_depth=2) with SparkContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_spark(ctx.spark)) @@ -520,6 +520,6 @@ def test_recursive_url_loader_ray(self): 'https://app.cnvrg.io/docs/core_concepts/python_sdk_v2.html', 'https://app.cnvrg.io/docs/cli_v2/cnvrgv2_cli.html', 'https://app.cnvrg.io/docs/collections/tutorials.html'] - op = RecursiveUrlLoader(urls, max_depth=2) + op = UrlLoader(urls, max_depth=2) with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_rayds()) \ No newline at end of file diff --git a/RecDP/tests/test_llmutils_pipelines.py b/RecDP/tests/test_llmutils_pipelines.py index f4fa6693..06870952 100644 --- a/RecDP/tests/test_llmutils_pipelines.py +++ b/RecDP/tests/test_llmutils_pipelines.py @@ -188,8 +188,7 @@ def test_llm_rag_url_pipeline(self): pipeline = TextPipeline() ops = [ UrlLoader(["https://www.intc.com/news-events/press-releases/detail/" - "1655/intel-reports-third-quarter-2023-financial-results"], - target_tag='div', target_attrs={'class': 'main-content'}), + "1655/intel-reports-third-quarter-2023-financial-results"]), DocumentSplit(text_splitter='RecursiveCharacterTextSplitter'), DocumentIngestion( vector_store='FAISS', @@ -209,7 +208,7 @@ def test_llm_rag_url_pdf_pipeline(self): ops = [ UrlLoader(["https://www.intc.com/news-events/press-releases/detail/" "1655/intel-reports-third-quarter-2023-financial-results"], - max_depth=2, target_tag='div', target_attrs={'class': 'main-content'}), + max_depth=2), DirectoryLoader("tests/data/press_pdf", glob="**/*.pdf"), RAGTextFix(), DocumentSplit(text_splitter='RecursiveCharacterTextSplitter') @@ -273,7 +272,7 @@ def test_llm_rag_pdf_use_existing_db_pipeline(self): display(ret) def test_llm_rag_pipeline_cnvrg(self): - from pyrecdp.primitives.operations import RecursiveUrlLoader,RAGTextFix,CustomerDocumentSplit,TextCustomerFilter,JsonlWriter + from pyrecdp.primitives.operations import UrlLoader,RAGTextFix,CustomerDocumentSplit,TextCustomerFilter,JsonlWriter from pyrecdp.LLM import TextPipeline def prepare_nltk_model(model, lang): @@ -319,7 +318,7 @@ def chunk_doc(text,max_num_of_words): pipeline = TextPipeline() ops = [ - RecursiveUrlLoader(urls, max_depth=2), + UrlLoader(urls, max_depth=2), RAGTextFix(str_to_replace={'\n###': '', '\n##': '', '\n#': ''}, remove_extra_whitespace=True), CustomerDocumentSplit(func=lambda text: text.split('# ')[1:]), TextCustomerFilter(custom_filter), From 3cd5f9742f6b979ec8231be2a7c420cbf54e8dd8 Mon Sep 17 00:00:00 2001 From: "Yao, Qing" Date: Wed, 20 Dec 2023 17:31:05 +0800 Subject: [PATCH 10/59] Remove unnecessary import in init file. . --- RecDP/pyrecdp/primitives/operations/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecDP/pyrecdp/primitives/operations/__init__.py b/RecDP/pyrecdp/primitives/operations/__init__.py index 31ce03a4..d25f59e5 100644 --- a/RecDP/pyrecdp/primitives/operations/__init__.py +++ b/RecDP/pyrecdp/primitives/operations/__init__.py @@ -65,10 +65,10 @@ from .text_perplexity_score import TextPerplexityScore from .random_select import RandomSelect from .text_ingestion import DocumentIngestion - from .doc_loader import DirectoryLoader, DocumentLoader, UrlLoader, RecursiveUrlLoader, YoutubeLoader + from .doc_loader import DirectoryLoader, DocumentLoader, UrlLoader, YoutubeLoader from .text_to_qa import TextToQA from .table_summary import TableSummary from .text_spell_correct import TextSpellCorrect from .text_contraction_remove import TextContractionRemove except Exception as e: - pass + pass \ No newline at end of file From 263a087cea6f5d8e9ae4af48e11e65ab9be2857e Mon Sep 17 00:00:00 2001 From: "Yao, Qing" Date: Wed, 20 Dec 2023 17:36:21 +0800 Subject: [PATCH 11/59] Fix notebook. . --- RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb | 4 ++-- .../notebooks/llmutils/rag_cnvrg_pipeline_step_by_step.ipynb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb index 41b3a5ae..a098e12f 100644 --- a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb +++ b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb @@ -351,7 +351,7 @@ } ], "source": [ - "from pyrecdp.primitives.operations import RecursiveUrlLoader,RAGTextFix,CustomerDocumentSplit,TextCustomerFilter,DocumentIngestion\n", + "from pyrecdp.primitives.operations import UrlLoader,RAGTextFix,CustomerDocumentSplit,TextCustomerFilter,DocumentIngestion\n", "from pyrecdp.LLM import TextPipeline\n", "import os\n", "\n", @@ -392,7 +392,7 @@ "\n", "pipeline = TextPipeline()\n", "ops = [\n", - " RecursiveUrlLoader(urls, max_depth=2),\n", + " UrlLoader(urls, max_depth=2),\n", " RAGTextFix(str_to_replace={'\\n###': '', '\\n##': '', '\\n#': ''}, remove_extra_whitespace=True),\n", " CustomerDocumentSplit(func=lambda text: text.split('# ')[1:]),\n", " TextCustomerFilter(custom_filter),\n", diff --git a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline_step_by_step.ipynb b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline_step_by_step.ipynb index c947a913..650e0484 100644 --- a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline_step_by_step.ipynb +++ b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline_step_by_step.ipynb @@ -281,8 +281,8 @@ " 'https://app.cnvrg.io/docs/cli_v2/cnvrgv2_cli.html',\n", " 'https://app.cnvrg.io/docs/collections/tutorials.html']\n", "\n", - "from pyrecdp.primitives.operations import RecursiveUrlLoader\n", - "url_loader = RecursiveUrlLoader(urls, max_depth=2)\n", + "from pyrecdp.primitives.operations import UrlLoader\n", + "url_loader = UrlLoader(urls, max_depth=2)\n", "\n", "ds = url_loader.process_rayds()\n", "display(ds.to_pandas())" From 7d906fdcfcd17728caa0298353fcf273a9d5abec Mon Sep 17 00:00:00 2001 From: "Chendi.Xue" Date: Wed, 20 Dec 2023 22:16:36 -0600 Subject: [PATCH 12/59] Update doc_loader.py --- RecDP/pyrecdp/primitives/operations/doc_loader.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/RecDP/pyrecdp/primitives/operations/doc_loader.py b/RecDP/pyrecdp/primitives/operations/doc_loader.py index 5bba870d..72280d09 100644 --- a/RecDP/pyrecdp/primitives/operations/doc_loader.py +++ b/RecDP/pyrecdp/primitives/operations/doc_loader.py @@ -261,12 +261,15 @@ def __init__( requirements = ['bs4', 'markdownify', 'langchain'] if text_to_markdown: - import markdownify - extractor = lambda x: markdownify.markdownify(x) - else: - if extractor is None: + def extractor_with_markdownify(x): + import markdownify + return markdownify.markdownify(x) + extractor = lambda x: extractor_with_markdownify(x) + elif extractor is None: + def extractor_with_bs4(x): from bs4 import BeautifulSoup - extractor = lambda x: BeautifulSoup(x, "html.parser").text + return BeautifulSoup(x, "html.parser").text + extractor = lambda x: extractor_with_bs4(x) settings = { 'urls': urls, From e0c9386a11431557169c5761cd839966efe74f2a Mon Sep 17 00:00:00 2001 From: "Zhang, Chaojun" Date: Thu, 21 Dec 2023 14:56:31 +0000 Subject: [PATCH 13/59] add notebook for document loader, document split and document ingestion --- .../llmutils/rag_cnvrg_pipeline.ipynb | 1062 +++++++++++++++-- RecDP/tests/test_llmutils_pipelines.py | 6 +- 2 files changed, 947 insertions(+), 121 deletions(-) diff --git a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb index a098e12f..97ec52fb 100644 --- a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb +++ b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb @@ -62,7 +62,7 @@ "id": "90ce4efa", "metadata": {}, "source": [ - "Setup and Run RAG Indexer Pipeline" + "### Setup And Run RAG Indexer Pipeline" ] }, { @@ -82,36 +82,768 @@ "name": "stdout", "output_type": "stream", "text": [ - "\u001b[32m2023-12-19 16:55:34.829\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['bs4', 'langchain']\u001b[0m\n", - "\u001b[32m2023-12-19 16:55:34.833\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['ftfy', 'selectolax']\u001b[0m\n", - "\u001b[32m2023-12-19 16:55:34.836\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['langchain']\u001b[0m\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[32m2023-12-19 16:55:34.894\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['bs4', 'langchain']\u001b[0m\n", - "\u001b[32m2023-12-19 16:55:34.897\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['ftfy', 'selectolax']\u001b[0m\n", - "\u001b[32m2023-12-19 16:55:34.900\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['langchain']\u001b[0m\n", - "init ray\n", - "execute with ray started ...\n" + "\u001b[32m2023-12-21 14:52:59.406\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['bs4', 'langchain']\u001b[0m\n", + "\u001b[32m2023-12-21 14:52:59.409\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['ftfy', 'selectolax']\u001b[0m\n", + "\u001b[32m2023-12-21 14:52:59.411\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['ftfy']\u001b[0m\n", + "\u001b[32m2023-12-21 14:52:59.413\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['langchain']\u001b[0m\n", + "\u001b[32m2023-12-21 14:52:59.470\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['bs4', 'langchain']\u001b[0m\n", + "\u001b[32m2023-12-21 14:52:59.473\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['ftfy', 'selectolax']\u001b[0m\n", + "\u001b[32m2023-12-21 14:52:59.475\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['ftfy']\u001b[0m\n", + "\u001b[32m2023-12-21 14:52:59.477\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['langchain']\u001b[0m\n", + "init spark\n", + "Will assign 48 cores and 412513 M memory for spark\n", + "per core memory size is 8.393 GB and shuffle_disk maximum capacity is 8589934592.000 GB\n", + "execute with spark started ...\n", + "DatasetReader\n", + "RecursiveUrlLoader\n", + "RAGTextFix\n", + "CustomerDocumentSplit\n", + "TextCustomerFilter\n", + "CustomerDocumentSplit\n", + "GlobalDeduplicate\n", + "Generate Global Hash started ...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:55:38,001 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 456495104; capacity: 422146228224. Object creation will fail if spilling is required.\n", - "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:55:48,016 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 456441856; capacity: 422146228224. Object creation will fail if spilling is required.\n", - "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:55:58,028 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 456417280; capacity: 422146228224. Object creation will fail if spilling is required.\n" + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:31.086 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:31.208 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.271 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.279 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.315 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.368 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.371 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.398 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.415 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:31.444 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.487 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.532 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.532 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.542 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.543 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.546 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.548 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.562 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.572 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.573 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.588 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.604 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.606 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.666 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.688 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.688 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.699 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.699 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.701 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.742 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.748 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.750 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.750 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.757 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.758 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.782 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.793 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.810 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.817 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.853 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:31.946 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:32.063 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:32.079 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:32.115 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:32.157 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:32.180 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:32.240 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:32.343 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:33.776 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:33.827 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:33.850 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:33.896 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:33.967 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:33.974 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.019 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:34.157 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:34.193 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.203 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.212 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.229 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:34.311 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.345 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.362 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.383 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.394 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.423 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.446 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.467 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.480 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.593 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.689 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:34.711 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.807 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.824 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.866 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.895 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.905 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.949 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:34.995 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:35.028 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:35.059 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:35.203 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:35.253 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:35.400 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:35.402 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:35.569 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:35.598 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:35.697 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:35.783 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:35.802 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:35.898 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:35.960 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:35.993 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:36.093 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:36.178 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:36.493 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:38.301 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:38.383 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:38.389 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:38.389 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:38.496 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:38.587 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:38.616 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:38.815 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:38.879 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:38.914 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:38.918 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.119 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.171 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.357 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.382 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.439 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.446 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.474 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.504 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.869 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.872 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.909 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.928 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.959 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.981 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.981 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.986 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:39.989 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.034 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.053 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.107 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.114 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.130 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.158 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.177 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.199 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.216 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.248 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.305 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.339 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.339 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.379 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.385 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.716 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.825 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.981 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:40.989 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:41.144 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:42.965 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:42.967 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:43.289 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:43.427 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:43.617 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:43.705 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:43.717 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:43.736 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:43.801 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:43.906 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:43.950 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.079 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.088 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.113 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:44.122 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.272 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.396 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.458 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.479 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.562 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.672 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.674 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.740 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.828 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.839 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.880 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.895 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:44.968 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.002 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.169 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.215 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.252 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.256 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.257 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.280 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.298 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.356 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.490 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:45.581 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.603 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.650 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.705 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.722 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.796 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.851 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:45.872 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:46.395 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:46.444 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:47.511 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:48.030 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:48.139 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:48.197 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:48.238 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:48.273 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:48.391 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:48.416 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:48.450 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:48.494 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:48.563 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:48.659 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:48.725 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:48.742 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:48.803 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:48.835 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:48.836 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:48.839 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:48.900 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:48.902 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:48.927 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:48.972 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:48.996 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.025 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.\n", + " warnings.warn(\"Setuptools is replacing distutils.\")\n", + "2023-12-21 14:53:49.077 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.294 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.295 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.300 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.306 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.349 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.364 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.462 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.484 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.504 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.509 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.537 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.565 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.583 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.593 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.605 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.629 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.656 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.725 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.817 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.848 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.923 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:49.951 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + "2023-12-21 14:53:50.150 | INFO | pyrecdp.core.import_utils:check_availability_and_install:52 - check_availability_and_install emoji==2.2.0\n", + " \r" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "\u001b[32m2023-12-19 16:56:00.001\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['farm-haystack', 'farm-haystack[elasticsearch7]']\u001b[0m\n" + " Generate Global Hash took 25.209684751927853 sec\n", + "Generate Global indexing based on hash started ...\n", + " Generate Global indexing based on hash took 0.4185355678200722 sec\n", + "Generate global duplication list started ...\n", + " Generate global duplication list took 0.34351083636283875 sec\n", + "reduce input file based on detected duplication started ...\n", + " reduce input file based on detected duplication took 0.3780368007719517 sec\n", + "DocumentIngestion\n", + "\u001b[32m2023-12-21 14:53:51.410\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mpyrecdp.core.import_utils\u001b[0m:\u001b[36mcheck_availability_and_install\u001b[0m:\u001b[36m47\u001b[0m - \u001b[1mcheck_availability_and_install ['farm-haystack', 'farm-haystack[elasticsearch7]']\u001b[0m\n" ] }, { @@ -141,7 +873,6 @@ "name": "stderr", "output_type": "stream", "text": [ - "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:56:08,042 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 456359936; capacity: 422146228224. Object creation will fail if spilling is required.\n", "WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.\n", "Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.\n", "To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.\n" @@ -165,56 +896,111 @@ "name": "stderr", "output_type": "stream", "text": [ - "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:56:18,054 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 455839744; capacity: 422146228224. Object creation will fail if spilling is required.\n", - "2023-12-19 16:56:21,436\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[Map()->FlatMap()->Filter()->FlatMap()->MapBatches()]\n", - "2023-12-19 16:56:21,438\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", - "2023-12-19 16:56:21,439\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "aaed7a3fc37b404198626b3247b75137", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Running 0: 0%| | 0/20 [00:00 TaskPoolMapOperator[Map()->FlatMap()->Filter()->FlatMap()]\n", - "2023-12-19 16:56:26,363\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", - "2023-12-19 16:56:26,366\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n", + "/root/miniforge3/envs/recdp/lib/python3.10/site-packages/elasticsearch/connection/base.py:200: ElasticsearchWarning: Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.\n", + " warnings.warn(message, category=ElasticsearchWarning)\n" ] }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "a9b523831f6c4c5fa0d23db8e5fb3f7b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Running 0: 0%| | 0/20 [00:00\n", " \n", " \n", - " text\n", + " global_id\n", + " hash\n", " metadata\n", + " text\n", " \n", " \n", " \n", " \n", " 0\n", - " Welcome to cnvrg.io cnvrg.io is a machine lear...\n", + " global_id@17179869184\n", + " 27cc3e8011a124ca3bf75a47fef72ff39721220bb75ce2...\n", " {'description': 'Documentation website for cnv...\n", + " Tutorials and Examples To help you get started...\n", " \n", " \n", " 1\n", - " Dataset Use Datasets to manage data with versi...\n", + " global_id@17179869185\n", + " 218474edcc8258de97665e684b6a91d8b3df965808e563...\n", " {'description': 'Documentation website for cnv...\n", + " Example Projects Build and Deploy an IMDB NLP ...\n", " \n", " \n", " 2\n", - " Use Papers to consolidate comparison across ex...\n", + " global_id@17179869186\n", + " e4443b6da5f362bda0c17d8d807f02b09101dc5d68d7b7...\n", " {'description': 'Documentation website for cnv...\n", + " Workspaces, Experiments and IDEs Run an Experi...\n", " \n", " \n", " 3\n", - " Resource Management With our Dashboard, get a ...\n", + " global_id@17179869187\n", + " 2f57da125db67ff3f1f08cc99bb7ccde9cc7d4d00b0a9f...\n", " {'description': 'Documentation website for cnv...\n", + " Flows and Serving Processing your Dataset with...\n", " \n", " \n", " 4\n", - " AI Library Continual learning and building mac...\n", + " global_id@17179869188\n", + " 231cc3aab439c2431eece36e98e787cdded39f5ed2552a...\n", " {'description': 'Documentation website for cnv...\n", + " Other Setup Slack Integration for Experiments ...\n", " \n", " \n", " ...\n", " ...\n", " ...\n", + " ...\n", + " ...\n", " \n", " \n", - " 900\n", - " Delete a registry To delete a registry from th...\n", + " 876\n", + " global_id@403726925875\n", + " f5ec39ffd11609e32239b918f86d8d84c71692546e46c1...\n", " {'description': 'Documentation website for cnv...\n", + " AND/OR operators To run queries with and/or lo...\n", " \n", " \n", - " 901\n", - " Create an image To create an image, use the fo...\n", + " 877\n", + " global_id@403726925876\n", + " 00e3f9ded7c9a1a91e760679de138e56b2f0d012eb4d20...\n", " {'description': 'Documentation website for cnv...\n", + " Saving queries Once you have searched using a ...\n", " \n", " \n", - " 902\n", - " Get an image To retrieve information about an ...\n", + " 878\n", + " global_id@403726925877\n", + " 2f94364a718ea68a3dc362bc486885ce19762492c8bd05...\n", " {'description': 'Documentation website for cnv...\n", + " Collaborators Making collaboration simpler is ...\n", " \n", " \n", - " 903\n", - " when reffering to an image built from dockerfi...\n", + " 879\n", + " global_id@403726925878\n", + " 07c3441c5dc9adaf1a6ebf6ff315fd08a13c7f32e0b8f6...\n", " {'description': 'Documentation website for cnv...\n", + " Add a collaborator Complete the following step...\n", " \n", " \n", - " 904\n", - " Delete an image To delete an image using its n...\n", + " 880\n", + " global_id@403726925879\n", + " c0314f9ebcc45e8f7b9bc95a2ca79558c3cd0e7cef3741...\n", " {'description': 'Documentation website for cnv...\n", + " Remove a collaborator Complete the following s...\n", " \n", " \n", "\n", - "

905 rows × 2 columns

\n", + "

881 rows × 4 columns

\n", "" ], "text/plain": [ - " text \\\n", - "0 Welcome to cnvrg.io cnvrg.io is a machine lear... \n", - "1 Dataset Use Datasets to manage data with versi... \n", - "2 Use Papers to consolidate comparison across ex... \n", - "3 Resource Management With our Dashboard, get a ... \n", - "4 AI Library Continual learning and building mac... \n", + " global_id \\\n", + "0 global_id@17179869184 \n", + "1 global_id@17179869185 \n", + "2 global_id@17179869186 \n", + "3 global_id@17179869187 \n", + "4 global_id@17179869188 \n", + ".. ... \n", + "876 global_id@403726925875 \n", + "877 global_id@403726925876 \n", + "878 global_id@403726925877 \n", + "879 global_id@403726925878 \n", + "880 global_id@403726925879 \n", + "\n", + " hash \\\n", + "0 27cc3e8011a124ca3bf75a47fef72ff39721220bb75ce2... \n", + "1 218474edcc8258de97665e684b6a91d8b3df965808e563... \n", + "2 e4443b6da5f362bda0c17d8d807f02b09101dc5d68d7b7... \n", + "3 2f57da125db67ff3f1f08cc99bb7ccde9cc7d4d00b0a9f... \n", + "4 231cc3aab439c2431eece36e98e787cdded39f5ed2552a... \n", ".. ... \n", - "900 Delete a registry To delete a registry from th... \n", - "901 Create an image To create an image, use the fo... \n", - "902 Get an image To retrieve information about an ... \n", - "903 when reffering to an image built from dockerfi... \n", - "904 Delete an image To delete an image using its n... \n", + "876 f5ec39ffd11609e32239b918f86d8d84c71692546e46c1... \n", + "877 00e3f9ded7c9a1a91e760679de138e56b2f0d012eb4d20... \n", + "878 2f94364a718ea68a3dc362bc486885ce19762492c8bd05... \n", + "879 07c3441c5dc9adaf1a6ebf6ff315fd08a13c7f32e0b8f6... \n", + "880 c0314f9ebcc45e8f7b9bc95a2ca79558c3cd0e7cef3741... \n", "\n", - " metadata \n", - "0 {'description': 'Documentation website for cnv... \n", - "1 {'description': 'Documentation website for cnv... \n", - "2 {'description': 'Documentation website for cnv... \n", - "3 {'description': 'Documentation website for cnv... \n", - "4 {'description': 'Documentation website for cnv... \n", + " metadata \\\n", + "0 {'description': 'Documentation website for cnv... \n", + "1 {'description': 'Documentation website for cnv... \n", + "2 {'description': 'Documentation website for cnv... \n", + "3 {'description': 'Documentation website for cnv... \n", + "4 {'description': 'Documentation website for cnv... \n", + ".. ... \n", + "876 {'description': 'Documentation website for cnv... \n", + "877 {'description': 'Documentation website for cnv... \n", + "878 {'description': 'Documentation website for cnv... \n", + "879 {'description': 'Documentation website for cnv... \n", + "880 {'description': 'Documentation website for cnv... \n", + "\n", + " text \n", + "0 Tutorials and Examples To help you get started... \n", + "1 Example Projects Build and Deploy an IMDB NLP ... \n", + "2 Workspaces, Experiments and IDEs Run an Experi... \n", + "3 Flows and Serving Processing your Dataset with... \n", + "4 Other Setup Slack Integration for Experiments ... \n", ".. ... \n", - "900 {'description': 'Documentation website for cnv... \n", - "901 {'description': 'Documentation website for cnv... \n", - "902 {'description': 'Documentation website for cnv... \n", - "903 {'description': 'Documentation website for cnv... \n", - "904 {'description': 'Documentation website for cnv... \n", + "876 AND/OR operators To run queries with and/or lo... \n", + "877 Saving queries Once you have searched using a ... \n", + "878 Collaborators Making collaboration simpler is ... \n", + "879 Add a collaborator Complete the following step... \n", + "880 Remove a collaborator Complete the following s... \n", "\n", - "[905 rows x 2 columns]" + "[881 rows x 4 columns]" ] }, "metadata": {}, "output_type": "display_data" - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:56:28,069 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 454561792; capacity: 422146228224. Object creation will fail if spilling is required.\n", - "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:56:38,082 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 454459392; capacity: 422146228224. Object creation will fail if spilling is required.\n", - "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:56:48,096 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 454348800; capacity: 422146228224. Object creation will fail if spilling is required.\n", - "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:56:58,109 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 454307840; capacity: 422146228224. Object creation will fail if spilling is required.\n", - "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:57:08,122 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 454258688; capacity: 422146228224. Object creation will fail if spilling is required.\n", - "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:57:18,135 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 454017024; capacity: 422146228224. Object creation will fail if spilling is required.\n", - "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 16:57:28,149 E 241023 241042] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_16-52-05_854938_240267 is over 95% full, available space: 453988352; capacity: 422146228224. Object creation will fail if spilling is required.\n" - ] } ], "source": [ - "from pyrecdp.primitives.operations import UrlLoader,RAGTextFix,CustomerDocumentSplit,TextCustomerFilter,DocumentIngestion\n", + "from pyrecdp.primitives.operations import RecursiveUrlLoader,RAGTextFix,CustomerDocumentSplit,TextCustomerFilter,DocumentIngestion, GlobalDeduplicate\n", "from pyrecdp.LLM import TextPipeline\n", - "import os\n", "\n", "urls = ['https://app.cnvrg.io/docs/', \n", " 'https://app.cnvrg.io/docs/core_concepts/python_sdk_v2.html',\n", @@ -397,15 +1219,17 @@ " CustomerDocumentSplit(func=lambda text: text.split('# ')[1:]),\n", " TextCustomerFilter(custom_filter),\n", " CustomerDocumentSplit(func=chunk_doc, max_num_of_words=50),\n", + " GlobalDeduplicate(),\n", " DocumentIngestion(\n", " rag_framework='haystack',\n", " vector_store='elasticsearch',\n", - " vector_store_args={'host': 'localhost', 'port': 9200}\n", + " vector_store_args={'host': '10.0.0.132', 'port': 9200}\n", " )\n", "]\n", "pipeline.add_operations(ops)\n", "ds = pipeline.execute()\n", - "display(ds.to_pandas())\n" + "display(ds.toPandas())\n", + "\n" ] } ], diff --git a/RecDP/tests/test_llmutils_pipelines.py b/RecDP/tests/test_llmutils_pipelines.py index 06870952..0afa65aa 100644 --- a/RecDP/tests/test_llmutils_pipelines.py +++ b/RecDP/tests/test_llmutils_pipelines.py @@ -4,6 +4,7 @@ from pathlib import Path import os from IPython.display import display +from pyspark.sql import DataFrame pathlib = str(Path(__file__).parent.parent.resolve()) print(pathlib) @@ -323,8 +324,9 @@ def chunk_doc(text,max_num_of_words): CustomerDocumentSplit(func=lambda text: text.split('# ')[1:]), TextCustomerFilter(custom_filter), CustomerDocumentSplit(func=chunk_doc, max_num_of_words=50), + GlobalDeduplicate(), JsonlWriter("TextPipeline_output_jsonl") ] pipeline.add_operations(ops) - ds = pipeline.execute() - display(ds.to_pandas()) + ds:DataFrame = pipeline.execute() + display(ds.toPandas()) From eb1c0e45339c60a69397092b3484e4f889a73ab1 Mon Sep 17 00:00:00 2001 From: "Zhang, Chaojun" Date: Thu, 21 Dec 2023 15:57:25 +0000 Subject: [PATCH 14/59] add global deduplicate operator for cnvrg rag pipeline --- RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb index 97ec52fb..5db56112 100644 --- a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb +++ b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb @@ -1174,7 +1174,7 @@ } ], "source": [ - "from pyrecdp.primitives.operations import RecursiveUrlLoader,RAGTextFix,CustomerDocumentSplit,TextCustomerFilter,DocumentIngestion, GlobalDeduplicate\n", + "from pyrecdp.primitives.operations import UrlLoader,RAGTextFix,CustomerDocumentSplit,TextCustomerFilter,DocumentIngestion, GlobalDeduplicate\n", "from pyrecdp.LLM import TextPipeline\n", "\n", "urls = ['https://app.cnvrg.io/docs/', \n", @@ -1223,7 +1223,7 @@ " DocumentIngestion(\n", " rag_framework='haystack',\n", " vector_store='elasticsearch',\n", - " vector_store_args={'host': '10.0.0.132', 'port': 9200}\n", + " vector_store_args={'host': 'localhost', 'port': 9200}\n", " )\n", "]\n", "pipeline.add_operations(ops)\n", From 58473aab0e886b2f3016849938e1966551e6bae5 Mon Sep 17 00:00:00 2001 From: "Xue, Chendi" Date: Thu, 21 Dec 2023 06:04:06 +0000 Subject: [PATCH 15/59] update dockerfile to fix ffmeg install Signed-off-by: Xue, Chendi --- RecDP/Dockerfile/DockerfileUbuntu | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RecDP/Dockerfile/DockerfileUbuntu b/RecDP/Dockerfile/DockerfileUbuntu index b61aaccb..1603391f 100644 --- a/RecDP/Dockerfile/DockerfileUbuntu +++ b/RecDP/Dockerfile/DockerfileUbuntu @@ -5,4 +5,5 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-8-jre RUN pip install --upgrade pip RUN pip install pyspark RUN pip install graphviz jupyterlab -RUN apt-get install -y tesseract-ocr \ No newline at end of file +RUN apt-get install -y tesseract-ocr +RUN apt-get update && apt-get install -y ffmpeg \ No newline at end of file From 551b74335dd6e74f4d0ac2d475f42ea17eaab529 Mon Sep 17 00:00:00 2001 From: "Xue, Chendi" Date: Thu, 21 Dec 2023 06:07:09 +0000 Subject: [PATCH 16/59] Fix UT issue from previous PR Signed-off-by: Xue, Chendi --- RecDP/tests/test_llmutils_operations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecDP/tests/test_llmutils_operations.py b/RecDP/tests/test_llmutils_operations.py index 4df110d7..6b13c346 100644 --- a/RecDP/tests/test_llmutils_operations.py +++ b/RecDP/tests/test_llmutils_operations.py @@ -238,7 +238,7 @@ def test_document_load_pdf_ray(self): def test_document_load_ray(self): op = DirectoryLoader("data/llm_data/document") - with RayContext("data/llm_data/tiny_c4_sample.jsonl") as ctx: + with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_rayds()) def test_url_load_ray(self): From 890481031df326988368adb31bab7497588618ac Mon Sep 17 00:00:00 2001 From: "Xue, Chendi" Date: Thu, 21 Dec 2023 16:41:32 +0000 Subject: [PATCH 17/59] fix pipeline and operators UT issue Signed-off-by: Xue, Chendi --- RecDP/tests/test_llmutils_operations.py | 2 +- RecDP/tests/test_llmutils_pipelines.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/RecDP/tests/test_llmutils_operations.py b/RecDP/tests/test_llmutils_operations.py index 6b13c346..5322a633 100644 --- a/RecDP/tests/test_llmutils_operations.py +++ b/RecDP/tests/test_llmutils_operations.py @@ -237,7 +237,7 @@ def test_document_load_pdf_ray(self): ctx.show(op.process_rayds()) def test_document_load_ray(self): - op = DirectoryLoader("data/llm_data/document") + op = DirectoryLoader("tests/data/llm_data/document") with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_rayds()) diff --git a/RecDP/tests/test_llmutils_pipelines.py b/RecDP/tests/test_llmutils_pipelines.py index 0afa65aa..d4b0d78f 100644 --- a/RecDP/tests/test_llmutils_pipelines.py +++ b/RecDP/tests/test_llmutils_pipelines.py @@ -170,6 +170,7 @@ def test_pipeline_execute_pandasdf_ray(self): df = pd.read_parquet("tests/data/PILE/NIH_sample.parquet") ret = pipeline.execute(df) display(ret.to_pandas()) + del pipeline def test_pipeline_execute_pandasdf_spark(self): import pandas as pd @@ -181,6 +182,7 @@ def test_pipeline_execute_pandasdf_spark(self): df = pd.read_parquet("tests/data/PILE/NIH_sample.parquet") ret = pipeline.execute(df) display(ret.toPandas()) + del pipeline def test_llm_rag_url_pipeline(self): model_root_path = os.path.join(RECDP_MODELS_CACHE, "huggingface") @@ -203,6 +205,7 @@ def test_llm_rag_url_pipeline(self): ] pipeline.add_operations(ops) pipeline.execute() + del pipeline def test_llm_rag_url_pdf_pipeline(self): pipeline = TextPipeline() @@ -217,6 +220,7 @@ def test_llm_rag_url_pdf_pipeline(self): pipeline.add_operations(ops) ret = pipeline.execute() display(ret.to_pandas()) + del pipeline def test_llm_rag_pdf_return_db_pipeline(self): model_root_path = os.path.join(RECDP_MODELS_CACHE, "huggingface") @@ -240,6 +244,7 @@ def test_llm_rag_pdf_return_db_pipeline(self): pipeline.add_operations(ops) ret = pipeline.execute() display(ret) + del pipeline def test_llm_rag_pdf_use_existing_db_pipeline(self): from pyrecdp.core.import_utils import import_sentence_transformers @@ -271,6 +276,7 @@ def test_llm_rag_pdf_use_existing_db_pipeline(self): pipeline.add_operations(ops) ret = pipeline.execute() display(ret) + del pipeline def test_llm_rag_pipeline_cnvrg(self): from pyrecdp.primitives.operations import UrlLoader,RAGTextFix,CustomerDocumentSplit,TextCustomerFilter,JsonlWriter @@ -330,3 +336,4 @@ def chunk_doc(text,max_num_of_words): pipeline.add_operations(ops) ds:DataFrame = pipeline.execute() display(ds.toPandas()) + del pipeline \ No newline at end of file From 813b277b19b332968a8ab376d8cb89038e6a8cfd Mon Sep 17 00:00:00 2001 From: "Xue, Chendi" Date: Wed, 29 Nov 2023 22:46:32 +0000 Subject: [PATCH 18/59] update RecDP readme Signed-off-by: Xue, Chendi --- README.md | 2 +- RecDP/README.md | 25 +++++++++---------------- RecDP/resources/recdp_performance.jpg | Bin 336246 -> 299733 bytes 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 39d7c45f..d945d916 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Intel® End-to-End AI Optimization Kit is a composable toolkits for E2E AI optim ## The key components are -* [RecDP](RecDP/README.md): A parallel data processing and feature engineering lib on top of Spark, and extensible to other data processing tools. It provides abstraction API to hide Spark programming complexity, delivers optimized performance through adaptive query plan & strategy, supports critical feature engineering functions on Tabular dataset, and can be easily integrated to third party solutions. +* [RecDP](RecDP/README.md): An one stop toolkit for AI data process. Providing two intel optimized solutions - [Auto Feature Engineering](RecDP/pyrecdp/autofe/README.md) and [LLM Data Preparation](RecDP/pyrecdp/LLM/README.md). Leverage Ray and Spark for distributed data processing. * [Smart Democratization Advisor (SDA)](e2eAIOK/SDA/README.md): A user-guided tool to facilitate automation of built-in model democratization via parameterized models, it generates yaml files based on user choice, provided build-in intelligence through parameterized models and leverage SigOpt for HPO. SDA converts the manual model tuning and optimization to assisted autoML and autoHPO. SDA provides a list of build-in optimized models ranging from RecSys, CV, NLP, ASR and RL. diff --git a/RecDP/README.md b/RecDP/README.md index c1c8eab7..69478f0c 100644 --- a/RecDP/README.md +++ b/RecDP/README.md @@ -2,14 +2,16 @@ We provide intel optimized solution for -* [**Tabular**](pyrecdp/autofe/README.md) - Auto Feature Engineering Pipeline, 50+ essential primitives for feature engineering. -* [**LLM Text**](pyrecdp/LLM/README.md) - 10+ essential primitives for text clean, fixing, deduplication, 4 quality control module, 2 built-in high quality data pipelines. +* [**Auto Feature Engineering**](pyrecdp/autofe/README.md) - Automatical Feature Engineering for Tabular input including 50+ essential primitives. Supporting numerical features, categorical features, text features, time series features, distributed process based on Spark. Feature Importance Analysis based on LightGBM. +* [**LLM Data Preparation**](pyrecdp/LLM/README.md) - 50+ essential operators for RAG data preparation, Finetune Data preparation, Foundation Model text prepration. Supporting text from PDF, words, crawl from URLs, distributed text process based on Ray or Spark, Quality Evaluation based on GPT-3, Divesity, Toxicity, Rouge-similarity, Perplexity. -## Getting Started +## How it works + +Install this tool through pip. ``` DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-8-jre graphviz -pip install pyrecdp --pre +pip install pyrecdp[all] --pre ``` ## RecDP - Tabular @@ -35,26 +37,17 @@ transformed_train_df = pipeline.fit_transform() * Low-code Fault-tolerant Auto-scaling Parallel Pipeline ![LLM Pipeline](resources/llm_pipeline.jpg) -Low Code to build your own pipeline -``` -from pyrecdp.LLM import ResumableTextPipeline -pipeline = ResumableTextPipeline("usecase/finetune_pipeline.yaml") -ret = pipeline.execute() -``` -or ``` from pyrecdp.primitives.operations import * from pyrecdp.LLM import ResumableTextPipeline pipeline = ResumableTextPipeline() ops = [ - JsonlReader("data/"), - URLFilter(), - LengthFilter(), + Url_Loader(urls="your_url"), + DocumentSplit(), ProfanityFilter(), - TextFix(), - LanguageIdentify(), PIIRemoval(), + ... PerfileParquetWriter("ResumableTextPipeline_output") ] pipeline.add_operations(ops) diff --git a/RecDP/resources/recdp_performance.jpg b/RecDP/resources/recdp_performance.jpg index a4fb26f303dc2a2f957da7144474faffa819ce0d..d196a7f19d8bbdf504eec39621931e22cabe7139 100644 GIT binary patch literal 299733 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

uJW?hjUBAkg6Yo2^T=qRLVG(aT3C1hH1> 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 OV*~#mZGh$1*Z%?^C$iN5 literal 336246 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�ZKRX$tI&%fe#gY?|Y;NrdO~h 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
    &lN$z3i@ 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 D_zx}p From 19616bbcf7dcac29887dc84d0f902136b619e42f Mon Sep 17 00:00:00 2001 From: "Chendi.Xue" Date: Wed, 20 Dec 2023 19:28:12 -0600 Subject: [PATCH 19/59] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d945d916..896fe679 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,9 @@ Intel® End-to-End AI Optimization Kit is a composable toolkits for E2E AI optim ## The key components are -* [RecDP](RecDP/README.md): An one stop toolkit for AI data process. Providing two intel optimized solutions - [Auto Feature Engineering](RecDP/pyrecdp/autofe/README.md) and [LLM Data Preparation](RecDP/pyrecdp/LLM/README.md). Leverage Ray and Spark for distributed data processing. +* [RecDP](RecDP/README.md): An one stop toolkit for AI data process. This toolkit provides LLM data processing and Machine Learning Feature Engineering lib in scalable fashion on top of Ray and Spark. It provides simple to use API for data scientists, delivers optimized performance, and can be easily integrated to third party solutions. + * [Auto Feature Engineering](RecDP/pyrecdp/autofe/README.md): Provides an automatical way to generate new features for any tabular dataset which containing numericals, categoricals and text features. It only takes 3 lines of codes to automatically enrich features based on data analysis, statistics, clustering and multi-feature interacting. + * [LLM Data Preparation](RecDP/pyrecdp/LLM/README.md). Provides a parallelled easy-to-use data pipeline for LLM data processing. It supports multiple data source such as jsonlines, pdfs, images, audio/vides. Users will be able to perform data extraction, deduplication(near dedup, rouge, exact), splitting, special_character fixing, types of filtering(length, perplexity, profanity, etc), quality analysis(diversity, GPT3 quality, toxicity, perplexity, etc). This tool also support to save output as jsonlines, parquets, or insertion into VectorStores(FaissStore, ChromaStore, ElasticSearchStore). * [Smart Democratization Advisor (SDA)](e2eAIOK/SDA/README.md): A user-guided tool to facilitate automation of built-in model democratization via parameterized models, it generates yaml files based on user choice, provided build-in intelligence through parameterized models and leverage SigOpt for HPO. SDA converts the manual model tuning and optimization to assisted autoML and autoHPO. SDA provides a list of build-in optimized models ranging from RecSys, CV, NLP, ASR and RL. From 6445456b4d9baf26d85ed4a312d4101b1849c86d Mon Sep 17 00:00:00 2001 From: "Chendi.Xue" Date: Wed, 20 Dec 2023 19:30:58 -0600 Subject: [PATCH 20/59] Update README.md --- RecDP/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RecDP/README.md b/RecDP/README.md index 69478f0c..8d8ac93e 100644 --- a/RecDP/README.md +++ b/RecDP/README.md @@ -2,8 +2,8 @@ We provide intel optimized solution for -* [**Auto Feature Engineering**](pyrecdp/autofe/README.md) - Automatical Feature Engineering for Tabular input including 50+ essential primitives. Supporting numerical features, categorical features, text features, time series features, distributed process based on Spark. Feature Importance Analysis based on LightGBM. -* [**LLM Data Preparation**](pyrecdp/LLM/README.md) - 50+ essential operators for RAG data preparation, Finetune Data preparation, Foundation Model text prepration. Supporting text from PDF, words, crawl from URLs, distributed text process based on Ray or Spark, Quality Evaluation based on GPT-3, Divesity, Toxicity, Rouge-similarity, Perplexity. +* [**Auto Feature Engineering**](pyrecdp/autofe/README.md) - Provides an automatical way to generate new features for any tabular dataset which containing numericals, categoricals and text features. It only takes 3 lines of codes to automatically enrich features based on data analysis, statistics, clustering and multi-feature interacting. +* [**LLM Data Preparation**](pyrecdp/LLM/README.md) - Provides a parallelled easy-to-use data pipeline for LLM data processing. It supports multiple data source such as jsonlines, pdfs, images, audio/vides. Users will be able to perform data extraction, deduplication(near dedup, rouge, exact), splitting, special_character fixing, types of filtering(length, perplexity, profanity, etc), quality analysis(diversity, GPT3 quality, toxicity, perplexity, etc). This tool also support to save output as jsonlines, parquets, or insertion into VectorStores(FaissStore, ChromaStore, ElasticSearchStore). ## How it works @@ -43,7 +43,7 @@ from pyrecdp.LLM import ResumableTextPipeline pipeline = ResumableTextPipeline() ops = [ - Url_Loader(urls="your_url"), + RecursiveUrlLoader(urls, max_depth=2), DocumentSplit(), ProfanityFilter(), PIIRemoval(), @@ -60,4 +60,4 @@ pipeline.execute() ## Dependency * Spark 3.4.* * python 3.* -* Ray 2.7.* \ No newline at end of file +* Ray 2.7.* From 7c1076999bdbfcfb0c65963773b080a9c9e06ee0 Mon Sep 17 00:00:00 2001 From: "Chendi.Xue" Date: Thu, 21 Dec 2023 15:54:17 -0600 Subject: [PATCH 21/59] Update README.md --- RecDP/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecDP/README.md b/RecDP/README.md index 8d8ac93e..937af02d 100644 --- a/RecDP/README.md +++ b/RecDP/README.md @@ -43,7 +43,7 @@ from pyrecdp.LLM import ResumableTextPipeline pipeline = ResumableTextPipeline() ops = [ - RecursiveUrlLoader(urls, max_depth=2), + UrlLoader(urls, max_depth=2), DocumentSplit(), ProfanityFilter(), PIIRemoval(), From 0a22658979239caa8cb5c66426c4e9173ff04461 Mon Sep 17 00:00:00 2001 From: "Chendi.Xue" Date: Thu, 21 Dec 2023 16:55:09 -0600 Subject: [PATCH 22/59] Update README.md --- RecDP/pyrecdp/LLM/README.md | 144 +++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 67 deletions(-) diff --git a/RecDP/pyrecdp/LLM/README.md b/RecDP/pyrecdp/LLM/README.md index 73182a7a..0959a36e 100644 --- a/RecDP/pyrecdp/LLM/README.md +++ b/RecDP/pyrecdp/LLM/README.md @@ -1,54 +1,6 @@ # RecDP LLM - LLM data preparation utility -RecDP LLM is a set of python components that enables quick and easy establish of your own LLM data preparation pipeline. -* 10 general LLM data process components for Foundation model and finetune model training. -* 4 LLM data quality enhancement module for finetune model training -* 2 use cases for foundation model data prepration and finetune model data preparation. - -## General - Foundation & FineTune - -| Type | notebook | Description | supports | Verified dataset & size | -| -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------- | -| [ Directory Loader ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/doc_loader.py#L77) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/document_extract.ipynb) | extract text from a directory | jpg, png, pdf, docx, | RefinedWeb - 1.7 TB | -| [ Document Loader ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/doc_loader.py#L15) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/document_extract.ipynb) | extract text from unstructured format | all [document loaders](https://python.langchain.com/docs/modules/data_connection/document_loaders/) provided in [langchain](https://python.langchain.com/) | RefinedWeb - 1.7 TB | -| [ Text Reader ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_reader.py#L16) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/reader.ipynb) | Read data from directory | jsonl, parquet, | RefinedWeb - 1.7 TB | -| [ Document Split ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_split.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/document_split.ipynb) | split documents | [text splitter](https://python.langchain.com/docs/modules/data_connection/document_transformers/#text-splitters) provided in [langchain](https://python.langchain.com/) and [customer document split](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_split.py#L278) | RefinedWeb - 1.7 TB | -| [ Document Ingestion ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_ingestion.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/document_ingestion.ipynb) | embedding documents and store into vector database | chroma,faiss,elasticsearch | RefinedWeb - 1.7 TB | -| [ Converter ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_converter.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/convert.ipynb) | Read and convert unstructed data to unified format | html, document, image, pdf, ... | RefinedWeb - 1.7 TB | -| [ Filter ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/filter.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/filter.ipynb) | Filter out document based on condition | profanity-based, black-list, url_based, length_based | RedPajama - 2 TB | -| [ Text Bytesize ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_bytesize.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/bytesize.ipynb) | Get text bytes size | | RedPajama - 2 TB | -| [ Text Fixer ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_fixer.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/text_fixer.ipynb) | Clean repeated format in html, latex, codes | html, latex, codes | RefinedWeb - 1.7 TB | -| [ Language Identify ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_language_identify.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/language_identify.ipynb) | Inentify major language type of document | en, zh, fr, de, .. total 25 langs | RedPajama - 2 TB | -| [ Fuzzy Deduplicator ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_deduplication.py#L99) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/fuzzy_deduplication.ipynb) | Detect and reduce duplication based on document context | minHashLSH | PILE - 200 GB | -| [ Global Decuplicator ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_deduplication.py#L194) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/decontamination.ipynb) | Detect and reduce duplication based on exact same content | sha256-hash | RefinedWeb - 1.7 TB, RedPajama - 2 TB | -| [ Rouge Score Decuplicator ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_compare_dedup.py#L157) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/rouge_score_deduplication.ipynb) | Remove similar data by calculating the rough score | alpaca | -| [ Repetition Removal ](#) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/repetition_remove.ipynb) | Detect and reduce repetition context in same document | | RefinedWeb - 1.7 TB, RedPajama - 2 TB | -| [ Document splitter ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_split.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/document_split.ipynb) | Split Document into multiple sub documents | chapter_based, length_based | RefinedWeb - 1.7 TB | -| [ PII Removal ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_pii_remove.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/pii_removal.ipynb) | Detect and replace personal infomation in document | email, phone, ip, username, password | RefinedWeb - 1.7 TB | -| [ User Defined Transform ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_custom.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/custom_map.ipynb) | Easy way to plugin user defined map function | parallel with ray or spark | RefinedWeb - 1.7 TB | -| [ User Defined Filter ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_custom.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/custom_filter.ipynb) | Easy way to plugin user defined filter function | parallel with ray or spark | RefinedWeb - 1.7 TB | -| [ Writer ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_writer.py#L7) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/writer.ipynb) | write data to directory | jsonl, parquet | RefinedWeb - 1.7 TB | -| [ ClassifyWriter ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_writer.py#L47) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/classify.ipynb) | Classify and write data into sub buckets | meta fields, language | RefinedWeb - 1.7 TB | -| [ Prompt Enhancement ](#) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/prompt_enhancement.ipynb) | creates high-complexity instructions from existing instruct-tuned LLM models | PromptSource, self-instruct, evol-instruct(wizardLM) | alpaca | -| [ Tokenization ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](#) | using LLAMA2 tokenizer and save as Megatron | LLAMA2 tokenizer | RefinedWeb - 1.7 TB | - -## LLM Data Quality Analysis - -| Diversity | GPT-3 Scoring | Toxicity | Perplexity | -| :-------- | :---------- | :------------|:------------| -| Visualize the diversity distribution of data | Leverage GPT-3 to scoring | Visualize Toxicity probability | Visualize Perplexity Distribution | -| ![diversity](/RecDP/resources/diversity_analysis.png) | ![quality](/RecDP/resources/quality_scoring.png) | ![toxicity](/RecDP/resources/toxicity_analysis.png)| ![perxicity](/RecDP/resources/perplexity.png) | -| [learn more](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/data_diversity_control.ipynb) | [learn more](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/text_quality_assessment.ipynb) | [learn more](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/toxicity_bias_control.ipynb) | [learn more](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/text_perplexity.ipynb) | - - -## RAG Operators -| Type | notebook | Description | -|-------------------------------------------------------------------------------------------------------------| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |-----------------------------| -| [ UrlLoader ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/doc_loader.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/url_loader.ipynb) | extract text from web pages | -| [ RAGTextFix ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_fixer.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/rag_text_fix.ipynb) | Clean up text for LLM RAG to use. | -| [ TextContractionRemove ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_contraction_remove.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/contraction_remove.ipynb) | Expand contractions in the text using the contractions library. | -| [ TextSpellCorrect ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_spell_correct.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/spelling_correction.ipynb) | pelling correction for text using library [textblog](https://textblob.readthedocs.io/en/dev/) | - +RecDP LLM provides an easy-to-use Resumable, Data Parallel pipeline, covering all general operations used during LLM data preparation. ## Getting Start @@ -58,9 +10,73 @@ DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-8-jre graphviz pip install pyrecdp[LLM] --pre ``` -### Data pipeline +## operation list +### Input +| Type | notebook | Description | supports | engine | +| -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------- | +| [ Directory Loader ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/doc_loader.py#L77) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/document_extract.ipynb) | extract text from a directory of files | jpg, png, pdf, docx, audio, video | ray, spark | +| [ URLLoader ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/doc_loader.py#L219) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/url_loader.ipynb) | extract text from URL links with specified depth crawling | url with depth from 1 - N | ray, spark | +| [ Text Reader ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_reader.py#L16) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/reader.ipynb) | Read data from directory | jsonl, parquet, | ray, spark | +| [ Text Prompt ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_prompt.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/prompt_enhancement.ipynb) | create prompt for different data source | PromptSource | ray, spark | +| [ TableSummary ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/table_summary.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/table_summary.ipynb) | convert markdown table to a paragraph of text | alpaca | ray, spark | +| [ TextToQA ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_to_qa.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/text_to_qa.ipynb) | convert plain text to QnA pairs | alpaca | ray, spark | + + +### Output +| Type | notebook | Description | supports | engine | +| -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------- | +| [ Writer ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_writer.py#L7) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/writer.ipynb) | write data to directory | jsonl, parquet | ray, spark | +| [ ClassifyWriter ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_writer.py#L47) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/classify.ipynb) | Classify and write data into sub buckets | meta fields, language | ray, spark | + +### Filter +| Type | notebook | Description | supports | engine | +| -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------- | +| [ Filter ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/filter.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/filter.ipynb) | 13 different types of Filtering | profanity-based, perplexity, ngram, bad-word, url_based, length_based, special-char ratio, token count, word count | ray, spark | +| [ Language Identify ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_language_identify.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/language_identify.ipynb) | Inentify major language type of document | en, zh, fr, de, .. total 25 langs | ray, spark | + +### Deduplication +| Type | notebook | Description | supports | engine | +| -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------- | +| [ Fuzzy Deduplicator ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_deduplication.py#L99) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/fuzzy_deduplication.ipynb) | Detect and reduce duplication based on document context | minHashLSH | ray, spark | +| [ Global Decuplicator ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_deduplication.py#L194) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/decontamination.ipynb) | Detect and reduce duplication based on exact same content | sha256-hash | ray, spark | +| [ Rouge Score Decuplicator ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_compare_dedup.py#L157) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/rouge_score_deduplication.ipynb) | Remove similar data by calculating the rough score | ray, spark | + -#### 1. RAG Data Pipeline - Build from public HTML [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/rag_pipeline.ipynb) +### RAG operation +| Type | notebook | Description | supports | Verified dataset & size | +| -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------- | +| [ Directory Loader ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/doc_loader.py#L77) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/document_extract.ipynb) | extract text from a directory of files | jpg, png, pdf, docx, audio, video | ray, spark | +| [ URLLoader ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/doc_loader.py#L219) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb) | extract text from URL links with specified depth crawling | url with depth from 1 - N | ray, spark | +| [ RAG Text Fixer ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_fixer.py#L277) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/rag_text_fix.ipynb) | Clean special character and clean for document split | html, markdown | ray, spark | +| [ Document Split ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_split.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/document_split.ipynb) | split documents | RecursiveCharacterTextSplit, MarkdownSplit, NLTKTextSplit, SetenceTransformersTokenSplit, pythonCodeSplit, ParagraphSplit | ray, spark | +| [ Document Ingestion ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_ingestion.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/document_ingestion.ipynb) | embedding documents and store into vector database | chroma, faiss, elasticsearch | ray, spark | + +### Data Clean +| Type | notebook | Description | supports | engine | +| -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------- | +| [ PII Removal ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_pii_remove.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/pii_removal.ipynb) | Detect and replace personal infomation in document | email, phone, ip, username, password | ray, spark | +| [ Text Contraction Remove ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_contraction_remove.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/contraction_remove.ipynb) | Expand contractions in the text using the contractions library. | | ray, spark | +| [ Text Spell Correct ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_spell_correct.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/spelling_correction.ipynb) | pelling correction for text using library [textblog](https://textblob.readthedocs.io/en/dev/) || ray, spark | +| [ Text Fixer ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_fixer.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/text_fixer.ipynb) | Clean repeated format in html, latex, codes | html, latex, codes | ray, spark | + +### Quality Analysis +| Type | notebook | Description | supports | engine | +| -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------- | +| [ Diversity ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_diversityindicate.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/data_diversity_control.ipynb) | Visualize the diversity distribution of data | alpaca | ray, spark | +| [ Quality Scoring ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_qualityscorer.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/text_quality_assessment.ipynb) | analyze text quality | GPT-3 | ray, spark | +| [ Toxicity ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_toxicity.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/toxicity_bias_control.ipynb) | Analyze text toxicity level | NLP model | ray, spark | +| [ Perplexity ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_perplexity_score.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/text_perplexity.ipynb) | Analyze text perplexity | perplexity score | ray, spark | +| [ Gopher ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/filter/text_gopherqualityfilter.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/filter/text_gopherqualityfilter.py) | Analyze text Quality using Gopher method | gopher score | ray, spark | + +### User Defined operation +| Type | notebook | Description | supports | engine | +| -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------- | +| [ User Defined Transform ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_custom.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/custom_map.ipynb) | Easy way to plugin user defined map function | parallel with ray or spark | ray, spark | +| [ User Defined Filter ](https://github.com/intel/e2eAIOK/blob/main/RecDP/pyrecdp/primitives/operations/text_custom.py) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/custom_filter.ipynb) | Easy way to plugin user defined filter function | parallel with ray or spark | ray, spark | + +## Pipeline + +### * RAG Data Pipeline - Build from public HTML [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/rag_pipeline.ipynb) Retrieval-augmented generation (RAG) for large language models (LLMs) aims to improve prediction quality by using an external datastore at inference time to build a richer prompt that includes some combination of context, history, and recent/relevant knowledge (RAG LLMs). Recdp LLM can provide a pipeline for ingesting data from a source and indexing it. We mainly provide the following capabilities. - **Load Data**: Load your data from source. You can use `UrlLoader` or `DirectoryLoader` for this. @@ -95,7 +111,7 @@ pipeline.add_operations(ops) pipeline.execute() ``` -#### 2. Finetune Data Pipeline - Build finetune dataset from Plain Text to QA +### * Finetune Data Pipeline - Build finetune dataset from Plain Text to QA [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/text_to_qa.ipynb) ``` from pyrecdp.LLM import TextPipeline @@ -113,7 +129,8 @@ pipeline.add_operations(ops) pipeline.execute() ``` -#### 3. Finetune Data Pipeline - Downsize public finetune dataset +### * Finetune Data Pipeline - Analysis quality of finetune dataset [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/downsize_dataset.ipynb) + ``` from pyrecdp.LLM import TextPipeline, ResumableTextPipeline @@ -136,11 +153,10 @@ pipeline.add_operations(ops) pipeline.execute() ``` -#### 4. AutoHPO +### * AutoHPO for high quality Finetune dataset [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/pipeline_hpo.ipynb) + -Low-Code configuration with automated operators parameter tuning, allowing user to transform their own raw data toward a high quality dataset with low-effort. We coupled data processing with Quality Analisys as evaluation metrics, which will estimate data's quality before actual model finetuning/inference. -[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/e2eAIOK/blob/main/RecDP/examples/notebooks/llmutils/pipeline_hpo.ipynb) -![image](https://github.com/chaojun-zhang/e2eAIOK/assets/4355494/f20cbde4-7221-4459-93a9-7f16af23377a) +Low-Code configuration with automated operators parameter tuning, allowing user to transform their own raw data toward a high quality dataset with low-effort. We coupled data processing with Quality Analisys as evaluation metrics, which will estimate data's quality before actual model finetuning/inference ``` from pyrecdp.primitives.llmutils.pipeline_hpo import text_pipeline_optimize @@ -153,16 +169,10 @@ output_pipeline_file = "config/pipeline.yaml" text_pipeline_optimize(input_pipeline_file, output_pipeline_file, input_hpo_file) ``` -## * run with individual component - * cmdline mode -``` -python pyrecdp/primitives/llmutils/language_identify.py \ - --data_dir tests/llm_data \ - --language_identify_output_dir output \ - --fasttext_model_dir ./cache/RecDP/models/lib.bin +## Integrate with your existing Ray and Spark -``` - * operation-based API - ray mode + +### * work with existing ray ``` from pyrecdp.primitives.operations import LengthFilter @@ -171,7 +181,7 @@ op = LengthFilter() op.process_rayds(dataset) ``` - * operation-based API - spark mode +### * work with existing spark ``` from pyrecdp.primitives.operations import LengthFilter From b60fb74e777a5ec62b5fc4621f24b865a455a336 Mon Sep 17 00:00:00 2001 From: "Xue, Chendi" Date: Thu, 21 Dec 2023 23:29:15 +0000 Subject: [PATCH 23/59] add copyright to all new components Signed-off-by: Xue, Chendi --- RecDP/pyrecdp/LLM/TextPipeline.py | 16 ++++ RecDP/pyrecdp/LLM/__init__.py | 16 ++++ RecDP/pyrecdp/__init__.py | 16 ++++ RecDP/pyrecdp/autofe/AutoFE.py | 16 ++++ RecDP/pyrecdp/autofe/FeatureEstimator.py | 16 ++++ RecDP/pyrecdp/autofe/FeatureProfiler.py | 16 ++++ RecDP/pyrecdp/autofe/FeatureWrangler.py | 16 ++++ RecDP/pyrecdp/autofe/RelationalBuilder.py | 16 ++++ RecDP/pyrecdp/autofe/TabularPipeline.py | 16 ++++ RecDP/pyrecdp/autofe/__init__.py | 16 ++++ RecDP/pyrecdp/core/__init__.py | 16 ++++ RecDP/pyrecdp/core/cache_utils.py | 16 ++++ RecDP/pyrecdp/core/class_utils.py | 16 ++++ RecDP/pyrecdp/core/dataframe.py | 16 ++++ RecDP/pyrecdp/core/di_graph.py | 16 ++++ RecDP/pyrecdp/core/import_utils.py | 16 ++++ RecDP/pyrecdp/core/model_utils.py | 16 ++++ RecDP/pyrecdp/core/parallel_iterator.py | 16 ++++ RecDP/pyrecdp/core/pipeline.py | 16 ++++ RecDP/pyrecdp/core/registry.py | 16 ++++ RecDP/pyrecdp/core/schema.py | 16 ++++ RecDP/pyrecdp/core/utils.py | 16 ++++ RecDP/pyrecdp/datasets/CESM_breast_cancer.py | 79 ------------------- RecDP/pyrecdp/datasets/__init__.py | 16 ++++ .../pyrecdp/datasets/amazon_product_review.py | 19 ----- RecDP/pyrecdp/datasets/base_api.py | 16 ++++ RecDP/pyrecdp/datasets/download.py | 16 ++++ RecDP/pyrecdp/datasets/ibm_fraud_detect.py | 17 ---- RecDP/pyrecdp/datasets/nyc_taxi.py | 30 ------- RecDP/pyrecdp/datasets/outbrain.py | 22 ------ RecDP/pyrecdp/datasets/pretrained.py | 12 --- RecDP/pyrecdp/datasets/twitter_recsys.py | 13 --- RecDP/pyrecdp/primitives/estimators/base.py | 16 ++++ .../pyrecdp/primitives/estimators/lightgbm.py | 16 ++++ .../pyrecdp/primitives/generators/__init__.py | 16 ++++ RecDP/pyrecdp/primitives/generators/base.py | 16 ++++ RecDP/pyrecdp/primitives/generators/binned.py | 16 ++++ .../pyrecdp/primitives/generators/category.py | 16 ++++ .../pyrecdp/primitives/generators/datetime.py | 16 ++++ RecDP/pyrecdp/primitives/generators/drop.py | 16 ++++ RecDP/pyrecdp/primitives/generators/encode.py | 16 ++++ .../generators/feature_transform.py | 16 ++++ .../generators/featuretools_adaptor.py | 16 ++++ RecDP/pyrecdp/primitives/generators/fillna.py | 16 ++++ .../pyrecdp/primitives/generators/geograph.py | 16 ++++ .../primitives/generators/group_category.py | 16 ++++ RecDP/pyrecdp/primitives/generators/name.py | 16 ++++ RecDP/pyrecdp/primitives/generators/nlp.py | 16 ++++ .../pyrecdp/primitives/generators/relation.py | 16 ++++ RecDP/pyrecdp/primitives/generators/type.py | 16 ++++ RecDP/pyrecdp/primitives/llmutils/classify.py | 16 ++++ RecDP/pyrecdp/primitives/llmutils/convert.py | 16 ++++ .../primitives/llmutils/decontaminate.py | 16 ++++ .../primitives/llmutils/diversity_analysis.py | 16 ++++ .../primitives/llmutils/document/extractor.py | 16 ++++ .../primitives/llmutils/document/reader.py | 16 ++++ .../primitives/llmutils/document/schema.py | 16 ++++ .../primitives/llmutils/document/writer.py | 16 ++++ .../primitives/llmutils/document_extractor.py | 16 ++++ RecDP/pyrecdp/primitives/llmutils/filter.py | 16 ++++ .../primitives/llmutils/global_dedup.py | 16 ++++ .../primitives/llmutils/global_hash.py | 16 ++++ .../llmutils/index_based_reduction.py | 16 ++++ .../primitives/llmutils/language_identify.py | 16 ++++ .../pyrecdp/primitives/llmutils/near_dedup.py | 16 ++++ .../primitives/llmutils/perplexity_score.py | 16 ++++ .../pii/detect/name_password_detection.py | 16 ++++ .../llmutils/pii/detect/phones_detection.py | 16 ++++ .../primitives/llmutils/pii/detect/utils.py | 16 ++++ .../primitives/llmutils/pii/pii_detection.py | 16 ++++ .../primitives/llmutils/pii/pii_redaction.py | 16 ++++ .../pyrecdp/primitives/llmutils/pii_remove.py | 16 ++++ .../primitives/llmutils/pipeline_hpo.py | 16 ++++ .../primitives/llmutils/profanity_filter.py | 16 ++++ .../primitives/llmutils/qa_generate.py | 16 ++++ .../primitives/llmutils/quality_classifier.py | 16 ++++ .../primitives/llmutils/rag_data_extractor.py | 16 ++++ .../primitives/llmutils/rouge_score_dedup.py | 16 ++++ .../primitives/llmutils/sentence_split.py | 16 ++++ .../primitives/llmutils/shrink_jsonl.py | 16 ++++ .../pyrecdp/primitives/llmutils/text_fixer.py | 16 ++++ .../primitives/llmutils/text_normalization.py | 16 ++++ .../primitives/llmutils/text_to_jsonl.py | 16 ++++ .../tokenize_and_save/count_tokens.py | 16 ++++ .../tokenize_and_save/merge_datasets.py | 16 ++++ .../llmutils/tokenize_and_save/run-dp.sh | 14 ++++ .../tokenize_and_save/tokenize_and_save.py | 16 ++++ .../primitives/llmutils/toxicity_score.py | 16 ++++ RecDP/pyrecdp/primitives/llmutils/utils.py | 16 ++++ RecDP/pyrecdp/primitives/operations/base.py | 16 ++++ .../pyrecdp/primitives/operations/category.py | 16 ++++ .../operations/constant/SPECIAL_CHARACTERS.py | 16 ++++ .../operations/constant/__init__.py | 16 ++++ RecDP/pyrecdp/primitives/operations/custom.py | 16 ++++ RecDP/pyrecdp/primitives/operations/data.py | 16 ++++ .../primitives/operations/dataframe.py | 16 ++++ .../primitives/operations/doc_loader.py | 16 ++++ RecDP/pyrecdp/primitives/operations/drop.py | 16 ++++ RecDP/pyrecdp/primitives/operations/encode.py | 16 ++++ .../operations/featuretools_adaptor.py | 16 ++++ RecDP/pyrecdp/primitives/operations/fillna.py | 16 ++++ .../operations/filter/alphanumeric_filter.py | 16 ++++ .../filter/average_line_length_filter.py | 16 ++++ .../operations/filter/badwords_filter.py | 16 ++++ .../primitives/operations/filter/base.py | 16 ++++ .../operations/filter/length_filter.py | 16 ++++ .../filter/maximum_line_length_filter.py | 16 ++++ .../operations/filter/perplexity_filter.py | 16 ++++ .../operations/filter/profanity_filter.py | 16 ++++ .../filter/special_characters_filter.py | 16 ++++ .../filter/text_gopherqualityfilter.py | 16 ++++ .../operations/filter/token_num_filter.py | 16 ++++ .../operations/filter/url_filter.py | 16 ++++ .../operations/filter/word_num_filter.py | 16 ++++ .../filter/word_repetition_filter.py | 16 ++++ .../pyrecdp/primitives/operations/geograph.py | 16 ++++ .../primitives/operations/logging_utils.py | 16 ++++ RecDP/pyrecdp/primitives/operations/merge.py | 16 ++++ RecDP/pyrecdp/primitives/operations/name.py | 16 ++++ .../primitives/operations/random_select.py | 16 ++++ .../primitives/operations/table_summary.py | 16 ++++ .../primitives/operations/text_bytesize.py | 16 ++++ .../operations/text_compare_dedup.py | 16 ++++ .../operations/text_contraction_remove.py | 16 ++++ .../primitives/operations/text_custom.py | 16 ++++ .../operations/text_deduplication.py | 16 ++++ .../operations/text_diversityindicate.py | 16 ++++ .../primitives/operations/text_fixer.py | 16 ++++ .../primitives/operations/text_ingestion.py | 16 ++++ .../operations/text_language_identify.py | 16 ++++ .../primitives/operations/text_normalize.py | 16 ++++ .../operations/text_perplexity_score.py | 16 ++++ .../primitives/operations/text_pii_remove.py | 16 ++++ .../primitives/operations/text_prompt.py | 16 ++++ .../operations/text_qualityscorer.py | 16 ++++ .../primitives/operations/text_reader.py | 16 ++++ .../operations/text_spell_correct.py | 16 ++++ .../primitives/operations/text_split.py | 16 ++++ .../primitives/operations/text_to_qa.py | 16 ++++ .../primitives/operations/text_toxicity.py | 16 ++++ .../primitives/operations/text_writer.py | 16 ++++ RecDP/pyrecdp/primitives/operations/tuple.py | 16 ++++ RecDP/pyrecdp/primitives/operations/type.py | 16 ++++ RecDP/pyrecdp/primitives/operations/utils.py | 16 ++++ .../primitives/profilers/cluster_infer.py | 16 ++++ .../profilers/distribution_infer.py | 16 ++++ RecDP/pyrecdp/primitives/profilers/statics.py | 16 ++++ .../primitives/profilers/time_series_infer.py | 16 ++++ .../primitives/profilers/type_infer.py | 16 ++++ .../spark_data_processor/data_processor.py | 16 ++++ .../spark_data_processor/encoder.py | 16 ++++ .../start-spark-standalone.sh | 14 ++++ .../primitives/spark_data_processor/utils.py | 16 ++++ .../primitives/tabutils/data_preprocess.py | 16 ++++ .../tabutils/feature_normal_transform.py | 16 ++++ .../primitives/tabutils/segmentation.py | 16 ++++ RecDP/pyrecdp/primitives/tabutils/utils.py | 16 ++++ RecDP/pyrecdp/widgets/BaseWidget.py | 16 ++++ RecDP/pyrecdp/widgets/TabWidget.py | 16 ++++ RecDP/pyrecdp/widgets/TableViewWidget.py | 16 ++++ RecDP/setup.py | 64 +++++++-------- e2eAIOK/deltatuner/deltatuner/deltatuner.py | 16 ++++ .../deltatuner/deltatuner/deltatuner_args.py | 16 ++++ .../deltatuner/deltatuner/deltatuner_model.py | 16 ++++ e2eAIOK/deltatuner/deltatuner/mapping.py | 16 ++++ .../deltatuner/scores/compute_de_score.py | 16 ++++ .../deltatuner/scores/transformer_proxy.py | 16 ++++ .../scores/transformer_proxy_ssf.py | 16 ++++ e2eAIOK/deltatuner/deltatuner/scores/utils.py | 16 ++++ .../deltatuner/search/BaseSearchEngine.py | 16 ++++ .../search/EvolutionarySearchEngine.py | 16 ++++ .../deltatuner/search/SearchEngineFactory.py | 16 ++++ e2eAIOK/deltatuner/deltatuner/search/utils.py | 16 ++++ .../deltatuner/tuner/deltatuner_lora.py | 16 ++++ .../deltatuner/tuner/deltatuner_ssf.py | 16 ++++ e2eAIOK/deltatuner/deltatuner/utils/config.py | 16 ++++ 176 files changed, 2717 insertions(+), 223 deletions(-) delete mode 100644 RecDP/pyrecdp/datasets/CESM_breast_cancer.py delete mode 100644 RecDP/pyrecdp/datasets/amazon_product_review.py delete mode 100644 RecDP/pyrecdp/datasets/ibm_fraud_detect.py delete mode 100644 RecDP/pyrecdp/datasets/nyc_taxi.py delete mode 100644 RecDP/pyrecdp/datasets/outbrain.py delete mode 100644 RecDP/pyrecdp/datasets/pretrained.py delete mode 100644 RecDP/pyrecdp/datasets/twitter_recsys.py diff --git a/RecDP/pyrecdp/LLM/TextPipeline.py b/RecDP/pyrecdp/LLM/TextPipeline.py index abf4ac94..9be961a0 100644 --- a/RecDP/pyrecdp/LLM/TextPipeline.py +++ b/RecDP/pyrecdp/LLM/TextPipeline.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.core.di_graph import DiGraph from pyrecdp.core.pipeline import BasePipeline from pyrecdp.primitives.operations import Operation, BaseOperation diff --git a/RecDP/pyrecdp/LLM/__init__.py b/RecDP/pyrecdp/LLM/__init__.py index f2aa37fd..b8e21cd9 100644 --- a/RecDP/pyrecdp/LLM/__init__.py +++ b/RecDP/pyrecdp/LLM/__init__.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.core.import_utils import check_availability_and_install, list_requirements import os, pathlib diff --git a/RecDP/pyrecdp/__init__.py b/RecDP/pyrecdp/__init__.py index 7bdf9a1a..148c926b 100644 --- a/RecDP/pyrecdp/__init__.py +++ b/RecDP/pyrecdp/__init__.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os, sys from pathlib import Path try: diff --git a/RecDP/pyrecdp/autofe/AutoFE.py b/RecDP/pyrecdp/autofe/AutoFE.py index 1746825b..617018ee 100644 --- a/RecDP/pyrecdp/autofe/AutoFE.py +++ b/RecDP/pyrecdp/autofe/AutoFE.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import logging from pyrecdp.core.utils import Timer, infer_problem_type from pyrecdp.core.dataframe import DataFrameAPI diff --git a/RecDP/pyrecdp/autofe/FeatureEstimator.py b/RecDP/pyrecdp/autofe/FeatureEstimator.py index ecbe2010..3386176c 100644 --- a/RecDP/pyrecdp/autofe/FeatureEstimator.py +++ b/RecDP/pyrecdp/autofe/FeatureEstimator.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.primitives.generators import * from pyrecdp.autofe.TabularPipeline import TabularPipeline import logging diff --git a/RecDP/pyrecdp/autofe/FeatureProfiler.py b/RecDP/pyrecdp/autofe/FeatureProfiler.py index 0a373aaa..f4c5703a 100644 --- a/RecDP/pyrecdp/autofe/FeatureProfiler.py +++ b/RecDP/pyrecdp/autofe/FeatureProfiler.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from jinja2 import Environment, PackageLoader from pyrecdp.primitives.profilers import * from pyrecdp.primitives.generators import * diff --git a/RecDP/pyrecdp/autofe/FeatureWrangler.py b/RecDP/pyrecdp/autofe/FeatureWrangler.py index 9b235a6a..54d46d72 100644 --- a/RecDP/pyrecdp/autofe/FeatureWrangler.py +++ b/RecDP/pyrecdp/autofe/FeatureWrangler.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.primitives.generators import * from pyrecdp.primitives.profilers import * from pyrecdp.autofe.TabularPipeline import TabularPipeline diff --git a/RecDP/pyrecdp/autofe/RelationalBuilder.py b/RecDP/pyrecdp/autofe/RelationalBuilder.py index ed645415..d001a682 100644 --- a/RecDP/pyrecdp/autofe/RelationalBuilder.py +++ b/RecDP/pyrecdp/autofe/RelationalBuilder.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.primitives.generators import * from pyrecdp.primitives.profilers import * from pyrecdp.autofe.TabularPipeline import TabularPipeline diff --git a/RecDP/pyrecdp/autofe/TabularPipeline.py b/RecDP/pyrecdp/autofe/TabularPipeline.py index 49668b7d..aeb9f310 100644 --- a/RecDP/pyrecdp/autofe/TabularPipeline.py +++ b/RecDP/pyrecdp/autofe/TabularPipeline.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.primitives.generators import * from pyrecdp.core.schema import DataFrameSchema from pyrecdp.core.di_graph import DiGraph diff --git a/RecDP/pyrecdp/autofe/__init__.py b/RecDP/pyrecdp/autofe/__init__.py index 824b8d32..ec2892f1 100644 --- a/RecDP/pyrecdp/autofe/__init__.py +++ b/RecDP/pyrecdp/autofe/__init__.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.core.import_utils import check_availability_and_install, list_requirements import os, pathlib diff --git a/RecDP/pyrecdp/core/__init__.py b/RecDP/pyrecdp/core/__init__.py index ace8ff5f..9c50b39e 100644 --- a/RecDP/pyrecdp/core/__init__.py +++ b/RecDP/pyrecdp/core/__init__.py @@ -1 +1,17 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.data_processor import DataProcessor as SparkDataProcessor \ No newline at end of file diff --git a/RecDP/pyrecdp/core/cache_utils.py b/RecDP/pyrecdp/core/cache_utils.py index 91a048ce..b95c8b0b 100644 --- a/RecDP/pyrecdp/core/cache_utils.py +++ b/RecDP/pyrecdp/core/cache_utils.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os # Default cache location diff --git a/RecDP/pyrecdp/core/class_utils.py b/RecDP/pyrecdp/core/class_utils.py index 5791412f..cd740cd6 100644 --- a/RecDP/pyrecdp/core/class_utils.py +++ b/RecDP/pyrecdp/core/class_utils.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + def new_instance(module, clazz, **clazz_kwargs): import importlib diff --git a/RecDP/pyrecdp/core/dataframe.py b/RecDP/pyrecdp/core/dataframe.py index 31bcebdf..997f4a3e 100644 --- a/RecDP/pyrecdp/core/dataframe.py +++ b/RecDP/pyrecdp/core/dataframe.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import pandas as pd class DataFrameAPI: diff --git a/RecDP/pyrecdp/core/di_graph.py b/RecDP/pyrecdp/core/di_graph.py index 5fd16596..87c2554d 100644 --- a/RecDP/pyrecdp/core/di_graph.py +++ b/RecDP/pyrecdp/core/di_graph.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from collections import defaultdict class Graph: diff --git a/RecDP/pyrecdp/core/import_utils.py b/RecDP/pyrecdp/core/import_utils.py index 37ce2642..df0dbe83 100644 --- a/RecDP/pyrecdp/core/import_utils.py +++ b/RecDP/pyrecdp/core/import_utils.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os from typing import Optional import pip diff --git a/RecDP/pyrecdp/core/model_utils.py b/RecDP/pyrecdp/core/model_utils.py index c95070de..7cd0731f 100644 --- a/RecDP/pyrecdp/core/model_utils.py +++ b/RecDP/pyrecdp/core/model_utils.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + """ This code is adapted from Alibaba data-juicer https://github.com/alibaba/data-juicer/blob/main/data_juicer/utils/model_utils.py """ diff --git a/RecDP/pyrecdp/core/parallel_iterator.py b/RecDP/pyrecdp/core/parallel_iterator.py index dec15fd4..9b36bd63 100644 --- a/RecDP/pyrecdp/core/parallel_iterator.py +++ b/RecDP/pyrecdp/core/parallel_iterator.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor import multiprocessing from multiprocessing.pool import ThreadPool diff --git a/RecDP/pyrecdp/core/pipeline.py b/RecDP/pyrecdp/core/pipeline.py index 1816f640..4e908182 100644 --- a/RecDP/pyrecdp/core/pipeline.py +++ b/RecDP/pyrecdp/core/pipeline.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.core.di_graph import DiGraph from pyrecdp.primitives.operations import Operation import logging diff --git a/RecDP/pyrecdp/core/registry.py b/RecDP/pyrecdp/core/registry.py index 87a35c03..993e653f 100644 --- a/RecDP/pyrecdp/core/registry.py +++ b/RecDP/pyrecdp/core/registry.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + class Registry(object): def __init__(self, registry_name): self._name = registry_name diff --git a/RecDP/pyrecdp/core/schema.py b/RecDP/pyrecdp/core/schema.py index 815e5002..4f764cf4 100644 --- a/RecDP/pyrecdp/core/schema.py +++ b/RecDP/pyrecdp/core/schema.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from woodwork.column_schema import ColumnSchema from pandas import StringDtype from pyrecdp.core.utils import is_text_series, is_tuple, is_integer_convertable diff --git a/RecDP/pyrecdp/core/utils.py b/RecDP/pyrecdp/core/utils.py index e278841c..34338bcd 100644 --- a/RecDP/pyrecdp/core/utils.py +++ b/RecDP/pyrecdp/core/utils.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import numpy as np import pandas as pd import copy diff --git a/RecDP/pyrecdp/datasets/CESM_breast_cancer.py b/RecDP/pyrecdp/datasets/CESM_breast_cancer.py deleted file mode 100644 index f4ab6bfe..00000000 --- a/RecDP/pyrecdp/datasets/CESM_breast_cancer.py +++ /dev/null @@ -1,79 +0,0 @@ -from .base_api import base_api - -def try_finall(regex, input_str): - import re - ret = re.findall(regex, input_str) - if len(ret) == 0: - return None - else: - return ret[0] - -def extract_info_from_report(report_content): - method = None - side = None - p_id = None - ret = {} - lines = [i for i in report_content.split('\n') if i != ''] - for t in lines: - if 'PATIENT NO.' in t: - p_id = try_finall("\d+", t) - method = None - side = None - elif 'SOFT TISSUE MAMMOGRAPHY REVEALED:' in t: - method = 'DM' - elif 'OPINION:' in t: - method = 'OP' - elif 'CONTRAST ENHANCED SPECTRAL MAMMOGRAPHY REVEALED:' in t: - method = 'CESM' - elif 'Right Breast' in t: - side = "R" - elif 'Left Breast' in t: - side = "L" - else: - if side is None or method is None: - continue - cur_key = f"{side}_{method}" - if cur_key not in ret: - ret[cur_key] = {} - ret[cur_key]['Side'] = side - ret[cur_key]['Patient_ID'] = int(p_id) - ret[cur_key]['Type'] = method - ret[cur_key]['symptoms'] = t - - return ret - -class CESM_breast_cancer(base_api): - def __init__(self, scale = 'full'): - super().__init__() - file_list = { - 'medical_report': "https://wiki.cancerimagingarchive.net/download/attachments/109379611/Medical%20reports%20for%20cases%20.zip?api=v2", - 'manual_annotations': "https://wiki.cancerimagingarchive.net/download/attachments/109379611/Radiology%20manual%20annotations.xlsx?api=v2" - } - - self.saved_path = dict() - self.saved_path['medical_report'] = self.download_url("Medical reports for cases", file_list['medical_report'], unzip = True) - self.saved_path['manual_annotations'] = self.download_url("radiology_manual_annotations.xlsx", file_list['manual_annotations']) - - def to_pandas(self, nrows = None): - import pandas as pd - import os, docx2txt - ret = {} - ret['manual_annotations'] = pd.read_excel(self.saved_path['manual_annotations'], sheet_name="all") - #ret['medical_report'] = {} - medical_report_content = [] - medical_extracted = [] - for f in os.listdir(self.saved_path['medical_report']): - try: - file_content = docx2txt.process(os.path.join(self.saved_path['medical_report'], f)) - except Exception as e: - file_content = "" - Warning(e) - medical_report_content.append(file_content) - ext = extract_info_from_report(file_content) - for side, line in ext.items(): - medical_extracted.append(line) - - ret['medical_report'] = pd.DataFrame.from_records(medical_extracted) - - return ret - \ No newline at end of file diff --git a/RecDP/pyrecdp/datasets/__init__.py b/RecDP/pyrecdp/datasets/__init__.py index 840337d3..3204bd45 100644 --- a/RecDP/pyrecdp/datasets/__init__.py +++ b/RecDP/pyrecdp/datasets/__init__.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.datasets.download import * from pyrecdp.datasets.nyc_taxi import * from pyrecdp.datasets.twitter_recsys import * diff --git a/RecDP/pyrecdp/datasets/amazon_product_review.py b/RecDP/pyrecdp/datasets/amazon_product_review.py deleted file mode 100644 index 239adea8..00000000 --- a/RecDP/pyrecdp/datasets/amazon_product_review.py +++ /dev/null @@ -1,19 +0,0 @@ -from .base_api import base_api - -class amazon_product_review(base_api): - def __init__(self): - super().__init__() - name = "amazon_reviews_us_Books.tsv" - url = "https://s3.amazonaws.com/amazon-reviews-pds/tsv/amazon_reviews_us_Books_v1_00.tsv.gz" - self.saved_path = self.download_url(name, url, unzip = True) - - def to_pandas(self, nrows = None): - import pandas as pd - df = pd.read_table(self.saved_path, on_bad_lines='skip') - - # fix train - df = df.loc[df['star_rating'].apply(lambda x: len(str(x)) <= 3)] - df['star_rating'] = df['star_rating'].astype(float) - - return df - \ No newline at end of file diff --git a/RecDP/pyrecdp/datasets/base_api.py b/RecDP/pyrecdp/datasets/base_api.py index c9a859f6..f379badd 100644 --- a/RecDP/pyrecdp/datasets/base_api.py +++ b/RecDP/pyrecdp/datasets/base_api.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os, requests from tqdm import tqdm import shutil diff --git a/RecDP/pyrecdp/datasets/download.py b/RecDP/pyrecdp/datasets/download.py index 074f46dd..21a43b12 100644 --- a/RecDP/pyrecdp/datasets/download.py +++ b/RecDP/pyrecdp/datasets/download.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base_api import base_api class download(base_api): diff --git a/RecDP/pyrecdp/datasets/ibm_fraud_detect.py b/RecDP/pyrecdp/datasets/ibm_fraud_detect.py deleted file mode 100644 index 125a18ba..00000000 --- a/RecDP/pyrecdp/datasets/ibm_fraud_detect.py +++ /dev/null @@ -1,17 +0,0 @@ -from .base_api import base_api - -class ibm_fraud_detect(base_api): - def __init__(self, scale = 'full'): - super().__init__() - if scale == 'test': - raise NotImplementedError("ibm_fraud_detect test dataset is not created yet") - else: - url = "https://huggingface.co/datasets/Chendi/ibm_transactions/resolve/main/transactions.tgz" - self.saved_path = self.download_url("card_transaction.v1.csv", url, unzip = True) - - def to_pandas(self, scale = 'full'): - import pandas as pd - if scale == 'test': - return pd.read_csv(self.saved_path, nrows = 100000) - return pd.read_csv(self.saved_path) - \ No newline at end of file diff --git a/RecDP/pyrecdp/datasets/nyc_taxi.py b/RecDP/pyrecdp/datasets/nyc_taxi.py deleted file mode 100644 index 9856f168..00000000 --- a/RecDP/pyrecdp/datasets/nyc_taxi.py +++ /dev/null @@ -1,30 +0,0 @@ -from .base_api import base_api - -class nyc_taxi(base_api): - def __init__(self, scale = 'full'): - super().__init__() - self.scale = scale - if scale == 'test': - name = "test_nyc_taxi_fare.parquet" - url = f"https://pyrecdp-testdata.s3.us-west-2.amazonaws.com/{name}" - elif scale == 'test_large': - name = "nyc_taxi_fare_1M.csv" - url = f"https://pyrecdp-testdata.s3.us-west-2.amazonaws.com/{name}" - elif scale == 'full': - name = "nyc_taxi_fare_cleaned.csv" - url = "https://huggingface.co/datasets/Chendi/NYC_TAXI_FARE_CLEANED/resolve/main/nyc_taxi_fare_cleaned.csv" - - self.saved_path = self.download_url(name, url) - - def to_pandas(self, nrows = None): - import pandas as pd - if self.scale == 'test': - return pd.read_parquet(self.saved_path) - elif self.scale == 'test_large': - return pd.read_csv(self.saved_path) - elif self.scale == 'full': - if nrows: - return pd.read_csv(self.saved_path, nrows = nrows) - else: - return pd.read_csv(self.saved_path) - \ No newline at end of file diff --git a/RecDP/pyrecdp/datasets/outbrain.py b/RecDP/pyrecdp/datasets/outbrain.py deleted file mode 100644 index ec12ec47..00000000 --- a/RecDP/pyrecdp/datasets/outbrain.py +++ /dev/null @@ -1,22 +0,0 @@ -from .base_api import base_api - -class outbrain(base_api): - def __init__(self): - super().__init__() - file_list = { - 'clicks': "clicks_train.csv", - 'documents_categories': "documents_categories.csv", - 'documents_entities': "documents_entities.csv", - 'documents_meta': "documents_meta.csv", - 'documents_topics': "documents_topics.csv", - 'events': "events.csv", - 'page_views': "page_views_sample.csv", - 'promoted_content': "promoted_content.csv" - } - - self.saved_path = dict((f_name, self.download_url(f_path, f"https://outbrain-sampled.s3.us-west-2.amazonaws.com/{f_path}")) for f_name, f_path in file_list.items()) - - def to_pandas(self, nrows = None): - import pandas as pd - return dict((f_name, pd.read_csv(f_path)) for f_name, f_path in self.saved_path.items()) - \ No newline at end of file diff --git a/RecDP/pyrecdp/datasets/pretrained.py b/RecDP/pyrecdp/datasets/pretrained.py deleted file mode 100644 index 486e9552..00000000 --- a/RecDP/pyrecdp/datasets/pretrained.py +++ /dev/null @@ -1,12 +0,0 @@ -from .base_api import base_api - -class pretrained(base_api): - def __init__(self): - super().__init__() - - def download(self, model_name): - if model_name == "nyc_taxi_fare": - name = "lightgbm_regression_nyc_taxi_fare_amount.mdl" - url = f"https://pyrecdp-testdata.s3.us-west-2.amazonaws.com/{name}" - return self.download_url(name, url) - \ No newline at end of file diff --git a/RecDP/pyrecdp/datasets/twitter_recsys.py b/RecDP/pyrecdp/datasets/twitter_recsys.py deleted file mode 100644 index bb5b9a69..00000000 --- a/RecDP/pyrecdp/datasets/twitter_recsys.py +++ /dev/null @@ -1,13 +0,0 @@ -from .base_api import base_api - -class twitter_recsys(base_api): - def __init__(self): - super().__init__() - name = "test_twitter_recsys.parquet" - url = f"https://pyrecdp-testdata.s3.us-west-2.amazonaws.com/{name}" - self.saved_path = self.download_url(name, url) - - def to_pandas(self, nrows = None): - import pandas as pd - return pd.read_parquet(self.saved_path) - \ No newline at end of file diff --git a/RecDP/pyrecdp/primitives/estimators/base.py b/RecDP/pyrecdp/primitives/estimators/base.py index fa629ad7..4b47db0a 100644 --- a/RecDP/pyrecdp/primitives/estimators/base.py +++ b/RecDP/pyrecdp/primitives/estimators/base.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.primitives.operations.base import BaseOperation import numpy as np from sklearn.metrics import mean_squared_error, roc_auc_score diff --git a/RecDP/pyrecdp/primitives/estimators/lightgbm.py b/RecDP/pyrecdp/primitives/estimators/lightgbm.py index be200090..a3acd7cd 100644 --- a/RecDP/pyrecdp/primitives/estimators/lightgbm.py +++ b/RecDP/pyrecdp/primitives/estimators/lightgbm.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseEstimator import pandas as pd import lightgbm as lgbm diff --git a/RecDP/pyrecdp/primitives/generators/__init__.py b/RecDP/pyrecdp/primitives/generators/__init__.py index c9922629..2b4fe637 100644 --- a/RecDP/pyrecdp/primitives/generators/__init__.py +++ b/RecDP/pyrecdp/primitives/generators/__init__.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .binned import BinnedFeatureGenerator from .category import CategoryFeatureGenerator from .group_category import GroupCategoryFeatureGenerator diff --git a/RecDP/pyrecdp/primitives/generators/base.py b/RecDP/pyrecdp/primitives/generators/base.py index 0e873a84..dd49ade7 100644 --- a/RecDP/pyrecdp/primitives/generators/base.py +++ b/RecDP/pyrecdp/primitives/generators/base.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.core.schema import SeriesSchema from typing import List diff --git a/RecDP/pyrecdp/primitives/generators/binned.py b/RecDP/pyrecdp/primitives/generators/binned.py index 6017efd2..fab1b071 100644 --- a/RecDP/pyrecdp/primitives/generators/binned.py +++ b/RecDP/pyrecdp/primitives/generators/binned.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseFeatureGenerator as super_class class BinnedFeatureGenerator(super_class): diff --git a/RecDP/pyrecdp/primitives/generators/category.py b/RecDP/pyrecdp/primitives/generators/category.py index 8b958501..3095a361 100644 --- a/RecDP/pyrecdp/primitives/generators/category.py +++ b/RecDP/pyrecdp/primitives/generators/category.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseFeatureGenerator as super_class import pandas as pd from pyrecdp.core.schema import SeriesSchema diff --git a/RecDP/pyrecdp/primitives/generators/datetime.py b/RecDP/pyrecdp/primitives/generators/datetime.py index 25e054ae..9c62ac5a 100644 --- a/RecDP/pyrecdp/primitives/generators/datetime.py +++ b/RecDP/pyrecdp/primitives/generators/datetime.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .featuretools_adaptor import FeaturetoolsBasedFeatureGenerator from featuretools.primitives import ( Day, diff --git a/RecDP/pyrecdp/primitives/generators/drop.py b/RecDP/pyrecdp/primitives/generators/drop.py index da6ed44d..ef2fd764 100644 --- a/RecDP/pyrecdp/primitives/generators/drop.py +++ b/RecDP/pyrecdp/primitives/generators/drop.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseFeatureGenerator as super_class from pyrecdp.primitives.operations import Operation from pyspark.sql import DataFrame as SparkDataFrame diff --git a/RecDP/pyrecdp/primitives/generators/encode.py b/RecDP/pyrecdp/primitives/generators/encode.py index 40a88dac..78f19fa0 100644 --- a/RecDP/pyrecdp/primitives/generators/encode.py +++ b/RecDP/pyrecdp/primitives/generators/encode.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseFeatureGenerator as super_class import pandas as pd from pyrecdp.core.schema import SeriesSchema diff --git a/RecDP/pyrecdp/primitives/generators/feature_transform.py b/RecDP/pyrecdp/primitives/generators/feature_transform.py index 99f887d7..fb178699 100644 --- a/RecDP/pyrecdp/primitives/generators/feature_transform.py +++ b/RecDP/pyrecdp/primitives/generators/feature_transform.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .featuretools_adaptor import FeaturetoolsBasedFeatureGenerator from pyrecdp.primitives.operations import Operation from featuretools.primitives.base import TransformPrimitive diff --git a/RecDP/pyrecdp/primitives/generators/featuretools_adaptor.py b/RecDP/pyrecdp/primitives/generators/featuretools_adaptor.py index c2036305..d257ca0a 100644 --- a/RecDP/pyrecdp/primitives/generators/featuretools_adaptor.py +++ b/RecDP/pyrecdp/primitives/generators/featuretools_adaptor.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseFeatureGenerator as super_class from pyrecdp.core.schema import SeriesSchema from pyrecdp.primitives.operations import Operation diff --git a/RecDP/pyrecdp/primitives/generators/fillna.py b/RecDP/pyrecdp/primitives/generators/fillna.py index 8a618013..68ff2896 100644 --- a/RecDP/pyrecdp/primitives/generators/fillna.py +++ b/RecDP/pyrecdp/primitives/generators/fillna.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseFeatureGenerator as super_class from pyrecdp.core.schema import SeriesSchema from pyrecdp.primitives.operations import Operation diff --git a/RecDP/pyrecdp/primitives/generators/geograph.py b/RecDP/pyrecdp/primitives/generators/geograph.py index 1fb2d2ed..e46e3c27 100644 --- a/RecDP/pyrecdp/primitives/generators/geograph.py +++ b/RecDP/pyrecdp/primitives/generators/geograph.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseFeatureGenerator as super_class from .featuretools_adaptor import FeaturetoolsBasedFeatureGenerator from pyrecdp.core.schema import SeriesSchema diff --git a/RecDP/pyrecdp/primitives/generators/group_category.py b/RecDP/pyrecdp/primitives/generators/group_category.py index b89d8545..871b7181 100644 --- a/RecDP/pyrecdp/primitives/generators/group_category.py +++ b/RecDP/pyrecdp/primitives/generators/group_category.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseFeatureGenerator as super_class import pandas as pd from pyrecdp.core.schema import SeriesSchema diff --git a/RecDP/pyrecdp/primitives/generators/name.py b/RecDP/pyrecdp/primitives/generators/name.py index 95147c6c..377f7a53 100644 --- a/RecDP/pyrecdp/primitives/generators/name.py +++ b/RecDP/pyrecdp/primitives/generators/name.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseFeatureGenerator as super_class from pyrecdp.primitives.operations import Operation diff --git a/RecDP/pyrecdp/primitives/generators/nlp.py b/RecDP/pyrecdp/primitives/generators/nlp.py index 38fb3c65..986f5459 100644 --- a/RecDP/pyrecdp/primitives/generators/nlp.py +++ b/RecDP/pyrecdp/primitives/generators/nlp.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .featuretools_adaptor import FeaturetoolsBasedFeatureGenerator from pyrecdp.core.schema import SeriesSchema from pyrecdp.primitives.operations import Operation diff --git a/RecDP/pyrecdp/primitives/generators/relation.py b/RecDP/pyrecdp/primitives/generators/relation.py index 0987e3cc..70eb54f2 100644 --- a/RecDP/pyrecdp/primitives/generators/relation.py +++ b/RecDP/pyrecdp/primitives/generators/relation.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseFeatureGenerator as super_class import pandas as pd from pyrecdp.core.schema import SeriesSchema, DataFrameSchema diff --git a/RecDP/pyrecdp/primitives/generators/type.py b/RecDP/pyrecdp/primitives/generators/type.py index f0d5c86a..808426d4 100644 --- a/RecDP/pyrecdp/primitives/generators/type.py +++ b/RecDP/pyrecdp/primitives/generators/type.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseFeatureGenerator as super_class from .featuretools_adaptor import FeaturetoolsBasedFeatureGenerator from pyrecdp.core.schema import SeriesSchema diff --git a/RecDP/pyrecdp/primitives/llmutils/classify.py b/RecDP/pyrecdp/primitives/llmutils/classify.py index 75677a3b..34a2d0e7 100644 --- a/RecDP/pyrecdp/primitives/llmutils/classify.py +++ b/RecDP/pyrecdp/primitives/llmutils/classify.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/convert.py b/RecDP/pyrecdp/primitives/llmutils/convert.py index 43e3a4a5..82e0452e 100644 --- a/RecDP/pyrecdp/primitives/llmutils/convert.py +++ b/RecDP/pyrecdp/primitives/llmutils/convert.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse import os, sys from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/decontaminate.py b/RecDP/pyrecdp/primitives/llmutils/decontaminate.py index bca19a36..f4211eb4 100644 --- a/RecDP/pyrecdp/primitives/llmutils/decontaminate.py +++ b/RecDP/pyrecdp/primitives/llmutils/decontaminate.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse import os from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/diversity_analysis.py b/RecDP/pyrecdp/primitives/llmutils/diversity_analysis.py index d9c83541..04e3d5b9 100644 --- a/RecDP/pyrecdp/primitives/llmutils/diversity_analysis.py +++ b/RecDP/pyrecdp/primitives/llmutils/diversity_analysis.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/document/extractor.py b/RecDP/pyrecdp/primitives/llmutils/document/extractor.py index c90541d1..e595d6d3 100644 --- a/RecDP/pyrecdp/primitives/llmutils/document/extractor.py +++ b/RecDP/pyrecdp/primitives/llmutils/document/extractor.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .reader import * from .writer import DocumentWriter diff --git a/RecDP/pyrecdp/primitives/llmutils/document/reader.py b/RecDP/pyrecdp/primitives/llmutils/document/reader.py index 05693788..4200540b 100644 --- a/RecDP/pyrecdp/primitives/llmutils/document/reader.py +++ b/RecDP/pyrecdp/primitives/llmutils/document/reader.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os from abc import abstractmethod, ABC from pathlib import Path diff --git a/RecDP/pyrecdp/primitives/llmutils/document/schema.py b/RecDP/pyrecdp/primitives/llmutils/document/schema.py index df1d4295..24c4f985 100644 --- a/RecDP/pyrecdp/primitives/llmutils/document/schema.py +++ b/RecDP/pyrecdp/primitives/llmutils/document/schema.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from dataclasses import dataclass, asdict import json diff --git a/RecDP/pyrecdp/primitives/llmutils/document/writer.py b/RecDP/pyrecdp/primitives/llmutils/document/writer.py index b2828526..e0fa407e 100644 --- a/RecDP/pyrecdp/primitives/llmutils/document/writer.py +++ b/RecDP/pyrecdp/primitives/llmutils/document/writer.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os from .schema import Document diff --git a/RecDP/pyrecdp/primitives/llmutils/document_extractor.py b/RecDP/pyrecdp/primitives/llmutils/document_extractor.py index 2537b4c3..40b6eb85 100644 --- a/RecDP/pyrecdp/primitives/llmutils/document_extractor.py +++ b/RecDP/pyrecdp/primitives/llmutils/document_extractor.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from typing import Optional, Union from pyrecdp.primitives.llmutils.document.extractor import DocumentExtractor diff --git a/RecDP/pyrecdp/primitives/llmutils/filter.py b/RecDP/pyrecdp/primitives/llmutils/filter.py index 0d67e86c..8c762483 100644 --- a/RecDP/pyrecdp/primitives/llmutils/filter.py +++ b/RecDP/pyrecdp/primitives/llmutils/filter.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse import os import sys diff --git a/RecDP/pyrecdp/primitives/llmutils/global_dedup.py b/RecDP/pyrecdp/primitives/llmutils/global_dedup.py index b0e6dbfe..3e68b3e0 100644 --- a/RecDP/pyrecdp/primitives/llmutils/global_dedup.py +++ b/RecDP/pyrecdp/primitives/llmutils/global_dedup.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/global_hash.py b/RecDP/pyrecdp/primitives/llmutils/global_hash.py index b7c6a2e7..89a3ca8c 100644 --- a/RecDP/pyrecdp/primitives/llmutils/global_hash.py +++ b/RecDP/pyrecdp/primitives/llmutils/global_hash.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse import os, sys from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/index_based_reduction.py b/RecDP/pyrecdp/primitives/llmutils/index_based_reduction.py index e9b04e91..0b833e7b 100644 --- a/RecDP/pyrecdp/primitives/llmutils/index_based_reduction.py +++ b/RecDP/pyrecdp/primitives/llmutils/index_based_reduction.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse import os from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/language_identify.py b/RecDP/pyrecdp/primitives/llmutils/language_identify.py index 8905ecc7..59697a9e 100644 --- a/RecDP/pyrecdp/primitives/llmutils/language_identify.py +++ b/RecDP/pyrecdp/primitives/llmutils/language_identify.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse from pyrecdp.core.utils import Timer import os diff --git a/RecDP/pyrecdp/primitives/llmutils/near_dedup.py b/RecDP/pyrecdp/primitives/llmutils/near_dedup.py index 1c50a3ae..1765d093 100644 --- a/RecDP/pyrecdp/primitives/llmutils/near_dedup.py +++ b/RecDP/pyrecdp/primitives/llmutils/near_dedup.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/perplexity_score.py b/RecDP/pyrecdp/primitives/llmutils/perplexity_score.py index 1dd627af..1dabeee2 100644 --- a/RecDP/pyrecdp/primitives/llmutils/perplexity_score.py +++ b/RecDP/pyrecdp/primitives/llmutils/perplexity_score.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/pii/detect/name_password_detection.py b/RecDP/pyrecdp/primitives/llmutils/pii/detect/name_password_detection.py index 18904a99..bc5b61e9 100644 --- a/RecDP/pyrecdp/primitives/llmutils/pii/detect/name_password_detection.py +++ b/RecDP/pyrecdp/primitives/llmutils/pii/detect/name_password_detection.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from transformers import Pipeline from .utils import PIIEntityType diff --git a/RecDP/pyrecdp/primitives/llmutils/pii/detect/phones_detection.py b/RecDP/pyrecdp/primitives/llmutils/pii/detect/phones_detection.py index c50b9b28..c6e0deaf 100644 --- a/RecDP/pyrecdp/primitives/llmutils/pii/detect/phones_detection.py +++ b/RecDP/pyrecdp/primitives/llmutils/pii/detect/phones_detection.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.core.import_utils import check_availability_and_install def detect_phones(text): diff --git a/RecDP/pyrecdp/primitives/llmutils/pii/detect/utils.py b/RecDP/pyrecdp/primitives/llmutils/pii/detect/utils.py index da5d6d65..adcb5a88 100644 --- a/RecDP/pyrecdp/primitives/llmutils/pii/detect/utils.py +++ b/RecDP/pyrecdp/primitives/llmutils/pii/detect/utils.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from enum import Enum, auto diff --git a/RecDP/pyrecdp/primitives/llmutils/pii/pii_detection.py b/RecDP/pyrecdp/primitives/llmutils/pii/pii_detection.py index bfbb6140..7130c7e1 100644 --- a/RecDP/pyrecdp/primitives/llmutils/pii/pii_detection.py +++ b/RecDP/pyrecdp/primitives/llmutils/pii/pii_detection.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .detect.ip_detection import detect_ip from .detect.emails_detection import detect_email from .detect.phones_detection import detect_phones diff --git a/RecDP/pyrecdp/primitives/llmutils/pii/pii_redaction.py b/RecDP/pyrecdp/primitives/llmutils/pii/pii_redaction.py index b1405650..12c82940 100644 --- a/RecDP/pyrecdp/primitives/llmutils/pii/pii_redaction.py +++ b/RecDP/pyrecdp/primitives/llmutils/pii/pii_redaction.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import json import random import string diff --git a/RecDP/pyrecdp/primitives/llmutils/pii_remove.py b/RecDP/pyrecdp/primitives/llmutils/pii_remove.py index 43200d30..f37d0972 100644 --- a/RecDP/pyrecdp/primitives/llmutils/pii_remove.py +++ b/RecDP/pyrecdp/primitives/llmutils/pii_remove.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse from pyspark.sql.dataframe import DataFrame diff --git a/RecDP/pyrecdp/primitives/llmutils/pipeline_hpo.py b/RecDP/pyrecdp/primitives/llmutils/pipeline_hpo.py index 1fc988d7..82b844d9 100644 --- a/RecDP/pyrecdp/primitives/llmutils/pipeline_hpo.py +++ b/RecDP/pyrecdp/primitives/llmutils/pipeline_hpo.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os from abc import abstractmethod, ABC from dataclasses import dataclass diff --git a/RecDP/pyrecdp/primitives/llmutils/profanity_filter.py b/RecDP/pyrecdp/primitives/llmutils/profanity_filter.py index 766fcae7..7b0741bc 100644 --- a/RecDP/pyrecdp/primitives/llmutils/profanity_filter.py +++ b/RecDP/pyrecdp/primitives/llmutils/profanity_filter.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/qa_generate.py b/RecDP/pyrecdp/primitives/llmutils/qa_generate.py index e2caea3d..e8e25035 100644 --- a/RecDP/pyrecdp/primitives/llmutils/qa_generate.py +++ b/RecDP/pyrecdp/primitives/llmutils/qa_generate.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/quality_classifier.py b/RecDP/pyrecdp/primitives/llmutils/quality_classifier.py index e0939bf3..2e336d16 100644 --- a/RecDP/pyrecdp/primitives/llmutils/quality_classifier.py +++ b/RecDP/pyrecdp/primitives/llmutils/quality_classifier.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/rag_data_extractor.py b/RecDP/pyrecdp/primitives/llmutils/rag_data_extractor.py index d6c97b3f..907e9ab8 100644 --- a/RecDP/pyrecdp/primitives/llmutils/rag_data_extractor.py +++ b/RecDP/pyrecdp/primitives/llmutils/rag_data_extractor.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse from typing import Optional, List diff --git a/RecDP/pyrecdp/primitives/llmutils/rouge_score_dedup.py b/RecDP/pyrecdp/primitives/llmutils/rouge_score_dedup.py index dc3d9be1..8c3df4a7 100644 --- a/RecDP/pyrecdp/primitives/llmutils/rouge_score_dedup.py +++ b/RecDP/pyrecdp/primitives/llmutils/rouge_score_dedup.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/sentence_split.py b/RecDP/pyrecdp/primitives/llmutils/sentence_split.py index 91dedefa..7796c560 100644 --- a/RecDP/pyrecdp/primitives/llmutils/sentence_split.py +++ b/RecDP/pyrecdp/primitives/llmutils/sentence_split.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/llmutils/shrink_jsonl.py b/RecDP/pyrecdp/primitives/llmutils/shrink_jsonl.py index ef80a4a0..25f41541 100644 --- a/RecDP/pyrecdp/primitives/llmutils/shrink_jsonl.py +++ b/RecDP/pyrecdp/primitives/llmutils/shrink_jsonl.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse import os import pickle diff --git a/RecDP/pyrecdp/primitives/llmutils/text_fixer.py b/RecDP/pyrecdp/primitives/llmutils/text_fixer.py index 4cf9a949..9ba5d725 100644 --- a/RecDP/pyrecdp/primitives/llmutils/text_fixer.py +++ b/RecDP/pyrecdp/primitives/llmutils/text_fixer.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/text_normalization.py b/RecDP/pyrecdp/primitives/llmutils/text_normalization.py index c9245aa2..a3972ffe 100644 --- a/RecDP/pyrecdp/primitives/llmutils/text_normalization.py +++ b/RecDP/pyrecdp/primitives/llmutils/text_normalization.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse import os, sys from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/text_to_jsonl.py b/RecDP/pyrecdp/primitives/llmutils/text_to_jsonl.py index 5b739f16..9dabfca0 100644 --- a/RecDP/pyrecdp/primitives/llmutils/text_to_jsonl.py +++ b/RecDP/pyrecdp/primitives/llmutils/text_to_jsonl.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse import os from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/count_tokens.py b/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/count_tokens.py index b53b582c..d88a89cb 100644 --- a/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/count_tokens.py +++ b/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/count_tokens.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from indexed_dataset import MMapIndexedDataset from transformers import AutoTokenizer diff --git a/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/merge_datasets.py b/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/merge_datasets.py index 0f16bb7c..37936252 100644 --- a/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/merge_datasets.py +++ b/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/merge_datasets.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + """this script is for merging multiple megatron-style data files.""" import os diff --git a/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/run-dp.sh b/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/run-dp.sh index 983b0d27..d6a4afa8 100755 --- a/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/run-dp.sh +++ b/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/run-dp.sh @@ -1,3 +1,17 @@ +# Copyright 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + start=`date +%s` echo -e "\n distributed tokenization with ray for Book" diff --git a/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/tokenize_and_save.py b/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/tokenize_and_save.py index a1f375e1..6b7f8a83 100644 --- a/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/tokenize_and_save.py +++ b/RecDP/pyrecdp/primitives/llmutils/tokenize_and_save/tokenize_and_save.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + """ this script is for tokenizing various data input in json format and saving to megatron-format. """ diff --git a/RecDP/pyrecdp/primitives/llmutils/toxicity_score.py b/RecDP/pyrecdp/primitives/llmutils/toxicity_score.py index 96dcc9af..b9b1172c 100644 --- a/RecDP/pyrecdp/primitives/llmutils/toxicity_score.py +++ b/RecDP/pyrecdp/primitives/llmutils/toxicity_score.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import argparse from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/llmutils/utils.py b/RecDP/pyrecdp/primitives/llmutils/utils.py index f10d33b2..a0e56d01 100644 --- a/RecDP/pyrecdp/primitives/llmutils/utils.py +++ b/RecDP/pyrecdp/primitives/llmutils/utils.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os, sys import time from pyrecdp.core.import_utils import check_availability_and_install diff --git a/RecDP/pyrecdp/primitives/operations/base.py b/RecDP/pyrecdp/primitives/operations/base.py index 9f743508..05b768f4 100644 --- a/RecDP/pyrecdp/primitives/operations/base.py +++ b/RecDP/pyrecdp/primitives/operations/base.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import json from dataclasses import dataclass from functools import wraps diff --git a/RecDP/pyrecdp/primitives/operations/category.py b/RecDP/pyrecdp/primitives/operations/category.py index 99f84acd..19db9c87 100644 --- a/RecDP/pyrecdp/primitives/operations/category.py +++ b/RecDP/pyrecdp/primitives/operations/category.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseOperation, AUTOFEOPERATORS import pandas as pd from pyspark.sql import DataFrame as SparkDataFrame diff --git a/RecDP/pyrecdp/primitives/operations/constant/SPECIAL_CHARACTERS.py b/RecDP/pyrecdp/primitives/operations/constant/SPECIAL_CHARACTERS.py index b535f24d..a0368e84 100644 --- a/RecDP/pyrecdp/primitives/operations/constant/SPECIAL_CHARACTERS.py +++ b/RecDP/pyrecdp/primitives/operations/constant/SPECIAL_CHARACTERS.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import string from pyrecdp.core.import_utils import check_availability_and_install diff --git a/RecDP/pyrecdp/primitives/operations/constant/__init__.py b/RecDP/pyrecdp/primitives/operations/constant/__init__.py index 0d75243d..f4712f10 100644 --- a/RecDP/pyrecdp/primitives/operations/constant/__init__.py +++ b/RecDP/pyrecdp/primitives/operations/constant/__init__.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + HF_TOKENIZER = 'EleutherAI/pythia-6.9b-deduped' VARIOUS_WHITESPACES = { diff --git a/RecDP/pyrecdp/primitives/operations/custom.py b/RecDP/pyrecdp/primitives/operations/custom.py index 41cf85ff..b773de22 100644 --- a/RecDP/pyrecdp/primitives/operations/custom.py +++ b/RecDP/pyrecdp/primitives/operations/custom.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseOperation, AUTOFEOPERATORS import copy diff --git a/RecDP/pyrecdp/primitives/operations/data.py b/RecDP/pyrecdp/primitives/operations/data.py index 92b624d0..d29eb70a 100644 --- a/RecDP/pyrecdp/primitives/operations/data.py +++ b/RecDP/pyrecdp/primitives/operations/data.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseOperation, AUTOFEOPERATORS import pandas as pd diff --git a/RecDP/pyrecdp/primitives/operations/dataframe.py b/RecDP/pyrecdp/primitives/operations/dataframe.py index 75406dd6..8848d4d2 100644 --- a/RecDP/pyrecdp/primitives/operations/dataframe.py +++ b/RecDP/pyrecdp/primitives/operations/dataframe.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import numpy as np import time import pandas as pd diff --git a/RecDP/pyrecdp/primitives/operations/doc_loader.py b/RecDP/pyrecdp/primitives/operations/doc_loader.py index 72280d09..198bf94d 100644 --- a/RecDP/pyrecdp/primitives/operations/doc_loader.py +++ b/RecDP/pyrecdp/primitives/operations/doc_loader.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os import re from typing import Optional, List, Callable, Union, Sequence diff --git a/RecDP/pyrecdp/primitives/operations/drop.py b/RecDP/pyrecdp/primitives/operations/drop.py index 99e9f8f1..38e3fec1 100644 --- a/RecDP/pyrecdp/primitives/operations/drop.py +++ b/RecDP/pyrecdp/primitives/operations/drop.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseOperation, AUTOFEOPERATORS import pandas as pd from pyspark.sql import DataFrame as SparkDataFrame diff --git a/RecDP/pyrecdp/primitives/operations/encode.py b/RecDP/pyrecdp/primitives/operations/encode.py index 651cb072..88892de0 100644 --- a/RecDP/pyrecdp/primitives/operations/encode.py +++ b/RecDP/pyrecdp/primitives/operations/encode.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseOperation, AUTOFEOPERATORS import pandas as pd from pyspark.sql import DataFrame as SparkDataFrame diff --git a/RecDP/pyrecdp/primitives/operations/featuretools_adaptor.py b/RecDP/pyrecdp/primitives/operations/featuretools_adaptor.py index b2e19965..da1efe21 100644 --- a/RecDP/pyrecdp/primitives/operations/featuretools_adaptor.py +++ b/RecDP/pyrecdp/primitives/operations/featuretools_adaptor.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseOperation import copy from pyrecdp.core.utils import class_name_fix diff --git a/RecDP/pyrecdp/primitives/operations/fillna.py b/RecDP/pyrecdp/primitives/operations/fillna.py index c34273e7..17ea3500 100644 --- a/RecDP/pyrecdp/primitives/operations/fillna.py +++ b/RecDP/pyrecdp/primitives/operations/fillna.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseOperation, AUTOFEOPERATORS import copy diff --git a/RecDP/pyrecdp/primitives/operations/filter/alphanumeric_filter.py b/RecDP/pyrecdp/primitives/operations/filter/alphanumeric_filter.py index 7432b97a..ec24568e 100644 --- a/RecDP/pyrecdp/primitives/operations/filter/alphanumeric_filter.py +++ b/RecDP/pyrecdp/primitives/operations/filter/alphanumeric_filter.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import sys from pyrecdp.primitives.operations.base import LLMOPERATORS diff --git a/RecDP/pyrecdp/primitives/operations/filter/average_line_length_filter.py b/RecDP/pyrecdp/primitives/operations/filter/average_line_length_filter.py index 03024747..72e69f6f 100644 --- a/RecDP/pyrecdp/primitives/operations/filter/average_line_length_filter.py +++ b/RecDP/pyrecdp/primitives/operations/filter/average_line_length_filter.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import sys from pyrecdp.primitives.operations.base import LLMOPERATORS diff --git a/RecDP/pyrecdp/primitives/operations/filter/badwords_filter.py b/RecDP/pyrecdp/primitives/operations/filter/badwords_filter.py index 9187cf7f..fa931906 100644 --- a/RecDP/pyrecdp/primitives/operations/filter/badwords_filter.py +++ b/RecDP/pyrecdp/primitives/operations/filter/badwords_filter.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.primitives.operations.base import LLMOPERATORS from pyrecdp.primitives.operations.filter.base import BaseFilter diff --git a/RecDP/pyrecdp/primitives/operations/filter/base.py b/RecDP/pyrecdp/primitives/operations/filter/base.py index 940f9348..04a55be0 100644 --- a/RecDP/pyrecdp/primitives/operations/filter/base.py +++ b/RecDP/pyrecdp/primitives/operations/filter/base.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyspark.sql import DataFrame from ray.data import Dataset diff --git a/RecDP/pyrecdp/primitives/operations/filter/length_filter.py b/RecDP/pyrecdp/primitives/operations/filter/length_filter.py index 768ba862..73bbca87 100644 --- a/RecDP/pyrecdp/primitives/operations/filter/length_filter.py +++ b/RecDP/pyrecdp/primitives/operations/filter/length_filter.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.primitives.operations.base import LLMOPERATORS from pyrecdp.primitives.operations.filter.base import BaseFilter diff --git a/RecDP/pyrecdp/primitives/operations/filter/maximum_line_length_filter.py b/RecDP/pyrecdp/primitives/operations/filter/maximum_line_length_filter.py index 4541f7ec..227945e8 100644 --- a/RecDP/pyrecdp/primitives/operations/filter/maximum_line_length_filter.py +++ b/RecDP/pyrecdp/primitives/operations/filter/maximum_line_length_filter.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import sys from pyrecdp.primitives.operations.base import LLMOPERATORS diff --git a/RecDP/pyrecdp/primitives/operations/filter/perplexity_filter.py b/RecDP/pyrecdp/primitives/operations/filter/perplexity_filter.py index 3506a146..48f7ad95 100644 --- a/RecDP/pyrecdp/primitives/operations/filter/perplexity_filter.py +++ b/RecDP/pyrecdp/primitives/operations/filter/perplexity_filter.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import sys from pyrecdp.core.model_utils import get_model, prepare_model diff --git a/RecDP/pyrecdp/primitives/operations/filter/profanity_filter.py b/RecDP/pyrecdp/primitives/operations/filter/profanity_filter.py index aeba132f..167dcbe0 100644 --- a/RecDP/pyrecdp/primitives/operations/filter/profanity_filter.py +++ b/RecDP/pyrecdp/primitives/operations/filter/profanity_filter.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.primitives.operations.base import LLMOPERATORS from pyrecdp.primitives.operations.filter.base import BaseFilter diff --git a/RecDP/pyrecdp/primitives/operations/filter/special_characters_filter.py b/RecDP/pyrecdp/primitives/operations/filter/special_characters_filter.py index bc7b26ab..ca62b5b9 100644 --- a/RecDP/pyrecdp/primitives/operations/filter/special_characters_filter.py +++ b/RecDP/pyrecdp/primitives/operations/filter/special_characters_filter.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.primitives.operations.base import LLMOPERATORS from pyrecdp.primitives.operations.filter.base import BaseFilter diff --git a/RecDP/pyrecdp/primitives/operations/filter/text_gopherqualityfilter.py b/RecDP/pyrecdp/primitives/operations/filter/text_gopherqualityfilter.py index 2b662a8b..c2ca8b66 100644 --- a/RecDP/pyrecdp/primitives/operations/filter/text_gopherqualityfilter.py +++ b/RecDP/pyrecdp/primitives/operations/filter/text_gopherqualityfilter.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.primitives.operations.filter.base import BaseFilter from pyrecdp.primitives.operations.base import LLMOPERATORS, statistics_decorator import re diff --git a/RecDP/pyrecdp/primitives/operations/filter/token_num_filter.py b/RecDP/pyrecdp/primitives/operations/filter/token_num_filter.py index d577ee1b..04147ed0 100644 --- a/RecDP/pyrecdp/primitives/operations/filter/token_num_filter.py +++ b/RecDP/pyrecdp/primitives/operations/filter/token_num_filter.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import sys from pyrecdp.core.model_utils import get_model, prepare_model diff --git a/RecDP/pyrecdp/primitives/operations/filter/url_filter.py b/RecDP/pyrecdp/primitives/operations/filter/url_filter.py index 591a89d9..5cb2a322 100644 --- a/RecDP/pyrecdp/primitives/operations/filter/url_filter.py +++ b/RecDP/pyrecdp/primitives/operations/filter/url_filter.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from functools import lru_cache from pyrecdp.primitives.operations.filter.base import BaseFilter diff --git a/RecDP/pyrecdp/primitives/operations/filter/word_num_filter.py b/RecDP/pyrecdp/primitives/operations/filter/word_num_filter.py index a2c34500..6b9ea4d6 100644 --- a/RecDP/pyrecdp/primitives/operations/filter/word_num_filter.py +++ b/RecDP/pyrecdp/primitives/operations/filter/word_num_filter.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import sys from pyrecdp.core.model_utils import get_model diff --git a/RecDP/pyrecdp/primitives/operations/filter/word_repetition_filter.py b/RecDP/pyrecdp/primitives/operations/filter/word_repetition_filter.py index a42af2f7..f618af2d 100644 --- a/RecDP/pyrecdp/primitives/operations/filter/word_repetition_filter.py +++ b/RecDP/pyrecdp/primitives/operations/filter/word_repetition_filter.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.core.model_utils import get_model, prepare_model from pyrecdp.primitives.operations.utils import get_words_from_document, words_refinement from pyrecdp.primitives.operations.base import LLMOPERATORS diff --git a/RecDP/pyrecdp/primitives/operations/geograph.py b/RecDP/pyrecdp/primitives/operations/geograph.py index 8082c888..afebee20 100644 --- a/RecDP/pyrecdp/primitives/operations/geograph.py +++ b/RecDP/pyrecdp/primitives/operations/geograph.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseOperation, AUTOFEOPERATORS from .featuretools_adaptor import FeaturetoolsOperation import copy diff --git a/RecDP/pyrecdp/primitives/operations/logging_utils.py b/RecDP/pyrecdp/primitives/operations/logging_utils.py index b3f43d27..fa130ab5 100644 --- a/RecDP/pyrecdp/primitives/operations/logging_utils.py +++ b/RecDP/pyrecdp/primitives/operations/logging_utils.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import logging import sys from loguru import logger diff --git a/RecDP/pyrecdp/primitives/operations/merge.py b/RecDP/pyrecdp/primitives/operations/merge.py index e5e7e868..9e85c6b5 100644 --- a/RecDP/pyrecdp/primitives/operations/merge.py +++ b/RecDP/pyrecdp/primitives/operations/merge.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseOperation, AUTOFEOPERATORS import pandas as pd from .dataframe import * diff --git a/RecDP/pyrecdp/primitives/operations/name.py b/RecDP/pyrecdp/primitives/operations/name.py index 02344792..246b6f93 100644 --- a/RecDP/pyrecdp/primitives/operations/name.py +++ b/RecDP/pyrecdp/primitives/operations/name.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseOperation, AUTOFEOPERATORS import copy diff --git a/RecDP/pyrecdp/primitives/operations/random_select.py b/RecDP/pyrecdp/primitives/operations/random_select.py index e195a4c6..e540f8ac 100644 --- a/RecDP/pyrecdp/primitives/operations/random_select.py +++ b/RecDP/pyrecdp/primitives/operations/random_select.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseLLMOperation, LLMOPERATORS from ray.data import Dataset from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/operations/table_summary.py b/RecDP/pyrecdp/primitives/operations/table_summary.py index c02dfeae..9aadb73e 100644 --- a/RecDP/pyrecdp/primitives/operations/table_summary.py +++ b/RecDP/pyrecdp/primitives/operations/table_summary.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseLLMOperation, LLMOPERATORS import ray from ray.data import Dataset diff --git a/RecDP/pyrecdp/primitives/operations/text_bytesize.py b/RecDP/pyrecdp/primitives/operations/text_bytesize.py index ee3673a0..4fe189f0 100644 --- a/RecDP/pyrecdp/primitives/operations/text_bytesize.py +++ b/RecDP/pyrecdp/primitives/operations/text_bytesize.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseLLMOperation, LLMOPERATORS from ray.data import Dataset from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/operations/text_compare_dedup.py b/RecDP/pyrecdp/primitives/operations/text_compare_dedup.py index cab269e4..22daaae2 100644 --- a/RecDP/pyrecdp/primitives/operations/text_compare_dedup.py +++ b/RecDP/pyrecdp/primitives/operations/text_compare_dedup.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseLLMOperation, LLMOPERATORS, statistics_decorator from ray.data import Dataset from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/operations/text_contraction_remove.py b/RecDP/pyrecdp/primitives/operations/text_contraction_remove.py index fb91822c..c91ddb46 100644 --- a/RecDP/pyrecdp/primitives/operations/text_contraction_remove.py +++ b/RecDP/pyrecdp/primitives/operations/text_contraction_remove.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from ray.data import Dataset from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/operations/text_custom.py b/RecDP/pyrecdp/primitives/operations/text_custom.py index 382c5dbb..9db0960a 100644 --- a/RecDP/pyrecdp/primitives/operations/text_custom.py +++ b/RecDP/pyrecdp/primitives/operations/text_custom.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from functools import partial from typing import Optional, Dict diff --git a/RecDP/pyrecdp/primitives/operations/text_deduplication.py b/RecDP/pyrecdp/primitives/operations/text_deduplication.py index 0c86c12c..57a32f9b 100644 --- a/RecDP/pyrecdp/primitives/operations/text_deduplication.py +++ b/RecDP/pyrecdp/primitives/operations/text_deduplication.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseLLMOperation, LLMOPERATORS, statistics_decorator from ray.data import Dataset from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/operations/text_diversityindicate.py b/RecDP/pyrecdp/primitives/operations/text_diversityindicate.py index 4d2494ce..c720a9a4 100644 --- a/RecDP/pyrecdp/primitives/operations/text_diversityindicate.py +++ b/RecDP/pyrecdp/primitives/operations/text_diversityindicate.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + # This tool is referred from alibaba data juicer project and used for # analyzing the verb-noun structure of the SFT dataset and plots its diversity in sunburst format. diff --git a/RecDP/pyrecdp/primitives/operations/text_fixer.py b/RecDP/pyrecdp/primitives/operations/text_fixer.py index 1e33fb35..fc795b56 100644 --- a/RecDP/pyrecdp/primitives/operations/text_fixer.py +++ b/RecDP/pyrecdp/primitives/operations/text_fixer.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseLLMOperation, LLMOPERATORS from ray.data import Dataset from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/operations/text_ingestion.py b/RecDP/pyrecdp/primitives/operations/text_ingestion.py index 02677504..309db1a4 100644 --- a/RecDP/pyrecdp/primitives/operations/text_ingestion.py +++ b/RecDP/pyrecdp/primitives/operations/text_ingestion.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os.path from abc import ABC, abstractmethod from typing import Optional, Dict, Union, Iterable, Any, cast diff --git a/RecDP/pyrecdp/primitives/operations/text_language_identify.py b/RecDP/pyrecdp/primitives/operations/text_language_identify.py index 247bb943..3ace00fc 100644 --- a/RecDP/pyrecdp/primitives/operations/text_language_identify.py +++ b/RecDP/pyrecdp/primitives/operations/text_language_identify.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseLLMOperation, LLMOPERATORS from ray.data import Dataset from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/operations/text_normalize.py b/RecDP/pyrecdp/primitives/operations/text_normalize.py index 5e9eda80..fde21f5e 100644 --- a/RecDP/pyrecdp/primitives/operations/text_normalize.py +++ b/RecDP/pyrecdp/primitives/operations/text_normalize.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseLLMOperation, LLMOPERATORS from ray.data import Dataset from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/operations/text_perplexity_score.py b/RecDP/pyrecdp/primitives/operations/text_perplexity_score.py index 586cd46a..4f68e1b9 100644 --- a/RecDP/pyrecdp/primitives/operations/text_perplexity_score.py +++ b/RecDP/pyrecdp/primitives/operations/text_perplexity_score.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseLLMOperation, statistics_decorator from ray.data import Dataset from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/operations/text_pii_remove.py b/RecDP/pyrecdp/primitives/operations/text_pii_remove.py index a14bd15f..723c594b 100644 --- a/RecDP/pyrecdp/primitives/operations/text_pii_remove.py +++ b/RecDP/pyrecdp/primitives/operations/text_pii_remove.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseLLMOperation, LLMOPERATORS from ray.data import Dataset from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/operations/text_prompt.py b/RecDP/pyrecdp/primitives/operations/text_prompt.py index 14755138..6680fb73 100644 --- a/RecDP/pyrecdp/primitives/operations/text_prompt.py +++ b/RecDP/pyrecdp/primitives/operations/text_prompt.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os, shutil, subprocess, sys, inspect from .base import BaseLLMOperation, LLMOPERATORS diff --git a/RecDP/pyrecdp/primitives/operations/text_qualityscorer.py b/RecDP/pyrecdp/primitives/operations/text_qualityscorer.py index d4a9989d..f470511b 100644 --- a/RecDP/pyrecdp/primitives/operations/text_qualityscorer.py +++ b/RecDP/pyrecdp/primitives/operations/text_qualityscorer.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseLLMOperation, LLMOPERATORS, statistics_decorator from ray.data import Dataset from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/operations/text_reader.py b/RecDP/pyrecdp/primitives/operations/text_reader.py index fd2d7629..6da04dc6 100644 --- a/RecDP/pyrecdp/primitives/operations/text_reader.py +++ b/RecDP/pyrecdp/primitives/operations/text_reader.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseLLMOperation, LLMOPERATORS from ray.data import Dataset from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/operations/text_spell_correct.py b/RecDP/pyrecdp/primitives/operations/text_spell_correct.py index 76aa838d..629e5ab9 100644 --- a/RecDP/pyrecdp/primitives/operations/text_spell_correct.py +++ b/RecDP/pyrecdp/primitives/operations/text_spell_correct.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from ray.data import Dataset from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/operations/text_split.py b/RecDP/pyrecdp/primitives/operations/text_split.py index 13a64855..29067685 100644 --- a/RecDP/pyrecdp/primitives/operations/text_split.py +++ b/RecDP/pyrecdp/primitives/operations/text_split.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import math from typing import List, Dict, Any, Optional, Callable, cast, Union diff --git a/RecDP/pyrecdp/primitives/operations/text_to_qa.py b/RecDP/pyrecdp/primitives/operations/text_to_qa.py index d598aaa8..1ec2a420 100644 --- a/RecDP/pyrecdp/primitives/operations/text_to_qa.py +++ b/RecDP/pyrecdp/primitives/operations/text_to_qa.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseLLMOperation, LLMOPERATORS, statistics_decorator import ray from ray.data import Dataset diff --git a/RecDP/pyrecdp/primitives/operations/text_toxicity.py b/RecDP/pyrecdp/primitives/operations/text_toxicity.py index 905b31fe..fbb9e6cd 100644 --- a/RecDP/pyrecdp/primitives/operations/text_toxicity.py +++ b/RecDP/pyrecdp/primitives/operations/text_toxicity.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseLLMOperation, LLMOPERATORS, statistics_decorator from ray.data import Dataset from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/operations/text_writer.py b/RecDP/pyrecdp/primitives/operations/text_writer.py index b1628506..07d6f3ea 100644 --- a/RecDP/pyrecdp/primitives/operations/text_writer.py +++ b/RecDP/pyrecdp/primitives/operations/text_writer.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseLLMOperation, LLMOPERATORS from ray.data import Dataset from pyspark.sql import DataFrame diff --git a/RecDP/pyrecdp/primitives/operations/tuple.py b/RecDP/pyrecdp/primitives/operations/tuple.py index aa1d4dee..e91d318b 100644 --- a/RecDP/pyrecdp/primitives/operations/tuple.py +++ b/RecDP/pyrecdp/primitives/operations/tuple.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseOperation, AUTOFEOPERATORS class TupleOperation(BaseOperation): diff --git a/RecDP/pyrecdp/primitives/operations/type.py b/RecDP/pyrecdp/primitives/operations/type.py index 1e60d47f..2cc11c10 100644 --- a/RecDP/pyrecdp/primitives/operations/type.py +++ b/RecDP/pyrecdp/primitives/operations/type.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .base import BaseOperation, AUTOFEOPERATORS from pyrecdp.core.schema import SeriesSchema import pandas as pd diff --git a/RecDP/pyrecdp/primitives/operations/utils.py b/RecDP/pyrecdp/primitives/operations/utils.py index 016604a3..2cbdba08 100644 --- a/RecDP/pyrecdp/primitives/operations/utils.py +++ b/RecDP/pyrecdp/primitives/operations/utils.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import re diff --git a/RecDP/pyrecdp/primitives/profilers/cluster_infer.py b/RecDP/pyrecdp/primitives/profilers/cluster_infer.py index f82ee798..1c168cb6 100644 --- a/RecDP/pyrecdp/primitives/profilers/cluster_infer.py +++ b/RecDP/pyrecdp/primitives/profilers/cluster_infer.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.core.schema import SeriesSchema from pyrecdp.primitives.operations import Operation import pandas as pd diff --git a/RecDP/pyrecdp/primitives/profilers/distribution_infer.py b/RecDP/pyrecdp/primitives/profilers/distribution_infer.py index f82ee798..1c168cb6 100644 --- a/RecDP/pyrecdp/primitives/profilers/distribution_infer.py +++ b/RecDP/pyrecdp/primitives/profilers/distribution_infer.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.core.schema import SeriesSchema from pyrecdp.primitives.operations import Operation import pandas as pd diff --git a/RecDP/pyrecdp/primitives/profilers/statics.py b/RecDP/pyrecdp/primitives/profilers/statics.py index 19d82b18..4a84ff91 100644 --- a/RecDP/pyrecdp/primitives/profilers/statics.py +++ b/RecDP/pyrecdp/primitives/profilers/statics.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.core.schema import SeriesSchema from pyrecdp.core.utils import is_text_series from pyrecdp.core.utils import Timer diff --git a/RecDP/pyrecdp/primitives/profilers/time_series_infer.py b/RecDP/pyrecdp/primitives/profilers/time_series_infer.py index 887c9a3b..09f7b96c 100644 --- a/RecDP/pyrecdp/primitives/profilers/time_series_infer.py +++ b/RecDP/pyrecdp/primitives/profilers/time_series_infer.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.core.schema import SeriesSchema from pyrecdp.primitives.operations import Operation import pandas as pd diff --git a/RecDP/pyrecdp/primitives/profilers/type_infer.py b/RecDP/pyrecdp/primitives/profilers/type_infer.py index b7cb6da7..ac9121f3 100644 --- a/RecDP/pyrecdp/primitives/profilers/type_infer.py +++ b/RecDP/pyrecdp/primitives/profilers/type_infer.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.core.schema import SeriesSchema from pyrecdp.core.utils import is_unique from pyrecdp.primitives.operations import Operation diff --git a/RecDP/pyrecdp/primitives/spark_data_processor/data_processor.py b/RecDP/pyrecdp/primitives/spark_data_processor/data_processor.py index b2e8089a..611cc30a 100644 --- a/RecDP/pyrecdp/primitives/spark_data_processor/data_processor.py +++ b/RecDP/pyrecdp/primitives/spark_data_processor/data_processor.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.utils import create_spark_context import uuid diff --git a/RecDP/pyrecdp/primitives/spark_data_processor/encoder.py b/RecDP/pyrecdp/primitives/spark_data_processor/encoder.py index 44aa5b98..c6610ab5 100644 --- a/RecDP/pyrecdp/primitives/spark_data_processor/encoder.py +++ b/RecDP/pyrecdp/primitives/spark_data_processor/encoder.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import uuid from pyrecdp.utils import * from pyspark.ml.feature import * diff --git a/RecDP/pyrecdp/primitives/spark_data_processor/start-spark-standalone.sh b/RecDP/pyrecdp/primitives/spark_data_processor/start-spark-standalone.sh index 88b6c8b7..36c6198b 100755 --- a/RecDP/pyrecdp/primitives/spark_data_processor/start-spark-standalone.sh +++ b/RecDP/pyrecdp/primitives/spark_data_processor/start-spark-standalone.sh @@ -1,3 +1,17 @@ +# Copyright 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + if [ "$#" -ne 1 ]; then echo "Please provide master node, ex: " $0 "127.0.0.1" fi diff --git a/RecDP/pyrecdp/primitives/spark_data_processor/utils.py b/RecDP/pyrecdp/primitives/spark_data_processor/utils.py index ac833f33..e928edaf 100644 --- a/RecDP/pyrecdp/primitives/spark_data_processor/utils.py +++ b/RecDP/pyrecdp/primitives/spark_data_processor/utils.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os import re from pyspark import * diff --git a/RecDP/pyrecdp/primitives/tabutils/data_preprocess.py b/RecDP/pyrecdp/primitives/tabutils/data_preprocess.py index e4859530..75fcccfb 100644 --- a/RecDP/pyrecdp/primitives/tabutils/data_preprocess.py +++ b/RecDP/pyrecdp/primitives/tabutils/data_preprocess.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import numpy as np import seaborn as sns from scipy.cluster import hierarchy diff --git a/RecDP/pyrecdp/primitives/tabutils/feature_normal_transform.py b/RecDP/pyrecdp/primitives/tabutils/feature_normal_transform.py index cda995e2..cd73e7be 100644 --- a/RecDP/pyrecdp/primitives/tabutils/feature_normal_transform.py +++ b/RecDP/pyrecdp/primitives/tabutils/feature_normal_transform.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import numpy as np from scipy.stats import yeojohnson from scipy.stats import kstest diff --git a/RecDP/pyrecdp/primitives/tabutils/segmentation.py b/RecDP/pyrecdp/primitives/tabutils/segmentation.py index ee500485..cbe292d9 100644 --- a/RecDP/pyrecdp/primitives/tabutils/segmentation.py +++ b/RecDP/pyrecdp/primitives/tabutils/segmentation.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from collections import defaultdict import pandas as pd import numpy as np diff --git a/RecDP/pyrecdp/primitives/tabutils/utils.py b/RecDP/pyrecdp/primitives/tabutils/utils.py index cc569b11..0124e018 100644 --- a/RecDP/pyrecdp/primitives/tabutils/utils.py +++ b/RecDP/pyrecdp/primitives/tabutils/utils.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import pandas as pd import numpy as np import numba diff --git a/RecDP/pyrecdp/widgets/BaseWidget.py b/RecDP/pyrecdp/widgets/BaseWidget.py index 1f563758..8bff817c 100644 --- a/RecDP/pyrecdp/widgets/BaseWidget.py +++ b/RecDP/pyrecdp/widgets/BaseWidget.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import ipywidgets as widgets from IPython.display import display, clear_output diff --git a/RecDP/pyrecdp/widgets/TabWidget.py b/RecDP/pyrecdp/widgets/TabWidget.py index 020751fb..9b72f2a4 100644 --- a/RecDP/pyrecdp/widgets/TabWidget.py +++ b/RecDP/pyrecdp/widgets/TabWidget.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import ipywidgets as widgets from IPython.display import display diff --git a/RecDP/pyrecdp/widgets/TableViewWidget.py b/RecDP/pyrecdp/widgets/TableViewWidget.py index 9c6021cd..089940e8 100644 --- a/RecDP/pyrecdp/widgets/TableViewWidget.py +++ b/RecDP/pyrecdp/widgets/TableViewWidget.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from pyrecdp.widgets import BaseWidget class TableViewWidget(BaseWidget): diff --git a/RecDP/setup.py b/RecDP/setup.py index 5e274bb2..16ddc215 100644 --- a/RecDP/setup.py +++ b/RecDP/setup.py @@ -59,34 +59,36 @@ def get_packages(self): setup_spec = SetupSpec() -setuptools.setup( - name="pyrecdp", - version=setup_spec.version, - author="INTEL BDF AIOK", - author_email="bdf.aiok@intel.com", - description= - "A data processing bundle for spark based recommender system operations", - long_description=long_description, - long_description_content_type="text/markdown", - url = "https://github.com/intel/e2eAIOK/", - project_urls={ - "Bug Tracker": "https://github.com/intel/e2eAIOK/", - }, - keywords=( - "pyrecdp recdp distributed parallel auto-feature-engineering autofe LLM python" - ), - classifiers=[ - "Programming Language :: Python :: 3", - "License :: OSI Approved :: Apache Software License", - "Operating System :: OS Independent", - ], - include_package_data=True, - package_dir={}, - packages=setup_spec.get_packages(), - package_data={"": ["*.jar"], "pyrecdp": ["version"]}, - python_requires=">=3.6", - #cmdclass={'install': post_install}, - zip_safe=False, - install_requires=setup_spec.install_requires, - extras_require=setup_spec.extras, -) +name_list = ["pyrecdp", "e2eAIOK-pyrecdp"] +for name in name_list: + setuptools.setup( + name=name, + version=setup_spec.version, + author="INTEL BDF AIOK", + author_email="bdf.aiok@intel.com", + description= + "A data processing bundle for spark based recommender system operations", + long_description=long_description, + long_description_content_type="text/markdown", + url = "https://github.com/intel/e2eAIOK/", + project_urls={ + "Bug Tracker": "https://github.com/intel/e2eAIOK/", + }, + keywords=( + "pyrecdp recdp distributed parallel auto-feature-engineering autofe LLM python" + ), + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: Apache Software License", + "Operating System :: OS Independent", + ], + include_package_data=True, + package_dir={}, + packages=setup_spec.get_packages(), + package_data={"": ["*.jar"], "pyrecdp": ["version"]}, + python_requires=">=3.6", + #cmdclass={'install': post_install}, + zip_safe=False, + install_requires=setup_spec.install_requires, + extras_require=setup_spec.extras, + ) diff --git a/e2eAIOK/deltatuner/deltatuner/deltatuner.py b/e2eAIOK/deltatuner/deltatuner/deltatuner.py index c9916346..b31720c2 100644 --- a/e2eAIOK/deltatuner/deltatuner/deltatuner.py +++ b/e2eAIOK/deltatuner/deltatuner/deltatuner.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import logging from peft import LoraConfig, PeftModel, LoraModel from .tuner import SSFConfig diff --git a/e2eAIOK/deltatuner/deltatuner/deltatuner_args.py b/e2eAIOK/deltatuner/deltatuner/deltatuner_args.py index d7f007c1..0aabdb84 100644 --- a/e2eAIOK/deltatuner/deltatuner/deltatuner_args.py +++ b/e2eAIOK/deltatuner/deltatuner/deltatuner_args.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from typing import List from dataclasses import dataclass, field from transformers import AutoTokenizer diff --git a/e2eAIOK/deltatuner/deltatuner/deltatuner_model.py b/e2eAIOK/deltatuner/deltatuner/deltatuner_model.py index 596bfa9f..da81b40d 100644 --- a/e2eAIOK/deltatuner/deltatuner/deltatuner_model.py +++ b/e2eAIOK/deltatuner/deltatuner/deltatuner_model.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os import torch import json diff --git a/e2eAIOK/deltatuner/deltatuner/mapping.py b/e2eAIOK/deltatuner/deltatuner/mapping.py index 18f7a5de..db1d9f23 100644 --- a/e2eAIOK/deltatuner/deltatuner/mapping.py +++ b/e2eAIOK/deltatuner/deltatuner/mapping.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .tuner import SSFConfig from typing import TYPE_CHECKING, Any, Dict from .deltatuner_model import DeltaTunerModel, DelatunerModelForCausalLM diff --git a/e2eAIOK/deltatuner/deltatuner/scores/compute_de_score.py b/e2eAIOK/deltatuner/deltatuner/scores/compute_de_score.py index 4985a8ad..e532126c 100644 --- a/e2eAIOK/deltatuner/deltatuner/scores/compute_de_score.py +++ b/e2eAIOK/deltatuner/deltatuner/scores/compute_de_score.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os, sys, time, logging diff --git a/e2eAIOK/deltatuner/deltatuner/scores/transformer_proxy.py b/e2eAIOK/deltatuner/deltatuner/scores/transformer_proxy.py index 6e9cae14..3aa0758e 100644 --- a/e2eAIOK/deltatuner/deltatuner/scores/transformer_proxy.py +++ b/e2eAIOK/deltatuner/deltatuner/scores/transformer_proxy.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os, sys, time, math import torch from torch import nn diff --git a/e2eAIOK/deltatuner/deltatuner/scores/transformer_proxy_ssf.py b/e2eAIOK/deltatuner/deltatuner/scores/transformer_proxy_ssf.py index e7a0a580..bfbd90e6 100644 --- a/e2eAIOK/deltatuner/deltatuner/scores/transformer_proxy_ssf.py +++ b/e2eAIOK/deltatuner/deltatuner/scores/transformer_proxy_ssf.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os, sys, time, math import torch from torch import nn diff --git a/e2eAIOK/deltatuner/deltatuner/scores/utils.py b/e2eAIOK/deltatuner/deltatuner/scores/utils.py index ef935aa4..445ee36a 100644 --- a/e2eAIOK/deltatuner/deltatuner/scores/utils.py +++ b/e2eAIOK/deltatuner/deltatuner/scores/utils.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import torch from transformers import pytorch_utils from peft.tuners.lora import Linear, Conv1D, LoraLayer diff --git a/e2eAIOK/deltatuner/deltatuner/search/BaseSearchEngine.py b/e2eAIOK/deltatuner/deltatuner/search/BaseSearchEngine.py index 718a7e79..8d72abcb 100644 --- a/e2eAIOK/deltatuner/deltatuner/search/BaseSearchEngine.py +++ b/e2eAIOK/deltatuner/deltatuner/search/BaseSearchEngine.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import logging import gc import json diff --git a/e2eAIOK/deltatuner/deltatuner/search/EvolutionarySearchEngine.py b/e2eAIOK/deltatuner/deltatuner/search/EvolutionarySearchEngine.py index 67bac46a..d125ff6f 100644 --- a/e2eAIOK/deltatuner/deltatuner/search/EvolutionarySearchEngine.py +++ b/e2eAIOK/deltatuner/deltatuner/search/EvolutionarySearchEngine.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os import sys import traceback diff --git a/e2eAIOK/deltatuner/deltatuner/search/SearchEngineFactory.py b/e2eAIOK/deltatuner/deltatuner/search/SearchEngineFactory.py index 6725685d..a63cfd90 100644 --- a/e2eAIOK/deltatuner/deltatuner/search/SearchEngineFactory.py +++ b/e2eAIOK/deltatuner/deltatuner/search/SearchEngineFactory.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + from .EvolutionarySearchEngine import EvolutionarySearchEngine SEARCHER_TYPES = { diff --git a/e2eAIOK/deltatuner/deltatuner/search/utils.py b/e2eAIOK/deltatuner/deltatuner/search/utils.py index b25ee56d..999bf5bd 100644 --- a/e2eAIOK/deltatuner/deltatuner/search/utils.py +++ b/e2eAIOK/deltatuner/deltatuner/search/utils.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import sys import os import json diff --git a/e2eAIOK/deltatuner/deltatuner/tuner/deltatuner_lora.py b/e2eAIOK/deltatuner/deltatuner/tuner/deltatuner_lora.py index 82ca8acb..98d4169e 100644 --- a/e2eAIOK/deltatuner/deltatuner/tuner/deltatuner_lora.py +++ b/e2eAIOK/deltatuner/deltatuner/tuner/deltatuner_lora.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import torch from peft import LoraModel from peft.import_utils import is_bnb_available, is_bnb_4bit_available diff --git a/e2eAIOK/deltatuner/deltatuner/tuner/deltatuner_ssf.py b/e2eAIOK/deltatuner/deltatuner/tuner/deltatuner_ssf.py index 2a871669..39785a6e 100644 --- a/e2eAIOK/deltatuner/deltatuner/tuner/deltatuner_ssf.py +++ b/e2eAIOK/deltatuner/deltatuner/tuner/deltatuner_ssf.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import os import math import re diff --git a/e2eAIOK/deltatuner/deltatuner/utils/config.py b/e2eAIOK/deltatuner/deltatuner/utils/config.py index f3657b42..73e29f62 100644 --- a/e2eAIOK/deltatuner/deltatuner/utils/config.py +++ b/e2eAIOK/deltatuner/deltatuner/utils/config.py @@ -1,3 +1,19 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + import enum from dataclasses import field from typing import List, Optional, Tuple, Union From d945ad0b3733f75d68a67fbac254607bb46f4546 Mon Sep 17 00:00:00 2001 From: "Xue, Chendi" Date: Thu, 21 Dec 2023 23:49:38 +0000 Subject: [PATCH 24/59] update version Signed-off-by: Xue, Chendi --- .../workflows/e2eaiok_recdp_release_pypi.yml | 37 +++++++++++++++++++ RecDP/version | 2 +- e2eAIOK/deltatuner/deltatuner/version | 2 +- e2eAIOK/version | 2 +- 4 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/e2eaiok_recdp_release_pypi.yml diff --git a/.github/workflows/e2eaiok_recdp_release_pypi.yml b/.github/workflows/e2eaiok_recdp_release_pypi.yml new file mode 100644 index 00000000..9be99185 --- /dev/null +++ b/.github/workflows/e2eaiok_recdp_release_pypi.yml @@ -0,0 +1,37 @@ +name: Publish RecDP Stable Release to PyPI + +on: + workflow_dispatch: + push: + branches: + - main + +permissions: + contents: read + packages: write + +jobs: + e2eaiok-release-python-pypi: + runs-on: self-hosted + if: ${{ github.repository_owner == 'intel' }} + steps: + - uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.7' + + - name: Build Package + run: | + pip install build wheel + release_version=$(cat e2eAIOK/version | head -1) + cd RecDP + echo $release_version > version + python3 setup.py sdist + + - name: Upload Package + uses: pypa/gh-action-pypi-publish@master + with: + password: ${{ secrets.PYPI_API_TOKEN_PYRECDP }} + packages_dir: RecDP/dist \ No newline at end of file diff --git a/RecDP/version b/RecDP/version index 9c6d6293..26aaba0e 100644 --- a/RecDP/version +++ b/RecDP/version @@ -1 +1 @@ -1.6.1 +1.2.0 diff --git a/e2eAIOK/deltatuner/deltatuner/version b/e2eAIOK/deltatuner/deltatuner/version index 512a1faa..26aaba0e 100644 --- a/e2eAIOK/deltatuner/deltatuner/version +++ b/e2eAIOK/deltatuner/deltatuner/version @@ -1 +1 @@ -1.1.9 +1.2.0 diff --git a/e2eAIOK/version b/e2eAIOK/version index 1cc5f657..867e5243 100644 --- a/e2eAIOK/version +++ b/e2eAIOK/version @@ -1 +1 @@ -1.1.0 \ No newline at end of file +1.2.0 \ No newline at end of file From ae95394338424717c965685d5a8ff525d2a7da95 Mon Sep 17 00:00:00 2001 From: "Chendi.Xue" Date: Thu, 21 Dec 2023 18:12:40 -0600 Subject: [PATCH 25/59] Update setup.py --- RecDP/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecDP/setup.py b/RecDP/setup.py index 16ddc215..d61f01cb 100644 --- a/RecDP/setup.py +++ b/RecDP/setup.py @@ -59,7 +59,7 @@ def get_packages(self): setup_spec = SetupSpec() -name_list = ["pyrecdp", "e2eAIOK-pyrecdp"] +name_list = ["pyrecdp", "e2eAIOK-recdp"] for name in name_list: setuptools.setup( name=name, From a64788aa7e3743cba89b43a9b6a7b28415a30b42 Mon Sep 17 00:00:00 2001 From: "Xue, Chendi" Date: Fri, 22 Dec 2023 00:17:21 +0000 Subject: [PATCH 26/59] fix setup.py Signed-off-by: Xue, Chendi --- RecDP/setup.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/RecDP/setup.py b/RecDP/setup.py index d61f01cb..c3497541 100644 --- a/RecDP/setup.py +++ b/RecDP/setup.py @@ -2,6 +2,7 @@ import pkg_resources import pathlib from itertools import chain +import sys with open("README.md", "r", encoding="utf-8") as fh: long_description = fh.read() @@ -57,10 +58,15 @@ def __init__(self): def get_packages(self): return setuptools.find_packages() -setup_spec = SetupSpec() -name_list = ["pyrecdp", "e2eAIOK-recdp"] -for name in name_list: +if __name__ == '__main__': + if "--with_prefix" in sys.argv: + name = 'e2eAIOK-recdp' + else: + name = 'pyrecdp' + + setup_spec = SetupSpec() + setuptools.setup( name=name, version=setup_spec.version, From c473e6ad3e43eee7ddf51e1186acc46f520b22ac Mon Sep 17 00:00:00 2001 From: "Xue, Chendi" Date: Fri, 22 Dec 2023 00:26:39 +0000 Subject: [PATCH 27/59] release with prefix Signed-off-by: Xue, Chendi --- .github/workflows/e2eaiok_recdp_release_pypi.yml | 2 +- RecDP/setup.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/e2eaiok_recdp_release_pypi.yml b/.github/workflows/e2eaiok_recdp_release_pypi.yml index 9be99185..2b4f0636 100644 --- a/.github/workflows/e2eaiok_recdp_release_pypi.yml +++ b/.github/workflows/e2eaiok_recdp_release_pypi.yml @@ -28,7 +28,7 @@ jobs: release_version=$(cat e2eAIOK/version | head -1) cd RecDP echo $release_version > version - python3 setup.py sdist + python3 setup.py sdist --with_prefix - name: Upload Package uses: pypa/gh-action-pypi-publish@master diff --git a/RecDP/setup.py b/RecDP/setup.py index c3497541..d2531e9c 100644 --- a/RecDP/setup.py +++ b/RecDP/setup.py @@ -60,8 +60,10 @@ def get_packages(self): if __name__ == '__main__': + if "--with_prefix" in sys.argv: name = 'e2eAIOK-recdp' + sys.argv.remove("--with_prefix") else: name = 'pyrecdp' From 98077cffd5bd8de790172e7db150e2d10fa74998 Mon Sep 17 00:00:00 2001 From: "Chendi.Xue" Date: Thu, 21 Dec 2023 19:57:35 -0600 Subject: [PATCH 28/59] Update e2eaiok_recdp_release_pypi.yml --- .github/workflows/e2eaiok_recdp_release_pypi.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2eaiok_recdp_release_pypi.yml b/.github/workflows/e2eaiok_recdp_release_pypi.yml index 2b4f0636..380f8259 100644 --- a/.github/workflows/e2eaiok_recdp_release_pypi.yml +++ b/.github/workflows/e2eaiok_recdp_release_pypi.yml @@ -33,5 +33,5 @@ jobs: - name: Upload Package uses: pypa/gh-action-pypi-publish@master with: - password: ${{ secrets.PYPI_API_TOKEN_PYRECDP }} - packages_dir: RecDP/dist \ No newline at end of file + password: ${{ secrets.PYPI_API_TOKEN_E2EAIOKRECDP }} + packages_dir: RecDP/dist From 00d90e0bd7fcdd1082fb8599ec0fad3677430745 Mon Sep 17 00:00:00 2001 From: "Zhang, Chaojun" Date: Tue, 26 Dec 2023 15:12:54 +0000 Subject: [PATCH 29/59] Refactor doc_loader.py to load documents concurrently using Ray actors or Spark tasks, instead of loading them all at once and then putting them into a dataset --- RecDP/pyrecdp/core/path_utils.py | 56 +++ RecDP/pyrecdp/datasets/__init__.py | 9 +- RecDP/pyrecdp/primitives/document/reader.py | 387 ++++++++++++++++++ .../{llmutils => }/document/schema.py | 1 + .../primitives/llmutils/document/__init__.py | 0 .../primitives/llmutils/document/extractor.py | 62 --- .../primitives/llmutils/document/reader.py | 354 ---------------- .../primitives/llmutils/document/writer.py | 37 -- .../primitives/llmutils/document_extractor.py | 81 ++-- .../primitives/operations/doc_loader.py | 261 ++++++------ .../primitives/operations/text_reader.py | 34 +- RecDP/tests/test_llmutils_operations.py | 124 ++++-- 12 files changed, 704 insertions(+), 702 deletions(-) create mode 100644 RecDP/pyrecdp/core/path_utils.py create mode 100644 RecDP/pyrecdp/primitives/document/reader.py rename RecDP/pyrecdp/primitives/{llmutils => }/document/schema.py (99%) delete mode 100644 RecDP/pyrecdp/primitives/llmutils/document/__init__.py delete mode 100644 RecDP/pyrecdp/primitives/llmutils/document/extractor.py delete mode 100644 RecDP/pyrecdp/primitives/llmutils/document/reader.py delete mode 100644 RecDP/pyrecdp/primitives/llmutils/document/writer.py diff --git a/RecDP/pyrecdp/core/path_utils.py b/RecDP/pyrecdp/core/path_utils.py new file mode 100644 index 00000000..adb02fb6 --- /dev/null +++ b/RecDP/pyrecdp/core/path_utils.py @@ -0,0 +1,56 @@ +from pathlib import Path +from typing import Optional, List, Union + + +def get_files( + input_dir: Union[str, Path], + glob: str = "**/[!.]*", + exclude: Optional[List] = None, + exclude_hidden: bool = True, + recursive: bool = False, + required_exts: Optional[List[str]] = None +) -> set[Path]: + """ get files from a directory""" + if input_dir is None: + raise ValueError("input_dir is required!") + + if isinstance(input_dir, str): + input_dir = Path(input_dir) + + all_files = set() + rejected_files = set() + + if exclude is not None: + for excluded_pattern in exclude: + if recursive: + # Recursive glob + for file in input_dir.rglob(excluded_pattern): + rejected_files.add(Path(file)) + else: + # Non-recursive glob + for file in input_dir.glob(excluded_pattern): + rejected_files.add(Path(file)) + + file_refs = list(input_dir.rglob(glob) if recursive else input_dir.glob(glob)) + + for ref in file_refs: + # Manually check if file is hidden or directory instead of + # in glob for backwards compatibility. + is_dir = ref.is_dir() + skip_because_hidden = exclude_hidden and ref.name.startswith(".") + skip_because_excluded = ref in rejected_files + skip_because_bad_ext = ( + required_exts is not None and ref.suffix not in required_exts + ) + if ( + is_dir + or skip_because_hidden + or skip_because_bad_ext + or skip_because_excluded + ): + continue + else: + ref.absolute().as_posix() + all_files.add(ref) + + return all_files diff --git a/RecDP/pyrecdp/datasets/__init__.py b/RecDP/pyrecdp/datasets/__init__.py index 3204bd45..7af19adc 100644 --- a/RecDP/pyrecdp/datasets/__init__.py +++ b/RecDP/pyrecdp/datasets/__init__.py @@ -14,11 +14,4 @@ limitations under the License. """ -from pyrecdp.datasets.download import * -from pyrecdp.datasets.nyc_taxi import * -from pyrecdp.datasets.twitter_recsys import * -from pyrecdp.datasets.amazon_product_review import * -from pyrecdp.datasets.outbrain import * -from pyrecdp.datasets.pretrained import * -from pyrecdp.datasets.ibm_fraud_detect import * -from pyrecdp.datasets.CESM_breast_cancer import * \ No newline at end of file +from pyrecdp.datasets.download import * \ No newline at end of file diff --git a/RecDP/pyrecdp/primitives/document/reader.py b/RecDP/pyrecdp/primitives/document/reader.py new file mode 100644 index 00000000..7b0bf3af --- /dev/null +++ b/RecDP/pyrecdp/primitives/document/reader.py @@ -0,0 +1,387 @@ +""" + Copyright 2024 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """ + +import os +import re +from abc import abstractmethod, ABC +from pathlib import Path +from typing import List, Dict, Type, Optional, Callable, Any, Union, Sequence + +from loguru import logger + +from pyrecdp.core.import_utils import check_availability_and_install +from pyrecdp.primitives.document.schema import Document + + +class DocumentReader(ABC): + """interface for document loader""" + + @abstractmethod + def load(self) -> List[Document]: + """abstract method for load documents""" + + +class FileBaseReader(DocumentReader, ABC): + """interface for loading document from a file.""" + + def __init__(self, file: Path, single_text_per_document: bool = True, page_separator: str = '\n'): + self.single_text_per_document = single_text_per_document + self.page_separator = page_separator or '\n' + self.file = file + + @classmethod + def setup(cls): + for pkg in cls.system_requirements: + os.system(f'apt-get install -y {pkg}') + for pkg in cls.requirements: + check_availability_and_install(pkg, verbose=1) + + def get_metadata(self): + return {"source": str(self.file)} + + def load(self) -> List[Document]: + docs: List[Document] = self.load_file(self.file) + docs: List[Document] = list(filter(lambda d: (d.text.strip() != ""), docs)) + + def firstAlphaIsUppercase(word: str) -> bool: + i: int = 0 + while i < len(word): + char = doc.text[i] + if char.isalpha(): + return char.isupper() + i += 1 + return False + + if self.single_text_per_document: + text = '' + for doc in docs: + if firstAlphaIsUppercase(doc.text): + text += f"\n\n {doc.text}" + else: + text += f" {doc.text}" + + return [Document(text=text, metadata=self.get_metadata())] + else: + return docs + + @abstractmethod + def load_file(self, file: Path) -> List[Document]: + """Load data from the input directory.""" + + +class PDFReader(FileBaseReader): + """PDF parser.""" + system_requirements = [] + requirements = ['pypdf'] + + def __init__(self, file: Path, single_text_per_document: bool = True, page_separator: str = '\n', + **load_kwargs): + super().__init__(file, single_text_per_document, page_separator) + self.load_kwargs = load_kwargs + self.file = file + + def load_file(self, file: Path) -> List[Document]: + import pypdf + # Create a PDF object + pdf = pypdf.PdfReader(file, **self.load_kwargs) + + # Get the number of pages in the PDF document + num_pages = len(pdf.pages) + + # Iterate over every page + docs = [] + for page in range(num_pages): + # Extract the text from the page + page_text = pdf.pages[page].extract_text() + page_label = pdf.page_labels[page] + metadata = {"page_label": page_label, "source": str(file)} + docs.append(Document(text=page_text, metadata=metadata)) + + return docs + + +class DocxReader(FileBaseReader): + """Docx parser.""" + system_requirements = [] + requirements = ['python-docx'] + + def __init__(self, file: Path, single_text_per_document: bool = True, page_separator: str = '\n'): + super().__init__(file, single_text_per_document, page_separator) + + def load_file(self, file: Path) -> List[Document]: + """Parse file.""" + import docx + document = docx.Document(str(file)) + + # read in each paragraph in file + return [Document(text=p.text, metadata={"source": str(file)}) for p in document.paragraphs] + + +class ImageReader(FileBaseReader): + """Image parser. + + Extract text from images using pytesseract. + + """ + system_requirements = ['tesseract-ocr'] + requirements = ['pillow', 'pytesseract'] + + def __init__( + self, + file: Path, + single_text_per_document: bool = True, + page_separator: str = '\n', + keep_image: bool = False, + ): + super().__init__(file, single_text_per_document, page_separator) + self._keep_image = keep_image + + def load_file(self, file: Path) -> List[Document]: + """Parse file.""" + from PIL import Image + from pytesseract import pytesseract + # load document image + image = Image.open(file) + if image.mode != "RGB": + image = image.convert("RGB") + + # Parse image into text + text_str = pytesseract.image_to_string(image) + + return [ + Document(text=text_str, metadata={"source": str(file)}) + ] + + +class AudioReader(FileBaseReader): + system_requirements = ['ffmpeg'] + requirements = ['openai-whisper'] + + def __init__( + self, + file: Path, + single_text_per_document: bool = True, + page_separator: str = '\n', + model='small', + ): + super().__init__(file, single_text_per_document, page_separator) + import whisper + self.model = whisper.load_model(model) + + def transcribe(self, file): + return self.model.transcribe(file) + + def load_file(self, file: Path) -> List[Document]: + file = str(file) + result = self.transcribe(file) + return [ + Document(text=result['text'], metadata={"source": file, 'language': result['language']}) + ] + + +_default_file_readers: Dict[str, Type[FileBaseReader]] = { + ".pdf": PDFReader, + ".docx": DocxReader, + ".jpg": ImageReader, + ".jpeg": ImageReader, + ".png": ImageReader, + ".mp3": AudioReader, + ".wav": AudioReader, + ".flac": AudioReader, +} + + +def read_from_directory(input_dirs: Optional[Union[str, List[str]]] = None, + input_files: Optional[list[str]] = None, + glob: str = "**/[!.]*", + recursive: bool = False, + exclude: Optional[List] = None, + exclude_hidden: bool = True, + max_concurrency: Optional[int] = None, + loaders: Optional[dict[str, Callable[[Path], List[Document]]]] = None, + required_exts: Optional[List[str]] = None): + def read_file(file_to_load, par): + try: + # use customer loader first if possible + if loaders and file_to_load.suffix in loaders: + document_loader: Callable = loaders[file_to_load.suffix] + assert isinstance(document_loader, Callable) + return document_loader(file_to_load) + + # load document with default registered file loader + if file_to_load.suffix in _default_file_readers: + document_loader_cls: Type[FileBaseReader] = _default_file_readers[file_to_load.suffix] + loader = document_loader_cls(file_to_load) + return loader.load() + + logger.warning(f"return empty documents, no loader registered for file type '{file_to_load.suffix}'") + return [] + finally: + par.update(1) + + if input_files: + files_to_read = [Path(f) for f in input_files if os.path.isfile(f)] + else: + input_dirs = [input_dirs] if isinstance(input_dirs, str) else input_dirs + from pyrecdp.core.path_utils import get_files + files_to_read = [ + file_to_read + for input_dir in input_dirs + for file_to_read in get_files( + input_dir, + glob=glob, + exclude=exclude, + exclude_hidden=exclude_hidden, + recursive=recursive, + required_exts=required_exts, + ) + ] + + files_to_read = list(set(files_to_read)) + + if len(files_to_read) == 0: + return [] + + def install_reader_requirements(): + file_exts = set() + for input_file in files_to_read: + file_exts.add(input_file.suffix) + + for file_ext in file_exts: + if file_ext in _default_file_readers: + _default_file_readers[file_ext].setup() + + install_reader_requirements() + + from tqdm import tqdm + from concurrent.futures import ThreadPoolExecutor + pbar = tqdm(total=len(files_to_read)) + + try: + with ThreadPoolExecutor(max_concurrency) as executor: + return [ + {'text': d.text, 'metadata': d.metadata} + for docs in executor.map(lambda f: read_file(f, pbar), files_to_read) + for d in docs + ] + finally: + pbar.close() + + +def read_from_url(url: str, text_to_markdown: bool, + max_depth: Optional[int] = 1, + use_async: Optional[bool] = None, + extractor: Optional[Callable[[str], str]] = None, + metadata_extractor: Optional[Callable[[str, str], str]] = None, + exclude_dirs: Optional[Sequence[str]] = (), + timeout: Optional[int] = 10, + prevent_outside: bool = True, + link_regex: Union[str, re.Pattern, None] = None, + headers: Optional[dict] = None, + check_response_status: bool = False, ) -> List[dict[str, Any]]: + """load documents from a url. + Args: + url: The URL to crawl. + text_to_markdown: Whether to page as markdown text. + max_depth: The max depth of the recursive loading. + use_async: Whether to use asynchronous loading. + If True, this function will not be lazy, but it will still work in the + expected way, just not lazy. + extractor: A function to extract document contents from raw html. + When extract function returns an empty string, the document is + ignored. + metadata_extractor: A function to extract metadata from raw html and the + source url (args in that order). Default extractor will attempt + to use BeautifulSoup4 to extract the title, description and language + of the page. + exclude_dirs: A list of subdirectories to exclude. + timeout: The timeout for the requests, in the unit of seconds. If None then + connection will not timeout. + prevent_outside: If True, prevent loading from urls which are not children + of the root url. + link_regex: Regex for extracting sub-links from the raw html of a web page. + check_response_status: If True, check HTTP response status and skip + URLs with error responses (400-599). + """ + + from langchain.document_loaders import RecursiveUrlLoader + if not extractor: + if text_to_markdown: + def extractor_with_markdownify(x): + import markdownify + return markdownify.markdownify(x) + + extractor = extractor_with_markdownify + elif extractor is None: + def extractor_with_bs4(x): + from bs4 import BeautifulSoup + return BeautifulSoup(x, "html.parser").text + + extractor = extractor_with_bs4 + + loader = RecursiveUrlLoader( + url, + extractor=extractor, + max_depth=max_depth, + use_async=use_async, + metadata_extractor=metadata_extractor, + exclude_dirs=exclude_dirs, + timeout=timeout, + prevent_outside=prevent_outside, + link_regex=link_regex, + headers=headers, + check_response_status=check_response_status, + ) + return [{'text': doc.page_content, 'metadata': doc.metadata} for doc in loader.load()] + + +def read_from_langchain(loader: str, loader_kwargs: Optional[dict[str, Any]] = None) -> List[dict[str, Any]]: + """load documents using langchain document loader""" + from pyrecdp.core.class_utils import new_instance + from langchain.document_loaders.base import BaseLoader + loader_kwargs = loader_kwargs or {} + loader = new_instance("langchain.document_loaders", loader, **loader_kwargs) + assert isinstance(loader, BaseLoader) + return [{'text': doc.page_content, 'metadata': doc.metadata} for doc in loader.load()] + + +def read_youtube_audio(url: Union[str, List[str]], save_dir: Optional[str] = None, model_name: Optional[str] = None): + import os + import tempfile + import shutil + + urls = [url] if isinstance(url, str) else url + use_temp_dir = False + if save_dir is None or not os.path.isdir(save_dir): + use_temp_dir = True + save_dir = tempfile.mkdtemp() + docs = [] + try: + from langchain.document_loaders.blob_loaders.youtube_audio import YoutubeAudioLoader + loader = YoutubeAudioLoader(urls, save_dir) + audio_paths = {} + for url, blob in zip(urls[::-1], loader.yield_blobs()): + audio_paths[url] = str(blob.path) + import whisper + model = whisper.load_model(model_name) + for url, audio_path in audio_paths.items(): + result = model.transcribe(audio_path) + docs.append({'text': result['text'], 'metadata': {"source": url, 'language': result['language']}}) + finally: + if use_temp_dir: + shutil.rmtree(save_dir) + + return docs diff --git a/RecDP/pyrecdp/primitives/llmutils/document/schema.py b/RecDP/pyrecdp/primitives/document/schema.py similarity index 99% rename from RecDP/pyrecdp/primitives/llmutils/document/schema.py rename to RecDP/pyrecdp/primitives/document/schema.py index 24c4f985..2fc1a52f 100644 --- a/RecDP/pyrecdp/primitives/llmutils/document/schema.py +++ b/RecDP/pyrecdp/primitives/document/schema.py @@ -17,6 +17,7 @@ from dataclasses import dataclass, asdict import json + @dataclass class Document: """Class for storing a piece of text and associated metadata.""" diff --git a/RecDP/pyrecdp/primitives/llmutils/document/__init__.py b/RecDP/pyrecdp/primitives/llmutils/document/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/RecDP/pyrecdp/primitives/llmutils/document/extractor.py b/RecDP/pyrecdp/primitives/llmutils/document/extractor.py deleted file mode 100644 index e595d6d3..00000000 --- a/RecDP/pyrecdp/primitives/llmutils/document/extractor.py +++ /dev/null @@ -1,62 +0,0 @@ -""" - Copyright 2024 Intel Corporation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - """ - -from .reader import * -from .writer import DocumentWriter - - -class DocumentExtractor: - def __init__( - self, - output_file: str, - input_dir: Optional[str] = None, - glob: str = "**/[!.]*", - use_multithreading: bool = False, - max_concurrency: Optional[int] = None, - input_files: Optional[List] = None, - single_text_per_document: bool = True, - exclude: Optional[List] = None, - exclude_hidden: bool = True, - silent_errors: bool = False, - recursive: bool = False, - encoding: str = "utf-8", - required_exts: Optional[List[str]] = None, - ) -> None: - if not input_dir and not input_files: - raise ValueError("Must provide either `input_dir` or `input_files`.") - if not output_file: - raise ValueError("Must provide either `output_file` or `writer`.") - - self.output_file = output_file - self.loader = DirectoryReader( - input_dir=input_dir, - glob=glob, - input_files=input_files, - use_multithreading=use_multithreading, - max_concurrency=max_concurrency, - single_text_per_document=single_text_per_document, - exclude=exclude, - exclude_hidden=exclude_hidden, - silent_errors=silent_errors, - recursive=recursive, - encoding=encoding, - required_exts=required_exts, - ) - - def execute(self): - with DocumentWriter(self.output_file) as writer: - for doc in self.loader.load(): - writer.write(doc) diff --git a/RecDP/pyrecdp/primitives/llmutils/document/reader.py b/RecDP/pyrecdp/primitives/llmutils/document/reader.py deleted file mode 100644 index 4200540b..00000000 --- a/RecDP/pyrecdp/primitives/llmutils/document/reader.py +++ /dev/null @@ -1,354 +0,0 @@ -""" - Copyright 2024 Intel Corporation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - """ - -import os -from abc import abstractmethod, ABC -from pathlib import Path -from typing import List, Optional, Dict, Type -from pyrecdp.core.import_utils import check_availability_and_install -from pyrecdp.primitives.llmutils.document.schema import Document - -class DocumentReader(ABC): - """interface for document loader""" - - @abstractmethod - def load(self) -> List[Document]: - """abstract method for load documents""" - - -class FileBaseReader(DocumentReader, ABC): - """interface for loading document from a file.""" - - def __init__(self, file: Path, single_text_per_document: bool = True, page_separator: str = '\n'): - self.single_text_per_document = single_text_per_document - self.page_separator = page_separator or '\n' - self.file = file - - @classmethod - def setup(cls): - for pkg in cls.system_requirements: - os.system(f'apt-get install -y {pkg}') - for pkg in cls.requirements: - check_availability_and_install(pkg, verbose=1) - - def get_metadata(self): - return {"source": str(self.file)} - - def load(self) -> List[Document]: - docs: List[Document] = self.load_file(self.file) - docs: List[Document] = list(filter(lambda d: (d.text.strip() != ""), docs)) - - def firstAlphaIsUppercase(word: str) -> bool: - i: int = 0 - while i < len(word): - char = doc.text[i] - if char.isalpha(): - return char.isupper() - i += 1 - return False - - if self.single_text_per_document: - text = '' - for doc in docs: - if firstAlphaIsUppercase(doc.text): - text += f"\n\n {doc.text}" - else: - text += f" {doc.text}" - - return [Document(text=text, metadata=self.get_metadata())] - else: - return docs - - @abstractmethod - def load_file(self, file: Path) -> List[Document]: - """Load data from the input directory.""" - - -class PDFReader(FileBaseReader): - """PDF parser.""" - system_requirements = [] - requirements = ['pypdf'] - def __init__(self, file: Path, single_text_per_document: bool = True, page_separator: str = '\n', - **load_kwargs): - super().__init__(file, single_text_per_document, page_separator) - self.load_kwargs = load_kwargs - self.file = file - - def load_file(self, file: Path) -> List[Document]: - import pypdf - # Create a PDF object - pdf = pypdf.PdfReader(file, **self.load_kwargs) - - # Get the number of pages in the PDF document - num_pages = len(pdf.pages) - - # Iterate over every page - docs = [] - for page in range(num_pages): - # Extract the text from the page - page_text = pdf.pages[page].extract_text() - page_label = pdf.page_labels[page] - metadata = {"page_label": page_label, "source": str(file)} - docs.append(Document(text=page_text, metadata=metadata)) - - return docs - - -class DocxReader(FileBaseReader): - """Docx parser.""" - system_requirements = [] - requirements = ['python-docx'] - def __init__(self, file: Path, single_text_per_document: bool = True, page_separator: str = '\n'): - super().__init__(file, single_text_per_document, page_separator) - - def load_file(self, file: Path) -> List[Document]: - """Parse file.""" - import docx - document = docx.Document(str(file)) - - # read in each paragraph in file - return [Document(text=p.text, metadata={"source": str(file)}) for p in document.paragraphs] - - -class ImageReader(FileBaseReader): - """Image parser. - - Extract text from images using pytesseract. - - """ - system_requirements = ['tesseract-ocr'] - requirements = ['pillow', 'pytesseract'] - def __init__( - self, - file: Path, - single_text_per_document: bool = True, - page_separator: str = '\n', - keep_image: bool = False, - ): - super().__init__(file, single_text_per_document, page_separator) - self._keep_image = keep_image - - def load_file(self, file: Path) -> List[Document]: - """Parse file.""" - from PIL import Image - from pytesseract import pytesseract - # load document image - image = Image.open(file) - if image.mode != "RGB": - image = image.convert("RGB") - - # Parse image into text - text_str = pytesseract.image_to_string(image) - - return [ - Document(text=text_str, metadata={"source": str(file)}) - ] - - -class AudioReader(FileBaseReader): - system_requirements = ['ffmpeg'] - requirements = ['openai-whisper'] - def __init__( - self, - file: Path, - single_text_per_document: bool = True, - page_separator: str = '\n', - model = 'small', - ): - super().__init__(file, single_text_per_document, page_separator) - import whisper - self.model = whisper.load_model(model) - - def transcribe(self, file): - return self.model.transcribe(file) - def load_file(self, file: Path) -> List[Document]: - file = str(file) - result = self.transcribe(file) - return [ - Document(text=result['text'], metadata={"source": file, 'language': result['language']}) - ] - - -CUSTOMIZE_SUPPORTED_SUFFIX: Dict[str, Type[FileBaseReader]] = { - ".pdf": PDFReader, - ".docx": DocxReader, - ".jpg": ImageReader, - ".jpeg": ImageReader, - ".png": ImageReader, - ".mp3": AudioReader, - ".wav": AudioReader, - ".flac": AudioReader, -} - - -class DirectoryReader(DocumentReader): - def __init__( - self, - input_dir: Optional[str] = None, - glob: str = "**/[!.]*", - use_multithreading: bool = False, - max_concurrency: Optional[int] = None, - input_files: Optional[List] = None, - single_text_per_document: bool = True, - exclude: Optional[List] = None, - exclude_hidden: bool = True, - silent_errors: bool = False, - recursive: bool = False, - encoding: str = "utf-8", - required_exts: Optional[List[str]] = CUSTOMIZE_SUPPORTED_SUFFIX.keys(), - page_separator: Optional[str] = '\n', - ) -> None: - """ - Loads documents from a directory or a list of files. - - Args: - input_dir: The input directory. - glob: A glob pattern to match files. - recursive: Whether to recursively search the input directory. - use_multithreading: Whether to use multithreading to load documents. - max_concurrency: The maximum number of concurrent threads to use. - input_files: A list of input files. - single_text_per_document: Whether to load each file as a single document. - exclude: A list of file patterns to exclude from loading. - exclude_hidden: Whether to exclude hidden files from loading. - silent_errors: Whether to silently ignore errors when loading documents. - encoding: The encoding to use when loading documents. - required_exts: A list of file extensions that are required for documents. - default extensions are [.pdf, .docx, .jpeg, .jpg, .png] - """ - if not input_dir and not input_files: - raise ValueError("Must provide either `path` or `input_files`.") - self.glob = glob - self.use_multithreading = use_multithreading - self.max_concurrency = max_concurrency - self.encoding = encoding - self.silent_errors = silent_errors - self.exclude = exclude - self.recursive = recursive - self.exclude_hidden = exclude_hidden - self.required_exts = required_exts - self.page_separator = page_separator - self.file_extractor = {} - if input_files: - self.input_files = [] - for path in input_files: - if not os.path.isfile(path): - raise ValueError(f"File {path} does not exist.") - input_file = Path(path) - self.input_files.append(input_file) - elif input_dir: - if not os.path.isdir(input_dir): - raise ValueError(f"Directory {input_dir} does not exist.") - self.input_dir = Path(input_dir) - self.exclude = exclude - self.input_files = self._add_files(self.input_dir) - - if len(self.input_files) == 1: - self.use_multithreading = False - - self.single_text_per_document = single_text_per_document - - def setup(self): - suffix_list = set(input_file.suffix.lower() for input_file in self.input_files) - for file_suffix in suffix_list: - if file_suffix in CUSTOMIZE_SUPPORTED_SUFFIX: - if file_suffix not in self.file_extractor: - file_base_reader_cls: Type[FileBaseReader] = CUSTOMIZE_SUPPORTED_SUFFIX[file_suffix] - file_base_reader_cls.setup() - - def _add_files(self, input_dir: Path) -> List[Path]: - all_files = set() - rejected_files = set() - - if self.exclude is not None: - for excluded_pattern in self.exclude: - if self.recursive: - # Recursive glob - for file in input_dir.rglob(excluded_pattern): - rejected_files.add(Path(file)) - else: - # Non-recursive glob - for file in input_dir.glob(excluded_pattern): - rejected_files.add(Path(file)) - - p = Path(input_dir) - file_refs = list(p.rglob(self.glob) if self.recursive else p.glob(self.glob)) - - for ref in file_refs: - # Manually check if file is hidden or directory instead of - # in glob for backwards compatibility. - is_dir = ref.is_dir() - skip_because_hidden = self.exclude_hidden and ref.name.startswith(".") - skip_because_bad_ext = ( - self.required_exts is not None and ref.suffix not in self.required_exts - ) - skip_because_excluded = ref in rejected_files - - if ( - is_dir - or skip_because_hidden - or skip_because_bad_ext - or skip_because_excluded - ): - continue - else: - all_files.add(ref) - - new_input_files = sorted(all_files) - - if len(new_input_files) == 0: - raise ValueError(f"No files found in {input_dir}.") - - return new_input_files - - def _load_file(self, input_file: Path, pbar): - try: - file_suffix = input_file.suffix.lower() - if file_suffix in CUSTOMIZE_SUPPORTED_SUFFIX: - if file_suffix not in self.file_extractor: - file_base_reader_cls: Type[FileBaseReader] = CUSTOMIZE_SUPPORTED_SUFFIX[file_suffix] - self.file_extractor[file_suffix] = file_base_reader_cls( - input_file, - single_text_per_document=self.single_text_per_document, - page_separator=self.page_separator, - ) - loader = self.file_extractor[file_suffix] - return loader.load() - else: - return [] - finally: - if pbar: - pbar.update(1) - - def load(self) -> List[Document]: - from tqdm import tqdm - pbar = tqdm(total=len(self.input_files)) - try: - docs_result: List[Document] = [] - if self.use_multithreading: - from concurrent.futures import ThreadPoolExecutor - with ThreadPoolExecutor(self.max_concurrency) as executor: - for docs in executor.map(lambda i: self._load_file(i, pbar), self.input_files): - if len(docs)>0: - docs_result.extend(docs) - else: - for file in self.input_files: - docs = self._load_file(file, pbar) - if len(docs) > 0: - docs_result.extend(docs) - return docs_result - finally: - pbar.close() diff --git a/RecDP/pyrecdp/primitives/llmutils/document/writer.py b/RecDP/pyrecdp/primitives/llmutils/document/writer.py deleted file mode 100644 index e0fa407e..00000000 --- a/RecDP/pyrecdp/primitives/llmutils/document/writer.py +++ /dev/null @@ -1,37 +0,0 @@ -""" - Copyright 2024 Intel Corporation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - """ - -import os - -from .schema import Document - - -class DocumentWriter: - def __init__(self, file: str): - self.file = file - - def __enter__(self): - folder_path = os.path.dirname(self.file) - if not os.path.exists(folder_path): - os.makedirs(folder_path) - self.writer = open(self.file, 'w') - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self.writer.close() - - def write(self, doc: Document): - self.writer.write(doc.json() + os.linesep) diff --git a/RecDP/pyrecdp/primitives/llmutils/document_extractor.py b/RecDP/pyrecdp/primitives/llmutils/document_extractor.py index 40b6eb85..1688ee2f 100644 --- a/RecDP/pyrecdp/primitives/llmutils/document_extractor.py +++ b/RecDP/pyrecdp/primitives/llmutils/document_extractor.py @@ -16,70 +16,51 @@ from typing import Optional, Union -from pyrecdp.primitives.llmutils.document.extractor import DocumentExtractor -from pyrecdp.primitives.llmutils.document.reader import * +from pyrecdp.primitives.document.reader import * def pdf_to_text(input_dir_or_files: Union[str, List[str]], output_file: str, - silent_errors: bool = False, recursive: bool = False, - use_multithreading: bool = False, - single_text_per_document: bool = True, - max_concurrency: Optional[int] = None): + **kwargs): document_to_text(input_dir_or_files, output_file, glob="**/*.pdf", - silent_errors=silent_errors, recursive=recursive, - single_text_per_document=single_text_per_document, - use_multithreading=use_multithreading, - max_concurrency=max_concurrency) + **kwargs + ) def docx_to_text(input_dir_or_files: Union[str, List[str]], output_file: str, - silent_errors: bool = False, recursive: bool = False, - use_multithreading: bool = False, - single_text_per_document: bool = True, - max_concurrency: Optional[int] = None): + **kwargs): document_to_text(input_dir_or_files, output_file, glob="**/*.docx", - silent_errors=silent_errors, recursive=recursive, - single_text_per_document=single_text_per_document, - use_multithreading=use_multithreading, - max_concurrency=max_concurrency) + **kwargs + ) def image_to_text(input_dir_or_files: Union[str, List[str]], output_file: str, - silent_errors: bool = False, recursive: bool = False, - use_multithreading: bool = False, - single_text_per_document: bool = True, - max_concurrency: Optional[int] = None): + **kwargs): document_to_text(input_dir_or_files, output_file, required_exts=[".jpeg", ".jpg", ".png"], - silent_errors=silent_errors, recursive=recursive, - single_text_per_document=single_text_per_document, - use_multithreading=use_multithreading, - max_concurrency=max_concurrency) + **kwargs + ) def document_to_text(input_dir_or_files: Union[str, List[str]], - output_file: str, + output_file: Optional[str] = None, glob: str = "**/*.*", - silent_errors: bool = False, recursive: bool = False, required_exts: Optional[List[str]] = None, - use_multithreading: bool = False, - single_text_per_document: bool = True, - max_concurrency: Optional[int] = None): + **kwargs): if isinstance(input_dir_or_files, str): if os.path.isdir(input_dir_or_files): input_dir, input_files = input_dir_or_files, None @@ -90,20 +71,30 @@ def document_to_text(input_dir_or_files: Union[str, List[str]], from pyrecdp.core.utils import Timer with Timer( - f"Document extract for '{input_dir_or_files}' with [glob={glob}, required_exts={required_exts}, recursive={recursive}, multithread={use_multithreading}]"): - converter = DocumentExtractor( - output_file=output_file, + f"Document extract for '{input_dir_or_files}' with [glob={glob}, required_exts={required_exts}, recursive={recursive}]"): + + from pyrecdp.primitives.spark_data_processor.data_processor import DataProcessor + + if 'spark' in kwargs: + sparkDP = DataProcessor(kwargs['spark']) + else: + sparkDP = DataProcessor() + spark = sparkDP.spark + + from pyrecdp.primitives.operations import DirectoryLoader + loader = DirectoryLoader( input_dir=input_dir, glob=glob, input_files=input_files, - silent_errors=silent_errors, recursive=recursive, - single_text_per_document=single_text_per_document, required_exts=required_exts, - use_multithreading=use_multithreading, - max_concurrency=max_concurrency, ) - converter.execute() + df = loader.process_spark(spark) + + if output_file: + df.write.mode('overwrite').parquet(output_file) + + return df if __name__ == '__main__': @@ -111,15 +102,11 @@ def document_to_text(input_dir_or_files: Union[str, List[str]], parser = argparse.ArgumentParser() parser.add_argument("-i", "--input_files", dest="input_files", type=str, nargs="*", default=None) - parser.add_argument("-d", "--input_dir", dest="input_dir", type=str,default=None) + parser.add_argument("-d", "--input_dir", dest="input_dir", type=str, default=None) parser.add_argument("-g", "--glob", dest="glob", type=str, default="**/*.jpeg") parser.add_argument("-o", "--output_file", dest="output_file", type=str) - parser.add_argument("-e", "--silent_errors", dest="silent_errors", default=False, type=bool) parser.add_argument("-r", "--recursive", dest="recursive", type=bool, default=False) parser.add_argument("-t", "--required_exts", dest="required_exts", type=str, nargs="*", default=None) - parser.add_argument("-m", "--use_multithreading", dest="use_multithreading", type=bool, default=False) - parser.add_argument("-c", "--max_concurrency", dest="max_concurrency", type=int, default=None) - parser.add_argument("-s", "--single_text_per_document", dest="single_text_per_document", type=bool, default=True) args = parser.parse_args() if not args.input_dir and not args.input_files: @@ -130,10 +117,6 @@ def document_to_text(input_dir_or_files: Union[str, List[str]], input_dir_or_files=input_dir_or_files, output_file=args.output_file, glob=args.glob, - silent_errors=args.silent_errors, recursive=args.recursive, - required_exts=args.required_exts, - use_multithreading=args.use_multithreading, - single_text_per_document=args.single_text_per_document, - max_concurrency=args.max_concurrency, + required_exts=args.required_exts ) diff --git a/RecDP/pyrecdp/primitives/operations/doc_loader.py b/RecDP/pyrecdp/primitives/operations/doc_loader.py index 198bf94d..3f6cfcc7 100644 --- a/RecDP/pyrecdp/primitives/operations/doc_loader.py +++ b/RecDP/pyrecdp/primitives/operations/doc_loader.py @@ -13,17 +13,13 @@ See the License for the specific language governing permissions and limitations under the License. """ - import os import re -from typing import Optional, List, Callable, Union, Sequence -from urllib.parse import urlparse, urlunparse, urljoin - -import requests +from pathlib import Path +from typing import Optional, List, Callable, Union, Sequence, Any from pyrecdp.core.import_utils import check_availability_and_install -from pyrecdp.core.import_utils import import_langchain -from pyrecdp.primitives.llmutils.document.schema import Document +from pyrecdp.primitives.document.schema import Document from pyrecdp.primitives.operations.base import LLMOPERATORS from pyrecdp.primitives.operations.text_reader import TextReader @@ -32,13 +28,16 @@ class DocumentLoader(TextReader): def __init__(self, loader: Optional[str] = None, loader_args: Optional[dict] = None, - args_dict: Optional[dict] = None, requirements=[]): + args_dict: Optional[dict] = None, requirements=None): """ Args: loader: The class name of the langchain document loader to use. loader_args: A dictionary of arguments to pass to the langchain document loader. """ + if requirements is None: + requirements = [] + if loader is None or not isinstance(loader, str): raise ValueError(f"loader must be provide!") @@ -58,20 +57,13 @@ def __init__(self, settings.update(args_dict or {}) super().__init__(settings, requirements=requirements) - self.doc_loader_func = self._get_loader() self.support_ray = True self.support_spark = True - def _get_loader(self) -> Callable[[], List[Document]]: - import_langchain() - from pyrecdp.core.class_utils import new_instance - from langchain.document_loaders.base import BaseLoader - langchain_loader: BaseLoader = new_instance("langchain.document_loaders", self.loader, **self.loader_args) - return lambda: [Document(text=doc.page_content, metadata=doc.metadata) for doc in langchain_loader.load()] - def load_documents(self): - return [{'text': doc.text, 'metadata': doc.metadata} for doc in self.doc_loader_func()] + from pyrecdp.primitives.document.reader import read_from_langchain + return read_from_langchain(self.loader, self.loader_args) def process_rayds(self, ds=None): import ray @@ -90,14 +82,17 @@ def process_spark(self, spark, spark_df=None): LLMOPERATORS.register(DocumentLoader) -class DirectoryLoader(DocumentLoader): - def __init__(self, input_dir: Optional[str] = None, glob: str = "**/[!.]*", recursive: bool = False, - use_multithreading: bool = True, max_concurrency: Optional[int] = None, - input_files: Optional[List] = None, single_text_per_document: bool = True, - exclude: Optional[List] = None, exclude_hidden: bool = True, silent_errors: bool = False, - encoding: str = "utf-8", required_exts: Optional[List[str]] = None, - page_separator: Optional[str] = '\n', - requirements=[], +class DirectoryLoader(TextReader): + def __init__(self, input_dir: Optional[Union[str, List[str]]] = None, + glob: str = "**/[!.]*", + recursive: bool = False, + input_files: Optional[List] = None, + exclude: Optional[List] = None, + exclude_hidden: bool = True, + max_concurrency: Optional[int] = None, + required_exts: Optional[List[str]] = None, + file_loaders: Optional[dict[str, Callable[[Path], List[Document]]]] = None, + requirements=None, **kwargs): """ Loads documents from a directory or a list of files. @@ -106,62 +101,78 @@ def __init__(self, input_dir: Optional[str] = None, glob: str = "**/[!.]*", recu input_dir: The input directory. glob: A glob pattern to match files. recursive: Whether to recursively search the input directory. - use_multithreading: Whether to use multithreading to load documents. - max_concurrency: The maximum number of concurrent threads to use. input_files: A list of input files. single_text_per_document: Whether to load each file as a single document. exclude: A list of file patterns to exclude from loading. exclude_hidden: Whether to exclude hidden files from loading. - silent_errors: Whether to silently ignore errors when loading documents. - encoding: The encoding to use when loading documents. + file_loaders: customize file loader. required_exts: A list of file extensions that are required for documents. - default extensions are [.pdf, .docx, .jpeg, .jpg, .png] """ + + if requirements is None: + requirements = [] + + if not input_dir and not input_files: + raise ValueError("Must provide either `input_dir` or `input_files`.") + settings = { 'input_dir': input_dir, 'glob': glob, 'input_files': input_files, 'recursive': recursive, - 'use_multithreading': use_multithreading, - 'max_concurrency': max_concurrency, - 'single_text_per_document': single_text_per_document, 'exclude': exclude, 'exclude_hidden': exclude_hidden, - 'silent_errors': silent_errors, - 'encoding': encoding, + 'max_concurrency': max_concurrency, 'required_exts': required_exts, - 'page_separator': page_separator, + 'file_loaders': file_loaders, } - from pyrecdp.primitives.llmutils.document.reader import DirectoryReader - - self.directory_loader = DirectoryReader( - input_dir=input_dir, - glob=glob, - input_files=input_files, - recursive=recursive, - use_multithreading=use_multithreading, - max_concurrency=max_concurrency, - single_text_per_document=single_text_per_document, - exclude=exclude, - exclude_hidden=exclude_hidden, - silent_errors=silent_errors, - encoding=encoding, - required_exts=required_exts, - page_separator=page_separator, + + self.input_files = input_files + self.input_dir = input_dir + self.glob = glob + self.recursive = recursive + self.exclude = exclude + self.exclude_hidden = exclude_hidden + self.max_concurrency = max_concurrency + self.required_exts = required_exts + self.file_loaders = file_loaders + + super().__init__(args_dict=settings, requirements=requirements) + + def load_documents(self): + from pyrecdp.primitives.document.reader import read_from_directory + return read_from_directory( + self.input_dir, + input_files=self.input_files, + glob=self.glob, + recursive=self.recursive, + exclude=self.exclude, + exclude_hidden=self.exclude_hidden, + max_concurrency=self.max_concurrency, + required_exts=self.required_exts, + loaders=self.file_loaders, ) - super().__init__(loader='DirectoryLoader', args_dict=settings, requirements=requirements) - def _get_loader(self) -> Callable[[], List[Document]]: - print("_get_loader") - self.directory_loader.setup() - return lambda: self.directory_loader.load() + def process_rayds(self, ds=None): + import ray + self.cache = ray.data.from_items(self.load_documents()) + if ds is not None: + self.cache = self.union_ray_ds(ds, self.cache) + return self.cache + + def process_spark(self, spark, spark_df=None): + self.cache = spark.createDataFrame(self.load_documents()) + if spark_df is not None: + self.cache = self.union_spark_df(spark_df, self.cache) + return self.cache LLMOPERATORS.register(DirectoryLoader) class YoutubeLoader(TextReader): - def __init__(self, urls: List[str], save_dir: str = None, model='small', **kwargs): + def __init__(self, urls: List[str], save_dir: str = None, model='small', + num_cpus: Optional[int] = None, **kwargs): """ Loads documents from a directory or a list of Youtube URLs. @@ -173,59 +184,48 @@ def __init__(self, urls: List[str], save_dir: str = None, model='small', **kwarg settings = { 'urls': urls, 'save_dir': save_dir, - 'model': model + 'model': model, + 'num_cpus': num_cpus, } super().__init__(settings) self.urls = urls self.save_dir = save_dir self.model_name = model - - def _load(self): - import os - import tempfile - import shutil - use_temp_dir = False - save_dir = self.save_dir - if save_dir is None or not os.path.isdir(save_dir): - use_temp_dir = True - save_dir = tempfile.mkdtemp() - docs = [] - try: - import_langchain() - from langchain.document_loaders.blob_loaders.youtube_audio import YoutubeAudioLoader - check_availability_and_install('yt_dlp') - loader = YoutubeAudioLoader(self.urls, save_dir) - audio_paths = {} - for url, blob in zip(self.urls[::-1], loader.yield_blobs()): - audio_paths[url] = str(blob.path) - import os - os.system("apt-get -qq -y install ffmpeg") - check_availability_and_install('openai-whisper') - import whisper - model = whisper.load_model(self.model_name) - for url, audio_path in audio_paths.items(): - result = model.transcribe(audio_path) - docs.append(Document(text=result['text'], metadata={"source": url, 'language': result['language']})) - finally: - if use_temp_dir: - shutil.rmtree(save_dir) - - return docs - - def load_documents(self): - return [{'text': doc.text, 'metadata': doc.metadata} for doc in self._load()] + self.num_cpus = num_cpus + os.system("apt-get -qq -y install ffmpeg") + check_availability_and_install(['langchain', 'yt_dlp', 'openai-whisper']) def process_rayds(self, ds=None): import ray - self.cache = ray.data.from_items(self.load_documents()) + url_ds = ray.data.from_items([{'url': url} for url in self.urls]) + from pyrecdp.primitives.document.reader import read_youtube_audio + self.cache = url_ds.flat_map(lambda record: read_youtube_audio(record['url'], self.save_dir, self.model_name), + num_cpus=self.num_cpus) if ds is not None: self.cache = self.union_ray_ds(ds, self.cache) return self.cache def process_spark(self, spark, spark_df=None): - self.cache = spark.createDataFrame(self.load_documents()) + from pyspark.sql import DataFrame + from pyspark.sql import types as T + urls_df: DataFrame = spark.createDataFrame(self.urls, T.StringType()) + + schema = T.StructType([ + T.StructField("text", T.StringType()), + T.StructField('metadata', T.StructType([ + T.StructField('source', T.StringType()), + T.StructField('language', T.StringType()), + ])) + ]) + + from pyrecdp.primitives.document.reader import read_youtube_audio + docs_rdd = urls_df.rdd.flatMap( + lambda row: read_youtube_audio(row['value'], self.save_dir, self.model_name)) + + self.cache = spark.createDataFrame(docs_rdd, schema) if spark_df is not None: self.cache = self.union_spark_df(spark_df, self.cache) + return self.cache @@ -248,6 +248,7 @@ def __init__( check_response_status: bool = False, text_to_markdown: bool = True, requirements=None, + num_cpus: Optional[int] = None, ) -> None: """Initialize with URL to crawl and any subdirectories to exclude. @@ -272,23 +273,12 @@ def __init__( link_regex: Regex for extracting sub-links from the raw html of a web page. check_response_status: If True, check HTTP response status and skip URLs with error responses (400-599). + num_cpus: The number of CPUs to reserve for each parallel url read worker. """ if requirements is None: requirements = ['bs4', 'markdownify', 'langchain'] - if text_to_markdown: - def extractor_with_markdownify(x): - import markdownify - return markdownify.markdownify(x) - extractor = lambda x: extractor_with_markdownify(x) - elif extractor is None: - def extractor_with_bs4(x): - from bs4 import BeautifulSoup - return BeautifulSoup(x, "html.parser").text - extractor = lambda x: extractor_with_bs4(x) - - settings = { - 'urls': urls, + self.loader_kwargs = { 'max_depth': max_depth, 'use_async': use_async, 'extractor': extractor, @@ -300,43 +290,52 @@ def extractor_with_bs4(x): 'headers': headers, 'check_response_status': check_response_status, } + settings = self.loader_kwargs.copy() + settings.update({'urls': urls, 'text_to_markdown': text_to_markdown, 'num_cpus': num_cpus}) + self.text_to_markdown = text_to_markdown super().__init__(settings, requirements=requirements) self.support_spark = True self.support_ray = True + self.num_cpus = num_cpus - from langchain.document_loaders import RecursiveUrlLoader as LCRecursiveURLLoader if isinstance(urls, str): urls = [urls] - urls = set(urls) - - self.loaders = [LCRecursiveURLLoader( - url, - max_depth=max_depth, - use_async=use_async, - extractor=extractor, - metadata_extractor=metadata_extractor, - exclude_dirs=exclude_dirs, - timeout=timeout, - prevent_outside=prevent_outside, - link_regex=link_regex, - headers=headers, - check_response_status=check_response_status, - ) for url in urls] - - def load_documents(self): - return [{'text': doc.page_content, 'metadata': doc.metadata} for loader in self.loaders for doc in - loader.load()] + self.urls = set(urls) def process_rayds(self, ds=None): import ray - self.cache = ray.data.from_items(self.load_documents()) + urls_ds = ray.data.from_items([{'url': url} for url in self.urls]) + + from pyrecdp.primitives.document.reader import read_from_url + self.cache = urls_ds.flat_map( + lambda record: read_from_url(record['url'], self.text_to_markdown, **self.loader_kwargs), + num_cpus=self.num_cpus) + if ds is not None: self.cache = self.union_ray_ds(ds, self.cache) return self.cache def process_spark(self, spark, spark_df=None): - self.cache = spark.createDataFrame(self.load_documents()) + from pyspark.sql import DataFrame + from pyspark.sql import types as T + urls_df: DataFrame = spark.createDataFrame(self.urls, T.StringType()) + + doc_schema = T.StructType([ + T.StructField("text", T.StringType()), + T.StructField('metadata', T.StructType([ + T.StructField('title', T.StringType()), + T.StructField('description', T.StringType()), + T.StructField('language', T.StringType()), + ])) + ]) + + from pyrecdp.primitives.document.reader import read_from_url + docs_rdd = urls_df.rdd.flatMap( + lambda row: read_from_url(row['value'], self.text_to_markdown, **self.loader_kwargs)) + + self.cache = spark.createDataFrame(docs_rdd, doc_schema) + if spark_df is not None: self.cache = self.union_spark_df(spark_df, self.cache) return self.cache diff --git a/RecDP/pyrecdp/primitives/operations/text_reader.py b/RecDP/pyrecdp/primitives/operations/text_reader.py index 6da04dc6..926e1707 100644 --- a/RecDP/pyrecdp/primitives/operations/text_reader.py +++ b/RecDP/pyrecdp/primitives/operations/text_reader.py @@ -99,7 +99,7 @@ def union_spark_df(self, df1, df2): df2_fields_dict[column_name] == NullType() or df1_fields_dict[column_name] == NullType()): df1 = df1.withColumn(column_name, F.col(column_name).cast(StringType())) df2 = df2.withColumn(column_name, F.col(column_name).cast(StringType())) - return df1.union(df2) + return df1.unionByName(df2, allowMissingColumns=True) class JsonlReader(TextReader): def __init__(self, input_dir = "", column_rename_dict = {}): @@ -118,7 +118,7 @@ def process_rayds(self, ds=None) -> Dataset: if ds is not None: self.cache = self.union_ray_ds(ds, self.cache) return self.cache - + def process_spark(self, spark, spark_df: DataFrame = None) -> DataFrame: df = self.rename_spark_df_columns(spark.read.json(self.input_dir).cache()) self.statistics.total_in = df.count() @@ -150,7 +150,7 @@ def __init__(self, input_dir = "", source_prefix = "", column_rename_dict = {}): self.input_dir = input_dir self.source_prefix = source_prefix self.column_rename_dict = column_rename_dict - + def get_files_with_subtask(self, file_type): from pyrecdp.primitives.llmutils.utils import get_target_file_list_from_local, sub_task_per_folder file_name = None @@ -162,11 +162,11 @@ def get_files_with_subtask(self, file_type): files_with_subtask = sub_task_per_folder(get_target_file_list_from_local(self.input_dir, file_name if file_name is not None else file_type)) logger.info(f"Load {files_with_subtask} as subtasks from {self.input_dir}") return files_with_subtask, input_dir - + class SourcedJsonlReader(SourcedReader): def __init__(self, input_dir = "", source_prefix = "", column_rename_dict = {}): super().__init__(input_dir = input_dir, source_prefix = source_prefix, column_rename_dict = column_rename_dict) - + def process_rayds(self, ds=None) -> Dataset: import ray.data as rd files_with_subtask, input_dir = self.get_files_with_subtask("jsonl") @@ -241,14 +241,14 @@ def __init__(self, input_dir = "", column_rename_dict = {}): self.support_spark = True self.input_dir = input_dir self.column_rename_dict = column_rename_dict - + def process_rayds(self, ds=None) -> Dataset: import ray.data as rd self.cache = self.rename_ray_ds_columns(rd.read_parquet(self.input_dir)) if ds is not None: self.cache = self.union_ray_ds(ds, self.cache) return self.cache - + def process_spark(self, spark, spark_df: DataFrame = None) -> DataFrame: self.cache = self.rename_spark_df_columns(spark.read.parquet(self.input_dir)) if spark_df is not None: @@ -259,11 +259,11 @@ def process_spark(self, spark, spark_df: DataFrame = None) -> DataFrame: class SourcedParquetReader(SourcedReader): def __init__(self, input_dir = "", source_prefix = "", column_rename_dict = {}): super().__init__(input_dir = input_dir, source_prefix = source_prefix, column_rename_dict = column_rename_dict) - + def process_rayds(self, ds=None) -> Dataset: import ray.data as rd def add_source(s, source_str): - s['source_id'] = source_str + s['source_id'] = source_str return s files_with_subtask, input_dir = self.get_files_with_subtask("parquet") to_read_list = [(sub_task, os.path.join(input_dir, f)) for sub_task, file_list in files_with_subtask.items() for f in file_list] @@ -273,7 +273,7 @@ def add_source(s, source_str): if ds is not None: self.cache = self.union_ray_ds(ds, self.cache) return self.cache - + def process_spark(self, spark, spark_df: DataFrame = None) -> DataFrame: import pyspark.sql.functions as F files_with_subtask, input_dir = self.get_files_with_subtask("parquet") @@ -320,7 +320,7 @@ def __init__(self, input_dir = "", source_prefix = "", column_rename_dict = {}): super().__init__(input_dir = input_dir, source_prefix = source_prefix, column_rename_dict = column_rename_dict) self.support_spark = True self.support_ray = True - + def process_rayds(self, ds=None): import ray.data as rd files_with_subtask, input_dir = self.get_files_with_subtask("jsonl") @@ -339,7 +339,7 @@ def add_source_str(content, source_str): self.statistics.total_out += ds_count self.cache.append((ds, source_id)) return self.cache - + def process_spark(self, spark, spark_df: DataFrame = None): files_with_subtask, input_dir = self.get_files_with_subtask("jsonl") to_read_list = [(sub_task, os.path.join(input_dir, f)) for sub_task, file_list in files_with_subtask.items() for f in file_list] @@ -368,17 +368,17 @@ def summarize(self) -> str: f"with {self.statistics.total_changed} rows read corrupted, {self.statistics.total_out} rows of data remaining.") LLMOPERATORS.register(PerfileSourcedJsonlReader) - + class PerfileSourcedParquetReader(SourcedReader, PerfileReader): def __init__(self, input_dir = "", source_prefix = "", column_rename_dict = {}): super().__init__(input_dir = input_dir, source_prefix = source_prefix, column_rename_dict = column_rename_dict) self.support_spark = True self.support_ray = True - + def process_rayds(self, ds=None) -> Dataset: import ray.data as rd def add_source(s, source_str): - s['source_id'] = source_str + s['source_id'] = source_str return s files_with_subtask, input_dir = self.get_files_with_subtask("parquet") to_read_list = [(sub_task, os.path.join(input_dir, f)) for sub_task, file_list in files_with_subtask.items() for f in file_list] @@ -388,7 +388,7 @@ def add_source(s, source_str): ds = self.rename_ray_ds_columns(rd.read_parquet(file_path).map(lambda x: add_source(x, source_id))) self.cache.append((ds, source_id)) return self.cache - + def process_spark(self, spark, spark_df: DataFrame = None): import pyspark.sql.functions as F files_with_subtask, input_dir = self.get_files_with_subtask("parquet") @@ -402,5 +402,5 @@ def process_spark(self, spark, spark_df: DataFrame = None): df = df.select(F.concat_ws("@", F.monotonically_increasing_id(), F.lit(source_id)).alias("global_id"), "*") self.cache.append((df, source_id)) return self.cache - + LLMOPERATORS.register(PerfileSourcedParquetReader) diff --git a/RecDP/tests/test_llmutils_operations.py b/RecDP/tests/test_llmutils_operations.py index 5322a633..cee000bd 100644 --- a/RecDP/tests/test_llmutils_operations.py +++ b/RecDP/tests/test_llmutils_operations.py @@ -68,8 +68,7 @@ def show(self, ds): class Test_LLMUtils_Operations(unittest.TestCase): def setUp(self): print(f"\n******\nTesting Method Name: {self._testMethodName}\n******") - - + ### ====== Priority execution ====== ### def a_test_youtube_load_spark(self): urls = ["https://www.youtube.com/watch?v=J31r79uUi9M", "https://www.youtube.com/watch?v=w9kq1BjqrfE"] @@ -82,6 +81,7 @@ def a_test_youtube_load_ray(self): op = YoutubeLoader(urls) with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_rayds()) + ### ====== Ray ====== ### def test_bytesize_ray(self): @@ -231,12 +231,12 @@ def test_gopherqualityfilter_ray(self): with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_rayds(ctx.ds)) - def test_document_load_pdf_ray(self): - op = DirectoryLoader("tests/data/llm_data/document", glob="**/*.pdf") + def test_directory_loader_ray(self): + op = DirectoryLoader("tests/data/llm_data/document") with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_rayds()) - def test_document_load_ray(self): + def test_directory_loader_spark(self): op = DirectoryLoader("tests/data/llm_data/document") with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_rayds()) @@ -245,7 +245,6 @@ def test_url_load_ray(self): op = UrlLoader(["https://www.intc.com/news-events/press-releases?year=2023&category=all"], max_depth=1) with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_rayds()) - def test_document_split_ray(self): op = DocumentSplit() @@ -266,15 +265,61 @@ def test_rag_text_fix_ray(self): op = RAGTextFix(chars_to_remove="abcdedfhijklmn") with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_rayds(ctx.ds)) - + def test_audio_loader_ray(self): op = DirectoryLoader("tests/data/audio") with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_rayds()) + def test_document_loader_ray(self): + url = 'https://app.cnvrg.io/docs/' + op = DocumentLoader(loader='RecursiveUrlLoader', loader_args={'url': url}) + with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: + ctx.show(op.process_rayds()) + + def test_url_loader_ray(self): + urls = ['https://app.cnvrg.io/docs/', + 'https://app.cnvrg.io/docs/core_concepts/python_sdk_v2.html', + 'https://app.cnvrg.io/docs/cli_v2/cnvrgv2_cli.html', + 'https://app.cnvrg.io/docs/collections/tutorials.html'] + op = UrlLoader(urls, max_depth=2) + with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: + ctx.show(op.process_rayds()) + + def test_document_embed_chroma_ray(self): + model_root_path = os.path.join(RECDP_MODELS_CACHE, "huggingface") + op = DocumentIngestion( + vector_store='chroma', + vector_store_args={ + "output_dir": "ResumableTextPipeline_output", + "collection_name": "test_index" + }, + embeddings='HuggingFaceEmbeddings', + embeddings_args={ + 'model_name': f"{model_root_path}/sentence-transformers/all-mpnet-base-v2" + } + ) + with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: + ctx.show(op.process_rayds(ctx.ds)) + + def test_document_embed_faiss_ray(self): + model_root_path = os.path.join(RECDP_MODELS_CACHE, "huggingface") + op = DocumentIngestion( + vector_store='FAISS', + vector_store_args={ + "output_dir": "ResumableTextPipeline_output", + "index_name": "test_index" + }, + embeddings='HuggingFaceEmbeddings', + embeddings_args={ + 'model_name': f"{model_root_path}/sentence-transformers/all-mpnet-base-v2" + } + ) + with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: + ctx.show(op.process_rayds(ctx.ds)) + ### ====== Spark ====== ### - - + def test_bytesize_spark(self): op = TextBytesize() with SparkContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: @@ -423,17 +468,11 @@ def test_gopherqualityfilter_spark(self): with SparkContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_spark(ctx.spark, ctx.ds)) - def test_document_load_spark(self): - op = DirectoryLoader("tests/data/llm_data/document", glob="**/*.pdf") - with SparkContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: - ctx.show(op.process_spark(ctx.spark)) - def test_url_load_spark(self): op = UrlLoader(["https://www.intc.com/news-events/press-releases?year=2023&category=all"], max_depth=1) with SparkContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_spark(ctx.spark)) - def test_document_split_spark(self): op = DocumentSplit() with SparkContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: @@ -444,7 +483,7 @@ def test_rag_text_fix_spark(self): with SparkContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_spark(ctx.spark, ctx.ds)) - def test_document_embed_ray(self): + def test_document_embed_faiss_spark(self): model_root_path = os.path.join(RECDP_MODELS_CACHE, "huggingface") op = DocumentIngestion( vector_store='FAISS', @@ -457,16 +496,16 @@ def test_document_embed_ray(self): 'model_name': f"{model_root_path}/sentence-transformers/all-mpnet-base-v2" } ) - with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: - ctx.show(op.process_rayds(ctx.ds)) + with SparkContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: + ctx.show(op.process_spark(ctx.spark, ctx.ds)) - def test_document_embed_spark(self): + def test_document_embed_chroma_spark(self): model_root_path = os.path.join(RECDP_MODELS_CACHE, "huggingface") op = DocumentIngestion( - vector_store='FAISS', + vector_store='chroma', vector_store_args={ "output_dir": "ResumableTextPipeline_output", - "index_name": "test_index" + "collection_name": "test_index" }, embeddings='HuggingFaceEmbeddings', embeddings_args={ @@ -476,20 +515,21 @@ def test_document_embed_spark(self): with SparkContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_spark(ctx.spark, ctx.ds)) - def test_document_paragraphs_split_ray(self): - model_root_path = os.path.join(RECDP_MODELS_CACHE, "huggingface") - model_name = f"{model_root_path}/sentence-transformers/all-mpnet-base-v2" - op = ParagraphsTextSplitter(model_name=model_name) - with RayContext("tests/data/llm_data/arxiv_sample_100.jsonl") as ctx: - ctx.show(op.process_rayds(ctx.ds)) + # + # def test_document_paragraphs_split_ray(self): + # model_root_path = os.path.join(RECDP_MODELS_CACHE, "huggingface") + # model_name = f"{model_root_path}/sentence-transformers/all-mpnet-base-v2" + # op = ParagraphsTextSplitter(model_name=model_name) + # with RayContext("tests/data/llm_data/arxiv_sample_100.jsonl") as ctx: + # ctx.show(op.process_rayds(ctx.ds)) + # + # def test_document_paragraphs_split_spark(self): + # model_root_path = os.path.join(RECDP_MODELS_CACHE, "huggingface") + # model_name = f"{model_root_path}/sentence-transformers/all-mpnet-base-v2" + # op = ParagraphsTextSplitter(model_name=model_name) + # with SparkContext("tests/data/llm_data/arxiv_sample_100.jsonl") as ctx: + # ctx.show(op.process_spark(ctx.spark, ctx.ds)) - def test_document_paragraphs_split_spark(self): - model_root_path = os.path.join(RECDP_MODELS_CACHE, "huggingface") - model_name = f"{model_root_path}/sentence-transformers/all-mpnet-base-v2" - op = ParagraphsTextSplitter(model_name=model_name) - with SparkContext("tests/data/llm_data/arxiv_sample_100.jsonl") as ctx: - ctx.show(op.process_spark(ctx.spark, ctx.ds)) - def test_audio_loader_spark(self): op = DirectoryLoader("tests/data/audio") with SparkContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: @@ -505,8 +545,7 @@ def test_spell_correct_spark(self): with SparkContext("tests/data/llm_data/tiny_c4_sample_10.jsonl") as ctx: ctx.show(op.process_spark(ctx.spark, ctx.ds)) - - def test_recursive_url_loader_spark(self): + def test_url_loader_spark(self): urls = ['https://app.cnvrg.io/docs/', 'https://app.cnvrg.io/docs/core_concepts/python_sdk_v2.html', 'https://app.cnvrg.io/docs/cli_v2/cnvrgv2_cli.html', @@ -515,11 +554,8 @@ def test_recursive_url_loader_spark(self): with SparkContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: ctx.show(op.process_spark(ctx.spark)) - def test_recursive_url_loader_ray(self): - urls = ['https://app.cnvrg.io/docs/', - 'https://app.cnvrg.io/docs/core_concepts/python_sdk_v2.html', - 'https://app.cnvrg.io/docs/cli_v2/cnvrgv2_cli.html', - 'https://app.cnvrg.io/docs/collections/tutorials.html'] - op = UrlLoader(urls, max_depth=2) - with RayContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: - ctx.show(op.process_rayds()) \ No newline at end of file + def test_document_loader_spark(self): + url = 'https://app.cnvrg.io/docs/' + op = DocumentLoader(loader='RecursiveUrlLoader', loader_args={'url': url}) + with SparkContext("tests/data/llm_data/tiny_c4_sample.jsonl") as ctx: + ctx.show(op.process_spark(ctx.spark)) From bca45dd09f6ba0108459d1b4334c236aadf16c98 Mon Sep 17 00:00:00 2001 From: "Zhang, Chaojun" Date: Tue, 26 Dec 2023 14:34:39 +0000 Subject: [PATCH 30/59] DocumentIngestion should use embedding property to decide whether to write document as vector index or normal index --- .../llmutils/rag_cnvrg_pipeline.ipynb | 3 +- .../rag_cnvrg_pipeline_step_by_step.ipynb | 253 +----------------- RecDP/pyrecdp/datasets/__init__.py | 9 +- .../primitives/operations/text_ingestion.py | 73 ++--- .../primitives/operations/text_reader.py | 2 +- 5 files changed, 44 insertions(+), 296 deletions(-) diff --git a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb index 5db56112..9ac40a0c 100644 --- a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb +++ b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline.ipynb @@ -1221,7 +1221,6 @@ " CustomerDocumentSplit(func=chunk_doc, max_num_of_words=50),\n", " GlobalDeduplicate(),\n", " DocumentIngestion(\n", - " rag_framework='haystack',\n", " vector_store='elasticsearch',\n", " vector_store_args={'host': 'localhost', 'port': 9200}\n", " )\n", @@ -1252,7 +1251,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.10.13" } }, "nbformat": 4, diff --git a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline_step_by_step.ipynb b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline_step_by_step.ipynb index 650e0484..8dddd77d 100644 --- a/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline_step_by_step.ipynb +++ b/RecDP/examples/notebooks/llmutils/rag_cnvrg_pipeline_step_by_step.ipynb @@ -1066,257 +1066,6 @@ "ds = chunk_doc_op.process_rayds(ds)\n", "display(ds.to_pandas())" ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "pLqx_qMnmL1o" - }, - "source": [ - "### 2.3 Store documents \n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### 2.3.1 Setup ElasticSearch\n", - "You'll need to install Docker Engine on your development system. Note that while Docker Engine is free to use, Docker Desktop may require you to purchase a license. See the [Docker Engine Server installation instructions](https://docs.docker.com/engine/install/#server) for details." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "docker: Error response from daemon: driver failed programming external connectivity on endpoint admiring_meitner (af5f1498f190e509046ff0a13aa9a6254e94bbb3e8b6cf7e2a9f9df5d6ae882f): Bind for 127.0.0.1:9300 failed: port is already allocated.\n", - "\u001b[31mERRO\u001b[0m[0000] error waiting for container: \n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-12-19 14:39:30,703 E 4182447 4182465] (raylet) file_system_monitor.cc:111: /tmp/ray/session_2023-12-19_14-38-38_780920_4181242 is over 95% full, available space: 563916800; capacity: 422146228224. Object creation will fail if spilling is required.\n" - ] - } - ], - "source": [ - "!docker run -p 127.0.0.1:9200:9200 -p 127.0.0.1:9300:9300 -e \"discovery.type=single-node\" docker.elastic.co/elasticsearch/elasticsearch:7.17.15" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"name\" : \"ffeee69fabad\",\n", - " \"cluster_name\" : \"docker-cluster\",\n", - " \"cluster_uuid\" : \"QJVbm1Z1RAq7XNnxFdVMeA\",\n", - " \"version\" : {\n", - " \"number\" : \"7.17.15\",\n", - " \"build_flavor\" : \"default\",\n", - " \"build_type\" : \"docker\",\n", - " \"build_hash\" : \"0b8ecfb4378335f4689c4223d1f1115f16bef3ba\",\n", - " \"build_date\" : \"2023-11-10T22:03:46.987399016Z\",\n", - " \"build_snapshot\" : false,\n", - " \"lucene_version\" : \"8.11.1\",\n", - " \"minimum_wire_compatibility_version\" : \"6.8.0\",\n", - " \"minimum_index_compatibility_version\" : \"6.0.0-beta1\"\n", - " },\n", - " \"tagline\" : \"You Know, for Search\"\n", - "}\n" - ] - } - ], - "source": [ - "! curl -X GET \"localhost:9200\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### 2.3.2 Ingest documents into document store" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2023-12-19 15:43:49,797\tINFO dataset.py:2380 -- Tip: Use `take_batch()` instead of `take() / show()` to return records in pandas or numpy batch format.\n", - "2023-12-19 15:43:49,801\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[MapBatches(add_dog_years)] -> LimitOperator[limit=20]\n", - "2023-12-19 15:43:49,803\tINFO streaming_executor.py:94 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=False, actor_locality_enabled=True, verbose_progress=False)\n", - "2023-12-19 15:43:49,804\tINFO streaming_executor.py:96 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "87eb8c5248fa44e592f3bdd9f7de875c", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Running 0: 0%| | 0/1 [00:00 Dict[str, np.ndarray]:\n", - " batch[\"age_in_dog_years\"] = 7 * batch[\"age\"]\n", - " return batch\n", - "\n", - "ds = (\n", - " ray.data.from_items([\n", - " {\"name\": \"Luna\", \"age\": 4},\n", - " {\"name\": \"Rory\", \"age\": 14},\n", - " {\"name\": \"Scout\", \"age\": 9},\n", - " ])\n", - " .map_batches(add_dog_years)\n", - ")\n", - "ds.show()\n" - ] } ], "metadata": { @@ -1338,7 +1087,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.10.13" } }, "nbformat": 4, diff --git a/RecDP/pyrecdp/datasets/__init__.py b/RecDP/pyrecdp/datasets/__init__.py index 3204bd45..7af19adc 100644 --- a/RecDP/pyrecdp/datasets/__init__.py +++ b/RecDP/pyrecdp/datasets/__init__.py @@ -14,11 +14,4 @@ limitations under the License. """ -from pyrecdp.datasets.download import * -from pyrecdp.datasets.nyc_taxi import * -from pyrecdp.datasets.twitter_recsys import * -from pyrecdp.datasets.amazon_product_review import * -from pyrecdp.datasets.outbrain import * -from pyrecdp.datasets.pretrained import * -from pyrecdp.datasets.ibm_fraud_detect import * -from pyrecdp.datasets.CESM_breast_cancer import * \ No newline at end of file +from pyrecdp.datasets.download import * \ No newline at end of file diff --git a/RecDP/pyrecdp/primitives/operations/text_ingestion.py b/RecDP/pyrecdp/primitives/operations/text_ingestion.py index 309db1a4..75e0aa23 100644 --- a/RecDP/pyrecdp/primitives/operations/text_ingestion.py +++ b/RecDP/pyrecdp/primitives/operations/text_ingestion.py @@ -57,14 +57,18 @@ def __init__(self, text_column: str, self.embeddings_column = embeddings_column self.vector_store_args = vector_store_args self.override = override - check_availability_and_install(["langchain"]) + check_availability_and_install('langchain') + from langchain.schema.embeddings import Embeddings self.embeddings: Optional[Embeddings] = self.create_embeddings(embeddings, **embeddings_args) + def is_vector_store(self): + return True + def create_embeddings(self, embeddings, **embeddings_args): """currently we only use langchain embeddings""" if embeddings is None: - return None + embeddings = 'HuggingFaceEmbeddings' if embeddings in ['HuggingFaceEmbeddings', 'HuggingFaceInstructEmbeddings', 'HuggingFaceBgeEmbeddings']: import_sentence_transformers() @@ -80,10 +84,12 @@ def create_embeddings(self, embeddings, **embeddings_args): def persist(self, ds: Union[Dataset, DataFrame], **kwargs): """interface for persist embeddings to underlying vector store""" - if isinstance(ds, Dataset): - ds = self.embedding_with_ray(ds, **kwargs) - else: - ds = self.embedding_with_spark(ds, **kwargs) + if self.is_vector_store(): + check_availability_and_install(["langchain"]) + if isinstance(ds, Dataset): + ds = self.embedding_with_ray(ds, **kwargs) + else: + ds = self.embedding_with_spark(ds, **kwargs) db = self.do_persist(ds, **kwargs) if self.vector_store_args["return_db_handler"]: @@ -133,6 +139,12 @@ def embedding_with_ray(self, ds: Dataset, return ds +class EmbeddingsOnlyStore(DocumentStore): + + def do_persist(self, ds: Union[Dataset, DataFrame], **kwargs): + return ds + + class LangchainFAAIS(DocumentStore): def do_persist(self, ds, **kwargs): check_availability_and_install(["faiss-cpu", "faiss-gpu", "langchain"]) @@ -173,7 +185,6 @@ def do_persist(self, ds, **kwargs): check_availability_and_install(["chromadb==0.4.15", "langchain"]) chroma = self.vector_store_args["db_handler"] - collection_name = self.vector_store_args.get("collection_name", 'langchain') rows = ds.iter_rows() if isinstance(ds, Dataset) else ds.collect() texts = [row[self.text_column] for row in rows] @@ -206,19 +217,15 @@ def do_persist(self, ds, **kwargs): class HaystackElasticSearch(DocumentStore): - def persist(self, ds, **kwargs): - db = self.do_persist(ds, **kwargs) - if self.vector_store_args["return_db_handler"]: - return db - else: - return ds + def is_vector_store(self): + return False def do_persist(self, ds, **kwargs): check_availability_and_install(["farm-haystack", "farm-haystack[elasticsearch7]"]) exclude_keys = ['db_handler', 'return_db_handler'] vector_store_args = dict((k, v) for k, v in self.vector_store_args.items() if k not in exclude_keys) if isinstance(ds, Dataset): - def batch_index(batch, text_column,vector_store_args: Optional[Dict[str, Any]]): + def batch_index(batch, text_column, vector_store_args: Optional[Dict[str, Any]]): from haystack.document_stores import ElasticsearchDocumentStore elasticsearch = ElasticsearchDocumentStore( **vector_store_args @@ -228,7 +235,8 @@ def batch_index(batch, text_column,vector_store_args: Optional[Dict[str, Any]]): elasticsearch.write_documents(documents) return {} - ds.map_batches(lambda batch: batch_index(batch,self.text_column, vector_store_args)).count() + + ds.map_batches(lambda batch: batch_index(batch, self.text_column, vector_store_args)).count() else: def batch_index_with_var(batch, bv_value): from haystack import Document as SDocument @@ -258,11 +266,10 @@ def batch_index_with_var(batch, bv_value): class DocumentIngestion(BaseLLMOperation): def __init__(self, text_column: str = 'text', - rag_framework: Optional[str] = 'langchain', embeddings_column: Optional[str] = 'embedding', - embeddings: Optional[str] = 'HuggingFaceEmbeddings', + embeddings: Optional[str] = None, embeddings_args: Optional[dict] = None, - vector_store: str = 'FAISS', + vector_store: str = None, vector_store_args: Optional[dict] = None, override: bool = False, compute_min_size: Optional[int] = None, @@ -272,16 +279,19 @@ def __init__(self, num_gpus: Optional[int] = None, return_db_handler=False, db_handler=None, - requirements=[]): + requirements=None, + **kwargs): """ Document ingestion operator. Args: text_column: The name of the column containing the text data. rag_framework: The RAG framework to use. The default is 'langchain'. embeddings_column: The name of the column to store the embeddings. - embeddings: The type of embeddings to use. The default is 'HuggingFaceEmbeddings'. - embeddings_args: Optional arguments for the embeddings. - vector_store: The type of vector store to use. The default is 'FAISS'. + embeddings: The type of embeddings to use. + + embeddings_args: Optional arguments for the embeddings. Examples: 'OpenAIEmbeddings', 'HuggingFaceEmbeddings'. + If the embeddings property is specified, then the documents and their embeddings will be written to the vector database. + vector_store: The type of vector store or document store to use. Current we support 'faiss' and 'chroma' for vector store, and 'elasticsearch' for document store. vector_store_args: Optional arguments for the vector store. override: Whether to override the existing embeddings and vector store. compute_min_size: The minimum size of the document to compute embeddings for. @@ -292,11 +302,8 @@ def __init__(self, return_db_handler: If false, return dataset; If True, return created vectorDB handler. db_handler: Use pre-created db_handler as input. """ - if rag_framework is None: - raise ValueError(f"rag framework is required") - - if rag_framework.lower() not in ['langchain', 'haystack']: - raise ValueError(f"only 'langchain' or 'haystack' rag framework is supported") + if requirements is None: + requirements = [] if text_column is None: raise ValueError(f"text column is required") @@ -306,7 +313,6 @@ def __init__(self, settings = { 'text_column': text_column, - 'rag_framework': rag_framework, 'embeddings_column': embeddings_column, 'embeddings': embeddings, @@ -330,7 +336,6 @@ def __init__(self, super().__init__(settings, requirements) self.support_ray = True self.support_spark = True - self.rag_framework = rag_framework.lower() self.text_column = text_column self.embeddings_column = embeddings_column, self.embeddings = embeddings @@ -361,21 +366,23 @@ def _create_document_store(self) -> DocumentStore: 'override': self.override, } - if 'langchain' == self.rag_framework: + if not self.embeddings and not self.vector_store: + return EmbeddingsOnlyStore(**document_store_ctor_args) + + if self.embeddings: if 'faiss' == self.vector_store: return LangchainFAAIS(**document_store_ctor_args) elif 'chroma' == self.vector_store: return LangchainChroma(**document_store_ctor_args) else: raise NotImplementedError( - f"vector store {self.vector_store} is not supported yet paired with langchain!") + f"vector store {self.vector_store} is not supported yet!") else: if 'elasticsearch' == self.vector_store: - document_store_ctor_args['embeddings'] = None return HaystackElasticSearch(**document_store_ctor_args) else: raise NotImplementedError( - f"vector store {self.vector_store} is not supported yet paired with haystack!") + f"document store {self.vector_store} is not supported yet!") def process_rayds(self, ds: Dataset = None): return self.document_store.persist(ds, **self.compute_args) diff --git a/RecDP/pyrecdp/primitives/operations/text_reader.py b/RecDP/pyrecdp/primitives/operations/text_reader.py index 6da04dc6..90a2cdf8 100644 --- a/RecDP/pyrecdp/primitives/operations/text_reader.py +++ b/RecDP/pyrecdp/primitives/operations/text_reader.py @@ -99,7 +99,7 @@ def union_spark_df(self, df1, df2): df2_fields_dict[column_name] == NullType() or df1_fields_dict[column_name] == NullType()): df1 = df1.withColumn(column_name, F.col(column_name).cast(StringType())) df2 = df2.withColumn(column_name, F.col(column_name).cast(StringType())) - return df1.union(df2) + return df1.unionByName(df2, allowMissingColumns=True) class JsonlReader(TextReader): def __init__(self, input_dir = "", column_rename_dict = {}): From aed06bbc97463c5a4abf81587dd8627ec3ef8b90 Mon Sep 17 00:00:00 2001 From: "Zhang, Chaojun" Date: Tue, 26 Dec 2023 16:27:39 +0000 Subject: [PATCH 31/59] Embedding performance improvement: Use function instead of caller to compute embedding, and no need to set up resources --- RecDP/pyrecdp/datasets/__init__.py | 9 +- .../primitives/operations/text_ingestion.py | 221 ++++++++---------- .../primitives/operations/text_reader.py | 2 +- 3 files changed, 95 insertions(+), 137 deletions(-) diff --git a/RecDP/pyrecdp/datasets/__init__.py b/RecDP/pyrecdp/datasets/__init__.py index 3204bd45..7af19adc 100644 --- a/RecDP/pyrecdp/datasets/__init__.py +++ b/RecDP/pyrecdp/datasets/__init__.py @@ -14,11 +14,4 @@ limitations under the License. """ -from pyrecdp.datasets.download import * -from pyrecdp.datasets.nyc_taxi import * -from pyrecdp.datasets.twitter_recsys import * -from pyrecdp.datasets.amazon_product_review import * -from pyrecdp.datasets.outbrain import * -from pyrecdp.datasets.pretrained import * -from pyrecdp.datasets.ibm_fraud_detect import * -from pyrecdp.datasets.CESM_breast_cancer import * \ No newline at end of file +from pyrecdp.datasets.download import * \ No newline at end of file diff --git a/RecDP/pyrecdp/primitives/operations/text_ingestion.py b/RecDP/pyrecdp/primitives/operations/text_ingestion.py index 309db1a4..ec1366c9 100644 --- a/RecDP/pyrecdp/primitives/operations/text_ingestion.py +++ b/RecDP/pyrecdp/primitives/operations/text_ingestion.py @@ -25,23 +25,23 @@ from pyrecdp.primitives.operations.base import BaseLLMOperation, LLMOPERATORS -class TextEmbedding: - def __init__(self, embeddings, text_column: str = 'text', embeddings_column: str = 'embedding'): - # Specify "cuda" to move the model to GPU. - if embeddings is None: - raise ValueError(f"embeddings is required") +def create_embeddings(embeddings_cls: Optional[str] = None, embeddings_construct_args: Optional[dict[str, Any]] = None): + """currently we only use langchain embeddings""" + if embeddings_cls is None: + embeddings_cls = 'HuggingFaceEmbeddings' - from langchain.schema.embeddings import Embeddings - if not isinstance(embeddings, Embeddings): - raise ValueError(f"embeddings must a valid implementation of langchain embeddings") + if embeddings_cls in ['HuggingFaceEmbeddings', 'HuggingFaceInstructEmbeddings', 'HuggingFaceBgeEmbeddings']: + import_sentence_transformers() - self.embeddings: Embeddings = embeddings - self.text_column = text_column - self.embeddings_column = embeddings_column + if embeddings_cls == 'HuggingFaceInstructEmbeddings': + check_availability_and_install("InstructorEmbedding") - def __call__(self, batch): - embeddings = self.embeddings.embed_documents(batch[self.text_column]) - return {self.text_column: batch[self.text_column], self.embeddings_column: embeddings} + from pyrecdp.core.class_utils import new_instance + embeddings_construct_args = embeddings_construct_args or {} + embeddings = new_instance('langchain.embeddings', embeddings_cls, **embeddings_construct_args) + from langchain.schema.embeddings import Embeddings + assert isinstance(embeddings, Embeddings) + return embeddings class DocumentStore(ABC): @@ -49,93 +49,83 @@ class DocumentStore(ABC): def __init__(self, text_column: str, embeddings_column: Optional[str] = 'embedding', - embeddings: Optional[str] = 'HuggingFaceEmbeddings', + embeddings: Optional[str] = None, embeddings_args: Optional[Dict] = None, vector_store_args: Optional[Dict] = None, override: bool = False): self.text_column = text_column + self.embeddings = embeddings self.embeddings_column = embeddings_column self.vector_store_args = vector_store_args self.override = override - check_availability_and_install(["langchain"]) - from langchain.schema.embeddings import Embeddings - self.embeddings: Optional[Embeddings] = self.create_embeddings(embeddings, **embeddings_args) - - def create_embeddings(self, embeddings, **embeddings_args): - """currently we only use langchain embeddings""" - if embeddings is None: - return None - - if embeddings in ['HuggingFaceEmbeddings', 'HuggingFaceInstructEmbeddings', 'HuggingFaceBgeEmbeddings']: - import_sentence_transformers() - if 'HuggingFaceInstructEmbeddings' == embeddings: - check_availability_and_install("InstructorEmbedding") - - from pyrecdp.core.class_utils import new_instance - embeddings = new_instance('langchain.embeddings', embeddings, **embeddings_args) - from langchain.schema.embeddings import Embeddings - assert isinstance(embeddings, Embeddings) - return embeddings - - def persist(self, ds: Union[Dataset, DataFrame], **kwargs): + self.embeddings_args = embeddings_args or {} + + def is_vector_store(self): + return True + + def persist(self, ds: Union[Dataset, DataFrame]): """interface for persist embeddings to underlying vector store""" - if isinstance(ds, Dataset): - ds = self.embedding_with_ray(ds, **kwargs) - else: - ds = self.embedding_with_spark(ds, **kwargs) + if self.is_vector_store(): + check_availability_and_install(["langchain"]) + if isinstance(ds, Dataset): + ds = self.embedding_with_ray(ds) + else: + ds = self.embedding_with_spark(ds) - db = self.do_persist(ds, **kwargs) + db = self.do_persist(ds) if self.vector_store_args["return_db_handler"]: return db else: return ds @abstractmethod - def do_persist(self, ds: Union[Dataset, DataFrame], **kwargs): + def do_persist(self, ds: Union[Dataset, DataFrame]): """base interface for vector store to persist the text and embeddings""" def embedding_with_spark(self, df: DataFrame, **kwargs): import pandas as pd from pyspark.sql import types as T def batch_embedding(batches: Iterable[pd.DataFrame]) -> Iterable[pd.DataFrame]: + lc_embedding = create_embeddings(self.embeddings, self.embeddings_args) for pdf in batches: - pdf[self.embeddings_column] = self.embeddings.embed_documents(pdf[self.text_column]) + pdf[self.embeddings_column] = lc_embedding.embed_documents(pdf[self.text_column]) yield pdf fields = [field for field in df.schema] + [T.StructField(self.embeddings_column, T.ArrayType(T.FloatType()))] df = df.mapInPandas(batch_embedding, T.StructType(fields)) return df - def embedding_with_ray(self, ds: Dataset, - batch_size: Optional[int] = None, - num_gpus: Optional[int] = None, - num_cpus: Optional[int] = None, - compute_min_size: Optional[int] = None, - compute_max_size: Optional[int] = None): - from ray.data import ActorPoolStrategy + def embedding_with_ray(self, ds: Dataset): + + def batch_embedding(batch, text_column: str, embedding_column: str, embeddings: str, + embedding_kwargs: Optional[dict[str, Any]] = None): + lc_embedding = create_embeddings(embeddings, embedding_kwargs) + batch[embedding_column] = lc_embedding.embed_documents(batch[text_column]) + return batch + ds = ds.map_batches( - TextEmbedding, - # Large batch size to maximize GPU utilization. - # Too large a batch size may result in GPU running out of memory. - # If the chunk size is increased, then decrease batch size. - # If the chunk size is decreased, then increase batch size. - batch_size=batch_size, # Large batch size to maximize GPU utilization. - num_gpus=num_gpus, - num_cpus=num_cpus, - compute=ActorPoolStrategy(min_size=compute_min_size, max_size=compute_max_size), - fn_constructor_kwargs={ - "text_column": self.text_column, - 'embeddings_column': self.embeddings_column, - 'embeddings': self.embeddings - } + lambda batch: batch_embedding( + batch, + self.text_column, + self.embeddings_column, + self.embeddings, + self.embeddings_args + ), + batch_format='pandas', ) return ds +class EmbeddingsOnlyStore(DocumentStore): + + def do_persist(self, ds: Union[Dataset, DataFrame], **kwargs): + return ds + + class LangchainFAAIS(DocumentStore): - def do_persist(self, ds, **kwargs): - check_availability_and_install(["faiss-cpu", "faiss-gpu", "langchain"]) + def do_persist(self, ds: Dataset): + check_availability_and_install(["langchain", "faiss-cpu"]) db = self.vector_store_args["db_handler"] index_name = self.vector_store_args.get("index", "index") @@ -151,28 +141,28 @@ def do_persist(self, ds, **kwargs): if "output_dir" not in self.vector_store_args: raise ValueError(f"You must have `output_dir` option specify for FAAIS vector store") faiss_folder_path = self.vector_store_args["output_dir"] + embeddings = create_embeddings(self.embeddings, self.embeddings_args) if not self.override and os.path.exists(os.path.join(faiss_folder_path, index_name + ".faiss")): - db = FAISS.load_local(faiss_folder_path, self.embeddings, index_name) + db = FAISS.load_local(faiss_folder_path, embeddings, index_name) db.add_embeddings(text_embeddings) else: - db = FAISS.from_embeddings(text_embeddings, embedding=self.embeddings) + db = FAISS.from_embeddings(text_embeddings, embedding=embeddings) db.save_local(faiss_folder_path, index_name) return db class LangchainChroma(DocumentStore): - def persist(self, ds, **kwargs): - db = self.do_persist(ds, **kwargs) + def persist(self, ds): + db = self.do_persist(ds) if self.vector_store_args["return_db_handler"]: return db else: return ds - def do_persist(self, ds, **kwargs): - check_availability_and_install(["chromadb==0.4.15", "langchain"]) - chroma = self.vector_store_args["db_handler"] - + def do_persist(self, ds): + check_availability_and_install(["chromadb==0.4.15"]) + chroma = self.vector_store_args["langchain", "db_handler"] collection_name = self.vector_store_args.get("collection_name", 'langchain') rows = ds.iter_rows() if isinstance(ds, Dataset) else ds.collect() @@ -191,34 +181,32 @@ def do_persist(self, ds, **kwargs): else: persist_directory = self.vector_store_args["persist_directory"] + embeddings = create_embeddings(self.embeddings, self.embeddings_args) if not self.override and os.path.exists(persist_directory): chroma = Chroma(collection_name=collection_name, persist_directory=persist_directory, - embedding_function=self.embeddings) + embedding_function=embeddings) chroma.add_texts(texts) else: chroma = Chroma.from_texts(texts, collection_name=collection_name, - embedding=self.embeddings, + embedding=embeddings, persist_directory=persist_directory) chroma.persist() return chroma class HaystackElasticSearch(DocumentStore): - def persist(self, ds, **kwargs): - db = self.do_persist(ds, **kwargs) - if self.vector_store_args["return_db_handler"]: - return db - else: - return ds - def do_persist(self, ds, **kwargs): + def is_vector_store(self): + return False + + def do_persist(self, ds): check_availability_and_install(["farm-haystack", "farm-haystack[elasticsearch7]"]) exclude_keys = ['db_handler', 'return_db_handler'] vector_store_args = dict((k, v) for k, v in self.vector_store_args.items() if k not in exclude_keys) if isinstance(ds, Dataset): - def batch_index(batch, text_column,vector_store_args: Optional[Dict[str, Any]]): + def batch_index(batch, text_column, vector_store_args: Optional[Dict[str, Any]]): from haystack.document_stores import ElasticsearchDocumentStore elasticsearch = ElasticsearchDocumentStore( **vector_store_args @@ -228,7 +216,8 @@ def batch_index(batch, text_column,vector_store_args: Optional[Dict[str, Any]]): elasticsearch.write_documents(documents) return {} - ds.map_batches(lambda batch: batch_index(batch,self.text_column, vector_store_args)).count() + + ds.map_batches(lambda batch: batch_index(batch, self.text_column, vector_store_args)).count() else: def batch_index_with_var(batch, bv_value): from haystack import Document as SDocument @@ -258,45 +247,34 @@ def batch_index_with_var(batch, bv_value): class DocumentIngestion(BaseLLMOperation): def __init__(self, text_column: str = 'text', - rag_framework: Optional[str] = 'langchain', embeddings_column: Optional[str] = 'embedding', - embeddings: Optional[str] = 'HuggingFaceEmbeddings', + embeddings: Optional[str] = None, embeddings_args: Optional[dict] = None, - vector_store: str = 'FAISS', + vector_store: Optional[str] = None, vector_store_args: Optional[dict] = None, override: bool = False, - compute_min_size: Optional[int] = None, - compute_max_size: Optional[int] = None, - batch_size: Optional[int] = None, - num_cpus: Optional[int] = None, - num_gpus: Optional[int] = None, return_db_handler=False, db_handler=None, - requirements=[]): + requirements=None, + **kwargs): """ Document ingestion operator. Args: text_column: The name of the column containing the text data. rag_framework: The RAG framework to use. The default is 'langchain'. embeddings_column: The name of the column to store the embeddings. - embeddings: The type of embeddings to use. The default is 'HuggingFaceEmbeddings'. - embeddings_args: Optional arguments for the embeddings. - vector_store: The type of vector store to use. The default is 'FAISS'. + embeddings: The type of embeddings to use. + + embeddings_args: Optional arguments for the embeddings. Examples: 'OpenAIEmbeddings', 'HuggingFaceEmbeddings'. + If the embeddings property is specified, then the documents and their embeddings will be written to the vector database. + vector_store: The type of vector store or document store to use. Current we support 'faiss' and 'chroma' for vector store, and 'elasticsearch' for document store. vector_store_args: Optional arguments for the vector store. override: Whether to override the existing embeddings and vector store. - compute_min_size: The minimum size of the document to compute embeddings for. - compute_max_size: The maximum size of the document to compute embeddings for. - batch_size: The batch size to use when computing embeddings. - num_cpus: The number of CPUs to use when computing embeddings. - num_gpus: The number of GPUs to use when computing embeddings. return_db_handler: If false, return dataset; If True, return created vectorDB handler. db_handler: Use pre-created db_handler as input. """ - if rag_framework is None: - raise ValueError(f"rag framework is required") - - if rag_framework.lower() not in ['langchain', 'haystack']: - raise ValueError(f"only 'langchain' or 'haystack' rag framework is supported") + if requirements is None: + requirements = [] if text_column is None: raise ValueError(f"text column is required") @@ -306,7 +284,6 @@ def __init__(self, settings = { 'text_column': text_column, - 'rag_framework': rag_framework, 'embeddings_column': embeddings_column, 'embeddings': embeddings, @@ -315,12 +292,6 @@ def __init__(self, 'vector_store': vector_store, 'vector_store_args': vector_store_args, 'override': override, - - 'compute_min_size': compute_min_size, - 'compute_max_size': compute_max_size, - 'batch_size': batch_size, - 'num_gpus': num_gpus, - 'num_cpus': num_cpus, 'requirements': requirements, 'return_db_handler': return_db_handler, @@ -330,19 +301,11 @@ def __init__(self, super().__init__(settings, requirements) self.support_ray = True self.support_spark = True - self.rag_framework = rag_framework.lower() self.text_column = text_column self.embeddings_column = embeddings_column, self.embeddings = embeddings self.embeddings_args = embeddings_args or {} - self.compute_args = { - 'compute_min_size': compute_min_size, - 'compute_max_size': compute_max_size, - 'batch_size': batch_size, - 'num_cpus': num_cpus, - 'num_gpus': num_gpus, - } self.vector_store = vector_store.lower() self.vector_store_args = vector_store_args or {} self.override = override @@ -361,27 +324,29 @@ def _create_document_store(self) -> DocumentStore: 'override': self.override, } - if 'langchain' == self.rag_framework: + if not self.embeddings and not self.vector_store: + return EmbeddingsOnlyStore(**document_store_ctor_args) + + if self.embeddings: if 'faiss' == self.vector_store: return LangchainFAAIS(**document_store_ctor_args) elif 'chroma' == self.vector_store: return LangchainChroma(**document_store_ctor_args) else: raise NotImplementedError( - f"vector store {self.vector_store} is not supported yet paired with langchain!") + f"vector store {self.vector_store} is not supported yet!") else: if 'elasticsearch' == self.vector_store: - document_store_ctor_args['embeddings'] = None return HaystackElasticSearch(**document_store_ctor_args) else: raise NotImplementedError( - f"vector store {self.vector_store} is not supported yet paired with haystack!") + f"document store {self.vector_store} is not supported yet!") def process_rayds(self, ds: Dataset = None): - return self.document_store.persist(ds, **self.compute_args) + return self.document_store.persist(ds) def process_spark(self, spark: SparkSession, df: DataFrame = None): - return self.document_store.persist(df, **self.compute_args) + return self.document_store.persist(df) LLMOPERATORS.register(DocumentIngestion) diff --git a/RecDP/pyrecdp/primitives/operations/text_reader.py b/RecDP/pyrecdp/primitives/operations/text_reader.py index 6da04dc6..90a2cdf8 100644 --- a/RecDP/pyrecdp/primitives/operations/text_reader.py +++ b/RecDP/pyrecdp/primitives/operations/text_reader.py @@ -99,7 +99,7 @@ def union_spark_df(self, df1, df2): df2_fields_dict[column_name] == NullType() or df1_fields_dict[column_name] == NullType()): df1 = df1.withColumn(column_name, F.col(column_name).cast(StringType())) df2 = df2.withColumn(column_name, F.col(column_name).cast(StringType())) - return df1.union(df2) + return df1.unionByName(df2, allowMissingColumns=True) class JsonlReader(TextReader): def __init__(self, input_dir = "", column_rename_dict = {}): From 7dbc02a8a06d38ee88f238a5bba612603990a971 Mon Sep 17 00:00:00 2001 From: "Chendi.Xue" Date: Thu, 4 Jan 2024 10:50:49 -0600 Subject: [PATCH 32/59] Update text_ingestion.py --- RecDP/pyrecdp/primitives/operations/text_ingestion.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/RecDP/pyrecdp/primitives/operations/text_ingestion.py b/RecDP/pyrecdp/primitives/operations/text_ingestion.py index f2289e07..98d6f6bc 100644 --- a/RecDP/pyrecdp/primitives/operations/text_ingestion.py +++ b/RecDP/pyrecdp/primitives/operations/text_ingestion.py @@ -87,8 +87,7 @@ def embedding_with_spark(self, df: DataFrame, **kwargs): import pandas as pd from pyspark.sql import types as T def batch_embedding(batches: Iterable[pd.DataFrame]) -> Iterable[pd.DataFrame]: - lc_embedding = - (self.embeddings, self.embeddings_args) + lc_embedding = create_embeddings(self.embeddings, self.embeddings_args) for pdf in batches: pdf[self.embeddings_column] = lc_embedding.embed_documents(pdf[self.text_column]) yield pdf From 7a5a977c5703470cba2e6df5722cfb3d52f2efe9 Mon Sep 17 00:00:00 2001 From: "Chendi.Xue" Date: Thu, 4 Jan 2024 10:58:09 -0600 Subject: [PATCH 33/59] Update text_ingestion.py --- RecDP/pyrecdp/primitives/operations/text_ingestion.py | 1 + 1 file changed, 1 insertion(+) diff --git a/RecDP/pyrecdp/primitives/operations/text_ingestion.py b/RecDP/pyrecdp/primitives/operations/text_ingestion.py index 98d6f6bc..2e34dc40 100644 --- a/RecDP/pyrecdp/primitives/operations/text_ingestion.py +++ b/RecDP/pyrecdp/primitives/operations/text_ingestion.py @@ -87,6 +87,7 @@ def embedding_with_spark(self, df: DataFrame, **kwargs): import pandas as pd from pyspark.sql import types as T def batch_embedding(batches: Iterable[pd.DataFrame]) -> Iterable[pd.DataFrame]: + lc_embedding = create_embeddings(self.embeddings, self.embeddings_args) for pdf in batches: pdf[self.embeddings_column] = lc_embedding.embed_documents(pdf[self.text_column]) From 9a1eebc3257f5f27b86b0ab5578dfdfbb54e3a18 Mon Sep 17 00:00:00 2001 From: "Chendi.Xue" Date: Thu, 4 Jan 2024 10:59:00 -0600 Subject: [PATCH 34/59] Update text_ingestion.py --- RecDP/pyrecdp/primitives/operations/text_ingestion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecDP/pyrecdp/primitives/operations/text_ingestion.py b/RecDP/pyrecdp/primitives/operations/text_ingestion.py index 2e34dc40..ec1366c9 100644 --- a/RecDP/pyrecdp/primitives/operations/text_ingestion.py +++ b/RecDP/pyrecdp/primitives/operations/text_ingestion.py @@ -87,7 +87,6 @@ def embedding_with_spark(self, df: DataFrame, **kwargs): import pandas as pd from pyspark.sql import types as T def batch_embedding(batches: Iterable[pd.DataFrame]) -> Iterable[pd.DataFrame]: - lc_embedding = create_embeddings(self.embeddings, self.embeddings_args) for pdf in batches: pdf[self.embeddings_column] = lc_embedding.embed_documents(pdf[self.text_column]) @@ -198,6 +197,7 @@ def do_persist(self, ds): class HaystackElasticSearch(DocumentStore): + def is_vector_store(self): return False From c43f810bdc67bb016e032180e36dc2c90c66bbdd Mon Sep 17 00:00:00 2001 From: "Chendi.Xue" Date: Thu, 4 Jan 2024 14:05:02 -0600 Subject: [PATCH 35/59] Update text_ingestion.py --- RecDP/pyrecdp/primitives/operations/text_ingestion.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RecDP/pyrecdp/primitives/operations/text_ingestion.py b/RecDP/pyrecdp/primitives/operations/text_ingestion.py index ec1366c9..98de7b67 100644 --- a/RecDP/pyrecdp/primitives/operations/text_ingestion.py +++ b/RecDP/pyrecdp/primitives/operations/text_ingestion.py @@ -161,8 +161,8 @@ def persist(self, ds): return ds def do_persist(self, ds): - check_availability_and_install(["chromadb==0.4.15"]) - chroma = self.vector_store_args["langchain", "db_handler"] + check_availability_and_install(["chromadb==0.4.15", "langchain"]) + chroma = self.vector_store_args["db_handler"] collection_name = self.vector_store_args.get("collection_name", 'langchain') rows = ds.iter_rows() if isinstance(ds, Dataset) else ds.collect() From 5026b0c0d57aecf52d22645787556fbfe84d7756 Mon Sep 17 00:00:00 2001 From: "Yao, Qing" Date: Fri, 29 Dec 2023 09:26:35 +0800 Subject: [PATCH 36/59] Fix issue about checking emoji lib everytime . --- .../primitives/operations/filter/word_repetition_filter.py | 1 - 1 file changed, 1 deletion(-) diff --git a/RecDP/pyrecdp/primitives/operations/filter/word_repetition_filter.py b/RecDP/pyrecdp/primitives/operations/filter/word_repetition_filter.py index f618af2d..b31ad437 100644 --- a/RecDP/pyrecdp/primitives/operations/filter/word_repetition_filter.py +++ b/RecDP/pyrecdp/primitives/operations/filter/word_repetition_filter.py @@ -18,7 +18,6 @@ from pyrecdp.primitives.operations.utils import get_words_from_document, words_refinement from pyrecdp.primitives.operations.base import LLMOPERATORS from pyrecdp.primitives.operations.filter.base import BaseFilter -from pyrecdp.primitives.operations.constant import SPECIAL_CHARACTERS # This filter is referred from alibaba data juicer project From 54c467350626181590b02dba160098580fc2c09f Mon Sep 17 00:00:00 2001 From: "Yao, Qing" Date: Fri, 29 Dec 2023 10:11:05 +0800 Subject: [PATCH 37/59] Fix bug if loader can't get any data. . --- RecDP/pyrecdp/primitives/operations/text_ingestion.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/RecDP/pyrecdp/primitives/operations/text_ingestion.py b/RecDP/pyrecdp/primitives/operations/text_ingestion.py index 98de7b67..ff32a4f1 100644 --- a/RecDP/pyrecdp/primitives/operations/text_ingestion.py +++ b/RecDP/pyrecdp/primitives/operations/text_ingestion.py @@ -23,6 +23,7 @@ from pyrecdp.core.import_utils import check_availability_and_install, import_sentence_transformers from pyrecdp.primitives.operations.base import BaseLLMOperation, LLMOPERATORS +from pyrecdp.primitives.operations.logging_utils import logger def create_embeddings(embeddings_cls: Optional[str] = None, embeddings_construct_args: Optional[dict[str, Any]] = None): @@ -132,7 +133,9 @@ def do_persist(self, ds: Dataset): rows = ds.iter_rows() if isinstance(ds, Dataset) else ds.collect() text_embeddings = [(row[self.text_column], row[self.embeddings_column]) for row in rows] - + if not bool(text_embeddings): + logger.error("Text embeddings is empty, no data to store!") + return db from langchain.vectorstores.faiss import FAISS if db is not None: db.add_embeddings(text_embeddings) From 74d86d8f66b7ad7d5a633b18a64477edf9dbf217 Mon Sep 17 00:00:00 2001 From: "Yao, Qing" Date: Fri, 29 Dec 2023 13:57:24 +0800 Subject: [PATCH 38/59] Add a pdfocrreaer. . --- RecDP/pyrecdp/primitives/document/reader.py | 56 +++++++++++++++++- .../primitives/operations/doc_loader.py | 5 ++ .../llm_data/document/Sample_Scanned_PDF.pdf | Bin 0 -> 887265 bytes RecDP/tests/test_llmutils_operations.py | 22 ++++--- 4 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 RecDP/tests/data/llm_data/document/Sample_Scanned_PDF.pdf diff --git a/RecDP/pyrecdp/primitives/document/reader.py b/RecDP/pyrecdp/primitives/document/reader.py index 7b0bf3af..4758fe12 100644 --- a/RecDP/pyrecdp/primitives/document/reader.py +++ b/RecDP/pyrecdp/primitives/document/reader.py @@ -113,6 +113,39 @@ def load_file(self, file: Path) -> List[Document]: return docs +class PDFOcrReader(FileBaseReader): + """PDF parser.""" + system_requirements = ['tesseract-ocr'] + requirements = ['PyMuPDF', 'pillow', 'pytesseract'] + + def __init__(self, file: Path, single_text_per_document: bool = True, page_separator: str = '\n', + **load_kwargs): + super().__init__(file, single_text_per_document, page_separator) + self.load_kwargs = load_kwargs + self.file = file + + def load_file(self, file: Path) -> List[Document]: + import fitz + from PIL import Image + import tempfile + from pytesseract import pytesseract + docs = [] + pdf_document = fitz.open(file) + for page_number in range(pdf_document.page_count): + page = pdf_document[page_number] + page_label = page.get_label() + pix = page.get_pixmap() + image = Image.frombytes("RGB", [pix.width, pix.height], pix.samples) + with tempfile.TemporaryDirectory() as td: + img_tmp = os.path.join(td, 'recdp_tmp.png') + image.save(img_tmp) + page_text = pytesseract.image_to_string(image) + metadata = {"page_label": page_label, "source": str(file)} + docs.append(Document(text=page_text, metadata=metadata)) + pdf_document.close() + return docs + + class DocxReader(FileBaseReader): """Docx parser.""" system_requirements = [] @@ -212,7 +245,28 @@ def read_from_directory(input_dirs: Optional[Union[str, List[str]]] = None, exclude_hidden: bool = True, max_concurrency: Optional[int] = None, loaders: Optional[dict[str, Callable[[Path], List[Document]]]] = None, - required_exts: Optional[List[str]] = None): + required_exts: Optional[List[str]] = None, + pdf_ocr: bool = False, + ): + """ + Loads documents from a directory or a list of files. + + Args: + input_dirs: The input directory. + input_files: A list of input files. + glob: A glob pattern to match files. + recursive: Whether to recursively search the input directory. + exclude: A list of file patterns to exclude from loading. + exclude_hidden: Whether to exclude hidden files from loading. + max_concurrency: The maximum number of concurrent threads to use. + loaders: Text Loader user what to use. + required_exts: A list of file extensions that are required for documents. + default extensions are [.pdf, .docx, .jpeg, .jpg, .png] + pdf_ocr: Whether to use ocr to load pdf. + """ + if pdf_ocr: + _default_file_readers['.pdf'] = PDFOcrReader + def read_file(file_to_load, par): try: # use customer loader first if possible diff --git a/RecDP/pyrecdp/primitives/operations/doc_loader.py b/RecDP/pyrecdp/primitives/operations/doc_loader.py index 3f6cfcc7..db3b51c1 100644 --- a/RecDP/pyrecdp/primitives/operations/doc_loader.py +++ b/RecDP/pyrecdp/primitives/operations/doc_loader.py @@ -93,6 +93,7 @@ def __init__(self, input_dir: Optional[Union[str, List[str]]] = None, required_exts: Optional[List[str]] = None, file_loaders: Optional[dict[str, Callable[[Path], List[Document]]]] = None, requirements=None, + pdf_ocr: bool = False, **kwargs): """ Loads documents from a directory or a list of files. @@ -107,6 +108,7 @@ def __init__(self, input_dir: Optional[Union[str, List[str]]] = None, exclude_hidden: Whether to exclude hidden files from loading. file_loaders: customize file loader. required_exts: A list of file extensions that are required for documents. + pdf_ocr: Whether to use ocr to load pdf. """ if requirements is None: @@ -125,6 +127,7 @@ def __init__(self, input_dir: Optional[Union[str, List[str]]] = None, 'max_concurrency': max_concurrency, 'required_exts': required_exts, 'file_loaders': file_loaders, + 'pdf_ocr': pdf_ocr } self.input_files = input_files @@ -136,6 +139,7 @@ def __init__(self, input_dir: Optional[Union[str, List[str]]] = None, self.max_concurrency = max_concurrency self.required_exts = required_exts self.file_loaders = file_loaders + self.pdf_ocr = pdf_ocr super().__init__(args_dict=settings, requirements=requirements) @@ -151,6 +155,7 @@ def load_documents(self): max_concurrency=self.max_concurrency, required_exts=self.required_exts, loaders=self.file_loaders, + pdf_ocr=self.pdf_ocr, ) def process_rayds(self, ds=None): diff --git a/RecDP/tests/data/llm_data/document/Sample_Scanned_PDF.pdf b/RecDP/tests/data/llm_data/document/Sample_Scanned_PDF.pdf new file mode 100644 index 0000000000000000000000000000000000000000..30f29a7b91f3b8c591978b1fc3532e10f4eba649 GIT binary patch literal 887265 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

      c_hY+Ch6z7YE+c)?Yt13@+ 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∾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

    Y`ot-fcvcmHmq*XYj#rh!l;gGju_AOCPz8 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ǧ?zUj>5m?Xb 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�%cNit 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 &u(hyR$$Q7ux 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