{ "cells": [ { "cell_type": "markdown", "id": "65c9fdf3", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Hugging Face: IA Colaborativa\n", "=========================" ] }, { "cell_type": "markdown", "id": "32a802c2", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "¿Quién soy?\n", "------------------\n", "\n", "
\n", "

Cristian Cardellino

\n", "
Profesor de FAMAFyC (UNC) - Investigador en Mercado Libre
\n", "
\n", " \n", "
\n", "
\n", " @crscardellino -\n", " @crscardellino@mastodon.social -\n", " https://crscardellino.ar\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "bb685a55", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Esquema de la charla\n", "\n", "1. [¿Qué hay detrás de ChatGPT?](#¿Qué-hay-detrás-de-ChatGPT?)\n", "2. [Hugging Face](#Hugging-Face)\n", "3. [Utilizando un modelo de Hugging Face](#Utilizando-un-modelo-de-Hugging-Face)\n", "4. Personalizando un modelo de Hugging Face" ] }, { "cell_type": "markdown", "id": "eb7f3997", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# ¿Qué hay detrás de ChatGPT?" ] }, { "cell_type": "markdown", "id": "87d1ca59", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## ¿Cómo continúa esta frase?\n", "\n", "

You ...

" ] }, { "cell_type": "markdown", "id": "1e5a5c6b", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "

You shall ...

" ] }, { "cell_type": "markdown", "id": "f71da59e", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "

You shall not ...

" ] }, { "cell_type": "markdown", "id": "2910e985", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "
\n", "

You shall not pass!

\n", "
\n", " \n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "283ca08c", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## ¿Qué son los \"modelos de lenguaje\"? (Language Models)\n", "\n", "- Modelos de aprendizaje automático.\n", "- Dado un contexto (e.g. una lista de palabras previas), predicen la palabra siguiente.\n", "- Se entrenan con texto libre." ] }, { "cell_type": "markdown", "id": "778b5e91", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "### ¿Qué son los \"LLMs\"? (Large Language Models)\n", "\n", "- Modelos de lenguajes entrenados con una gran cantidad de datos y de parámetros:\n", " - Suelen entrenarse con corpus del orden de $10^{10}$ palabras.\n", " - Suelen tener de $10^8$ o $10^9$ parámetros en adelante.\n", "- El término se asocia generalmente a aquellos modelos basados en la arquitectura neuronal del **Transformer**." ] }, { "cell_type": "markdown", "id": "cfc710ea", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## ¿Qué es un \"Transformer\"?\n", "\n", "- Es una arquitectura de red neuronal basada en el concepto de \"Atención\" que se presentó en el paper [\"Attention is All You Need\"](https://arxiv.org/abs/1706.03762).\n", "- Originalmente se planteó como un esquema para hacer traducción automática.\n", " - Consta de dos partes: Un codificador y un decodificador.\n", " - A partir de este surgieron dos variantes\n", " - Los modelos basados en el codificador (e.g. [BERT](https://arxiv.org/abs/1810.04805)). Sirven para buscar representaciones vectoriales (embeddings) del texto.\n", " - Los modelos basados en el decodificador (e.g. [GPT](https://arxiv.org/abs/2005.14165)). Sirven para generación de texto.\n", "- La idea del transformer es \"definir\" una palabra de acuerdo a la relación que tiene con las palabras de su vecindario, en una operación de multiplicación matricial con pesos.\n", " - Para una explicación más sencilla pero más detallada sugiero los posts de la serie \"The Illustrated...\" de [Jay Alammar](http://jalammar.github.io/):\n", " - [The Illustrated Transformer](http://jalammar.github.io/illustrated-transformer/)\n", " - [The Illustrated BERT](http://jalammar.github.io/illustrated-bert/)\n", " - [The Illustrated GPT-2](http://jalammar.github.io/illustrated-gpt2/) / [How GPT-3 Works](http://jalammar.github.io/how-gpt3-works-visualizations-animations/)" ] }, { "cell_type": "markdown", "id": "8958cf42", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Hugging Face" ] }, { "cell_type": "markdown", "id": "6038bd78", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## ¿Qué es Hugging Face?\n", "\n", "- Una [comunidad colaborativa](https://huggingface.co/) para hacer Inteligencia Artificial (IA).\n", "- Cuenta con repositorios para subir [modelos](https://huggingface.co/models), [datasets](https://huggingface.co/datasets) y [demos](https://huggingface.co/spaces).\n", "- Además, ofrecen varias librerías orientadas a la IA, particularmente al Aprendizaje Profundo (Deep Learning), entre las que destacan:\n", " - [`transformers`](https://huggingface.co/docs/transformers): La que veremos en esta charla, para todo lo relacionado a NLP con LLMs.\n", " - [`datasets`](https://huggingface.co/docs/datasets): Una librería especializada en el tratamiento de los conjuntos de datos a utilizar para entrenar/ajustar los LLMs.\n", " - [`tokenizers`](https://huggingface.co/docs/tokenizers): Para el proceso de \"tokenización\", i.e. la división de texto de manera discreta en palabras o subpalabras.\n", "- Hugging Face no sólo ofrece soluciones sobre NLP, sino que también lo hace con imágenes, con librerías como [`diffusers`](https://huggingface.co/docs/diffusers), para la generación de imágenes:\n", " - Lectura recomendada: [The Illustrated Stable Diffusion](http://jalammar.github.io/illustrated-stable-diffusion/)" ] }, { "cell_type": "markdown", "id": "25ad7d45", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## ¿Cómo empezar con Hugging Face?\n", "\n", "- Primero se [crea una cuenta en la página](https://huggingface.co/join).\n", "- Luego podemos [crear modelos](https://huggingface.co/new) a través del menú que se despliega de nuestro avatar.\n", "- Una vez creado el modelo, este es un repositorio de git que puede accederse clonándolo localmente.\n", " - Requiere de [`git-lfs`](https://git-lfs.com/)." ] }, { "cell_type": "markdown", "id": "3c6f89c3", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Utilizando un modelo de Hugging Face" ] }, { "cell_type": "markdown", "id": "f91311b5", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Cargando los modelos\n", "\n", "- Hugging Face ofrece muchísimos modelos en su [repositorio](https://huggingface.co/models), para este caso elegimos el modelo [`bigscience/bloom-3b`](https://huggingface.co/bigscience/bloom-3b) de la organización [Big Science](https://bigscience.huggingface.co/blog/bloom).\n", " - Esta organización ha estado [creando modelos](https://huggingface.co/bigscience) bajo una [licencia abierta](https://bigscience.huggingface.co/blog/the-bigscience-rail-license) (con ciertas limitaciones de uso para evitar abuso).\n", " - Son responsables del [LLM abierto más grande actualmente disponible](https://huggingface.co/bigscience/bloom).\n", "- El modelo elegido es un modelo de 3 mil millones (3 billion) de parámetros." ] }, { "cell_type": "code", "execution_count": null, "id": "d3225616", "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "import torch\n", "\n", "from IPython.display import display, HTML\n", "from transformers import AutoModelForCausalLM, AutoTokenizer\n", "\n", "BASE_MODEL = 'bigscience/bloom-3b' # More models at https://huggingface.co/models\n", "\n", "tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL)\n", "model = AutoModelForCausalLM.from_pretrained(\n", " BASE_MODEL,\n", " low_cpu_mem_usage=True,\n", " torch_dtype='auto'\n", ")" ] }, { "cell_type": "markdown", "id": "b523bf51", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Generando Texto a Partir de un PROMPT\n", "\n", "- Los modelos de lenguaje necesitan una semilla, denominada comúnmente **prompt**, para iniciar su conversación.\n", "- A partir de dicha semilla, los modelos pueden empezar a predecir las palabras siguiente.\n", "- La coherencia de la frase depende de varios aspectos:\n", " - El tamaño y [entrenamiento](https://github.com/huggingface/notebooks/blob/main/examples/language_modeling_from_scratch.ipynb) o [ajuste](https://github.com/huggingface/notebooks/blob/main/examples/language_modeling.ipynb) (fine-tuning) del modelo.\n", " - Modelos más grandes suelen ser mejor en escenarios \"open end\", aunque pueden desvariar (o \"alucinar\").\n", " - El tipo de datos con el que se entrenó/ajustó el modelo.\n", " - La [estrategia](https://github.com/huggingface/blog/blob/main/notebooks/02_how_to_generate.ipynb) a la hora de generar texto.\n", " - La [documentación de Hugging Face](https://huggingface.co/docs/transformers/notebooks) tiene más ejemplos que pueden reproducirse." ] }, { "cell_type": "markdown", "id": "eed5b04f", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Estableciendo un PROMPT\n", "\n", "- El **prompt** inicial es el que \"ayudará\" al modelo a devolver resultados más o menos coherentes.\n", "- Actualmente es más un arte que una ciencia.\n", " - **No existe el \"prompt engineering\" porque los modelos no son determinísticos.**\n", "- Depende muchísimo del modelo, la inicialización aleatoria (i.e. la suerte), la tarea que se busca resolver, entre otros factores.\n", "- Siguiendo los ejemplos de [esta publicación](https://medium.com/@fractal.ai/create-conversational-agents-using-bloom-part-1-63a66e6321c0), y en vistas de armar un chatbot, buscaré definir 3 cosas:\n", " - La \"identidad\", i.e. ¿Qué es?\n", " - La \"intención\", i.e. ¿Qué hace?\n", " - El \"comportamiento\", i.e. ¿Cómo lo hace?\n", "- Además, se le pueden dar ejemplos concretos de cómo se espera que interactúe. Estos sirven a los LLMs para hacer lo que se conoce como \"Few Shot Learning\" (aunque no están \"aprendiendo\", los ejemplos sólo ayudan a mejorar el contexto." ] }, { "cell_type": "code", "execution_count": null, "id": "d6f85ea7", "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "PROMPT = \"\"\"\n", "La siguiente es una conversación entre un HUMANO y un bot EXPERTO en software libre.\n", "El EXPERTO le ayuda al HUMANO con preguntas acerca de software libre.\n", "El EXPERTO es conversacional, optimista, flexible, creativo y genera respuestas parecidas a un humano.\n", "\n", "HUMANO: Hola, ¿Cómo estás?\n", "EXPERTO: Hola, pmuy bien. Estoy acá para ayudarte con preguntas respecto al software libre.\n", "\n", "HUMANO: ¿Qué es el software libre?\n", "EXPERTO:\"\"\".strip()" ] }, { "cell_type": "markdown", "id": "fc3a8ded", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Generando texto de manera \"Greedy\"\n", "\n", "- La estrategia para generar texto puede variar. La opción más directa es **greedy**, i.e. devolver la palabra que es más probable después de la secuencia.\n", " - La principal ventaja de esta alternativa, es que es determinística, i.e. ante la misma entrada debería devolver la misma salida.\n", " - La principal desventaja es que tiende a repetir y quedar limitada a ciertas frases o palabras." ] }, { "cell_type": "code", "execution_count": null, "id": "33e984d7", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "MAX_TOKENS = 50\n", "input_ids = tokenizer.encode(PROMPT, return_tensors='pt')\n", "greedy_output = model.generate(input_ids, max_length=input_ids.shape[1] + MAX_TOKENS)\n", "output = tokenizer.decode(greedy_output[0], skip_special_tokens=True)\n", "\n", "print(output)" ] }, { "cell_type": "markdown", "id": "db1bc6cc", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Generando texto usando aleatoriedad\n", "\n", "- Si bien hay [varias estrategias para generar texto libre](https://github.com/huggingface/blog/blob/main/notebooks/02_how_to_generate.ipynb) una que resulta muy interesante es mediante el sampleo estadístico.\n", "- La idea es que la manera de seleccionar la siguiente palabra es con cierta probabilidad estadística (i.e. no siempre la más probable).\n", " - La principal ventaja es que hace el texto más \"creativo\" y más \"humano\".\n", " - La principal desventaja es que no es determinístico y es suceptible de \"alucinar\".\n", " - En este caso se samplea de las `top_k` palabras más probable que a su vez son la menor cantidad de palabras cuya probabilidad conjunta es mayor que `top_p`." ] }, { "cell_type": "code", "execution_count": null, "id": "bf547d6a", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "torch.manual_seed(42) # To ensure determinism\n", "\n", "sampling_output = model.generate(\n", " input_ids,\n", " do_sample=True,\n", " max_length=input_ids.shape[1] + MAX_TOKENS,\n", " top_k=50,\n", " top_p=0.95,\n", ")\n", "output = tokenizer.decode(sampling_output[0], skip_special_tokens=True)\n", "\n", "print(output)" ] }, { "cell_type": "markdown", "id": "50d2c808", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Un Chatbot Sencillo\n", "\n", "- El modelo de lenguaje no tiene noción de cuando parar, porque está entrenado para continuar el mensaje dado en el **prompt**.\n", " - Seguirá generando texto hasta alcanzar el valor del parámetro `max_length`.\n", " - El texto generado inluirá las palabras que marcan la conversación (i.e. \"HUMANO\" y \"EXPERTO\").\n", "- Para poder utilizar un modelo para hacer un **chatbot** requerimos de un poco de ingeniería de software clásica.\n", " - Una opción es utilizar precisamente las palabras que definen la conversación como puntos de inicio y final, y descartar el resto.\n", "- En [`chatbot.py`](./chatbot.py) hay un ejemplo sencillo de cómo puede realizarse esto.\n", " - Consiste de una clase `ChatBot` que sirve como *wrapper* de los modelos de Hugging Face.\n", " - Posee un CLI sencillo que mantiene un loop continuo para chatear." ] }, { "cell_type": "code", "execution_count": null, "id": "cff18d7f", "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "from chatbot import ChatBot\n", "\n", "PROMPT = \"\"\"\n", "La siguiente es una conversación entre un HUMANO y un bot EXPERTO en software libre.\n", "El EXPERTO le ayuda al HUMANO con preguntas acerca de software libre.\n", "El EXPERTO es conversacional, optimista, flexible, creativo y genera respuestas parecidas a un humano.\n", "\n", "HUMANO: Hola, ¿Cómo estás?\n", "EXPERTO: Hola, muy bien. Estoy acá para ayudarte con preguntas respecto al software libre.\n", "\"\"\".strip()\n", "\n", "chatbot = ChatBot(\n", " base_model=model,\n", " tokenizer=tokenizer,\n", " initial_prompt=PROMPT,\n", " keep_context=True,\n", " creative=True,\n", " human_identifier='HUMAN',\n", " bot_identifier='EXPERTO'\n", ")\n", "\n", "while True:\n", " input_text = input('> ')\n", " if input_text == 'exit' or input_text == 'quit':\n", " break\n", " print(chatbot.chat(input_text))" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.8" }, "rise": { "scroll": true } }, "nbformat": 4, "nbformat_minor": 5 }