sábado, 30 de mayo de 2026

La evolución del desarrollo de software con IA: De copiar y pegar al desarrollo síncrono dirigido por especificaciones

El panorama de la programación ha cambiado radicalmente en los últimos dos años. Lo que empezó como una interacción básica con un chatbot se ha transformado en un ecosistema complejo de agentes autónomos, flujos de trabajo asíncronos y metodologías estructuradas.

A lo largo de mi carrera he visto pasar muchas tecnologías, pero la velocidad de esta última ola es inédita. A continuación, me gustaría explicar cómo he vivido en primera persona la evolución de este viaje tecnológico desde mediados de 2024 hasta la actualidad, y cómo los desarrolladores senior estamos adaptando nuestras metodologías para no perder el control de la base de código.

1. La era del "Copiar y Pegar" (Mediados de 2024)

Hace apenas un par de años (ya hablé sobre esto en un artículo anterior), la integración de la Inteligencia Artificial en nuestro día a día era puramente manual y externa. El flujo de trabajo estándar de cualquier ingeniero consistía en una interacción biodireccional, fragmentada y bastante rudimentaria:

  • De la IDE al Chatbot: Seleccionábamos un fragmento de código en editores como Visual Studio Code, lo copiábamos y lo pegábamos directamente en la interfaz web de modelos como GPT.
  • Las peticiones típicas: Nuestros prompts se limitaban a revisiones superficiales: "¿Puedes revisar este código?", "¿Cómo puedo mejorarlo?" o "Genera un script en Python que haga X cosa".
  • Del Chatbot a la IDE: Una vez que la IA generaba la respuesta, copiábamos el código de vuelta a nuestro entorno local para compilarlo, ejecutarlo y testearlo.

Si bien este método ya representaba una mejora sustancial frente a programar en absoluta soledad, distaba mucho de ser un flujo de trabajo óptimo, fluido o integrado en el ciclo de vida del software.

2. El salto a los Agentes de Código integrados

Hoy en día, el panorama es completamente distinto gracias a la integración directa de los Modelos de Lenguaje (LLMs) en nuestros entornos de desarrollo a través de plugins y, especialmente, mediante agentes de código (coding agents).

Para los desarrolladores que, como yo, preferimos la terminal, herramientas de línea de comandos como Claude Code (que lo normal es ejecutarla sobre la infraestructura segura de AWS Bedrock) u opciones de código abierto como OpenCode han cambiado las reglas del juego. La gran diferencia radica en la autonomía del agente: ahora la IA puede leer la base de código completa y modificar archivos directamente en el sistema de archivos.

El factor seguridad y los Guardrails

Darle autonomía a un agente para inspeccionar archivos mediante comandos de terminal (ls, grep, find) puede parecer una locura peligrosa. Por ello, a nivel de ingeniería de plataforma, implementamos barreras de seguridad estrictas (guardrails):

Nota de experiencia: Para evitar acciones imprevistas o destructivas, ciertos comandos críticos ejecutados por el agente requieren obligatoriamente de nuestra intervención e inspección humana antes de aplicarse en el entorno.

A diferencia de las herramientas comerciales ligadas a un solo proveedor (como las herramientas de Anthropic y sus modelos Claude), alternativas open-source como OpenCode permiten a los equipos conectar sus flujos de trabajo a cualquier proveedor de LLM del mercado, algo crucial para evitar el vendor lock-in.

3. Desarrollo Dirigido por Especificaciones (Spec-Driven Development)

Con la llegada de la autonomía de los agentes, los ingenieros senior nos enfrentamos pronto a un nuevo problema: el consumo desmedido de tokens y el riesgo de que la IA tomara direcciones de arquitectura equivocadas. Para solucionar esto, ha ganado fuerza el Desarrollo Dirigido por Especificaciones, una metodología que reintroduce el criterio humano en el bucle de decisión mediante dos frameworks principales:

  • SpecKit: Ideal para proyectos que nacen desde cero (Greenfield projects).
  • OpenSpecs: El que yo prefiero para trabajar en entornos reales con código ya existente y sistemas legados (Brownfield projects).

¿Cómo funciona el flujo con OpenSpecs?

El proceso no consiste en lanzar al agente a picar código a ciegas. Seguimos una serie de fases estructuradas mediante archivos Markdown (.md) que sirven como contratos de diseño. Escribiré más detalladamente sobre esto en otro artículo.

La estrategia clave: Como arquitectos o ingenieros principales, no debemos permitir que el agente implemente todo el proyecto de golpe. Mi recomendación es guiarlo para que realice la implementación fase por fase. Esto genera Pull Requests (PRs) más pequeños, limpios y acotados. En la actualidad, el cuello de botella ya no está en la velocidad de generación de código, sino en la verificación humana y la revisión del mismo (code review).

4. Gestión de Costes, Modelos y Ventana de Contexto

El uso de agentes no es gratuito y requiere una gestión de recursos tan inteligente como la del propio software. Tomando como ejemplo nuestro uso de Claude Code, categorizamos las tareas según su complejidad para optimizar el gasto de la organización:

Complejidad Baja (Modelo: Haiku)
Lo usamos para tareas simples, refactorizaciones menores, automatizaciones rápidas y bajo coste.
Complejidad Alta (Modelo: Sonnet / Opus)
Lo reservamos para tareas complejas y lógica de negocio core con requerimientos cognitivos elevados.

Además, como desarrolladores debemos monitorizar activamente el consumo de tokens y el llenado de la ventana de contexto. En mi experiencia, al alcanzar aproximadamente el 60% de la capacidad del contexto, es vital compactarlo o limpiarlo; de lo contrario, el modelo empieza a perder el hilo de las dependencias y aumentan drásticamente las posibilidades de sufrir alucinaciones en el código.

5. El paso hacia un modelo de trabajo Asíncrono

Quizás el cambio cultural y metodológico más grande en mi rutina diaria es la transición hacia un modelo de trabajo puramente asíncrono.

Agentes modernos como Jules (el agente de código de Google) se sincronizan directamente con plataformas como GitHub. Puedo asignarle una tarea compleja al agente (como la creación de una nueva funcionalidad secundaria), indicarle que trabaje en una rama independiente (branch) y que levante un Pull Request al finalizar.

Esto cambia radicalmente cómo gestiono mi tiempo: ya no tengo que mantener el 100% de mi atención fija en la pantalla viendo cómo la IA escribe línea por línea. Puedo delegar la tarea, ponerme a diseñar otra parte del sistema o atender una reunión de arquitectura, y regresar más tarde a revisar, testear y aprobar el código resultante. La IA ha dejado de ser un mero asistente de copia y pega para convertirse, efectivamente, en un ingeniero junior asíncrono en mi equipo.

Reflexión final: El nuevo rol del ingeniero

Este viaje de dos años me ha enseñado que la Inteligencia Artificial no viene a reemplazarnos, sino a obligarnos a subir de nivel. Nuestro valor ya no se mide por las líneas de código que somos capaces de picar por minuto, sino por nuestra capacidad para diseñar buenas arquitecturas, definir especificaciones precisas en proyectos complejos y mantener un criterio técnico riguroso durante las revisiones. Al final del día, la IA puede escribir el código, pero la responsabilidad última de la robustez del software sigue siendo, y siempre será, nuestra.

martes, 10 de junio de 2025

MCP y Agentes de IA basados en LLM

La Programación de Controladores Múltiples (MCP, por sus siglas en inglés) es un enfoque que se utiliza para gestionar varios agentes o tareas simultáneamente. Este tipo de programación es esencial en entornos donde múltiples procesos deben coordinarse y comunicarse entre sí. En el contexto de la inteligencia artificial, los sistemas basados en MCP pueden ser muy efectivos al permitir que diferentes agentes colaboren y compartan información, lo cual es crucial para resolver problemas complejos.

Por otro lado, los Agentes de IA basados en Modelos de Lenguaje Grande (LLM, por sus siglas en inglés) están diseñados para comprender y generar texto humano. Estos modelos utilizan arquitecturas avanzadas como Transformers y han sido entrenados con grandes volúmenes de datos textuales. Gracias a su capacidad para procesar el lenguaje natural, los LLM pueden interactuar con los usuarios de manera más intuitiva y brindar respuestas coherentes a diversas consultas.

Cuando combinamos MCP con agentes basados en LLM, obtenemos sistemas que no solo son capaces de entender el lenguaje natural, sino también de gestionar múltiples tareas y coordinar acciones entre distintos agentes. Por ejemplo, imagina un asistente virtual que puede manejar reservas de restaurantes mientras responde preguntas sobre el clima o proporciona recomendaciones personalizadas. Cada uno de estos aspectos puede ser gestionado por diferentes agentes dentro del marco MCP.

Esta combinación abre un abanico de posibilidades en aplicaciones prácticas, desde atención al cliente hasta sistemas autónomos complejos. Los desafíos residen en garantizar una comunicación efectiva entre los agentes y optimizar la toma de decisiones en tiempo real. El futuro del desarrollo en este campo promete avances significativos que podrían transformar cómo interactuamos con las máquinas.

Arquitectura de Agentes de IA basados en LLM, Planner, Orchestrator, Executor, etc

La arquitectura de agentes de inteligencia artificial (IA) se ha vuelto un tema central en el desarrollo de sistemas complejos que pueden interactuar con el entorno, aprender de él y tomar decisiones autónomas. En este contexto, los modelos de lenguaje grandes (LLM, por sus siglas en inglés) juegan un papel crucial al proporcionar capacidades avanzadas de comprensión y generación del lenguaje natural. Para entender cómo funcionan estos agentes, es necesario desglosar su arquitectura en componentes clave: el Planificador (Planner), el Orquestador (Orchestrator) y el Ejecutador (Executor).

El Planificador es responsable de la toma de decisiones estratégicas dentro del agente. Su función principal es analizar los objetivos establecidos y crear un plan que guíe el comportamiento del agente hacia la consecución de esos objetivos. Utilizando un modelo LLM, el Planificador puede interpretar las intenciones del usuario y generar una serie de acciones recomendadas basadas en esos objetivos. Por ejemplo, si se le solicita a un agente que organice una reunión, el Planificador evaluará las disponibilidades, los participantes y otros factores relevantes para elaborar un cronograma óptimo.

Para llevar a cabo su tarea efectivamente, el Planificador necesita acceso a información contextual y antecedentes sobre las tareas pendientes. Aquí es donde los LLM pueden ser particularmente útiles ya que son capaces de manejar grandes cantidades de datos textuales y extraer patrones significativos. Esto les permite adaptar sus planes a situaciones cambiantes o imprevistas, mejorando así la flexibilidad del sistema.

A continuación se encuentra el Orquestador. Este componente actúa como un coordinador entre diferentes partes del sistema y asegura que todas las acciones se ejecuten en sincronía para alcanzar los objetivos establecidos por el Planificador. La orquestación implica asignar tareas a distintos módulos o subagentes dentro del sistema, además de gestionar la comunicación entre ellos.

El Orquestador también juega un papel fundamental al facilitar la interacción entre el agente IA y otros sistemas externos. Por ejemplo, si un agente necesita consultar datos adicionales desde una base externa o comunicarse con otros servicios web para completar una tarea específica, será responsabilidad del Orquestador gestionar estas interacciones eficientemente. Mediante esta coordinación efectiva, se maximiza la eficacia operativa del sistema en su conjunto.

Finalmente tenemos al Ejecutador, que es quien materializa las acciones propuestas por el Planificador bajo la supervisión del Orquestador. Este componente convierte las decisiones estratégicas en acciones prácticas; por ejemplo, puede enviar correos electrónicos automatizados, realizar búsquedas en bases de datos o incluso interactuar físicamente con dispositivos IoT (Internet of Things). El Ejecutador debe ser robusto y capaz de manejar errores o contingencias durante su funcionamiento para garantizar que cada acción se ejecute correctamente.

Una característica interesante sobre esta arquitectura basada en agentes es su capacidad para aprender continuamente mediante técnicas como el aprendizaje automático (ML). Los modelos LLM pueden actualizarse constantemente con nueva información proveniente tanto del entorno como de experiencias pasadas; esto significa que cada iteración mejora la calidad general del agente. Así mismo, los errores cometidos durante la ejecución pueden ser analizados posteriormente por el Planificador para ajustar futuros planes.

No obstante, implementar una arquitectura tan compleja presenta desafíos significativos. La integración efectiva entre estos componentes requiere una cuidadosa planificación y diseño arquitectónico para evitar problemas como cuellos de botella en la comunicación o fallas en la ejecución debido a dependencias mal gestionadas entre módulos.

A medida que avanzamos hacia un futuro donde los agentes IA desempeñarán roles más prominentes tanto en entornos empresariales como personales, será esencial seguir investigando nuevas maneras de optimizar estas arquitecturas. Las innovaciones podrían incluir mejoras en algoritmos predictivos dentro del Planificador o desarrollar interfaces más intuitivas para facilitar la colaboración humano-agente.

Además hay cuestiones éticas involucradas cuando hablamos sobre arquitecturas inteligentes autónomas; por lo tanto también debemos considerar aspectos relacionados con privacidad y seguridad al diseñar estos sistemas inteligentes. Cada vez más empresas están tomando conciencia sobre la importancia de construir aplicaciones responsables e inclusivas basadas no solo en eficiencia sino también respetando principios éticos claros.

En resumen, comprender cómo funciona cada uno de estos componentes -el Planificador, Orquestador y Ejecutador- nos brinda una visión clara sobre cómo diseñar e implementar agentes IA efectivos utilizando LLMs como núcleo funcional. A medida que continuemos explorando esta fascinante área tecnológica juntos encontraremos nuevas oportunidades para mejorar nuestra vida cotidiana mediante soluciones inteligentes bien estructuradas.

Arquitectura de Agentes de IA basados en LLM, Elementos y Interaccion

La arquitectura de agentes de inteligencia artificial (IA) basados en modelos de lenguaje grande (LLM, por sus siglas en inglés) se fundamenta en la capacidad de estos modelos para procesar y generar lenguaje humano de manera efectiva. Un agente basado en LLM suele estar compuesto por tres elementos esenciales: el motor de procesamiento del lenguaje, la interfaz de usuario y el módulo de toma de decisiones. Estos componentes trabajan conjuntamente para ofrecer una experiencia interactiva y contextualizada.

El motor de procesamiento del lenguaje es el corazón del agente. Este componente se basa en un modelo preentrenado que ha sido alimentado con grandes volúmenes de texto para aprender patrones lingüísticos, gramática, contexto y significado. Cuando un usuario introduce un texto o pregunta, el motor analiza la entrada utilizando algoritmos complejos que permiten entender no solo las palabras individuales, sino también las intenciones subyacentes del mensaje. La generación de respuestas coherentes y relevantes depende en gran medida de la calidad del modelo LLM empleado.

La interfaz de usuario es fundamental para la interacción entre el agente y el usuario. Esta puede adoptar diversas formas, desde chatbots simples hasta interfaces gráficas más sofisticadas que integran voz o imágenes. Una buena interfaz permite al usuario comunicarse con el agente sin fricciones. Es importante diseñarla teniendo en cuenta la usabilidad y accesibilidad para garantizar que todos los usuarios puedan beneficiarse del sistema sin complicaciones.

El módulo de toma de decisiones actúa como intermediario entre el motor del lenguaje y las acciones a realizar por parte del agente. Este componente está diseñado para interpretar las respuestas generadas por el motor y determinar cómo proceder basándose en reglas predefinidas o aprendizaje automático. Por ejemplo, si un usuario pregunta sobre recomendaciones gastronómicas, este módulo evaluará las opciones generadas por el modelo y decidirá cuál presentar al usuario según su contexto específico.

Otro aspecto crucial en la arquitectura es la retroalimentación continua, que permite al agente aprender y mejorar con cada interacción. Esto implica almacenar datos sobre las conversaciones pasadas para ajustar los modelos y optimizar así tanto la precisión como la relevancia de las respuestas futuras. Además, incorporar métodos de evaluación permite identificar errores comunes y áreas donde se necesita entrenamiento adicional.

En conclusión, entender los elementos básicos e interacciones dentro de una arquitectura basada en LLM es esencial para desarrollar agentes inteligentes eficaces. Cada componente juega un papel crítico que contribuye a crear sistemas capaces no solo de responder preguntas, sino también de mantener conversaciones significativas con los usuarios.

sábado, 31 de mayo de 2025

Técnicas para mejorar prompts - chatbots y LLMs - Limitar la longitud de las respuestas deseadas

En el ámbito de la interacción con chatbots y modelos de lenguaje de gran tamaño (LLMs, por sus siglas en inglés), una de las habilidades más importantes que podemos desarrollar es la capacidad de formular prompts efectivos. Un aspecto clave para mejorar la calidad de las respuestas es aprender a limitar la longitud de las respuestas deseadas. Esto no solo ayuda a obtener información más concisa y relevante, sino que también permite gestionar mejor nuestras expectativas respecto a lo que queremos obtener del modelo.

Limitar la longitud de las respuestas se refiere a establecer un marco claro sobre cuántas palabras o frases debería contener una respuesta. Al hacerlo, guiamos al modelo hacia una comunicación más eficiente. Por ejemplo, si deseas que el chatbot te dé un resumen breve sobre un tema específico, puedes indicar claramente que busques una respuesta en tres o cuatro oraciones. Esta técnica permite al modelo centrarse en los puntos clave sin divagar en detalles innecesarios.

Una forma efectiva de implementar esta técnica es mediante el uso de instrucciones explícitas dentro del prompt. En lugar de simplemente preguntar "¿Qué es el cambio climático?", podrías reformularlo como "Por favor, define el cambio climático en dos oraciones". Este tipo de directrices no solo aclara tus expectativas, sino que también facilita al modelo entender qué tipo de respuesta estás buscando.

Además, puedes utilizar ejemplos como parte del prompt para mostrarle al modelo lo que consideras una respuesta adecuada. Si has encontrado ejemplos previos donde se ha cumplido con tus requisitos, incluirlos puede ser muy útil. Por ejemplo: "Describa la fotosíntesis en tres oraciones como este ejemplo: 'La fotosíntesis es el proceso mediante el cual las plantas convierten luz solar en energía química...'". De esta manera, le proporcionas un contexto adicional que mejora su capacidad para ajustar su respuesta a tus necesidades.

Otra técnica útil implica incorporar restricciones adicionales relacionadas con la longitud o estructura del texto. Puedes pedir respuestas que sean no solo breves sino también organizadas. Por ejemplo: "Dame tres puntos clave sobre los beneficios del ejercicio físico en formato de lista". Esto no solo limita la extensión sino también da claridad sobre cómo debe presentarse la información, facilitando su comprensión.

Es importante tener en cuenta que limitar la longitud no significa sacrificar calidad o profundidad; más bien se trata de ser selectivo acerca de qué información es esencial para ti. Si bien puede parecer tentador permitir respuestas largas para obtener más detalles, muchas veces esto resulta contraproducente porque puede llevar a inundarnos con datos irrelevantes o redundantes.

A medida que experimentas con diferentes formas y longitudes en tus prompts, podrás identificar patrones sobre cómo responden los modelos según estas limitaciones. Con el tiempo y la práctica, esto te permitirá afinar aún más tus preguntas y mejorar tu interacción general con chatbots y LLMs.

No olvides hacer pruebas A/B utilizando diferentes versiones del mismo prompt pero variando únicamente la longitud solicitada o los formatos específicos requeridos. Esto podría darte información valiosa sobre cómo reacciona cada sistema ante cambios sutiles en tus solicitudes y cuáles son las mejores prácticas para cada situación particular.

Además, ten presente que hay diversas aplicaciones prácticas donde esta técnica puede ser crucial. En entornos profesionales donde necesitas informes rápidos o resúmenes ejecutivos claros y concisos, saber articular adecuadamente un prompt limitado puede ahorrar tiempo valioso tanto para ti como para cualquier equipo involucrado.

Asimismo, cuando trabajamos con estudiantes u otros usuarios menos familiarizados con tecnología avanzada o análisis complejos, utilizar prompts limitados puede facilitarles entender conceptos difíciles sin sentirse abrumados por exceso de información. Esto promueve un ambiente educativo más eficiente donde todos pueden participar activamente sin perderse entre datos excesivos.

Por último, vale mencionar que mientras trabajamos con LLMs estamos constantemente aprendiendo sobre sus capacidades y limitaciones inherentes; así pues adoptar una mentalidad flexible e innovadora frente a nuestras interacciones promete enriquecer enormemente nuestra experiencia general usando estos sistemas avanzados.

Para concluir este punto vital dentro del aprendizaje sobre técnicas efectivas aplicables a chatbots y LLMs: recuerda siempre ajustar tu enfoque dependiendo del contexto específico donde estés trabajando—ya sea académico u organizacional—y aprovecha al máximo todas las oportunidades disponibles experimentando continuamente hasta encontrar ese balance ideal entre claridad y suficiencia informativa cuando formules tus prompts limitados.

sábado, 24 de mayo de 2025

Pasos y Tecnicas para entrenar LLM - Entrenamiento del modelo utilizando técnicas de optimización como Adam o SGD

El entrenamiento de un modelo de lenguaje grande (LLM) es un proceso complejo que requiere una cuidadosa selección de técnicas y algoritmos. Uno de los aspectos más cruciales en este proceso es la elección del optimizador, que se encarga de ajustar los pesos del modelo para minimizar la función de pérdida durante el entrenamiento. Dos de los optimizadores más populares son Adam y Stochastic Gradient Descent (SGD). Cada uno tiene sus propias ventajas y desventajas, y la elección entre ellos puede influir significativamente en el rendimiento del modelo.

Adam, que significa Adaptive Moment Estimation, es un optimizador que combina las ventajas de dos métodos: el promedio móvil del gradiente y el promedio móvil del cuadrado del gradiente. Esto permite a Adam adaptar la tasa de aprendizaje para cada parámetro individualmente, lo cual es especialmente útil en problemas con grandes cantidades de datos o parámetros. Durante el entrenamiento con Adam, se actualizan los momentos acumulativos que ayudan a estabilizar las actualizaciones, lo que puede resultar en convergencias más rápidas y eficientes.

Por otro lado, SGD es un método más tradicional que actualiza los pesos utilizando sólo una pequeña parte del conjunto de datos (un mini-batch) en cada paso. Aunque SGD puede ser menos eficiente inicialmente debido a su naturaleza estocástica, a menudo resulta ser muy efectivo cuando se trata de generalización. Una técnica común al utilizar SGD es implementar una tasa de aprendizaje programada o "learning rate schedule", donde la tasa disminuye progresivamente a medida que avanza el entrenamiento, ayudando así al modelo a afinarse durante las etapas finales.

Es importante mencionar que tanto Adam como SGD pueden beneficiarse enormemente de técnicas como la normalización por lotes (batch normalization) o técnicas avanzadas como el "gradient clipping". La normalización por lotes ayuda a estabilizar el aprendizaje al normalizar las salidas intermedias dentro del mini-batch, mientras que el "gradient clipping" evita explosiones en los gradientes limitando su magnitud. Estas técnicas son esenciales cuando trabajamos con LLMs debido a su complejidad y tamaño.

Al entrenar LLMs también debemos considerar otros factores como la cantidad adecuada de épocas (epochs) para evitar sobreajuste y cómo manejar los datos no balanceados si estamos trabajando con tareas específicas. La validación cruzada es otra técnica clave que nos ayuda a evaluar realmente cómo nuestro modelo está aprendiendo generalizando sobre nuevos datos.

Finalmente, recuerda siempre monitorear métricas relevantes durante el entrenamiento para asegurarte de que tu modelo no solo minimiza la función pérdida sino también mejora su rendimiento general en tareas específicas. El uso adecuado y combinado de estos optimizadores junto con técnicas adicionales te permitirá entrenar modelos robustos y eficientes en procesamiento del lenguaje natural.

lunes, 19 de mayo de 2025

LLM - Transformer Architecture - Decoders and Encoders

In the realm of machine learning, particularly in natural language processing, the transformer architecture has revolutionized how we approach tasks such as translation, summarization, and text generation. At the heart of this architecture are two main components: encoders and decoders. Understanding their roles is crucial for grasping how large language models (LLMs) function.

The encoder's primary responsibility is to process input data, transforming it into a format that captures the underlying meaning of the text. It does this through a series of self-attention mechanisms and feed-forward neural networks. The self-attention mechanism allows the model to weigh the importance of different words in relation to one another, effectively capturing context and relationships within a sentence or phrase. This enables the encoder to create a rich representation of the input sequence that retains essential semantic information.

On the other hand, decoders take these encoded representations and generate output sequences based on them. While they also utilize self-attention mechanisms, they include an additional layer that attends not only to previous outputs but also to the encoder's output. This ensures that each word generated by the decoder is informed by both what has been produced so far and what was learned from the input data. As a result, decoders are capable of producing coherent and contextually relevant sentences or paragraphs.

In summary, both encoders and decoders play critical roles in transformer architectures. Encoders focus on understanding and representing input data while decoders specialize in generating meaningful output from these representations. This interplay allows large language models to perform complex language tasks with impressive accuracy and fluency.