├── .github ├── scripts │ ├── generate_datasets_table.py │ └── reorder_table_columns.py └── workflows │ └── readme-generation.yml ├── README.md ├── aplicaciones_de_los_transformers.ipynb ├── cuantizacion └── GPT_J_6B_8bit_ES.ipynb ├── datasets.csv ├── grupo_de_estudio ├── README.md └── nlp_con_transformers_1.pdf ├── hackathon_2022 ├── README.md ├── analisis_error_modelos_nlp_omar_sanseviero.pdf ├── lxai_nlp_extended_abstract_javier_turek.pdf └── nlp_lenguas_minorizadas_mx_ximena_gutierrez.pdf ├── hackathon_2023 └── README.md ├── hackathon_2024 ├── creacion_de_datasets_sinteticos_con_distilabel.ipynb ├── distilabel_y_argilla_creacion_datasets_para_sft_y_dpo.ipynb ├── entrenamiento_llm_instrucciones.ipynb ├── entrenar_con_datos_de_calidad.ipynb ├── fine_tune_gemma_2b_on_openhermes_using_qlora.ipynb ├── taller_distilabel_y_argilla.ipynb └── taller_escritura_abstracts_lxai_naacl.pdf ├── plantillas_docs_proyectos ├── README.md ├── dataset_card.md ├── estructura_corpus.md └── model_card.md └── proyectos_de_la_comunidad └── 2023_01_12_biomedia.pdf /.github/scripts/generate_datasets_table.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | df = pd.read_csv("datasets.csv") 4 | 5 | # Sort the DataFrame by the "nombre" column and save it 6 | df.sort_values(by="nombre", inplace=True) 7 | df.to_csv("datasets.csv", index=False) 8 | 9 | # Generate the datasets table 10 | table_content = df.to_markdown(index=False) 11 | 12 | with open("README.md", "r") as f: 13 | readme_template = f.read() 14 | 15 | start_delimiter = "" 16 | end_delimiter = "" 17 | 18 | start_pos = readme_template.find(start_delimiter) 19 | end_pos = readme_template.find(end_delimiter) 20 | 21 | updated_readme_content = ( 22 | readme_template[:start_pos + len(start_delimiter)] 23 | + "\n" + table_content + "\n" 24 | + readme_template[end_pos:] 25 | ) 26 | 27 | with open("README.md", "w") as f: 28 | f.write(updated_readme_content) 29 | -------------------------------------------------------------------------------- /.github/scripts/reorder_table_columns.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import pandas as pd 3 | 4 | FILE_NAME = "datasets.csv" 5 | 6 | 7 | def reorder_columns(original_index, final_index, file_name=FILE_NAME): 8 | df = pd.read_csv(file_name) 9 | 10 | if final_index < 0 or original_index < 0 or final_index >= df.shape[1] or original_index >= df.shape[1]: 11 | print("Invalid column index specified.") 12 | else: 13 | columns_except_original = [col for col in df.columns if col != df.columns[original_index]] 14 | 15 | new_columns = ( 16 | columns_except_original[:final_index] + 17 | [df.columns[original_index]] + 18 | columns_except_original[final_index:] 19 | ) 20 | 21 | df_reordered = df[new_columns] 22 | 23 | df_reordered.to_csv(file_name, index=False) 24 | 25 | print("Columns reordered successfully.") 26 | 27 | 28 | if __name__ == "__main__": 29 | parser = argparse.ArgumentParser(description="Reorder columns in a CSV file.") 30 | parser.add_argument("original_index", type=int, help="Original column index") 31 | parser.add_argument("final_index", type=int, help="Final column index") 32 | 33 | args = parser.parse_args() 34 | 35 | reorder_columns(args.original_index, args.final_index) 36 | -------------------------------------------------------------------------------- /.github/workflows/readme-generation.yml: -------------------------------------------------------------------------------- 1 | name: Generate README on datasets.csv file update 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | paths: 8 | - "datasets.csv" 9 | 10 | jobs: 11 | generate-readme: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - name: Check out repository 16 | uses: actions/checkout@v2 17 | 18 | - name: Set up Python 19 | uses: actions/setup-python@v2 20 | with: 21 | python-version: "3.x" 22 | 23 | - name: Install dependencies 24 | run: | 25 | pip install pandas tabulate 26 | 27 | - name: Reorder datasets.csv and generate README 28 | run: | 29 | python .github/scripts/generate_datasets_table.py 30 | 31 | - name: Commit and push changes 32 | run: | 33 | git config user.name "${{ github.actor }}" 34 | git config user.email "${{ github.actor }}@users.noreply.github.com" 35 | 36 | git add datasets.csv README.md 37 | git commit -m "docs: reorder datasets.csv and update datasets table" 38 | git push --force origin HEAD:${{ github.head_ref }} 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Recursos de PLN en Español 2 | 3 | En este repo encontrarás: 4 | 5 | - Datasets open-source: Lista de datasets abiertos de PLN en español (a continuación) 6 | - Hackathon Somos NLP [2022](https://github.com/somosnlp/recursos-nlp-es/tree/main/hackathon_2022) y [2023](https://github.com/somosnlp/recursos-nlp-es/tree/main/hackathon_2023): Diapositivas y notebooks de las charlas y talleres impartidas durante el mayor hackathon open-source de PLN en español 7 | - [Grupo de estudio](https://github.com/somosnlp/recursos-nlp-es/tree/main/grupo_de_estudio): Diapositivas y material del grupo de estudio, únete en el canal #grupo-de-estudio de Discord 8 | 9 | Tenemos también una sección de la página web dedicada a recursos de PLN: 10 | 11 | Si no encuentras lo que estás buscando te animamos a unirte a Discord y preguntar a la comunidad. Aquí tienes una [invitación](https://discord.com/invite/my8w7JUxZR). 12 | 13 | ## Datasets Open-Source 14 | 15 | - [Versión web](https://somosnlp.org/recursos/open-source/datasets) 16 | 17 | 18 | | nombre | tareas | dominio | idioma | pais | página_web | github | paper | hf_dataset_name | hf_contributor_handle | 19 | |:--------------------------------------------------|:-----------------------------------------------------|:-----------|:-------------------------|:-------|:-----------------------------------------------------|:---------------------------------------------------------|:-----------------------------------------------------------------------|:-----------------------|:------------------------| 20 | | BasCrawl | modelado del lenguaje | general | euskera | España | https://doi.org/10.5281/zenodo.7313092 | nan | nan | nan | nan | 21 | | Biomedical Spanish CBOW Word Embeddings in Floret | modelado del lenguaje,CBOW (Continuous Bag Of Words) | clinico | español | España | https://doi.org/10.5281/zenodo.7314041 | https://arxiv.org/abs/2109.07765 | nan | nan | nan | 22 | | CSIC Spanish Corpus | modelado del lenguaje | academico | español | España | https://doi.org/10.5281/zenodo.7313126 | nan | nan | nan | nan | 23 | | Catalonia Independence Corpus | clasificación de sentimientos | rrss | catalán, español | España | nan | https://github.com/ixa-ehu/catalonia-independence-corpus | https://www.aclweb.org/anthology/2020.lrec-1.171/ | catalonia_independence | lewtun | 24 | | HEAD-QA | preguntas de opción múltiple | clinico | español | España | https://aghie.github.io/head-qa/ | https://github.com/aghie/head-qa | https://www.aclweb.org/anthology/P19-1092/ | head_qa | mariagrandury | 25 | | InfoLibros Corpus | modelado del lenguaje | literatura | español | Varios | https://doi.org/10.5281/zenodo.7313105 | nan | nan | nan | nan | 26 | | Large Spanish Corpus | modelado del lenguaje,pre-entrenamiento | general | español | Varios | nan | https://github.com/josecannete/spanish-corpora | nan | large_spanish_corpus | lewtun | 27 | | Mucho Cine | clasificación de sentimientos | general | español | Varios | http://www.lsi.us.es/~fermin/index.php/Datasets | nan | nan | muchocine | mapmeld | 28 | | Spanish Billion Words | modelado del lenguaje,pre-entrenamiento | general | español | Varios | https://crscardellino.github.io/SBWCE/ | nan | nan | spanish_billion_words | mariagrandury | 29 | | Spanish Biomedical Crawled Corpus | modelado del lenguaje | clinico | español | España | https://doi.org/10.5281/zenodo.5513237 | nan | https://arxiv.org/abs/2109.07765 | nan | nan | 30 | | Spanish CBOW Word Embeddings in FastText | modelado del lenguaje,FastText | general | español | España | https://doi.org/10.5281/zenodo.5044988 | nan | http://journal.sepln.org/sepln/ojs/ojs/index.php/pln/article/view/6405 | nan | nan | 31 | | Spanish CBOW Word Embeddings in Floret | modelado del lenguaje,CBOW (Continuous Bag Of Words) | general | español | España | https://doi.org/10.5281/zenodo.7314098 | nan | nan | nan | nan | 32 | | Spanish Legal Domain Corpora | modelado del lenguaje | legal | español | España | https://doi.org/10.5281/zenodo.5495529 | https://github.com/PlanTL-GOB-ES/lm-legal-es | https://arxiv.org/abs/2110.12201 | nan | nan | 33 | | Spanish Legal Domain Word & Sub-Word Embeddings | modelado del lenguaje | legal | español | España | https://doi.org/10.5281/zenodo.5036147 | https://github.com/PlanTL-GOB-ES/lm-legal-es | https://arxiv.org/abs/2110.12201 | nan | nan | 34 | | Spanish Skip-Gram Word Embeddings in FastText | modelado del lenguaje,FastText | general | español | España | https://doi.org/10.5281/zenodo.5046525 | nan | http://journal.sepln.org/sepln/ojs/ojs/index.php/pln/article/view/6405 | nan | nan | 35 | | TDX Thesis Spanish Corpus | modelado del lenguaje | academico | catalán, español | España | https://doi.org/10.5281/zenodo.7313149 | nan | nan | nan | nan | 36 | | WikiCorpus | modelado del lenguaje,POS (Part of Speech) | general | catalán, español, inglés | Varios | https://www.cs.upc.edu/~nlp/wikicorpus/ | nan | https://www.cs.upc.edu/~nlp/papers/reese10.pdf | wikicorpus | albertvillanova | 37 | | eHealth-KD | reconocimiento de entidades nombradas (NER) | clinico | es | España | https://knowledge-learning.github.io/ehealthkd-2020/ | https://github.com/knowledge-learning/ehealthkd-2020 | http://ceur-ws.org/Vol-2664/eHealth-KD_overview.pdf | ehealth_kd | mariagrandury | 38 | 39 | -------------------------------------------------------------------------------- /cuantizacion/GPT_J_6B_8bit_ES.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "BERTIN-GPT-J-6B-ES-8bit.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "machine_shape": "hm", 10 | "include_colab_link": true 11 | }, 12 | "kernelspec": { 13 | "name": "python3", 14 | "display_name": "Python 3" 15 | }, 16 | "language_info": { 17 | "name": "python" 18 | }, 19 | "accelerator": "GPU", 20 | "widgets": { 21 | "application/vnd.jupyter.widget-state+json": { 22 | "3b354e5db9bb462dbc60e13a5302388b": { 23 | "model_module": "@jupyter-widgets/controls", 24 | "model_name": "HBoxModel", 25 | "model_module_version": "1.5.0", 26 | "state": { 27 | "_dom_classes": [], 28 | "_model_module": "@jupyter-widgets/controls", 29 | "_model_module_version": "1.5.0", 30 | "_model_name": "HBoxModel", 31 | "_view_count": null, 32 | "_view_module": "@jupyter-widgets/controls", 33 | "_view_module_version": "1.5.0", 34 | "_view_name": "HBoxView", 35 | "box_style": "", 36 | "children": [ 37 | "IPY_MODEL_cfc7dd89a25243519bbfdb3d1741f3b7", 38 | "IPY_MODEL_c9786564c94c400ba59befbeb2484718", 39 | "IPY_MODEL_b23669a67d5f4bfc8a3df6b82d0cc0fe" 40 | ], 41 | "layout": "IPY_MODEL_073e80247a2a46fda0d6d73175d374a2" 42 | } 43 | }, 44 | "cfc7dd89a25243519bbfdb3d1741f3b7": { 45 | "model_module": "@jupyter-widgets/controls", 46 | "model_name": "HTMLModel", 47 | "model_module_version": "1.5.0", 48 | "state": { 49 | "_dom_classes": [], 50 | "_model_module": "@jupyter-widgets/controls", 51 | "_model_module_version": "1.5.0", 52 | "_model_name": "HTMLModel", 53 | "_view_count": null, 54 | "_view_module": "@jupyter-widgets/controls", 55 | "_view_module_version": "1.5.0", 56 | "_view_name": "HTMLView", 57 | "description": "", 58 | "description_tooltip": null, 59 | "layout": "IPY_MODEL_7254d7f2f786449c8c6616244cd6e492", 60 | "placeholder": "​", 61 | "style": "IPY_MODEL_ef1d34c16b4e4f4291ac1c09bd217635", 62 | "value": "100%" 63 | } 64 | }, 65 | "c9786564c94c400ba59befbeb2484718": { 66 | "model_module": "@jupyter-widgets/controls", 67 | "model_name": "FloatProgressModel", 68 | "model_module_version": "1.5.0", 69 | "state": { 70 | "_dom_classes": [], 71 | "_model_module": "@jupyter-widgets/controls", 72 | "_model_module_version": "1.5.0", 73 | "_model_name": "FloatProgressModel", 74 | "_view_count": null, 75 | "_view_module": "@jupyter-widgets/controls", 76 | "_view_module_version": "1.5.0", 77 | "_view_name": "ProgressView", 78 | "bar_style": "success", 79 | "description": "", 80 | "description_tooltip": null, 81 | "layout": "IPY_MODEL_a6e8d510cd2d43bf97c99ca70c37bf3a", 82 | "max": 49, 83 | "min": 0, 84 | "orientation": "horizontal", 85 | "style": "IPY_MODEL_a59c626d9fbf43dd9edf77ce62f2b155", 86 | "value": 49 87 | } 88 | }, 89 | "b23669a67d5f4bfc8a3df6b82d0cc0fe": { 90 | "model_module": "@jupyter-widgets/controls", 91 | "model_name": "HTMLModel", 92 | "model_module_version": "1.5.0", 93 | "state": { 94 | "_dom_classes": [], 95 | "_model_module": "@jupyter-widgets/controls", 96 | "_model_module_version": "1.5.0", 97 | "_model_name": "HTMLModel", 98 | "_view_count": null, 99 | "_view_module": "@jupyter-widgets/controls", 100 | "_view_module_version": "1.5.0", 101 | "_view_name": "HTMLView", 102 | "description": "", 103 | "description_tooltip": null, 104 | "layout": "IPY_MODEL_2de45259c3f64ae7a1b98aa74ec629f6", 105 | "placeholder": "​", 106 | "style": "IPY_MODEL_f21ca1e656ff42648dcb0ba75484f3c6", 107 | "value": " 49/49 [13:12<00:00, 16.32s/it]" 108 | } 109 | }, 110 | "073e80247a2a46fda0d6d73175d374a2": { 111 | "model_module": "@jupyter-widgets/base", 112 | "model_name": "LayoutModel", 113 | "model_module_version": "1.2.0", 114 | "state": { 115 | "_model_module": "@jupyter-widgets/base", 116 | "_model_module_version": "1.2.0", 117 | "_model_name": "LayoutModel", 118 | "_view_count": null, 119 | "_view_module": "@jupyter-widgets/base", 120 | "_view_module_version": "1.2.0", 121 | "_view_name": "LayoutView", 122 | "align_content": null, 123 | "align_items": null, 124 | "align_self": null, 125 | "border": null, 126 | "bottom": null, 127 | "display": null, 128 | "flex": null, 129 | "flex_flow": null, 130 | "grid_area": null, 131 | "grid_auto_columns": null, 132 | "grid_auto_flow": null, 133 | "grid_auto_rows": null, 134 | "grid_column": null, 135 | "grid_gap": null, 136 | "grid_row": null, 137 | "grid_template_areas": null, 138 | "grid_template_columns": null, 139 | "grid_template_rows": null, 140 | "height": null, 141 | "justify_content": null, 142 | "justify_items": null, 143 | "left": null, 144 | "margin": null, 145 | "max_height": null, 146 | "max_width": null, 147 | "min_height": null, 148 | "min_width": null, 149 | "object_fit": null, 150 | "object_position": null, 151 | "order": null, 152 | "overflow": null, 153 | "overflow_x": null, 154 | "overflow_y": null, 155 | "padding": null, 156 | "right": null, 157 | "top": null, 158 | "visibility": null, 159 | "width": null 160 | } 161 | }, 162 | "7254d7f2f786449c8c6616244cd6e492": { 163 | "model_module": "@jupyter-widgets/base", 164 | "model_name": "LayoutModel", 165 | "model_module_version": "1.2.0", 166 | "state": { 167 | "_model_module": "@jupyter-widgets/base", 168 | "_model_module_version": "1.2.0", 169 | "_model_name": "LayoutModel", 170 | "_view_count": null, 171 | "_view_module": "@jupyter-widgets/base", 172 | "_view_module_version": "1.2.0", 173 | "_view_name": "LayoutView", 174 | "align_content": null, 175 | "align_items": null, 176 | "align_self": null, 177 | "border": null, 178 | "bottom": null, 179 | "display": null, 180 | "flex": null, 181 | "flex_flow": null, 182 | "grid_area": null, 183 | "grid_auto_columns": null, 184 | "grid_auto_flow": null, 185 | "grid_auto_rows": null, 186 | "grid_column": null, 187 | "grid_gap": null, 188 | "grid_row": null, 189 | "grid_template_areas": null, 190 | "grid_template_columns": null, 191 | "grid_template_rows": null, 192 | "height": null, 193 | "justify_content": null, 194 | "justify_items": null, 195 | "left": null, 196 | "margin": null, 197 | "max_height": null, 198 | "max_width": null, 199 | "min_height": null, 200 | "min_width": null, 201 | "object_fit": null, 202 | "object_position": null, 203 | "order": null, 204 | "overflow": null, 205 | "overflow_x": null, 206 | "overflow_y": null, 207 | "padding": null, 208 | "right": null, 209 | "top": null, 210 | "visibility": null, 211 | "width": null 212 | } 213 | }, 214 | "ef1d34c16b4e4f4291ac1c09bd217635": { 215 | "model_module": "@jupyter-widgets/controls", 216 | "model_name": "DescriptionStyleModel", 217 | "model_module_version": "1.5.0", 218 | "state": { 219 | "_model_module": "@jupyter-widgets/controls", 220 | "_model_module_version": "1.5.0", 221 | "_model_name": "DescriptionStyleModel", 222 | "_view_count": null, 223 | "_view_module": "@jupyter-widgets/base", 224 | "_view_module_version": "1.2.0", 225 | "_view_name": "StyleView", 226 | "description_width": "" 227 | } 228 | }, 229 | "a6e8d510cd2d43bf97c99ca70c37bf3a": { 230 | "model_module": "@jupyter-widgets/base", 231 | "model_name": "LayoutModel", 232 | "model_module_version": "1.2.0", 233 | "state": { 234 | "_model_module": "@jupyter-widgets/base", 235 | "_model_module_version": "1.2.0", 236 | "_model_name": "LayoutModel", 237 | "_view_count": null, 238 | "_view_module": "@jupyter-widgets/base", 239 | "_view_module_version": "1.2.0", 240 | "_view_name": "LayoutView", 241 | "align_content": null, 242 | "align_items": null, 243 | "align_self": null, 244 | "border": null, 245 | "bottom": null, 246 | "display": null, 247 | "flex": null, 248 | "flex_flow": null, 249 | "grid_area": null, 250 | "grid_auto_columns": null, 251 | "grid_auto_flow": null, 252 | "grid_auto_rows": null, 253 | "grid_column": null, 254 | "grid_gap": null, 255 | "grid_row": null, 256 | "grid_template_areas": null, 257 | "grid_template_columns": null, 258 | "grid_template_rows": null, 259 | "height": null, 260 | "justify_content": null, 261 | "justify_items": null, 262 | "left": null, 263 | "margin": null, 264 | "max_height": null, 265 | "max_width": null, 266 | "min_height": null, 267 | "min_width": null, 268 | "object_fit": null, 269 | "object_position": null, 270 | "order": null, 271 | "overflow": null, 272 | "overflow_x": null, 273 | "overflow_y": null, 274 | "padding": null, 275 | "right": null, 276 | "top": null, 277 | "visibility": null, 278 | "width": null 279 | } 280 | }, 281 | "a59c626d9fbf43dd9edf77ce62f2b155": { 282 | "model_module": "@jupyter-widgets/controls", 283 | "model_name": "ProgressStyleModel", 284 | "model_module_version": "1.5.0", 285 | "state": { 286 | "_model_module": "@jupyter-widgets/controls", 287 | "_model_module_version": "1.5.0", 288 | "_model_name": "ProgressStyleModel", 289 | "_view_count": null, 290 | "_view_module": "@jupyter-widgets/base", 291 | "_view_module_version": "1.2.0", 292 | "_view_name": "StyleView", 293 | "bar_color": null, 294 | "description_width": "" 295 | } 296 | }, 297 | "2de45259c3f64ae7a1b98aa74ec629f6": { 298 | "model_module": "@jupyter-widgets/base", 299 | "model_name": "LayoutModel", 300 | "model_module_version": "1.2.0", 301 | "state": { 302 | "_model_module": "@jupyter-widgets/base", 303 | "_model_module_version": "1.2.0", 304 | "_model_name": "LayoutModel", 305 | "_view_count": null, 306 | "_view_module": "@jupyter-widgets/base", 307 | "_view_module_version": "1.2.0", 308 | "_view_name": "LayoutView", 309 | "align_content": null, 310 | "align_items": null, 311 | "align_self": null, 312 | "border": null, 313 | "bottom": null, 314 | "display": null, 315 | "flex": null, 316 | "flex_flow": null, 317 | "grid_area": null, 318 | "grid_auto_columns": null, 319 | "grid_auto_flow": null, 320 | "grid_auto_rows": null, 321 | "grid_column": null, 322 | "grid_gap": null, 323 | "grid_row": null, 324 | "grid_template_areas": null, 325 | "grid_template_columns": null, 326 | "grid_template_rows": null, 327 | "height": null, 328 | "justify_content": null, 329 | "justify_items": null, 330 | "left": null, 331 | "margin": null, 332 | "max_height": null, 333 | "max_width": null, 334 | "min_height": null, 335 | "min_width": null, 336 | "object_fit": null, 337 | "object_position": null, 338 | "order": null, 339 | "overflow": null, 340 | "overflow_x": null, 341 | "overflow_y": null, 342 | "padding": null, 343 | "right": null, 344 | "top": null, 345 | "visibility": null, 346 | "width": null 347 | } 348 | }, 349 | "f21ca1e656ff42648dcb0ba75484f3c6": { 350 | "model_module": "@jupyter-widgets/controls", 351 | "model_name": "DescriptionStyleModel", 352 | "model_module_version": "1.5.0", 353 | "state": { 354 | "_model_module": "@jupyter-widgets/controls", 355 | "_model_module_version": "1.5.0", 356 | "_model_name": "DescriptionStyleModel", 357 | "_view_count": null, 358 | "_view_module": "@jupyter-widgets/base", 359 | "_view_module_version": "1.2.0", 360 | "_view_name": "StyleView", 361 | "description_width": "" 362 | } 363 | } 364 | } 365 | } 366 | }, 367 | "cells": [ 368 | { 369 | "cell_type": "markdown", 370 | "metadata": { 371 | "id": "view-in-github", 372 | "colab_type": "text" 373 | }, 374 | "source": [ 375 | "\"Open" 376 | ] 377 | }, 378 | { 379 | "cell_type": "markdown", 380 | "metadata": { 381 | "id": "kLzX_EPqAnEW" 382 | }, 383 | "source": [ 384 | "# Spanish 6-Billion GPT-J (8-bit quantized)\n", 385 | "\n", 386 | "> Notebook original de [@mrm8488](https://twitter.com/mrm8488)" 387 | ] 388 | }, 389 | { 390 | "cell_type": "code", 391 | "source": [ 392 | "! nvidia-smi" 393 | ], 394 | "metadata": { 395 | "id": "jy1hn5_TXbG5", 396 | "outputId": "1c87fc40-50bc-4f15-8b45-05c59abed63f", 397 | "colab": { 398 | "base_uri": "https://localhost:8080/" 399 | } 400 | }, 401 | "execution_count": null, 402 | "outputs": [ 403 | { 404 | "output_type": "stream", 405 | "name": "stdout", 406 | "text": [ 407 | "Tue Aug 9 15:34:37 2022 \n", 408 | "+-----------------------------------------------------------------------------+\n", 409 | "| NVIDIA-SMI 460.32.03 Driver Version: 460.32.03 CUDA Version: 11.2 |\n", 410 | "|-------------------------------+----------------------+----------------------+\n", 411 | "| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |\n", 412 | "| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |\n", 413 | "| | | MIG M. |\n", 414 | "|===============================+======================+======================|\n", 415 | "| 0 Tesla P100-PCIE... Off | 00000000:00:04.0 Off | 0 |\n", 416 | "| N/A 45C P0 30W / 250W | 0MiB / 16280MiB | 0% Default |\n", 417 | "| | | N/A |\n", 418 | "+-------------------------------+----------------------+----------------------+\n", 419 | " \n", 420 | "+-----------------------------------------------------------------------------+\n", 421 | "| Processes: |\n", 422 | "| GPU GI CI PID Type Process name GPU Memory |\n", 423 | "| ID ID Usage |\n", 424 | "|=============================================================================|\n", 425 | "| No running processes found |\n", 426 | "+-----------------------------------------------------------------------------+\n" 427 | ] 428 | } 429 | ] 430 | }, 431 | { 432 | "cell_type": "code", 433 | "execution_count": null, 434 | "metadata": { 435 | "colab": { 436 | "base_uri": "https://localhost:8080/" 437 | }, 438 | "id": "Op0GXmC8CCyR", 439 | "outputId": "8bb9d2fb-1451-4093-d9b3-8cb37c42e802" 440 | }, 441 | "outputs": [ 442 | { 443 | "output_type": "stream", 444 | "name": "stdout", 445 | "text": [ 446 | "Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n", 447 | "Requirement already satisfied: transformers==4.14.1 in /usr/local/lib/python3.7/dist-packages (4.14.1)\n", 448 | "Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.7/dist-packages (from transformers==4.14.1) (21.3)\n", 449 | "Requirement already satisfied: regex!=2019.12.17 in /usr/local/lib/python3.7/dist-packages (from transformers==4.14.1) (2022.6.2)\n", 450 | "Requirement already satisfied: numpy>=1.17 in /usr/local/lib/python3.7/dist-packages (from transformers==4.14.1) (1.21.6)\n", 451 | "Requirement already satisfied: filelock in /usr/local/lib/python3.7/dist-packages (from transformers==4.14.1) (3.7.1)\n", 452 | "Requirement already satisfied: tokenizers<0.11,>=0.10.1 in /usr/local/lib/python3.7/dist-packages (from transformers==4.14.1) (0.10.3)\n", 453 | "Requirement already satisfied: requests in /usr/local/lib/python3.7/dist-packages (from transformers==4.14.1) (2.23.0)\n", 454 | "Requirement already satisfied: huggingface-hub<1.0,>=0.1.0 in /usr/local/lib/python3.7/dist-packages (from transformers==4.14.1) (0.8.1)\n", 455 | "Requirement already satisfied: importlib-metadata in /usr/local/lib/python3.7/dist-packages (from transformers==4.14.1) (4.12.0)\n", 456 | "Requirement already satisfied: tqdm>=4.27 in /usr/local/lib/python3.7/dist-packages (from transformers==4.14.1) (4.64.0)\n", 457 | "Requirement already satisfied: pyyaml>=5.1 in /usr/local/lib/python3.7/dist-packages (from transformers==4.14.1) (6.0)\n", 458 | "Requirement already satisfied: sacremoses in /usr/local/lib/python3.7/dist-packages (from transformers==4.14.1) (0.0.53)\n", 459 | "Requirement already satisfied: typing-extensions>=3.7.4.3 in /usr/local/lib/python3.7/dist-packages (from huggingface-hub<1.0,>=0.1.0->transformers==4.14.1) (4.1.1)\n", 460 | "Requirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in /usr/local/lib/python3.7/dist-packages (from packaging>=20.0->transformers==4.14.1) (3.0.9)\n", 461 | "Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.7/dist-packages (from importlib-metadata->transformers==4.14.1) (3.8.1)\n", 462 | "Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.7/dist-packages (from requests->transformers==4.14.1) (2.10)\n", 463 | "Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from requests->transformers==4.14.1) (1.24.3)\n", 464 | "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.7/dist-packages (from requests->transformers==4.14.1) (2022.6.15)\n", 465 | "Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests->transformers==4.14.1) (3.0.4)\n", 466 | "Requirement already satisfied: click in /usr/local/lib/python3.7/dist-packages (from sacremoses->transformers==4.14.1) (7.1.2)\n", 467 | "Requirement already satisfied: joblib in /usr/local/lib/python3.7/dist-packages (from sacremoses->transformers==4.14.1) (1.1.0)\n", 468 | "Requirement already satisfied: six in /usr/local/lib/python3.7/dist-packages (from sacremoses->transformers==4.14.1) (1.15.0)\n", 469 | "Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n", 470 | "Collecting http://35.184.69.80/root/pypi/+f/01a/9628eee5d6858/bitsandbytes-cuda111-0.26.0.tar.gz\n", 471 | " Downloading http://35.184.69.80/root/pypi/+f/01a/9628eee5d6858/bitsandbytes-cuda111-0.26.0.tar.gz (3.9 MB)\n", 472 | "\u001b[K |████████████████████████████████| 3.9 MB 303 kB/s \n", 473 | "\u001b[?25h Installing build dependencies ... \u001b[?25l\u001b[?25hdone\n", 474 | " Getting requirements to build wheel ... \u001b[?25l\u001b[?25hdone\n", 475 | " Preparing wheel metadata ... \u001b[?25l\u001b[?25hdone\n", 476 | "Building wheels for collected packages: bitsandbytes-cuda11.1.1\n", 477 | " Building wheel for bitsandbytes-cuda11.1.1 (PEP 517) ... \u001b[?25l\u001b[?25hdone\n", 478 | " Created wheel for bitsandbytes-cuda11.1.1: filename=bitsandbytes_cuda11.1.1-0.26.0-py3-none-any.whl size=3985724 sha256=0e0b41581d09f9048a7010145a9ccaff14449ee220c1f51b7945632e9a460e1e\n", 479 | " Stored in directory: /root/.cache/pip/wheels/93/02/4e/d54aafb3d81e795aae3d1193a5423c3fa563be41ac9f89212e\n", 480 | "Successfully built bitsandbytes-cuda11.1.1\n", 481 | "Installing collected packages: bitsandbytes-cuda11.1.1\n", 482 | "Successfully installed bitsandbytes-cuda11.1.1-0.26.0\n" 483 | ] 484 | } 485 | ], 486 | "source": [ 487 | "!pip install transformers==4.14.1\n", 488 | "!pip install http://35.184.69.80/root/pypi/+f/01a/9628eee5d6858/bitsandbytes-cuda111-0.26.0.tar.gz" 489 | ] 490 | }, 491 | { 492 | "cell_type": "code", 493 | "execution_count": null, 494 | "metadata": { 495 | "id": "p0dy1ZFwClcq" 496 | }, 497 | "outputs": [], 498 | "source": [ 499 | "import transformers\n", 500 | "import torch" 501 | ] 502 | }, 503 | { 504 | "cell_type": "markdown", 505 | "metadata": { 506 | "id": "GODiktIBFt4w" 507 | }, 508 | "source": [ 509 | "## Convierte el modelo a 8 bits\n", 510 | "\n", 511 | "Primero convertimos el modelo GPT-J-6B de EleutherAI a 8 bits usando la biblioteca de Facebook [bitsandbytes](https://github.com/facebookresearch/bitsandbytes). Así, reducimos el tamaño del modelo de 20Gb a solo 6Gb.\n", 512 | "\n", 513 | "Nota: No convertimos las capas lineares de sesgos a 8 bits porque no queremos perder esa información y de todas formas solo representan el 1% del tamaño del modelo." 514 | ] 515 | }, 516 | { 517 | "cell_type": "code", 518 | "source": [ 519 | "! wget https://huggingface.co/mrm8488/bertin-gpt-j-6B-ES-8bit/resolve/main/Utils.py -O Utils.py" 520 | ], 521 | "metadata": { 522 | "colab": { 523 | "base_uri": "https://localhost:8080/" 524 | }, 525 | "id": "BecZDZ2lelN_", 526 | "outputId": "bb3a2d46-3604-48cc-b00b-57d6f6f0eb44" 527 | }, 528 | "execution_count": null, 529 | "outputs": [ 530 | { 531 | "output_type": "stream", 532 | "name": "stdout", 533 | "text": [ 534 | "--2022-08-09 15:33:22-- https://huggingface.co/mrm8488/bertin-gpt-j-6B-ES-8bit/resolve/main/Utils.py\n", 535 | "Resolving huggingface.co (huggingface.co)... 52.2.34.29, 34.231.117.252, 2600:1f18:147f:e850:d57d:d46a:df34:61ee, ...\n", 536 | "Connecting to huggingface.co (huggingface.co)|52.2.34.29|:443... connected.\n", 537 | "HTTP request sent, awaiting response... 200 OK\n", 538 | "Length: 5838 (5.7K) [text/plain]\n", 539 | "Saving to: ‘Utils.py’\n", 540 | "\n", 541 | "Utils.py 100%[===================>] 5.70K --.-KB/s in 0s \n", 542 | "\n", 543 | "2022-08-09 15:33:22 (80.2 MB/s) - ‘Utils.py’ saved [5838/5838]\n", 544 | "\n" 545 | ] 546 | } 547 | ] 548 | }, 549 | { 550 | "cell_type": "code", 551 | "execution_count": null, 552 | "metadata": { 553 | "id": "P8Y75B6WDIN-" 554 | }, 555 | "outputs": [], 556 | "source": [ 557 | "from Utils import GPTJBlock, GPTJForCausalLM" 558 | ] 559 | }, 560 | { 561 | "cell_type": "code", 562 | "execution_count": null, 563 | "metadata": { 564 | "id": "BOSZ-S1cDRq1" 565 | }, 566 | "outputs": [], 567 | "source": [ 568 | "transformers.models.gptj.modeling_gptj.GPTJBlock = GPTJBlock # monkey-patch GPT-J" 569 | ] 570 | }, 571 | { 572 | "cell_type": "code", 573 | "execution_count": null, 574 | "metadata": { 575 | "id": "DuW4H6HTS82r" 576 | }, 577 | "outputs": [], 578 | "source": [ 579 | "device = 'cuda' if torch.cuda.is_available() else 'cpu'\n", 580 | "\n", 581 | "CKPT = 'mrm8488/bertin-gpt-j-6B-ES-8bit'\n", 582 | "\n", 583 | "tokenizer = transformers.AutoTokenizer.from_pretrained(CKPT)\n", 584 | "model = GPTJForCausalLM.from_pretrained(CKPT).to(device)" 585 | ] 586 | }, 587 | { 588 | "cell_type": "code", 589 | "source": [ 590 | "import textwrap" 591 | ], 592 | "metadata": { 593 | "id": "_uABnZ_GbVG1" 594 | }, 595 | "execution_count": null, 596 | "outputs": [] 597 | }, 598 | { 599 | "cell_type": "code", 600 | "source": [ 601 | "def generate(text: str, max_length: int = 64, do_sample: bool = True, temperature: float = 0.9) -> str:\n", 602 | " prompt = tokenizer(text, return_tensors='pt')\n", 603 | " features = {key: value.to(device) for key, value in prompt.items()}\n", 604 | " out = model.generate(**features, max_length=max_length, do_sample=do_sample, temperature=temperature)\n", 605 | " return tokenizer.decode(out[0])" 606 | ], 607 | "metadata": { 608 | "id": "O_UmBxrpo5ru" 609 | }, 610 | "execution_count": null, 611 | "outputs": [] 612 | }, 613 | { 614 | "cell_type": "markdown", 615 | "source": [ 616 | "## Juega con el modelo\n", 617 | "\n", 618 | "Aquí te dejamos una serie de ejemplos para que puedas jugar con el modelo. Te animamos a que pruebes tus propias ideas e investigues cómo \"razona\" el modelo." 619 | ], 620 | "metadata": { 621 | "id": "0MlLc3y4HJ_S" 622 | } 623 | }, 624 | { 625 | "cell_type": "code", 626 | "source": [ 627 | "offers = [\n", 628 | "['¡30% EXTRA! Disfruta de este cupón descuento Venca ¡REBAJAS!',\n", 629 | " '25% MENOS usando el código descuento Yoins al realizar tu compra',\n", 630 | " '10% EXTRA en tus compras al aplicar el cupón descuento Samsung',\n", 631 | " '12% MENOS aplicando este código descuento Sammydress en tu pedido online',\n", 632 | " '-15% al aplicar este código en todos los productos',\n", 633 | " '-20% al introducir el código promocional Mister Spex',\n", 634 | " '-5% aplicando este código promocional MiniInTheBox antes de finalizar tu pedido',\n", 635 | " '-18% introduciendo el cupón descuento Milanoo de Navidad',\n", 636 | " '-10% aplicando este código al comprar 3 artículos en la web',\n", 637 | " '20% MENOS al aplicar el código descuento Miss Hamptons',\n", 638 | " '70% MENOS para hacer calendarios personalizados para hacer calendarios personalizados para hacer calendarios personalizados para hacer calendarios personalizados con este código Vistaprint',\n", 639 | " '10% de ahorro en TODA la web aplicando este código descuento Spartoo ¡Limitado!',\n", 640 | " '20% MENOS al aplicar este código promocional iStock',\n", 641 | " '8% MENOS en tu alojamiento aplicando este cupón Hoteles.com',\n", 642 | " '-15% al usar el código promocional Bikeinn del Cyber Monday',\n", 643 | " '-17% en Yoins introduciendo este código en la web',\n", 644 | " '15% de rebaja en gaming Omen aplicando este código descuento HP',\n", 645 | " '20% código descuento Nutritienda en una selección de marcas',\n", 646 | " '40% MENOS en tus pedidos al aplicar este código promocional Vistaprint',\n", 647 | " '30% usando este código al comprar álbumes de lujo',\n", 648 | " '19% de ahorro al aplicar este código descuento Yoins ¡Celebra el Año Nuevo!',\n", 649 | " '12% código descuento iStock en TODO para nuevos clientes',\n", 650 | " '-10% usando el código descuento Qatar Airways al reservar desde el móvil',\n", 651 | " '-40% usando este código descuento Photobox al comprar un álbum de fotos',\n", 652 | " '-10% aplicando este código ¡Oportunidad Yoins!',\n", 653 | " '5% código descuento Zoombits en Multicompra',\n", 654 | " '10% código descuento Animalear',\n", 655 | " '7% MENOS en tu reserva aplicando este código descuento H10 Hotels',\n", 656 | " '-10% usando este código al comprar muebles en VidaXL',\n", 657 | " '25% MENOS al aplicar este cupón La Tostadora',\n", 658 | " '-8% en electrónica de consumo aplicando este código promocional GearBest',\n", 659 | " '¡-20% aplicando este cupón descuento Lentes-Shop!',\n", 660 | " '-20% en tu moda favorita ¡código Venca!',\n", 661 | " '5% código descuento Agoda para viajar a Shanghai',\n", 662 | " '10% MENOS en snack para tu mascota aplicando este cupón promocional activo',\n", 663 | " '10%. 15% o 20% ¡Elige tu cupón Kiwoko y ahorra en el pienso para tu perro!',\n", 664 | " '¡15% menos con este gran código promocional Runnerinn del Cyber Monday!',\n", 665 | " '5% EXTRA aplicando este código en TODO',\n", 666 | " '20% MENOS usando este código al comprar la mejor moda',\n", 667 | " '30% MENOS en todas las bebidas al aplicar el código promocional Tassimo',\n", 668 | " '10% MENOS al aplicar este código descuento FocalPrice',\n", 669 | " '20% MENOS en una gran variedad de lámparas aplicando este cupón',\n", 670 | " '8% MENOS al aplicar este cupón descuento',\n", 671 | " '12% MENOS al aplicar este cupón descuento Dosfarma',\n", 672 | " '15% MENOS al aplicar el cupón descuento Magix',\n", 673 | " '-5% aplicando este código promocional Spartoo de verano',\n", 674 | " '20% en Novedades Milano con código promocional Fifty Factory',\n", 675 | " '20% MENOS al aplicar el código descuento Zavvi en vinilos',\n", 676 | " '-5% usando este código descuento Zoombits al comprar 2 artículos',\n", 677 | " '-8% aplicando este código',\n", 678 | " '20% adicional en en TODA la web si usas el cupón descuento El Armario de la Tele',\n", 679 | " '5% código descuento en los accesorios de cocina de Zoombits',\n", 680 | " '20% código descuento Lopesan Hoteles']" 681 | ], 682 | "metadata": { 683 | "id": "8PZhoJGmTRuq" 684 | }, 685 | "execution_count": null, 686 | "outputs": [] 687 | }, 688 | { 689 | "cell_type": "code", 690 | "source": [ 691 | "text = '''\n", 692 | "título: 5% código descuento Zoombits en Multicompra\n", 693 | "oferta: 5% en Multicompra\n", 694 | "\n", 695 | "título: -10% usando este cupón descuento Alltricks\n", 696 | "oferta: -10%\n", 697 | "\n", 698 | "título: 10% código descuento Animalear\n", 699 | "oferta; 10%\n", 700 | "\n", 701 | "título: ¡5% adicional utilizando este código descuento Barceló Hoteles!\n", 702 | "oferta: 5% adicional\n", 703 | "\n", 704 | "título: 15% de descuento al utilizar el código promocional Spartoo\n", 705 | "oferta: 15%\n", 706 | "\n", 707 | "título: 25% MENOS utilizando este código descuento Groupon\n", 708 | "oferta: 25% MENOS\n", 709 | "\n", 710 | "título: -25% en la web usando e cupón descuento vistaprint\n", 711 | "oferta: -25% en la web\n", 712 | "\n", 713 | "título: -10% usando este código al comprar muebles en VidaXL\n", 714 | "oferta: -10% al comprar muebles\n", 715 | "\n", 716 | "título: -20% en tu moda favorita ¡código Venca!\n", 717 | "oferta: -20% en tu moda favorita\n", 718 | "\n", 719 | "título: 19% de ahorro al aplicar este código descuento Yoins ¡Celebra el Año Nuevo!\n", 720 | "oferta: 19% de ahorro\n", 721 | "\n", 722 | "título: 8% MENOS en tu alojamiento aplicando este cupón Hoteles.com\n", 723 | "oferta: 8% MENOS en tu alojamiento\n", 724 | "\n", 725 | "título::\n", 726 | "oferta:'''" 727 | ], 728 | "metadata": { 729 | "id": "IL_C363KRl58" 730 | }, 731 | "execution_count": null, 732 | "outputs": [] 733 | }, 734 | { 735 | "cell_type": "code", 736 | "source": [ 737 | "from tqdm.notebook import tqdm" 738 | ], 739 | "metadata": { 740 | "id": "p7stT18iX8gQ" 741 | }, 742 | "execution_count": null, 743 | "outputs": [] 744 | }, 745 | { 746 | "cell_type": "code", 747 | "source": [ 748 | "titles = []\n", 749 | "ofertas = []\n", 750 | "for offer in tqdm(offers):\n", 751 | " prompt = text.replace('título::', 'título: ' + offer)\n", 752 | " response = generate(prompt, 512, True, temperature = 0.8)\n", 753 | " print(offer)\n", 754 | " print(response.replace(prompt, ''))\n", 755 | " print()\n", 756 | " print(\"===\")\n", 757 | " titles.append(offer)\n", 758 | " ofertas.append(response.replace(prompt, '').split('\\n')[0].strip())\n" 759 | ], 760 | "metadata": { 761 | "colab": { 762 | "base_uri": "https://localhost:8080/", 763 | "height": 1000, 764 | "referenced_widgets": [ 765 | "3b354e5db9bb462dbc60e13a5302388b", 766 | "cfc7dd89a25243519bbfdb3d1741f3b7", 767 | "c9786564c94c400ba59befbeb2484718", 768 | "b23669a67d5f4bfc8a3df6b82d0cc0fe", 769 | "073e80247a2a46fda0d6d73175d374a2", 770 | "7254d7f2f786449c8c6616244cd6e492", 771 | "ef1d34c16b4e4f4291ac1c09bd217635", 772 | "a6e8d510cd2d43bf97c99ca70c37bf3a", 773 | "a59c626d9fbf43dd9edf77ce62f2b155", 774 | "2de45259c3f64ae7a1b98aa74ec629f6", 775 | "f21ca1e656ff42648dcb0ba75484f3c6" 776 | ] 777 | }, 778 | "id": "KpeYgdavVYV6", 779 | "outputId": "4e5b8d07-6ea0-4bf9-c4f2-3891d759017d" 780 | }, 781 | "execution_count": null, 782 | "outputs": [ 783 | { 784 | "output_type": "display_data", 785 | "data": { 786 | "text/plain": [ 787 | " 0%| | 0/49 [00:00 6 | 7 | 8 | ### Sesiones 9 | 10 | | Fecha | Tema | Material ES | Notebook ES | Notebook EN | Sesión EN | 11 | |---|---|---|---|---|---| 12 | | 9 Abr | Introducción | [Diapos](https://github.com/somosnlp/recursos/blob/main/grupo_de_estudio/nlp_con_transformers_1.pdf) de @sofi#2291 | [![Abrir en Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://somosnlp.org/recursos/tutoriales/01_aplicaciones_de_los_transformers) | [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/nlp-with-transformers/notebooks/blob/main/01_introduction.ipynb) | [Sesión EN YouTube](https://youtu.be/8uVvfJIH_LY) | 13 | | 3 Nov | Clasificación de texto | | | | | 14 | 15 | 16 | 17 | ### Invitación 18 | 19 | Nuestro medio de comunicación es el canal #grupo-de-estudio del Discord de la comunidad Somos NLP. 20 | ¡Únete con esta [invitación](https://discord.com/invite/my8w7JUxZR)! 21 | -------------------------------------------------------------------------------- /grupo_de_estudio/nlp_con_transformers_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/somosnlp/recursos/ac5d0bfed81fdb8f3cfc453418a59932f81e99be/grupo_de_estudio/nlp_con_transformers_1.pdf -------------------------------------------------------------------------------- /hackathon_2022/README.md: -------------------------------------------------------------------------------- 1 | # Hackathon Somos NLP 2022 2 | 3 | En este repo están las diapositivas y notebooks de algunas de las charlas y talleres impartidas durante la primera edición del [Hackathon de PLN en Español](https://somosnlp.org/blog/hackathon-2022). 4 | 5 | Todos los eventos están grabados y subidos a esta [playlist de YouTube](https://www.youtube.com/playlist?list=PLTA-KAy8nxaAbVZ2lVcycHnJ2qEDip7hG), ¡aprende de la mano de especialistas! ✨ 6 | -------------------------------------------------------------------------------- /hackathon_2022/analisis_error_modelos_nlp_omar_sanseviero.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/somosnlp/recursos/ac5d0bfed81fdb8f3cfc453418a59932f81e99be/hackathon_2022/analisis_error_modelos_nlp_omar_sanseviero.pdf -------------------------------------------------------------------------------- /hackathon_2022/lxai_nlp_extended_abstract_javier_turek.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/somosnlp/recursos/ac5d0bfed81fdb8f3cfc453418a59932f81e99be/hackathon_2022/lxai_nlp_extended_abstract_javier_turek.pdf -------------------------------------------------------------------------------- /hackathon_2022/nlp_lenguas_minorizadas_mx_ximena_gutierrez.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/somosnlp/recursos/ac5d0bfed81fdb8f3cfc453418a59932f81e99be/hackathon_2022/nlp_lenguas_minorizadas_mx_ximena_gutierrez.pdf -------------------------------------------------------------------------------- /hackathon_2023/README.md: -------------------------------------------------------------------------------- 1 | # Hackathon Somos NLP 2023 2 | 3 | Todas las charlas y talleres del hackathon están grabadas, ¡visualízalas [aquí](https://somosnlp.org/eventos)! ✨ 4 | -------------------------------------------------------------------------------- /hackathon_2024/creacion_de_datasets_sinteticos_con_distilabel.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [], 7 | "gpuType": "T4", 8 | "include_colab_link": true 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "language_info": { 15 | "name": "python" 16 | }, 17 | "accelerator": "GPU" 18 | }, 19 | "cells": [ 20 | { 21 | "cell_type": "markdown", 22 | "metadata": { 23 | "id": "view-in-github", 24 | "colab_type": "text" 25 | }, 26 | "source": [ 27 | "\"Open" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "source": [ 33 | "# Agradecimientos\n", 34 | "\n", 35 | "Muchas gracias al equipo de Argilla por preparar este notebook de ejemplo, en especial a Daniel Vila Suero (CEO y fundador) y Agustín Piqueres (MLE).\n", 36 | "\n", 37 | "Muchas gracias también a Hugging Face por darnos la oportunidad de disfrutar de la PRO API durante el hackathon. Pedimos a todos los equipos responsabilidad, por favor utilizad esta API para el desarrollo de proyectos del hackathon. Así seguiremos pudiendo organizar estos maravillosos eventos gratuitos. ¡Gracias!" 38 | ], 39 | "metadata": { 40 | "id": "lH5SbqdWv3W6" 41 | } 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "source": [ 46 | "# Instalar requisitos" 47 | ], 48 | "metadata": { 49 | "id": "B86XP2iJvv4_" 50 | } 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": null, 55 | "metadata": { 56 | "id": "RdY5HkI3eKMI", 57 | "colab": { 58 | "base_uri": "https://localhost:8080/" 59 | }, 60 | "outputId": "0e7a3c36-d00f-4b17-e73e-39a8104bf88f" 61 | }, 62 | "outputs": [ 63 | { 64 | "output_type": "stream", 65 | "name": "stdout", 66 | "text": [ 67 | "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m156.5/156.5 kB\u001b[0m \u001b[31m3.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", 68 | "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m254.3/254.3 kB\u001b[0m \u001b[31m6.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", 69 | "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m12.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", 70 | "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m64.2/64.2 kB\u001b[0m \u001b[31m8.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", 71 | "\u001b[?25h Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n", 72 | "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m98.5/98.5 MB\u001b[0m \u001b[31m8.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", 73 | "\u001b[?25h Building wheel for ftfy (setup.py) ... \u001b[?25l\u001b[?25hdone\n" 74 | ] 75 | } 76 | ], 77 | "source": [ 78 | "%pip install -U distilabel[hf-inference-endpoints,argilla] -qqq" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "source": [ 84 | "from distilabel.llm.huggingface.inference_endpoints import InferenceEndpointsLLM\n", 85 | "from distilabel.tasks import TextGenerationTask\n", 86 | "from distilabel.tasks import SelfInstructTask\n", 87 | "from distilabel.pipeline import Pipeline" 88 | ], 89 | "metadata": { 90 | "id": "VujeChEdeSzc" 91 | }, 92 | "execution_count": null, 93 | "outputs": [] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "source": [ 98 | "import distilabel\n", 99 | "distilabel.__version__" 100 | ], 101 | "metadata": { 102 | "colab": { 103 | "base_uri": "https://localhost:8080/", 104 | "height": 35 105 | }, 106 | "id": "gKOz0-iKaoHc", 107 | "outputId": "2fddc989-a35d-46cf-8a75-eefdc7bfb052" 108 | }, 109 | "execution_count": null, 110 | "outputs": [ 111 | { 112 | "output_type": "execute_result", 113 | "data": { 114 | "text/plain": [ 115 | "'0.6.0'" 116 | ], 117 | "application/vnd.google.colaboratory.intrinsic+json": { 118 | "type": "string" 119 | } 120 | }, 121 | "metadata": {}, 122 | "execution_count": 5 123 | } 124 | ] 125 | }, 126 | { 127 | "cell_type": "markdown", 128 | "source": [ 129 | "# Introducción\n", 130 | "\n", 131 | "En este tutorial se muestra como generar conjuntos de datos sintéticos en Español para entrenar y mejorar modelos del lenguaje en Español.\n", 132 | "\n", 133 | "Para ello se utiliza `distilabel` de Argilla, una librería escalable para generar datasets para LLMs.\n", 134 | "\n", 135 | "Este cuaderno provee una breve guía de introducción pero se recomienda leer la [documentación](https://distilabel.argilla.io/latest/) y explorar opciones más avanzadas así como casos de uso interesantes, más allá del ejemplo utilizado aquí.\n", 136 | "\n", 137 | "En este cuaderno:\n", 138 | "\n", 139 | "- Se muestra como generar instrucciones y respuestas para SFT (supervised fine tuning) utilizando Hugging Face Inference for PRO (gracias al sponsorship de Hugging Face).\n", 140 | "\n", 141 | "- Se muestra como generar instrucciones y respuestas para SFT (supervised fine tuning) utilizando la GPU de Colab y modelos locales.\n" 142 | ], 143 | "metadata": { 144 | "id": "0D8tHM7Wtgpl" 145 | } 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "source": [ 150 | "# Generación de instrucciones con HF Inference endpoints\n", 151 | "\n", 152 | "Con este apartado, los equipos pueden generar instrucciones en Español sobre distintos temas y para distintas aplicaciones. Aquí se muestra solo un ejemplo muy básico.\n", 153 | "\n", 154 | "Para ejecutar este apartado es necesario formar parte de la organización SomosNLP en Hugging Face y configurar el token personal (nivel write) para poder hacer uso de la cuenta PRO.\n", 155 | "\n", 156 | "\n", 157 | "Se ruega no sobrecargar la API de inferencia y hacer pruebas con pequeñas muestras hasta tener claro el caso de uso y en cualquier caso no generar datasets de más de 5000 ejemplos." 158 | ], 159 | "metadata": { 160 | "id": "OOOdMpkfspe2" 161 | } 162 | }, 163 | { 164 | "cell_type": "markdown", 165 | "source": [ 166 | "## Comprobar acceso a Inference Endpoints" 167 | ], 168 | "metadata": { 169 | "id": "XP95xr4WqVx4" 170 | } 171 | }, 172 | { 173 | "cell_type": "code", 174 | "source": [ 175 | "from google.colab import userdata\n", 176 | "\n", 177 | "hf_token = userdata.get('HF_TOKEN')\n", 178 | "\n", 179 | "# change endpoint name and namespace once deployed\n", 180 | "ENDPOINT_NAME = \"mistralai/Mixtral-8x7B-Instruct-v0.1\"\n", 181 | "\n", 182 | "\n", 183 | "llm = InferenceEndpointsLLM(\n", 184 | " endpoint_name_or_model_id=ENDPOINT_NAME,\n", 185 | " task=TextGenerationTask(),\n", 186 | " token=hf_token,\n", 187 | " prompt_format=\"llama2\"\n", 188 | ")" 189 | ], 190 | "metadata": { 191 | "colab": { 192 | "base_uri": "https://localhost:8080/" 193 | }, 194 | "id": "5oHD3ETGewPV", 195 | "outputId": "25e58241-a2b2-4acd-b4f9-b3e304c98ea7" 196 | }, 197 | "execution_count": null, 198 | "outputs": [ 199 | { 200 | "output_type": "stream", 201 | "name": "stderr", 202 | "text": [ 203 | "INFO:distilabel:Using Serverless Inference Endpoint\n" 204 | ] 205 | } 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "source": [ 211 | "llm.generate([{\"input\": \"Generate a random joke in Spanish, just the joke, no greetings\"}])" 212 | ], 213 | "metadata": { 214 | "colab": { 215 | "base_uri": "https://localhost:8080/" 216 | }, 217 | "id": "mMSg8K3Zexop", 218 | "outputId": "794b139f-2ab9-4099-ecce-aaee2098e3e7" 219 | }, 220 | "execution_count": null, 221 | "outputs": [ 222 | { 223 | "output_type": "execute_result", 224 | "data": { 225 | "text/plain": [ 226 | "[[{'model_name': 'mistralai/Mixtral-8x7B-Instruct-v0.1',\n", 227 | " 'prompt_used': \"[INST] <>\\nYou are a helpful, respectful and honest assistant. Always answer as helpfully as possible, while being safe. Your answers should not include any harmful, unethical, racist, sexist, toxic, dangerous, or illegal content. Please ensure that your responses are socially unbiased and positive in nature.\\nIf a question does not make any sense, or is not factually coherent, explain why instead of answering something not correct. If you don't know the answer to a question, please don't share false information.<>\\n\\nGenerate a random joke in Spanish, just the joke, no greetings [/INST]\",\n", 228 | " 'raw_output': ' ¿Por qué el pollo siempre cruza la calle?\\nPorque quiere llegar al otro lado y decir: \"¡Adivinen quién acaba de cruzar la calle!\" (Why does the chicken always cross the road? Because it wants to get to the other side and say: \"Guess who just crossed the road!\")',\n", 229 | " 'parsed_output': {'generations': ' ¿Por qué el pollo siempre cruza la calle?\\nPorque quiere llegar al otro lado y decir: \"¡Adivinen quién acaba de cruzar la calle!\" (Why does the chicken always cross the road? Because it wants to get to the other side and say: \"Guess who just crossed the road!\")'}}]]" 230 | ] 231 | }, 232 | "metadata": {}, 233 | "execution_count": 7 234 | } 235 | ] 236 | }, 237 | { 238 | "cell_type": "markdown", 239 | "source": [ 240 | "## Generar dataset de instrucciones por temas\n", 241 | "\n", 242 | "Esto es solo un ejemplo y configurando la lista de `topics` y la `application_description` se pueden generar instrucciones de mucho tipos y dominios, sé creativ@!" 243 | ], 244 | "metadata": { 245 | "id": "YwQv0l7rqaVZ" 246 | } 247 | }, 248 | { 249 | "cell_type": "code", 250 | "source": [ 251 | "from datasets import Dataset\n", 252 | "\n", 253 | "topics = [\n", 254 | " \"Matemáticas\",\n", 255 | " \"Física\",\n", 256 | " \"Química\",\n", 257 | " \"Biología\",\n", 258 | " \"Informática\",\n", 259 | " \"Ingeniería\",\n", 260 | " \"Astronomía\",\n", 261 | " \"Geología\",\n", 262 | " \"Ciencias Ambientales\",\n", 263 | " \"Robótica\",\n", 264 | " \"Estadística\",\n", 265 | " \"Ciencias de Materiales\",\n", 266 | " \"Nanotecnología\",\n", 267 | " \"Genética\",\n", 268 | " \"Oceanografía\",\n", 269 | " \"Meteorología\",\n", 270 | " \"Farmacología\",\n", 271 | " \"Neurociencia\",\n", 272 | " \"Bioquímica\",\n", 273 | " \"Física de Partículas\",\n", 274 | " \"Ciencia de Datos\",\n", 275 | " \"Inteligencia Artificial\",\n", 276 | " \"Sostenibilidad\",\n", 277 | " \"Energías Renovables\"\n", 278 | "]\n", 279 | "\n", 280 | "\n", 281 | "dataset = Dataset.from_dict({\n", 282 | " \"input\": topics\n", 283 | "})" 284 | ], 285 | "metadata": { 286 | "id": "SZMVodOIgxVg" 287 | }, 288 | "execution_count": null, 289 | "outputs": [] 290 | }, 291 | { 292 | "cell_type": "markdown", 293 | "source": [ 294 | "Te invitamos a probar diferentes prompts y ver cuál da mejores resultados:" 295 | ], 296 | "metadata": { 297 | "id": "gbqntFRazdx4" 298 | } 299 | }, 300 | { 301 | "cell_type": "code", 302 | "source": [ 303 | "application_description = (\n", 304 | " \"An AI assistant adept at answering a wide array of math, logic, and reasoning puzzles, trivia, \"\n", 305 | " \"and general questions. Users of this assistant love to ask the assistant to think and outlines \"\n", 306 | " \"the solutions step by step. It expects complete questions from users providing all the details \"\n", 307 | " \"to solve the proposed problem or respond to general knowledge questions. It covers general \"\n", 308 | " \"knowledge about math, puzzles, reasoning exercises, and real-life scenarios where math and \"\n", 309 | " \"reasoning are important. Highly important!! You can only generate text in SPANISH\"\n", 310 | ")\n", 311 | "\n", 312 | "# Por defecto, `SelfInstructTask` generará 5 instrucciones pero se puede modificar este comportamiento con el argumento `num_instructions`.\n", 313 | "instruction_task = SelfInstructTask(\n", 314 | " application_description=application_description\n", 315 | ")\n", 316 | "\n", 317 | "print(f\"`SelfInstructTask`\\n - Input arguments: {instruction_task.input_args_names}\\n - Output arguments: {instruction_task.output_args_names}\")" 318 | ], 319 | "metadata": { 320 | "id": "k4ugAnsaibHt", 321 | "colab": { 322 | "base_uri": "https://localhost:8080/" 323 | }, 324 | "outputId": "2cf8da02-8e0a-455e-e77f-acce77a47cd3" 325 | }, 326 | "execution_count": null, 327 | "outputs": [ 328 | { 329 | "output_type": "stream", 330 | "name": "stdout", 331 | "text": [ 332 | "`SelfInstructTask`\n", 333 | " - Input arguments: ['input']\n", 334 | " - Output arguments: ['instructions']\n" 335 | ] 336 | } 337 | ] 338 | }, 339 | { 340 | "cell_type": "code", 341 | "source": [ 342 | "llm = InferenceEndpointsLLM(\n", 343 | " endpoint_name_or_model_id=ENDPOINT_NAME,\n", 344 | " task=instruction_task,\n", 345 | " token=hf_token,\n", 346 | " prompt_format=\"llama2\",\n", 347 | " num_threads=4\n", 348 | ")\n", 349 | "\n", 350 | "pipeline = Pipeline(generator=llm)\n", 351 | "distiset = pipeline.generate(\n", 352 | " dataset=dataset,\n", 353 | " num_generations=5,\n", 354 | " batch_size=4,\n", 355 | " display_progress_bar=True\n", 356 | ")" 357 | ], 358 | "metadata": { 359 | "id": "OQ8-q4LtislP" 360 | }, 361 | "execution_count": null, 362 | "outputs": [] 363 | }, 364 | { 365 | "cell_type": "code", 366 | "source": [ 367 | "distiset.to_pandas().head(5)" 368 | ], 369 | "metadata": { 370 | "colab": { 371 | "base_uri": "https://localhost:8080/", 372 | "height": 147 373 | }, 374 | "id": "jK9LDzuCtFH7", 375 | "outputId": "6b89bd23-faa6-410b-b88e-c1ce048e3dc4" 376 | }, 377 | "execution_count": null, 378 | "outputs": [ 379 | { 380 | "output_type": "execute_result", 381 | "data": { 382 | "text/plain": [ 383 | " input generation_model \\\n", 384 | "0 Matemáticas [mistralai/Mixtral-8x7B-Instruct-v0.1, mistral... \n", 385 | "1 Física [mistralai/Mixtral-8x7B-Instruct-v0.1, mistral... \n", 386 | "\n", 387 | " generation_prompt \\\n", 388 | "0 [[INST] <>\\nYou are an expert prompt w... \n", 389 | "1 [[INST] <>\\nYou are an expert prompt w... \n", 390 | "\n", 391 | " raw_generation_responses \\\n", 392 | "0 [ 1. \"Explica detalladamente cómo calcular la ... \n", 393 | "1 [ 1. \"Explica paso a paso cómo funciona la seg... \n", 394 | "\n", 395 | " instructions \n", 396 | "0 [[\"Explica detalladamente cómo calcular la raí... \n", 397 | "1 [[\"Explica paso a paso cómo funciona la segund... " 398 | ], 399 | "text/html": [ 400 | "\n", 401 | "
\n", 402 | "
\n", 403 | "\n", 416 | "\n", 417 | " \n", 418 | " \n", 419 | " \n", 420 | " \n", 421 | " \n", 422 | " \n", 423 | " \n", 424 | " \n", 425 | " \n", 426 | " \n", 427 | " \n", 428 | " \n", 429 | " \n", 430 | " \n", 431 | " \n", 432 | " \n", 433 | " \n", 434 | " \n", 435 | " \n", 436 | " \n", 437 | " \n", 438 | " \n", 439 | " \n", 440 | " \n", 441 | " \n", 442 | " \n", 443 | " \n", 444 | " \n", 445 | "
inputgeneration_modelgeneration_promptraw_generation_responsesinstructions
0Matemáticas[mistralai/Mixtral-8x7B-Instruct-v0.1, mistral...[<s>[INST] <<SYS>>\\nYou are an expert prompt w...[ 1. \"Explica detalladamente cómo calcular la ...[[\"Explica detalladamente cómo calcular la raí...
1Física[mistralai/Mixtral-8x7B-Instruct-v0.1, mistral...[<s>[INST] <<SYS>>\\nYou are an expert prompt w...[ 1. \"Explica paso a paso cómo funciona la seg...[[\"Explica paso a paso cómo funciona la segund...
\n", 446 | "
\n", 447 | "
\n", 448 | "\n", 449 | "
\n", 450 | " \n", 458 | "\n", 459 | " \n", 499 | "\n", 500 | " \n", 524 | "
\n", 525 | "\n", 526 | "\n", 527 | "
\n", 528 | " \n", 539 | "\n", 540 | "\n", 629 | "\n", 630 | " \n", 652 | "
\n", 653 | "
\n", 654 | "
\n" 655 | ], 656 | "application/vnd.google.colaboratory.intrinsic+json": { 657 | "type": "dataframe", 658 | "summary": "{\n \"name\": \"distiset\",\n \"rows\": 2,\n \"fields\": [\n {\n \"column\": \"input\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 2,\n \"samples\": [\n \"F\\u00edsica\",\n \"Matem\\u00e1ticas\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"generation_model\",\n \"properties\": {\n \"dtype\": \"object\",\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"generation_prompt\",\n \"properties\": {\n \"dtype\": \"object\",\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"raw_generation_responses\",\n \"properties\": {\n \"dtype\": \"object\",\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"instructions\",\n \"properties\": {\n \"dtype\": \"object\",\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}" 659 | } 660 | }, 661 | "metadata": {}, 662 | "execution_count": 11 663 | } 664 | ] 665 | }, 666 | { 667 | "cell_type": "markdown", 668 | "source": [ 669 | "### Inspeccionar el dataset en argilla\n", 670 | "\n", 671 | "A continuación vamos a crear un espacio en argilla para poder inspeccionar las instrucciones generadas en nuestra pipeline. Podemos crear una instancia de argilla como un espacio de HuggingFace. A continuación se ofrece un ejemplo para hacerlo utilizando la librería de `huggingface_hub`." 672 | ], 673 | "metadata": { 674 | "id": "lN6xA_xUPQE4" 675 | } 676 | }, 677 | { 678 | "cell_type": "code", 679 | "source": [ 680 | "rg_distiset = distiset.to_argilla(vector_strategy=False, metric_strategy=False)" 681 | ], 682 | "metadata": { 683 | "id": "oYxJzfM8J1gJ" 684 | }, 685 | "execution_count": null, 686 | "outputs": [] 687 | }, 688 | { 689 | "cell_type": "code", 690 | "source": [ 691 | "from huggingface_hub import duplicate_space\n", 692 | "\n", 693 | "# Crea un HF Space de argilla programáticamente\n", 694 | "from_id = \"argilla/argilla-template-space\"\n", 695 | "# Recuerda actualizar esta variable con el nombre del dataset\n", 696 | "dataset_name = \"mi-dataset\"\n", 697 | "to_id = f\"{dataset_name}-distiset\"\n", 698 | "new_space = duplicate_space(from_id, to_id=to_id)\n", 699 | "new_space" 700 | ], 701 | "metadata": { 702 | "id": "3p8R57j_MYLb" 703 | }, 704 | "execution_count": null, 705 | "outputs": [] 706 | }, 707 | { 708 | "cell_type": "markdown", 709 | "source": [ 710 | "Esto puede llevar unos minutos, puedes visitar el espacio accediendo a `new_space.url`. Una vez que esté listo, el usuario para acceder y contraseña son los que vienen por defecto\n", 711 | "\n", 712 | "- usuario: `argilla`\n", 713 | "- contraseña: `12345678`" 714 | ], 715 | "metadata": { 716 | "id": "NwKsoncNNN6V" 717 | } 718 | }, 719 | { 720 | "cell_type": "markdown", 721 | "source": [ 722 | "A continuación nos conectamos a nuestra instancia para poder subir el dataset:" 723 | ], 724 | "metadata": { 725 | "id": "oAhqCd8ONwpL" 726 | } 727 | }, 728 | { 729 | "cell_type": "code", 730 | "source": [ 731 | "import argilla as rg\n", 732 | "\n", 733 | "argilla_api_key = \"admin.apikey\"\n", 734 | "argilla_space_url = f\"https://{new_space.namespace}-{to_id}.hf.space\"\n", 735 | "\n", 736 | "workspace = \"admin\"\n", 737 | "\n", 738 | "rg.init(\n", 739 | " api_key=argilla_api_key,\n", 740 | " api_url=argilla_space_url,\n", 741 | " workspace=workspace\n", 742 | ")" 743 | ], 744 | "metadata": { 745 | "id": "vUC9x_6TN42N" 746 | }, 747 | "execution_count": null, 748 | "outputs": [] 749 | }, 750 | { 751 | "cell_type": "markdown", 752 | "source": [ 753 | "Y estamos listos para subir nuestro dataset con las instrucciones para revisarlas antes de avanzar al siguiente paso. Para ello transformamos nuestro dataset al formato necesario de argilla utilizando `to_argilla`, y subimos el dataset a la instancia de argilla utilizando `push_to_argilla`." 754 | ], 755 | "metadata": { 756 | "id": "i6kMlgbBOvvL" 757 | } 758 | }, 759 | { 760 | "cell_type": "code", 761 | "source": [ 762 | "rg_distiset = distiset.to_argilla(vector_strategy=False, metric_strategy=False)" 763 | ], 764 | "metadata": { 765 | "id": "PgEDtg3-QBba" 766 | }, 767 | "execution_count": null, 768 | "outputs": [] 769 | }, 770 | { 771 | "cell_type": "code", 772 | "source": [ 773 | "rg_distiset.push_to_argilla(name=\"instrucciones-distiset\", workspace=workspace)" 774 | ], 775 | "metadata": { 776 | "id": "P_SEu8GPOYCc" 777 | }, 778 | "execution_count": null, 779 | "outputs": [] 780 | }, 781 | { 782 | "cell_type": "markdown", 783 | "source": [ 784 | "### Transformar a un dataset para generación de respuestas\n", 785 | "\n", 786 | "A continuación vamos a transformar nuestro dataset con instrucciones al formato esperado por `distilabel` para la generación, extrayendo todas las instrucciones anidadas, y poniendo la columna \"input\"." 787 | ], 788 | "metadata": { 789 | "id": "KZHm-_XIQZqQ" 790 | } 791 | }, 792 | { 793 | "cell_type": "code", 794 | "source": [ 795 | "rows = []\n", 796 | "from datasets import Dataset\n", 797 | "\n", 798 | "generations = []\n", 799 | "for row in distiset:\n", 800 | " for instructions in row[\"instructions\"]:\n", 801 | " for generation in instructions:\n", 802 | " generations.append(generation)\n", 803 | "\n", 804 | "generation_dataset = Dataset.from_dict({\"input\": generations})" 805 | ], 806 | "metadata": { 807 | "id": "eWTS5xvUQjdH" 808 | }, 809 | "execution_count": null, 810 | "outputs": [] 811 | }, 812 | { 813 | "cell_type": "code", 814 | "source": [ 815 | "generation_dataset" 816 | ], 817 | "metadata": { 818 | "id": "-qy6v5HZRzHx", 819 | "outputId": "749ee2f1-acbe-44bf-d0d4-35ad392e5b73", 820 | "colab": { 821 | "base_uri": "https://localhost:8080/" 822 | } 823 | }, 824 | "execution_count": null, 825 | "outputs": [ 826 | { 827 | "output_type": "execute_result", 828 | "data": { 829 | "text/plain": [ 830 | "Dataset({\n", 831 | " features: ['input'],\n", 832 | " num_rows: 14\n", 833 | "})" 834 | ] 835 | }, 836 | "metadata": {}, 837 | "execution_count": 53 838 | } 839 | ] 840 | }, 841 | { 842 | "cell_type": "markdown", 843 | "source": [ 844 | "# Generación de respuestas con HF Inference endpoints\n", 845 | "\n", 846 | "En esta sección vamos a utilizar el dataset previo `generation_dataset` para generar conjuntos de instrucciones y problemas sintéticos para poder poder ajustar nuestro propio modelo utilizando Supervised Fine Tuning (SFT):" 847 | ], 848 | "metadata": { 849 | "id": "AjDTjpmSsxte" 850 | } 851 | }, 852 | { 853 | "cell_type": "markdown", 854 | "source": [ 855 | "Vamos a crear una tarea genérica para generación de texto, reutilizando la misma descripción que pasamos a nuestra tarea previa a modo de *system_prompt*, para guiar al modelo:" 856 | ], 857 | "metadata": { 858 | "id": "Q-DLvtByUfpJ" 859 | } 860 | }, 861 | { 862 | "cell_type": "code", 863 | "source": [ 864 | "text_generation_task = TextGenerationTask(system_prompt=application_description)\n", 865 | "text_generation_task" 866 | ], 867 | "metadata": { 868 | "id": "4mwFUBpvS_EH", 869 | "outputId": "1de97222-02fb-4645-bfe7-95945d1fa65b", 870 | "colab": { 871 | "base_uri": "https://localhost:8080/" 872 | } 873 | }, 874 | "execution_count": null, 875 | "outputs": [ 876 | { 877 | "output_type": "execute_result", 878 | "data": { 879 | "text/plain": [ 880 | "TextGenerationTask(system_prompt='An AI assistant adept at answering a wide array of math, logic, and reasoning puzzles, trivia, and general questions. Users of this assistant love to ask the assistant to think and outlines the solutions step by step. It expects complete questions from users providing all the details to solve the proposed problem or respond to general knowledge questions. It covers general knowledge about math, puzzles, reasoning exercises, and real-life scenarios where math and reasoning are important. Highly important!! You can only generate text in SPANISH', principles_distribution=None)" 881 | ] 882 | }, 883 | "metadata": {}, 884 | "execution_count": 57 885 | } 886 | ] 887 | }, 888 | { 889 | "cell_type": "markdown", 890 | "source": [ 891 | "La forma de llamar a nuestra `pipeline` va a ser muy similar en este caso, tendremos una nueva `Task`, y dado que los problemas pueden requerir mayor cantidad de texto, vamos a modificar `max_new_tokens` a 1024." 892 | ], 893 | "metadata": { 894 | "id": "VVWn-XgOYIye" 895 | } 896 | }, 897 | { 898 | "cell_type": "code", 899 | "source": [ 900 | "llm = InferenceEndpointsLLM(\n", 901 | " endpoint_name_or_model_id=ENDPOINT_NAME,\n", 902 | " task=text_generation_task,\n", 903 | " token=hf_token,\n", 904 | " prompt_format=\"llama2\",\n", 905 | " max_new_tokens=1024,\n", 906 | " num_threads=4\n", 907 | ")\n", 908 | "\n", 909 | "pipeline = Pipeline(generator=llm)\n", 910 | "distiset_generations = pipeline.generate(\n", 911 | " dataset=generation_dataset,\n", 912 | " num_generations=1,\n", 913 | " batch_size=8,\n", 914 | ")" 915 | ], 916 | "metadata": { 917 | "id": "m6KHFPtqSnGq" 918 | }, 919 | "execution_count": null, 920 | "outputs": [] 921 | }, 922 | { 923 | "cell_type": "markdown", 924 | "source": [ 925 | "Igual que hicimos con nuestras instrucciones, vamos a subir ahora nuestro dataset junto con las respuestas generadas para ver lo que ha generado nuestro modelo." 926 | ], 927 | "metadata": { 928 | "id": "UDnGb_B6XZeu" 929 | } 930 | }, 931 | { 932 | "cell_type": "code", 933 | "source": [ 934 | "rg_distiset_generations = distiset_generations.to_argilla(vector_strategy=False, metric_strategy=False)" 935 | ], 936 | "metadata": { 937 | "id": "mwzJnwSiWSej" 938 | }, 939 | "execution_count": null, 940 | "outputs": [] 941 | }, 942 | { 943 | "cell_type": "code", 944 | "source": [ 945 | "rg_distiset_generations.push_to_argilla(name=\"sciency-distiset\", workspace=workspace)" 946 | ], 947 | "metadata": { 948 | "id": "-9GPSj1SWf7q" 949 | }, 950 | "execution_count": null, 951 | "outputs": [] 952 | }, 953 | { 954 | "cell_type": "markdown", 955 | "source": [ 956 | "# Push al hub\n", 957 | "\n", 958 | "Una vez esté el dataset listo, súbelo a la organización de [SomosNLP](https://huggingface.co/organizations/somosnlp/share/qgytUhPKvxVxsbZWTzVUAUSUnZmVXNPmjc) del hub de Hugging Face. ¡Este paso es imprescindible para participar en el hackathon!" 959 | ], 960 | "metadata": { 961 | "id": "Br5U9PjNg4Ua" 962 | } 963 | } 964 | ] 965 | } -------------------------------------------------------------------------------- /hackathon_2024/entrenamiento_llm_instrucciones.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "id": "view-in-github", 7 | "colab_type": "text" 8 | }, 9 | "source": [ 10 | "\"Open" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": { 16 | "id": "UvszEncV1g7-" 17 | }, 18 | "source": [ 19 | "# Hackathon SomosNLP 2024: Entrenamiento de LLMs\n", 20 | "\n", 21 | "En este tutorial veremos cómo entrenar LLMs para instrucciones / chat con las herramientas de HuggingFace. En la siguiente parte del notebook veremos cómo hacer esto mismo con [autotransformers](https://github.com/lenguajenatural-ai/autotransformers), añadiendo el entrenamiento con NEFTune." 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": { 27 | "id": "VIUWAjOe1g7_" 28 | }, 29 | "source": [ 30 | "Lo primero de todo instalamos la librería `autotransformers` que ya nos va a traer directamente el resto de dependencias que necesitamos." 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": null, 36 | "metadata": { 37 | "id": "X5VJCdZS1g7_" 38 | }, 39 | "outputs": [], 40 | "source": [ 41 | "!pip install autotransformers" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": { 47 | "id": "T4LgPOTi1g8A" 48 | }, 49 | "source": [ 50 | "## Importación de Librerías\n", 51 | "\n", 52 | "Este bloque de código se encarga de importar todas las librerías necesarias para el funcionamiento del script. Se importan herramientas para la manipulación de modelos de aprendizaje automático como `torch` y `transformers`, así como librerías específicas para la preparación y configuración de modelos (`peft`), carga y procesamiento de conjuntos de datos (`datasets`), y una librería especial (`trl`) para el entrenamiento de modelos de lenguaje mediante técnicas de fine-tuning." 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": null, 58 | "metadata": { 59 | "id": "c3RjcDtZ1g8A" 60 | }, 61 | "outputs": [], 62 | "source": [ 63 | "from peft import LoraConfig, prepare_model_for_kbit_training, get_peft_model\n", 64 | "from datasets import load_dataset\n", 65 | "from transformers import BitsAndBytesConfig, TrainingArguments, AutoTokenizer, AutoModelForCausalLM\n", 66 | "from trl import SFTTrainer\n", 67 | "import torch\n", 68 | "from peft.tuners.lora import LoraLayer" 69 | ] 70 | }, 71 | { 72 | "cell_type": "markdown", 73 | "metadata": { 74 | "id": "QExt_XtS1g8A" 75 | }, 76 | "source": [ 77 | "## Creando la plantilla de chat\n", 78 | "\n", 79 | "En esta sección, se crea una plantilla para formatear los mensajes de chat durante el entrenamiento. La plantilla utiliza sintaxis específica para identificar y organizar los roles de los participantes en la conversación (usuario, sistema, asistente, entrada), permitiendo que el modelo comprenda y genere respuestas adecuadas dentro del contexto establecido." 80 | ] 81 | }, 82 | { 83 | "cell_type": "code", 84 | "execution_count": null, 85 | "metadata": { 86 | "id": "ND64q4yf1g8A" 87 | }, 88 | "outputs": [], 89 | "source": [ 90 | "# create chat template\n", 91 | "CHAT_TEMPLATE = \"\"\"{% for message in messages %}\n", 92 | " {% if message['role'] == 'user' %}\n", 93 | " {{' ' + message['content'].strip() + ' ' }}\n", 94 | " {% elif message['role'] == 'system' %}\n", 95 | " {{'\\\\n' + message['content'].strip() + '\\\\n\\\\n\\\\n' }}\n", 96 | " {% elif message['role'] == 'assistant' %}\n", 97 | " {{ message['content'].strip() + ' ' + eos_token }}\n", 98 | " {% elif message['role'] == 'input' %}\n", 99 | " {{' ' + message['content'] + ' ' }}\n", 100 | " {% endif %}\n", 101 | "{% endfor %}\"\"\"" 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": { 107 | "id": "UKCbYM6m1g8B" 108 | }, 109 | "source": [ 110 | "## Carga del dataset y preprocesado\n", 111 | "\n", 112 | "Se carga un dataset específico llamado `somosnlp/somos-clean-alpaca-es` usando la librería `datasets`. Posteriormente, se define y aplica una función de preprocesado (`process_alpaca`) que estructura cada muestra del dataset en un formato adecuado para entrenar chatbots, etiquetando cada mensaje con su respectivo rol en la conversación. Finalmente, el dataset procesado se divide en conjuntos de entrenamiento y prueba." 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": null, 118 | "metadata": { 119 | "id": "Y6YX774V1g8B" 120 | }, 121 | "outputs": [], 122 | "source": [ 123 | "alpaca = load_dataset(\"somosnlp/somos-clean-alpaca-es\")\n", 124 | "\n", 125 | "def process_alpaca(sample: dict) -> dict:\n", 126 | " \"\"\"\n", 127 | " Processes a single sample from the alpaca dataset to structure it for chatbot training.\n", 128 | "\n", 129 | " This function transforms the dataset sample into a format suitable for training,\n", 130 | " where each message is categorized by its role in the conversation (system, input, user, assistant).\n", 131 | " It initializes the conversation with a system message, then conditionally adds an input message,\n", 132 | " follows with the user's instruction, and finally, the assistant's output based on the provided inputs.\n", 133 | "\n", 134 | " Parameters\n", 135 | " ----------\n", 136 | " sample : dict\n", 137 | " A dictionary representing a single sample from the dataset. It must contain\n", 138 | " keys corresponding to input and output components of the conversation.\n", 139 | "\n", 140 | " Returns\n", 141 | " -------\n", 142 | " dict\n", 143 | " A modified dictionary with a 'messages' key that contains a list of ordered messages,\n", 144 | " each annotated with its role in the conversation.\n", 145 | " \"\"\"\n", 146 | " chat = [\n", 147 | " {\"role\": \"system\", \"content\": \"Eres un asistente que resuelve las instrucciones del usuario. Si se proporciona contexto adicional, utiliza esa información para completar la instrucción.\"}\n", 148 | " ]\n", 149 | " inp_ = sample[\"inputs\"][\"2-input\"]\n", 150 | " if inp_ is not None and inp_ != \"\":\n", 151 | " chat.append(\n", 152 | " {\"role\": \"input\", \"content\": inp_}\n", 153 | " )\n", 154 | " chat.extend(\n", 155 | " [\n", 156 | " {\"role\": \"user\", \"content\": sample[\"inputs\"][\"1-instruction\"]},\n", 157 | " {\"role\": \"assistant\", \"content\": sample[\"inputs\"][\"3-output\"]}\n", 158 | " ]\n", 159 | " )\n", 160 | " sample[\"messages\"] = chat\n", 161 | " return sample\n", 162 | "\n", 163 | "alpaca = alpaca.map(\n", 164 | " process_alpaca,\n", 165 | " batched=False,\n", 166 | " num_proc=4,\n", 167 | " remove_columns=[col for col in alpaca[\"train\"].column_names if col != \"messages\"])\n", 168 | "\n", 169 | "alpaca = alpaca[\"train\"].train_test_split(0.2, seed=203984)" 170 | ] 171 | }, 172 | { 173 | "cell_type": "markdown", 174 | "metadata": { 175 | "id": "BZZzvGBl1g8B" 176 | }, 177 | "source": [ 178 | "## Definición de los argumentos de entrenamiento\n", 179 | "\n", 180 | "Se configuran los argumentos de entrenamiento utilizando la clase `TrainingArguments` de la librería `transformers`. Estos argumentos incluyen configuraciones importantes como el tamaño del batch, la tasa de aprendizaje, el tipo de optimizador, y varios otros parámetros que influencian directamente en el rendimiento y la eficiencia del entrenamiento del modelo.\n" 181 | ] 182 | }, 183 | { 184 | "cell_type": "code", 185 | "execution_count": null, 186 | "metadata": { 187 | "id": "Mj3CjGsm1g8B" 188 | }, 189 | "outputs": [], 190 | "source": [ 191 | "training_args = TrainingArguments(\n", 192 | " output_dir=\"./gemma_2b_alpaca\",\n", 193 | " per_device_train_batch_size=1,\n", 194 | " per_device_eval_batch_size=1,\n", 195 | " gradient_accumulation_steps=16,\n", 196 | " warmup_ratio=0.03,\n", 197 | " learning_rate=2e-4,\n", 198 | " bf16=True,\n", 199 | " logging_steps=50,\n", 200 | " lr_scheduler_type=\"constant\",\n", 201 | " weight_decay=0.001,\n", 202 | " eval_steps=200,\n", 203 | " save_steps=50,\n", 204 | " num_train_epochs=1,\n", 205 | " logging_first_step=True,\n", 206 | " evaluation_strategy=\"steps\",\n", 207 | " save_strategy=\"steps\",\n", 208 | " max_grad_norm=0.3,\n", 209 | " optim=\"paged_adamw_32bit\",\n", 210 | " gradient_checkpointing=True,\n", 211 | " group_by_length=False,\n", 212 | " save_total_limit=5,\n", 213 | ")" 214 | ] 215 | }, 216 | { 217 | "cell_type": "markdown", 218 | "metadata": { 219 | "id": "D0RGqqlb1g8B" 220 | }, 221 | "source": [ 222 | "## Carga del tokenizador\n", 223 | "\n", 224 | "Se carga un tokenizador preentrenado correspondiente al modelo `google/gemma-2b` usando la librería `transformers`. Además, se configura el tokenizador con la plantilla de chat creada anteriormente y se ajustan parámetros específicos como el token de relleno y la longitud máxima de secuencia.\n" 225 | ] 226 | }, 227 | { 228 | "cell_type": "code", 229 | "execution_count": null, 230 | "metadata": { 231 | "id": "a_TtTuG81g8B" 232 | }, 233 | "outputs": [], 234 | "source": [ 235 | "model_name = \"google/gemma-2b\"\n", 236 | "max_seq_length = 4096\n", 237 | "tokenizer = AutoTokenizer.from_pretrained(model_name, token=True)\n", 238 | "tokenizer.add_special_tokens({\"pad_token\": \"[PAD]\"})\n", 239 | "tokenizer.model_max_length = max_seq_length\n", 240 | "tokenizer.chat_template=CHAT_TEMPLATE" 241 | ] 242 | }, 243 | { 244 | "cell_type": "markdown", 245 | "metadata": { 246 | "id": "hX2JLBVM1g8C" 247 | }, 248 | "source": [ 249 | "## Función de formateo del chat\n", 250 | "\n", 251 | "Esta función toma las muestras del dataset y las procesa aplicando la plantilla de chat configurada previamente. El objetivo es tokenizar las entradas para que el modelo pueda entender y generar respuestas durante el entrenamiento y la evaluación." 252 | ] 253 | }, 254 | { 255 | "cell_type": "code", 256 | "execution_count": null, 257 | "metadata": { 258 | "id": "xZCBnaZx1g8C" 259 | }, 260 | "outputs": [], 261 | "source": [ 262 | "def format_chat(\n", 263 | " samples: dict,\n", 264 | ") -> dict:\n", 265 | " \"\"\"\n", 266 | " Tokenize inputs for chatbot or instruction tuning.\n", 267 | "\n", 268 | " Parameters\n", 269 | " ----------\n", 270 | " samples: Dict\n", 271 | " Dataset samples to process.\n", 272 | "\n", 273 | " Returns\n", 274 | " -------\n", 275 | " samples: Dict\n", 276 | " Processed samples with tokenized data.\n", 277 | " \"\"\"\n", 278 | " texts = []\n", 279 | " for i in range(len(samples[\"messages\"])):\n", 280 | " full_text = tokenizer.apply_chat_template(\n", 281 | " samples[\"messages\"][i], tokenize=False\n", 282 | " )\n", 283 | " texts.append(full_text)\n", 284 | " return texts" 285 | ] 286 | }, 287 | { 288 | "cell_type": "markdown", 289 | "metadata": { 290 | "id": "tK8hPfq71g8C" 291 | }, 292 | "source": [ 293 | "## Carga del modelo\n", 294 | "\n", 295 | "Se configura y carga el modelo de lenguaje causal para entrenamiento con cuantización y ajustes específicos para mejorar el rendimiento y reducir el consumo de memoria. Se utiliza una configuración específica para LoRA (Low-Rank Adaptation) y QLoRA (Quantized LoRA), ajustando parámetros como el rango y la tasa de dropout, y se prepara el modelo para el entrenamiento con estos ajustes." 296 | ] 297 | }, 298 | { 299 | "cell_type": "code", 300 | "execution_count": null, 301 | "metadata": { 302 | "id": "ErjfOZz21g8C" 303 | }, 304 | "outputs": [], 305 | "source": [ 306 | "lora_config = LoraConfig(\n", 307 | " r=64, # NOTE: Al usar rslora podemos subir el rango con mejoras en el rendimiento.\n", 308 | " lora_alpha=32,\n", 309 | " target_modules=\"all-linear\", # NOTE: En QLoRA entrenamos todas las capas lineales del modelo.\n", 310 | " lora_dropout=0.10, # 0.1 for <13B models, 0.05 otherwise.\n", 311 | " bias=\"none\",\n", 312 | " task_type=\"CAUSAL_LM\",\n", 313 | " use_rslora=True # NOTE: flag para usar QLoRA.\n", 314 | ")" 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": null, 320 | "metadata": { 321 | "id": "k8wppLBw1g8C" 322 | }, 323 | "outputs": [], 324 | "source": [ 325 | "\n", 326 | "qlora_config = BitsAndBytesConfig(\n", 327 | " load_in_4bit=True, # NOTE: Lo cargamos en 4bits.\n", 328 | " bnb_4bit_use_double_quant=True, # NOTE: Usamos la doble cuantización de QLoRA para ahorrar aún más espacio.\n", 329 | " bnb_4bit_quant_type=\"nf4\", # NOTE: Usamos NormalFloat 4bits ya que según el paper de QLoRA funciona mejor.\n", 330 | " bnb_4bit_compute_dtype=torch.bfloat16, # NOTE: Utilizamos para los cálculos bfloat16; cambiar a float16 en arquitecturas no Ampere.\n", 331 | ")\n" 332 | ] 333 | }, 334 | { 335 | "cell_type": "code", 336 | "execution_count": null, 337 | "metadata": { 338 | "id": "MGwV67Cw1g8C" 339 | }, 340 | "outputs": [], 341 | "source": [ 342 | "\n", 343 | "model = AutoModelForCausalLM.from_pretrained(model_name, quantization_config=qlora_config, token=True)\n", 344 | "model = prepare_model_for_kbit_training(model, use_gradient_checkpointing=True)\n", 345 | "model = get_peft_model(model, lora_config)\n", 346 | "model.config.use_cache = False\n" 347 | ] 348 | }, 349 | { 350 | "cell_type": "code", 351 | "execution_count": null, 352 | "metadata": { 353 | "id": "gKm1h7zS1g8C" 354 | }, 355 | "outputs": [], 356 | "source": [ 357 | "for name, module in model.named_modules():\n", 358 | " if isinstance(module, LoraLayer):\n", 359 | " module = module.to(torch.bfloat16)\n", 360 | " if \"norm\" in name:\n", 361 | " module = module.to(torch.float32)\n", 362 | " if \"lm_head\" in name or \"embed_tokens\" in name:\n", 363 | " if hasattr(module, \"weight\"):\n", 364 | " module = module.to(torch.bfloat16)" 365 | ] 366 | }, 367 | { 368 | "cell_type": "markdown", 369 | "metadata": { 370 | "id": "aagdFFeT1g8C" 371 | }, 372 | "source": [ 373 | "# Definición del Trainer y Entrenamiento\n", 374 | "\n", 375 | "Se inicializa el `Trainer` (en este caso un `SFTTrainer` específico para entrenamiento de modelos de lenguaje) con el modelo, los argumentos de entrenamiento, y el dataset formateado. Finalmente, se ejecuta el entrenamiento del modelo utilizando el método `.train()`." 376 | ] 377 | }, 378 | { 379 | "cell_type": "code", 380 | "execution_count": null, 381 | "metadata": { 382 | "id": "MdW-bO5N1g8C" 383 | }, 384 | "outputs": [], 385 | "source": [ 386 | "trainer = SFTTrainer(\n", 387 | " model,\n", 388 | " args=training_args,\n", 389 | " train_dataset=alpaca[\"train\"],\n", 390 | " eval_dataset=alpaca[\"test\"],\n", 391 | " formatting_func=format_chat,\n", 392 | " max_seq_length=max_seq_length\n", 393 | ")" 394 | ] 395 | }, 396 | { 397 | "cell_type": "code", 398 | "execution_count": null, 399 | "metadata": { 400 | "id": "haSt3IIp1g8C" 401 | }, 402 | "outputs": [], 403 | "source": [ 404 | "trainer.train()" 405 | ] 406 | }, 407 | { 408 | "cell_type": "markdown", 409 | "metadata": { 410 | "id": "-d5FzaFh1g8C" 411 | }, 412 | "source": [ 413 | "# Entrenamiento de LLMs con AutoTransformers.\n", 414 | "\n", 415 | "Ahora veremos cómo llevar a cabo esto mismo con `autotransformers`, que simplifica el proceso a la vez que ofrece mayor flexibilidad en cómo se procesan los datos y se lleva a cabo el entrenamiento. Esta parte es una adaptación a español de [este notebook](https://github.com/lenguajenatural-ai/autotransformers/blob/master/notebooks/chatbot_instructions/train_instructional_chatbot.ipynb), que tiene las explicaciones más completas desarrolladas originalmente en inglés." 416 | ] 417 | }, 418 | { 419 | "cell_type": "code", 420 | "execution_count": null, 421 | "metadata": { 422 | "id": "UJzkyEfR1g8D" 423 | }, 424 | "outputs": [], 425 | "source": [ 426 | "from autotransformers import AutoTrainer, DatasetConfig, ModelConfig\n", 427 | "from autotransformers.llm_templates import instructions_to_chat, NEFTuneTrainer, QLoraWrapperModelInit, modify_tokenizer, qlora_config, SavePeftModelCallback\n", 428 | "from functools import partial\n", 429 | "from datasets import load_dataset\n", 430 | "from peft import LoraConfig" 431 | ] 432 | }, 433 | { 434 | "cell_type": "markdown", 435 | "metadata": { 436 | "id": "n0oMRAK71g8D" 437 | }, 438 | "source": [ 439 | "## Creando la Plantilla de Chat\n", 440 | "\n", 441 | "Para formatear correctamente las conversaciones para el entrenamiento, definimos una plantilla de chat usando la sintaxis de plantillas Jinja2. Esta plantilla itera a través de cada mensaje en una conversación, categorizándolos y formateándolos basados en su rol:\n", 442 | "\n", 443 | "- **Mensajes de Usuario**: Envueltos con etiquetas `` para indicar claramente mensajes del usuario. Estos son las instrucciones o consultas dirigidas al chatbot.\n", 444 | "\n", 445 | "- **Mensajes del Sistema**: Encerrados dentro de etiquetas ``, seguidos por saltos de línea para la legibilidad. Estos mensajes podrían incluir instrucciones generadas por el sistema o contexto que guía las respuestas del chatbot.\n", 446 | "\n", 447 | "- **Respuestas del Asistente**: Colocadas entre la conversación, después de las etiquetas `` y marcadas con etiquetas `` al final, junto con el token de fin de oración (EOS). Estas son las respuestas del chatbot o acciones tomadas en respuesta al mensaje del usuario, en cada intervención o turno en la conversación.\n", 448 | "\n", 449 | "- **Datos de Entrada**: Marcados con etiquetas `` para distinguir cualquier entrada adicional o información contextual proporcionada al chatbot.\n", 450 | "\n", 451 | "Este formato estructurado es crucial para que el modelo entienda los diferentes componentes de una conversación, permitiéndole generar respuestas apropiadas basadas en el rol de cada mensaje.\n", 452 | "\n", 453 | "Típicamente, una conversación empezará con el mensaje del sistema, luego tendrá una entrada conteniendo contexto adicional para el asistente, y luego turnos de usuario-asistente, que pueden ser uno o más.\n" 454 | ] 455 | }, 456 | { 457 | "cell_type": "code", 458 | "execution_count": null, 459 | "metadata": { 460 | "id": "rXkp0ZPH1g8D" 461 | }, 462 | "outputs": [], 463 | "source": [ 464 | "CHAT_TEMPLATE = \"\"\"{% for message in messages %}\n", 465 | " {% if message['role'] == 'user' %}\n", 466 | " {{' ' + message['content'].strip() + ' ' }}\n", 467 | " {% elif message['role'] == 'system' %}\n", 468 | " {{'\\\\n' + message['content'].strip() + '\\\\n\\\\n\\\\n' }}\n", 469 | " {% elif message['role'] == 'assistant' %}\n", 470 | " {{ message['content'].strip() + ' ' + eos_token }}\n", 471 | " {% elif message['role'] == 'input' %}\n", 472 | " {{' ' + message['content'] + ' ' }}\n", 473 | " {% endif %}\n", 474 | "{% endfor %}\"\"\"" 475 | ] 476 | }, 477 | { 478 | "cell_type": "markdown", 479 | "metadata": { 480 | "id": "VUjtujSY1g8D" 481 | }, 482 | "source": [ 483 | "## Preparación del Dataset\n", 484 | "\n", 485 | "La fase de preparación del dataset es crucial para estructurar los datos de manera que sea propicia para el entrenamiento de un chatbot. Primero cargamos el dataset desde el hub y luego utilizamos `instructions_to_chat`, para transformar cada muestra del dataset `somos-clean-alpaca` en un formato que refleje un flujo de conversación real involucrando un mensaje del sistema, la entrada del usuario y la respuesta del asistente.\n", 486 | "\n", 487 | "### La Función `instructions_to_chat`\n", 488 | "\n", 489 | "`instructions_to_chat` toma un diccionario que representa una sola muestra del dataset y lo reestructura categorizando y ordenando mensajes basados en su rol en una conversación:\n", 490 | "\n", 491 | "- Comienza agregando un **mensaje del sistema** que establece el contexto para el chatbot como un asistente diseñado para seguir las instrucciones del usuario.\n", 492 | "- Si está presente, los **datos de entrada** se agregan a continuación para proporcionar contexto o información adicional necesaria para cumplir con la solicitud del usuario.\n", 493 | "- La **instrucción del usuario** se añade luego, seguida de la **respuesta del asistente**, que es la respuesta a la solicitud del usuario.\n", 494 | "\n", 495 | "Esta reestructuración resulta en una lista `messages` dentro del diccionario de muestra, conteniendo todos los elementos de la conversación en su orden lógico.\n", 496 | "\n", 497 | "### Aplicando la Transformación\n", 498 | "\n", 499 | "Para aplicar esta transformación a través de todo el dataset:\n", 500 | "\n", 501 | "- Utilizamos el método `.map` con `instructions_to_chat` como la función de mapeo, estableciendo `batched=False` para procesar las muestras individualmente y `num_proc=4` para paralelizar la operación, mejorando la eficiencia.\n", 502 | "- Se eliminan las columnas que no forman parte de la estructura de `messages` para simplificar el dataset.\n", 503 | "\n", 504 | "Finalmente, el dataset se divide en conjuntos de entrenamiento y prueba con un 20% para el tamaño de prueba, asegurando que podamos evaluar el rendimiento de nuestro chatbot en datos no vistos. Esta división se logra usando el método `train_test_split`, proporcionando una base sólida para entrenar y validar el modelo del chatbot." 505 | ] 506 | }, 507 | { 508 | "cell_type": "code", 509 | "execution_count": null, 510 | "metadata": { 511 | "id": "UX8NVVYf1g8D" 512 | }, 513 | "outputs": [], 514 | "source": [ 515 | "alpaca = load_dataset(\"somosnlp/somos-clean-alpaca-es\")" 516 | ] 517 | }, 518 | { 519 | "cell_type": "code", 520 | "execution_count": null, 521 | "metadata": { 522 | "id": "8NMZAYfH1g8D" 523 | }, 524 | "outputs": [], 525 | "source": [ 526 | "alpaca = alpaca.map(\n", 527 | " partial(\n", 528 | " instructions_to_chat,\n", 529 | " input_field=\"1-instruction\",\n", 530 | " context_field=\"2-input\",\n", 531 | " output_field=\"3-output\",\n", 532 | " nested_field=\"inputs\",\n", 533 | " system_message=\"Eres un asistente que resuelve las instrucciones que le presenta el usuario. En caso de tener un contexto adicional, utilízalo para resolver la instrucción.\"\n", 534 | " ),\n", 535 | " batched=False,\n", 536 | " num_proc=4,\n", 537 | " remove_columns=[col for col in alpaca[\"train\"].column_names if col != \"messages\"])" 538 | ] 539 | }, 540 | { 541 | "cell_type": "code", 542 | "execution_count": null, 543 | "metadata": { 544 | "id": "xkbNpQ5p1g8D" 545 | }, 546 | "outputs": [], 547 | "source": [ 548 | "alpaca = alpaca[\"train\"].train_test_split(0.2, seed=203984)" 549 | ] 550 | }, 551 | { 552 | "cell_type": "markdown", 553 | "metadata": { 554 | "id": "RIRusbeh1g8D" 555 | }, 556 | "source": [ 557 | "## Configurando el Dataset para AutoTransformers\n", 558 | "\n", 559 | "Para asegurar que nuestro modelo de chatbot instructivo se entrene de manera eficiente y efectiva, configuramos meticulosamente nuestro dataset usando la configuración de dataset (`DatasetConfig`) de la biblioteca `autotransformers`. Este paso es esencial para adaptar el proceso de entrenamiento a nuestras necesidades específicas, incluyendo la configuración de hiperparámetros, detalles del dataset y estrategias de entrenamiento.\n", 560 | "\n", 561 | "### Configuración de los Argumentos de Entrenamiento\n", 562 | "\n", 563 | "Se define un conjunto de argumentos de entrenamiento fijos (`fixed_train_args`) para controlar varios aspectos del proceso de entrenamiento:\n", 564 | "\n", 565 | "- **Tamaños de lote** tanto para el entrenamiento como para la evaluación se establecen en 1, indicando que las muestras se procesan individualmente. Esto puede ser particularmente útil para modelos grandes o cuando la memoria GPU es limitada.\n", 566 | "- **Acumulación de gradientes** se utiliza con 16 pasos, permitiéndonos simular efectivamente un tamaño de lote más grande y estabilizar el entrenamiento sin exceder los límites de memoria.\n", 567 | "- Un **ratio de calentamiento** de 0.03 aumenta gradualmente la tasa de aprendizaje al comienzo del entrenamiento para prevenir que el modelo converja demasiado rápido a una solución subóptima.\n", 568 | "- **Tasa de aprendizaje**, **decaimiento de peso**, y otros ajustes de optimización son cuidadosamente elegidos para equilibrar la velocidad de aprendizaje del modelo y la calidad.\n", 569 | "- **Estrategias de evaluación y guardado** se configuran para verificar periódicamente el rendimiento del modelo y guardar puntos de control, permitiendo el monitoreo y la continuación del entrenamiento desde el último estado guardado.\n", 570 | "\n", 571 | "### Creando la Configuración del Dataset\n", 572 | "\n", 573 | "El diccionario `alpaca_config` abarca toda la información necesaria para la preparación e integración del dataset:\n", 574 | "\n", 575 | "- **Detalles del dataset** como el nombre, tipo de tarea y columnas específicas a usar para texto y etiquetas aseguran que el modelo se entrene en el formato correcto de datos.\n", 576 | "- **Parámetros de entrenamiento** se incluyen a través del diccionario `fixed_training_args`.\n", 577 | "- **Clases de callback**, como `SavePeftModelCallback`, automatizan pasos importantes como el guardado del modelo durante el entrenamiento.\n", 578 | "- **Optimizaciones de proceso** como establecer una semilla para reproducibilidad, especificar la dirección de optimización y la métrica, y habilitar divisiones parciales para la creación del conjunto de validación.\n" 579 | ] 580 | }, 581 | { 582 | "cell_type": "code", 583 | "execution_count": null, 584 | "metadata": { 585 | "id": "0gB2PiYH1g8D" 586 | }, 587 | "outputs": [], 588 | "source": [ 589 | "fixed_train_args = {\n", 590 | " \"per_device_train_batch_size\": 1,\n", 591 | " \"per_device_eval_batch_size\": 1,\n", 592 | " \"gradient_accumulation_steps\": 16,\n", 593 | " \"warmup_ratio\": 0.03,\n", 594 | " \"learning_rate\": 2e-4,\n", 595 | " \"bf16\": True,\n", 596 | " \"logging_steps\": 50,\n", 597 | " \"lr_scheduler_type\": \"constant\",\n", 598 | " \"weight_decay\": 0.001,\n", 599 | " \"eval_steps\": 200,\n", 600 | " \"save_steps\": 50,\n", 601 | " \"num_train_epochs\": 1,\n", 602 | " \"logging_first_step\": True,\n", 603 | " \"evaluation_strategy\": \"steps\",\n", 604 | " \"save_strategy\": \"steps\",\n", 605 | " \"max_grad_norm\": 0.3,\n", 606 | " \"optim\": \"paged_adamw_32bit\",\n", 607 | " \"gradient_checkpointing\": True,\n", 608 | " \"group_by_length\": False,\n", 609 | " \"save_total_limit\": 50,\n", 610 | " \"adam_beta2\": 0.999\n", 611 | "}" 612 | ] 613 | }, 614 | { 615 | "cell_type": "code", 616 | "execution_count": null, 617 | "metadata": { 618 | "id": "k6ppNLsG1g8D" 619 | }, 620 | "outputs": [], 621 | "source": [ 622 | "alpaca_config = {\n", 623 | " \"seed\": 9834,\n", 624 | " \"callbacks\": [SavePeftModelCallback],\n", 625 | " \"fixed_training_args\": fixed_train_args,\n", 626 | " \"dataset_name\": \"alpaca\",\n", 627 | " \"alias\": \"alpaca\",\n", 628 | " \"retrain_at_end\": False,\n", 629 | " \"task\": \"chatbot\",\n", 630 | " \"text_field\": \"messages\",\n", 631 | " \"label_col\": \"messages\",\n", 632 | " \"num_proc\": 4, #\n", 633 | " \"loaded_dataset\": alpaca, # Aquí metemos el dataset pre-cargado.\n", 634 | " \"partial_split\": True, # NOTE: Para crear una partición de validación.\n", 635 | "}" 636 | ] 637 | }, 638 | { 639 | "cell_type": "code", 640 | "execution_count": null, 641 | "metadata": { 642 | "id": "rIVOvJt01g8D" 643 | }, 644 | "outputs": [], 645 | "source": [ 646 | "alpaca_config = DatasetConfig(**alpaca_config)" 647 | ] 648 | }, 649 | { 650 | "cell_type": "markdown", 651 | "metadata": { 652 | "id": "xGMdfE4b1g8D" 653 | }, 654 | "source": [ 655 | "## Configuración del Modelo\n", 656 | "\n", 657 | "En la sección \"Configuración del Modelo\", delineamos cómo configurar las configuraciones del modelo usando `autotransformers`, enfocándonos en integrar LoRA (Adaptación de Bajo Rango) para la adaptación del modelo y aplicar la cuantización para la eficiencia. Estos pasos son cruciales para personalizar el modelo para nuestra tarea y entorno específicos, asegurando un rendimiento óptimo y la utilización de recursos.\n", 658 | "\n", 659 | "### Configuración de LoRA\n", 660 | "\n", 661 | "El objeto `LoraConfig` se instancia con parámetros diseñados para mejorar la adaptabilidad del modelo mientras se mantiene la eficiencia:\n", 662 | "\n", 663 | "- **r (rango)** y **lora_alpha** se establecen para ajustar la capacidad y el multiplicador de la tasa de aprendizaje para las capas LoRA, equilibrando entre la flexibilidad del modelo y el riesgo de sobreajuste.\n", 664 | "- **target_modules** especifica qué partes del modelo aplicar LoRA. En este caso, se apuntan los módulos \"all-linear\" para la adaptación, ofreciendo una mejora amplia sobre las capacidades del modelo.\n", 665 | "- **lora_dropout** se ajusta según el tamaño del modelo, asegurando que la regularización esté escalada apropiadamente.\n", 666 | "- La configuración de **bias** se establece en \"none\", indicando que no se usan términos de bias adicionales en las capas de adaptación LoRA.\n", 667 | "- El **task_type** se especifica como \"CAUSAL_LM\" para indicar la tarea de modelado del lenguaje causal, alineándose con la naturaleza del chatbot instructivo.\n", 668 | "- El parámetro **use_rslora** se utiliza para activar rank-stabilized lora que nos permite entrenar con rangos más altos.\n", 669 | "\n", 670 | "### Configuración del Modelo GEMMA\n", 671 | "\n", 672 | "La `ModelConfig` para el modelo GEMMA incluye varios parámetros clave y personalizaciones:\n", 673 | "\n", 674 | "- **Nombre del Modelo**: Especifica el modelo preentrenado a ser adaptado, \"google/gemma-2b-it\" en este caso.\n", 675 | "- **Nombre de Guardado y Directorio**: Define la convención de nomenclatura y ubicación para guardar el modelo afinado.\n", 676 | "- **Parámetros Personalizados**: Incluye configuraciones específicas del modelo, como habilitar la confianza en código remoto y configurar el mapeo de dispositivos para el entrenamiento.\n", 677 | "- **Envoltorio de Inicialización del Modelo**: `QLoraWrapperModelInit` se usa para integrar el marco de cuantización QLoRA con el modelo configurado LoRA, optimizando tanto la adaptabilidad como la eficiencia.\n", 678 | "- **Configuraciones de Cantidadización y PEFT**: Se aplican a través de los parámetros `quantization_config` y `peft_config`, asegurando que el modelo se beneficie tanto de las adaptaciones LoRA como de la cuantización eficiente después del entrenamiento.\n", 679 | "- **Modificación del Tokenizador**: Se usa una función parcial para personalizar el tokenizador, ajustando la longitud de secuencia, añadiendo tokens especiales e incorporando la plantilla de chat diseñada para nuestro contexto conversacional.\n" 680 | ] 681 | }, 682 | { 683 | "cell_type": "code", 684 | "execution_count": null, 685 | "metadata": { 686 | "id": "MM3NlVP01g8D" 687 | }, 688 | "outputs": [], 689 | "source": [ 690 | "lora_config = LoraConfig(\n", 691 | " r=64, # NOTE: Al usar rslora podemos subir el rango con mejoras en el rendimiento.\n", 692 | " lora_alpha=32,\n", 693 | " target_modules=\"all-linear\", # NOTE: En QLoRA entrenamos todas las capas lineales del modelo.\n", 694 | " lora_dropout=0.10, # NOTE: 0.1 for <13B models, 0.05 otherwise.\n", 695 | " bias=\"none\",\n", 696 | " task_type=\"CAUSAL_LM\",\n", 697 | " use_rslora=True # NOTE: flag para usar QLoRA.\n", 698 | ")" 699 | ] 700 | }, 701 | { 702 | "cell_type": "code", 703 | "execution_count": null, 704 | "metadata": { 705 | "id": "x_Aab63P1g8D" 706 | }, 707 | "outputs": [], 708 | "source": [ 709 | "gemma_config = ModelConfig(\n", 710 | " name=\"google/gemma-2b-it\",\n", 711 | " save_name=\"gemma_2b\",\n", 712 | " save_dir=\"./gemma_2b_alpaca\",\n", 713 | " model_init_wrap_cls=QLoraWrapperModelInit,\n", 714 | " quantization_config=qlora_config,\n", 715 | " peft_config=lora_config,\n", 716 | " neftune_noise_alpha=10, # NOTE: Este es el parámetro que podemos tocar de NEFTune.\n", 717 | " custom_trainer_cls=NEFTuneTrainer, # NOTE: Un Trainer ajustado para usar NEFTune.\n", 718 | " func_modify_tokenizer=partial(\n", 719 | " modify_tokenizer,\n", 720 | " new_model_seq_length=4096, # lower the maximum seq length to 4096 instead of 8192 to fit in google colab GPUs.\n", 721 | " add_special_tokens={\"pad_token\": \"[PAD]\"}, # add pad token.\n", 722 | " chat_template=CHAT_TEMPLATE # add the new chat template including the system and input roles.\n", 723 | " )\n", 724 | ")" 725 | ] 726 | }, 727 | { 728 | "cell_type": "markdown", 729 | "metadata": { 730 | "id": "Z8aAR30p1g8I" 731 | }, 732 | "source": [ 733 | "## Vamos a Entrenar\n", 734 | "\n", 735 | "Con nuestras configuraciones de dataset y modelo en su lugar, ahora estamos listos para iniciar el proceso de entrenamiento. Aquí es donde entra en juego la clase `AutoTrainer` de la biblioteca `autotransformers`, orquestando toda la operación de entrenamiento basada en las especificaciones que hemos proporcionado.\n", 736 | "\n", 737 | "### Configurando el AutoTrainer\n", 738 | "\n", 739 | "El `AutoTrainer` es una clase integral diseñada para agilizar el entrenamiento de modelos de aprendizaje automático, especialmente adaptada para modelos de lenguaje grandes. Acepta varios parámetros para controlar el proceso de entrenamiento:\n", 740 | "\n", 741 | "- **Configuraciones del Modelo**: Una lista de objetos `ModelConfig`, cada uno definiendo las configuraciones y personalizaciones para un modelo. Para nuestro chatbot instructivo, incluimos la configuración para el modelo GEMMA adaptado con LoRA y cuantización.\n", 742 | "- **Configuraciones del Dataset**: Similar a las configuraciones del modelo, estas se especifican usando objetos `DatasetConfig`. Pasamos la configuración para nuestro dataset `alpaca` preprocesado y estructurado, asegurando que se utilice efectivamente durante el entrenamiento.\n", 743 | "- **Directorio de Métricas**: Especifica el directorio donde se almacenarán las métricas de entrenamiento, permitiendo el monitoreo y evaluación del rendimiento.\n", 744 | "- **Modo de Búsqueda de Hiperparámetros**: Establecido en \"fijo\" en nuestro caso, indicando que no estamos explorando diferentes hiperparámetros sino entrenando con un conjunto predeterminado.\n", 745 | "- **Limpieza**: Una bandera booleana para limpiar los datos de ejecuciones anteriores, asegurando un nuevo inicio para cada sesión de entrenamiento.\n", 746 | "- **Limpiador de Métricas**: Especifica la utilidad para manejar datos temporales de métricas, manteniendo nuestro directorio de métricas ordenado y centrado en resultados significativos.\n", 747 | "- **Usar Token de Autenticación**: Habilita el uso de un token de autenticación, necesario para acceder a ciertos modelos o datasets que pueden tener restricciones de acceso.\n", 748 | "\n", 749 | "### Iniciando el Entrenamiento\n", 750 | "\n", 751 | "Con el `AutoTrainer` configurado, procedemos a llamar a su método de ejecución. Este paso inicia el proceso de entrenamiento, aprovechando las configuraciones que hemos configurado meticulosamente. El proceso implica:\n", 752 | "\n", 753 | "- Cargar y preparar automáticamente el dataset según nuestro `DatasetConfig`.\n", 754 | "- Adaptar y afinar el modelo basado en el `ModelConfig`, incluyendo cualquier mejora de LoRA o cuantización especificada.\n", 755 | "- Evaluar regularmente el rendimiento del modelo usando el conjunto de validación proporcionado, permitiéndonos monitorear su efectividad en tiempo real.\n", 756 | "- Guardar puntos de control del modelo y métricas de entrenamiento, habilitando tanto la introspección del proceso de entrenamiento como la reanudación del entrenamiento desde el último estado guardado.\n", 757 | "\n", 758 | "Al completarse, los resultados del entrenamiento, incluyendo métricas de rendimiento y puntos de control del modelo, están disponibles para análisis y despliegue. Este paso marca la culminación de la preparación de nuestro chatbot instructivo, dejándolo listo para pruebas y eventualmente, despliegue en escenarios del mundo real.\n" 759 | ] 760 | }, 761 | { 762 | "cell_type": "code", 763 | "execution_count": null, 764 | "metadata": { 765 | "id": "KNlf6YFT1g8J" 766 | }, 767 | "outputs": [], 768 | "source": [ 769 | "autotrainer = AutoTrainer(\n", 770 | " model_configs=[gemma_config], # NOTE: Aquí podríamos poner tantos modelos como quisiéramos, y se entrenarían en bucle.\n", 771 | " dataset_configs=[alpaca_config], # NOTE: Aquí también podríamos utilizar tantos datasets como quisiéramos.\n", 772 | " metrics_dir=\"./metrics_alpaca\",\n", 773 | " hp_search_mode=\"fixed\", # NOTE: Normalmente con LLMs no buscamos hiperparámetros ya que sería un proceso demasiado costoso.\n", 774 | " use_auth_token=True\n", 775 | ")" 776 | ] 777 | }, 778 | { 779 | "cell_type": "code", 780 | "execution_count": null, 781 | "metadata": { 782 | "id": "W7DrFr1X1g8J" 783 | }, 784 | "outputs": [], 785 | "source": [ 786 | "results = autotrainer()" 787 | ] 788 | }, 789 | { 790 | "cell_type": "code", 791 | "execution_count": null, 792 | "metadata": { 793 | "id": "gP-VEhD61g8J" 794 | }, 795 | "outputs": [], 796 | "source": [] 797 | } 798 | ], 799 | "metadata": { 800 | "kernelspec": { 801 | "display_name": "autotransformers", 802 | "language": "python", 803 | "name": "python3" 804 | }, 805 | "language_info": { 806 | "codemirror_mode": { 807 | "name": "ipython", 808 | "version": 3 809 | }, 810 | "file_extension": ".py", 811 | "mimetype": "text/x-python", 812 | "name": "python", 813 | "nbconvert_exporter": "python", 814 | "pygments_lexer": "ipython3", 815 | "version": "3.10.12" 816 | }, 817 | "colab": { 818 | "provenance": [], 819 | "include_colab_link": true 820 | } 821 | }, 822 | "nbformat": 4, 823 | "nbformat_minor": 0 824 | } -------------------------------------------------------------------------------- /hackathon_2024/taller_escritura_abstracts_lxai_naacl.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/somosnlp/recursos/ac5d0bfed81fdb8f3cfc453418a59932f81e99be/hackathon_2024/taller_escritura_abstracts_lxai_naacl.pdf -------------------------------------------------------------------------------- /plantillas_docs_proyectos/README.md: -------------------------------------------------------------------------------- 1 | # Plantillas para documentar tus proyectos 2 | 3 | Estas plantillas de Dataset Card y Model Card son una adaptación de las de Hugging Face con comentarios adicionales para ayudarte a rellenarlas. 4 | 5 | ¿Cómo utilizarlas? Copia el contenido **raw** (para incluir los comentarios) en el README.md del repo de tu dataset/modelo en el Hub de Hugging Face y rellena cada sección. Si tienes dudas puedes preguntarle a @mariagrandury en el Discord de la comunidad. 6 | 7 | Como siempre, se aceptan contribuciones, mejoras y comentarios 🤗 8 | -------------------------------------------------------------------------------- /plantillas_docs_proyectos/dataset_card.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | # Dataset Card for < Nombre del corpus > 12 | 13 | 30 | 31 | ## Dataset Details 32 | 33 | ### Dataset Description 34 | 35 | 36 | 37 | - **Curated by:** [More Information Needed] 38 | - **Funded by:** SomosNLP, HuggingFace, Argilla 39 | - **Language(s) (NLP):** [More Information Needed] 40 | - **License:** apache-2.0 41 | 42 | ### Dataset Sources 43 | 44 | - **Repository:** [More Information Needed] 45 | - **Paper [optional]:** [More Information Needed] 46 | - **Demo:** [optional] [More Information Needed] 47 | - **Video presentation:** [optional] [More Information Needed] 48 | 49 | ### Dataset Versions & Formats [optional] 50 | 51 | 52 | 53 | 54 | 55 | ## Uses 56 | 57 | 58 | 59 | ### Direct Use 60 | 61 | 62 | 63 | [More Information Needed] 64 | 65 | ### Out-of-Scope Use 66 | 67 | 68 | 69 | [More Information Needed] 70 | 71 | ## Dataset Structure 72 | 73 | 74 | 75 | 93 | 94 | [More Information Needed] 95 | 96 | ## Dataset Creation 97 | 98 | ### Curation Rationale 99 | 100 | 101 | 102 | [More Information Needed] 103 | 104 | ### Source Data 105 | 106 | 107 | 108 | 109 | 110 | #### Data Collection and Processing 111 | 112 | 113 | 114 | 115 | 116 | [More Information Needed] 117 | 118 | #### Who are the source data producers? 119 | 120 | 121 | 122 | [More Information Needed] 123 | 124 | ### Annotations [optional] 125 | 126 | 127 | 128 | #### Annotation process 129 | 130 | 131 | 132 | 133 | 134 | [More Information Needed] 135 | 136 | #### Who are the annotators? 137 | 138 | 139 | 140 | [More Information Needed] 141 | 142 | #### Personal and Sensitive Information 143 | 144 | 145 | 146 | [More Information Needed] 147 | 148 | ## Bias, Risks, and Limitations 149 | 150 | 151 | 152 | 153 | 154 | [More Information Needed] 155 | 156 | ### Recommendations 157 | 158 | 163 | 164 | [More Information Needed] 165 | 166 | ## License 167 | 168 | 169 | 170 | ## Citation 171 | 172 | 173 | 174 | **BibTeX:** 175 | 176 | [More Information Needed] 177 | 178 | 199 | 200 | ## Glossary [optional] 201 | 202 | 203 | 204 | ## More Information 205 | 206 | 207 | 208 | This project was developed during the [Hackathon #Somos600M](https://somosnlp.org/hackathon) organized by SomosNLP. The dataset was created using `distilabel` by Argilla and endpoints sponsored by HuggingFace. 209 | 210 | **Team:** [More Information Needed] 211 | 212 | 216 | 217 | ## Contact [optional] 218 | 219 | 220 | -------------------------------------------------------------------------------- /plantillas_docs_proyectos/estructura_corpus.md: -------------------------------------------------------------------------------- 1 | # Estructura Corpus 2 | 3 | ## Columnas que incluir 4 | 5 | Por ser corpus de instrucciones debe tener las siguientes columnas: 6 | 7 | - `pregunta` 8 | - `respuesta` 9 | 10 | Además, dado el enfoque en las variedades de la lengua del hackathon, también incluimos las siguientes columnas: 11 | 12 | - `idioma` (variedad geográfica): código ISO del idioma ("catalán" = `ca`, "quechua" = `qu`), en caso de ser español hay que especificar la variedad geográfica ("español de México" = `es_MX`, "español de Ecuador" = `es_EC`). 13 | - `registro` (variedad funcional): `coloquial`, `medio` o `culto` 14 | - `periodo` (variedad histórica): si es un corpus en español elegid entre `actual`, `moderno` (ss. XVIII-XIX), `clásico` (ss. XVI-XVII) o `medieval`, si es en otro idioma rellenar si tenéis conocimiento. 15 | 16 | Para completar la información de los ejemplos incluiremos también: 17 | 18 | - `dominio`: `legal`, `salud` (clínico, biomédico, farmacia), `literatura` (poesía, música, teatro), `sociales` (historia, geografía, etc), `exactas` (física, mates, etc), `prensa`, `gastronomia`, `filosofia` (ética, lógica, etc), `seguros`, ..., `general` (última opción). Si puedes, especifica el subdominio, e.g. `literatura_poesia`, `sociales_historia`. 19 | - `tarea`: `pregunta`, `clasificacion`, `traduccion`, `resumen`, `similitud_semantica`. Si puedes, especifica también la subtarea, e.g. `pregunta_abierta`, `pregunta_opcion_multiple`. 20 | - `país_origen`: código ISO del país de origen de los datos. En general, coincide con la variedad geográfica. Si por ejemplo sabes la zona concreta del país, indícalo también (e.g. `ES (Galicia)`). 21 | - `país_referencia`: código ISO del país al que hace referencia el texto, si aplica. 22 | 23 | Otras consideraciones: 24 | 25 | - Si anotáis manual o sintéticamente una base de datos ya existente, incluid en la nueva versión toda la información disponible en la primera (no eliminéis columnas). 26 | - Si tomáis información de internet o documentos de texto, incluid una columna `origen` con el enlace a la web o al documento como referencia. 27 | - Si el ejemplo ha sido generado sintéticamente, incluid columnas `prompt` y `modelo` con el prompt y modelo utilizados. 28 | 29 | ## Aclaraciones sobre la información de los países 30 | 31 | - La variedad geográfica y el país de origen de los datos suele coincidir, si habéis tomado los datos de una web ".es" seguramente la variedad sea `es_ES`, si es una ley peruana será `es_PE`, si son datos de una red social paraguaya será `es_PY`. Si el corpus ha sido anotado a mano, la variedad geográfica coincide con el país de origen de la persona anotadora. 32 | - El país de referencia no tiene nada que ver con la variedad de la lengua. Ejemplos: 33 | - "Decime tres platos típicos de Cuba", `pais_origen: AR/UY, pais_referencia: CU` 34 | - "¿Cómo le dicen a la micro en Bolivia?", `pais_origen: CL, pais_referencia: BO` 35 | - "Decime cuáles son los vinos más típicos de Mendoza", `pais_origen: AR, pais_referencia: AR` 36 | - "Según la ley colombiana, ¿qué pasa si...?", `pais_referencia: CO` 37 | - "¿Cómo diría un boricua que ...?", `pais_referencia: PR` 38 | 39 | ## Colaboración y preguntas 40 | 41 | Esta guía está en desarrollo, las sugerencias y comentarios son más que bienvenidas. A vuestra disposición en Discord :) 42 | -------------------------------------------------------------------------------- /plantillas_docs_proyectos/model_card.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | # Model Card for < Nombre del modelo > 10 | 11 | 28 | 29 | ## Model Details 30 | 31 | ### Model Description 32 | 33 | 34 | 35 | - **Developed by:** [More Information Needed] 36 | - **Funded by:** SomosNLP, HuggingFace 37 | - **Model type:** Language model, instruction tuned 38 | - **Language(s):** [More Information Needed] 39 | - **License:** apache-2.0 40 | - **Fine-tuned from model:** [More Information Needed] 41 | - **Dataset used:** [More Information Needed] 42 | 43 | ### Model Sources 44 | 45 | - **Repository:** [More Information Needed] 46 | - **Paper:** [optional] [More Information Needed] 47 | - **Demo:** [More Information Needed] 48 | - **Video presentation:** [optional] [More Information Needed] 49 | 50 | ### Model Family [optional] 51 | 52 | 53 | 54 | ## Uses 55 | 56 | 57 | 58 | ### Direct Use 59 | 60 | 61 | 62 | [More Information Needed] 63 | 64 | ### Downstream Use [optional] 65 | 66 | 67 | 68 | [More Information Needed] 69 | 70 | ### Out-of-Scope Use 71 | 72 | 73 | 74 | [More Information Needed] 75 | 76 | ## Bias, Risks, and Limitations 77 | 78 | 79 | 80 | [More Information Needed] 81 | 82 | ### Recommendations 83 | 84 | 85 | 86 | 87 | 88 | ## How to Get Started with the Model 89 | 90 | Use the code below to get started with the model. 91 | 92 | ``` 93 | 94 | [More Information Needed] 95 | 96 | ``` 97 | 98 | ## Training Details 99 | 100 | ### Training Data 101 | 102 | 103 | 104 | [More Information Needed] 105 | 106 | ### Training Procedure 107 | 108 | 109 | 110 | 111 | 112 | #### Preprocessing [optional] 113 | 114 | [More Information Needed] 115 | 116 | #### Training Hyperparameters 117 | 118 | 119 | 120 | - **Training regime:** 121 | 122 | #### Speeds, Sizes, Times [optional] 123 | 124 | 125 | 126 | [More Information Needed] 127 | 128 | ## Evaluation 129 | 130 | 131 | 132 | ### Testing Data, Factors & Metrics 133 | 134 | #### Testing Data 135 | 136 | 137 | 138 | [More Information Needed] 139 | 140 | #### Factors 141 | 142 | 143 | 144 | [More Information Needed] 145 | 146 | #### Metrics 147 | 148 | 149 | 150 | [More Information Needed] 151 | 152 | ### Results 153 | 154 | 155 | 156 | [More Information Needed] 157 | 158 | ## Model Examination [optional] 159 | 160 | 161 | 162 | [More Information Needed] 163 | 164 | ## Environmental Impact 165 | 166 | 167 | 168 | 169 | 170 | Carbon emissions can be estimated using the [Machine Learning Impact calculator](https://mlco2.github.io/impact#compute) presented in [Lacoste et al. (2019)](https://arxiv.org/abs/1910.09700). 171 | 172 | - **Hardware Type:** [More Information Needed] 173 | - **Hours used:** [More Information Needed] 174 | - **Cloud Provider:** [More Information Needed] 175 | - **Compute Region:** [More Information Needed] 176 | - **Carbon Emitted:** [More Information Needed] 177 | 178 | ## Technical Specifications [optional] 179 | 180 | 181 | 182 | ### Model Architecture and Objective 183 | 184 | [More Information Needed] 185 | 186 | ### Compute Infrastructure 187 | 188 | [More Information Needed] 189 | 190 | #### Hardware 191 | 192 | 193 | 194 | [More Information Needed] 195 | 196 | #### Software 197 | 198 | 199 | 200 | [More Information Needed] 201 | 202 | ## License 203 | 204 | 205 | 206 | ## Citation 207 | 208 | **BibTeX:** 209 | 210 | [More Information Needed] 211 | 212 | 233 | 234 | ## Glossary [optional] 235 | 236 | 237 | 238 | ## More Information 239 | 240 | 241 | 242 | This project was developed during the [Hackathon #Somos600M](https://somosnlp.org/hackathon) organized by SomosNLP. The model was trained using GPUs sponsored by HuggingFace. 243 | 244 | **Team:** [More Information Needed] 245 | 246 | 250 | 251 | ## Contact [optional] 252 | 253 | 254 | -------------------------------------------------------------------------------- /proyectos_de_la_comunidad/2023_01_12_biomedia.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/somosnlp/recursos/ac5d0bfed81fdb8f3cfc453418a59932f81e99be/proyectos_de_la_comunidad/2023_01_12_biomedia.pdf --------------------------------------------------------------------------------