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.
I prerequisiti principali per questa guida introduttiva includono una risorsa OpenAI di Azure funzionante e un cluster Apache Spark con SynapseML installato.
Ottenere una sottoscrizione di Microsoft Fabric. In alternativa, iscriversi per ottenere una versione di valutazione di Microsoft Fabric gratuita.
Accedere a Microsoft Fabric.
Usare l’opzione esperienza sul lato sinistro della home page per passare all'esperienza Science di Synapse.
- Passare all'esperienza di data science in Microsoft Fabric.
- Creare un nuovo notebook.
- Una risorsa OpenAI di Azure: richiedere l'accesso al servizio OpenAI di Azure prima di creare una risorsa
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
- Scaricare questa demo come notebook, (selezionare Raw e poi salvare il file)
- Importare il notebook nell'area di lavoro di Synapse o, se si usa Fabric, importarlo nell'area di lavoro di Fabric
- 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
- Connettere il notebook a un cluster e attenersi alla procedura di modifica e di esecuzione delle celle.
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
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")
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")
)
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. |
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))
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"
)
)
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)
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)
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))
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))