Freigeben über


Azure OpenAI für Big Data

Der Azure OpenAI-Dienst kann verwendet werden, um eine große Anzahl von natürlichsprachlichen Aufgaben durch Auffordern der Abschluss-API zu lösen. Damit Sie Ihre Äußerungsworkflows von einigen Beispielen auf große Beispieldatasets skalieren können, haben wir die verteilte Machine Learning-Bibliothek SynapseML in den Azure OpenAI-Dienst integriert. Durch diese Integration kann das Apache Spark-Framework für verteiltes Computing komfortabel verwendet werden, um Millionen von Äußerungen mit dem OpenAI-Dienst zu verarbeiten. In diesem Tutorial wird gezeigt, wie große Sprachmodelle im verteilten Maßstab mithilfe von Azure OpenAI und Azure Synapse Analytics angewendet werden.

Voraussetzungen

Zu den wichtigsten Voraussetzungen für diesen Schnellstart gehören eine funktionierende Azure OpenAI-Ressource und ein Apache Spark-Cluster mit einer SynapseML-Installation.

Diese Anleitung als Notebook importieren

Der nächste Schritt besteht darin, Ihrem Spark-Cluster diesen Code hinzuzufügen. Zum Ausführen der Demo können Sie ein Notebook auf Ihrer Spark-Plattform erstellen und den Code in dieses Notebook kopieren. Alternativ können Sie das Notebook herunterladen und es in Synapse Analytics importieren.

  1. Laden Sie diese Demo als Notebook herunter (klicken Sie auf Raw, und speichern Sie dann die Datei).
  2. Importieren Sie das Notebook in den Synapse-Arbeitsbereich oder, wenn Sie Fabric verwenden, in den Fabric-Arbeitsbereich.
  3. Installieren Sie SynapseML auf Ihrem Cluster. Mehr dazu finden Sie in den Installationsanweisungen für Synapse unten auf der SynapseML-Website. Wenn Sie Fabric verwenden, lesen Sie die Installationsanleitung. Dafür ist es erforderlich, oben in Ihrem importierten Notebook eine zusätzliche Zeile einzufügen.
  4. Verbinden Sie Ihr Notebook mit einem Cluster, und fahren Sie begleitend mit dem Bearbeiten und Ausführen der Zellen fort.

Ausfüllen der Dienstinformationen

Bearbeiten Sie als Nächstes die Zelle im Notebook, die auf Ihren Dienst verweisen soll. Legen Sie insbesondere die Variablen service_name, deployment_name, location und key auf die Werte für Ihren OpenAI-Dienst fest:

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

Erstellen eines Datasets mit Äußerungen

Erstellen Sie als Nächstes ein Datenframe, das aus einer Reihe von Zeilen besteht, mit einer Äußerung pro Zeile.

Sie können Daten auch direkt aus ADLS oder anderen Datenbanken laden. Weitere Informationen zum Laden und Vorbereiten von Spark-Datenframes finden Sie im Apache Spark-Datenladehandbuch.

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

Erstellen des OpenAICompletion Apache Spark-Clients

Damit Sie den OpenAI Completion-Dienst auf den erstellten Dataframe anwenden können, erstellen Sie ein OpenAICompletion-Objekt, das als verteilter Client fungiert. Die Parameter des Diensts können entweder mit einem einzelnen Wert oder durch eine Spalte des Datenframes mit den entsprechenden Settern für das OpenAICompletion-Objekt festgelegt werden. Hier legen wir maxTokens auf 200 fest. Ein Token weist um die vier Zeichen auf, und dieser Grenzwert gilt für die Summe der Äußerung und das Ergebnis. Wir legen außerdem den promptCol-Parameter auf den Namen der Äußerungsspalte im Datenframe fest.

from synapse.ml.cognitive import OpenAICompletion

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

Transformieren des Datenframes mit dem OpenAICompletion-Client

Nachdem Sie über den Datenframe und den Abschlussclient verfügen, können Sie Ihr Eingabedatenset transformieren und eine Spalte completions hinzufügen, die alle vom Dienst hinzugefügten Informationen enthält. Aus Gründen der Einfachheit wählen wir nur den Text aus.

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

Die Ausgabe sollte etwa wie folgt aussehen. Der Abschlusstext unterscheidet sich vom Beispiel.

prompt error text
Hallo, mein Name ist NULL Makaveli. Ich bin achtzehn Jahre alt und möchte Rapper werden, wenn ich groß bin. Ich liebe es, zu schreiben und Musik zu machen. Ich bin aus Los Angeles, Kalifornien.
Der beste Code ist Code, der NULL verständlich ist. Das ist eine subjektive Aussage, und es gibt keine endgültige Antwort.
SynapseML ist NULL ein Algorithmus für maschinelles Lernen, der imstande ist, das Vorhersagen des zukünftigen Ergebnisses von Ereignissen zu lernen.

Weitere Anwendungsbeispiele

Generieren von Texteinbettungen

Zusätzlich zum Vervollständigen von Text können Sie auch Text für die Verwendung in Downstreamalgorithmen oder Vektorabrufarchitekturen einbetten. Das Erstellen von Einbettungen ermöglicht das Suchen und Abrufen von Dokumenten aus großen Sammlungen und kann verwendet werden, wenn das Prompt Engineering für die Aufgabe nicht ausreicht. Weitere Informationen zur Verwendung von OpenAIEmbedding finden Sie in unserem Einbettungsleitfaden.

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

Chatvervollständigung

Modelle wie ChatGPT und GPT-4 sind in der Lage, Chats anstelle einzelner Prompts zu verstehen. Der Transformer OpenAIChatCompletion macht diese Funktionalität im großen Stil verfügbar.

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

Verbessern des Durchsatzes durch Batchverarbeitung von Anforderungen

Im Beispiel werden mehrere Anforderungen an den Dienst ausgeführt, eine für jeden Prompt. Wenn Sie mehrere Äußerungen in einer einzelnen Anforderungen abschließen möchten, verwenden Sie den Batchmodus. Anstatt die Spalte „Prompt“ im OpenAICompletion-Objekt auf „Prompt“ festzulegen, geben Sie zunächst „batchPrompt“ für die Spalte „BatchPrompt“ an. Erstellen Sie dazu ein Datenframe mit einer Liste von Äußerungen pro Zeile.

Es gibt derzeit ein Limit von 20 Prompts pro Anforderung und ein festes Limit von 2048 Token oder ungefähr 1500 Wörtern.

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

Als Nächstes erstellen wir das OpenAICompletion-Objekt. Anstatt die Äußerungsspalte festzulegen, legen Sie die batchPrompt-Spalte fest, wenn Ihre Spalte vom Typ Array[String] ist.

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

Anschließend wird in dem zu transformierenden Aufruf eine Anforderung pro Zeile getätigt. Da eine einzelne Zeile mehrere Prompts enthält, wird jede Anforderung mit allen Prompts gesendet, die die Zeile enthält. Die Ergebnisse enthalten eine Zeile für jede Zeile in der Anforderung.

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

Verwenden eines automatischen Minibatchers

Wenn Ihre Daten im Spaltenformat vorliegen, können Sie sie mithilfe des FixedMiniBatcherTransformer von SynapseML in das Zeilenformat übersetzen.

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)

Prompt Engineering zur Übersetzung

Der Azure OpenAI-Dienst kann viele verschiedene natürlichsprachliche Aufgaben mithilfe von Prompt Engineering lösen. Hier zeigen wir ein Beispiel für die Aufforderung zur Sprachübersetzung:

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

Aufforderung zur Beantwortung von Fragen

Hier fordern wir GPT-3 zur Beantwortung allgemeiner Fragen auf:

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