Personalizando compañeros de codificación para organizaciones

Mejorando la personalización de compañeros de codificación para organizaciones

Los modelos de IA generativa para compañeros de programación se entrenan principalmente con código fuente de acceso público y texto en lenguaje natural. Si bien el tamaño grande del corpus de entrenamiento permite que los modelos generen código para funcionalidades comúnmente utilizadas, estos modelos no conocen el código de los repositorios privados ni los estilos de codificación asociados que se implementan al desarrollar con ellos. En consecuencia, las sugerencias generadas pueden requerir volver a escribirse antes de ser adecuadas para su incorporación en un repositorio interno.

Podemos abordar esta brecha y minimizar la edición manual adicional al incorporar conocimiento de código de repositorios privados en un modelo de lenguaje entrenado con código público. Es por eso que desarrollamos una capacidad de personalización para Amazon CodeWhisperer. En esta publicación, te mostramos dos posibles formas de personalizar compañeros de codificación utilizando generación aumentada por recuperación y ajuste fino.

Nuestro objetivo con la capacidad de personalización de CodeWhisperer es permitir que las organizaciones adapten el modelo de CodeWhisperer utilizando sus repositorios y bibliotecas privadas para generar recomendaciones de código específicas de la organización que ahorren tiempo, sigan el estilo y las convenciones organizativas y eviten errores o vulnerabilidades de seguridad. Esto beneficia el desarrollo de software empresarial y ayuda a superar los siguientes desafíos:

  1. Documentación o información escasa sobre bibliotecas internas y API que obliga a los desarrolladores a pasar tiempo examinando código previamente escrito para replicar el uso.
  2. Falta de conocimiento y consistencia en la implementación de prácticas, estilos y patrones de codificación específicos de la empresa.
  3. Uso accidental de código y API obsoletos por parte de los desarrolladores.

Al utilizar repositorios de código interno para el entrenamiento adicional que ya han pasado por revisiones de código, el modelo de lenguaje puede mostrar el uso de API internas y bloques de código que superan la lista de problemas mencionada anteriormente. Dado que el código de referencia ya está revisado y cumple con los estándares exigentes del cliente, también se minimiza la probabilidad de introducir errores o vulnerabilidades de seguridad. Además, al seleccionar cuidadosamente los archivos fuente utilizados para la personalización, las organizaciones pueden reducir el uso de código obsoleto.

Desafíos de diseño

La personalización de las sugerencias de código basadas en los repositorios privados de una organización presenta muchos desafíos de diseño interesantes. Desplegar modelos de lenguaje grandes (LLMs) para mostrar sugerencias de código implica costos fijos de disponibilidad y costos variables debido a la inferencia basada en el número de tokens generados. Por lo tanto, tener personalizaciones separadas para cada cliente y alojarlas individualmente, incurriendo así en costos fijos adicionales, puede resultar enormemente costoso. Por otro lado, tener varias personalizaciones simultáneamente en el mismo sistema requiere una infraestructura de múltiples inquilinos para aislar el código propietario de cada cliente. Además, la capacidad de personalización debe ofrecer opciones para seleccionar el subconjunto de entrenamiento adecuado del repositorio interno utilizando diferentes métricas (por ejemplo, archivos con una historia de menos errores o código que se haya commitado recientemente en el repositorio). Al seleccionar el código en función de estas métricas, la personalización puede entrenarse utilizando código de mayor calidad, lo que mejora la calidad de las sugerencias de código. Por último, incluso con repositorios de código en constante evolución, el costo asociado con la personalización debe ser mínimo para ayudar a las empresas a ahorrar costos mediante un aumento de la productividad de los desarrolladores.

Un enfoque básico para construir la personalización podría ser preentrenar el modelo con un único corpus de entrenamiento compuesto por el conjunto de datos de preentrenamiento existente (público) junto con el código de la empresa (privado). Si bien este enfoque funciona en la práctica, requiere preentrenamiento individual redundante utilizando el conjunto de datos público para cada empresa. También requiere costos de implementación redundantes asociados con el alojamiento de un modelo personalizado para cada cliente que solo sirve solicitudes de clientes que provienen de ese cliente. Al separar el entrenamiento de código público y privado y desplegar la personalización en un sistema de múltiples inquilinos, se pueden evitar estos costos redundantes.

Cómo personalizar

A grandes rasgos, existen dos tipos de técnicas de personalización posibles: generación aumentada por recuperación (RAG) y ajuste fino (FT).

  • Generación aumentada por recuperación: RAG encuentra fragmentos de código coincidentes en un repositorio que son similares a un fragmento de código dado (por ejemplo, código que precede inmediatamente al cursor en el IDE) y amplía la solicitud utilizada para consultar el LLM con estos fragmentos de código coincidentes. Esto enriquece la solicitud y ayuda al modelo a generar código más relevante. Hay algunas técnicas exploradas en la literatura en esta línea. Consulta Generación aumentada por recuperación para tareas de PLN intensivas en conocimiento, REALM, kNN-LM y RETRO.

  • Ajuste fino: FT toma un LLM previamente entrenado y lo entrena aún más en un código base específico y más pequeño (en comparación con el conjunto de datos de preentrenamiento) para adaptarlo al repositorio adecuado. El ajuste fino ajusta los pesos del LLM en función de este entrenamiento, haciéndolo más adaptado a las necesidades únicas de la organización.

Tanto RAG como el ajuste fino son herramientas poderosas para mejorar el rendimiento de la personalización basada en LLM. RAG puede adaptarse rápidamente a bibliotecas privadas o APIs con una complejidad y costos de entrenamiento más bajos. Sin embargo, buscar y aumentar fragmentos de código recuperados para la indicación aumenta la latencia en tiempo de ejecución. En cambio, el ajuste fino no requiere ninguna ampliación del contexto porque el modelo ya está entrenado en bibliotecas privadas y APIs. Sin embargo, esto conlleva mayores costos y complejidades de entrenamiento al servir el modelo, cuando es necesario admitir múltiples modelos personalizados en múltiples clientes empresariales. Como discutiremos más adelante, estas preocupaciones pueden ser remediadas optimizando aún más el enfoque.

Generación aumentada por recuperación

Hay algunos pasos involucrados en RAG:

Indexación

Dado un repositorio privado como entrada por el administrador, se crea un índice dividiendo los archivos de código fuente en trozos. En pocas palabras, la segmentación convierte los fragmentos de código en piezas digeribles que probablemente sean más informativas para el modelo y sean fáciles de recuperar dadas las circunstancias. El tamaño de un trozo y la forma en que se extrae de un archivo son decisiones de diseño que afectan el resultado final. Por ejemplo, los trozos pueden dividirse según las líneas de código o según los bloques sintácticos, etc.

Flujo de trabajo del administrador

Búsqueda contextual

Buscar un conjunto de fragmentos de código indexados en función de unas pocas líneas de código sobre el cursor y recuperar fragmentos de código relevantes. Esta recuperación puede ocurrir mediante diferentes algoritmos. Estas elecciones pueden incluir:

  • Bag of words (BM25): Una función de recuperación de bag-of-words que clasifica un conjunto de fragmentos de código en función de las frecuencias de términos de consulta y las longitudes de fragmentos de código.

Recuperación basada en BM25

La siguiente figura ilustra cómo funciona BM25. Para utilizar BM25, primero se construye un índice invertido. Se trata de una estructura de datos que relaciona diferentes términos con los fragmentos de código en los que ocurren esos términos. En el momento de la búsqueda, buscamos fragmentos de código en función de los términos presentes en la consulta y los clasificamos en función de la frecuencia.

  • Recuperación semántica [Contriever, UniXcoder] – Convierte la consulta y los fragmentos de código indexados en vectores de alta dimensión y clasifica los fragmentos de código en función de la similitud semántica. Formalmente, a menudo se utiliza la búsqueda de vecinos más cercanos (KNN) o la búsqueda de los vecinos más cercanos aproximados (ANN) para encontrar otros fragmentos con semánticas similares.

Recuperación semántica

BM25 se centra en la coincidencia léxica. Por lo tanto, reemplazar “add” por “delete” puede no cambiar la puntuación BM25 según los términos de la consulta, pero la funcionalidad recuperada puede ser opuesta a la que se requiere. En contraste, la recuperación semántica se centra en la funcionalidad del fragmento de código, aunque los nombres de variables y APIs pueden ser diferentes. Normalmente, una combinación de recuperaciones basadas en BM25 y semánticas puede funcionar bien juntas para obtener mejores resultados.

Inferencia aumentada

Cuando los desarrolladores escriben código, utilizan su programa existente para formular una consulta que se envía al índice de recuperación. Después de recuperar varios fragmentos de código utilizando una de las técnicas mencionadas anteriormente, los adjuntamos a la indicación original. Aquí hay muchas opciones de diseño, que incluyen el número de fragmentos que se deben recuperar, la ubicación relativa de los fragmentos en la indicación y el tamaño del fragmento. La elección final de diseño está impulsada principalmente por la observación empírica al explorar varios enfoques con el modelo de lenguaje subyacente y desempeña un papel clave en la determinación de la precisión del enfoque. Los contenidos de los fragmentos recuperados y el código original se combinan y se envían al modelo para obtener sugerencias de código personalizadas.

Flujo de trabajo del desarrollador

Afinamiento fino:

El afinamiento fino de un modelo de lenguaje se realiza para el aprendizaje por transferencia en el que los pesos de un modelo pre-entrenado se entrenan con nuevos datos. El objetivo es retener el conocimiento apropiado de un modelo ya entrenado en un gran corpus y refinar, reemplazar o agregar nuevo conocimiento del nuevo corpus, en nuestro caso, una nueva base de código. Simplemente entrenar en una nueva base de código conduce al olvido catastrófico. Por ejemplo, el modelo de lenguaje puede “olvidar” su conocimiento de seguridad o las API que se utilizan de forma esporádica en la base de código empresarial hasta la fecha. Existen diversas técnicas como repetición de experiencia, GEM y PP-TF que se emplean para abordar este desafío.

Afinamiento fino

Existen dos formas de realizar el afinamiento fino. Un enfoque es utilizar los datos adicionales sin aumentar la indicación para afinar el modelo. Otra aproximación es aumentar la indicación durante el afinamiento fino mediante la recuperación de sugerencias de código relevantes. Esto ayuda a mejorar la capacidad del modelo para proporcionar mejores sugerencias en presencia de fragmentos de código recuperados. Luego, se evalúa el modelo en un conjunto de ejemplos separados después de ser entrenado. Posteriormente, el modelo personalizado se implementa y utiliza para generar las sugerencias de código.

A pesar de las ventajas de utilizar LLM dedicados para generar código en repositorios privados, los costos pueden ser prohibitivos para organizaciones pequeñas y de tamaño VoAGI. Esto se debe a que se requieren recursos informáticos dedicados aunque puedan subutilizarse dada el tamaño de los equipos. Una forma de lograr eficiencia en costos es servir varios modelos en la misma infraestructura informática (por ejemplo, SageMaker multi-tenancy). Sin embargo, los modelos de lenguaje requieren una o más GPUs dedicadas en varias zonas para manejar las limitaciones de latencia y rendimiento. Por lo tanto, la multi-tenencia de alojamiento de modelos completos en cada GPU es inviable.

Podemos superar este problema al servir a múltiples clientes en la misma infraestructura informática utilizando pequeños adaptadores para el LLM. Se utilizan técnicas de afinamiento eficiente de parámetros (PEFT) como ajuste de indicación, ajuste de prefijo y Adaptación de Baja Rango (LoRA) para reducir los costos de entrenamiento sin perder precisión. LoRA, en particular, ha tenido un gran éxito al lograr una precisión similar (o mejor) que el afinamiento fino de modelo completo. La idea básica es diseñar una matriz de rango bajo que luego se agrega a las matrices con el peso original de la matriz de capas objetivo del modelo. Por lo general, estos adaptadores se fusionan con los pesos originales del modelo para su uso. Esto conduce al mismo tamaño y arquitectura que la red neuronal original. Manteniendo los adaptadores separados, podemos utilizar el mismo modelo base con varios adaptadores de modelo. Esto devuelve las economías de escala a nuestros clientes pequeños y de tamaño VoAGI.

Adaptación de bajo rango (LoRA)

Medición de la efectividad de la personalización

Necesitamos métricas de evaluación para evaluar la eficacia de la solución personalizada. Las métricas de evaluación sin conexión actúan como barreras para enviar personalizaciones que sean inferiores al modelo predeterminado. Al construir conjuntos de datos a partir de un conjunto de datos retenido dentro del repositorio proporcionado, el enfoque de personalización se puede aplicar a este conjunto de datos para medir la eficacia. Comparar el código fuente existente con la sugerencia de código personalizado cuantifica la utilidad de la personalización. Las medidas comunes utilizadas para esta cuantificación incluyen métricas como similitud de edición, coincidencia exacta y CodeBLEU.

<p.también (cqi),="" 1="" 10.="" a="" ambos="" api="" aspectos="" calidad="" como="" comparación="" comparándolo="" con="" conocida="" cqi="" cuantificando="" cuenta="" código="" de="" del="" diseñado="" el="" en="" enfoque="" entre="" es="" exitosa.="" finalización="" frecuencia="" fuente="" fácil="" genérico.

Resumen

Construimos la capacidad de personalización de Amazon CodeWhisperer basada en una mezcla de las técnicas técnicas principales discutidas en esta publicación del blog y la evaluamos con estudios de usuarios sobre la productividad de los desarrolladores, realizados por Persistent Systems. En estos dos estudios, encargados por AWS, se pidió a los desarrolladores que crearan una aplicación de software médico en Java que requería el uso de sus bibliotecas internas. En el primer estudio, los desarrolladores sin acceso a CodeWhisperer tardaron (en promedio) ~8.2 horas en completar la tarea, mientras que aquellos que usaron CodeWhisperer (sin personalización) completaron la tarea un 62 por ciento más rápido en (en promedio) ~3.1 horas.

En el segundo estudio con un diferente conjunto de grupos de desarrolladores, los desarrolladores que usaron CodeWhisperer que había sido personalizado utilizando su código base privado completaron la tarea en 2.5 horas en promedio, un 28 por ciento más rápido que aquellos que usaron CodeWhisperer sin personalización y completaron la tarea en ~3.5 horas en promedio. Creemos firmemente que herramientas como CodeWhisperer que se personalizan según su base de código tienen un papel clave que desempeñar en impulsar aún más la productividad de los desarrolladores y recomendamos que se le dé una oportunidad. Para obtener más información y comenzar, visite la página de Amazon CodeWhisperer.

We will continue to update Zepes; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

Inteligencia Artificial

Cómo los LLM basados en Transformer extraen conocimiento de sus parámetros

En los últimos años, los modelos de lenguaje basados en transformadores (LLMs, por sus siglas en inglés) se han vuelt...

Inteligencia Artificial

Del Texto más allá de las Palabras

Hola lectores, hoy en día vivimos en la era de los Modelos de Lenguaje Grandes (LLMs), los cuales potencian software ...

Inteligencia Artificial

Google Chrome ahora muestra resúmenes de artículos impulsados por IA para una lectura sin esfuerzo

Google está una vez más a la vanguardia de la innovación con su Experiencia Generativa de Búsqueda (SGE) impulsada po...