Si llegaste hasta acá buscando cómo NOFRAUD ha creado su propio LLM, llegaste al lugar indicado. En este artículo vamos a demostrarte paso a paso cómo hemos creado FraudGPT, un LLM especializado en prevenir y detectar el fraude interno, la corrupción y comportamientos deshonestos al interior de las organizaciones.
Los LLM existentes en el mercado como ChatGPT, Llama, Mistral y Gemma tienen un conocimiento general pero no específico en la prevención y detección de fraudes
Lo que hemos hecho es entrenar un modelo abierto ya pre-entrenado con nuestras casuísticas de fraude y corrupción. Este proceso se conoce como fine-tuning y lo que pretende es darle un conocimiento a un LLM ya existente sobre una materia en la cual no es especialista.
Objetivos de la demostración
Esta demostración tiene como objetivo explicar cómo entrenamos un LLM abierto en un Mac Studio con Apple Silicon usando nuestros propios datos para lograr que el modelo nuevo detecte y prevenga el fraude con precisión.
Vamos a poner de ejemplo un conjunto de datos que contiene casuísticas de fraude donde las personas se confabulan entre si o maquinan una operación anti-ética para defraudar la confianza y sacar un beneficio personal deshonesto.
Una vez entrenado el modelo vamos a ponerlo a prueba para verificar qué tan inteligente lo hemos convertido y qué tan eficiente es respecto a un modelo que no ha sido específicamente entrenado para la labor de prevenir y detectar fraude.
Qué es el fine-tuning
El fine-tuning es un proceso que se utiliza para adaptar un modelo previamente entrenado a una tarea o conjunto de datos específicos, mejorando su rendimiento y relevancia para aplicaciones particulares.
En el contexto de los modelos de los LLM, el fine-tuning implica entrenar más el modelo en un conjunto de datos más pequeño y específico para una tarea, lo que le permite especializarse en áreas como por ejemplo la prevención del fraude.
Este entrenamiento se logra ajustando los parámetros del modelo para capturar mejor los matices de los nuevos datos. El fine-tuning puede mejorar significativamente la precisión y la eficiencia del modelo para la tarea deseada, aprovechando las fortalezas del modelo previamente entrenado y adaptándolo para satisfacer necesidades específicas.
Técnica de entrenamiento LoRA
Hacer un entrenamiento clásico de de un LLM cambiaría la mayoría de los pesos de las neuronas de los modelos, lo que requiere una gran cantidad de potencia computacional y recursos. El fine-tuning basado en LoRA (Low Rank Adaptation) que es el que escogimos en NOFRAUD, congela los pesos originales y solo entrena una pequeña cantidad de parámetros, lo que hace que el entrenamiento sea mucho más eficiente.
Para que el entrenamiento sea más eficiente, el enfoque de LoRA consiste en representar las actualizaciones de peso con dos matrices más pequeñas (llamadas matrices de actualización) mediante una descomposición de bajo rango. Estas nuevas matrices se pueden entrenar para que se adapten a los nuevos datos.
La matriz de peso original permanece congelada y no recibe más ajustes. Para producir los resultados finales, se combinan tanto los pesos originales como los adaptados.
El framework de entrenamiento MLX
MLX es el framework para el procesamiento de LLMs creado por Apple Research para procesadores con tecnología Apple Silicon. MLX traduce “Machine Learning X”. El framework fue especialmente creado para entrenar y desplegar modelos abiertos usando la gran potencia de cómputo y la memoria unificada de los procesadores M con arquitectura ARM.
En NOFRAUD hemos escogido este framework porque su laboratorio de inteligencia artificial está basado en equipos Mac Studio con procesadores M1 Max y Ultra, con memorias unificadas de 32 y 128GB.
Preparamos el entorno base
Nuestro equipo de ingenieros desplegaron primero las herramientas base que hicieron posible correr el Framework MLX, empezando por instalar Homebrew en cada uno de los Mac Studio. Homebrew es un administrador de paquetes para el sistema operativo MacOS que nos permite instalar y desinstalar aplicaciones de manera sencilla sin preocuparnos por sus dependencias. La instalación de este administrador de paquetes se hizo ejecutando en una terminal el comando:
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Al momento de ejecutar este comando se pide que se instale XCode Command Line Tools, para lo cual seguimos el procedimiento que se nos presentó en la pantalla. Lo siguiente fue instalar Python:
$ brew install python@3.11
Descargamos el Framework MLX y sus componentes de apoyo, para luego proceder a instalar los requerimientos y librerías necesarias para el entrenamiento:
$ git clone https://github.com/ml-explore/mlx-examples.git
$ cd mlx-examples/lora
$ pip install -r requirements.txt
$ pip3 install mlx-lm
$ pip3 install tensorflow datasets torch
$ pip3 install urllib3==1.26.15
$ brew install cmake git wget
Para poder ejecutar cómodamente los comandos necesarios de aquí en adelante tuvimos que agregar al PATH el directorio donde quedaron los ejecutables del Framework MLX:
$ echo "$HOME/Library/Python/3.9/bin/" >> /etc/paths
Nos registramos en Huggingface
Huggingface es el gran repositorio de modelos LLM abiertos donde las personas y empresas que se registran pueden descargar los modelos de lenguaje que se publican allí. Como nosotros entrenamos un modelo abierto, lo que hicimos fue bajarlo de Huggingface, no manualmente, sino a través de MLX.
Para que esta descarga automática fuera posible debimos primero registrarnos en Huggingface. Una vez creada una cuenta, fuimos al perfil del usuario, luego entramos a Settings y creamos un Access Token con todos los permisos para acceder a los repositorios. Este Access Token lo copiamos en un lugar seguro y luego en la consola de MacOS creamos una variable de entorno para que automáticamente MLX la usara y pudiera conectarse a las API de Huggingface:
$ export HF_TOKEN="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"
Pedimos autorización para acceder al modelo abierto
Aunque los LLM publicados en Huggingface son libres de acceso y la mayoría de ellos tienen una licencia que permite usarlos comercialmente, se debe solicitar autorización previa para el acceso a cada modelo y esperar a que el desarrollador del mismo lo autorice.
Nosotros solicitamos acceso al modelo de Google Gemma-2 de 9 billones de parámetros en su versión “Instruction Trained” de 18GB y lo hicimos visitando directamente el link y solicitando su acceso. Este proceso de autorización duró un par de días.
Descargamos del modelo
Una vez que el acceso al modelo fue autorizado en Huggingface, procedimos a descargarlo y a convertirlo en el formato que el Framework de MLX entendía:
$ mlx_lm.convert --hf-path google/gemma-2-9b-it
$ ls ~/.cache/huggingface/hub/
Automáticamente se conectaría a Huggingface mediante su API usando como autorización el Access Token que se creó en le punto anterior. Este proceso lo que hizo fue descargar el modelo original a la carpeta oculta cache del usuario de MacOS y adicionalmente creó una carpeta llamada mlx_model donde se guardó el modelo convertido al formato que entiende el Framework MLX.
Creación del dataset de entrenamiento
Posiblemente la parte mas difícil, retadora y demorada de todo el proceso de fine-tuning fue crear el conjunto de datos de entrenamiento. Si quieres entrenar, debes primero ser un profesor o experto en la materia. El proceso de entrenamiento se parece mucho a cómo se le enseña a un estudiante una técnica específica, es decir, con ejemplos, teoría y práctica.
Lo primero que hicimos fue crear un Excel dentro de una carpeta que llamamos data, con los datos que le quisimos enseñar al modelo para que sea más preciso e inteligente. Como nuestra temática es la prevención del fraude, creamos un Excel con muchos casos de fraude y le explicamos al LLM por qué debía considerar cada caso un potencial fraude.
El Excel tiene varias columnas, la primera tiene el texto tipo “conversación” que muestra una casuística de fraude y una segunda columna tiene una explicación del por qué se considera que esto es fraude.
Este archivo de Excel contiene suficiente información en calidad y cantidad de datos para que el modelo impacte significativamente su comprensión y precisión. Para tener una idea de la cantidad de datos, otros dataset que analizan riesgos mentales en comunicaciones escritas, tienen alrededor de entre 1.000 y 50.000 mil filas de ejemplos.
El dataset de NOFRAUD tiene más de 100 mil filas de ejemplos con casuísticas recolectadas y documentadas durante más de 11 años. En El archivo en Excel no se ven otro tipo de columnas de NOFRAUD ha documentado, esto no lo mostramos aquí para guardar y proteger el knowhow de nuestra metodología.
La instrucción que entiende el LLM
Los humanos nos comunicamos con el LLM a través de un prompt. Programáticamente el LLM tiene una serie de reglas para formular el prompt y cada LLM puede tener sus propias reglas de comunicación. Para el LLM de Google Gemma-2 las reglas son estas:
<bos><start_of_turn>user AQUI_VA_LA_PETICION_DEL_HUMANO<end_of_turn>
<start_of_turn>model AQUI_VA_LA_RESPUESTA_QUE_QUEREMOS_OBTENER_DEL_LLM<end_of_turn><eos>
Con lo anterior, la instrucción que entendería el LLM Gemma-2 para entrenarlo sería:
<bos><start_of_turn>user Ayúdame a identificar si existe algun comportamiento
sospechoso, fraudulento, poco ético o riesgoso en el siguiente texto: ### Hola Jose, esperando
que todo se encuentre muy bien,paso por aca para recordarte el cvy que negociamos el otro dia.
Que Dios te bendiga y te de mucha prosperidad, saludos a la familia y espero verte pronto por
aca en la empresa. ###<end_of_turn><start_of_turn>model El comportamiento es sospecho,
riesgoso y poco ético. En Colombia el término 'cvy' se refiere a 'como voy yo' y es usado para
pedir una coima o comisión, normalmente por corrupción en la contratación.<end_of_turn><eos>
Es decir, aunque nuestro dataset se encuentra en Excel, el LLM no entiende ni sabe en principio leer el contenido del Excel ni interpretar qué columna es la petición y cual es la respuesta. El LLM entiende basado en una plantilla, como lo mostramos en los ejemplos especificando los tags de inicio, fin, del input del usuario y el output del modelo. Debido a esto, debimos transformar los datos contenidos en nuestro Excel a ese formato que entiende el LLM como paso previo antes de entrenarlo. Esto lo hicimos con un script en PHP que mostramos a continuación.
Transformamos el dataset al lenguaje del LLM
Vamos a convertir cada fila del archivo del Excel a líneas en el formato de tags que entiende el LLM y adicionalmente vamos a elegir un formato que entiende el framework MLX cuando necesite pasarle estos datos al LLM. Este formato es JSONL (JSON línea a línea separado por un ENTER al final).
Desarrollamos un código en PHP para la labor. Este código lee un archivo Excel linea por linea y lo exporta a varios archivos JSONL:
/*
* The Fraud Explorer
* https://www.thefraudexplorer.com/
*
* Copyright (c) 2014-2024 The Fraud Explorer
* email: customer@thefraudexplorer.com
* Licensed under GNU GPL v3
* https://www.thefraudexplorer.com/License
*
* Author: jrios@nofraud.la
* Version code-name: nemesis
*
* Description: Generation of training files for FraudGPT
*/
require 'vendor/autoload.php';
/* Excel Reader */
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
$spreadsheet = new Spreadsheet();
$inputFileType = 'Xlsx';
$inputFileName = './dataset.xlsx';
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile($inputFileName);
$reader->setReadDataOnly(true);
$spreadsheet = $reader->load($inputFileName);
$sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, true);
/* Prompt */
$prompt = "Ayúdame a identificar si existe algun comportamiento sospechoso, fraudulento, poco\
ético o riesgoso en el siguiente texto: ### %s ###";
/*
* This function curates text
*
* @param string $string -> text to curate
*
* return : curated string
*/
function stringCurator($string)
{
$string = str_replace("\n", " ", $string);
$string = str_replace("\"", "'", $string);
return $string;
}
/*
* This function creates train.jsonl file
*
* no @param : empty
*
* return : none
*/
function create_train_file()
{
global $prompt;
global $sheetData;
if (file_exists("train.jsonl")) unlink("train.jsonl");
if (file_exists("dataset.jsonl")) unlink("dataset.jsonl");
foreach ($sheetData as $key => $value)
{
$query = sprintf($prompt, $value['A']);
$answer = $value['B'];
$result = ['text' => 'user '.stringCurator($query).'model '.stringCurator($answer).''];
$output = json_encode($result, JSON_UNESCAPED_UNICODE) . "\n";
file_put_contents('train.jsonl', $output, FILE_APPEND);
file_put_contents('dataset.jsonl', $output, FILE_APPEND);
}
}
/*
* This function creates valid.jsonl file
*
* no @param : empty
*
* return : none
*/
function create_valid_test_file()
{
if (!file_exists('train.jsonl') ) die('No train.jsonl file found!');
$train = file_get_contents('train.jsonl');
$trainLines = explode("\n", $train);
$totalLines = count($trainLines);
$thirtyPercent = round($totalLines * 0.3);
$twentyPercent = round($totalLines * 0.2);
$tenPercent = round($totalLines * 0.1);
$valLines = array_slice($trainLines, 0, $twentyPercent);
$testLines = array_slice($trainLines, $twentyPercent, $tenPercent);
$trainLines = array_slice($trainLines, $thirtyPercent);
$train = implode("\n", $trainLines);
$val = implode("\n", $valLines);
$test = implode("\n", $testLines);
file_put_contents('train.jsonl', $train);
file_put_contents('valid.jsonl', $val);
file_put_contents('test.jsonl', $test);
}
create_train_file();
create_valid_test_file();
Guardamos este código en el archivo transformDataset.php dentro de la carpeta que hemos creado para almacenar el Excel, llamada data. Para ejecutar este código, previamente debimos instalar PHP y la librería PHPSpreadsheet:
$ brew install php
$ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
$ php composer-setup.php
$ php -r "unlink('composer-setup.php');"
$ ./composer.phar require phpoffice/phpspreadsheet
$ php transformDataset.php
Este código en PHP lo que hizo fue leer el archivo de Excel linea por línea, extrayendo cada una de ellas y creando la instrucción para el LLM en el formato que lo puede entender. Al final tuvimos tres archivos en JSONL, uno llamado train.jsonl, otro llamado valid.jsonl y otro test.jsonl, los cuales tuvieron cada uno un porcentaje de líneas del Excel original, normalmente un 70% en train.jsonl, 20% en valid.jsonl y 10% en test.jsonl, tal cual como lo requiere el Framework de entrenamiento. Cada archivo tiene líneas en formato JSONL que se ven así:
<bos><start_of_turn>user Ayúdame a identificar si existe algun comportamiento
sospechoso, fraudulento, poco ético o riesgoso en el siguiente texto: ### Hola Jose, esperando
que todo se encuentre muy bien,paso por aca para recordarte el cvy que negociamos el otro dia.
Que Dios te bendiga y te de mucha prosperidad, saludos a la familia y espero verte pronto por
aca en la empresa. ###<end_of_turn><start_of_turn>model El comportamiento es sospecho,
riesgoso y poco ético. En Colombia el término 'cvy' se refiere a 'como voy yo' y es usado para
pedir una coima o comisión, normalmente por corrupción en la contratación.<end_of_turn><eos>
Entrenamiento del modelo
Con lo anterior ya estábamos listos para ejecutar el entrenamiento. Lo hicimos con el siguiente comando:
$ mlx_lm.lora --train --model ./mlx_model --data ./data --batch-size 4 --num-layers 16 --iters 300
El argumento model debía apuntar a la carpeta donde se encontraba el modelo Gemma-2 convertido. El argumento data debía apuntar a la carpeta donde se encontraban los archivos train.jsonl y valid.jsonl. El argumento batch, num-layers e iters hacen referencia básicamente a la potencia computacional que se usaría para entrenar el modelo, entre mas recursos se tengan, mas se podrían incrementar estos argumentos.
Para un Apple Silicon Mac Studio M1 Ultra con 64GB de RAM, esto debería tardar aproximadamente 2 horas. Durante ese tiempo el sistema operativo se volvía inutilizable, por lo cual no ejecutaríamos ningún otro tipo de tareas hasta que terminara.
Mientras tanto lo que vimos fue lo siguiente, iteración por iteración:
Loading pretrained model
Total parameters 9241.580M
Trainable parameters 0.715M
Loading datasets
Training
Iter 1: Val loss 0.988, Val took 96.121s
Iter 10: Train loss 0.792, It/sec 0.213, Tokens/sec 219.751
Iter 20: Train loss 0.611, It/sec 0.253, Tokens/sec 248.804
Iter 30: Train loss 0.786, It/sec 0.092, Tokens/sec 96.585
Iter 40: Train loss 0.600, It/sec 0.011, Tokens/sec 77.446
Iter 50: Train loss 0.766, It/sec 0.200, Tokens/sec 131.037
Iter 60: Train loss 0.618, It/sec 0.063, Tokens/sec 82.585
Iter 70: Train loss 0.699, It/sec 0.037, Tokens/sec 31.715
Iter 80: Train loss 0.570, It/sec 0.041, Tokens/sec 49.500
Al terminar el proceso lo que obtuvimos fue una carpeta llamada adapters con varios archivos dentro de ella que contenían los cambios en los pesos al modelo base que podrían ser aplicados para cambiar la forma en la que se comporta, dadas nuestras instrucciones.
Así se ve el consumo de recursos del Mac M1 Ultra al momento de entrenar la red neuronal. Los procesadores centrales (CPU) no se usan, pero en cambio la potencia computacional del GPU se usa completamente junto con la memoria unificada. La temperatura varía entre 50 y 64 grados centígrados y la energía que consume constantemente es en promedio unos 52 Watts.
Fusionamos los adaptadores y el modelo base
Para ese momento teníamos un modelo base original descargado de Huggingface (Gemma-2), un modelo convertido al formato MLX de Gemma-2 y unos adaptadores con la información de los pesos que se debían modificar al modelo base para cambiar su comportamiento.
Lo que hicimos después fue fusionar los adaptadores y el modelo convertido:
$ mlx_lm.fuse --model ./mlx_model --adapter-path ./adapters
Esto nos creó una carpeta llamada fused_model con varios archivos en formato safetensors que si bien ya estaban listos para usarse como modelo LLM, tendríamos que ejecutar unos pasos mas para poder integrarlo al software Ollama, que es el que usamos en NOFRAUD para recibir las peticiones de todas nuestras instancias de manera centralizada.
Lo que hicimos a continuación fue instalar las herramientas necesarias para convertir este modelo recién generado en un formato que entendiera Ollama, que es el formato GGUF:
$ git clone https://github.com/ggerganov/llama.cpp.git
$ cd llama.cpp/
$ pip3 install -r requirements.txt
$ cmake -B build
$ cmake --build build --config Release
Seguimos con la conversión final al formato GGUF y aplicamos quantización de 4bits al modelo:
$ python3 llama.cpp/convert_hf_to_gguf.py ./fused_model --outfile fraudgpt.gguf
$ ./llama.cpp/build/bin/llama-quantize fraudgpt.gguf fraudgpt-4bit.gguf q4_0
El formato GGUF fue diseñado para que la carga y ejecución de un LLM se hiciera de manera mas sencilla en aplicaciones a las que se les pueda configurar este tipo de modelos, como por ejemplo la que utilizamos para The Fraud Explorer llamada Ollama.
La quantización lo que hace es reducir el tamaño del LLM cambiando el tamaño de sus redes neuronales. La quantización de 4bits ha demostrado se efectiva en cuanto a que reduce considerablemente el tamaño del LLM (en este caso de 18GB pasa a 8GB) y no se pierde capacidad de inferencia.
Evaluación del modelo
En NOFRAUD usamos varias métricas para medir la efectividad del modelo, una de ellas es la métrica Perplexity, ademas de medir la pérdida (loss) del entrenamiento y la pérdida de evaluación.
$ mlx_lm.lora --model ./fused_model --data ~/Documents/the-fraud-explorer/LLM/FraudGPT --test
Cuanto más cerca esté la pérdida de entrenamiento al valor 1.2, significa que el modelo no se sobreajustó (overfitting) ni le faltó entrenamiento (underfitting). Si logramos que la métrica de pérdida de evaluación éste cercana a la pérdida de entrenamiento significa que el modelo quedó bien entrenado.
Pasamos el modelo a producción
Subimos el LLM a nuestro servidor dedicado que contiene el hardware específico para cargar el modelo y le indicamos a Ollama que usara el recién actualizado modelo FraudGPT:
$ echo "FROM fraudgpt-4bit.gguf" > Modelfile
$ ollama create -f Modelfile fraudgpt
$ systemctl restart ollama
Lo ponemos a disposición de nuestros clientes
Como hemos comentado en otros artículos, The Fraud Explorer genera alertas por comportamientos anti éticos basados en la teoría del triángulo del fraude de Donald Cressey. Estas alertas se generan no por el análisis del LLM FraudGPT sino por el análisis de un algoritmo léxico.
Esto al principio puede sonar rudimentario, pero nuestro algoritmo léxico garantiza poder dar una explicación transparente al proceso de generación de alertas por sospecha de fraude, lo que no puede ocurrir con una red neuronal, porque no se sabe por qué o cómo llegó a una conclusión. Esto hace parte de nuestra apuesta por la ética en el uso de sistemas de inteligencia artificial.
El modelo LLM FraudGPT entra a funcionar en la última fase o filtro de alertamiento, cuando es necesario aplicar razonamiento para analizar una alerta previamente generada por los algoritmos del triángulo del fraude.
Cada cliente, en su instancia de The Fraud Explorer independiente, consulta al LLM FraudGPT a través de una API y le pide que analice la alerta previamente generada. El LLM devuelve una respuesta compuesta de un razonamiento y otras instrucciones de valor para finalizar el ciclo de alertamiento. Así es como nuestros clientes usan FraudGPT.
Conclusiones
Describimos en éste artículo cómo en NOFRAUD hemos creado nuestro propio modelo LLM FraudGPT paso a paso usando el Framework de Machine Learning MLX del equipo de Apple Research, utilizando el hardware de sus nuevos procesadores M basados en arquitectura ARM y aprovechando los beneficios de su memoria unificada.
Demostramos nuestro proceso de entrenamiento basado en un conjunto de datos privado cuidadosamente construido y refinado durante 11 años, que contiene más de 100 mil casuísticas de comportamientos deshonestos que hemos logrado documentar y que tienen aplicación en diferentes industrias, como la Financiera, de Seguros, Infraestructura, Servicios, Salud, Tecnología, Energética, Oil&Gas, Bancaria, Alimenticia y Manufacturera en la mayoría de países de América Latina.
Nuestros clientes se ven beneficiados de este gran entrenamiento al contar con un sistema que no solo tiene un conocimiento genérico de la ocurrencia de fraudes, sino que tiene un conocimiento mucho más específico sobre las actividades deshonestas que pueden ocurrir en sus organizaciones.
Referencias
(Apple, 2024) Apple MLX Opensource Machine Learning Framework
Acerca de NOFRAUD
NOFRAUD es la compañía que desarrolla el software antifraude The Fraud Explorer y apoya a personas y empresas a enfrentar y solucionar sus retos en materia de fraude interno, corrupción y abuso corporativo. NOFRAUD ha creado la base de datos conductual de actos deshonestos más grande del mundo en Español e Inglés, que sirve para que la inteligencia artificial encuentre patrones sospechosos de corrupción al interior de las organizaciones.
Mejoramos la capacidad de las organizaciones incrementando sus beneficios, arrebatándole a los perpetradores la posibilidad de afectar negativamente los ingresos a través del fraude, la corrupción, el abuso corporativo y la generación de ambientes tóxicos.
Contacte conmigo en » jrios@nofraud.la y Visítenos en » www.nofraud.la.