Serviço de modelo de linguagem grande (LLM) otimizado

Importante

Esse recurso está em uma versão prévia.

Importante

Os exemplos de código neste guia usam APIs preteridas. O Databricks recomenda usar a experiência de taxa de transferência provisionada para inferência otimizada de LLMs. Confira Migrar LLM otimizado atendendo pontos de extremidade para taxa de transferência provisionada.

Este artigo demonstra como habilitar otimizações para LLMs (modelos de linguagem grandes) no Model Serving.

O serviço llm otimizado fornece melhorias de taxa de transferência e latência no intervalo de 3 a 5 vezes melhor em comparação com as abordagens tradicionais de serviço. A tabela a seguir resume as famílias LLM com suporte e suas variantes.

O Databricks recomenda a instalação de modelos de fundação usando o Databricks Marketplace. Você pode procurar uma família de modelos e, na página do modelo, selecione Obter acesso e fornecer credenciais de logon para instalar o modelo no Catálogo do Unity.

Família do modelo Instalar pelo Marketplace
Lhama 2 Modelos do Llama 2
Ministério Público do Trabalho
Mistral Modelos da Mistral

Requisitos

  • O serving otimizado de LLMs é compatível como parte da Versão Prévia Pública de implantações em GPU.

  • Seu modelo deve ser registrado usando o MLflow 2.4 e superior ou o Databricks Runtime 13.2 ML e superior.

  • Ao implantar modelos, é essencial corresponder o tamanho do parâmetro do modelo com o tamanho de computação apropriado. Para modelos com 50 bilhões ou mais de parâmetros, entre em contato com a sua equipe de conta do Azure Databricks para acessar as GPUs necessárias.

    Tamanho dos parâmetros do modelo Tamanho de computação recomendado Tipo de carga de trabalho
    7 bilhões 1xA100 GPU_LARGE
    13 bilhões 1xA100 GPU_LARGE
    30-34 bilhões 1xA100 GPU_LARGE
    70 bilhões 2xA100 GPU_LARGE_2

Registre seu modelo de linguagem de grande porte em log

Primeiro, registre seu modelo com o tipo transformers de MLflow e especifique o campo de tarefa nos metadados MLflow com metadata = {"task": "llm/v1/completions"}. Isto especifica a assinatura da API usada para o endpoint de implantação do modelo.

A disponibilização otimizada de LLMs é compatível com os tipos de rota compatíveis com o Azure Databricks AI Gateway; atualmente, llm/v1/completions. Se houver uma família de modelos ou um tipo de tarefa que você deseja atender que não tenha suporte, entre em contato com sua equipe de conta do Azure Databricks.

model = AutoModelForCausalLM.from_pretrained("mosaicml/mpt-7b-instruct",torch_dtype=torch.bfloat16, trust_remote_code=True)
tokenizer = AutoTokenizer.from_pretrained("mosaicml/mpt-7b-instruct")
with mlflow.start_run():
    components = {
        "model": model,
        "tokenizer": tokenizer,
    }
    mlflow.transformers.log_model(
        artifact_path="model",
        transformers_model=components,
        input_example=["Below is an instruction that describes a task. Write a response that appropriately completes the request.\n\n### Instruction:\nWhat is Apache Spark?\n\n### Response:\n"],
        metadata={"task": "llm/v1/completions"},
        registered_model_name='mpt'
    )

Depois que o modelo for registrado, você poderá registrar seus modelos no Catálogo do Unity com o seguinte, no qual você substituirá CATALOG.SCHEMA.MODEL_NAME pelo nome de três níveis do modelo.


mlflow.set_registry_uri("databricks-uc")

registered_model_name=CATALOG.SCHEMA.MODEL_NAME

Criar o ponto de extremidade de serviço do modelo

Em seguida, crie o endpoint de disponibilização do modelo. Se o seu modelo for aceito pelo serviço de LLM otimizado, o Azure Databricks cria automaticamente um ponto final de serviço de modelo otimizado quando tenta servi-lo.

import requests
import json

# Set the name of the MLflow endpoint
endpoint_name = "llama2-3b-chat"

# Name of the registered MLflow model
model_name = "ml.llm-catalog.llama-13b"

# Get the latest version of the MLflow model
model_version = 3

# Specify the type of compute (CPU, GPU_SMALL, GPU_LARGE, etc.)
workload_type = "GPU_LARGE"

# Specify the scale-out size of compute (Small, Medium, Large, etc.)
workload_size = "Small"

# Specify Scale to Zero (only supported for CPU endpoints)
scale_to_zero = False

# Get the API endpoint and token for the current notebook context
API_ROOT = dbutils.notebook.entry_point.getDbutils().notebook().getContext().apiUrl().get()
API_TOKEN = dbutils.notebook.entry_point.getDbutils().notebook().getContext().apiToken().get()

# send the POST request to create the serving endpoint

data = {
    "name": endpoint_name,
    "config": {
        "served_models": [
            {
                "model_name": model_name,
                "model_version": model_version,
                "workload_size": workload_size,
                "scale_to_zero_enabled": scale_to_zero,
                "workload_type": workload_type,
            }
        ]
    },
}

headers = {"Context-Type": "text/json", "Authorization": f"Bearer {API_TOKEN}"}

response = requests.post(
    url=f"{API_ROOT}/api/2.0/serving-endpoints", json=data, headers=headers
)

print(json.dumps(response.json(), indent=4))

Formato de esquema de entrada e saída

Um endpoint de serviço LLM otimizado tem esquemas de entrada e saída controlados pelo Azure Databricks. Há suporte para quatro formatos diferentes.

  • dataframe_split é um DataFrame do Pandas serializado em JSON na orientação split.

    {
      "dataframe_split": {
        "columns": ["prompt"],
        "index": [0],
        "data": [
          [
            "Below is an instruction that describes a task. Write a response that appropriately completes the request.\n\n### Instructions:\nWhat is Apache Spark?\n\n### Response:\n"
          ]
        ]
      },
      "params": {
        "temperature": 0.5,
        "max_tokens": 100,
        "stop": ["word1", "word2"],
        "candidate_count": 1
      }
    }
    
  • dataframe_records é um DataFrame do Pandas serializado em JSON na orientação records.

    {
      "dataframe_records": [
        {
          "prompt": "Below is an instruction that describes a task. Write a response that appropriately completes the request.\n\n### Instructions:\nWhat is Apache Spark?\n\n### Response:\n"
        }
      ],
      "params": {
        "temperature": 0.5,
        "max_tokens": 100,
        "stop": ["word1", "word2"],
        "candidate_count": 1
      }
    }
    
  • instâncias

    {
      "instances": [
        {
          "prompt": "Below is an instruction that describes a task. Write a response that appropriately completes the request.\n\n### Instructions:\nWhat is Apache Spark?\n\n### Response:\n"
        }
      ],
      "params": {
        "temperature": 0.5,
        "max_tokens": 100,
        "stop": ["word1", "word2"],
        "candidate_count": 1
      }
    }
    
  • entradas

    {
      "inputs": {
        "prompt": "Below is an instruction that describes a task. Write a response that appropriately completes the request.\n\n### Instructions:\nWhat is Apache Spark?\n\n### Response:\n"
      },
      "params": {
        "temperature": 0.5,
        "max_tokens": 100,
        "stop": ["word1", "word2"],
        "candidate_count": 1
      }
    }
    

Consulte seu endpoint

Depois que o endpoint estiver pronto, você poderá consultá-lo fazendo uma requisição à API. Dependendo do tamanho e da complexidade do modelo, pode levar 30 minutos ou mais para o endpoint ficar pronto.


data = {
    "inputs": {
        "prompt": [
            "Hello, I'm a language model,"
        ]
    },
    "params": {
        "max_tokens": 100,
        "temperature": 0.0
    }
}

headers = {"Context-Type": "text/json", "Authorization": f"Bearer {API_TOKEN}"}

response = requests.post(
    url=f"{API_ROOT}/serving-endpoints/{endpoint_name}/invocations", json=data, headers=headers
)

print(json.dumps(response.json()))

Limitações

  • Devido aos maiores requisitos de instalação para modelos atendidos por GPU, a criação da imagem de contêiner para atendimento por GPU leva mais tempo do que a criação da imagem para atendimento por CPU.
    • O tamanho do modelo também afeta a criação da imagem. Por exemplo, modelos que têm 30 bilhões de parâmetros ou mais podem levar pelo menos uma hora para serem compilados.
    • O Databricks reutiliza o mesmo contêiner na próxima vez que a mesma versão do modelo for implantada, portanto, as implantações subsequentes levarão menos tempo.
  • O dimensionamento automático para atendimento com GPU leva mais tempo do que para atendimento com CPU, devido ao maior tempo de configuração dos modelos atendidos em infraestrutura de computação com GPU. O Databricks recomenda o excesso de provisionamento para evitar tempos limite de solicitações.