Para la mayoría de las personas con las que interactúo, la mayor parte del tiempo soy simplemente otro programa basado en texto. Si la entrada y la salida son tan simples, ¿podría ser reemplazado por el modelo? Para que esto funcione, el modelo necesitaría no sólo entender mi estilo de escritura sino también saber mucho sobre mí. La mejor fuente para esto es mi Telegram Messenger, ya que lo uso a diario y contiene casi todo sobre mis pensamientos y acciones en forma de historiales de chat.
El enfoque más sencillo sería extraer todos mis mensajes, cargarlos en el contexto de ChatGPT e indicarle que use esta información para imitar mi estilo al responder a mensajes nuevos. Sin embargo, este enfoque está limitado por el tamaño de la ventana de contexto, lo que me obliga a preprocesar los mensajes para extraer puntos clave. Como quiero evitar esta molestia, tal vez se pueda utilizar la generación aumentada de recuperación (RAG) para extraer la información necesaria cuando sea necesario. Sin embargo, según mi experiencia, la recuperación de datos diversos, como sesiones de chat, generalmente requiere un ajuste supervisado del modelo de recuperación, y no estoy interesado en crear un conjunto de datos de este tipo. Por tanto, el ajuste fino parece la mejor opción. Es ideal por varias razones: debería capturar mi estilo de escritura y potencialmente acumular conocimiento de todos mis mensajes sin tener que seleccionar lo que es importante.
OpenAI ofrece capacidades de ajuste , pero como usaré mis mensajes privados, no quiero utilizar ningún servicio de ajuste de terceros. Entonces, necesito elegir un modelo base. Según la tabla de clasificación Hugging Face Open LLM , uno de los modelos más pequeños (≤13B parámetros) es Mistral 7B . Incluso supera a Llama 2 13B . Ahora, la pregunta es si LoRA es suficiente o si es necesario un ajuste completo. Varias comparaciones [1] [2] sugieren que LoRA es un poco peor que el ajuste completo, pero aún así está bien la mayor parte del tiempo. Sin embargo, para tareas específicas como la mía (idioma ruso + chat), encontré un artículo donde los investigadores realizaron ajustes de la instrucción Llama en chino, similar en complejidad a mi objetivo. Descubrieron que el ajuste basado en LoRA en un modelo base sin ajuste de instrucciones previas es menos efectivo que el ajuste completo. Sin embargo, el ajuste basado en LoRA en un modelo ya ajustado para instrucciones puede producir resultados comparables. En mi caso, esto significa un ajuste completo en un modelo base o LoRA en un modelo ya ajustado para chatear en ruso. Como no pude encontrar un modelo optimizado para el chat en ruso, probaré LoRA en un modelo optimizado para el chat en inglés, como el modelo Dolphin optimizado de Mistral.
Entonces, el plan es:
Un aspecto único de la mensajería en aplicaciones como Telegram, en comparación con los correos electrónicos, es el flujo conversacional. Los mensajes no suelen alternarse uno por uno entre usted y su contacto. En cambio, a menudo te encuentras enviando un par de mensajes seguidos, seguidos de varias respuestas de la otra persona. Estos mensajes también suelen ser breves. Quería preservar este estilo de conversación natural en mis datos.
Telegram ofrece una función incorporada para exportar todos los chats a JSON. Después de filtrar y agrupar mensajes en sesiones, recopilé datos de los últimos cinco años de uso de Telegram. Esto resultó en 15.789 sesiones de 466 chats, con una duración promedio de sesión de 8,51 mensajes. Para estructurar los datos, elegí el formato de solicitud ChatML . Aquí hay una sesión de muestra (traducida del ruso):
<|im_start|>Juan Smith
>>> maldita sea, no puedo pasar el límite de tiempo de 135
>>> tratando de hacer todo de manera súper óptima, pero no tuve suerte<|im_end|>
<|im_start|>Alejandro Smirnov
>>> si lo mismo
>>> ¿Sigues con la misma idea?<|im_end|>
<|im_start|>Juan Smith
>>> no sé, creo que estamos en la misma página
>>> como dijiste
>>> yendo con la cadena invertida en un intento e intentando encontrar algo allí
>>> parece una verdadera mierda porque la función z arruina todo……………………<|im_end|>
<|im_start|>Alejandro Smirnov
>>> no entiendo dónde entra z en esto<|im_end|>
<|im_start|>Juan Smith
>>> No sé, parece que estoy haciendo todo de forma iterativa de todos modos, pero sí, tengo que invertir algunas cadenas para construir la función z.
>>> y es solo una solución aleatoria
>>> de las discusiones<|im_end|>
<|im_start|>Alejandro Smirnov
>>> lo tengo<|im_end|>
Mi recopilador de datos garantiza que la pérdida solo se calcule en función de la respuesta de alguien. Predecir quién hablará a continuación es relativamente sencillo y no queremos que el modelo se centre en aprender eso. Por lo tanto, las partes de la conversación donde se calcula la pérdida están resaltadas en negrita.
Quizás observe que no sólo mis respuestas sino también las de otros se utilizan para el cálculo de pérdidas. Esto es deliberado. Al hacer esto, la modelo podrá actuar no solo como yo sino también como mis frecuentes compañeros de conversación.
Probaré modelos manteniendo chats de dos maneras. Primero, la modelo pretenderá ser yo y estaré charlando conmigo misma desde la perspectiva de mis diferentes amigos. Luego, charlaré como yo mismo mientras la modelo actúa como mi amiga. El inicio de mi conversación siempre serán los mismos 2 mensajes: "oye" y "¿qué pasa?" (en ruso, “прив” y “как дела?”). Se resaltarán las frases y personas generadas a medida que actúa el modelo. Para las pruebas, usaré oobabooga/text-generation-webui .
Al principio, quiero explorar cómo el modelo Mistral afinado de conversación genérica aborda esa tarea sin ningún entrenamiento previo por mi parte.
Amigo 1 contra Alexander Smirnov
Alexander Smirnov vs Amigo 1
Ok, es capaz de formar oraciones coherentes. El problema más notorio es su desconocimiento del contexto de las conversaciones, lo que da lugar a respuestas insulsas y genéricas. Los mensajes carecían de un estilo distintivo y se sentían bastante básicos. Otro problema es que el ruso del modelo es pobre. Esto es de esperar, ya que el modelo es demasiado pequeño para generalizarse bien a otros idiomas además del inglés principal. Además, el modelo tendía a ser demasiado proactivo y terminaba casi cada oración con una pregunta, que no es la forma en que las personas reales suelen comunicarse en Messenger.
¡Intentemos arreglar todo esto!
LoRA ofrece un enfoque de bajo esfuerzo en términos tanto del proceso de capacitación como de los requisitos de hardware. Entrena alrededor del 1% del peso total. Elegí una longitud de secuencia de 1024 y un tamaño de lote de 8. El entrenamiento, que consumió 20 GB de VRAM en un RTX 3090, tomó tres épocas y duró 5,5 horas. Para esto, utilicé vast.ai , donde el costo de la GPU fue de $0,362 por hora, lo que suma un total de $2 para toda la capacitación, excluyendo el tiempo dedicado a experimentos y corrección de errores.
Aquí están los resultados:
Amigo 1 contra Alexander Smirnov
Amigo 2 contra Alexander Smirnov
Alexander Smirnov vs Amigo 1
Alexander Smirnov vs Amigo 2
Esto es mucho mejor. Definitivamente captura el estilo de la persona en nombre de la cual responde. También identifica los temas más comunes discutidos entre pares específicos de personas. Por ejemplo, con el amigo 2, la atención se centra claramente más en el trabajo. Sin embargo, la gramática todavía está mal y se pierde rápidamente el contexto de la conversación. Estoy bastante seguro de que LoRA funcionará con una calidad razonable en inglés y es posible que no sea necesario realizar un ajuste completo. Pero, dado que el ruso no es el idioma nativo del modelo, intentemos realizar un ajuste completo.
El ajuste completo es más desafiante debido a la necesidad de capacitación en múltiples GPU. Los métodos populares incluyen ZeRO y DeepSpeed [3] o FSDP [4] , siendo FSDP esencialmente un ZeRO3 [5] . Decidí optar por FSDP.
Mientras implementaba el proceso de capacitación, me referí al código de ajuste fino de Stanford Alpaca y al código de ajuste fino Mistral de Anton Bacaj .
El uso de un fragmento completo FSDP de media precisión con una longitud de secuencia de 1024 y un tamaño de micro lote de 2 requirió 63 GB de VRAM en cada una de las ocho GPU A100 de 80 GB. El entrenamiento, que duró tres épocas, duró sólo 20 minutos. El costo total de la máquina virtual fue de $8,88 por hora, lo que resultó en $3, sin incluir el tiempo para experimentos y corrección de errores.
Conversaciones:
Amigo 1 contra Alexander Smirnov
Amigo 2 contra Alexander Smirnov
Alexander Smirnov vs Amigo 1
Alexander Smirnov vs Amigo 2
Las conversaciones se han vuelto más interesantes y atractivas, aunque todavía existe el riesgo de perder el contexto. El rendimiento en ruso ha mejorado, pero aún se producen errores. Creo que antes de realizar un ajuste fino para una tarea específica con datos limitados, como la mía, sería beneficioso primero ajustar el modelo sin supervisión en un gran corpus de textos rusos. Además, incorporar los nombres de los interlocutores de conversación comunes como tokens separados podría mejorar la calidad.
No diría que resultó ser significativamente mejor que LoRA. Podría ser más eficaz centrarse únicamente en una sola persona y calcular la pérdida basándose únicamente en mis respuestas (o las de otra persona), en lugar de intentar aprender sobre todos y cada uno de los interlocutores de la conversación.
Ciertamente, tuve que seleccionar cuidadosamente los resultados, no porque la mayoría de las respuestas del modelo fueran inadecuadas, sino porque muchas eran respuestas simples como "te llamaré más tarde", "ocupado" y "ok", que son naturalmente frecuentes. en conversaciones. A pesar de esto, está claro que el modelo sobresale en imitar el estilo de la persona a la que personifica. También captura los temas comúnmente discutidos entre dos personas. Sin embargo, carece significativamente de contexto en las conversaciones. Responder a preguntas como "¿Y entonces?" o "¿cuáles son tus planes para el fin de semana?" es un desafío sin tener un contexto completo. Quizás podría resultar beneficioso utilizar un sistema como Rewind , que captura todo lo que hace el usuario en la computadora.
Puede encontrar el código para este proyecto, así como instrucciones sobre cómo replicarlo usted mismo en su propio volcado de Telegram en mi repositorio de github . Se puede acceder a los registros de entrenamiento en WandB .
Imagen principal de Christian Wiediger en Unsplash