top of page

Hacia modelos que puedan describir código

Hemos creado un modelo de lenguaje llamado Gemini que puede leer código y describir su funcionalidad en lenguaje natural.  Nuestro modelo es compatible con una variedad de lenguajes de programación y es multilingüe. En este blog, detallamos sus capacidades, así como los impactos potenciales.

2 de enero de 2022

Project Gemini (17).png

Creamos un modelo de lenguaje llamado Gemini que se entrenó en aproximadamente 1 millón de pares de código-descripción. El objetivo de este proyecto era simple: ¿podemos habilitar máquinas con la capacidad de describir código de manera efectiva de la misma manera que lo haría un ser humano? Si bien es una tarea difícil, el trabajo reciente en modelos de lenguaje ha logrado avances rápidos, lo que hace que las tareas que antes eran difíciles sean mucho más plausibles.

Sin embargo, la creación de modelos de lenguaje para el código informático presenta más desafíos que los modelos de lenguaje tradicionales. Primero, la confiabilidad de los datos es bastante variable y no tan abundante. Por lo general, los conjuntos de datos disponibles públicamente contienen ejemplos de código de calidad media, pero se quedan cortos cuando contienen descripciones de calidad. Esto puede sesgar negativamente el rendimiento de un modelo desde el principio, lo que es difícil de reparar más adelante en el ciclo de desarrollo. En segundo lugar, lograr modelos de lenguaje de alto rendimiento en cualquier tarea se ha vuelto cada vez más costoso. Está bien documentado que cuanto más grande sea un modelo de lenguaje en parámetros entrenables, mejor funcionará; Sin embargo, esta estrategia viene con mayores costos monetarios y de cómputo.

Otro desafío importante al construir un modelo de lenguaje es la confiabilidad del sistema en general. El trabajo reciente de empresas como OpenAI, Google y Facebook ha demostrado que los modelos de lenguaje, particularmente en el dominio de la generación de lenguaje, pueden producir resultados inesperados. El control de las salidas generadas sigue siendo un problema de investigación abierto que en gran medida aún no se ha resuelto. 

Con todos los desafíos mencionados, las preguntas se volvieron más claras para construir un sistema exitoso para describir el código:

1.¿Podemos seleccionar suficientes muestras de datos que contengan descripciones de código de calidad con el código original?
2. ¿Cómo podemos construir un modelo de lenguaje más pequeño que maximice la consistencia y la fidelidad al mismo tiempo?

Construcción de un modelo para describir código


Modelo
Para abordar las preguntas mencionadas anteriormente, Gemini utiliza la popular arquitectura de transformadores. Descubrimos que el entrenamiento con cualquier otro tipo de arquitectura (es decir, RNN o GRU) no produjo la misma calidad que un transformador. 

En primer lugar, un enfoque principal de la construcción de un sistema para describir el código fue agregar consistencia a los resultados generados. Gemini usa una estructura de codificador-decodificador, opuesta a una estructura de solo decodificador como GPT-3. Descubrimos que el uso de una estructura de codificador-decodificador mejoró drásticamente la consistencia de las descripciones generadas en comparación con el uso de solo decodificadores. 

Gemini consta de 3 modelos de diferentes tamaños. El principal consta de 600 millones de parámetros, una versión más pequeña "Lambda" con 230 millones de parámetros y "Plato" con 64 millones de parámetros. Esto puede sorprender a algunos lectores dada la escala reciente de proyectos como GPT-3, que utilizan hasta 175 mil millones de parámetros; Sin embargo, descubrimos que más parámetros solo produjeron un mejor rendimiento cuando se combinaron con un ajuste fino. 


conjunto de datos
En segundo lugar, encontrar datos de calidad fue un gran desafío. Nuestro objetivo con Gemini es proporcionar resúmenes naturales de código; Dado que no hay conjuntos de datos disponibles públicamente de muestras de código con una descripción natural correspondiente, tuvimos que generar muestras sintéticamente. Comenzamos con el primer entrenamiento previo de Gemini en 885K muestras disponibles públicamente de pares de código-cadena de documentos durante 7 épocas. Esto le dio a Gemini una buena base para comprender la semántica del código al traducirlo al inglés.

Para lograr la naturalidad, preparamos manualmente 250 muestras manuscritas con su correspondiente fragmento de código. Estos nuevos puntos de datos se usaron para afinar una nueva versión de Gemini para 2 épocas, lo que le dio la capacidad de escribir de forma natural. Nuestra intención en este punto era dejar que Gemini volviera a anotar nuestro conjunto de datos original, sin embargo, solo podía escribir alrededor de 3 de cada 10 descripciones a un nivel satisfactorio. 

Con ayuda humana, Gemini pudo generar sintéticamente 700 descripciones, lo que nos permitió volver a ajustar el modelo. Esta vez, descubrimos que Géminis podía describir el código mucho más claro. Repetimos este ciclo hasta que Gemini produjo 10 000 muestras para Python, Javascript, Go, PHP, Java y Ruby. 

Screenshot 2021-12-30 5.12.02 PM.png

La figura de la izquierda/arriba es un ejemplo visual de nuestra estrategia de generación de datos sintéticos, que es esencial para alcanzar el rendimiento de Gemini. La generación de datos sintéticos de calidad también es importante para mantener la seguridad del código del usuario. Debido a que tenemos una sólida canalización de generación de datos, no es necesario usar el código del usuario en nuestros modelos. 

Descubrimos que los modelos solo necesitaban ser ajustados por un máximo de 3 épocas, independientemente del tamaño del modelo. En el futuro, esperamos requerir solo capacitación previa o ajuste para nuevas tareas.  

Muestras

Las muestras que se muestran a la derecha/abajo se tomaron de nuestras pruebas internas iniciales de nuestros tres modelos. Si bien seleccionamos estas muestras, creemos que representan con precisión las habilidades de nuestro modelo. Para mejorar el rendimiento, utilizamos un método de búsqueda "lo mejor de" al generar resultados. Descubrimos que todos los modelos funcionan mejor cuando se eligen entre los 3 o 4 mejores resultados. Además, descubrimos que establecer una penalización de repetición de 2,5 a 3 arrojó los mejores resultados al intentar maximizar la coherencia. 

Nota: n denota el número "mejor de" (por ejemplo, tomar la mejor solución de 3 salidas generadas) yp denota penalización por repetición.

Géminis (602 millones de parámetros)
n = 3  p = 3,0

Codigo de entrada

solicitudes de importación
importar json

def post_url (punto final, json_data):
    r = solicitudes.post(punto final, datos=json.dumps(json_data))
    devolver r.text

Descripción generada:

Este programa envía un POST a un punto final determinado y devuelve la respuesta del servidor JSON.

Experimentos

Mientras construíamos Gemini, teníamos muchas preguntas sobre qué afectaría más al rendimiento. Consideramos un modelo de alto rendimiento como uno que puede escribir resultados coherentes y sensatos que cubren el alcance del código. El trabajo anterior en este dominio ha demostrado que los modelos de lenguaje más grandes (en términos de parámetros) mejoran significativamente el rendimiento, por lo que entrenamos una variedad de tamaños de modelos.

Nuestras preguntas más importantes fueron las siguientes:

 

  • ¿Cómo afectaría el tamaño del modelo a los resultados generados?

  • ¿El pre-entrenamiento + ajuste fino supera al estricto pre-entrenamiento?

  • ¿Qué tan bien generaliza cada modelo si solo se entrena previamente y se ajusta en un lenguaje de programación? (es decir, ¿puede un modelo entrenado solo en Python generalizar a Javascript, Java, etc.)

  • ¿Podemos reducir el número de épocas de entrenamiento necesarias?​

Recomendaciones

En nuestros experimentos, encontramos que simplemente aumentar la cantidad de parámetros entrenables no se correlaciona con un aumento significativo en el rendimiento. En cambio, encontramos que el entrenamiento previo y el ajuste fino producen el mejor rendimiento, lo cual ha sido bien documentado en trabajos anteriores.

Para nuestra sorpresa, descubrimos que solo el ajuste fino en un lenguaje de programación es competitivo con el ajuste fino en múltiples lenguajes de programación. Nuestra teoría es que Gemini presta atención a la semántica del código (es decir, nombres de variables, nombres de funciones, nombres de bibliotecas, etc.) en lugar de la mera memorización. Esto nos lleva a creer que un modelo más grande que esté preentrenado y ajustado en un amplio alcance de un lenguaje de programación podría superar sustancialmente la versión actual de Gemini. 

Los modelos más grandes tenían una ventaja en la cantidad de épocas de entrenamiento necesarias. En términos generales, Géminis solo necesitó alrededor de 5 épocas de preentrenamiento y 1 o 2 épocas de ajuste fino para lograr resultados de calidad. 

Codigo de entrada

importar * como tf desde '@tensorflow/tfjs';

 

exportar función asíncrona loadModel() {

   const modelo = esperar tf.loadModel('/modelo/modelo.json');

   return modelo;

}

 

exportar función asíncrona startServer() {

    const model = esperar loadModel();

    const servidor = http.createServer(async (req, res) => {

 

    si (req.método === 'POST') {

      const body = esperar req.json();

      const entrada = tf.tensor2d(cuerpo.entrada, [1, cuerpo.entrada]);

      const salida = modelo.predecir(entrada);

      res.json(salida.dataSync());

    }

  });

  servidor.escuchar(8080);

}

Géminis (602 millones de parámetros, preentrenados + ajustados)

Este programa se utiliza para crear un servidor para el modelo. Primero carga el modelo y luego inicia un oyente en el servidor.

Gemini (602 millones de parámetros, preentrenamiento sin ajuste fino)

Carga un modelo de TensorFlow e inicia el servidor para las solicitudes.

Géminis (1.400 millones de parámetros, preentrenamiento sin ajuste fino)

Este programa hace lo siguiente: primero carga el modelo. A continuación, inicia un servidor de escucha. Por último, inicia un servidor para solicitudes.

Gemini (662 millones de parámetros, entrenamiento previo en varios idiomas, ajuste fino solo en Python)

Esta función se utiliza para iniciar un servidor para el modelo. Primero carga el modelo y luego inicia el servidor.

Áreas para mejorar

Durante nuestra experimentación, encontramos algunas deficiencias comunes de Gemini y las versiones más pequeñas. La mayoría de las deficiencias tienden a seguir el trabajo previo en el espacio de modelado del lenguaje, que se esperaba en cierta medida. Algunas de las deficiencias son las siguientes:
 

Las salidas son ocasionalmentetambién conciso
Cuando se le plantean entradas más largas, Géminis resumirá la descripción en 7 palabras o menos. En general, esto no sería un problema, pero encontramos que estas descripciones carecen de claridad o no cubren el alcance completo de la entrada. 

Las descripciones tendrán una alta repetibilidad en ciertos escenarios 

Un problema común en el modelado del lenguaje son las palabras u oraciones repetidas. Encontramos que Gemini se involucrará en este comportamiento cuando se plantee con un contexto mixto (es decir, entradas que tienen diferentes tipos de código mezclados).

Gemini es computacionalmente costoso de entrenar

El entrenamiento previo de Gemini durante 5 a 7 épocas requiere un día completo con una GPU Nvidia A100. Esto puede llevar mucho tiempo y ser costoso para que una startup lo haga de manera consistente.

La basura que entra sigue siendo igual a la basura que sale

Si bien este no es un comportamiento sorprendente, Gemini no puede describir bien el código si está mal escrito. Esperamos poder cerrar esta brecha con nuevos métodos o más datos en el futuro.

La ventana de contexto de Géminis es una limitación.

En su versión actual, Gemini solo puede aceptar 512 tokens como entrada. Esto puede ser limitante en ciertos escenarios donde se resumen programas completos.

¿Qué sigue para Géminis?

Creemos que Gemini podría ser el comienzo de una tecnología de gran impacto, hasta el punto de un cambio potencialmente importante en la forma en que se desarrolla el software. Los desarrolladores de software generalmente disfrutan escribiendo código y construyendo nuevas tecnologías; Sin embargo, muchas partes del desarrollo de software restan valor a la escritura de código, como la documentación, la revisión y la corrección de errores. Un sistema como Gemini podría usarse de diversas maneras para automatizar las partes no agradables de escribir software y permitir que se concentre más tiempo en mejores formas.

Estamos increíblemente emocionados de ver dónde se podría usar Gemini. En un futuro próximo, prevemos que Gemini se utilizará de las siguientes maneras:

 

  • Incorporación más rápida para equipos de software de cualquier tamaño(es decir, aumentar la velocidad de comprensión del código base)

  • Automatización de prácticas internas de software(por ejemplo, revisión de código, corrección de errores, documentación, etc.)

  • Romper las barreras del idioma para equipos multilingües/remotos

  • Instituciones educacionales(Aumentando la velocidad a la que los estudiantes pueden entender el código)

  • Proyectos de código abierto(eliminando la ambigüedad de la funcionalidad)

 

Sin embargo, nuestra visión de Gemini es mucho más grande que una simple explicación del código. En el futuro, queremos expandir las capacidades de Gemini para:

 

  • Escriba documentos completos, como LÉAME o informes sobre la funcionalidad del código.

  • Pregunta respondiendo sobre el código.

  • Crear diferentes niveles de explicación.(por ejemplo, la descripción de un código para un desarrollador experimentado puede ser diferente de la de un estudiante de secundaria)​​

  • Escribir ejemplos de cómo se podría usar el código en la práctica(es decir: generación de ejemplos de llamadas a funciones)

A partir de esos ejemplos, uno puede comenzar a imaginar el amplio alcance de un código general dentro del texto como Gemini.

Filosofía de liberación

En última instancia, nuestro objetivo es distribuir el poder de los sólidos sistemas de aprendizaje automático a la mayor cantidad posible de personas, grupos y organizaciones. Debido a que los sistemas como Gemini son actualmente costosos de desarrollar, lo estamos lanzando como un producto pago. Permitiremos que cualquier persona acceda a Gemini (y otras versiones) a través de:

  • Un producto sin código totalmente administrado

  • API de desarrollador

  • licencias de productos

  • Asociaciones


Todo lo cual se utilizará para financiar la próxima generación de nuestros motores. En los próximos años, planeamos hacer que varias versiones de Gemini estén disponibles a través de código abierto, ya que creemos firmemente en permitir que cualquiera use nuestra tecnología. Sin embargo, los plazos no están garantizados. 

bottom of page