Language Model (LLM) no es necesariamente el paso final en la producción de su aplicación generativa de IA. Una parte a menudo olvidada, pero crucial del ciclo de vida de MLOPS es adecuadamente prueba de carga Su LLM y asegurarse de que esté listo para soportar su tráfico de producción esperado. Las pruebas de carga en un alto nivel es la práctica de probar su aplicación o en este caso su modelo con el tráfico que esperaría en un entorno de producción asegurarse de que sea un rendimiento.
En el pasado hemos discutido Prueba de carga modelos ML tradicionales Uso de herramientas de Python de código abierto como Langosta. La langosta ayuda a capturar métricas de rendimiento general, como solicitudes por segundo (RPS) y percentiles de latencia por solicitud. Si bien esto es efectivo con modelos API y ML más tradicionales, no captura la historia completa para LLM.
Los LLM tradicionalmente tienen un RPS mucho más bajo y una latencia más alta que los modelos ML tradicionales debido a su tamaño y mayores requisitos de cómputo. En general, la métrica RPS realmente no proporciona la imagen más precisa, ya que las solicitudes pueden variar en gran medida según la entrada al LLM. Por ejemplo, es posible que tenga una consulta pidiendo resumir una gran parte del texto y otra consulta que podría requerir una respuesta de una palabra.
Por eso tokens son vistos como una representación mucho más precisa del rendimiento de un LLM. En un nivel alto, un token es un trozo de texto, cada vez que un LLM procesa su entrada, “toca” la entrada. Un token difiere dependiendo específicamente del LLM que esté utilizando, pero puede imaginarlo, por ejemplo, como una palabra, secuencia de palabras o caracteres en esencia.
Lo que haremos en este artículo es explorar cómo podemos generar métricas basadas en token para que podamos entender cómo su LLM está funcionando desde una perspectiva de servicio/implementación. Después de este artículo, tendrá una idea de cómo puede configurar una herramienta de prueba de carga específicamente para comparar diferentes LLM en el caso de que esté evaluando muchos modelos o diferentes configuraciones de implementación o una combinación de ambos.
¡Vamos a tener en la mano! Si es más un alumno basado en video, no dude en seguir mi video correspondiente de YouTube a continuación:
NOTA: Este artículo asume una comprensión básica de Python, LLMS y Amazon Bedrock/Sagemaker. Si es nuevo en el roca madre de Amazon, consulte mi guía de inicio aquí. Si desea obtener más información sobre las implementaciones de Sagemaker JumpStart LLM, consulte el video aquí.
DESCARGO DE RESPONSABILIDAD: Soy un arquitecto de aprendizaje automático en AWS y mis opiniones son mías.
Tabla de contenido
- Métricas específicas de LLM
- Intro de llmperf
- Aplicar LLMPERF a Amazon Bedrock
- Recursos adicionales y conclusión
Métricas específicas de LLM
Como discutimos brevemente en la introducción con respecto al alojamiento de LLM, las métricas basadas en tokens generalmente proporcionan una representación mucho mejor de cómo su LLM está respondiendo a diferentes tamaños de carga útil o tipos de consultas (resumen vs QNA).
Tradicionalmente, siempre hemos rastreado RP y latencia que aún veremos aquí, pero más aún a nivel de token. Estas son algunas de las métricas a tener en cuenta antes de comenzar con las pruebas de carga:
- Es hora de token primero: Esta es la duración que se necesita para generar el primer token. Esto es especialmente útil cuando se transmite. Por ejemplo, cuando se usa CHATGPT, comenzamos a procesar información cuando aparece la primera pieza de texto (token).
- Tokens de salida total por segundo: Este es el número total de tokens generados por segundo, puede pensar en esto como una alternativa más granular a las solicitudes por segundo que tradicionalmente rastreamos.
Estas son las principales métricas en las que nos centraremos, y hay algunas otras, como la latencia interactiva, que también se mostrarán como parte de las pruebas de carga. Tenga en cuenta que los parámetros que también influyen en estas métricas incluyen el tamaño esperado de la entrada y el token de salida. Jugamos específicamente con estos parámetros para obtener una comprensión precisa de cómo funciona nuestro LLM en respuesta a las diferentes tareas de generación.
Ahora echemos un vistazo a una herramienta que nos permite alternar estos parámetros y mostrar las métricas relevantes que necesitamos.
Intro de llmperf
LLMPERF se construye encima de Rayoun popular marco de Python de computación distribuida. LLMPERF aprovecha específicamente a Ray para crear pruebas de carga distribuidas donde podemos simular el tráfico de nivel de producción en tiempo real.
Tenga en cuenta que cualquier herramienta de prueba de carga también solo podrá generar su cantidad esperada de tráfico si la máquina del cliente en la que está tiene suficiente potencia de cálculo para que coincida con su carga esperada. Por ejemplo, a medida que escala la concurrencia o rendimiento esperado para su modelo, también desea escalar las máquinas del cliente donde está ejecutando su prueba de carga.
Ahora específicamente dentro Llmperf Hay algunos parámetros expuestos que se adaptan a las pruebas de carga LLM, como hemos discutido:
- Modelo: Este es el proveedor de modelos y su modelo alojado con el que está trabajando. Para nuestro caso de uso será Roca madre de Amazon y Soneto Claude 3 específicamente.
- API LLM: Este es el formato API en el que se debe estructurar la carga útil. Usamos Litellm que proporciona una estructura de carga útil estandarizada en diferentes proveedores de modelos, simplificando así el proceso de configuración para nosotros, especialmente si queremos probar diferentes modelos alojados en diferentes plataformas.
- Tokens de entrada: La longitud media del token de entrada, también puede especificar una desviación estándar para este número.
- Tokens de salida: La longitud media del token de salida, también puede especificar una desviación estándar para este número.
- Solicitudes concurrentes: El número de solicitudes concurrentes para que la prueba de carga simule.
- Duración de la prueba: Puede controlar la duración de la prueba, este parámetro está habilitado en segundos.
LLMPERF expone específicamente todos estos parámetros a través de su token_benchmark_ray.py Script que configuramos con nuestros valores específicos. Echemos un vistazo ahora a cómo podemos configurar esto específicamente para Amazon Bedrock.
Aplicar LLMPERF a Amazon Bedrock
Configuración
Para este ejemplo trabajaremos en un Instancia de cuaderno clásico de Sagemaker con un conda_python3 kernel y Ml.G5.12xLarge instancia. Tenga en cuenta que desea seleccionar una instancia que tenga suficiente cálculo para generar la carga de tráfico que desea simular. Asegúrese de tener su Credenciales de AWS para que LLMPERF acceda al modelo alojado, ya sea en Bedrock o Sagemaker.
Configuración de litellm
Primero configuramos nuestra estructura de la API LLM de elección, que es litellm en este caso. Con Litellm hay soporte en varios proveedores de modelos, en este caso configuramos el API de finalización Para trabajar con Amazon Bedrock:
import os
from litellm import completion
os.environ["AWS_ACCESS_KEY_ID"] = "Enter your access key ID"
os.environ["AWS_SECRET_ACCESS_KEY"] = "Enter your secret access key"
os.environ["AWS_REGION_NAME"] = "us-east-1"
response = completion(
model="anthropic.claude-3-sonnet-20240229-v1:0",
messages=[{ "content": "Who is Roger Federer?","role": "user"}]
)
output = response.choices[0].message.content
print(output)
Para trabajar con Bedrock, configuramos la ID del modelo para apuntar hacia Claude 3 Sonnet y pasar en nuestro mensaje. La parte ordenada con Litellm es que la clave de mensajes tiene un formato consistente entre los proveedores de modelos.
Después de la ejecución aquí, podemos centrarnos en configurar LLMPERF para Bedrock específicamente.
LLMPERF Bedrock Integration
Para ejecutar una prueba de carga con LLMPERF, simplemente podemos usar el proporcionado token_benchmark_ray.py script y pase en los siguientes parámetros de los que hablamos anteriormente:
- Tokens de entrada media y desviación estándar
- Tokens de salida media y desviación estándar
- Número máximo de solicitudes de prueba
- Duración de la prueba
- Solicitudes concurrentes
En este caso, también especificamos que nuestro formato API es litellm y podemos ejecutar la prueba de carga con un script de shell simple como el siguiente:
%%sh
python llmperf/token_benchmark_ray.py \
--model bedrock/anthropic.claude-3-sonnet-20240229-v1:0 \
--mean-input-tokens 1024 \
--stddev-input-tokens 200 \
--mean-output-tokens 1024 \
--stddev-output-tokens 200 \
--max-num-completed-requests 30 \
--num-concurrent-requests 1 \
--timeout 300 \
--llm-api litellm \
--results-dir bedrock-outputs
En este caso, mantenemos la concurrencia baja, pero no dudamos en alternar este número dependiendo de lo que esté esperando en la producción. Nuestra prueba se ejecutará durante 300 segundos y la duración posterior debe ver un directorio de salida con dos archivos que representan estadísticas para cada inferencia y también las métricas medias en todas las solicitudes en la duración de la prueba.
Podemos hacer que este aspecto sea un poco más ordenado analizando el archivo de resumen con pandas:
import json
from pathlib import Path
import pandas as pd
# Load JSON files
individual_path = Path("bedrock-outputs/bedrock-anthropic-claude-3-sonnet-20240229-v1-0_1024_1024_individual_responses.json")
summary_path = Path("bedrock-outputs/bedrock-anthropic-claude-3-sonnet-20240229-v1-0_1024_1024_summary.json")
with open(individual_path, "r") as f:
individual_data = json.load(f)
with open(summary_path, "r") as f:
summary_data = json.load(f)
# Print summary metrics
df = pd.DataFrame(individual_data)
summary_metrics = {
"Model": summary_data.get("model"),
"Mean Input Tokens": summary_data.get("mean_input_tokens"),
"Stddev Input Tokens": summary_data.get("stddev_input_tokens"),
"Mean Output Tokens": summary_data.get("mean_output_tokens"),
"Stddev Output Tokens": summary_data.get("stddev_output_tokens"),
"Mean TTFT (s)": summary_data.get("results_ttft_s_mean"),
"Mean Inter-token Latency (s)": summary_data.get("results_inter_token_latency_s_mean"),
"Mean Output Throughput (tokens/s)": summary_data.get("results_mean_output_throughput_token_per_s"),
"Completed Requests": summary_data.get("results_num_completed_requests"),
"Error Rate": summary_data.get("results_error_rate")
}
print("Claude 3 Sonnet - Performance Summary:\n")
for k, v in summary_metrics.items():
print(f"{k}: {v}")
Los resultados de la prueba de carga final se verán como lo siguiente:
Como podemos ver, vemos los parámetros de entrada que configuramos, y luego los resultados correspondientes con el tiempo de token (s) y rendimiento con respecto a los tokens de salida medios por segundo.
En un caso de uso del mundo real, puede usar LLMPERF en muchos proveedores de modelos diferentes y ejecutar pruebas en estas plataformas. Con esta herramienta, puede usarla de manera integral para identificar el modelo adecuado y la pila de implementación para su caso de uso cuando se usa a escala.
Recursos adicionales y conclusión
Todo el código para la muestra se puede encontrar en este asociado Repositorio de Github. Si también desea trabajar con SageMaker Endpoints, puede encontrar una muestra de prueba de carga de implementación de Llama JumpStart aquí.
En general, las pruebas y evaluación de carga son cruciales para garantizar que su LLM tenga un rendimiento contra su tráfico esperado antes de empujar a la producción. En futuros artículos cubriremos no solo la parte de evaluación, sino cómo podemos crear una prueba holística con ambos componentes.
Como siempre, gracias por leer y no dude en dejar cualquier comentario y conectarse conmigo en Linkedln y incógnita.