Leggere in inglese

Condividi tramite


Azure OpenAI per Big Data

Il servizio Azure OpenAI può essere usato per svolgere un numero elevato di attività in linguaggio naturale tramite prompting dell'API di completamento. Per semplificare la scalabilità dei flussi di lavoro di prompting richiesta da alcuni esempi a set di dati di grandi dimensioni, è stato integrato il servizio OpenAI di Azure con la libreria di Machine Learning distribuita SynapseML. Questa integrazione semplifica l'uso del framework di calcolo distribuito Apache Spark per elaborare milioni di richieste con il servizio OpenAI. L'esercitazione illustra come applicare modelli linguistici di grandi dimensioni su scala distribuita usando Azure OpenAI e Azure Synapse Analytics.

Prerequisiti

I prerequisiti principali per questa guida introduttiva includono una risorsa OpenAI di Azure funzionante e un cluster Apache Spark con SynapseML installato.

Importare questa guida come notebook

Il passaggio successivo consiste nell'aggiungere questo codice al cluster Spark. È possibile creare un notebook nella piattaforma Spark e copiare il codice in questo notebook per eseguire la demo. Oppure scaricare il notebook e importarlo in Synapse Analytics

  1. Scaricare questa demo come notebook, (selezionare Raw e poi salvare il file)
  2. Importare il notebook nell'area di lavoro di Synapse o, se si usa Fabric, importarlo nell'area di lavoro di Fabric
  3. Installare SynapseML nel cluster. Vedere le istruzioni di installazione per Synapse nella parte inferiore del sito Web SynapseML. Se si usa Fabric, vedere Guida all'installazione. Ciò richiede di incollare un'altra cella nella parte superiore del notebook importato
  4. Connettere il notebook a un cluster e attenersi alla procedura di modifica e di esecuzione delle celle.

Inserire le informazioni sul servizio

Modificare quindi la cella nel notebook in modo che punti al servizio. In particolare, impostare le variabili service_name, deployment_name, location, e key in modo che corrispondano al servizio 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

Crea un set di dati di prompt

Creare quindi un dataframe costituito da una serie di righe, con un prompt per riga.

È anche possibile caricare i dati direttamente da ADLS o da altri database. Per ulteriori informazioni sul caricamento e la preparazione dei dataframe Spark, vedere la Guida al caricamento dei dati di Apache Spark.

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

Creare il client Apache Spark per il completamento di OpenAI

Per applicare il servizio di completamento di OpenAI al dataframe appena creato, creare un oggetto OpenAICompletion che funge da client distribuito. I parametri del servizio possono essere impostati con un singolo valore o da una colonna del dataframe con i setter appropriati nell'oggetto OpenAICompletion. In questo caso, si imposta maxTokens su 200. Un token è intorno a quattro caratteri e questo limite si applica alla somma della richiesta e del risultato. Si imposta anche il parametro promptCol con il nome della colonna del prompt nel 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")
)

Trasformare il dataframe con il client di completamento di OpenAI

Dopo il completamento del dataframe e del client, è possibile trasformare il set di dati di input e aggiungere una colonna denominata completions con tutte le informazioni aggiunte dal servizio. Selezionare solo il testo per semplicità.

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"),
    )
)

L'output dovrebbe risultare simile a quanto segue. Il testo di completamento sarà diverso dall'esempio.

prompt error Testo
Ciao, mi chiamo Null Makaveli ho diciotto anni e voglio essere un rapper; mi è sempre piaciuto scrivere e fare musica; sono di Los Angeles, CA
Il codice migliore è il codice che sia Null comprensibile. Questa è una dichiarazione soggettiva, e non c'è una risposta definitiva.
SynapseML è Null Un algoritmo di Machine Learning in grado di apprendere come stimare il risultato futuro degli eventi.

Altri esempi di utilizzo

Generazione di incorporamenti di testo

Oltre a completare il testo, è anche possibile incorporare testo da usare negli algoritmi downstream o nelle architetture di recupero vettoriale. La creazione di incorporamenti consente di cercare e recuperare documenti da raccolte di grandi dimensioni e può essere usata quando la progettazione dei prompt non è sufficiente per l'attività. Per altre informazioni sull'uso di OpenAIEmbedding, vedere la guida all'incorporamento.

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))

Completamento chat

I modelli come ChatGPT e GPT-4 sono in grado di comprendere le chat anziché le singole richieste. Il trasformatore OpenAIChatCompletion espone questa funzionalità su larga scala.

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"
    )
)

Migliorare la velocità effettiva con l'invio in batch delle richieste

Nell'esempio vengono eseguite diverse richieste al servizio, una per ogni prompt. Per completare più prompt in una singola richiesta, usare la modalità in batch. Innanzitutto, nell'oggetto OpenAICompletion, anziché impostare la colonna Prompt su "Prompt", specificare "batchPrompt" per la colonna BatchPrompt. A tale scopo, creare un dataframe con un elenco di prompt per riga.

Al momento è previsto un limite di 20 prompt in una singola richiesta e un limite di 2048 token o di circa 1500 parole.

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")

Verrà quindi creato l'oggetto OpenAICompletion. Anziché impostare la colonna dei prompt, impostare la colonna batchPrompt se la colonna è di tipo Array[String].

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

Nella chiamata alla trasformazione verrà effettuata una richiesta per ogni riga. Da quando sono presenti più richieste in una singola riga, ogni richiesta viene inviata con tutte le richieste in tale riga. I risultati contengono una riga per ogni riga nella richiesta.

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

Uso di un mini strumento di creazione di batch automatico

Se i dati sono in formato colonna, è possibile trasporli in formato riga usando FixedMiniBatcherTransformer di SynapseML.

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)

Progettazione di prompt per la traduzione

Il servizio Azure OpenAI può svolgere diverse attività in linguaggio naturale tramite progettazione prompt. Di seguito viene illustrato un esempio di richiesta di traduzione di una lingua:

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))

Prompt per risposte alle domande

In questo caso, viene richiesto GPT-3 per la risposta alle domande generali:

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))