From 42f0045e0afc0cdb1ece5d19934edfef2145544d Mon Sep 17 00:00:00 2001 From: Angel Delgado Panadero Date: Fri, 15 Sep 2023 12:11:50 +0200 Subject: [PATCH 01/20] initial commit --- .../text-davinci-003_en_classification.prompt | 54 +++++++++++++++++++ .../text-davinci-003_es_classification.prompt | 54 +++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 promptmeteo/prompts/text-davinci-003_en_classification.prompt create mode 100644 promptmeteo/prompts/text-davinci-003_es_classification.prompt diff --git a/promptmeteo/prompts/text-davinci-003_en_classification.prompt b/promptmeteo/prompts/text-davinci-003_en_classification.prompt new file mode 100644 index 0000000..582da33 --- /dev/null +++ b/promptmeteo/prompts/text-davinci-003_en_classification.prompt @@ -0,0 +1,54 @@ +# Copyright (c) 2023 Paradigma Digital S.L. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + + +TEMPLATE: + "I need you to help me with a text classification task. + {__PROMPT_DOMAIN__} + {__PROMPT_LABELS__} + + {__CHAIN_THOUGHT__} + {__ANSWER_FORMAT__}" + + +PROMPT_DOMAIN: + "The texts you will be processing are from the {__DOMAIN__} domain." + + +PROMPT_LABELS: + "I want you to classify the texts into one of the following categories: + {__LABELS__}." + + +PROMPT_DETAIL: + "" + + +CHAIN_THOUGHT: + "Please provide a step-by-step argument for your answer, explain why you + believe your final choice is justified, and make sure to conclude your + explanation with the name of the class you have selected as the correct + one, in lowercase and without punctuation." + + +ANSWER_FORMAT: + "In your response, include only the name of the class as a single word, in + lowercase, without punctuation, and without adding any other statements or + words." diff --git a/promptmeteo/prompts/text-davinci-003_es_classification.prompt b/promptmeteo/prompts/text-davinci-003_es_classification.prompt new file mode 100644 index 0000000..ec72f9d --- /dev/null +++ b/promptmeteo/prompts/text-davinci-003_es_classification.prompt @@ -0,0 +1,54 @@ +# Copyright (c) 2023 Paradigma Digital S.L. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + + +TEMPLATE: + "Necesito que me ayudes en una tarea de clasificación de texto. + {__PROMPT_DOMAIN__} + {__PROMPT_LABELS__} + + {__CHAIN_THOUGHT__} + {__ANSWER_FORMAT__}" + + +PROMPT_DOMAIN: + "Los textos que vas procesar del ambito de {__DOMAIN__}." + + +PROMPT_LABELS: + "Quiero que me clasifiques los textos una de las siguientes categorías: + {__LABELS__}." + + +PROMPT_DETAIL: + "" + + +CHAIN_THOUGHT: + "Por favor argumenta tu respuesta paso a paso, explica por qué crees que + está justificada tu elección final, y asegúrate de que acabas tu + explicación con el nombre de la clase que has escogido como la + correcta, en minúscula y sin puntuación." + + +ANSWER_FORMAT: + "En tu respuesta incluye sólo el nombre de la clase, como una única + palabra, en minúscula, sin puntuación, y sin añadir ninguna otra + afirmación o palabra." From e330a7156e21694d412dcb56c2d1f0891db180a6 Mon Sep 17 00:00:00 2001 From: Bea Date: Thu, 18 Jan 2024 16:10:13 +0100 Subject: [PATCH 02/20] [Feature: New model] API Generation (#6) * Add new models: OpenAI GPT3.5-Turbo and Azure OpenAI. Azure OpenAI allows for the embeddings model to be from a different endpoint * Parser for the API generation and correction response * add models, prompts and add to tests * Changes: - Change in base.py from prompts, formatting the prompt - Change in test_prompts adding a new symbol to delete * add data for examples --------- Co-authored-by: Miguel Lopez --- ...5_test_openai_classification_prompts.ipynb | 1718 +++++++++++++++++ promptmeteo/api_formatter.py | 6 +- .../text-davinci-003_en_classification.prompt | 54 - .../text-davinci-003_es_classification.prompt | 54 - promptmeteo/tasks/task.py | 1 + 5 files changed, 1723 insertions(+), 110 deletions(-) create mode 100644 examples/05_test_openai_classification_prompts.ipynb delete mode 100644 promptmeteo/prompts/text-davinci-003_en_classification.prompt delete mode 100644 promptmeteo/prompts/text-davinci-003_es_classification.prompt diff --git a/examples/05_test_openai_classification_prompts.ipynb b/examples/05_test_openai_classification_prompts.ipynb new file mode 100644 index 0000000..fb85aad --- /dev/null +++ b/examples/05_test_openai_classification_prompts.ipynb @@ -0,0 +1,1718 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "73d808a5-a4dd-4ec5-b4bc-438f1dd5596f", + "metadata": {}, + "source": [ + "# OpenAI test classification prompts." + ] + }, + { + "cell_type": "markdown", + "id": "7ffd3703-20b9-46b6-8ad3-502ec27d2e49", + "metadata": {}, + "source": [ + "In this notebook we are going to use the **Amazon Review Dataset** to test Promptmeteo in the sentiment analysis task" + ] + }, + { + "cell_type": "markdown", + "id": "dad1d69f-59bf-4f34-9000-46e5851d99f6", + "metadata": {}, + "source": [ + "## 1. Data Preparation - EN - Build sentiment dataset." + ] + }, + { + "cell_type": "markdown", + "id": "7993f034-cdd6-4424-b6d1-5917b0638583", + "metadata": {}, + "source": [ + "The dataset contains reviews from Amazon in English collected between November 1, 2015 and November 1, 2019. Each record in the dataset contains the review text, the review title, the star rating, an anonymized reviewer ID, an anonymized product ID and the coarse-grained product category (e.g. ‘books’, ‘appliances’, etc.). The corpus is balanced across stars, so each star rating constitutes 20% of the reviews in each language." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "d2c9f56c-4717-42a8-b9d4-cfcc20215f99", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "shape: (5, 2)
REVIEWTARGET
strstr
"I reuse my Nes…"positive"
"Fits great kin…"positive"
"Movie freezes …"negative"
"This is my thi…"positive"
"For the money,…"neutral"
" + ], + "text/plain": [ + "shape: (5, 2)\n", + "┌───────────────────────────────────┬──────────┐\n", + "│ REVIEW ┆ TARGET │\n", + "│ --- ┆ --- │\n", + "│ str ┆ str │\n", + "╞═══════════════════════════════════╪══════════╡\n", + "│ I reuse my Nespresso capsules an… ┆ positive │\n", + "│ Fits great kinda expensive but i… ┆ positive │\n", + "│ Movie freezes up. Can't watch it… ┆ negative │\n", + "│ This is my third G-shock as I ha… ┆ positive │\n", + "│ For the money, it's a good buy..… ┆ neutral │\n", + "└───────────────────────────────────┴──────────┘" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import polars as pl\n", + "import sys; sys.path.append('..')\n", + "\n", + "data = pl.read_parquet('../data/amazon_reviews_en/amazon_reviews_multi-test.parquet')\n", + "sql = pl.SQLContext()\n", + "sql.register('data', data)\n", + "\n", + "sentiment_data = sql.execute(\"\"\"\n", + " SELECT\n", + " review_body as REVIEW,\n", + " CASE\n", + " WHEN stars=1 THEN 'negative'\n", + " WHEN stars=3 THEN 'neutral'\n", + " WHEN stars=5 THEN 'positive'\n", + " ELSE null\n", + " END AS TARGET,\n", + " FROM data\n", + " WHERE stars!=2 AND stars!=4;\n", + " \"\"\").collect().sample(fraction=1.0, shuffle=True, seed=0)\n", + "\n", + "train_reviews = sentiment_data.head(100).select('REVIEW').to_series().to_list()\n", + "train_targets = sentiment_data.head(100).select('TARGET').to_series().to_list()\n", + "\n", + "test_reviews = sentiment_data.tail(100).select('REVIEW').to_series().to_list()\n", + "test_targets = sentiment_data.tail(100).select('TARGET').to_series().to_list()\n", + "\n", + "sentiment_data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4baccad9-20fd-48a6-adb4-d75d2335a3ac", + "metadata": {}, + "outputs": [], + "source": [ + "token = 'sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'" + ] + }, + { + "cell_type": "markdown", + "id": "34b211cc-0fcf-47a9-ad80-edd70577648b", + "metadata": {}, + "source": [ + " \n" + ] + }, + { + "cell_type": "markdown", + "id": "6f43c63d-b523-418b-bee8-6faf65186e61", + "metadata": {}, + "source": [ + " \n" + ] + }, + { + "cell_type": "markdown", + "id": "37078106-46f9-4f2b-8719-199fef2aad51", + "metadata": {}, + "source": [ + " \n" + ] + }, + { + "cell_type": "markdown", + "id": "51e6344e-549f-4c33-8ba9-6256e47c2c09", + "metadata": {}, + "source": [ + "## 2. EN - Sin entrenamiento" + ] + }, + { + "cell_type": "markdown", + "id": "9153b637-b41b-42a0-8cb5-2f7d273ee842", + "metadata": {}, + "source": [ + "### Prueba 1" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "98ff2491-70ae-48b4-a887-e1f81c33ef8a", + "metadata": {}, + "outputs": [], + "source": [ + "prompt='''\n", + "TEMPLATE:\n", + " \"I need you to help me with a text classification task.\n", + " {__PROMPT_DOMAIN__}\n", + " {__PROMPT_LABELS__}\n", + "\n", + " {__CHAIN_THOUGHT__}\n", + " {__ANSWER_FORMAT__}\"\n", + "\n", + "\n", + "PROMPT_DOMAIN:\n", + " \"The texts you will be processing are from the {__DOMAIN__} domain.\"\n", + "\n", + "\n", + "PROMPT_LABELS:\n", + " \"I want you to classify the texts into one of the following categories:\n", + " {__LABELS__}.\"\n", + "\n", + "\n", + "PROMPT_DETAIL:\n", + " \"\"\n", + "\n", + "\n", + "CHAIN_THOUGHT:\n", + " \"Please provide a step-by-step argument for your answer, explain why you\n", + " believe your final choice is justified, and make sure to conclude your\n", + " explanation with the name of the class you have selected as the correct\n", + " one, in lowercase and without punctuation.\"\n", + "\n", + "\n", + "ANSWER_FORMAT:\n", + " \"In your response, include only the name of the class as a single word, in\n", + " lowercase, without punctuation, and without adding any other statements or\n", + " words.\"\n", + "'''" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "b491bbff-68ae-4265-a08a-56108ed94fdb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import seaborn as sns\n", + "from sklearn.metrics import confusion_matrix\n", + "from promptmeteo import DocumentClassifier\n", + "\n", + "model = DocumentClassifier(\n", + " language = 'en',\n", + " model_name = 'text-davinci-003',\n", + " model_provider_name = 'openai',\n", + " model_provider_token = token,\n", + " prompt_domain = 'product reviews',\n", + " prompt_labels = ['positive','negative','neutral'],\n", + " selector_k = 0,\n", + ")\n", + "\n", + "model.task.prompt.read_prompt(prompt)\n", + "\n", + "pred_targets = model.predict(test_reviews)\n", + "pred_targets = [pred if len(pred)==1 else [''] for pred in pred_targets]\n", + "\n", + "sns.heatmap(\n", + " confusion_matrix(test_targets, pred_targets),\n", + " annot=True,\n", + " cmap='Blues')" + ] + }, + { + "cell_type": "markdown", + "id": "76722bfe-f1b9-47fe-9f87-2bc9f97062ca", + "metadata": {}, + "source": [ + "### Prueba 2" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "349e834b-a836-4093-b705-210ccc618c90", + "metadata": {}, + "outputs": [], + "source": [ + "prompt='''\n", + "TEMPLATE:\n", + " \"I need you to help me with a text classification task.\n", + " {__PROMPT_DOMAIN__}\n", + " {__PROMPT_LABELS__}\n", + "\n", + " {__CHAIN_THOUGHT__}\n", + " {__ANSWER_FORMAT__}\"\n", + "\n", + "\n", + "PROMPT_DOMAIN:\n", + " \"The texts you will be processing are from the {__DOMAIN__} domain.\"\n", + "\n", + "\n", + "PROMPT_LABELS:\n", + " \"I want you to classify the texts into one of the following categories:\n", + " {__LABELS__}.\"\n", + "\n", + "\n", + "PROMPT_DETAIL:\n", + " \"\"\n", + "\n", + "\n", + "CHAIN_THOUGHT:\n", + " \"Think step by step you answer.\"\n", + "\n", + "\n", + "ANSWER_FORMAT:\n", + " \"In your response, include only the name of the class predicted.\"\n", + "'''" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "988735fe-a05b-4c01-a4a4-4c262f28add1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import seaborn as sns\n", + "from sklearn.metrics import confusion_matrix\n", + "from promptmeteo import DocumentClassifier\n", + "\n", + "model = DocumentClassifier(\n", + " language = 'en',\n", + " model_name = 'text-davinci-003',\n", + " model_provider_name = 'openai',\n", + " model_provider_token = token,\n", + " prompt_domain = 'product reviews',\n", + " prompt_labels = ['positive','negative','neutral'],\n", + " selector_k = 0,\n", + ")\n", + "\n", + "model.task.prompt.read_prompt(prompt)\n", + "\n", + "pred_targets = model.predict(test_reviews)\n", + "\n", + "sns.heatmap(\n", + " confusion_matrix(test_targets, pred_targets),\n", + " annot=True,\n", + " cmap='Blues')" + ] + }, + { + "cell_type": "markdown", + "id": "c703c30f-d696-4379-84a3-c536a6d7f565", + "metadata": {}, + "source": [ + "## 3. EN - Con entrenamiento" + ] + }, + { + "cell_type": "markdown", + "id": "71ce3032-eaa0-4ba9-b7ff-2f455f57a66f", + "metadata": {}, + "source": [ + "### Prueba 1" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "ef488d68-63b3-4f15-8e4c-d56633ddb147", + "metadata": {}, + "outputs": [], + "source": [ + "prompt='''\n", + "TEMPLATE:\n", + " \"I need you to help me with a text classification task.\n", + " {__PROMPT_DOMAIN__}\n", + " {__PROMPT_LABELS__}\n", + "\n", + " {__CHAIN_THOUGHT__}\n", + " {__ANSWER_FORMAT__}\"\n", + "\n", + "\n", + "PROMPT_DOMAIN:\n", + " \"The texts you will be processing are from the {__DOMAIN__} domain.\"\n", + "\n", + "\n", + "PROMPT_LABELS:\n", + " \"I want you to classify the texts into one of the following categories:\n", + " {__LABELS__}.\"\n", + "\n", + "\n", + "PROMPT_DETAIL:\n", + " \"\"\n", + "\n", + "\n", + "CHAIN_THOUGHT:\n", + " \"Please provide a step-by-step argument for your answer, explain why you\n", + " believe your final choice is justified, and make sure to conclude your\n", + " explanation with the name of the class you have selected as the correct\n", + " one, in lowercase and without punctuation.\"\n", + "\n", + "\n", + "ANSWER_FORMAT:\n", + " \"In your response, include only the name of the class as a single word, in\n", + " lowercase, without punctuation, and without adding any other statements or\n", + " words.\"\n", + "'''" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "172c20d7-cecb-44ef-9fff-82d075b1d53f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import seaborn as sns\n", + "from sklearn.metrics import confusion_matrix\n", + "from promptmeteo import DocumentClassifier\n", + "\n", + "model = DocumentClassifier(\n", + " language = 'en',\n", + " model_name = 'text-davinci-003',\n", + " model_provider_name = 'openai',\n", + " model_provider_token = token,\n", + " selector_k = 10,\n", + ")\n", + "\n", + "model.task.prompt.read_prompt(prompt)\n", + "\n", + "model.train(\n", + " examples = train_reviews,\n", + " annotations = train_targets\n", + ")\n", + "\n", + "pred_targets = model.predict(test_reviews)\n", + "\n", + "sns.heatmap(\n", + " confusion_matrix(test_targets, pred_targets),\n", + " annot=True,\n", + " cmap='Blues')" + ] + }, + { + "cell_type": "markdown", + "id": "5e9681b2-c628-4a3f-968d-c5cbecc298ec", + "metadata": {}, + "source": [ + "### Prueba 2" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "9def17bf-b9fc-4afd-af9a-fdeef0c974aa", + "metadata": {}, + "outputs": [], + "source": [ + "prompt='''\n", + "TEMPLATE:\n", + " \"I need you to help me with a text classification task.\n", + " {__PROMPT_DOMAIN__}\n", + " {__PROMPT_LABELS__}\n", + "\n", + " {__CHAIN_THOUGHT__}\n", + " {__ANSWER_FORMAT__}\"\n", + "\n", + "\n", + "PROMPT_DOMAIN:\n", + " \"The texts you will be processing are from the {__DOMAIN__} domain.\"\n", + "\n", + "\n", + "PROMPT_LABELS:\n", + " \"I want you to classify the texts into one of the following categories:\n", + " {__LABELS__}.\"\n", + "\n", + "\n", + "PROMPT_DETAIL:\n", + " \"\"\n", + "\n", + "\n", + "CHAIN_THOUGHT:\n", + " \"Think step by step you answer.\"\n", + "\n", + "\n", + "ANSWER_FORMAT:\n", + " \"In your response, include only the name of the class predicted.\"\n", + "'''" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "0c198bff-2112-4141-a528-3d97c9d16a33", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import seaborn as sns\n", + "from sklearn.metrics import confusion_matrix\n", + "from promptmeteo import DocumentClassifier\n", + "\n", + "model = DocumentClassifier(\n", + " language = 'en',\n", + " model_name = 'text-davinci-003',\n", + " model_provider_name = 'openai',\n", + " model_provider_token = token,\n", + " prompt_domain = 'product reviews',\n", + " prompt_labels = ['positive','negative','neutral'],\n", + " selector_k = 20,\n", + ")\n", + "\n", + "model.task.prompt.read_prompt(prompt)\n", + "\n", + "model.train(\n", + " examples = train_reviews,\n", + " annotations = train_targets,\n", + ")\n", + "\n", + "pred_targets = model.predict(test_reviews)\n", + "\n", + "sns.heatmap(\n", + " confusion_matrix(test_targets, pred_targets),\n", + " annot=True,\n", + " cmap='Blues')" + ] + }, + { + "cell_type": "markdown", + "id": "1d69e21c-d1d9-4897-a6df-ec5ef43fe4d0", + "metadata": {}, + "source": [ + " \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dd55f1c6-ac6e-447f-b291-1d0ac50e9048", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "0d24dafd-c16a-40f6-8537-69ff06a1b34d", + "metadata": {}, + "source": [ + "### Prueba 3" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "f0bab4a5-da98-4362-9f52-c3f5ca534ccd", + "metadata": {}, + "outputs": [], + "source": [ + "prompt='''\n", + "TEMPLATE:\n", + " \"I need you to help me with a text classification task.\n", + " {__PROMPT_DOMAIN__}\n", + " {__PROMPT_LABELS__}\n", + "\n", + " {__CHAIN_THOUGHT__}\n", + " {__ANSWER_FORMAT__}\"\n", + "\n", + "PROMPT_DOMAIN:\n", + " \"\"\n", + "\n", + "PROMPT_LABELS:\n", + " \"\"\n", + "\n", + "PROMPT_DETAIL:\n", + " \"\"\n", + "\n", + "CHAIN_THOUGHT:\n", + " \"\"\n", + "\n", + "ANSWER_FORMAT:\n", + " \"\"\n", + "'''" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "c0cf795a-4563-4f6b-a970-20c47eca9870", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import seaborn as sns\n", + "from sklearn.metrics import confusion_matrix\n", + "from promptmeteo import DocumentClassifier\n", + "\n", + "model = DocumentClassifier(\n", + " language = 'en',\n", + " model_name = 'text-davinci-003',\n", + " model_provider_name = 'openai',\n", + " model_provider_token = token,\n", + " selector_k = 20,\n", + ")\n", + "\n", + "model.task.prompt.read_prompt(prompt)\n", + "\n", + "model.train(\n", + " examples = train_reviews,\n", + " annotations = train_targets,\n", + ")\n", + "\n", + "pred_targets = model.predict(test_reviews)\n", + "\n", + "sns.heatmap(\n", + " confusion_matrix(test_targets, pred_targets),\n", + " annot=True,\n", + " cmap='Blues')" + ] + }, + { + "cell_type": "markdown", + "id": "ea111fd4-6640-4631-b6ed-897fa95d10e2", + "metadata": {}, + "source": [ + " \n" + ] + }, + { + "cell_type": "markdown", + "id": "b9993ba0-7b7b-44d5-b89b-d399ce4d9649", + "metadata": {}, + "source": [ + " \n" + ] + }, + { + "cell_type": "markdown", + "id": "194182f1-0296-4d51-8d5a-aa736d722406", + "metadata": {}, + "source": [ + "## 4. Data Preparation - SP - Build sentiment dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "0b3ff622-fdb4-49da-ace2-c9e2a1cffcfb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "shape: (5, 2)
REVIEWTARGET
strstr
"El filtro de d…"positive"
"Un poquito esc…"positive"
"Para qué decir…"negative"
"Mi hija esta e…"positive"
"Se podría mejo…"neutral"
" + ], + "text/plain": [ + "shape: (5, 2)\n", + "┌───────────────────────────────────┬──────────┐\n", + "│ REVIEW ┆ TARGET │\n", + "│ --- ┆ --- │\n", + "│ str ┆ str │\n", + "╞═══════════════════════════════════╪══════════╡\n", + "│ El filtro de de aire es como si … ┆ positive │\n", + "│ Un poquito escaso pero funciona … ┆ positive │\n", + "│ Para qué decir más... ┆ negative │\n", + "│ Mi hija esta en un campamento y … ┆ positive │\n", + "│ Se podría mejorar el ajuste del … ┆ neutral │\n", + "└───────────────────────────────────┴──────────┘" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import polars as pl\n", + "\n", + "data = pl.read_parquet('../data/amazon_reviews_sp/amazon_reviews_multi-test.parquet')\n", + "data.head()\n", + "\n", + "sql = pl.SQLContext()\n", + "sql.register('data', data)\n", + "\n", + "sentiment_data = sql.execute(\"\"\"\n", + " SELECT\n", + " review_body as REVIEW,\n", + " CASE\n", + " WHEN stars=1 THEN 'negative'\n", + " WHEN stars=3 THEN 'neutral'\n", + " WHEN stars=5 THEN 'positive'\n", + " ELSE null\n", + " END AS TARGET,\n", + " FROM data\n", + " WHERE stars!=2 AND stars!=4;\n", + " \"\"\").collect().sample(fraction=1.0, shuffle=True, seed=0)\n", + "/\n", + "train_reviews = sentiment_data.head(100).select('REVIEW').to_series().to_list()\n", + "train_targets = sentiment_data.head(100).select('TARGET').to_series().to_list()\n", + "\n", + "test_reviews = sentiment_data.tail(100).select('REVIEW').to_series().to_list()\n", + "test_targets = sentiment_data.tail(100).select('TARGET').to_series().to_list()\n", + "\n", + "sentiment_data.head()" + ] + }, + { + "cell_type": "markdown", + "id": "cdfdb171-0391-4e3e-beca-072d56267948", + "metadata": {}, + "source": [ + " \n" + ] + }, + { + "cell_type": "markdown", + "id": "d4d2b731-7d7c-4217-9a51-47e6689bbe7f", + "metadata": {}, + "source": [ + " \n" + ] + }, + { + "cell_type": "markdown", + "id": "de2d1b15-01fd-4c98-8c92-29256d242cac", + "metadata": {}, + "source": [ + " \n" + ] + }, + { + "cell_type": "markdown", + "id": "8d322711-2b28-442e-8c19-108c3a083a50", + "metadata": {}, + "source": [ + "## 5 SP - Sin Entrenamiento" + ] + }, + { + "cell_type": "markdown", + "id": "0cf9f12a-1a9b-4732-8d2c-59c9ed52f8a2", + "metadata": {}, + "source": [ + "### Prueba 1" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "0abdc935-3926-461c-9e45-ab90374a5fdb", + "metadata": {}, + "outputs": [], + "source": [ + "prompt='''\n", + "TEMPLATE:\n", + " \"Necesito que me ayudes en una tarea de clasificación de texto.\n", + " {__PROMPT_DOMAIN__}\n", + " {__PROMPT_LABELS__}\n", + "\n", + " {__CHAIN_THOUGHT__}\n", + " {__ANSWER_FORMAT__}\"\n", + "\n", + "\n", + "PROMPT_DOMAIN:\n", + " \"Los textos que vas procesar del ambito de {__DOMAIN__}.\"\n", + "\n", + "\n", + "PROMPT_LABELS:\n", + " \"Quiero que me clasifiques los textos una de las siguientes categorías:\n", + " {__LABELS__}.\"\n", + "\n", + "\n", + "PROMPT_DETAIL:\n", + " \"\"\n", + "\n", + "\n", + "CHAIN_THOUGHT:\n", + " \"Por favor argumenta tu respuesta paso a paso, explica por qué crees que\n", + " está justificada tu elección final, y asegúrate de que acabas tu\n", + " explicación con el nombre de la clase que has escogido como la\n", + " correcta, en minúscula y sin puntuación.\"\n", + "\n", + "\n", + "ANSWER_FORMAT:\n", + " \"En tu respuesta incluye sólo el nombre de la clase, como una única\n", + " palabra, en minúscula, sin puntuación, y sin añadir ninguna otra\n", + " afirmación o palabra.\"\n", + "'''" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "9d88b784-746a-45d3-83b6-67c1f09a878a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import seaborn as sns\n", + "from sklearn.metrics import confusion_matrix\n", + "from promptmeteo import DocumentClassifier\n", + "\n", + "model = DocumentClassifier(\n", + " language = 'es',\n", + " model_name = 'text-davinci-003',\n", + " model_provider_name = 'openai',\n", + " model_provider_token = token,\n", + " prompt_domain = 'opiniones de productos',\n", + " prompt_labels = ['positiva','negativa','neutral'],\n", + " selector_k = 0,\n", + ")\n", + "\n", + "model.task.prompt.read_prompt(prompt)\n", + "\n", + "pred_targets = model.predict(test_reviews)\n", + "pred_targets = [pred if len(pred)==1 else [''] for pred in pred_targets]\n", + "\n", + "sns.heatmap(\n", + " confusion_matrix(test_targets, pred_targets),\n", + " annot=True,\n", + " cmap='Blues')" + ] + }, + { + "cell_type": "markdown", + "id": "e55bc005-7447-48f1-967a-6f1ae76f37bb", + "metadata": {}, + "source": [ + "### Prueba 2" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "id": "9ae93a75-bddc-410b-bc29-4019a928ddae", + "metadata": {}, + "outputs": [], + "source": [ + "prompt='''\n", + "TEMPLATE:\n", + " \"Necesito que me ayudes en una tarea de clasificación de texto.\n", + " {__PROMPT_DOMAIN__}\n", + " {__PROMPT_LABELS__}\n", + "\n", + " {__CHAIN_THOUGHT__}\n", + " {__ANSWER_FORMAT__}\"\n", + "\n", + "\n", + "PROMPT_DOMAIN:\n", + " \"Los textos que vas procesar del ambito de {__DOMAIN__}.\"\n", + "\n", + "\n", + "PROMPT_LABELS:\n", + " \"Quiero que me clasifiques los textos una de las siguientes categorías:\n", + " {__LABELS__}.\"\n", + "\n", + "\n", + "PROMPT_DETAIL:\n", + " \"\"\n", + "\n", + "\n", + "CHAIN_THOUGHT:\n", + " \"Argumenta tu respuesta paso a paso.\"\n", + "\n", + "\n", + "ANSWER_FORMAT:\n", + " \"En tu respuesta incluye sólo el nombre de la clase, como una única\n", + " respuesta\"\n", + "'''" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "20ee64ed-cfb9-4fd8-ae5f-9bdf1fddf5a3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAf8AAAGiCAYAAADp4c+XAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAA0zElEQVR4nO3de3wU9dn///cmJBsOSSAJkCCCyCGBQJAiQkBAkVPsF+XgCamCxXPAYoraoBhS/TUqqMiNgNUWqIpQD2CxCjdigVIDYjQCChQQBQQCCZBATDYh2d8fe5u4AwoLm5115vXsYx4P89nZmWuvfvTa6zOzuw632+0WAACwjRCzAwAAAIFF8QcAwGYo/gAA2AzFHwAAm6H4AwBgMxR/AABshuIPAIDNUPwBALAZij8AADZD8QcAwGYo/gAABIm5c+cqJSVFUVFRioqKUmpqqj744IOax8vLy5Wenq7Y2Fg1atRIo0aNUkFBgc/ncfDd/gAABIfly5crNDRU7du3l9vt1sKFCzV9+nR9/vnnSk5O1n333ad//vOfWrBggaKjozVhwgSFhIToP//5j0/nofgDABDEYmJiNH36dN1www1q2rSpFi1apBtuuEGStH37dnXs2FG5ubnq1avXOR+TZX8AAOqQy+VSSUmJ1+Zyuc76vKqqKi1evFilpaVKTU1VXl6eKisrNXDgwJp9kpKS1KpVK+Xm5voUUz2fX0UdKT9ldgQAgF+KiDquXvW7TfDbsR65Pk7Z2dleY1lZWZo2bdoZ99+yZYtSU1NVXl6uRo0aaenSperUqZPy8/MVHh6uxo0be+3fvHlzHTp0yKeYgqb4AwAQNBz+WxjPzMxURkaG15jT6fzJ/RMTE5Wfn6/i4mK99dZbGjt2rNauXeu3eCSKPwAAdcrpdP5ssTcKDw9Xu3btJEndu3fXpk2b9MILL+jmm29WRUWFjh8/7tX9FxQUKD4+3qeYuOYPAICRw+G/7QJVV1fL5XKpe/fuCgsL0+rVq2se27Fjh/bu3avU1FSfjknnDwCAkR+X/X2RmZmptLQ0tWrVSidOnNCiRYu0Zs0arVy5UtHR0Ro/frwyMjIUExOjqKgoTZw4UampqT7d6S9R/AEAOJ0fOvbzcfjwYd1+++06ePCgoqOjlZKSopUrV2rQoEGSpOeff14hISEaNWqUXC6XhgwZojlz5vh8nqD5nD93+wMAzlWd3+3fI+PsO52jsk3P+e1Y/kLnDwCAkUnL/oFC8QcAwMikZf9AsfZbGwAAcBo6fwAAjFj2BwDAZlj2BwAAVkLnDwCAEcv+AADYDMv+AADASuj8AQAwYtkfAACbsfiyP8UfAAAji3f+1n51AADgNHT+AAAYWbzzp/gDAGAUYu1r/tZ+awMAAE5D5w8AgBHL/gAA2IzFP+pn7bc252jxoteVNmiAenTrojG33KgtmzebHZIpyEMtcuFBHjzIgwd5sA7bF/8VH7yvGc/k6J7707X4zaVKTEzSffeMV1FRkdmhBRR5qEUuPMiDB3nwsF0eHCH+24JQcEYVQK8unK+RN9yk4SNGqW27dnosK1sRERFa9s7bZocWUOShFrnwIA8e5MHDdnlwOPy3BSFbF//Kigpt++pL9UrtXTMWEhKiXr16a/MXn5sYWWCRh1rkwoM8eJAHD/JgPT7f8FdYWKi//vWvys3N1aFDhyRJ8fHx6t27t8aNG6emTZue9Rgul0sul8trzB3qlNPp9DWcC3Ls+DFVVVUpNjbWazw2NlZ79nwd0FjMRB5qkQsP8uBBHjxsmYcgXa73F59e3aZNm9ShQwfNmjVL0dHR6tevn/r166fo6GjNmjVLSUlJ+vTTT896nJycHEVHR3tt05/OOe8XAQCAX1l82d+nzn/ixIm68cYbNW/ePDkML8jtduvee+/VxIkTlZub+7PHyczMVEZGhvfzQwPb9UtSk8ZNFBoaetoNK0VFRYqLiwt4PGYhD7XIhQd58CAPHrbMA51/rS+++EIPPvjgaYVfkhwOhx588EHl5+ef9ThOp1NRUVFeW6CX/CUpLDxcHTsla+OG2jcr1dXV2rgxVylduwU8HrOQh1rkwoM8eJAHD/JgPT51/vHx8frkk0+UlJR0xsc/+eQTNW/e3C+BBcptY+/Q1CmPKDm5szp3SdFrry5UWVmZho8YaXZoAUUeapELD/LgQR48bJeHIF2u9xefiv/kyZN19913Ky8vT9dcc01NoS8oKNDq1av18ssva8aMGXUSaF0Zmnatjh09qjmzZ6mw8IgSkzpqzkuvKNaqS1k/gTzUIhce5MGDPHjYLg8WX/Z3uN1uty9PWLJkiZ5//nnl5eWpqqpKkhQaGqru3bsrIyNDN91003kFUn7qvJ4GALChiDr+cvr6177gt2OVvf87vx3LX3wu/j+orKxUYWGhJCkuLk5hYWEXFAjFHwBwruq8+P96lt+OVfbPB/x2LH857/SFhYUpISHBn7EAABAcLL7sb+1XBwAATsNP+gIAYGTxzp/iDwCAkcU/6mfttzYAAOA0dP4AABix7A8AgM1YfNmf4g8AgJHFO39rvzoAAHAaOn8AAIxY9gcAwF7O9NP1VsKyPwAANkPnDwCAgdU7f4o/AABG1q79LPsDAGA3dP4AABiw7A8AgM1Yvfiz7A8AgM3Q+QMAYGD1zp/iDwCAAcUfAAC7sXbt55o/AADBIicnRz169FBkZKSaNWum4cOHa8eOHV77XHXVVXI4HF7bvffe69N5KP4AABgYi+uFbL5Yu3at0tPTtWHDBq1atUqVlZUaPHiwSktLvfa76667dPDgwZrtmWee8ek8LPsDAGDgz2v+LpdLLpfLa8zpdMrpdJ6274oVK7z+XrBggZo1a6a8vDz169evZrxBgwaKj48/75iCpvg36THB7BCCwrFNs80OIShUnKo2O4SgEF6PxTmJ+fAD5sMvU05OjrKzs73GsrKyNG3atLM+t7i4WJIUExPjNf7666/rtddeU3x8vIYNG6apU6eqQYMG5xxT0BR/AACChT87/8zMTGVkZHiNnanrN6qurtakSZPUp08fde7cuWb81ltvVevWrdWiRQtt3rxZjzzyiHbs2KF33nnnnGOi+AMAYODP4v9TS/xnk56erq1bt2r9+vVe43fffXfNP3fp0kUJCQm65pprtHv3brVt2/acjs0aEgAAQWbChAl677339K9//UstW7b82X179uwpSdq1a9c5H5/OHwAAI5M+5+92uzVx4kQtXbpUa9asUZs2bc76nPz8fElSQkLCOZ+H4g8AgIFZ3/CXnp6uRYsW6d1331VkZKQOHTokSYqOjlb9+vW1e/duLVq0SNdee61iY2O1efNmPfjgg+rXr59SUlLO+TwUfwAAgsTcuXMleb7I58fmz5+vcePGKTw8XB9++KFmzpyp0tJSXXzxxRo1apQee+wxn85D8QcAwMCszt/tdv/s4xdffLHWrl17weeh+AMAYMAP+wAAYDfWrv181A8AALuh8wcAwIBlfwAAbMbqxZ9lfwAAbIbOHwAAA6t3/hR/AAAMrF78WfYHAMBm6PwBADCyduNP8QcAwIhlfwAAYCl0/gAAGFi986f4AwBgQPEHAMBurF37ueYPAIDd0PkDAGDAsj8AADZj9eJvq2X/u268Up8syVTBv6er4N/TtWbh7zW4T6eax53h9fT8H27S/n89rSP/eVZvzLhTzWIiTYw4sBYvel1pgwaoR7cuGnPLjdqyebPZIQXcZ3mb9ODE+5Q2sJ96dO2oNR99aHZIprL7nGA+eLP7fLASWxX/7wqOa+r/vKveY55RnzHTteaT/+rN5+9Wx0vjJUnPTB6lX/frrDEP/0WD75yphKbRWvzsnSZHHRgrPnhfM57J0T33p2vxm0uVmJik++4Zr6KiIrNDC6iysjJ1SEzUw5lTzQ7FdMwJ5sOP2W0+OBwOv23ByFbF//11W7Vy/VfavfeIdu09rGkvLtfJ7126IqWNohpFaNzwVD3y3Dtau+m/+nzbPt2d9ZpSL2urK7pcYnbode7VhfM18oabNHzEKLVt106PZWUrIiJCy9552+zQAqrPlf1034RJuvqaQWaHYjrmBPPhx+w2Hyj+FhUS4tCNQ7qrYf1wbdy8R906tlJ4WD19tGFHzT7//aZAew8eVc+UNiZGWvcqKyq07asv1Su1d81YSEiIevXqrc1ffG5iZDALcwI/xnywHr8X/3379um3v/3tz+7jcrlUUlLitbmrq/wdyhklt2uhI/95VsUbZ2rWozfr5t+/rO1fH1J8bJRcFZUqPlnmtf/hohI1j40KSGxmOXb8mKqqqhQbG+s1Hhsbq8LCQpOigpmYE/gxW84Hhx+3IOT34n/06FEtXLjwZ/fJyclRdHS013aqIM/foZzRf78pUM9bctTv9hl6+c31evmPtynp/675AwAgWX/Z3+eP+v3jH//42ce//vrrsx4jMzNTGRkZXmPN+j7iayjnpfJUlb7e53mn+vm2feqe3Erpo6/SW//7mZzhYYpuVN+r+28WG6WCopKAxGaWJo2bKDQ09LQbd4qKihQXF2dSVDATcwI/xnywHp+L//Dhw+VwOOR2u39yn7O903E6nXI6nd7PCQn1NRS/CHE45Ayvp8+37VVF5Sld3TNRy1bnS5Lat26mVgkx2rh5jymxBUpYeLg6dkrWxg25GnDNQElSdXW1Nm7M1S2jf2NydDADcwI/Zsf5EKwdu7/4XPwTEhI0Z84cXX/99Wd8PD8/X927d7/gwOrCHydep5X/+VL7Dh5TZMMI3Zx2ufpd3l7D7p+jkpPlWrAsV0//fqSOFpfqRGm5nnvkRm344mt9suUbs0Ovc7eNvUNTpzyi5OTO6twlRa+9ulBlZWUaPmKk2aEF1Pffl2rf3r01fx/4br92bN+m6OhoxSe0MDGywGNOMB9+zG7zweK13/fi3717d+Xl5f1k8T/bqoCZmsY00l+euF3xcVEqPlmurTu/07D75+ijjdslSQ/PeFvV1W69MeNOOcPr6cOPt+l3OUtMjjowhqZdq2NHj2rO7FkqLDyixKSOmvPSK4q12ZLeti+/1L13jq35+/kZT0uSfn3dcE17IsessEzBnGA+/Jjd5oPVO3+H28dK/e9//1ulpaUaOnToGR8vLS3Vp59+qv79+/sUSP1uE3za36qObZptdghBoeJUtdkhBIXwerb9NK4X5oMH86FWRB1/OX37h1b47Vg7p5+5XprJ5/T17dv3Zx9v2LChz4UfAIBgYvHGnx/2AQDAyOrL/qwhAQBgM3T+AAAYWLzxp/gDAGAUEmLt6s+yPwAANkPnDwCAAcv+AADYDHf7AwAAS6HzBwDAwOKNP8UfAAAjqy/7U/wBADCwevHnmj8AADZD5w8AgIHFG3+KPwAARiz7AwAAS6HzBwDAwOKNP8UfAAAjlv0BAICl0PkDAGBg8caf4g8AgBHL/gAAICBycnLUo0cPRUZGqlmzZho+fLh27NjhtU95ebnS09MVGxurRo0aadSoUSooKPDpPBR/AAAMHA7/bb5Yu3at0tPTtWHDBq1atUqVlZUaPHiwSktLa/Z58MEHtXz5cr355ptau3atDhw4oJEjR/p0Hpb9AQAwMGvZf8WKFV5/L1iwQM2aNVNeXp769eun4uJi/eUvf9GiRYs0YMAASdL8+fPVsWNHbdiwQb169Tqn89D5AwBg4M/O3+VyqaSkxGtzuVznFEdxcbEkKSYmRpKUl5enyspKDRw4sGafpKQktWrVSrm5uef8+oKm8z+2abbZISCIhNfjfSlqMR/wS5aTk6Ps7GyvsaysLE2bNu1nn1ddXa1JkyapT58+6ty5syTp0KFDCg8PV+PGjb32bd68uQ4dOnTOMQVN8QcAIFj4c9k/MzNTGRkZXmNOp/Osz0tPT9fWrVu1fv16v8XyA4o/AAAG/rzk73Q6z6nY/9iECRP03nvvad26dWrZsmXNeHx8vCoqKnT8+HGv7r+goEDx8fHnfHzW0gAACBJut1sTJkzQ0qVL9dFHH6lNmzZej3fv3l1hYWFavXp1zdiOHTu0d+9epaamnvN56PwBADAw627/9PR0LVq0SO+++64iIyNrruNHR0erfv36io6O1vjx45WRkaGYmBhFRUVp4sSJSk1NPec7/SWKPwAApzHrC/7mzp0rSbrqqqu8xufPn69x48ZJkp5//nmFhIRo1KhRcrlcGjJkiObMmePTeRxut9vtj4AvVPkpsyMAAPxSRNRx63rljH/77VjrJ/f127H8hc4fAAADq3+3P8UfAAADqxd/7vYHAMBm6PwBADCweONP8QcAwMjqy/4UfwAADCxe+7nmDwCA3dD5AwBgwLI/AAA2Y/Haz7I/AAB2Q+cPAIBBiMVbf4o/AAAGFq/9LPsDAGA3dP4AABhwtz8AADYTYu3aT/EHAMDI6p0/1/wBALAZOn8AAAws3vjT+UvS4kWvK23QAPXo1kVjbrlRWzZvNjskU5CHWuTCgzx4kAcPO+XB4cf/BSPbF/8VH7yvGc/k6J7707X4zaVKTEzSffeMV1FRkdmhBRR5qEUuPMiDB3nwIA/WYvvi/+rC+Rp5w00aPmKU2rZrp8eyshUREaFl77xtdmgBRR5qkQsP8uBBHjzslocQh/+2YGTr4l9ZUaFtX32pXqm9a8ZCQkLUq1dvbf7icxMjCyzyUItceJAHD/LgYcc8OBwOv23ByNbF/9jxY6qqqlJsbKzXeGxsrAoLC02KKvDIQy1y4UEePMiDB3mwHp+Lf1lZmdavX6+vvvrqtMfKy8v1t7/97azHcLlcKikp8dpcLpevoQAAUCccDv9twcin4v/f//5XHTt2VL9+/dSlSxf1799fBw8erHm8uLhYd9xxx1mPk5OTo+joaK9t+tM5vkd/gZo0bqLQ0NDTblgpKipSXFxcwOMxC3moRS48yIMHefCwYx5CHA6/bcHIp+L/yCOPqHPnzjp8+LB27NihyMhI9enTR3v37vXppJmZmSouLvbaHnok06dj+ENYeLg6dkrWxg25NWPV1dXauDFXKV27BTwes5CHWuTCgzx4kAcP8mA9Pn3Jz8cff6wPP/xQcXFxiouL0/Lly3X//ferb9+++te//qWGDRue03GcTqecTqfXWPkpXyLxn9vG3qGpUx5RcnJnde6SotdeXaiysjINHzHSnIBMQh5qkQsP8uBBHjzslocgbdj9xqfiX1ZWpnr1ap/icDg0d+5cTZgwQf3799eiRYv8HmBdG5p2rY4dPao5s2epsPCIEpM6as5LryjWoktZP4U81CIXHuTBgzx42C0PwXqXvr843G63+1x3vuKKKzRx4kTddtttpz02YcIEvf766yopKVFVVZXPgZjV+QMAfnki6vjL6W9c8JnfjvXmuF/57Vj+4tM1/xEjRuiNN94442OzZ8/W6NGj5cN7CQAAYAKfOv+6ROcPADhXdd3537zQf19etGRs8N0Uya/6AQBgYO0r/jb/hj8AAOyIzh8AAAOr3+1P8QcAwCBYf43PX1j2BwDAZuj8AQAwYNkfAACbsXjtZ9kfAAC7ofMHAMCAZX8AAGzG6nf7U/wBADCweufPNX8AAGyGzh8AAANr9/0UfwAAThPCsj8AALASOn8AAAws3vhT/AEAMOJufwAAYCl0/gAAGFi88af4AwBgxN3+AAAgINatW6dhw4apRYsWcjgcWrZsmdfj48aNk8Ph8NqGDh3q83ko/gAAGDgc/tt8UVpaqq5du+rFF1/8yX2GDh2qgwcP1mxvvPGGz6+PZX8AAAz8ebe/y+WSy+XyGnM6nXI6naftm5aWprS0tJ89ntPpVHx8/AXFFDTF//fLt5kdQlB4dlhHs0MIClfNWGt2CEFhzeT+ZocQFApPVJgdQlCIiww3OwTb8OeyeE5OjrKzs73GsrKyNG3atPM63po1a9SsWTM1adJEAwYM0JNPPqnY2FifjhE0xR8AACvKzMxURkaG19iZuv5zMXToUI0cOVJt2rTR7t27NWXKFKWlpSk3N1ehoaHnfByKPwAABv5c9v+pJf7zccstt9T8c5cuXZSSkqK2bdtqzZo1uuaaa875ONzwBwCAQYjDf1tduvTSSxUXF6ddu3b59DyKPwAAv1D79+9XUVGREhISfHoey/4AABjUdcf+U06ePOnVxe/Zs0f5+fmKiYlRTEyMsrOzNWrUKMXHx2v37t16+OGH1a5dOw0ZMsSn81D8AQAwMOuHfT799FNdffXVNX//cKPg2LFjNXfuXG3evFkLFy7U8ePH1aJFCw0ePFhPPPGEz/cUUPwBAAgSV111ldxu908+vnLlSr+ch+IPAICBWcv+gULxBwDAwOK/68Pd/gAA2A2dPwAABlb/SV+KPwAABlZfFqf4AwBgYPHG3/JvbgAAgAGdPwAABlzzBwDAZixe+1n2BwDAbuj8AQAw4Bv+AACwGatf82fZHwAAm6HzBwDAwOKNP8UfAAAjq1/zZ9kfAACbofMHAMDAIWu3/hR/AAAMrL7sb7vi3y62vga2j9XFjSPUuH6YXtqwT5sPnqx5/LZfJahX68Zez/mq4KRe/HhfgCMNvMWLXtfC+X9RYeERdUhM0h+mTFWXlBSzw6ozt/e6WFclxql1TAO5TlVry3clenHN19p7tKxmn/BQhx4Y0FaDOjVTWGiINu45qukrd+ro95UmRh44dpsTRv94e4n+8c4SFRw8IElqfWlb3fbbe9Wzd1+TIzOHneaD1Yu/7a75h9cL0f5il/7+RcFP7vPloZPKfP+/NdtfN30XwAjNseKD9zXjmRzdc3+6Fr+5VImJSbrvnvEqKioyO7Q6061VY7392QHd+ernemDJZtULceiFm1MUEVb7r8Wka9rpynaxmrLsK933er7iGjn11MhkE6MOHDvOCaO4Zs11V/okzV2wRHMWLFa37j31+MMP6Juvd5kdWsAxH6zFdsX/q4JSvbftiL44eOIn9zlV7VaJq6pmK6usDmCE5nh14XyNvOEmDR8xSm3btdNjWdmKiIjQsnfeNju0OvPg37fon1sKtKfwe+06XKon/rlDCdERSoqPlCQ1dIZqWNd4vfDRbuV9e1w7Ck7qyX9uV0rLaCW3iDQ5+rpnxzlh1LvvVerZu59atmqti1tdovH3PaD6DRroq62bzQ4t4Ow2HxwOh9+2YGS74n8u2sc10FPXttfjAy/VLV3j1TA81OyQ6lRlRYW2ffWleqX2rhkLCQlRr169tfmLz02MLLAaOT3/P5eUeZb0k+IjFRYaok3fHKvZ59ujZTpYXK4uF0WZEmOgMCdOV1VVpY9WfaDysjJ16tLV7HACyo7zIcThvy0Y+XzNf9u2bdqwYYNSU1OVlJSk7du364UXXpDL5dJvfvMbDRgw4KzHcLlccrlcXmNVlRUKDQv3NRy/+6qgVPkHTqjo+0rFNQzTdZ2a6f7UizVj7Tdymx1cHTl2/JiqqqoUGxvrNR4bG6s9e742KarAckiaNLCdvthXrK8Lv5ckxTYMV8Wpap10VXnte7S0QrENzZ+rdYk5UevrXf/VxLt+o4qKCtWv30DZT8/UJW3amh1WQDEfrMenzn/FihW67LLLNHnyZHXr1k0rVqxQv379tGvXLn377bcaPHiwPvroo7MeJycnR9HR0V5b3tt/Pu8X4U9535Voy6GTOlDi0uaDJzU3d58uiamvDk0bmB0a6tBDg9urbdOGeuwfX5kdCoLMxa3b6M9/e0sv/uV1XTfyJj39x8f0zZ7dZoeFOuZw+G8LRj4V/z/+8Y966KGHVFRUpPnz5+vWW2/VXXfdpVWrVmn16tV66KGH9NRTT531OJmZmSouLvbauo+6+7xfRF0q+r5SJ1yn1NTCnV6Txk0UGhp62o07RUVFiouLMymqwPn9oHbq0y5G9y/6QkdOVNSMF5VWKLxeSM3lgB/ENAxXUWmF8TCWYvc58WNhYWG66OJW6pCUrDvvn6S27TronSWvmR1WQNlxPoQ4HH7bgpFPxf/LL7/UuHHjJEk33XSTTpw4oRtuuKHm8TFjxmjz5rPfCON0OhUVFeW1BcOS/5k0jqinhuGhKi4/ZXYodSYsPFwdOyVr44bcmrHq6mpt3JirlK7dTIys7v1+UDv17xCnCW9s1sHicq/Hth86ocqqavW4pEnNWKuY+kqIjtCW70oCHWpA2XlOnE21263KCmu/+TNiPliPz9f8f7hzMSQkRBEREYqOjq55LDIyUsXFxf6Lrg44Qx1q2qj2jUZsg3C1jHaqtKJK31dU6dqOTfX5dyUqcVWpacMwDU9upiOlFdp2uNTEqOvebWPv0NQpjyg5ubM6d0nRa68uVFlZmYaPGGl2aHXmocHtNLhTcz389laVVpxSTMMwSVKpq0quU9UqdVVp+ReH9MCAtiouO6VS1yn9flA7bd5frC8P/PSnRazCjnPC6JU5M3VF6pVq1jxB339fqo/+93198dkmPTVzntmhBZzd5kOw3qjnLz4V/0suuUQ7d+5U27aem11yc3PVqlWrmsf37t2rhIQE/0boZ62a1Nekvq1r/r4hpbkkacO3x7U4/5BaRDnVs9XFqh8WquKySm077Plo4Klqq97u5zE07VodO3pUc2bPUmHhESUmddScl15RrEWX9CRp1K8ukiTNHXOZ1/gT/9yuf27xfA/EzNW7VO1uq5wRnRT+f1/y88z/7gx0qKaw45wwOnbsqJ7KflRHi46oYaNIXdq2vZ6aOU+X9+x99idbjN3mQ5Cu1vuNw+12n3NVmzdvni6++GL9+te/PuPjU6ZM0eHDh/XKK6/4HEj60m0+P8eKnh3W0ewQgsJVM9aaHUJQWDO5v9khBIXCE/ZaZv8pcZHBeXnUDBF1/P20//OfPX471sQ+bfx2LH/xKX333nvvzz7+pz/96YKCAQAgGITwwz4AANiL1Zf9Kf4AABhY/YY/vt4XAACbofMHAMAgWL+cx18o/gAAGFi89rPsDwCA3dD5AwBgwLI/AAA2Y/Haz7I/AAB2Q+cPAICB1Ttjij8AAAYOi6/7W/3NDQAAMKDzBwDAwNp9P8UfAIDT8FE/AABsxtqln2v+AADYDp0/AAAGFl/1p/gDAGDER/0AAICl0PkDAGBg9c7Y6q8PAACfORwOv22+WLdunYYNG6YWLVrI4XBo2bJlXo+73W49/vjjSkhIUP369TVw4EDt3LnT59dH8QcAIEiUlpaqa9euevHFF8/4+DPPPKNZs2Zp3rx52rhxoxo2bKghQ4aovLzcp/Ow7A8AgIFZt/ulpaUpLS3tjI+53W7NnDlTjz32mK6//npJ0t/+9jc1b95cy5Yt0y233HLO56HzBwDAwJ/L/i6XSyUlJV6by+XyOaY9e/bo0KFDGjhwYM1YdHS0evbsqdzcXJ+OFTSd/7PDOpodAoLImsn9zQ4BQSQuMtzsEIDzlpOTo+zsbK+xrKwsTZs2zafjHDp0SJLUvHlzr/HmzZvXPHaugqb4AwAQLPy5LJ6ZmamMjAyvMafT6ccz+I7iDwCAgT+/5MfpdPql2MfHx0uSCgoKlJCQUDNeUFCgyy67zKdjcc0fAAADhx83f2nTpo3i4+O1evXqmrGSkhJt3LhRqampPh2Lzh8AgCBx8uRJ7dq1q+bvPXv2KD8/XzExMWrVqpUmTZqkJ598Uu3bt1ebNm00depUtWjRQsOHD/fpPBR/AAAMzPpq/08//VRXX311zd8/3CswduxYLViwQA8//LBKS0t199136/jx47ryyiu1YsUKRURE+HQeh9vtdvs18vNUfsrsCAAAvxQRddy6Lt9S4LdjDevS/Ow7BRjX/AEAsBmW/QEAMLD4L/pS/AEAMHKY9gW/gcGyPwAANkPnDwCAAcv+AADYTAjL/gAAwEro/AEAMGDZHwAAm6H4AwBgM3zUDwAAWAqdPwAABiHWbvwp/gAAGLHsDwAALIXOHwAAA+72BwDAZlj2BwAAlkLnDwCAAXf7AwBgMyz728DiRa8rbdAA9ejWRWNuuVFbNm82OyRTkIda5MKDPHiQBw/yYB22L/4rPnhfM57J0T33p2vxm0uVmJik++4Zr6KiIrNDCyjyUItceJAHD/LgYbc8OBz+24KRX4q/2+32x2FM8erC+Rp5w00aPmKU2rZrp8eyshUREaFl77xtdmgBRR5qkQsP8uBBHjzslgeHH7dg5Jfi73Q6tW3bNn8cKqAqKyq07asv1Su1d81YSEiIevXqrc1ffG5iZIFFHmqRCw/y4EEePOyYhxCHw29bMPLphr+MjIwzjldVVempp55SbGysJOm555772eO4XC65XC6vMXeoU06n05dwLtix48dUVVVVE/cPYmNjtWfP1wGNxUzkoRa58CAPHuTBgzxYj0/Ff+bMmeratasaN27sNe52u7Vt2zY1bNhQjnN4l5OTk6Ps7GyvsUenZumxx6f5Eg4AAHUiOPt1//Gp+P/pT3/Sn//8Zz377LMaMGBAzXhYWJgWLFigTp06ndNxMjMzT1tFcIcGtuuXpCaNmyg0NPS0G1aKiooUFxcX8HjMQh5qkQsP8uBBHjxsmQeLV3+frvn/4Q9/0JIlS3Tfffdp8uTJqqysPK+TOp1ORUVFeW2BXvKXpLDwcHXslKyNG3Jrxqqrq7VxY65SunYLeDxmIQ+1yIUHefAgDx7kwXp8/pKfHj16KC8vT+np6br88sv1+uuvn9NSf7C6bewdmjrlESUnd1bnLil67dWFKisr0/ARI80OLaDIQy1y4UEePMiDh93yYPUv+Tmvb/hr1KiRFi5cqMWLF2vgwIGqqqryd1wBMzTtWh07elRzZs9SYeERJSZ11JyXXlGsVZeyfgJ5qEUuPMiDB3nwsFsefsE97TlxuC/wQ/r79+9XXl6eBg4cqIYNG573ccpPXUgUAAA7iajjL6f/5Otivx3rikuj/XYsf7ng9LVs2VItW7b0RywAAAQFizf+/LAPAACnsXj1t/13+wMAYDd0/gAAGHC3PwAANmP1u/0p/gAAGFi89nPNHwAAu6HzBwDAyOKtP8UfAAADq9/wx7I/AAA2Q+cPAIABd/sDAGAzFq/9LPsDAGA3dP4AABhZvPWn+AMAYMDd/gAAwFLo/AEAMOBufwAAbMbitZ/iDwDAaSxe/bnmDwCAzdD5AwBgwN3+AADYjMPhv80X06ZNk8Ph8NqSkpL8/vro/AEACCLJycn68MMPa/6uV8//pZriDwCAgZmL/vXq1VN8fHydnoNlfwAAjBz+21wul0pKSrw2l8v1k6feuXOnWrRooUsvvVRjxozR3r17/f/y3G632+9HPQ/lp8yOAMHkRBkTQpIi67M4J0lNhvzJ7BCCwrGVU8wOIWhE1PG/GtsOlvrtWEtemq7s7GyvsaysLE2bNu20fT/44AOdPHlSiYmJOnjwoLKzs/Xdd99p69atioyM9FtMFH8EJYq/B8Xfg+LvQfGvVdfFf/vB7/12rDYxoad1+k6nU06n86zPPX78uFq3bq3nnntO48eP91tM/JcFAAADf36977kW+jNp3LixOnTooF27dvkvIHHNHwCAoHXy5Ent3r1bCQkJfj0uxR8AAAM/3u/nk8mTJ2vt2rX65ptv9PHHH2vEiBEKDQ3V6NGj/fCqarHsDwCAkUmf9du/f79Gjx6toqIiNW3aVFdeeaU2bNigpk2b+vU8FH8AAAzM+nrfxYsXB+Q8LPsDAGAzdP4AABj4827/YETxBwDAwOK1n2V/AADshs4fAAAji7f+FH8AAAzMuts/UFj2BwDAZuj8AQAw4G5/AABsxuK1n2V/AADshs4fAAAji7f+FH8AAAysfrc/xR8AAAOr3/DHNX8AAGyGzh8AAAOLN/4UfwAAjFj2BwAAlkLnDwDAaazd+tP5S1q86HWlDRqgHt26aMwtN2rL5s1mh2QK8iC9Ov9l3Xn7TRrUr4f+36C+yvz9RO39Zo/ZYZnGbnNi8uhUrX9xnA4v/72+fet3+vsfR6l9yxivfZo3aai//GGY9rz5gArfm6yP5/1Ww/smmhRxYNlpPjgc/tuCke2L/4oP3teMZ3J0z/3pWvzmUiUmJum+e8arqKjI7NACijx4fP7ZJo28cbRemv+Gnn/xZZ06dUoPTrhLZWXfmx1awNlxTvRNaaV5/8hT/wkL9f8efkP1QkP13jOj1SAirGafV/4wTB0ujtWNj72py+96Re/+e4demzpCXds1NzHyumfH+WBlDrfb7TY7CEkqP2XOecfccqOSO3fRlMcelyRVV1dr8DX9NfrW2zT+rrvNCcoEwZaHE2UmTQiDY8eOatigvpr954W67FeXB/z8kfXNuzIXTHOiyZA/BfR8P4iLbqB970zSwEmv6j9b9kmSjrw3WQ/MXKE3Ptxas9/+pZP02Mv/0oL3v6jTeI6tnFKnx/85wTQfJCmijv/VOHC8wm/HatE43G/H8hdbd/6VFRXa9tWX6pXau2YsJCREvXr11uYvPjcxssAiDz+t9OQJSVJUVLTJkQQWc8IjqqFTknTsRHnN2IYv9+uGqzuqSWSEHA7pxqs7KSKsntbl7zUrzDpnx/lg9WV/U9oKl8sll8vlNeYOdcrpdAY0jmPHj6mqqkqxsbFe47Gxsdqz5+uAxmIm8nBm1dXVmvXs0+rStZsubdfe7HACijnh+Y/29PSB+njLPn31zZGa8d/8calenTpCB5ZlqPJUlb4vr9TNWW/r6wPHTIy2bjEfrOeCOv/S0lLNnz9fjz76qGbPnn3O135ycnIUHR3ttU1/OudCQgH87rmnn9TXu3cq+08zzA4FJpj5wFAlX9JUtz+5zGs8647+atzIqbTJi9Tnvvma9dYneu3xEUpu09ScQFEnHH78XzDyqfPv1KmT1q9fr5iYGO3bt0/9+vXTsWPH1KFDB+3evVtPPPGENmzYoDZt2vzscTIzM5WRkeE15g4NbNcvSU0aN1FoaOhpb1qKiooUFxcX8HjMQh5O99zTT+rj9Ws1+88L1ax5vNnhBJzd58TzEwfr2l7tNPDBV/Vd4Yma8TYJjXXfiMv1q9/+Wdu+LZQkbfn6sPp0uVj3XN9dD8xcYVbIdcqW8yE4a7bf+NT5b9++XadOeW7EyszMVIsWLfTtt9/qk08+0bfffquUlBQ9+uijZz2O0+lUVFSU1xboJX9JCgsPV8dOydq4IbdmrLq6Whs35iqla7eAx2MW8lDL7Xbruaef1Lo1q/XC3L+qxUUtzQ7JFHaeE89PHKzrrkzU0Mmv69tDxV6P/XDXf7XhPumqardCgvXirh/YcT44/LgFo/O+5p+bm6t58+YpOtpzI1SjRo2UnZ2tW265xW/BBcJtY+/Q1CmPKDm5szp3SdFrry5UWVmZho8YaXZoAUUePJ59+gl9uOJ95Tz7P2rQoIGKCj3Xehs1ipQzIsLk6ALLjnNi5gNDdPM1ybpx6ls6+X2FmjdpKEkqLnWpvOKUduwt0q79RzX7wTRlzlutopIyXXdlB13TvY1GPvp3k6OvW3acD1bmc/F3/N+72/LyciUkJHg9dtFFF+nIkSNnelrQGpp2rY4dPao5s2epsPCIEpM6as5LryjWqktZP4E8eCx7a4kkaeI947zGp2Q9qWuHjTAhIvPYcU7cc313SdKq53/jNX7XM8v12sotOlVVreFTlujJO6/WW//fTWoUEabdB47pzqeXa+Unu80IOWDsNh8svJAjycfP+YeEhKhz586qV6+edu7cqQULFmjUqFE1j69bt0633nqr9u/f73MgZn3OH8EpWD7nbzYzP+cfTMz6nH+wMfNz/sGmrj/nf+SE//4b1DQy+P499imirKwsr78bNWrk9ffy5cvVt2/fC48KAADUGdt/wx+CE52/B52/B52/B51/rTrv/E/6sfNvFHz/HgdfRAAAmMzil/zt/fW+AADYEZ0/AAAGVr/bn+IPAIBBsH4tr7+w7A8AgM3Q+QMAYGD1ZX86fwAAbIbOHwAAAzp/AABgKXT+AAAYWP1uf4o/AAAGLPsDAABLofMHAMDA4o0/xR8AgNNYvPqz7A8AgM3Q+QMAYMDd/gAA2Ax3+wMAAEuh8wcAwMDijT/FHwCA01i8+rPsDwCAgcOP//PViy++qEsuuUQRERHq2bOnPvnkE7+/Poo/AABBYsmSJcrIyFBWVpY+++wzde3aVUOGDNHhw4f9eh6KPwAABg6H/zaXy6WSkhKvzeVynfG8zz33nO666y7dcccd6tSpk+bNm6cGDRror3/9q39foBtut9vtLi8vd2dlZbnLy8vNDsVU5MGDPHiQBw/y4EEezk9WVpZbkteWlZV12n4ul8sdGhrqXrp0qdf47bff7r7uuuv8GpPD7Xa7/ft24peppKRE0dHRKi4uVlRUlNnhmIY8eJAHD/LgQR48yMP5cblcp3X6TqdTTqfTa+zAgQO66KKL9PHHHys1NbVm/OGHH9batWu1ceNGv8XE3f4AANShMxV6s3HNHwCAIBAXF6fQ0FAVFBR4jRcUFCg+Pt6v56L4AwAQBMLDw9W9e3etXr26Zqy6ulqrV6/2ugzgDyz7/x+n06msrKygW5oJNPLgQR48yIMHefAgD3UvIyNDY8eO1eWXX64rrrhCM2fOVGlpqe644w6/nocb/gAACCKzZ8/W9OnTdejQIV122WWaNWuWevbs6ddzUPwBALAZrvkDAGAzFH8AAGyG4g8AgM1Q/AEAsBmKvwLz84nBbt26dRo2bJhatGghh8OhZcuWmR2SKXJyctSjRw9FRkaqWbNmGj58uHbs2GF2WAE3d+5cpaSkKCoqSlFRUUpNTdUHH3xgdlime+qpp+RwODRp0iSzQwmoadOmyeFweG1JSUlmh4ULYPviH6ifTwx2paWl6tq1q1588UWzQzHV2rVrlZ6erg0bNmjVqlWqrKzU4MGDVVpaanZoAdWyZUs99dRTysvL06effqoBAwbo+uuv15dffml2aKbZtGmTXnrpJaWkpJgdiimSk5N18ODBmm39+vVmh4QL4defCfoFuuKKK9zp6ek1f1dVVblbtGjhzsnJMTEqc0k67Vel7Orw4cNuSe61a9eaHYrpmjRp4n7llVfMDsMUJ06ccLdv3969atUqd//+/d2/+93vzA4poLKystxdu3Y1Owz4ka07/4qKCuXl5WngwIE1YyEhIRo4cKByc3NNjAzBori4WJIUExNjciTmqaqq0uLFi1VaWur3rxj9pUhPT9evf/1rr/9W2M3OnTvVokULXXrppRozZoz27t1rdki4ALb+et/CwkJVVVWpefPmXuPNmzfX9u3bTYoKwaK6ulqTJk1Snz591LlzZ7PDCbgtW7YoNTVV5eXlatSokZYuXapOnTqZHVbALV68WJ999pk2bdpkdiim6dmzpxYsWKDExEQdPHhQ2dnZ6tu3r7Zu3arIyEizw8N5sHXxB35Oenq6tm7dattrm4mJicrPz1dxcbHeeustjR07VmvXrrXVG4B9+/bpd7/7nVatWqWIiAizwzFNWlpazT+npKSoZ8+eat26tf7+979r/PjxJkaG82Xr4h/In0/EL8uECRP03nvvad26dWrZsqXZ4ZgiPDxc7dq1kyR1795dmzZt0gsvvKCXXnrJ5MgCJy8vT4cPH9avfvWrmrGqqiqtW7dOs2fPlsvlUmhoqIkRmqNx48bq0KGDdu3aZXYoOE+2vuYfyJ9PxC+D2+3WhAkTtHTpUn300Udq06aN2SEFjerqarlcLrPDCKhrrrlGW7ZsUX5+fs12+eWXa8yYMcrPz7dl4ZekkydPavfu3UpISDA7FJwnW3f+UuB+PjHYnTx50utd/J49e5Sfn6+YmBi1atXKxMgCKz09XYsWLdK7776ryMhIHTp0SJIUHR2t+vXrmxxd4GRmZiotLU2tWrXSiRMntGjRIq1Zs0YrV640O7SAioyMPO1+j4YNGyo2NtZW94FMnjxZw4YNU+vWrXXgwAFlZWUpNDRUo0ePNjs0nCfbF/+bb75ZR44c0eOPP17z84krVqw47SZAq/v000919dVX1/ydkZEhSRo7dqwWLFhgUlSBN3fuXEnSVVdd5TU+f/58jRs3LvABmeTw4cO6/fbbdfDgQUVHRyslJUUrV67UoEGDzA4NJti/f79Gjx6toqIiNW3aVFdeeaU2bNigpk2bmh0azhM/6QsAgM3Y+po/AAB2RPEHAMBmKP4AANgMxR8AAJuh+AMAYDMUfwAAbIbiDwCAzVD8AQCwGYo/AAA2Q/EHAMBmKP4AANjM/w/mwyR9qI1H5gAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import seaborn as sns\n", + "from sklearn.metrics import confusion_matrix\n", + "from promptmeteo import DocumentClassifier\n", + "\n", + "model = DocumentClassifier(\n", + " language = 'es',\n", + " model_name = 'text-davinci-003',\n", + " model_provider_name = 'openai',\n", + " model_provider_token = token,\n", + " prompt_domain = 'opiniones de productos',\n", + " prompt_labels = ['positiva','negativa','neutra'],\n", + " selector_k = 0,\n", + ")\n", + "\n", + "model.task.prompt.read_prompt(prompt)\n", + "\n", + "pred_targets = model.predict(test_reviews)\n", + "\n", + "sns.heatmap(\n", + " confusion_matrix(test_targets, pred_targets),\n", + " annot=True,\n", + " cmap='Blues')" + ] + }, + { + "cell_type": "markdown", + "id": "cf2744f0-ea90-4873-92bc-8d44c52621e1", + "metadata": {}, + "source": [ + "### Prueba 3" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "db7ab35e-0714-4308-b24d-69f08ca13900", + "metadata": {}, + "outputs": [], + "source": [ + "prompt='''\n", + "TEMPLATE:\n", + " \"Necesito que me ayudes en una tarea de clasificación de texto.\n", + " {__PROMPT_DOMAIN__}\n", + " {__PROMPT_LABELS__}\n", + "\n", + " {__CHAIN_THOUGHT__}\n", + " {__ANSWER_FORMAT__}\"\n", + "\n", + "\n", + "PROMPT_DOMAIN:\n", + " \"\"\n", + "\n", + "\n", + "PROMPT_LABELS:\n", + " \"Quiero que me clasifiques los textos una de las siguientes categorías:\n", + " {__LABELS__}.\"\n", + "\n", + "\n", + "PROMPT_DETAIL:\n", + " \"\"\n", + "\n", + "\n", + "CHAIN_THOUGHT:\n", + " \"\"\n", + "\n", + "\n", + "ANSWER_FORMAT:\n", + " \"\"\n", + "'''" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "32f5bd08-c05a-4f33-8564-35e0eba3dfb5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import seaborn as sns\n", + "from sklearn.metrics import confusion_matrix\n", + "from promptmeteo import DocumentClassifier\n", + "\n", + "model = DocumentClassifier(\n", + " language = 'es',\n", + " model_name = 'text-davinci-003',\n", + " model_provider_name = 'openai',\n", + " model_provider_token = token,\n", + " prompt_domain = 'opiniones de productos',\n", + " prompt_labels = ['positiva','negativa','neutra'],\n", + " selector_k = 0,\n", + ")\n", + "\n", + "model.task.prompt.read_prompt(prompt)\n", + "\n", + "pred_targets = model.predict(test_reviews)\n", + "pred_targets = [pred if len(pred)==1 else [''] for pred in pred_targets]\n", + "\n", + "sns.heatmap(\n", + " confusion_matrix(test_targets, pred_targets),\n", + " annot=True,\n", + " cmap='Blues')" + ] + }, + { + "cell_type": "markdown", + "id": "504d176d-7402-44ab-8a64-acfcfc6c6459", + "metadata": {}, + "source": [ + "## ES - Con entrenamiento" + ] + }, + { + "cell_type": "markdown", + "id": "f62c3cd5-0724-46ac-99af-9e10de663976", + "metadata": {}, + "source": [ + "### Prueba 1" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "b4f26ab8-ab4f-4631-bcf9-ea48fa670171", + "metadata": {}, + "outputs": [], + "source": [ + "prompt='''\n", + "TEMPLATE:\n", + " \"Necesito que me ayudes en una tarea de clasificación de texto.\n", + " {__PROMPT_DOMAIN__}\n", + " {__PROMPT_LABELS__}\n", + "\n", + " {__CHAIN_THOUGHT__}\n", + " {__ANSWER_FORMAT__}\"\n", + "\n", + "\n", + "PROMPT_DOMAIN:\n", + " \"Los textos que vas procesar del ambito de {__DOMAIN__}.\"\n", + "\n", + "\n", + "PROMPT_LABELS:\n", + " \"Quiero que me clasifiques los textos una de las siguientes categorías:\n", + " {__LABELS__}.\"\n", + "\n", + "\n", + "PROMPT_DETAIL:\n", + " \"\"\n", + "\n", + "\n", + "CHAIN_THOUGHT:\n", + " \"Por favor argumenta tu respuesta paso a paso, explica por qué crees que\n", + " está justificada tu elección final, y asegúrate de que acabas tu\n", + " explicación con el nombre de la clase que has escogido como la\n", + " correcta, en minúscula y sin puntuación.\"\n", + "\n", + "\n", + "ANSWER_FORMAT:\n", + " \"En tu respuesta incluye sólo el nombre de la clase, como una única\n", + " palabra, en minúscula, sin puntuación, y sin añadir ninguna otra\n", + " afirmación o palabra.\"\n", + "'''" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "1495f569-7656-4567-be30-75b7aedb401e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import seaborn as sns\n", + "from sklearn.metrics import confusion_matrix\n", + "from promptmeteo import DocumentClassifier\n", + "\n", + "model = DocumentClassifier(\n", + " language = 'es',\n", + " model_name = 'text-davinci-003',\n", + " model_provider_name = 'openai',\n", + " model_provider_token = token,\n", + " prompt_domain = 'opiniones de productos',\n", + " prompt_labels = ['positiva','negativa','neutra'],\n", + " selector_k = 10,\n", + ")\n", + "\n", + "model.task.prompt.read_prompt(prompt)\n", + "\n", + "model.train(\n", + " examples = train_reviews,\n", + " annotations = train_targets,\n", + ")\n", + "\n", + "pred_targets = model.predict(test_reviews)\n", + "pred_targets = [pred if len(pred)==1 else [''] for pred in pred_targets]\n", + "\n", + "sns.heatmap(\n", + " confusion_matrix(test_targets, pred_targets),\n", + " annot=True,\n", + " cmap='Blues')" + ] + }, + { + "cell_type": "markdown", + "id": "8006de83-a826-478c-bee7-6bf38d0fa23a", + "metadata": {}, + "source": [ + "### Prueba 2" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "e2ed16b3-fe75-48e0-9ee5-801aefa95143", + "metadata": {}, + "outputs": [], + "source": [ + "prompt='''\n", + "TEMPLATE:\n", + " \"Necesito que me ayudes en una tarea de clasificación de texto.\n", + " {__PROMPT_DOMAIN__}\n", + " {__PROMPT_LABELS__}\n", + "\n", + " {__CHAIN_THOUGHT__}\n", + " {__ANSWER_FORMAT__}\"\n", + "\n", + "\n", + "PROMPT_DOMAIN:\n", + " \"Los textos que vas procesar del ambito de {__DOMAIN__}.\"\n", + "\n", + "\n", + "PROMPT_LABELS:\n", + " \"Quiero que me clasifiques los textos una de las siguientes categorías:\n", + " {__LABELS__}.\"\n", + "\n", + "\n", + "PROMPT_DETAIL:\n", + " \"\"\n", + "\n", + "\n", + "CHAIN_THOUGHT:\n", + " \"Argumenta tu respuesta paso a paso.\"\n", + "\n", + "\n", + "ANSWER_FORMAT:\n", + " \"En tu respuesta incluye sólo el nombre de la clase, como una única\n", + " respuesta\"\n", + "'''" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "80360efc-af76-4d15-b935-586a79e33abc", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import seaborn as sns\n", + "from sklearn.metrics import confusion_matrix\n", + "from promptmeteo import DocumentClassifier\n", + "\n", + "model = DocumentClassifier(\n", + " language = 'es',\n", + " model_name = 'text-davinci-003',\n", + " model_provider_name = 'openai',\n", + " model_provider_token = token,\n", + " prompt_domain = 'opiniones de productos',\n", + " prompt_labels = ['positiva','negativa','neutra'],\n", + " selector_k = 10,\n", + ")\n", + "\n", + "model.task.prompt.read_prompt(prompt)\n", + "\n", + "model.train(\n", + " examples = train_reviews,\n", + " annotations = train_targets,\n", + ")\n", + "\n", + "pred_targets = model.predict(test_reviews)\n", + "pred_targets = [pred if len(pred)==1 else [''] for pred in pred_targets]\n", + "\n", + "sns.heatmap(\n", + " confusion_matrix(test_targets, pred_targets),\n", + " annot=True,\n", + " cmap='Blues')" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "f50d8cd3-af0f-416a-8f9d-a6d57cd86ac6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['positiva'],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " ['neutra'],\n", + " [''],\n", + " ['neutra'],\n", + " ['neutra'],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " ['neutra']]" + ] + }, + "execution_count": 48, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pred_targets" + ] + }, + { + "cell_type": "markdown", + "id": "25261a04-f35a-4eef-8d57-1d5019bcd424", + "metadata": {}, + "source": [ + "### Prueba 3" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "74a71c53-6983-49d6-aac6-f2d0a2e88e2f", + "metadata": {}, + "outputs": [], + "source": [ + "prompt='''\n", + "TEMPLATE:\n", + " \"Necesito que me ayudes en una tarea de clasificación de texto.\n", + " {__PROMPT_DOMAIN__}\n", + " {__PROMPT_LABELS__}\n", + "\n", + " {__CHAIN_THOUGHT__}\n", + " {__ANSWER_FORMAT__}\"\n", + "\n", + "\n", + "PROMPT_DOMAIN:\n", + " \"\"\n", + "\n", + "\n", + "PROMPT_LABELS:\n", + " \"\"\n", + "\n", + "\n", + "PROMPT_DETAIL:\n", + " \"\"\n", + "\n", + "\n", + "CHAIN_THOUGHT:\n", + " \"\"\n", + "\n", + "\n", + "ANSWER_FORMAT:\n", + " \"\"\n", + "'''" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "id": "ea907475-c58a-4b77-904e-0a4f30d78ed4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import seaborn as sns\n", + "from sklearn.metrics import confusion_matrix\n", + "from promptmeteo import DocumentClassifier\n", + "\n", + "model = DocumentClassifier(\n", + " language = 'es',\n", + " model_name = 'text-davinci-003',\n", + " model_provider_name = 'openai',\n", + " model_provider_token = token,\n", + " prompt_domain = 'opiniones de productos',\n", + " prompt_labels = ['positiva','negativa','neutra'],\n", + " selector_k = 20,\n", + ")\n", + "\n", + "model.task.prompt.read_prompt(prompt)\n", + "\n", + "model.train(\n", + " examples = train_reviews,\n", + " annotations = train_targets,\n", + ")\n", + "\n", + "pred_targets = model.predict(test_reviews)\n", + "pred_targets = [pred if len(pred)==1 else [''] for pred in pred_targets]\n", + "\n", + "sns.heatmap(\n", + " confusion_matrix(test_targets, pred_targets),\n", + " annot=True,\n", + " cmap='Blues')" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "id": "100497a5-bffa-47c8-905a-b9569cce41bb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " ['neutra'],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " ['neutra'],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " ['neutra'],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " [''],\n", + " ['neutra'],\n", + " [''],\n", + " ['neutra']]" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pred_targets" + ] + }, + { + "cell_type": "markdown", + "id": "572a6af8-112e-43d3-be26-79b100facd50", + "metadata": {}, + "source": [ + "## Conclusiones" + ] + }, + { + "cell_type": "markdown", + "id": "f2070ce4-4ede-44be-9764-d3186d3e62dd", + "metadata": {}, + "source": [ + "* Parece que con el modelo Flan-t5-small, el mejor resultado se obtiene añadiendo más ejemplot y quitando la instrucción del prompt\n", + "\n", + "* Parece que hay mucho errores asociados con que la respuesta tenga un espacio antes de laa respuesta" + ] + } + ], + "metadata": { + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/promptmeteo/api_formatter.py b/promptmeteo/api_formatter.py index b6d7c15..93fb633 100644 --- a/promptmeteo/api_formatter.py +++ b/promptmeteo/api_formatter.py @@ -1,5 +1,4 @@ #!/usr/bin/python3 - # Copyright (c) 2023 Paradigma Digital S.L. # Permission is hereby granted, free of charge, to any person obtaining a copy @@ -37,7 +36,7 @@ from typing_extensions import Self from .base import BaseUnsupervised -from .tasks import TaskTypes +from .tasks import TaskTypes, TaskBuilder from .tools import add_docstring_from from .validations import version_validation @@ -265,7 +264,10 @@ def predict(self, api_codes: List[str], external_info: dict) -> List[str]: ---------- api_codes : List[str] +<<<<<<< HEAD external_info: dict +======= +>>>>>>> 8ceaf0d ([Feature: New model] API Generation (#6)) Returns diff --git a/promptmeteo/prompts/text-davinci-003_en_classification.prompt b/promptmeteo/prompts/text-davinci-003_en_classification.prompt deleted file mode 100644 index 582da33..0000000 --- a/promptmeteo/prompts/text-davinci-003_en_classification.prompt +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2023 Paradigma Digital S.L. - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - - -TEMPLATE: - "I need you to help me with a text classification task. - {__PROMPT_DOMAIN__} - {__PROMPT_LABELS__} - - {__CHAIN_THOUGHT__} - {__ANSWER_FORMAT__}" - - -PROMPT_DOMAIN: - "The texts you will be processing are from the {__DOMAIN__} domain." - - -PROMPT_LABELS: - "I want you to classify the texts into one of the following categories: - {__LABELS__}." - - -PROMPT_DETAIL: - "" - - -CHAIN_THOUGHT: - "Please provide a step-by-step argument for your answer, explain why you - believe your final choice is justified, and make sure to conclude your - explanation with the name of the class you have selected as the correct - one, in lowercase and without punctuation." - - -ANSWER_FORMAT: - "In your response, include only the name of the class as a single word, in - lowercase, without punctuation, and without adding any other statements or - words." diff --git a/promptmeteo/prompts/text-davinci-003_es_classification.prompt b/promptmeteo/prompts/text-davinci-003_es_classification.prompt deleted file mode 100644 index ec72f9d..0000000 --- a/promptmeteo/prompts/text-davinci-003_es_classification.prompt +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2023 Paradigma Digital S.L. - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - - -TEMPLATE: - "Necesito que me ayudes en una tarea de clasificación de texto. - {__PROMPT_DOMAIN__} - {__PROMPT_LABELS__} - - {__CHAIN_THOUGHT__} - {__ANSWER_FORMAT__}" - - -PROMPT_DOMAIN: - "Los textos que vas procesar del ambito de {__DOMAIN__}." - - -PROMPT_LABELS: - "Quiero que me clasifiques los textos una de las siguientes categorías: - {__LABELS__}." - - -PROMPT_DETAIL: - "" - - -CHAIN_THOUGHT: - "Por favor argumenta tu respuesta paso a paso, explica por qué crees que - está justificada tu elección final, y asegúrate de que acabas tu - explicación con el nombre de la clase que has escogido como la - correcta, en minúscula y sin puntuación." - - -ANSWER_FORMAT: - "En tu respuesta incluye sólo el nombre de la clase, como una única - palabra, en minúscula, sin puntuación, y sin añadir ninguna otra - afirmación o palabra." diff --git a/promptmeteo/tasks/task.py b/promptmeteo/tasks/task.py index c1b6be4..8397fc4 100644 --- a/promptmeteo/tasks/task.py +++ b/promptmeteo/tasks/task.py @@ -1,4 +1,5 @@ #!/usr/bin/python3 +from string import Formatter # Copyright (c) 2023 Paradigma Digital S.L. From eec914a61c6e96597040ec694a0b71a3009e4b3a Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Wed, 24 Jan 2024 14:11:44 +0100 Subject: [PATCH 03/20] task_builder.py: - New task added. New prompts added: - json-summarizer in spanish and english json_summarizer.py: - New model class for JSON summarization task. TODO: Fix the example and delete commented code __init__.py: - Added the new model in the init script promptmeteo/parsers/__init__.py: - New option for new type of task (json summarization). - TODO: We must change it to use a new parser for JSON treatment. --- promptmeteo/__init__.py | 1 + promptmeteo/json_summarizer.py | 268 ++++++++++++++++++ promptmeteo/parsers/__init__.py | 4 + ...pt-3.5-turbo-16k_en_json-summarizer.prompt | 51 ++++ ...pt-3.5-turbo-16k_es_json-summarizer.prompt | 51 ++++ promptmeteo/tasks/task_builder.py | 1 + 6 files changed, 376 insertions(+) create mode 100644 promptmeteo/json_summarizer.py create mode 100644 promptmeteo/prompts/gpt-3.5-turbo-16k_en_json-summarizer.prompt create mode 100644 promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-summarizer.prompt diff --git a/promptmeteo/__init__.py b/promptmeteo/__init__.py index f7ee081..e0cbf4d 100644 --- a/promptmeteo/__init__.py +++ b/promptmeteo/__init__.py @@ -4,3 +4,4 @@ from .document_classifier import DocumentClassifier from .api_generator import APIGenerator from .api_formatter import APIFormatter +from .json_summarizer import JSONSummarizer diff --git a/promptmeteo/json_summarizer.py b/promptmeteo/json_summarizer.py new file mode 100644 index 0000000..104923a --- /dev/null +++ b/promptmeteo/json_summarizer.py @@ -0,0 +1,268 @@ +#%% +#!/usr/bin/python3 +# Copyright (c) 2023 Paradigma Digital S.L. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +import re +import tarfile +import tempfile +import json +import os + +import yaml +from copy import deepcopy +from typing import List + +try: + from typing import Self +except ImportError: + from typing_extensions import Self +from langchain.prompts import PromptTemplate + +from .base import BaseUnsupervised +from .tasks import TaskTypes, TaskBuilder +from .tools import add_docstring_from +from .validations import version_validation + + +class JSONSummarizer(BaseUnsupervised): + + """ + API Generator Task. + """ + + ALLOWED_PROTOCOLS = ["REST"] + + @add_docstring_from(BaseUnsupervised.__init__) + def __init__( + self, + language, + json_fields: str, + fields_description: dict, + **kwargs, + ) -> None: + """ + Example + ------- + + >>> from promptmeteo import APIFormatter + + >>> model = APIFormatter( + >>> language='en', + >>> api_version = '3.0.3', + >>> api_protocol = 'REST', + >>> api_style_instructions = [ + >>> 'Use always camel case.', + >>> 'Do not use acronyms.' + >>> ], + >>> model_provider_name='openai', + >>> model_name='gpt-3.5-turbo-16k', + >>> model_provider_token=model_token, + >>> external_info={ + >>> "servers": [ + >>> { + >>> "url": "http://localhost:8080/", + >>> "description": "Local environment", + >>> } + >>> ], + >>> } + >>> ) + + >>> model.predict(api) + """ + + kwargs["labels"] = None + kwargs["language"] = language + kwargs["json_fields"] = json_fields + kwargs["fields_description"] = fields_description + + task_type = TaskTypes.JSON_SUMMARIZER.value + super(JSONSummarizer, self).__init__(**kwargs) + + self._builder = TaskBuilder( + language=self.language, + task_type=task_type, + verbose=self.verbose, + ) + + # Build model + self._builder.build_model( + model_name=self.model_name, + model_provider_name=self.model_provider_name, + model_provider_token=self.model_provider_token, + model_params=self.model_params, + ) + + # Building prompt + self._builder.build_prompt( + model_name=self.model_name, + prompt_domain=self.prompt_domain, + prompt_labels=self.prompt_labels, + prompt_detail=self.prompt_detail, + ) + + # Setting the prompt description according to necessities + prompt_detail = PromptTemplate.from_template(self.task.prompt.PROMPT_DETAIL) + if len(set(prompt_detail.input_variables).intersection(set(["__FIELDS_DESCRIPTION__","__FIELDS__"]))) != 2: + raise RuntimeError("Prompt file misses fields __FIELDS_DESCRIPTION__ or __FIELDS__") + + description_fields_str = "\n".join([f"{i+1}. {description} ({field})" + for i,field,description in + zip(range(len(fields_description)), + fields_description.keys(), fields_description.values())]) + prompt_detail = prompt_detail.format(__FIELDS__=",".join(json_fields), + __FIELDS_DESCRIPTION__=description_fields_str) + + self.prompt_detail = prompt_detail + self._builder.build_prompt( + model_name=self.model_name, + prompt_domain=self.prompt_domain, + prompt_labels=self.prompt_labels, + prompt_detail=self.prompt_detail, + ) + self.builder.task.prompt.PROMPT_DETAIL = prompt_detail + ## + # Build parser + self._builder.build_parser( + prompt_labels=self.prompt_labels, + ) + + + + + + @add_docstring_from(BaseUnsupervised.train) + def train( + self, + ) -> Self: + """ + Train the APIFormatter to extract entities anda parameteres. + + Parameters + ---------- + + api_codes : List[str] + + + Returns + ------- + + self + + """ + super(JSONSummarizer, self).train(examples=[""]) + + return self + + @classmethod + @add_docstring_from(BaseUnsupervised.load_model) + def load_model( + cls, + model_path: str, + ) -> Self: + """ + Loads a model artifact to make new predictions. + + Parameters + ---------- + + model_path : str + + + Returns + ------- + + self : Promptmeteo + + """ + + model_dir = os.path.dirname(model_path) + model_name = os.path.basename(model_path) + + if not model_name.endswith(".meteo"): + raise ValueError( + f"{cls.__name__} error in `load_model()`. " + f'model_path="{model_path}" has a bad model name extension. ' + f"Model name must end with `.meteo` (i.e. `./model.meteo`)" + ) + + if not os.path.exists(model_path): + raise ValueError( + f"{cls.__name__} error in `load_model()`. " + f"directory {model_dir} does not exists." + ) + + with tempfile.TemporaryDirectory() as tmp: + with tarfile.open(model_path, "r:gz") as tar: + tar.extractall(tmp) + + init_tmp_path = os.path.join( + tmp, f"{os.path.splitext(model_name)[0]}.init" + ) + + with open(init_tmp_path) as f_init: + params = json.load(f_init) + + self = cls(**params) + + self.builder.build_selector_by_load( + model_path=os.path.join(tmp, model_name), + selector_type=self.SELECTOR_TYPE, + selector_k=self._selector_k, + selector_algorithm=self._selector_algorithm, + ) + + self._is_trained = True + + return self + + # @add_docstring_from(BaseUnsupervised.predict) + # def predict(self, api_codes: List[str], external_info: dict) -> List[str]: + # """ + # Receibe a list of API codes and return a list with the corrected APIs. + + # Parameters + # ---------- + + # api_codes : List[str] + + + # Returns + # ------- + + # List[str] + + # """ + + # _api_codes = deepcopy(api_codes) + # _api_codes = super(JSONSummarizer, self).predict(examples=_api_codes) + # _api_codes = [self._replace(api) for api in _api_codes] + # _api_codes = [ + # self._add_external_information(api, external_info) + # for api in _api_codes + # ] + # return _api_codes + +#%% +# json_summarizer = JSONSummarizer(language="es", +# json_fields=["summary","sentiment","topic","keywords"], +# fields_description={"summary":"", +# "sentiment":"", +# "topic":"", +# "keywords":""}) diff --git a/promptmeteo/parsers/__init__.py b/promptmeteo/parsers/__init__.py index 9021f1e..cac8ad1 100644 --- a/promptmeteo/parsers/__init__.py +++ b/promptmeteo/parsers/__init__.py @@ -41,6 +41,7 @@ class ParserTypes(str, Enum): PARSER_4: str = "code-generation" PARSER_5: str = "api-generation" PARSER_6: str = "api-correction" + PARSER_7: str = "json-summarizer" class ParserFactory: @@ -77,6 +78,9 @@ def factory_method( elif task_type == ParserTypes.PARSER_6.value: parser_cls = ApiParser + + elif task_type == ParserTypes.PARSER_7.value: + parser_cls = DummyParser else: raise ValueError( diff --git a/promptmeteo/prompts/gpt-3.5-turbo-16k_en_json-summarizer.prompt b/promptmeteo/prompts/gpt-3.5-turbo-16k_en_json-summarizer.prompt new file mode 100644 index 0000000..f1b483d --- /dev/null +++ b/promptmeteo/prompts/gpt-3.5-turbo-16k_en_json-summarizer.prompt @@ -0,0 +1,51 @@ +# Copyright (c) 2023 Paradigma Digital S.L. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + + +TEMPLATE: + "{__PROMPT_DOMAIN__} + {__PROMPT_SAMPLE__} + {__PROMPT_DETAIL__} + {__CHAIN_THOUGHT__} + {__ANSWER_FORMAT__}" + +PROMPT_SAMPLE: + "Given the text: + + ```\n{__SAMPLE__}\n``` + " + +PROMPT_DOMAIN: + "" + +PROMPT_DETAIL: + " + extract the information in JSON format, where we will have the following fields ({__FIELDS__}):\n + {__FIELDS_DESCRIPTION__} + " + +SHOT_EXAMPLES: + "" + +CHAIN_THOUGHT: + "" + +ANSWER_FORMAT: + "" diff --git a/promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-summarizer.prompt b/promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-summarizer.prompt new file mode 100644 index 0000000..247b8b1 --- /dev/null +++ b/promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-summarizer.prompt @@ -0,0 +1,51 @@ +# Copyright (c) 2023 Paradigma Digital S.L. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + + +TEMPLATE: + "{__PROMPT_DOMAIN__} + {__PROMPT_SAMPLE__} + {__PROMPT_DETAIL__} + {__CHAIN_THOUGHT__} + {__ANSWER_FORMAT__}" + +PROMPT_SAMPLE: + "Dado el texto: + + ```\n{__SAMPLE__}\n``` + " + +PROMPT_DOMAIN: + "" + +PROMPT_DETAIL: + " + extrae la información en formato json donde tendremos los siguientes campos ({__FIELDS__}):\n + {__FIELDS_DESCRIPTION__} + " + +SHOT_EXAMPLES: + "" + +CHAIN_THOUGHT: + "" + +ANSWER_FORMAT: + "" diff --git a/promptmeteo/tasks/task_builder.py b/promptmeteo/tasks/task_builder.py index 5f77944..66f9501 100644 --- a/promptmeteo/tasks/task_builder.py +++ b/promptmeteo/tasks/task_builder.py @@ -50,6 +50,7 @@ class TaskTypes(str, Enum): CODE_GENERATION: str = "code-generation" API_GENERATION: str = "api-generation" API_CORRECTION: str = "api-correction" + JSON_SUMMARIZER: str = "json-summarizer" class TaskBuilder: From 2d9aa3fd4a444a6ddbdc44bc2411f9f4aabed1e7 Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Wed, 24 Jan 2024 15:17:52 +0100 Subject: [PATCH 04/20] JSON parser added --- promptmeteo/parsers/__init__.py | 3 +- promptmeteo/parsers/json_parser.py | 67 ++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 promptmeteo/parsers/json_parser.py diff --git a/promptmeteo/parsers/__init__.py b/promptmeteo/parsers/__init__.py index cac8ad1..1483817 100644 --- a/promptmeteo/parsers/__init__.py +++ b/promptmeteo/parsers/__init__.py @@ -27,6 +27,7 @@ from .base import BaseParser from .dummy_parser import DummyParser from .classification_parser import ClassificationParser +from .json_parser import JSONParser class ParserTypes(str, Enum): @@ -80,7 +81,7 @@ def factory_method( parser_cls = ApiParser elif task_type == ParserTypes.PARSER_7.value: - parser_cls = DummyParser + parser_cls = JSONParser else: raise ValueError( diff --git a/promptmeteo/parsers/json_parser.py b/promptmeteo/parsers/json_parser.py new file mode 100644 index 0000000..51293b2 --- /dev/null +++ b/promptmeteo/parsers/json_parser.py @@ -0,0 +1,67 @@ +#!/usr/bin/python3 + +# Copyright (c) 2023 Paradigma Digital S.L. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +from typing import List +import re +from .base import BaseParser +import regex +import json + + +class JSONParser(BaseParser): + + """ + Parser for the classification task. + """ + + def run( + self, + text: str, + ) -> List[str]: + """ + Given a response string from an LLM, returns the response expected for + the task. + """ + + try: + json_output = self._preprocess(text) + json_obtanaied = json.loads(json_output) + return json_output + except: + return "" + + + def _preprocess( + self, + text: str, + ) -> str: + """ + Preprocess output string before parsing result to solve common mistakes + such as end-of-line presence and beginning and finishing with empty + space. + """ + pattern = regex.compile(r'\{(?:[^{}]|(?R))*\}') + str_json = pattern.findall(text)[0] + + str_json = str_json.replace("'",'"') + + return str_json From b657425a135303f32a90df5985d27800e4398eba Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Thu, 25 Jan 2024 11:24:47 +0100 Subject: [PATCH 05/20] Changes: prompts. New prompt for anthropic claude added and name changing for gpt 3.5 models. pyproject.toml. Added boto3 in the requirements to connect with aws. __init__.py. Name changing of the task json_info_extraction.py: - New file replacing json_summarizer.py with the new naming /models/__init__.py: - New model provider added for Bedrock /models/bedrock.py: - Class for Bedrock models. - Only anthropic claude v2 integrated - By the moment, huggingface embeddings /parsers/__init__.py: - Name changing of the parser /tasks/task_builder.py: - Name changing and summarization task included for new development. --- promptmeteo/__init__.py | 2 +- ..._summarizer.py => json_info_extraction.py} | 43 +----- promptmeteo/models/__init__.py | 6 + promptmeteo/models/bedrock.py | 127 ++++++++++++++++++ promptmeteo/parsers/__init__.py | 2 +- ....claude-v2_es_json-info-extraction.prompt} | 0 ...-turbo-16k_en_json-info-extraction.prompt} | 0 ...5-turbo-16k_es_json-info-extraction.prompt | 51 +++++++ promptmeteo/tasks/task_builder.py | 3 +- 9 files changed, 192 insertions(+), 42 deletions(-) rename promptmeteo/{json_summarizer.py => json_info_extraction.py} (83%) create mode 100644 promptmeteo/models/bedrock.py rename promptmeteo/prompts/{gpt-3.5-turbo-16k_es_json-summarizer.prompt => anthropic.claude-v2_es_json-info-extraction.prompt} (100%) rename promptmeteo/prompts/{gpt-3.5-turbo-16k_en_json-summarizer.prompt => gpt-3.5-turbo-16k_en_json-info-extraction.prompt} (100%) create mode 100644 promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-info-extraction.prompt diff --git a/promptmeteo/__init__.py b/promptmeteo/__init__.py index e0cbf4d..6cb3a20 100644 --- a/promptmeteo/__init__.py +++ b/promptmeteo/__init__.py @@ -4,4 +4,4 @@ from .document_classifier import DocumentClassifier from .api_generator import APIGenerator from .api_formatter import APIFormatter -from .json_summarizer import JSONSummarizer +from .json_info_extraction import JSONInfoExtraction diff --git a/promptmeteo/json_summarizer.py b/promptmeteo/json_info_extraction.py similarity index 83% rename from promptmeteo/json_summarizer.py rename to promptmeteo/json_info_extraction.py index 104923a..33aaf5f 100644 --- a/promptmeteo/json_summarizer.py +++ b/promptmeteo/json_info_extraction.py @@ -41,7 +41,7 @@ from .validations import version_validation -class JSONSummarizer(BaseUnsupervised): +class JSONInfoExtraction(BaseUnsupervised): """ API Generator Task. @@ -92,8 +92,8 @@ def __init__( kwargs["json_fields"] = json_fields kwargs["fields_description"] = fields_description - task_type = TaskTypes.JSON_SUMMARIZER.value - super(JSONSummarizer, self).__init__(**kwargs) + task_type = TaskTypes.JSON_INFO_EXTRACTION.value + super(JSONInfoExtraction, self).__init__(**kwargs) self._builder = TaskBuilder( language=self.language, @@ -166,7 +166,7 @@ def train( self """ - super(JSONSummarizer, self).train(examples=[""]) + super(JSONInfoExtraction, self).train(examples=[""]) return self @@ -231,38 +231,3 @@ def load_model( self._is_trained = True return self - - # @add_docstring_from(BaseUnsupervised.predict) - # def predict(self, api_codes: List[str], external_info: dict) -> List[str]: - # """ - # Receibe a list of API codes and return a list with the corrected APIs. - - # Parameters - # ---------- - - # api_codes : List[str] - - - # Returns - # ------- - - # List[str] - - # """ - - # _api_codes = deepcopy(api_codes) - # _api_codes = super(JSONSummarizer, self).predict(examples=_api_codes) - # _api_codes = [self._replace(api) for api in _api_codes] - # _api_codes = [ - # self._add_external_information(api, external_info) - # for api in _api_codes - # ] - # return _api_codes - -#%% -# json_summarizer = JSONSummarizer(language="es", -# json_fields=["summary","sentiment","topic","keywords"], -# fields_description={"summary":"", -# "sentiment":"", -# "topic":"", -# "keywords":""}) diff --git a/promptmeteo/models/__init__.py b/promptmeteo/models/__init__.py index 27db4c7..ec3fd32 100644 --- a/promptmeteo/models/__init__.py +++ b/promptmeteo/models/__init__.py @@ -29,6 +29,7 @@ from .hf_hub_api import HFHubApiLLM from .hf_pipeline import HFPipelineLLM from .google_vertexai import GoogleVertexAILLM +from .bedrock import BedrockLLM class ModelProvider(str, Enum): @@ -42,6 +43,7 @@ class ModelProvider(str, Enum): PROVIDER_2: str = "hf_hub_api" PROVIDER_3: str = "hf_pipeline" PROVIDER_4: str = "google-vertexai" + PROVIDER_5: str = "bedrock" class ModelFactory: @@ -57,6 +59,7 @@ class ModelFactory: ModelProvider.PROVIDER_2: HFHubApiLLM, ModelProvider.PROVIDER_3: HFPipelineLLM, ModelProvider.PROVIDER_3: GoogleVertexAILLM, + ModelProvider.PROVIDER_5: BedrockLLM } @classmethod @@ -87,6 +90,9 @@ def factory_method( elif model_provider_name == ModelProvider.PROVIDER_4.value: model_cls = GoogleVertexAILLM + + elif model_provider_name == ModelProvider.PROVIDER_5.value: + model_cls = BedrockLLM else: raise ValueError( diff --git a/promptmeteo/models/bedrock.py b/promptmeteo/models/bedrock.py new file mode 100644 index 0000000..837dcfb --- /dev/null +++ b/promptmeteo/models/bedrock.py @@ -0,0 +1,127 @@ +#!/usr/bin/python3 + +# Copyright (c) 2023 Paradigma Digital S.L. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +from enum import Enum +from typing import Dict +from typing import Optional +import os +import boto3 +from langchain.llms.bedrock import Bedrock +from langchain.embeddings import HuggingFaceEmbeddings + +from .base import BaseModel + + +class ModelTypes(str, Enum): + + """ + Enum of available model types. + """ + + AnthropicClaudeV2: str = "anthropic.claude-v2" + + @classmethod + def has_value( + cls, + value: str, + ) -> bool: + """ + Checks if the value is in the enum or not. + """ + + return value in cls._value2member_map_ + + +class ModelEnum(Enum): + + """ + Model Parameters. + """ + + class AnthropicClaudeV2: + + """ + Default parameters for Anthropic Claude V2 + """ + + client = Bedrock + embedding = HuggingFaceEmbeddings + boto3_bedrock = boto3.client('bedrock-runtime') + model_task: str = "text2text-generation" + params: dict = { + 'max_tokens_to_sample': 2048, + 'temperature': 0.3, + 'top_k': 250, + 'top_p': 0.999, + 'stop_sequences': ['Human:'] + } + + +class BedrockLLM(BaseModel): + + """ + Bedrock LLM model. + """ + + def __init__( + self, + model_name: Optional[str] = "", + model_params: Optional[Dict] = None, + model_provider_token: Optional[str] = "", + ) -> None: + """ + Make predictions using a model from OpenAI. + It will use the os environment called OPENAI_ORGANIZATION for instance the LLM + """ + + if not ModelTypes.has_value(model_name): + raise ValueError( + f"`model_name`={model_name} not in supported model names: " + f"{[i.name for i in ModelTypes]}" + ) + + super(BedrockLLM, self).__init__() + + # Model name + model = ModelTypes(model_name).name + + # Model parameters + if not model_params: + model_params = ( + ModelEnum[model].value.params + if not model_params + else model_params + ) + self.model_params = model_params + + # Model + self._llm = ModelEnum[model].value.client( + model_id=model_name, + model_kwargs=self.model_params, + client = ModelEnum[model].value.boto3_bedrock + ) + + embedding_name = "sentence-transformers/all-MiniLM-L6-v2" + if os.path.exists("/home/models/all-MiniLM-L6-v2"): + embedding_name = "/home/models/all-MiniLM-L6-v2" + + self._embeddings = HuggingFaceEmbeddings(model_name=embedding_name) diff --git a/promptmeteo/parsers/__init__.py b/promptmeteo/parsers/__init__.py index 1483817..f33eeaa 100644 --- a/promptmeteo/parsers/__init__.py +++ b/promptmeteo/parsers/__init__.py @@ -42,7 +42,7 @@ class ParserTypes(str, Enum): PARSER_4: str = "code-generation" PARSER_5: str = "api-generation" PARSER_6: str = "api-correction" - PARSER_7: str = "json-summarizer" + PARSER_7: str = "json-info-extraction" class ParserFactory: diff --git a/promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-summarizer.prompt b/promptmeteo/prompts/anthropic.claude-v2_es_json-info-extraction.prompt similarity index 100% rename from promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-summarizer.prompt rename to promptmeteo/prompts/anthropic.claude-v2_es_json-info-extraction.prompt diff --git a/promptmeteo/prompts/gpt-3.5-turbo-16k_en_json-summarizer.prompt b/promptmeteo/prompts/gpt-3.5-turbo-16k_en_json-info-extraction.prompt similarity index 100% rename from promptmeteo/prompts/gpt-3.5-turbo-16k_en_json-summarizer.prompt rename to promptmeteo/prompts/gpt-3.5-turbo-16k_en_json-info-extraction.prompt diff --git a/promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-info-extraction.prompt b/promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-info-extraction.prompt new file mode 100644 index 0000000..247b8b1 --- /dev/null +++ b/promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-info-extraction.prompt @@ -0,0 +1,51 @@ +# Copyright (c) 2023 Paradigma Digital S.L. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + + +TEMPLATE: + "{__PROMPT_DOMAIN__} + {__PROMPT_SAMPLE__} + {__PROMPT_DETAIL__} + {__CHAIN_THOUGHT__} + {__ANSWER_FORMAT__}" + +PROMPT_SAMPLE: + "Dado el texto: + + ```\n{__SAMPLE__}\n``` + " + +PROMPT_DOMAIN: + "" + +PROMPT_DETAIL: + " + extrae la información en formato json donde tendremos los siguientes campos ({__FIELDS__}):\n + {__FIELDS_DESCRIPTION__} + " + +SHOT_EXAMPLES: + "" + +CHAIN_THOUGHT: + "" + +ANSWER_FORMAT: + "" diff --git a/promptmeteo/tasks/task_builder.py b/promptmeteo/tasks/task_builder.py index 66f9501..a465c1a 100644 --- a/promptmeteo/tasks/task_builder.py +++ b/promptmeteo/tasks/task_builder.py @@ -50,7 +50,8 @@ class TaskTypes(str, Enum): CODE_GENERATION: str = "code-generation" API_GENERATION: str = "api-generation" API_CORRECTION: str = "api-correction" - JSON_SUMMARIZER: str = "json-summarizer" + JSON_INFO_EXTRACTION: str = "json-info-extraction" + SUMMARIZATION: str = "summarization" class TaskBuilder: From 906417501b9c519aae89348182767a117901ac91 Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Thu, 25 Jan 2024 15:05:28 +0100 Subject: [PATCH 06/20] __init__.py: - Added Summarizer class json_info_extraction.py: - Changes in the example and code comments. - json_fields parameter removed due to it is implicit in fields_description summarizer.py: - New class for Summarization task parsers/__init__.py: - New parser added for summarization task (dummy parser) new prompts for anthropic claude summarization and minor changes in prompts tests/tools/dictionary_checker: - 'sample' word added in spanish dictionary because is a keyword for injecting. --- promptmeteo/__init__.py | 1 + promptmeteo/json_info_extraction.py | 48 ++-- promptmeteo/parsers/__init__.py | 4 + ...c.claude-v2_es_json-info-extraction.prompt | 6 +- ...nthropic.claude-v2_es_summarization.prompt | 51 ++++ ...5-turbo-16k_es_json-info-extraction.prompt | 2 +- .../gpt-3.5-turbo-16k_es_summarization.prompt | 49 ++++ promptmeteo/summarizer.py | 218 ++++++++++++++++++ 8 files changed, 346 insertions(+), 33 deletions(-) create mode 100644 promptmeteo/prompts/anthropic.claude-v2_es_summarization.prompt create mode 100644 promptmeteo/prompts/gpt-3.5-turbo-16k_es_summarization.prompt create mode 100644 promptmeteo/summarizer.py diff --git a/promptmeteo/__init__.py b/promptmeteo/__init__.py index 6cb3a20..61fe25c 100644 --- a/promptmeteo/__init__.py +++ b/promptmeteo/__init__.py @@ -5,3 +5,4 @@ from .api_generator import APIGenerator from .api_formatter import APIFormatter from .json_info_extraction import JSONInfoExtraction +from .summarizer import Summarizer \ No newline at end of file diff --git a/promptmeteo/json_info_extraction.py b/promptmeteo/json_info_extraction.py index 33aaf5f..ba289d9 100644 --- a/promptmeteo/json_info_extraction.py +++ b/promptmeteo/json_info_extraction.py @@ -44,16 +44,13 @@ class JSONInfoExtraction(BaseUnsupervised): """ - API Generator Task. + Task for information extraction from text in JSON format. """ - ALLOWED_PROTOCOLS = ["REST"] - @add_docstring_from(BaseUnsupervised.__init__) def __init__( self, language, - json_fields: str, fields_description: dict, **kwargs, ) -> None: @@ -61,35 +58,26 @@ def __init__( Example ------- - >>> from promptmeteo import APIFormatter - - >>> model = APIFormatter( - >>> language='en', - >>> api_version = '3.0.3', - >>> api_protocol = 'REST', - >>> api_style_instructions = [ - >>> 'Use always camel case.', - >>> 'Do not use acronyms.' - >>> ], - >>> model_provider_name='openai', - >>> model_name='gpt-3.5-turbo-16k', - >>> model_provider_token=model_token, - >>> external_info={ - >>> "servers": [ - >>> { - >>> "url": "http://localhost:8080/", - >>> "description": "Local environment", - >>> } - >>> ], - >>> } - >>> ) - - >>> model.predict(api) + >>> from promptmeteo import JSONInfoExtraction + + >>> JSONInfoExtraction( + >>> language="es", + >>> fields_description = { + >>> "topic":"Motivo de la llamada", + >>> "sentiment":"Sentimiento del cliente", + >>> "summary":"Resumen de la llamada", + >>> "negative_tags":"Entidades y tópicos negativos en la llamada", + >>> "positive_tags":"Entidades y tópicos positivos en la llamada" + >>> }, + >>> model_name = "anthropic.claude-v2", + >>> model_provider_name = "bedrock" + >>> ) + + >>> model.predict(text) """ kwargs["labels"] = None kwargs["language"] = language - kwargs["json_fields"] = json_fields kwargs["fields_description"] = fields_description task_type = TaskTypes.JSON_INFO_EXTRACTION.value @@ -126,7 +114,7 @@ def __init__( for i,field,description in zip(range(len(fields_description)), fields_description.keys(), fields_description.values())]) - prompt_detail = prompt_detail.format(__FIELDS__=",".join(json_fields), + prompt_detail = prompt_detail.format(__FIELDS__=",".join([i for i in fields_description.keys()]), __FIELDS_DESCRIPTION__=description_fields_str) self.prompt_detail = prompt_detail diff --git a/promptmeteo/parsers/__init__.py b/promptmeteo/parsers/__init__.py index f33eeaa..000af85 100644 --- a/promptmeteo/parsers/__init__.py +++ b/promptmeteo/parsers/__init__.py @@ -43,6 +43,7 @@ class ParserTypes(str, Enum): PARSER_5: str = "api-generation" PARSER_6: str = "api-correction" PARSER_7: str = "json-info-extraction" + PARSER_8: str = "summarization" class ParserFactory: @@ -82,6 +83,9 @@ def factory_method( elif task_type == ParserTypes.PARSER_7.value: parser_cls = JSONParser + + elif task_type == ParserTypes.PARSER_8.value: + parser_cls = DummyParser else: raise ValueError( diff --git a/promptmeteo/prompts/anthropic.claude-v2_es_json-info-extraction.prompt b/promptmeteo/prompts/anthropic.claude-v2_es_json-info-extraction.prompt index 247b8b1..0c4c060 100644 --- a/promptmeteo/prompts/anthropic.claude-v2_es_json-info-extraction.prompt +++ b/promptmeteo/prompts/anthropic.claude-v2_es_json-info-extraction.prompt @@ -20,7 +20,7 @@ TEMPLATE: - "{__PROMPT_DOMAIN__} + "Human: {__PROMPT_DOMAIN__} {__PROMPT_SAMPLE__} {__PROMPT_DETAIL__} {__CHAIN_THOUGHT__} @@ -29,7 +29,7 @@ TEMPLATE: PROMPT_SAMPLE: "Dado el texto: - ```\n{__SAMPLE__}\n``` + \n\"{__SAMPLE__}\"\n " PROMPT_DOMAIN: @@ -39,6 +39,8 @@ PROMPT_DETAIL: " extrae la información en formato json donde tendremos los siguientes campos ({__FIELDS__}):\n {__FIELDS_DESCRIPTION__} + + Assistant: A continuación el JSON obtenido: " SHOT_EXAMPLES: diff --git a/promptmeteo/prompts/anthropic.claude-v2_es_summarization.prompt b/promptmeteo/prompts/anthropic.claude-v2_es_summarization.prompt new file mode 100644 index 0000000..d124fe0 --- /dev/null +++ b/promptmeteo/prompts/anthropic.claude-v2_es_summarization.prompt @@ -0,0 +1,51 @@ +# Copyright (c) 2023 Paradigma Digital S.L. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + + +TEMPLATE: + "Human: {__PROMPT_DOMAIN__} + {__PROMPT_SAMPLE__} + {__PROMPT_DETAIL__} + {__CHAIN_THOUGHT__} + {__ANSWER_FORMAT__}" + +PROMPT_SAMPLE: + " + \n\"{__SAMPLE__}\"\n + " + +PROMPT_DOMAIN: + "{__DOMAIN__}" + +PROMPT_DETAIL: + " + Basado en el segmento de texto, por favor genera un resumen preciso y no invente información. + + Assistant: A continuación muestro el resumen: + " + +SHOT_EXAMPLES: + "" + +CHAIN_THOUGHT: + "" + +ANSWER_FORMAT: + "" diff --git a/promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-info-extraction.prompt b/promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-info-extraction.prompt index 247b8b1..fa03e4e 100644 --- a/promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-info-extraction.prompt +++ b/promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-info-extraction.prompt @@ -29,7 +29,7 @@ TEMPLATE: PROMPT_SAMPLE: "Dado el texto: - ```\n{__SAMPLE__}\n``` + \n\"{__SAMPLE__}\"\n " PROMPT_DOMAIN: diff --git a/promptmeteo/prompts/gpt-3.5-turbo-16k_es_summarization.prompt b/promptmeteo/prompts/gpt-3.5-turbo-16k_es_summarization.prompt new file mode 100644 index 0000000..b0c7a9d --- /dev/null +++ b/promptmeteo/prompts/gpt-3.5-turbo-16k_es_summarization.prompt @@ -0,0 +1,49 @@ +# Copyright (c) 2023 Paradigma Digital S.L. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + + +TEMPLATE: + "{__PROMPT_DOMAIN__} + {__PROMPT_SAMPLE__} + {__PROMPT_DETAIL__} + {__CHAIN_THOUGHT__} + {__ANSWER_FORMAT__}" + +PROMPT_SAMPLE: + " + \n\"{__SAMPLE__}\"\n + " + +PROMPT_DOMAIN: + "{__DOMAIN__}" + +PROMPT_DETAIL: + " + Basado en el segmento de texto, por favor genera un resumen preciso y no invente información. + " + +SHOT_EXAMPLES: + "" + +CHAIN_THOUGHT: + "" + +ANSWER_FORMAT: + "" diff --git a/promptmeteo/summarizer.py b/promptmeteo/summarizer.py new file mode 100644 index 0000000..999295f --- /dev/null +++ b/promptmeteo/summarizer.py @@ -0,0 +1,218 @@ +#%% +#!/usr/bin/python3 +# Copyright (c) 2023 Paradigma Digital S.L. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +import re +import tarfile +import tempfile +import json +import os + +import yaml +from copy import deepcopy +from typing import List + +try: + from typing import Self +except ImportError: + from typing_extensions import Self +from langchain.prompts import PromptTemplate + +from .base import BaseUnsupervised +from .tasks import TaskTypes, TaskBuilder +from .tools import add_docstring_from +from .validations import version_validation + + +class Summarizer(BaseUnsupervised): + + """ + Class for text summarization + """ + @add_docstring_from(BaseUnsupervised.__init__) + def __init__( + self, + prompt_domain, + language, + **kwargs, + ) -> None: + """ + Example + ------- + """ + + kwargs["labels"] = None + kwargs["language"] = language + kwargs["prompt_domain"] = prompt_domain + + + task_type = TaskTypes.SUMMARIZATION.value + super(Summarizer, self).__init__(**kwargs) + + self._builder = TaskBuilder( + language=self.language, + task_type=task_type, + verbose=self.verbose, + ) + + # Build model + self._builder.build_model( + model_name=self.model_name, + model_provider_name=self.model_provider_name, + model_provider_token=self.model_provider_token, + model_params=self.model_params, + ) + + # Building prompt + self._builder.build_prompt( + model_name=self.model_name, + prompt_domain=self.prompt_domain, + prompt_labels=self.prompt_labels, + prompt_detail=self.prompt_detail, + ) + + ## + # Build parser + self._builder.build_parser( + prompt_labels=self.prompt_labels, + ) + + + + + @add_docstring_from(BaseUnsupervised.train) + def train( + self, + ) -> Self: + """ + Train the APIFormatter to extract entities anda parameteres. + + Parameters + ---------- + + api_codes : List[str] + + + Returns + ------- + + self + + """ + super(Summarizer, self).train(examples=[""]) + + return self + + @classmethod + @add_docstring_from(BaseUnsupervised.load_model) + def load_model( + cls, + model_path: str, + ) -> Self: + """ + Loads a model artifact to make new predictions. + + Parameters + ---------- + + model_path : str + + + Returns + ------- + + self : Promptmeteo + + """ + + model_dir = os.path.dirname(model_path) + model_name = os.path.basename(model_path) + + if not model_name.endswith(".meteo"): + raise ValueError( + f"{cls.__name__} error in `load_model()`. " + f'model_path="{model_path}" has a bad model name extension. ' + f"Model name must end with `.meteo` (i.e. `./model.meteo`)" + ) + + if not os.path.exists(model_path): + raise ValueError( + f"{cls.__name__} error in `load_model()`. " + f"directory {model_dir} does not exists." + ) + + with tempfile.TemporaryDirectory() as tmp: + with tarfile.open(model_path, "r:gz") as tar: + tar.extractall(tmp) + + init_tmp_path = os.path.join( + tmp, f"{os.path.splitext(model_name)[0]}.init" + ) + + with open(init_tmp_path) as f_init: + params = json.load(f_init) + + self = cls(**params) + + self.builder.build_selector_by_load( + model_path=os.path.join(tmp, model_name), + selector_type=self.SELECTOR_TYPE, + selector_k=self._selector_k, + selector_algorithm=self._selector_algorithm, + ) + + self._is_trained = True + + return self + + # @add_docstring_from(BaseUnsupervised.predict) + # def predict(self, api_codes: List[str], external_info: dict) -> List[str]: + # """ + # Receibe a list of API codes and return a list with the corrected APIs. + + # Parameters + # ---------- + + # api_codes : List[str] + + + # Returns + # ------- + + # List[str] + + # """ + + # _api_codes = deepcopy(api_codes) + # _api_codes = super(JSONInfoExtractor, self).predict(examples=_api_codes) + # _api_codes = [self._replace(api) for api in _api_codes] + # _api_codes = [ + # self._add_external_information(api, external_info) + # for api in _api_codes + # ] + # return _api_codes + +#%% +# JSON_SUMMARIZATION = JSONInfoExtractor(language="es", +# json_fields=["summary","sentiment","topic","keywords"], +# fields_description={"summary":"", +# "sentiment":"", +# "topic":"", +# "keywords":""}) From 62e121cd0290515aab654c4fc6cd2e45ad882951 Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Thu, 25 Jan 2024 15:08:43 +0100 Subject: [PATCH 07/20] Minor changes in example documentation --- promptmeteo/json_info_extraction.py | 2 +- promptmeteo/summarizer.py | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/promptmeteo/json_info_extraction.py b/promptmeteo/json_info_extraction.py index ba289d9..c1403d5 100644 --- a/promptmeteo/json_info_extraction.py +++ b/promptmeteo/json_info_extraction.py @@ -60,7 +60,7 @@ def __init__( >>> from promptmeteo import JSONInfoExtraction - >>> JSONInfoExtraction( + >>> model = JSONInfoExtraction( >>> language="es", >>> fields_description = { >>> "topic":"Motivo de la llamada", diff --git a/promptmeteo/summarizer.py b/promptmeteo/summarizer.py index 999295f..7ab8f65 100644 --- a/promptmeteo/summarizer.py +++ b/promptmeteo/summarizer.py @@ -56,6 +56,16 @@ def __init__( """ Example ------- + + >>> from promptmeteo import Summarizer + + >>> model = Summarizer( + >>> language="es", + >>> prompt_domain="A partir del siguiente texto:", + >>> model_name="anthropic.claude-v2", + >>> model_provider_name = "bedrock" + >>> ) + >>> model.predict([text]) """ kwargs["labels"] = None From 45ec1e9fe672e861015dceb77079cc56c675b7fb Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Thu, 25 Jan 2024 15:11:34 +0100 Subject: [PATCH 08/20] Removing comments --- promptmeteo/summarizer.py | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/promptmeteo/summarizer.py b/promptmeteo/summarizer.py index 7ab8f65..93d192c 100644 --- a/promptmeteo/summarizer.py +++ b/promptmeteo/summarizer.py @@ -191,38 +191,3 @@ def load_model( self._is_trained = True return self - - # @add_docstring_from(BaseUnsupervised.predict) - # def predict(self, api_codes: List[str], external_info: dict) -> List[str]: - # """ - # Receibe a list of API codes and return a list with the corrected APIs. - - # Parameters - # ---------- - - # api_codes : List[str] - - - # Returns - # ------- - - # List[str] - - # """ - - # _api_codes = deepcopy(api_codes) - # _api_codes = super(JSONInfoExtractor, self).predict(examples=_api_codes) - # _api_codes = [self._replace(api) for api in _api_codes] - # _api_codes = [ - # self._add_external_information(api, external_info) - # for api in _api_codes - # ] - # return _api_codes - -#%% -# JSON_SUMMARIZATION = JSONInfoExtractor(language="es", -# json_fields=["summary","sentiment","topic","keywords"], -# fields_description={"summary":"", -# "sentiment":"", -# "topic":"", -# "keywords":""}) From 257469a3b3297232d81f5c8906e9440f91f2e11b Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Mon, 29 Jan 2024 11:54:58 +0100 Subject: [PATCH 09/20] Minor change: - Change for region selection --- promptmeteo/models/bedrock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/promptmeteo/models/bedrock.py b/promptmeteo/models/bedrock.py index 837dcfb..bca4022 100644 --- a/promptmeteo/models/bedrock.py +++ b/promptmeteo/models/bedrock.py @@ -65,7 +65,7 @@ class AnthropicClaudeV2: client = Bedrock embedding = HuggingFaceEmbeddings - boto3_bedrock = boto3.client('bedrock-runtime') + boto3_bedrock = boto3.client('bedrock-runtime', region_name="us-east-1") model_task: str = "text2text-generation" params: dict = { 'max_tokens_to_sample': 2048, From 160f1360c613db8ef092d62da3c8090420d1fce5 Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Mon, 29 Jan 2024 12:43:00 +0100 Subject: [PATCH 10/20] Changes: - test_models.py: Added model Bedrock for unit test - test_parsers.py: Added unit test for json parser. - json_parser.py: Change in description --- promptmeteo/parsers/json_parser.py | 2 +- tests/test_models.py | 26 ++++++++++++++++++++++++++ tests/test_parsers.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/promptmeteo/parsers/json_parser.py b/promptmeteo/parsers/json_parser.py index 51293b2..c7f3ca9 100644 --- a/promptmeteo/parsers/json_parser.py +++ b/promptmeteo/parsers/json_parser.py @@ -30,7 +30,7 @@ class JSONParser(BaseParser): """ - Parser for the classification task. + Parser for potential JSON outputs """ def run( diff --git a/tests/test_models.py b/tests/test_models.py index fa3cbc7..a1e6897 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -57,6 +57,32 @@ def test_model_openai(self): ) assert error.value.args[0] == invalid_provider + + def test_model_bedrock(self): + from promptmeteo.models.bedrock import BedrockLLM + from promptmeteo.models.bedrock import ModelTypes + + for model_name in ModelTypes: + BedrockLLM( + model_name=model_name.value, + model_params={}, + model_provider_token="TEST_TOKEN" + ) + + with pytest.raises(ValueError) as error: + BedrockLLM( + model_name="WRONG_NAME", + model_params={}, + model_provider_token="TEST_TOKEN" + ) + + invalid_provider = ( + "`model_name`=WRONG_NAME not in supported model names: " + f"{[i.name for i in ModelTypes]}" + ) + assert error.value.args[0] == invalid_provider + + def test_model_fakellm(self): from promptmeteo.models.fake_llm import ModelTypes from promptmeteo.models.fake_llm import FakeLLM diff --git a/tests/test_parsers.py b/tests/test_parsers.py index 8a4ceef..2a9885e 100644 --- a/tests/test_parsers.py +++ b/tests/test_parsers.py @@ -4,6 +4,7 @@ from promptmeteo.parsers import ParserFactory from promptmeteo.parsers.dummy_parser import DummyParser from promptmeteo.parsers.classification_parser import ClassificationParser +from promptmeteo.parsers.json_parser import JSONParser class Testparsers: @@ -37,3 +38,31 @@ def test_classification_parser(self): assert ["true"] == parser.run("True") assert ["true"] == parser.run("blabla, true, blabla") assert ["true", "false"] == parser.run("true, false") + + def test_json_parser(self): + parser = JSONParser(prompt_labels=["true","false"]) + + wrong_json = """{ + "item1":[1,2,3,4], + 'item2':{ + "item2.1":"test item", + 'item2.2":["i211","i212",'i213'] + }, + "item3":"this is the third item" + }""" + + correct_json = """{ + "item1":[1,2,3,4], + "item2":{ + "item2.1":"test item", + "item2.2":["i211","i212","i213"] + }, + "item3":"this is the third item" + }""" + + assert correct_json == parser.run(wrong_json) + assert parser.run(correct_json) == parser.run(wrong_json) + import json + json.loads(parser.run(wrong_json)) + assert "" == parser.run("This is not a json format") + assert "" == parser.run("{This is not a complete json") From 9f1608f81b760c4418e4fd5f7fe1b3e0b5d44330 Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Mon, 29 Jan 2024 13:24:38 +0100 Subject: [PATCH 11/20] Merge branch 'main' into integracion-summary --- promptmeteo/tasks/task.py | 1 - 1 file changed, 1 deletion(-) diff --git a/promptmeteo/tasks/task.py b/promptmeteo/tasks/task.py index 8397fc4..c1b6be4 100644 --- a/promptmeteo/tasks/task.py +++ b/promptmeteo/tasks/task.py @@ -1,5 +1,4 @@ #!/usr/bin/python3 -from string import Formatter # Copyright (c) 2023 Paradigma Digital S.L. From 91a5e2881ffa74c8134fa6453eea5fa4df3daee4 Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Mon, 29 Jan 2024 13:51:23 +0100 Subject: [PATCH 12/20] Changes: json_info_extraction.py: - Adapted to new Base model building structure summarizer.py: - Adapted to new Base model building structure. pyproject.toml: - boto3 added --- promptmeteo/json_info_extraction.py | 38 +++-------------------------- promptmeteo/summarizer.py | 38 ++--------------------------- pyproject.toml | 1 + 3 files changed, 7 insertions(+), 70 deletions(-) diff --git a/promptmeteo/json_info_extraction.py b/promptmeteo/json_info_extraction.py index c1403d5..59fa951 100644 --- a/promptmeteo/json_info_extraction.py +++ b/promptmeteo/json_info_extraction.py @@ -46,11 +46,11 @@ class JSONInfoExtraction(BaseUnsupervised): """ Task for information extraction from text in JSON format. """ + TASK_TYPE = TaskTypes.JSON_INFO_EXTRACTION.value @add_docstring_from(BaseUnsupervised.__init__) def __init__( self, - language, fields_description: dict, **kwargs, ) -> None: @@ -75,41 +75,17 @@ def __init__( >>> model.predict(text) """ - - kwargs["labels"] = None - kwargs["language"] = language kwargs["fields_description"] = fields_description - task_type = TaskTypes.JSON_INFO_EXTRACTION.value super(JSONInfoExtraction, self).__init__(**kwargs) - - self._builder = TaskBuilder( - language=self.language, - task_type=task_type, - verbose=self.verbose, - ) - - # Build model - self._builder.build_model( - model_name=self.model_name, - model_provider_name=self.model_provider_name, - model_provider_token=self.model_provider_token, - model_params=self.model_params, - ) - - # Building prompt - self._builder.build_prompt( - model_name=self.model_name, - prompt_domain=self.prompt_domain, - prompt_labels=self.prompt_labels, - prompt_detail=self.prompt_detail, - ) + # Setting the prompt description according to necessities prompt_detail = PromptTemplate.from_template(self.task.prompt.PROMPT_DETAIL) if len(set(prompt_detail.input_variables).intersection(set(["__FIELDS_DESCRIPTION__","__FIELDS__"]))) != 2: raise RuntimeError("Prompt file misses fields __FIELDS_DESCRIPTION__ or __FIELDS__") + # Building description to inject in the prompt description_fields_str = "\n".join([f"{i+1}. {description} ({field})" for i,field,description in zip(range(len(fields_description)), @@ -117,6 +93,7 @@ def __init__( prompt_detail = prompt_detail.format(__FIELDS__=",".join([i for i in fields_description.keys()]), __FIELDS_DESCRIPTION__=description_fields_str) + # Setting the prompt detail field self.prompt_detail = prompt_detail self._builder.build_prompt( model_name=self.model_name, @@ -125,13 +102,6 @@ def __init__( prompt_detail=self.prompt_detail, ) self.builder.task.prompt.PROMPT_DETAIL = prompt_detail - ## - # Build parser - self._builder.build_parser( - prompt_labels=self.prompt_labels, - ) - - diff --git a/promptmeteo/summarizer.py b/promptmeteo/summarizer.py index 93d192c..3423b7a 100644 --- a/promptmeteo/summarizer.py +++ b/promptmeteo/summarizer.py @@ -46,11 +46,11 @@ class Summarizer(BaseUnsupervised): """ Class for text summarization """ + TASK_TYPE = TaskTypes.SUMMARIZATION.value + @add_docstring_from(BaseUnsupervised.__init__) def __init__( self, - prompt_domain, - language, **kwargs, ) -> None: """ @@ -67,42 +67,8 @@ def __init__( >>> ) >>> model.predict([text]) """ - - kwargs["labels"] = None - kwargs["language"] = language - kwargs["prompt_domain"] = prompt_domain - - - task_type = TaskTypes.SUMMARIZATION.value super(Summarizer, self).__init__(**kwargs) - self._builder = TaskBuilder( - language=self.language, - task_type=task_type, - verbose=self.verbose, - ) - - # Build model - self._builder.build_model( - model_name=self.model_name, - model_provider_name=self.model_provider_name, - model_provider_token=self.model_provider_token, - model_params=self.model_params, - ) - - # Building prompt - self._builder.build_prompt( - model_name=self.model_name, - prompt_domain=self.prompt_domain, - prompt_labels=self.prompt_labels, - prompt_detail=self.prompt_detail, - ) - - ## - # Build parser - self._builder.build_parser( - prompt_labels=self.prompt_labels, - ) diff --git a/pyproject.toml b/pyproject.toml index 13d397d..fe5ee8d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,7 @@ dependencies = [ "pydantic == 1.10.11", "faiss-cpu == 1.7.4", "tiktoken==0.4.0", + "boto3==1.34.23" ] [tool.setuptools_scm] From a6192b4c25137097ee2a214fb7b485a4872a39b8 Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Wed, 31 Jan 2024 15:33:05 +0100 Subject: [PATCH 13/20] prompts added and readme --- README.md | 19 ++++++ ...thropic.claude-v2_en_classification.prompt | 61 +++++++++++++++++++ ...nthropic.claude-v2_en_summarization.prompt | 51 ++++++++++++++++ ...thropic.claude-v2_es_classification.prompt | 61 +++++++++++++++++++ 4 files changed, 192 insertions(+) create mode 100644 promptmeteo/prompts/anthropic.claude-v2_en_classification.prompt create mode 100644 promptmeteo/prompts/anthropic.claude-v2_en_summarization.prompt create mode 100644 promptmeteo/prompts/anthropic.claude-v2_es_classification.prompt diff --git a/README.md b/README.md index 903b224..8a42ced 100644 --- a/README.md +++ b/README.md @@ -204,7 +204,23 @@ HUGGINGFACEHUB_API_TOKEN="MY_HF_API_KEY" You can also pass `huggingfacehub_api_token` as a named parameter. +#### AWS Bedrock +Create your access keys in security credentials of your user in AWS. +Then write in the files ```~/.aws/config``` and ````~/.aws/credentials```` for Linux and MacOS or ````%USERPROFILE%\.aws\config```` and ````%USERPROFILE%\.aws\credentials```` for Windows: + +In credentials: +```shell +[default] +aws_access_key_id = +aws_secret_access_key = +``` + +In config: +```shell +[default] +region = +``` ### ⚙️ Install locally @@ -238,6 +254,7 @@ The current available tasks in Promptmeteo are: | `CodeGenerator` | Code generation | | `ApiGenerator` | API REST generation | | `ApiFormatter` | API REST correction | +| `Summarizer` | Text summarization | ### ✅ Available Model @@ -259,3 +276,5 @@ The current available `model_name` and `language` values are: | google | text-bison@001 | en | | google | text-bison-32k | es | | google | text-bison-32k | en | +| bedrock | anthropic.claude-v2 | en | +| bedrock | anthropic.claude-v2 | es | diff --git a/promptmeteo/prompts/anthropic.claude-v2_en_classification.prompt b/promptmeteo/prompts/anthropic.claude-v2_en_classification.prompt new file mode 100644 index 0000000..11bbfe9 --- /dev/null +++ b/promptmeteo/prompts/anthropic.claude-v2_en_classification.prompt @@ -0,0 +1,61 @@ +# Copyright (c) 2023 Paradigma Digital S.L. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + + +TEMPLATE: + "I need you to help me with a text classification task. + {__PROMPT_DOMAIN__} + {__PROMPT_LABELS__} + + {__CHAIN_THOUGHT__} + {__ANSWER_FORMAT__} + {__SHOT_EXAMPLES__} + {__PROMPT_SAMPLE__}" + + +PROMPT_DOMAIN: + "The texts you will be processing are from the {__DOMAIN__} domain." + + +PROMPT_LABELS: + "I want you to classify the texts into one of the following categories: + {__LABELS__}." + + +PROMPT_DETAIL: + "" + +SHOT_EXAMPLES: + "Examples:\n\n{__EXAMPLES__}" + +PROMPT_SAMPLE: + "\n\n{__SAMPLE__}\n" + +CHAIN_THOUGHT: + "Please provide a step-by-step argument for your answer, explain why you + believe your final choice is justified, and make sure to conclude your + explanation with the name of the class you have selected as the correct + one, in lowercase and without punctuation." + + +ANSWER_FORMAT: + "In your response, include only the name of the class as a single word, in + lowercase, without punctuation, and without adding any other statements or + words." diff --git a/promptmeteo/prompts/anthropic.claude-v2_en_summarization.prompt b/promptmeteo/prompts/anthropic.claude-v2_en_summarization.prompt new file mode 100644 index 0000000..5399512 --- /dev/null +++ b/promptmeteo/prompts/anthropic.claude-v2_en_summarization.prompt @@ -0,0 +1,51 @@ +# Copyright (c) 2023 Paradigma Digital S.L. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + + +TEMPLATE: + "Human: {__PROMPT_DOMAIN__} + {__PROMPT_SAMPLE__} + {__PROMPT_DETAIL__} + {__CHAIN_THOUGHT__} + {__ANSWER_FORMAT__}" + +PROMPT_SAMPLE: + " + \n\"{__SAMPLE__}\"\n + " + +PROMPT_DOMAIN: + "{__DOMAIN__}" + +PROMPT_DETAIL: + " + Based on the text segment, please build a precise summary and do not invent information. + + Assistant: Here is the summary: + " + +SHOT_EXAMPLES: + "" + +CHAIN_THOUGHT: + "" + +ANSWER_FORMAT: + "" diff --git a/promptmeteo/prompts/anthropic.claude-v2_es_classification.prompt b/promptmeteo/prompts/anthropic.claude-v2_es_classification.prompt new file mode 100644 index 0000000..11bbfe9 --- /dev/null +++ b/promptmeteo/prompts/anthropic.claude-v2_es_classification.prompt @@ -0,0 +1,61 @@ +# Copyright (c) 2023 Paradigma Digital S.L. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + + +TEMPLATE: + "I need you to help me with a text classification task. + {__PROMPT_DOMAIN__} + {__PROMPT_LABELS__} + + {__CHAIN_THOUGHT__} + {__ANSWER_FORMAT__} + {__SHOT_EXAMPLES__} + {__PROMPT_SAMPLE__}" + + +PROMPT_DOMAIN: + "The texts you will be processing are from the {__DOMAIN__} domain." + + +PROMPT_LABELS: + "I want you to classify the texts into one of the following categories: + {__LABELS__}." + + +PROMPT_DETAIL: + "" + +SHOT_EXAMPLES: + "Examples:\n\n{__EXAMPLES__}" + +PROMPT_SAMPLE: + "\n\n{__SAMPLE__}\n" + +CHAIN_THOUGHT: + "Please provide a step-by-step argument for your answer, explain why you + believe your final choice is justified, and make sure to conclude your + explanation with the name of the class you have selected as the correct + one, in lowercase and without punctuation." + + +ANSWER_FORMAT: + "In your response, include only the name of the class as a single word, in + lowercase, without punctuation, and without adding any other statements or + words." From c8056a75667c119a93ca737b51026fb5d902e02b Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Wed, 31 Jan 2024 16:08:42 +0100 Subject: [PATCH 14/20] Changes: prompts/base.py: - Change to allow to fill 'domain' field in prompt even if there is no 'prompt domain' param (same with prompt detail) - Removal of JSON info extraction task --- promptmeteo/__init__.py | 1 - promptmeteo/json_info_extraction.py | 191 ---------------------------- promptmeteo/prompts/base.py | 11 +- promptmeteo/tasks/task_builder.py | 1 - 4 files changed, 4 insertions(+), 200 deletions(-) delete mode 100644 promptmeteo/json_info_extraction.py diff --git a/promptmeteo/__init__.py b/promptmeteo/__init__.py index 61fe25c..8b9c6a7 100644 --- a/promptmeteo/__init__.py +++ b/promptmeteo/__init__.py @@ -4,5 +4,4 @@ from .document_classifier import DocumentClassifier from .api_generator import APIGenerator from .api_formatter import APIFormatter -from .json_info_extraction import JSONInfoExtraction from .summarizer import Summarizer \ No newline at end of file diff --git a/promptmeteo/json_info_extraction.py b/promptmeteo/json_info_extraction.py deleted file mode 100644 index 59fa951..0000000 --- a/promptmeteo/json_info_extraction.py +++ /dev/null @@ -1,191 +0,0 @@ -#%% -#!/usr/bin/python3 -# Copyright (c) 2023 Paradigma Digital S.L. - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -import re -import tarfile -import tempfile -import json -import os - -import yaml -from copy import deepcopy -from typing import List - -try: - from typing import Self -except ImportError: - from typing_extensions import Self -from langchain.prompts import PromptTemplate - -from .base import BaseUnsupervised -from .tasks import TaskTypes, TaskBuilder -from .tools import add_docstring_from -from .validations import version_validation - - -class JSONInfoExtraction(BaseUnsupervised): - - """ - Task for information extraction from text in JSON format. - """ - TASK_TYPE = TaskTypes.JSON_INFO_EXTRACTION.value - - @add_docstring_from(BaseUnsupervised.__init__) - def __init__( - self, - fields_description: dict, - **kwargs, - ) -> None: - """ - Example - ------- - - >>> from promptmeteo import JSONInfoExtraction - - >>> model = JSONInfoExtraction( - >>> language="es", - >>> fields_description = { - >>> "topic":"Motivo de la llamada", - >>> "sentiment":"Sentimiento del cliente", - >>> "summary":"Resumen de la llamada", - >>> "negative_tags":"Entidades y tópicos negativos en la llamada", - >>> "positive_tags":"Entidades y tópicos positivos en la llamada" - >>> }, - >>> model_name = "anthropic.claude-v2", - >>> model_provider_name = "bedrock" - >>> ) - - >>> model.predict(text) - """ - kwargs["fields_description"] = fields_description - - super(JSONInfoExtraction, self).__init__(**kwargs) - - - # Setting the prompt description according to necessities - prompt_detail = PromptTemplate.from_template(self.task.prompt.PROMPT_DETAIL) - if len(set(prompt_detail.input_variables).intersection(set(["__FIELDS_DESCRIPTION__","__FIELDS__"]))) != 2: - raise RuntimeError("Prompt file misses fields __FIELDS_DESCRIPTION__ or __FIELDS__") - - # Building description to inject in the prompt - description_fields_str = "\n".join([f"{i+1}. {description} ({field})" - for i,field,description in - zip(range(len(fields_description)), - fields_description.keys(), fields_description.values())]) - prompt_detail = prompt_detail.format(__FIELDS__=",".join([i for i in fields_description.keys()]), - __FIELDS_DESCRIPTION__=description_fields_str) - - # Setting the prompt detail field - self.prompt_detail = prompt_detail - self._builder.build_prompt( - model_name=self.model_name, - prompt_domain=self.prompt_domain, - prompt_labels=self.prompt_labels, - prompt_detail=self.prompt_detail, - ) - self.builder.task.prompt.PROMPT_DETAIL = prompt_detail - - - - @add_docstring_from(BaseUnsupervised.train) - def train( - self, - ) -> Self: - """ - Train the APIFormatter to extract entities anda parameteres. - - Parameters - ---------- - - api_codes : List[str] - - - Returns - ------- - - self - - """ - super(JSONInfoExtraction, self).train(examples=[""]) - - return self - - @classmethod - @add_docstring_from(BaseUnsupervised.load_model) - def load_model( - cls, - model_path: str, - ) -> Self: - """ - Loads a model artifact to make new predictions. - - Parameters - ---------- - - model_path : str - - - Returns - ------- - - self : Promptmeteo - - """ - - model_dir = os.path.dirname(model_path) - model_name = os.path.basename(model_path) - - if not model_name.endswith(".meteo"): - raise ValueError( - f"{cls.__name__} error in `load_model()`. " - f'model_path="{model_path}" has a bad model name extension. ' - f"Model name must end with `.meteo` (i.e. `./model.meteo`)" - ) - - if not os.path.exists(model_path): - raise ValueError( - f"{cls.__name__} error in `load_model()`. " - f"directory {model_dir} does not exists." - ) - - with tempfile.TemporaryDirectory() as tmp: - with tarfile.open(model_path, "r:gz") as tar: - tar.extractall(tmp) - - init_tmp_path = os.path.join( - tmp, f"{os.path.splitext(model_name)[0]}.init" - ) - - with open(init_tmp_path) as f_init: - params = json.load(f_init) - - self = cls(**params) - - self.builder.build_selector_by_load( - model_path=os.path.join(tmp, model_name), - selector_type=self.SELECTOR_TYPE, - selector_k=self._selector_k, - selector_algorithm=self._selector_algorithm, - ) - - self._is_trained = True - - return self diff --git a/promptmeteo/prompts/base.py b/promptmeteo/prompts/base.py index 44c1fd3..26b28c9 100644 --- a/promptmeteo/prompts/base.py +++ b/promptmeteo/prompts/base.py @@ -189,15 +189,12 @@ def run( prompt_variables["__PROMPT_LABELS__"] = ( self.PROMPT_LABELS.format(__LABELS__=prompt_labels) if self._prompt_labels - else "" + else self.PROMPT_LABELS ) # Domain - prompt_variables["__PROMPT_DOMAIN__"] = ( - self.PROMPT_DOMAIN.format(__DOMAIN__=self._prompt_domain) - if self._prompt_domain - else "" - ) + prompt_variables["__PROMPT_DOMAIN__"] = self.PROMPT_DOMAIN.format(__DOMAIN__=self._prompt_domain) + # Detail prompt_detail = ( @@ -208,7 +205,7 @@ def run( prompt_variables["__PROMPT_DETAIL__"] = ( self.PROMPT_DETAIL.format(__DETAIL__=prompt_detail) if self._prompt_detail - else "" + else self.PROMPT_DETAIL ) return PromptTemplate.from_template( diff --git a/promptmeteo/tasks/task_builder.py b/promptmeteo/tasks/task_builder.py index a465c1a..36cec4f 100644 --- a/promptmeteo/tasks/task_builder.py +++ b/promptmeteo/tasks/task_builder.py @@ -50,7 +50,6 @@ class TaskTypes(str, Enum): CODE_GENERATION: str = "code-generation" API_GENERATION: str = "api-generation" API_CORRECTION: str = "api-correction" - JSON_INFO_EXTRACTION: str = "json-info-extraction" SUMMARIZATION: str = "summarization" From b558313c193ce862812b92a18f480a6d59a55303 Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Wed, 31 Jan 2024 16:16:39 +0100 Subject: [PATCH 15/20] Changes in vocabulary in prompts and minor bug in prompts/base --- promptmeteo/prompts/base.py | 2 +- promptmeteo/prompts/fake-static_es_classification.prompt | 2 +- promptmeteo/prompts/fake-static_es_ner.prompt | 2 +- .../prompts/google-flan-t5-small_es_classification.prompt | 2 +- promptmeteo/prompts/google-flan-t5-small_es_ner.prompt | 2 +- promptmeteo/prompts/google-flan-t5-xxl_es_classification.prompt | 2 +- promptmeteo/prompts/google-flan-t5-xxl_es_ner.prompt | 2 +- .../prompts/gpt-3.5-turbo-instruct_es_classification.prompt | 2 +- promptmeteo/prompts/text-bison-32k_es_classification.prompt | 2 +- promptmeteo/prompts/text-bison-32k_es_ner.prompt | 2 +- promptmeteo/prompts/text-bison@001_es_classification.prompt | 2 +- promptmeteo/prompts/text-bison@001_es_ner.prompt | 2 +- promptmeteo/prompts/text-bison_es_classification.prompt | 2 +- promptmeteo/prompts/text-bison_es_ner.prompt | 2 +- promptmeteo/prompts/text-davinci-003_es_ner.prompt | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/promptmeteo/prompts/base.py b/promptmeteo/prompts/base.py index 26b28c9..c6533cf 100644 --- a/promptmeteo/prompts/base.py +++ b/promptmeteo/prompts/base.py @@ -189,7 +189,7 @@ def run( prompt_variables["__PROMPT_LABELS__"] = ( self.PROMPT_LABELS.format(__LABELS__=prompt_labels) if self._prompt_labels - else self.PROMPT_LABELS + else "" ) # Domain diff --git a/promptmeteo/prompts/fake-static_es_classification.prompt b/promptmeteo/prompts/fake-static_es_classification.prompt index cf59492..2df720b 100644 --- a/promptmeteo/prompts/fake-static_es_classification.prompt +++ b/promptmeteo/prompts/fake-static_es_classification.prompt @@ -31,7 +31,7 @@ TEMPLATE: PROMPT_DOMAIN: - "Los textos que vas procesar del ambito de {__DOMAIN__}." + "Los textos que vas procesar del ámbito de {__DOMAIN__}." PROMPT_LABELS: diff --git a/promptmeteo/prompts/fake-static_es_ner.prompt b/promptmeteo/prompts/fake-static_es_ner.prompt index 16c3eea..c2c11bd 100644 --- a/promptmeteo/prompts/fake-static_es_ner.prompt +++ b/promptmeteo/prompts/fake-static_es_ner.prompt @@ -29,7 +29,7 @@ TEMPLATE: PROMPT_DOMAIN: - "Los textos que vas procesar del ambito de {__DOMAIN__}." + "Los textos que vas procesar del ámbito de {__DOMAIN__}." PROMPT_LABELS: diff --git a/promptmeteo/prompts/google-flan-t5-small_es_classification.prompt b/promptmeteo/prompts/google-flan-t5-small_es_classification.prompt index 42eb520..65df7e4 100644 --- a/promptmeteo/prompts/google-flan-t5-small_es_classification.prompt +++ b/promptmeteo/prompts/google-flan-t5-small_es_classification.prompt @@ -31,7 +31,7 @@ TEMPLATE: PROMPT_DOMAIN: - "Los textos que vas procesar del ambito de {__DOMAIN__}." + "Los textos que vas procesar del ámbito de {__DOMAIN__}." PROMPT_LABELS: diff --git a/promptmeteo/prompts/google-flan-t5-small_es_ner.prompt b/promptmeteo/prompts/google-flan-t5-small_es_ner.prompt index a5a08af..8dbe0fd 100644 --- a/promptmeteo/prompts/google-flan-t5-small_es_ner.prompt +++ b/promptmeteo/prompts/google-flan-t5-small_es_ner.prompt @@ -29,7 +29,7 @@ TEMPLATE: PROMPT_DOMAIN: - "Los textos que vas procesar del ambito de {__DOMAIN__}." + "Los textos que vas procesar del ámbito de {__DOMAIN__}." PROMPT_LABELS: diff --git a/promptmeteo/prompts/google-flan-t5-xxl_es_classification.prompt b/promptmeteo/prompts/google-flan-t5-xxl_es_classification.prompt index c2f0018..00360c0 100644 --- a/promptmeteo/prompts/google-flan-t5-xxl_es_classification.prompt +++ b/promptmeteo/prompts/google-flan-t5-xxl_es_classification.prompt @@ -31,7 +31,7 @@ TEMPLATE: PROMPT_DOMAIN: - "Los textos que vas procesar del ambito de {__DOMAIN__}." + "Los textos que vas procesar del ámbito de {__DOMAIN__}." PROMPT_LABELS: diff --git a/promptmeteo/prompts/google-flan-t5-xxl_es_ner.prompt b/promptmeteo/prompts/google-flan-t5-xxl_es_ner.prompt index 16c3eea..c2c11bd 100644 --- a/promptmeteo/prompts/google-flan-t5-xxl_es_ner.prompt +++ b/promptmeteo/prompts/google-flan-t5-xxl_es_ner.prompt @@ -29,7 +29,7 @@ TEMPLATE: PROMPT_DOMAIN: - "Los textos que vas procesar del ambito de {__DOMAIN__}." + "Los textos que vas procesar del ámbito de {__DOMAIN__}." PROMPT_LABELS: diff --git a/promptmeteo/prompts/gpt-3.5-turbo-instruct_es_classification.prompt b/promptmeteo/prompts/gpt-3.5-turbo-instruct_es_classification.prompt index c2f0018..00360c0 100644 --- a/promptmeteo/prompts/gpt-3.5-turbo-instruct_es_classification.prompt +++ b/promptmeteo/prompts/gpt-3.5-turbo-instruct_es_classification.prompt @@ -31,7 +31,7 @@ TEMPLATE: PROMPT_DOMAIN: - "Los textos que vas procesar del ambito de {__DOMAIN__}." + "Los textos que vas procesar del ámbito de {__DOMAIN__}." PROMPT_LABELS: diff --git a/promptmeteo/prompts/text-bison-32k_es_classification.prompt b/promptmeteo/prompts/text-bison-32k_es_classification.prompt index c2f0018..00360c0 100644 --- a/promptmeteo/prompts/text-bison-32k_es_classification.prompt +++ b/promptmeteo/prompts/text-bison-32k_es_classification.prompt @@ -31,7 +31,7 @@ TEMPLATE: PROMPT_DOMAIN: - "Los textos que vas procesar del ambito de {__DOMAIN__}." + "Los textos que vas procesar del ámbito de {__DOMAIN__}." PROMPT_LABELS: diff --git a/promptmeteo/prompts/text-bison-32k_es_ner.prompt b/promptmeteo/prompts/text-bison-32k_es_ner.prompt index 16c3eea..c2c11bd 100644 --- a/promptmeteo/prompts/text-bison-32k_es_ner.prompt +++ b/promptmeteo/prompts/text-bison-32k_es_ner.prompt @@ -29,7 +29,7 @@ TEMPLATE: PROMPT_DOMAIN: - "Los textos que vas procesar del ambito de {__DOMAIN__}." + "Los textos que vas procesar del ámbito de {__DOMAIN__}." PROMPT_LABELS: diff --git a/promptmeteo/prompts/text-bison@001_es_classification.prompt b/promptmeteo/prompts/text-bison@001_es_classification.prompt index 1680e8b..874738e 100644 --- a/promptmeteo/prompts/text-bison@001_es_classification.prompt +++ b/promptmeteo/prompts/text-bison@001_es_classification.prompt @@ -30,7 +30,7 @@ TEMPLATE: {__PROMPT_SAMPLE__}" PROMPT_DOMAIN: - "Los textos que vas procesar del ambito de {__DOMAIN__}." + "Los textos que vas procesar del ámbito de {__DOMAIN__}." PROMPT_LABELS: diff --git a/promptmeteo/prompts/text-bison@001_es_ner.prompt b/promptmeteo/prompts/text-bison@001_es_ner.prompt index 16c3eea..c2c11bd 100644 --- a/promptmeteo/prompts/text-bison@001_es_ner.prompt +++ b/promptmeteo/prompts/text-bison@001_es_ner.prompt @@ -29,7 +29,7 @@ TEMPLATE: PROMPT_DOMAIN: - "Los textos que vas procesar del ambito de {__DOMAIN__}." + "Los textos que vas procesar del ámbito de {__DOMAIN__}." PROMPT_LABELS: diff --git a/promptmeteo/prompts/text-bison_es_classification.prompt b/promptmeteo/prompts/text-bison_es_classification.prompt index cf59492..2df720b 100644 --- a/promptmeteo/prompts/text-bison_es_classification.prompt +++ b/promptmeteo/prompts/text-bison_es_classification.prompt @@ -31,7 +31,7 @@ TEMPLATE: PROMPT_DOMAIN: - "Los textos que vas procesar del ambito de {__DOMAIN__}." + "Los textos que vas procesar del ámbito de {__DOMAIN__}." PROMPT_LABELS: diff --git a/promptmeteo/prompts/text-bison_es_ner.prompt b/promptmeteo/prompts/text-bison_es_ner.prompt index 16c3eea..c2c11bd 100644 --- a/promptmeteo/prompts/text-bison_es_ner.prompt +++ b/promptmeteo/prompts/text-bison_es_ner.prompt @@ -29,7 +29,7 @@ TEMPLATE: PROMPT_DOMAIN: - "Los textos que vas procesar del ambito de {__DOMAIN__}." + "Los textos que vas procesar del ámbito de {__DOMAIN__}." PROMPT_LABELS: diff --git a/promptmeteo/prompts/text-davinci-003_es_ner.prompt b/promptmeteo/prompts/text-davinci-003_es_ner.prompt index 16c3eea..c2c11bd 100644 --- a/promptmeteo/prompts/text-davinci-003_es_ner.prompt +++ b/promptmeteo/prompts/text-davinci-003_es_ner.prompt @@ -29,7 +29,7 @@ TEMPLATE: PROMPT_DOMAIN: - "Los textos que vas procesar del ambito de {__DOMAIN__}." + "Los textos que vas procesar del ámbito de {__DOMAIN__}." PROMPT_LABELS: From abac53b7f38c9141763321fa05c68184a40d70ee Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Wed, 31 Jan 2024 16:50:20 +0100 Subject: [PATCH 16/20] Minor changes in prompt/base, new words added to spanish dictionary and .prompts modification --- ...thropic.claude-v2_es_classification.prompt | 18 +++---- ...c.claude-v2_es_json-info-extraction.prompt | 53 ------------------- promptmeteo/prompts/base.py | 7 +-- ...5-turbo-16k_en_json-info-extraction.prompt | 51 ------------------ ...5-turbo-16k_es_json-info-extraction.prompt | 51 ------------------ tests/tools/dictionary_checker.py | 2 +- 6 files changed, 10 insertions(+), 172 deletions(-) delete mode 100644 promptmeteo/prompts/anthropic.claude-v2_es_json-info-extraction.prompt delete mode 100644 promptmeteo/prompts/gpt-3.5-turbo-16k_en_json-info-extraction.prompt delete mode 100644 promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-info-extraction.prompt diff --git a/promptmeteo/prompts/anthropic.claude-v2_es_classification.prompt b/promptmeteo/prompts/anthropic.claude-v2_es_classification.prompt index 11bbfe9..65df7e4 100644 --- a/promptmeteo/prompts/anthropic.claude-v2_es_classification.prompt +++ b/promptmeteo/prompts/anthropic.claude-v2_es_classification.prompt @@ -20,7 +20,7 @@ TEMPLATE: - "I need you to help me with a text classification task. + "Necesito que me ayudes en una tarea de clasificación de texto. {__PROMPT_DOMAIN__} {__PROMPT_LABELS__} @@ -31,11 +31,11 @@ TEMPLATE: PROMPT_DOMAIN: - "The texts you will be processing are from the {__DOMAIN__} domain." + "Los textos que vas procesar del ámbito de {__DOMAIN__}." PROMPT_LABELS: - "I want you to classify the texts into one of the following categories: + "Quiero que me clasifiques los textos una de las siguientes categorías: {__LABELS__}." @@ -43,19 +43,15 @@ PROMPT_DETAIL: "" SHOT_EXAMPLES: - "Examples:\n\n{__EXAMPLES__}" + "Ejemplos:\n\n{__EXAMPLES__}" PROMPT_SAMPLE: "\n\n{__SAMPLE__}\n" CHAIN_THOUGHT: - "Please provide a step-by-step argument for your answer, explain why you - believe your final choice is justified, and make sure to conclude your - explanation with the name of the class you have selected as the correct - one, in lowercase and without punctuation." + "" ANSWER_FORMAT: - "In your response, include only the name of the class as a single word, in - lowercase, without punctuation, and without adding any other statements or - words." + "En tu respuesta incluye sólo el nombre de la clase, como una única + palabra." diff --git a/promptmeteo/prompts/anthropic.claude-v2_es_json-info-extraction.prompt b/promptmeteo/prompts/anthropic.claude-v2_es_json-info-extraction.prompt deleted file mode 100644 index 0c4c060..0000000 --- a/promptmeteo/prompts/anthropic.claude-v2_es_json-info-extraction.prompt +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2023 Paradigma Digital S.L. - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - - -TEMPLATE: - "Human: {__PROMPT_DOMAIN__} - {__PROMPT_SAMPLE__} - {__PROMPT_DETAIL__} - {__CHAIN_THOUGHT__} - {__ANSWER_FORMAT__}" - -PROMPT_SAMPLE: - "Dado el texto: - - \n\"{__SAMPLE__}\"\n - " - -PROMPT_DOMAIN: - "" - -PROMPT_DETAIL: - " - extrae la información en formato json donde tendremos los siguientes campos ({__FIELDS__}):\n - {__FIELDS_DESCRIPTION__} - - Assistant: A continuación el JSON obtenido: - " - -SHOT_EXAMPLES: - "" - -CHAIN_THOUGHT: - "" - -ANSWER_FORMAT: - "" diff --git a/promptmeteo/prompts/base.py b/promptmeteo/prompts/base.py index c6533cf..2f7f155 100644 --- a/promptmeteo/prompts/base.py +++ b/promptmeteo/prompts/base.py @@ -202,11 +202,8 @@ def run( if isinstance(self._prompt_detail, list) else self._prompt_detail ) - prompt_variables["__PROMPT_DETAIL__"] = ( - self.PROMPT_DETAIL.format(__DETAIL__=prompt_detail) - if self._prompt_detail - else self.PROMPT_DETAIL - ) + prompt_variables["__PROMPT_DETAIL__"] = self.PROMPT_DETAIL.format(__DETAIL__=prompt_detail) + return PromptTemplate.from_template( PromptTemplate.from_template(self.TEMPLATE).format( diff --git a/promptmeteo/prompts/gpt-3.5-turbo-16k_en_json-info-extraction.prompt b/promptmeteo/prompts/gpt-3.5-turbo-16k_en_json-info-extraction.prompt deleted file mode 100644 index f1b483d..0000000 --- a/promptmeteo/prompts/gpt-3.5-turbo-16k_en_json-info-extraction.prompt +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (c) 2023 Paradigma Digital S.L. - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - - -TEMPLATE: - "{__PROMPT_DOMAIN__} - {__PROMPT_SAMPLE__} - {__PROMPT_DETAIL__} - {__CHAIN_THOUGHT__} - {__ANSWER_FORMAT__}" - -PROMPT_SAMPLE: - "Given the text: - - ```\n{__SAMPLE__}\n``` - " - -PROMPT_DOMAIN: - "" - -PROMPT_DETAIL: - " - extract the information in JSON format, where we will have the following fields ({__FIELDS__}):\n - {__FIELDS_DESCRIPTION__} - " - -SHOT_EXAMPLES: - "" - -CHAIN_THOUGHT: - "" - -ANSWER_FORMAT: - "" diff --git a/promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-info-extraction.prompt b/promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-info-extraction.prompt deleted file mode 100644 index fa03e4e..0000000 --- a/promptmeteo/prompts/gpt-3.5-turbo-16k_es_json-info-extraction.prompt +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (c) 2023 Paradigma Digital S.L. - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - - -TEMPLATE: - "{__PROMPT_DOMAIN__} - {__PROMPT_SAMPLE__} - {__PROMPT_DETAIL__} - {__CHAIN_THOUGHT__} - {__ANSWER_FORMAT__}" - -PROMPT_SAMPLE: - "Dado el texto: - - \n\"{__SAMPLE__}\"\n - " - -PROMPT_DOMAIN: - "" - -PROMPT_DETAIL: - " - extrae la información en formato json donde tendremos los siguientes campos ({__FIELDS__}):\n - {__FIELDS_DESCRIPTION__} - " - -SHOT_EXAMPLES: - "" - -CHAIN_THOUGHT: - "" - -ANSWER_FORMAT: - "" diff --git a/tests/tools/dictionary_checker.py b/tests/tools/dictionary_checker.py index e2fe023..977e8e8 100644 --- a/tests/tools/dictionary_checker.py +++ b/tests/tools/dictionary_checker.py @@ -9,7 +9,7 @@ class DictionaryChecker: ADDED_WORDS = { "en": {"openapi": 1, "api": 1, "schema": 1, "schemas": 1}, - "es": {"openapi": 1, "api": 1, "sample":1, "examples":1}, + "es": {"openapi": 1, "api": 1, "sample":1, "examples":1, "generes":1, "human":1, "assistant":1}, } def __init__(self, language: str): From 06cd54500565087f032bcabd1ac0eb42944b702e Mon Sep 17 00:00:00 2001 From: Bea Date: Fri, 2 Feb 2024 14:11:47 +0100 Subject: [PATCH 17/20] api_formatter no changes --- promptmeteo/api_formatter.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/promptmeteo/api_formatter.py b/promptmeteo/api_formatter.py index 93fb633..c55ce86 100644 --- a/promptmeteo/api_formatter.py +++ b/promptmeteo/api_formatter.py @@ -1,4 +1,5 @@ #!/usr/bin/python3 + # Copyright (c) 2023 Paradigma Digital S.L. # Permission is hereby granted, free of charge, to any person obtaining a copy @@ -36,7 +37,7 @@ from typing_extensions import Self from .base import BaseUnsupervised -from .tasks import TaskTypes, TaskBuilder +from .tasks import TaskTypes from .tools import add_docstring_from from .validations import version_validation @@ -264,10 +265,7 @@ def predict(self, api_codes: List[str], external_info: dict) -> List[str]: ---------- api_codes : List[str] -<<<<<<< HEAD external_info: dict -======= ->>>>>>> 8ceaf0d ([Feature: New model] API Generation (#6)) Returns @@ -384,4 +382,4 @@ def replace_values(orig_dict, replace_dict): sort_keys=False, ) - return api + return api \ No newline at end of file From e8c02c15e0f2c023cd7d1548b52a6ec3881a0eb4 Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Thu, 8 Feb 2024 16:06:49 +0100 Subject: [PATCH 18/20] Changes: - Added in BedrockLLM model the option of kwargs argument to allow to select different arguments for boto3 client - Change in test for models the region argument --- promptmeteo/models/bedrock.py | 6 +++--- tests/test_models.py | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/promptmeteo/models/bedrock.py b/promptmeteo/models/bedrock.py index bca4022..abc9be2 100644 --- a/promptmeteo/models/bedrock.py +++ b/promptmeteo/models/bedrock.py @@ -65,7 +65,6 @@ class AnthropicClaudeV2: client = Bedrock embedding = HuggingFaceEmbeddings - boto3_bedrock = boto3.client('bedrock-runtime', region_name="us-east-1") model_task: str = "text2text-generation" params: dict = { 'max_tokens_to_sample': 2048, @@ -87,6 +86,7 @@ def __init__( model_name: Optional[str] = "", model_params: Optional[Dict] = None, model_provider_token: Optional[str] = "", + **kwargs ) -> None: """ Make predictions using a model from OpenAI. @@ -98,7 +98,7 @@ def __init__( f"`model_name`={model_name} not in supported model names: " f"{[i.name for i in ModelTypes]}" ) - + boto3_bedrock = boto3.client('bedrock-runtime', **kwargs) super(BedrockLLM, self).__init__() # Model name @@ -117,7 +117,7 @@ def __init__( self._llm = ModelEnum[model].value.client( model_id=model_name, model_kwargs=self.model_params, - client = ModelEnum[model].value.boto3_bedrock + client = boto3_bedrock ) embedding_name = "sentence-transformers/all-MiniLM-L6-v2" diff --git a/tests/test_models.py b/tests/test_models.py index a1e6897..7e2622b 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -73,7 +73,8 @@ def test_model_bedrock(self): BedrockLLM( model_name="WRONG_NAME", model_params={}, - model_provider_token="TEST_TOKEN" + model_provider_token="TEST_TOKEN", + region_name="us-east-1" ) invalid_provider = ( From ef0b24bc64b6ecdd2451b88be6de8da2f4eade50 Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Thu, 8 Feb 2024 16:24:58 +0100 Subject: [PATCH 19/20] minor error in test model --- tests/test_models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_models.py b/tests/test_models.py index 7e2622b..11c35fd 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -66,7 +66,8 @@ def test_model_bedrock(self): BedrockLLM( model_name=model_name.value, model_params={}, - model_provider_token="TEST_TOKEN" + model_provider_token="TEST_TOKEN", + region_name="us-east-1" ) with pytest.raises(ValueError) as error: From c38181b5546ec24a12622c34056c047b60a649b8 Mon Sep 17 00:00:00 2001 From: Miguel Lopez Date: Tue, 13 Feb 2024 08:52:27 +0100 Subject: [PATCH 20/20] minor --- promptmeteo/models/bedrock.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/promptmeteo/models/bedrock.py b/promptmeteo/models/bedrock.py index abc9be2..6536d13 100644 --- a/promptmeteo/models/bedrock.py +++ b/promptmeteo/models/bedrock.py @@ -98,7 +98,7 @@ def __init__( f"`model_name`={model_name} not in supported model names: " f"{[i.name for i in ModelTypes]}" ) - boto3_bedrock = boto3.client('bedrock-runtime', **kwargs) + self.boto3_bedrock = boto3.client('bedrock-runtime', **kwargs) super(BedrockLLM, self).__init__() # Model name @@ -117,7 +117,7 @@ def __init__( self._llm = ModelEnum[model].value.client( model_id=model_name, model_kwargs=self.model_params, - client = boto3_bedrock + client = self.boto3_bedrock ) embedding_name = "sentence-transformers/all-MiniLM-L6-v2"