{"id":56,"date":"2025-11-25T15:48:42","date_gmt":"2025-11-25T15:48:42","guid":{"rendered":"https:\/\/pulki.es\/blog\/?p=56"},"modified":"2025-11-25T15:49:44","modified_gmt":"2025-11-25T15:49:44","slug":"large-language-model-llm-from-scratch-intro","status":"publish","type":"post","link":"https:\/\/pulki.es\/blog\/index.php\/2025\/11\/25\/large-language-model-llm-from-scratch-intro\/","title":{"rendered":"Large Language Model (LLM) from scratch. Intro."},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Un <em>Large Language Model<\/em> (LLM) es un tipo de modelo capaz de entender y generar lenguaje natural, y se entrena utilizando grandes cantidades de datos. El ejemplo m\u00e1s popular de este tipo de modelos es ChatGPT, conocido por la calidad de sus respuestas, que se debe al alto nivel de inteligencia que ha alcanzado.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Si bien ChatGPT \u2014y otros modelos similares\u2014 puede resolver una lista pr\u00e1cticamente interminable de problemas actuales, existen razones de peso para plantearse el desarrollo de un LLM propio. A mi juicio, la m\u00e1s importante es el control sobre las salidas del modelo. Como comentamos, estos sistemas se entrenan con cantidades masivas de datos, en su mayor\u00eda procedentes de la web u otras fuentes cuya fiabilidad no siempre puede verificarse por completo. Esto abre la puerta a respuestas sesgadas o, en el peor de los casos, claramente inapropiadas.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><br>Aunque OpenAI ha invertido un esfuerzo considerable en mitigar este tipo de comportamientos (con un \u00e9xito razonable), considero que, para una instituci\u00f3n \u2014especialmente gubernamental\u2014 el escenario ideal consiste en minimizar al m\u00e1ximo la probabilidad de que el modelo genere contenido que pueda da\u00f1ar su reputaci\u00f3n o credibilidad. Una forma de avanzar en esa direcci\u00f3n es construir y depurar un conjunto de datos cuya fiabilidad pueda ser auditada por la propia instituci\u00f3n y utilizarlo como base para entrenar (o especializar) el modelo. Por ello, dise\u00f1ar LLMs orientados a fines espec\u00edficos puede resultar especialmente valioso.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dicho lo anterior, y antes de empezar con el tutorial, hay dos puntos que aclarar. <strong>Primero<\/strong>: <em>OpenAI<\/em> dispone de <a href=\"https:\/\/platform.openai.com\/docs\/guides\/model-optimization\">herramientas<\/a> para mitigar salidas no deseadas. <strong>Segundo<\/strong>: con la tecnolog\u00eda actual, incluso si la entrada de datos es cien por ciento fiable, la probabilidad de que el modelo genere salidas no deseadas no ser\u00e1 cero.<\/p>\n\n\n\n<figure class=\"wp-block-pullquote\"><blockquote><p><strong><em>Manos a la obra<\/em><\/strong><\/p><\/blockquote><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">En este tutorial utilizaremos como referencia el libro de Daniel <a href=\"https:\/\/web.stanford.edu\/~jurafsky\/slp3\/ed3book_aug25.pdf\">Jurafsky y James H. Martin (2025)<\/a>. En particular, en esta entrada seguiremos de cerca el cap\u00edtulo 2, que define conceptos clave que ser\u00e1n \u00fatiles para codear nuestro primer LLM tipo transformer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Primero, es necesario explicar c\u00f3mo funcionar\u00e1 el modelo. En t\u00e9rminos simples, el modelo recibe un texto de entrada y, a partir de \u00e9l, genera un nuevo texto como salida. Para poder hacerlo, necesita transformar ese texto en unidades que pueda manejar internamente. Lo habitual es definir un <strong>vocabulario<\/strong> de tokens (peque\u00f1as unidades de texto) e incorporarlo al modelo, de modo que pueda mapear cada fragmento del texto de entrada a un token conocido y, con esa representaci\u00f3n, calcular paso a paso los tokens que compondr\u00e1n la respuesta.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">De manera intuitiva, podr\u00eda pensarse que dicho <strong>vocabulario<\/strong> deber\u00eda estar formado por palabras completas. Sin embargo, esto plantea un problema importante: el n\u00famero de palabras distintas crece a medida que aumenta la cantidad de texto. En la pr\u00e1ctica, esto significa que, si us\u00e1ramos solo palabras como unidades, el modelo se encontrar\u00eda continuamente con formas que no est\u00e1n en su vocabulario fijo (palabras fuera de vocabulario) y no podr\u00eda representarlas adecuadamente. Por este motivo, es necesario considerar unidades alternativas. A continuaci\u00f3n presentamos otro posible candidato: los <strong>morfemas<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><em>Morfemas&#8230;<\/em><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Como sabemos, una palabra posee significado. Sin embargo, desde una perspectiva ling\u00fc\u00edstica tambi\u00e9n es posible centrarse en una sola palabra y buscar unidades de significado m\u00e1s peque\u00f1as en su interior. A estas unidades se les llama <strong>morfemas<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Por ejemplo, la palabra <strong>\u201cviv\u00eda\u201d<\/strong> puede analizarse en dos morfemas: el lexema <strong>\u201cviv-\u201d<\/strong>, que aporta el significado b\u00e1sico (<em>vivir<\/em>), y <strong>\u201c-\u00eda\u201d<\/strong>, que es el morfema verbal flexivo que indica tiempo, modo y persona. En este sentido, podr\u00edamos definir una unidad como \u201cviv\u201d y otra como \u201c\u00eda\u201d. As\u00ed, si nuestro vocabulario contiene las unidades \u201cviv\u201d, \u201c\u00eda\u201d y \u201csab\u201d, y en el texto de entrada aparece la palabra <strong>\u201csab\u00eda\u201d<\/strong>, el modelo podr\u00eda representarla combinando \u201csab\u201d + \u201c\u00eda\u201d, sin necesidad de que \u201csab\u00eda\u201d est\u00e9 incluida expl\u00edcitamente en el vocabulario.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">El problema es que, en la pr\u00e1ctica, no siempre hay un consenso claro sobre <strong>d\u00f3nde cortar<\/strong> el morfema. Si hilamos fino, \u201cviv\u00eda\u201d tambi\u00e9n puede descomponerse como <strong>\u201cviv-\u201d<\/strong> (lexema), <strong>\u201c-\u00ed-\u201d<\/strong> (vocal tem\u00e1tica) y <strong>\u201c-a\u201d<\/strong> (desinencia de imperfecto), lo que nos dar\u00eda tres unidades en vez de dos, como en el ejemplo anterior. Es decir, el n\u00famero y los l\u00edmites de los morfemas dependen del criterio te\u00f3rico y del nivel de detalle que adoptemos.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Debido a esta dificultad para definir y segmentar morfemas de forma clara y autom\u00e1tica (adem\u00e1s de otros problemas t\u00e9cnicos que exceden esta entrada), los morfemas, por s\u00ed solos, no constituyen un buen candidato de vocabulario para el modelo.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><em>Caracteres individuales&#8230;<\/em><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Entonces, si usar palabras o morfemas como tokens no resulta adecuado, podr\u00edamos pensar que un buen vocabulario ser\u00edan los caracteres individuales. Sin embargo, esta opci\u00f3n tambi\u00e9n tiene importantes inconvenientes: al representar cada car\u00e1cter como un token, el n\u00famero de tokens por texto se dispara, lo que encarece mucho el entrenamiento (las secuencias son m\u00e1s largas y el modelo debe procesar muchos m\u00e1s pasos) y hace la inferencia m\u00e1s lenta y menos eficiente.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><em>Byte-pair Encoding (BPE)<\/em><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Como vimos, si utilizamos palabras completas como tokens, las palabras desconocidas se convierten en un problema. Tambi\u00e9n vimos que los morfemas como unidad de tokenizaci\u00f3n no son una opci\u00f3n pr\u00e1ctica, y que trabajar a nivel de caracteres resulta, entre otras cosas, mucho m\u00e1s costoso. Una soluci\u00f3n intermedia entre estas alternativas es el algoritmo <strong>BPE<\/strong>. Este algoritmo aprende un vocabulario de <strong>subpalabras<\/strong> que puede incluir caracteres sueltos, fragmentos de palabra cercanos a morfemas e incluso palabras completas, reduciendo de forma considerable el problema de las palabras fuera de vocabulario y mejorando la eficiencia con respecto a usar solo caracteres. En la siguiente entrada explicaremos este algoritmo con m\u00e1s detalle.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><em>Notas finales, y pr\u00f3xima entrada&#8230;<\/em><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En esta serie de publicaciones mostraremos c\u00f3mo construir un LLM desde cero. Para ello, era fundamental exponer algunas ideas clave, como <strong>vocabulario<\/strong>, <strong>tokens<\/strong> y la motivaci\u00f3n detr\u00e1s de algoritmos como <strong>BPE<\/strong>. Ahora, con esta base en mente, en la siguiente entrada explicaremos en detalle c\u00f3mo funciona dicho algoritmo.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Jos\u00e9 Miguel Mu\u00f1oz Urra \u2013\u00a0<a href=\"mailto:jmunozu@pulki.es\">jmunozu@pulki.es<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Un Large Language Model (LLM) es un tipo de modelo capaz de entender y generar lenguaje natural, y se entrena utilizando grandes cantidades de datos. El ejemplo m\u00e1s popular de este tipo de modelos es ChatGPT, conocido por la calidad de sus respuestas, que se debe al alto nivel de inteligencia que ha alcanzado. Si [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-56","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/posts\/56","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=56"}],"version-history":[{"count":3,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/posts\/56\/revisions"}],"predecessor-version":[{"id":59,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/posts\/56\/revisions\/59"}],"wp:attachment":[{"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=56"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=56"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=56"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}