Elevando la experiencia de la IA generativa Introduciendo el soporte de transmisión en la hospedaje de Amazon SageMaker

Potenciando la IA generativa con transmisión en Amazon SageMaker

Nos complace anunciar la disponibilidad de la transmisión de respuestas a través de la inferencia en tiempo real de Amazon SageMaker. Ahora puedes transmitir continuamente las respuestas de inferencia de vuelta al cliente cuando uses la inferencia en tiempo real de SageMaker para ayudarte a crear experiencias interactivas para aplicaciones de inteligencia artificial generativa como chatbots, asistentes virtuales y generadores de música. Con esta nueva función, puedes comenzar a transmitir las respuestas inmediatamente cuando estén disponibles en lugar de esperar a que se genere toda la respuesta. Esto reduce el tiempo hasta el primer byte para tus aplicaciones de inteligencia artificial generativa.

En esta publicación, mostraremos cómo construir una aplicación web de transmisión utilizando puntos finales en tiempo real de SageMaker con la nueva función de transmisión de respuestas para un caso de uso de chat interactivo. Utilizamos Streamlit para la interfaz de usuario de la aplicación de demostración de muestra.

Descripción general de la solución

Para obtener respuestas transmitidas desde SageMaker, puedes usar nuestra nueva API InvokeEndpointWithResponseStream. Ayuda a mejorar la satisfacción del cliente al ofrecer un tiempo hasta la primera respuesta más rápido. Esta reducción en la latencia percibida por el cliente es particularmente crucial para aplicaciones construidas con modelos de inteligencia artificial generativa, donde se valora el procesamiento inmediato en lugar de esperar toda la carga útil. Además, introduce una sesión persistente que permitirá la continuidad en las interacciones, beneficiando casos de uso como los chatbots para crear experiencias de usuario más naturales y eficientes.

La implementación de la transmisión de respuestas en los puntos finales en tiempo real de SageMaker se logra a través de la codificación fragmentada HTTP 1.1, que es un mecanismo para enviar múltiples respuestas. Este es un estándar HTTP que admite contenido binario y es compatible con la mayoría de los marcos cliente/servidor. La codificación fragmentada HTTP admite tanto la transmisión de datos de texto como de imágenes, lo que significa que los modelos alojados en los puntos finales de SageMaker pueden enviar respuestas transmitidas como texto o imagen, como los modelos Falcon, Llama 2 y Stable Diffusion. En cuanto a la seguridad, tanto la entrada como la salida están aseguradas mediante TLS utilizando AWS Sigv4 Auth. También se implementan otras técnicas de transmisión como Server-Sent Events (SSE) utilizando el mismo mecanismo de codificación fragmentada HTTP. Para aprovechar la nueva API de transmisión, debes asegurarte de que el contenedor del modelo devuelva la respuesta transmitida como datos codificados en fragmentos.

El siguiente diagrama ilustra la arquitectura de alto nivel para la transmisión de respuestas con un punto final de inferencia de SageMaker.

Uno de los casos de uso que se beneficiará de la transmisión de respuestas es el de los chatbots impulsados por modelos de inteligencia artificial generativa. Tradicionalmente, los usuarios envían una consulta y esperan a que se genere toda la respuesta antes de recibir una respuesta. Esto podría llevar segundos preciosos o incluso más tiempo, lo que potencialmente puede degradar el rendimiento de la aplicación. Con la transmisión de respuestas, el chatbot puede comenzar a enviar resultados parciales de inferencia a medida que se generan. Esto significa que los usuarios pueden ver la respuesta inicial casi instantáneamente, incluso mientras la inteligencia artificial continúa refinando su respuesta en segundo plano. Esto crea un flujo de conversación fluido y atractivo, donde los usuarios sienten que están chateando con una inteligencia artificial que comprende y responde en tiempo real.

En esta publicación, mostramos dos opciones de contenedor para crear un punto final de SageMaker con transmisión de respuestas: usando un contenedor de Inferencia de Modelo Grande (LMI) de AWS y un contenedor de Inferencia de Generación de Texto Hugging Face (TGI). En las secciones siguientes, te guiaremos a través de los pasos de implementación detallados para implementar y probar el modelo Falcon-7B-Instruct utilizando tanto los contenedores LMI como TGI en SageMaker. Elegimos Falcon 7B como ejemplo, pero cualquier modelo puede aprovechar esta nueva función de transmisión.

Prerrequisitos

Necesitas una cuenta de AWS con un rol de Identity and Access Management (IAM) con permisos para administrar los recursos creados como parte de la solución. Para obtener detalles, consulta Crear una cuenta de AWS. Si es la primera vez que trabajas con Amazon SageMaker Studio, primero debes crear un dominio de SageMaker. Además, es posible que necesites solicitar un aumento de cuota de servicio para las instancias de alojamiento de SageMaker correspondientes. Para el modelo Falcon-7B-Instruct, utilizamos una instancia de alojamiento de SageMaker ml.g5.2xlarge. Para alojar un modelo Falcon-40B-Instruct, utilizamos una instancia de alojamiento de SageMaker ml.g5.48xlarge. Puedes solicitar un aumento de cuota desde la interfaz de Service Quotas. Para obtener más información, consulta Cómo solicitar un aumento de cuota.

Opción 1: Implementar un punto final de transmisión en tiempo real utilizando un contenedor LMI

El contenedor LMI es uno de los contenedores de Deep Learning para inferencia de modelos grandes alojados por SageMaker para facilitar el alojamiento de modelos de lenguaje grandes (LLMs) en la infraestructura de AWS para casos de uso de inferencia de baja latencia. El contenedor LMI utiliza Deep Java Library (DJL) Serving, que es un marco Java de alto nivel y agnóstico del motor de inteligencia artificial para el aprendizaje profundo. Con estos contenedores, puedes utilizar bibliotecas de código abierto correspondientes como DeepSpeed, Accelerate, Transformers-neuronx y FasterTransformer para particionar los parámetros del modelo utilizando técnicas de paralelismo de modelo para utilizar la memoria de múltiples GPUs o aceleradores para la inferencia. Para obtener más detalles sobre los beneficios de utilizar el contenedor LMI para implementar modelos grandes en SageMaker, consulta Implementar modelos grandes con alto rendimiento utilizando FasterTransformer en Amazon SageMaker e Implementar modelos grandes en Amazon SageMaker utilizando DJLServing e inferencia de modelo paralelo de DeepSpeed. También puedes encontrar más ejemplos de alojamiento de LLMs de código abierto en SageMaker utilizando los contenedores LMI en este repositorio de GitHub.

Para el contenedor LMI, esperamos los siguientes artefactos para ayudar a configurar el modelo para la inferencia:

  • serving.properties (requerido) – Define la configuración del servidor de modelos
  • model.py (opcional) – Un archivo Python para definir la lógica principal de inferencia
  • requirements.txt (opcional) – Cualquier rueda de pip adicional que se necesite instalar

Los contenedores LMI se pueden utilizar para alojar modelos sin proporcionar su propio código de inferencia. Esto es extremadamente útil cuando no hay un procesamiento personalizado de los datos de entrada o un postprocesamiento de las predicciones del modelo. Utilizamos la siguiente configuración:

  • Para este ejemplo, alojamos el modelo Falcon-7B-Instruct. Necesitamos crear un archivo de configuración serving.properties con nuestras opciones de alojamiento deseadas y empaquetarlo en un artefacto tar.gz. La transmisión de respuestas se puede habilitar en DJL Serving configurando la opción enable_streaming en el archivo serving.properties. Para todos los parámetros admitidos, consulte la configuración de transmisión de Python.
  • En este ejemplo, utilizamos los controladores predeterminados en DJL Serving para transmitir respuestas, por lo que solo nos preocupamos por enviar solicitudes e interpretar la respuesta de salida. También puede proporcionar un código de entrypoint con un controlador personalizado en un archivo model.py para personalizar los controladores de entrada y salida. Para obtener más detalles sobre el controlador personalizado, consulte el controlador personalizado de model.py.
  • Debido a que alojamos el modelo Falcon-7B-Instruct en una sola instancia de GPU (ml.g5.2xlarge), establecemos option.tensor_parallel_degree en 1. Si planea ejecutar en varias GPUs, utilice esto para establecer el número de GPUs por trabajador.
  • Utilizamos option.output_formatter para controlar el tipo de contenido de salida. El tipo de contenido de salida predeterminado es application/json, por lo que si su aplicación requiere una salida diferente, puede sobrescribir este valor. Para obtener más información sobre las opciones disponibles, consulte las configuraciones y opciones de configuración de DJL.
%%writefile serving.properties
engine=MPI 
option.model_id=tiiuae/falcon-7b-instruct
option.trust_remote_code=true
option.tensor_parallel_degree=1
option.max_rolling_batch_size=32
option.rolling_batch=auto
option.output_formatter=jsonlines
option.paged_attention=false
option.enable_streaming=true

Para crear el modelo de SageMaker, recupere la URI de la imagen del contenedor:

image_uri = image_uris.retrieve(
    framework="djl-deepspeed",
    region=sess.boto_session.region_name,
    version="0.23.0"
)

Utilice el SDK de Python de SageMaker para crear el modelo de SageMaker e implementarlo en un punto de enlace en tiempo real de SageMaker utilizando el método deploy:

instance_type = "ml.g5.2xlarge"
endpoint_name = sagemaker.utils.name_from_base("lmi-model-falcon-7b")

model = Model(sagemaker_session=sess, 
                image_uri=image_uri, 
                model_data=code_artifact, 
                role=role)

model.deploy(
    initial_instance_count=1,
    instance_type=instance_type,
    endpoint_name=endpoint_name,
    container_startup_health_check_timeout=900
)

Cuando el punto de enlace esté en servicio, puede utilizar la llamada de API InvokeEndpointWithResponseStream para invocar el modelo. Esta API permite que el modelo responda como una secuencia de partes de la carga útil de respuesta completa. Esto permite que los modelos respondan con respuestas de mayor tamaño y habilita un tiempo más rápido hasta el primer byte para modelos en los que hay una diferencia significativa entre la generación del primer y el último byte de la respuesta.

El tipo de contenido de respuesta mostrado en x-amzn-sagemaker-content-type para el contenedor LMI es application/jsonlines según se especifica en la configuración de las propiedades del modelo. Como forma parte de los formatos de datos comunes admitidos para la inferencia, podemos utilizar el deserializador predeterminado proporcionado por el SDK de Python de SageMaker para deserializar los datos de líneas JSON. Creamos una clase de ayuda LineIterator para analizar la secuencia de respuesta recibida desde la solicitud de inferencia:

class LineIterator:
    """
    Una clase de ayuda para analizar la entrada de flujo de bytes. 
    
    La salida del modelo estará en el siguiente formato:
    ```
    b'{"outputs": [" a"]}\n'
    b'{"outputs": [" challenging"]}\n'
    b'{"outputs": [" problem"]}\n'
    ...
    ```
    
    Aunque normalmente cada evento PayloadPart del flujo de eventos contendrá una matriz de bytes
    con un json completo, esto no está garantizado y algunos de los objetos json pueden estar divididos entre
    eventos PayloadPart. Por ejemplo:
    ```
    {'PayloadPart': {'Bytes': b'{"outputs": '}}
    {'PayloadPart': {'Bytes': b'[" problem"]}\n'}}
    ```
    
    Esta clase tiene esto en cuenta concatenando bytes escritos a través de la función 'write'
    y luego exponiendo un método que devolverá líneas (terminadas con un carácter '\n') dentro
    del búfer a través de la función 'scan_lines'. Mantiene la posición de lectura anterior
    para asegurarse de que los bytes anteriores no se expongan nuevamente. 
    """
    
    def __init__(self, stream):
        self.byte_iterator = iter(stream)
        self.buffer = io.BytesIO()
        self.read_pos = 0

    def __iter__(self):
        return self

    def __next__(self):
        while True:
            self.buffer.seek(self.read_pos)
            line = self.buffer.readline()
            if line and line[-1] == ord('\n'):
                self.read_pos += len(line)
                return line[:-1]
            try:
                chunk = next(self.byte_iterator)
            except StopIteration:
                if self.read_pos < self.buffer.getbuffer().nbytes:
                    continue
                raise
            if 'PayloadPart' not in chunk:
                print('Tipo de evento desconocido:' + chunk)
                continue
            self.buffer.seek(0, io.SEEK_END)
            self.buffer.write(chunk['PayloadPart']['Bytes'])

Con la clase en el código anterior, cada vez que se transmite una respuesta, devolverá una cadena binaria (por ejemplo, b'{"outputs": [" a"]}\n') que se puede deserializar nuevamente en un diccionario de Python utilizando el paquete JSON. Podemos usar el siguiente código para iterar a través de cada línea de texto transmitida y devolver la respuesta de texto:

body = {"inputs": "¿qué es la vida?", "parameters": {"max_new_tokens":400}}
resp = smr.invoke_endpoint_with_response_stream(EndpointName=nombre_endpoint, Body=json.dumps(body), ContentType="application/json")
event_stream = resp['Body']

for line in LineIterator(event_stream):
    resp = json.loads(line)
    print(resp.get("outputs")[0], end='')

La siguiente captura de pantalla muestra cómo se vería si se invoca el modelo a través del bloc de notas SageMaker utilizando un contenedor LMI.

Opción 2: Implementar un chatbot utilizando un contenedor Hugging Face TGI

En la sección anterior, viste cómo implementar el modelo Falcon-7B-Instruct utilizando un contenedor LMI. En esta sección, mostramos cómo hacer lo mismo utilizando un contenedor Hugging Face Text Generation Inference (TGI) en SageMaker. TGI es una solución de código abierto especialmente diseñada para implementar LLM. Incorpora optimizaciones que incluyen paralelismo de tensor para una inferencia de múltiples GPU más rápida, lotificación dinámica para aumentar el rendimiento general y un código de transformers optimizado que utiliza flash-attention para arquitecturas de modelos populares como BLOOM, T5, GPT-NeoX, StarCoder y LLaMa.

Los contenedores de aprendizaje profundo TGI admiten la transmisión de tokens utilizando Server-Sent Events (SSE). Con la transmisión de tokens, el servidor puede comenzar a responder después del primer pase de “prefill” directamente, sin esperar a que se complete toda la generación. Para consultas extremadamente largas, esto significa que los clientes pueden comenzar a ver algo sucediendo órdenes de magnitud antes de que se complete el trabajo. El siguiente diagrama muestra un flujo de trabajo de solicitud/respuesta de extremo a extremo de alto nivel para alojar LLM en un punto de conexión de SageMaker utilizando el contenedor TGI.

Para implementar el modelo Falcon-7B-Instruct en un punto de conexión de SageMaker, utilizamos la clase HuggingFaceModel del SDK de Python de SageMaker. Comenzamos estableciendo nuestros parámetros de la siguiente manera:

hf_model_id = "tiiuae/falcon-7b-instruct" # ID del modelo de huggingface.co/models
number_of_gpus = 1 # número de GPUs a utilizar para inferencia y paralelismo de tensor
health_check_timeout = 300 # Aumentar el tiempo de espera para la comprobación de salud a 5 minutos para descargar el modelo
instance_type = "ml.g5.2xlarge" # tipo de instancia a utilizar para la implementación

En comparación con la implementación de modelos regulares de Hugging Face, primero necesitamos recuperar la URI del contenedor y proporcionarla a nuestra clase de modelo HuggingFaceModel con image_uri apuntando a la imagen. Para recuperar el nuevo DLC de Hugging Face LLM en SageMaker, podemos utilizar el método get_huggingface_llm_image_uri proporcionado por el SDK de SageMaker. Este método nos permite recuperar la URI del DLC de Hugging Face LLM deseado en función del backend, la sesión, la región y la versión especificados. Para obtener más detalles sobre las versiones disponibles, consulte los contenedores de inferencia de generación de texto de HuggingFace.

llm_image = get_huggingface_llm_image_uri(
    "huggingface",
    version="0.9.3"
)

Luego creamos el HuggingFaceModel y lo implementamos en SageMaker utilizando el método deploy:

endpoint_name = sagemaker.utils.name_from_base("tgi-model-falcon-7b")
llm_model = HuggingFaceModel(
    role=role,
    image_uri=llm_image,
    env={
        'HF_MODEL_ID': hf_model_id,
        # 'HF_MODEL_QUANTIZE': "bitsandbytes", # comentar para cuantizar
        'SM_NUM_GPUS': str(number_of_gpus),
        'MAX_INPUT_LENGTH': "1900",  # Longitud máxima del texto de entrada
        'MAX_TOTAL_TOKENS': "2048",  # Longitud máxima de la generación (incluido el texto de entrada)
    }
)

llm = llm_model.deploy(
    initial_instance_count=1,
    instance_type=instance_type,
    container_startup_health_check_timeout=health_check_timeout,
    endpoint_name=endpoint_name,
)

La diferencia principal en comparación con el contenedor LMI es que habilitas la transmisión de respuestas cuando invocas el punto final suministrando stream=true como parte de la carga útil de la solicitud de invocación. El siguiente código es un ejemplo de la carga útil utilizada para invocar el contenedor TGI con transmisión:

body = {
    "inputs":"dime una oración",
    "parameters":{
        "max_new_tokens":400,
        "return_full_text": False
    },
    "stream": True
}

Luego puedes invocar el punto final y recibir una respuesta transmitida utilizando el siguiente comando:

from sagemaker.base_deserializers import StreamDeserializer

llm.deserializer=StreamDeserializer()
resp = smr.invoke_endpoint_with_response_stream(EndpointName=llm.endpoint_name, Body=json.dumps(body), ContentType='application/json')

El tipo de contenido de respuesta mostrado en x-amzn-sagemaker-content-type para el contenedor TGI es text/event-stream. Utilizamos StreamDeserializer para deserializar la respuesta en la clase EventStream y analizamos el cuerpo de la respuesta utilizando la misma clase LineIterator que se utiliza en la sección del contenedor LMI.

Ten en cuenta que la respuesta transmitida de los contenedores TGI devolverá una cadena binaria (por ejemplo, b`data:{"token": {"text": "sometext"}}`), que se puede deserializar nuevamente en un diccionario de Python utilizando un paquete JSON. Podemos utilizar el siguiente código para iterar a través de cada línea transmitida de texto y devolver una respuesta de texto:

event_stream = resp['Body']
start_json = b'{'
for line in LineIterator(event_stream):
    if line != b'' and start_json in line:
        data = json.loads(line[line.find(start_json):].decode('utf-8'))
        if data['token']['text'] != stop_token:
            print(data['token']['text'], end='')

La siguiente captura de pantalla muestra cómo se vería si invocaras el modelo a través del bloc de notas de SageMaker utilizando un contenedor TGI.

Ejecuta la aplicación de chatbot en SageMaker Studio

En este caso de uso, construimos un chatbot dinámico en SageMaker Studio utilizando Streamlit, que invoca el modelo Falcon-7B-Instruct alojado en un punto final en tiempo real de SageMaker para proporcionar respuestas en tiempo real. Primero, puedes probar que las respuestas en tiempo real funcionan en el bloc de notas como se muestra en la sección anterior. Luego, puedes configurar la aplicación Streamlit en el terminal JupyterServer de SageMaker Studio y acceder a la interfaz de usuario del chatbot desde tu navegador siguiendo los siguientes pasos:

  1. Abre un terminal del sistema en SageMaker Studio.

  2. En el menú superior de la consola de SageMaker Studio, elige Archivo, luego Nuevo, luego Terminal.

  3. Instala los paquetes de Python requeridos que se especifican en el archivo requirements.txt:

    $ pip install -r requirements.txt
  4. Configura la variable de entorno con el nombre del punto final implementado en tu cuenta:

    $ export endpoint_name=<nombre del punto final Falcon-7B-instruct implementado en tu cuenta>
  5. Inicia la aplicación Streamlit desde el archivo streamlit_chatbot_<LMI o TGI>.py, que actualizará automáticamente los nombres de los puntos finales en el script en función de la variable de entorno que se configuró anteriormente:

    $ streamlit run streamlit_chatbot_LMI.py --server.port 6006
  6. Para acceder a la interfaz de usuario de Streamlit, copia tu URL de SageMaker Studio en otra pestaña de tu navegador y reemplaza lab? con proxy/[NÚMERO DE PUERTO]/. Como especificamos el puerto del servidor como 6006, la URL debería verse de la siguiente manera:

    https://<ID de dominio>.studio.<región>.sagemaker.aws/jupyter/default/proxy/6006/

Reemplace el ID del dominio y la Región en la URL anterior con su cuenta y Región para acceder a la interfaz de usuario del chatbot. Puede encontrar algunas sugerencias de comandos en el panel izquierdo para comenzar.

La siguiente demostración muestra cómo la transmisión de respuestas revoluciona la experiencia del usuario. Puede hacer que las interacciones se sientan fluidas y receptivas, mejorando así la satisfacción y participación del usuario. Consulte el repositorio de GitHub para obtener más detalles sobre la implementación del chatbot.

Limpiar

Cuando haya terminado de probar los modelos, como buena práctica, elimine el punto final para ahorrar costos si el punto final ya no es necesario:

# - Eliminar el punto final
sm_client.delete_endpoint(EndpointName=endpoint_name)

Conclusión

En esta publicación, proporcionamos una descripción general de cómo construir aplicaciones con IA generativa, los desafíos y cómo SageMaker con la transmisión de respuestas en tiempo real le ayuda a abordar estos desafíos. Mostramos cómo construir una aplicación de chatbot para implementar el modelo Falcon-7B-Instruct utilizando la transmisión de respuestas utilizando los contenedores de SageMaker LMI y HuggingFace TGI usando un ejemplo disponible en GitHub.

¡Comience a construir sus propias aplicaciones de transmisión de vanguardia con LLMs y SageMaker hoy mismo! Contáctenos para obtener orientación experta y desbloquear el potencial de la transmisión de modelos grandes para sus proyectos.

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

Biosensor ofrece retroalimentación en tiempo real para la diálisis

Investigadores de la Universidad de Tecnología de Shahrood en Irán han desarrollado un nuevo biosensor para acelerar ...

Aprendizaje Automático

La caja de voz de Meta la IA que habla todos los idiomas.

En un desarrollo innovador, Meta, la empresa matriz de Facebook, ha presentado su última inteligencia artificial (IA)...

Inteligencia Artificial

Explorando las últimas tendencias en IA/DL Desde el Metaverso hasta la Computación Cuántica

El autor discute varias tendencias emergentes en Inteligencia Artificial y Aprendizaje Profundo, como el Metaverso y ...

Inteligencia Artificial

Silicon Volley Los diseñadores utilizan la IA generativa para obtener un asistente de Chip

Un artículo de investigación publicado hoy describe formas en que la inteligencia artificial generativa puede ayudar ...

Ciencias de la Computación

Alphabet apuesta por los láseres para llevar Internet a áreas remotas

El proyecto Taara utiliza láseres para llevar acceso a Internet a zonas remotas y rurales.