Azure OpenAI para big data

O serviço Azure OpenAI pode ser usado para resolver um grande número de tarefas de linguagem natural por meio da solicitação da API de conclusão. Para facilitar a escala de seus fluxos de trabalho de solicitação de alguns exemplos para grandes conjuntos de dados de exemplos, integramos o serviço Azure OpenAI com a biblioteca de aprendizado de máquina distribuída SynapseML. Essa integração facilita o uso da estrutura de computação distribuída Apache Spark para processar milhões de prompts com o serviço OpenAI. Este tutorial mostra como aplicar modelos de linguagem grandes em uma escala distribuída usando o Azure OpenAI e o Azure Synapse Analytics.

Pré-requisitos

Os principais pré-requisitos para este início rápido incluem um recurso OpenAI do Azure em funcionamento e um cluster Apache Spark com SynapseML instalado.

  • Obtenha uma assinatura do Microsoft Fabric. Ou inscreva-se para uma avaliação gratuita do Microsoft Fabric.

  • Entre no Microsoft Fabric.

  • Use o seletor de experiência no lado esquerdo da sua página inicial para alternar para a experiência Synapse Data Science.

    Captura de tela do menu do seletor de experiência, mostrando onde selecionar Ciência de Dados.

Importar este guia como um bloco de notas

A próxima etapa é adicionar esse código ao cluster do Spark. Você pode criar um bloco de anotações em sua plataforma Spark e copiar o código para este bloco de anotações para executar a demonstração. Ou baixe o notebook e importe-o para o Synapse Analytics

  1. Faça o download desta demonstração como um bloco de anotações (selecione Raw e salve o arquivo)
  2. Importe o bloco de anotações para o espaço de trabalho Synapse ou, se estiver usando o Fabric , importe para o espaço de trabalho de malha
  3. Instale o SynapseML no cluster. Consulte as instruções de instalação do Synapse na parte inferior do site do SynapseML. Se você estiver usando o Fabric, consulte o Guia de Instalação. Para tal, é necessário colar uma célula extra na parte superior do bloco de notas importado.
  4. Conecte seu bloco de anotações a um cluster e acompanhe, editando e executando as células.

Preencha as informações do serviço

Em seguida, edite a célula no bloco de anotações para apontar para o serviço. Em particular, defina as service_namevariáveis , deployment_name, locatione key para correspondê-las ao seu serviço OpenAI:

import os
from pyspark.sql import SparkSession
from synapse.ml.core.platform import running_on_synapse, find_secret

# Bootstrap Spark Session
spark = SparkSession.builder.getOrCreate()

if running_on_synapse():
    from notebookutils.visualization import display

# Fill in the following lines with your service information
# Learn more about selecting which embedding model to choose: https://openai.com/blog/new-and-improved-embedding-model
service_name = "synapseml-openai"
deployment_name = "gpt-35-turbo"
deployment_name_embeddings = "text-embedding-ada-002"

key = find_secret(
    "openai-api-key"
)  # please replace this line with your key as a string

assert key is not None and service_name is not None

Criar um conjunto de dados de prompts

Em seguida, crie um dataframe que consiste em uma série de linhas, com um prompt por linha.

Você também pode carregar dados diretamente do ADLS ou de outros bancos de dados. Para obter mais informações sobre como carregar e preparar dataframes do Spark, consulte o guia de carregamento de dados do Apache Spark.

df = spark.createDataFrame(
    [
        ("Hello my name is",),
        ("The best code is code thats",),
        ("SynapseML is ",),
    ]
).toDF("prompt")

Criar o OpenAICompletion Apache Spark Client

Para aplicar o serviço OpenAI Completion ao seu dataframe que você criou, crie um objeto OpenAICompletion, que serve como um cliente distribuído. Os parâmetros do serviço podem ser definidos com um único valor ou por uma coluna do dataframe com os setters apropriados no OpenAICompletion objeto. Aqui estamos definindo maxTokens para 200. Um token tem cerca de quatro caracteres, e esse limite se aplica à soma do prompt e do resultado. Também estamos definindo o promptCol parâmetro com o nome da coluna de prompt no dataframe.

from synapse.ml.cognitive import OpenAICompletion

completion = (
    OpenAICompletion()
    .setSubscriptionKey(key)
    .setDeploymentName(deployment_name)
    .setCustomServiceName(service_name)
    .setMaxTokens(200)
    .setPromptCol("prompt")
    .setErrorCol("error")
    .setOutputCol("completions")
)

Transforme o dataframe com o OpenAICompletion Client

Depois de concluir o dataframe e o cliente de conclusão, você pode transformar seu conjunto de dados de entrada e adicionar uma coluna chamada completions com todas as informações adicionadas pelo serviço. Selecione apenas o texto para simplificar.

from pyspark.sql.functions import col

completed_df = completion.transform(df).cache()
display(
    completed_df.select(
        col("prompt"),
        col("error"),
        col("completions.choices.text").getItem(0).alias("text"),
    )
)

Sua saída deve ser mais ou menos assim. O texto de conclusão será diferente da amostra.

Prompt erro texto
Olá meu nome é nulo Makaveli Eu tenho dezoito anos e eu quero ser um rapper quando eu crescer Eu amo escrever e fazer música Eu sou de Los Angeles, CA
O melhor código é o código que é nulo compreensível Esta é uma afirmação subjetiva, e não há uma resposta definitiva.
SynapseML é nulo Um algoritmo de aprendizagem automática que é capaz de aprender a prever o resultado futuro dos eventos.

Mais exemplos de uso

Gerando incorporações de texto

Além de completar o texto, também podemos incorporar texto para uso em algoritmos downstream ou arquiteturas de recuperação vetorial. A criação de incorporações permite pesquisar e recuperar documentos de grandes coleções e pode ser usada quando a engenharia imediata não é suficiente para a tarefa. Para obter mais informações sobre como usar OpenAIEmbeddingo , consulte nosso guia de incorporação.

from synapse.ml.cognitive import OpenAIEmbedding

embedding = (
    OpenAIEmbedding()
    .setSubscriptionKey(key)
    .setDeploymentName(deployment_name_embeddings)
    .setCustomServiceName(service_name)
    .setTextCol("prompt")
    .setErrorCol("error")
    .setOutputCol("embeddings")
)

display(embedding.transform(df))

Conclusão do bate-papo

Modelos como ChatGPT e GPT-4 são capazes de entender chats em vez de prompts únicos. O OpenAIChatCompletion transformador expõe esta funcionalidade em escala.

from synapse.ml.cognitive import OpenAIChatCompletion
from pyspark.sql import Row
from pyspark.sql.types import *


def make_message(role, content):
    return Row(role=role, content=content, name=role)


chat_df = spark.createDataFrame(
    [
        (
            [
                make_message(
                    "system", "You are an AI chatbot with red as your favorite color"
                ),
                make_message("user", "Whats your favorite color"),
            ],
        ),
        (
            [
                make_message("system", "You are very excited"),
                make_message("user", "How are you today"),
            ],
        ),
    ]
).toDF("messages")


chat_completion = (
    OpenAIChatCompletion()
    .setSubscriptionKey(key)
    .setDeploymentName(deployment_name)
    .setCustomServiceName(service_name)
    .setMessagesCol("messages")
    .setErrorCol("error")
    .setOutputCol("chat_completions")
)

display(
    chat_completion.transform(chat_df).select(
        "messages", "chat_completions.choices.message.content"
    )
)

Melhore a taxa de transferência com o processamento em lote de solicitações

O exemplo faz várias solicitações ao serviço, uma para cada prompt. Para concluir vários prompts em uma única solicitação, use o modo de lote. Primeiro, no objeto OpenAICompletion, em vez de definir a coluna Prompt como "Prompt", especifique "batchPrompt" para a coluna BatchPrompt. Para fazer isso, crie um dataframe com uma lista de prompts por linha.

No momento em que este artigo foi escrito, há atualmente um limite de 20 prompts em uma única solicitação e um limite rígido de 2048 "tokens", ou aproximadamente 1500 palavras.

batch_df = spark.createDataFrame(
    [
        (["The time has come", "Pleased to", "Today stocks", "Here's to"],),
        (["The only thing", "Ask not what", "Every litter", "I am"],),
    ]
).toDF("batchPrompt")

Em seguida, criamos o objeto OpenAICompletion. Em vez de definir a coluna prompt, defina a coluna batchPrompt se a coluna for do tipo Array[String].

batch_completion = (
    OpenAICompletion()
    .setSubscriptionKey(key)
    .setDeploymentName(deployment_name)
    .setCustomServiceName(service_name)
    .setMaxTokens(200)
    .setBatchPromptCol("batchPrompt")
    .setErrorCol("error")
    .setOutputCol("completions")
)

Na chamada para transformação, será feita uma solicitação por linha. Como há vários prompts em uma única linha, cada solicitação é enviada com todos os prompts nessa linha. Os resultados contêm uma linha para cada linha na solicitação.

completed_batch_df = batch_completion.transform(batch_df).cache()
display(completed_batch_df)

Usando um minibatcher automático

Se seus dados estiverem em formato de coluna, você poderá transpô-los para o formato de linha usando o SynapseML's FixedMiniBatcherTransformer.

from pyspark.sql.types import StringType
from synapse.ml.stages import FixedMiniBatchTransformer
from synapse.ml.core.spark import FluentAPI

completed_autobatch_df = (
    df.coalesce(
        1
    )  # Force a single partition so that our little 4-row dataframe makes a batch of size 4, you can remove this step for large datasets
    .mlTransform(FixedMiniBatchTransformer(batchSize=4))
    .withColumnRenamed("prompt", "batchPrompt")
    .mlTransform(batch_completion)
)

display(completed_autobatch_df)

Engenharia imediata para tradução

O serviço Azure OpenAI pode resolver muitas tarefas diferentes de linguagem natural através de engenharia imediata. Aqui, mostramos um exemplo de solicitação de tradução de idiomas:

translate_df = spark.createDataFrame(
    [
        ("Japanese: Ookina hako \nEnglish: Big box \nJapanese: Midori tako\nEnglish:",),
        (
            "French: Quel heure et il au Montreal? \nEnglish: What time is it in Montreal? \nFrench: Ou est le poulet? \nEnglish:",
        ),
    ]
).toDF("prompt")

display(completion.transform(translate_df))

Solicitar resposta a perguntas

Aqui, solicitamos ao GPT-3 a resposta a perguntas de conhecimentos gerais:

qa_df = spark.createDataFrame(
    [
        (
            "Q: Where is the Grand Canyon?\nA: The Grand Canyon is in Arizona.\n\nQ: What is the weight of the Burj Khalifa in kilograms?\nA:",
        )
    ]
).toDF("prompt")

display(completion.transform(qa_df))