Freigeben über


Entwickeln Sie Reasoning-Apps mit DeepSeek-Modellen in der Azure AI Foundry mithilfe des OpenAI SDKs.

Erfahren Sie, wie Sie Reasoning-Modelle wie DeepSeek in Azure OpenAI mit dem OpenAI SDK für Python verwenden.

In diesem Artikel werden mehrere bewährte Methoden für die Integration von Begründungsmodellen gezeigt:

  • Schlüssellose Authentifizierung: Verwenden Sie verwaltete Identitäten oder Entwickleranmeldeinformationen anstelle von API-Schlüsseln.
  • Asynchrone Vorgänge: Verwenden Sie asynchrone Features, um eine bessere Leistung zu erzielen.
  • Streamen von Antworten: Geben Sie Benutzern sofortiges Feedback.
  • Trennung von Begründungsschritten: Trennen Sie die Gründe für die Begründungsschritte von der endgültigen Ausgabe.
  • Ressourcenverwaltung: Bereinigen Sie Ressourcen nach der Verwendung.

Der DeepSeek-Baustein

Erkunden Sie das DeepSeek-Bausteinbeispiel . Es zeigt, wie Sie die OpenAI-Clientbibliothek verwenden, um das DeepSeek-R1-Modell aufzurufen und Antworten auf Benutzernachrichten zu generieren.

Architekturübersicht

Das folgende Diagramm zeigt die einfache Architektur der Beispiel-App: Diagramm mit Architektur von Client zu Back-End-App.

Die Chat-App wird als Azure-Container App ausgeführt. Die App verwendet verwaltete Identität mit Microsoft Entra ID, um sich mit Azure OpenAI anstelle eines API-Schlüssels zu authentifizieren. Die App verwendet Azure OpenAI, um Antworten auf Benutzernachrichten zu generieren.

Die App basiert auf diesen Diensten und Komponenten:

  • Eine Python Quart-App , die das OpenAI-Clientbibliothekspaket verwendet, um Antworten auf Benutzernachrichten zu generieren
  • Ein einfaches HTML/JS-Frontend, das Antworten aus dem Back-End mithilfe von JSON-Zeilen über einen ReadableStream streamt
  • Bicep-Dateien für die Bereitstellung von Azure-Ressourcen, einschließlich Azure AI Services, Azure Container Apps, Azure Container Registry, Azure Log Analytics und RBAC-Rollen.

Kosten

Um die Kosten niedrig zu halten, verwendet dieses Beispiel grundlegende preisniveaus oder Verbrauchsniveaus für die meisten Ressourcen. Passen Sie die Ebene nach Bedarf an, und löschen Sie Ressourcen, wenn Sie damit fertig sind, um Gebühren zu vermeiden.

Weitere Informationen zu den Kosten im Beispielrepository finden Sie hier.

Voraussetzungen

Ein Entwicklungscontainer enthält alle Abhängigkeiten, die Sie für diesen Artikel benötigen. Sie können es in GitHub Codespaces (in einem Browser) oder lokal mit Visual Studio Code ausführen.

Um diesem Artikel zu folgen, stellen Sie sicher, dass Sie diese Voraussetzungen erfüllen:

Offene Entwicklungsumgebung

Führen Sie die folgenden Schritte aus, um eine vorkonfigurierte Entwicklungsumgebung mit allen erforderlichen Abhängigkeiten einzurichten.

GitHub Codespaces führt einen Entwicklungscontainer aus, der von GitHub mit Visual Studio Code für das Web als Schnittstelle verwaltet wird. Verwenden Sie GitHub Codespaces für die einfachste Einrichtung, da sie mit den für diesen Artikel vorinstallierten erforderlichen Tools und Abhängigkeiten enthalten ist.

Von Bedeutung

Alle GitHub-Konten können Codespaces für bis zu 60 Stunden kostenlos jeden Monat mit zwei Kerninstanzen verwenden. Weitere Informationen finden Sie unter monatlich inbegriffene Speicher- und Kernstunden für GitHub Codespaces.

Gehen Sie wie folgt vor, um einen neuen GitHub Codespace auf dem main Branch des Azure-Samples/deepseek-python GitHub-Repositorys zu erstellen.

  1. Klicken Sie mit der rechten Maustaste auf die folgende Schaltfläche, und wählen Sie im neuen Fenster "Link öffnen" aus. Mit dieser Aktion können Sie die Entwicklungsumgebung und die Dokumentation nebeneinander öffnen.

    In GitHub Codespaces öffnen

  2. Überprüfen Sie auf der Seite Codespace erstellen die Informationen und wählen Sie dann Neuen Codespace erstellen.

  3. Warten Sie, bis der Codespace gestartet wird. Dies kann einige Minuten dauern.

  4. Melden Sie sich mit der Azure Developer CLI bei Azure am Terminal am unteren Bildschirmrand an.

    azd auth login
    
  5. Kopieren Sie den Code vom Terminal, und fügen Sie ihn dann in einen Browser ein. Befolgen Sie die Anweisungen zum Authentifizieren mit Ihrem Azure-Konto.

Sie führen die restlichen Aufgaben in diesem Entwicklungscontainer aus.

Implementieren und Ausführen

Das Beispiel-Repository enthält alle Code- und Konfigurationsdateien, die Sie zum Bereitstellen der Chat-App in Azure benötigen. Führen Sie die folgenden Schritte aus, um die Chat-App in Azure bereitzustellen.

Bereitstellen einer Chat-App in Azure

Von Bedeutung

Azure-Ressourcen, die in diesem Abschnitt erstellt wurden, beginnen sofort mit dem Kostenaufwand. Diese Ressourcen verursachen möglicherweise weiterhin Kosten, auch wenn Sie den Befehl beenden, bevor er abgeschlossen ist.

  1. Führen Sie den folgenden Azure Developer CLI-Befehl für die Bereitstellung von Azure-Ressourcen und die Quellcodebereitstellung aus:

    azd up
    
  2. Gehen Sie zum Beantworten der Eingabeaufforderungen gemäß der folgenden Tabelle vor:

    Prompt Antwort
    Umgebungsname Halten Sie sie kurz und klein geschrieben. Fügen Sie Ihren Namen oder Alias hinzu. Beispiel: chat-app. Es wird als Teil des Namens der Ressourcengruppe verwendet.
    Abonnement Wählen Sie das Abonnement aus, in dem die Ressourcen erstellt werden sollen.
    Standort (für Hosting) Wählen Sie einen Speicherort in ihrer Nähe aus der Liste aus.
    Standort für das DeepSeek-Modell Wählen Sie einen Speicherort in ihrer Nähe aus der Liste aus. Wenn derselbe Speicherort wie Ihr erster Speicherort verfügbar ist, wählen Sie diesen Speicherort aus.
  3. Warten Sie, bis die App bereitgestellt wird. Die Bereitstellung dauert in der Regel 5 bis 10 Minuten.

Verwenden der Chat-App zum Stellen von Fragen zum großen Sprachmodell

  1. Nach der Bereitstellung zeigt das Terminal eine URL an.

  2. Wählen Sie die URL aus, die beschriftet ist Deploying service web , um die Chat-App in Ihrem Browser zu öffnen.

    Screenshot der Chat-App im Browser mit einer Frage im Chattextfeld zusammen mit der Antwort.

  3. Stellen Sie im Browser eine Frage zu dem hochgeladenen Bild wie "Wer malte die Mona Lisa?"

  4. Azure OpenAI bietet die Antwort über modellische Rückschlüsse und das Ergebnis wird in der App angezeigt.

Untersuchen des Beispielcodes

OpenAI- und Azure OpenAI-Dienst verwenden beide die allgemeine Python-Clientbibliothek, aber Sie müssen einige kleine Codeänderungen für Azure OpenAI-Endpunkte vornehmen. In diesem Beispiel wird ein DeepSeek-R1 Reasoning-Modell verwendet, um Antworten in einer einfachen Chat-App zu generieren.

Einrichten und Authentifizierung

Die src\quartapp\chat.py Datei beginnt mit dem Einrichten und Konfigurieren der schlüssellosen Authentifizierung.

Infrastrukturaufbau

Das Skript verwendet Quart, ein asynchrones Webframework, um ein Blueprint mit dem Namen chat zu erstellen. Diese Blueprint definiert die Routen der App und verwaltet deren Lebenszyklus-Hooks.

bp = Blueprint("chat", __name__, template_folder="templates", static_folder="static")

Blueprint definiert die Routen / und /chat/stream und die Lebenszyklus-Hooks @bp.before_app_serving und @bp.after_app_serving.

Initialisierung mit schlüsselloser Authentifizierung

Der folgende Codeausschnitt behandelt die Authentifizierung.

Hinweis

Der @bp.before_app_serving Hook initialisiert den OpenAI-Client und verarbeitet die Authentifizierung. Dieser Ansatz ist entscheidend für den sicheren Zugriff auf von Azure gehostete DeepSeek-R1-Modelle.

Die Authentifizierungsstrategie passt sich an die Umgebung an:

  • In der Produktion: Verwendet verwaltete Identitätsanmeldeinformationen mit einer Azure-Client-ID, um vertrauliche Schlüssel zu vermeiden. Diese Methode ist sicher und skalierbar für cloudeigene Apps.
  • In der Entwicklung: Verwendet Azure Developer CLI-Anmeldeinformationen mit einer Azure-Mandanten-ID, um lokale Tests mithilfe der Azure CLI-Anmeldesitzung des Entwicklers zu vereinfachen.
@bp.before_app_serving
async def configure_openai():
    if os.getenv("RUNNING_IN_PRODUCTION"):
        client_id = os.environ["AZURE_CLIENT_ID"]
        bp.azure_credential = ManagedIdentityCredential(client_id=client_id)
    else:
        tenant_id = os.environ["AZURE_TENANT_ID"]
        bp.azure_credential = AzureDeveloperCliCredential(tenant_id=tenant_id)

Dieser schlüssellose Authentifizierungsansatz bietet Folgendes:

  • Bessere Sicherheit: Keine API-Schlüssel, die in Code- oder Umgebungsvariablen gespeichert sind.
  • Einfachere Verwaltung: Sie müssen keine Schlüssel drehen oder geheime Schlüssel verwalten.
  • Reibungslose Übergänge: Derselbe Code funktioniert sowohl in der Entwicklung als auch in der Produktion.

Einrichten des Tokenanbieters

Im folgenden Codeausschnitt erstellt der Tokenanbieter ein Bearertoken zum Authentifizieren von Anforderungen an Azure OpenAI-Dienste. Sie generiert und aktualisiert diese Token automatisch mithilfe der konfigurierten Anmeldeinformationen.

bp.openai_token_provider = get_bearer_token_provider(
    bp.azure_credential, "https://cognitiveservices.azure.com/.default"
)

Azure OpenAI-Clientkonfiguration

Es gibt zwei mögliche Clients, AzureOpenAI und AsyncAzureOpenAI. Der folgende Codeausschnitt verwendet AsyncAzureOpenAI zusammen mit dem asynchronen Quart-Framework für eine bessere Leistung mit gleichzeitigen Benutzern:

bp.openai_client = AsyncAzureOpenAI(
    azure_endpoint=os.environ["AZURE_INFERENCE_ENDPOINT"],
    azure_ad_token_provider=openai_token_provider,
    api_version="2024-10-21",
  • base_url: Verweist auf den von Azure gehosteten Inferenz-Endpunkt DeepSeek
  • api_key: Verwendet einen dynamisch generierten API-Schlüssel vom Tokenanbieter.
  • api-version: Gibt die API-Version an, die DeepSeek-Modelle unterstützt

Namenskonfiguration für die Modellimplementierung

Der folgende Codeausschnitt legt die DeepSeek-Modellversion fest, indem der Bereitstellungsname aus Ihrer Umgebungskonfiguration abgerufen wird. Er weist der bp.model_deployment_name Variablen den Namen zu, sodass er in der gesamten App zugänglich ist. Mit diesem Ansatz können Sie die Modellbereitstellung ändern, ohne den Code zu aktualisieren.

bp.model_deployment_name = os.getenv("AZURE_DEEPSEEK_DEPLOYMENT")

Hinweis

In Azure OpenAI verwenden Sie keine Modellnamen wie gpt-4o oder deepseek-r1. Stattdessen erstellen Sie Bereitstellungen, das sind benannte Instanzen von Modellen in Ihrer Azure OpenAI-Ressource. Dieser Ansatz bietet die folgenden Vorteile:

  • Abstraktion: Schließt Bereitstellungsnamen mithilfe von Umgebungsvariablen aus dem Code aus.
  • Flexibilität: Ermöglicht es Ihnen, zwischen verschiedenen DeepSeek-Bereitstellungen zu wechseln, ohne den Code zu ändern.
  • Umgebungsspezifische Konfiguration: Ermöglicht die Verwendung verschiedener Bereitstellungen für Entwicklung, Tests und Produktion.
  • Ressourcenverwaltung: Jede Azure-Bereitstellung verfügt über ein eigenes Kontingent, eine Einschränkung und Überwachung.

Lebenszyklusverwaltung

Der folgende Codeausschnitt verhindert Ressourcenlecks, indem der asynchrone Azure OpenAI-Client geschlossen wird, wenn die Anwendung heruntergefahren wird. Der @bp.after_app_serving- Hook sorgt für eine ordnungsgemäße Bereinigung von Ressourcen.

@bp.after_app_serving
async def shutdown_openai():
    await bp.openai_client.close()

Streamingfunktion für Chathandler

Die chat_handler() Funktion verwaltet Benutzerinteraktionen mit dem DeepSeek-R1 Modell über die chat/stream Route. Er streamt Antworten in Echtzeit zurück an den Client und verarbeitet sie. Die Funktion extrahiert Nachrichten aus der JSON-Nutzlast.

Streamingimplementierung

  1. Die response_stream Funktion beginnt mit der Annahme von Nachrichten vom Client.

    • request_messages: Die Route erwartet eine JSON-Nutzlast, die Benutzernachrichten enthält.
    @bp.post("/chat/stream")
    async def chat_handler():
       request_messages = (await request.get_json())["messages"]
    
  2. Als Nächstes streamt die Funktion Antworten aus der OpenAI-API. Es kombiniert Systemnachrichten wie "Sie sind ein hilfreicher Assistent" mit vom Benutzer bereitgestellten Nachrichten.

    @stream_with_context
    async def response_stream():
        all_messages = [
            {"role": "system", "content": "You are a helpful assistant."},
        ] + request_messages
    
  3. Als Nächstes erstellt die Funktion eine Abschlussanforderung für Streaming-Chats.

    Die chat.completions.create Methode sendet die Nachrichten an das DeepSeek-R1 Modell. Der stream=True Parameter ermöglicht das Streaming von Echtzeitantworten.

      chat_coroutine = bp.openai_client.chat.completions.create(
          model=bp.openai_model,
          messages=all_messages,
          stream=True,
      )
    
  4. Der folgende Codeausschnitt verarbeitet Streamingantworten aus dem DeepSeek-R1 Modell und behandelt Fehler. Es durchläuft Updates, sucht nach gültigen Auswahlmöglichkeiten und sendet jeden Antwortabschnitt als JSON-Zeilen. Wenn ein Fehler auftritt, protokolliert er den Fehler und sendet eine JSON-Fehlermeldung an den Client, während der Datenstrom fortgesetzt wird.

    try:
        async for update in await chat_coroutine:
            if update.choices:
                yield update.choices[0].model_dump_json() + "\n"
        except Exception as e:
            current_app.logger.error(e)
            yield json.dumps({"error": str(e)}, ensure_ascii=False) + "\n"
    
    return Response(response_stream())
    

Handhabung des Begründungsinhalts

Während herkömmliche Sprachmodelle nur endgültige Ausgaben bereitstellen, zeigen Begründungsmodelle ihre DeepSeek-R1 zwischengeschalteten Begründungsschritte an. Diese Schritte machen sie nützlich für:

  • Lösen komplexer Probleme
  • Ausführen mathematischer Berechnungen
  • Handhabung der mehrteiligen logischen Begründung
  • Transparente Entscheidungen treffen

Der submit-Ereignishandler in index.html verarbeitet im Frontend die Streamingantwort. Mit diesem Ansatz können Sie auf die Denkschritte des Modells zugreifen und diese zusammen mit der endgültigen Ausgabe anzeigen.

Das Frontend verwendet eine ReadableStream zum Verarbeiten von Streaming-Antworten aus dem Backend. Sie trennt die Begründung von regulären Inhalten, zeigt die Begründung in einem erweiterbaren Abschnitt und die endgültige Antwort im Hauptchatbereich an.

Schrittweise Aufschlüsselung

  1. Initiieren der Streaminganforderung

    Dieser Codeausschnitt erstellt eine Verbindung zwischen dem JavaScript-Frontend und dem Python-Back-End, wodurch die Azure OpenAI-Integration von DeepSeek-R1 mit schlüsselloser Authentifizierung ermöglicht wird.

    const response = await fetch("/chat/stream", {
        method: "POST",
        headers: {"Content-Type": "application/json"},
        body: JSON.stringify({messages: messages})
    });
    
  2. Initialisieren der Variablen

    Der folgende Codeausschnitt initialisiert Variablen, um die Antwort und Gedanken separat zu speichern. Diese Trennung hilft bei der effektiven Behandlung von Argumentationsinhalten.

    let answer = "";
    let thoughts = "";    
    
  3. Bearbeite jedes Update

    Der folgende Codeausschnitt durchläuft asynchron Blöcke der Antwort des Modells.

    for await (const event of readNDJSONStream(response.body)) {
    
  4. Erkennen und Weiterleiten des Inhaltstyps

    Das Skript überprüft, ob das Ereignis ein delta Feld enthält. Wenn dies der Fall ist, verarbeitet er den Inhalt je nachdem, ob es sich um Argumentationsinhalt oder regulären Inhalt handelt.

    if (!event.delta) {
         continue;
    }
    if (event.delta.reasoning_content) {
         thoughts += event.delta.reasoning_content;
         if (thoughts.trim().length > 0) {
             // Only show thoughts if they are more than just whitespace
             messageDiv.querySelector(".loading-bar").style.display = "none";
             messageDiv.querySelector(".thoughts").style.display = "block";
             messageDiv.querySelector(".thoughts-content").innerHTML = converter.makeHtml(thoughts);
         }
     } else if (event.delta.content) {
         messageDiv.querySelector(".loading-bar").style.display = "none";
         answer += event.delta.content;
         messageDiv.querySelector(".answer-content").innerHTML = converter.makeHtml(answer);
     }
    
    • Wenn der Inhaltstyp reasoning_content ist, wird der Inhalt zu thoughts hinzugefügt und im .thoughts-content Abschnitt angezeigt.
    • Wenn der Inhaltstyp content ist, wird der Inhalt zu answer hinzugefügt und im .answer-content Abschnitt angezeigt.
    • Das .loading-bar wird ausgeblendet, sobald der Inhalt gestreamt wird, und der .thoughts Abschnitt wird angezeigt, wenn Gedanken vorhanden sind.
  5. Fehlerbehandlung:

    Fehler werden im Back-End protokolliert und im JSON-Format an den Client zurückgegeben.

    except Exception as e:
        current_app.logger.error(e)
        yield json.dumps({"error": str(e)}, ensure_ascii=False) + "\n"
    

    Dieser Frontend-Codeausschnitt zeigt die Fehlermeldung in der Chatoberfläche an.

    messageDiv.scrollIntoView();
    if (event.error) {
        messageDiv.innerHTML = "Error: " + event.error;
    }
    

Aufräumen von GitHub-Codespaces

Löschen Sie die GitHub Codespaces-Umgebung, um Ihre kostenlosen Stunden pro Kern zu maximieren.

Von Bedeutung

Weitere Informationen zu den kostenlosen Speicher- und Kernstunden Ihres GitHub-Kontos finden Sie unter GitHub Codespaces monatlich enthaltene Speicher- und Kernstunden.

  1. Melden Sie sich beim GitHub Codespaces-Dashboardan.

  2. Suchen Sie Ihre aktiven Codespaces, die aus dem Azure-Samples//deepseek-python GitHub-Repository erstellt wurden.

  3. Öffnen Sie das Kontextmenü für den Codespace und wählen Sie Löschenaus.

Hier erhalten Sie Hilfe

Protokollieren Sie Ihr Problem mit den Problemen des Repositorys.

Nächste Schritte