Human-in-the-Loop-Workflow mit Callbacks erstellen

In dieser Anleitung erfahren Sie, wie Sie einen Übersetzungsworkflow erstellen, der auf Sie – den Human in the Loop – und Ihre Eingabe wartet, und der eine Firestore-Datenbank, zwei Cloud Run-Funktionen, die Cloud Translation API und eine Webseite verbindet, die das Firebase SDK nutzt, um in Echtzeit eine Aktualisierung durchzuführen.

Mit Workflows können Sie einen Callback-Endpunkt (oder Webhook) unterstützen, der darauf wartet, dass HTTP-Anfragen an diesem Endpunkt ankommen, und die Ausführung des Workflows zu einem späteren Zeitpunkt fortsetzt. In diesem Fall wartet der Workflow auf die Ablehnung oder Validierung der Übersetzung eines Textes, aber es könnte auch ein externer Prozess sein. Weitere Informationen finden Sie unter Mit Callbacks warten.

Architektur

In dieser Anleitung wird eine Webanwendung erstellt, die Folgendes ermöglicht:

  1. Geben Sie auf der Übersetzungswebseite den Text ein, der vom Englischen ins Französische übersetzt werden soll. Klicken Sie auf Übersetzen.
  2. Über die Webseite wird eine Cloud Run-Funktion aufgerufen, die die Ausführung des Workflows startet. Der zu übersetzende Text wird als Parameter sowohl an die Funktion als auch an den Workflow übergeben.
  3. Der Text wird in einer Cloud Firestore-Datenbank gespeichert. Cloud Translation API wird aufgerufen. Die zurückgegebene Übersetzung wird in der Datenbank gespeichert. Die Webanwendung wird mit Firebase Hosting bereitgestellt und in Echtzeit aktualisiert, um den übersetzten Text anzuzeigen.
  4. Im Schritt create_callback des Workflows wird eine Callback-Endpunkt-URL erstellt, die auch in der Firestore-Datenbank gespeichert wird. Auf der Webseite werden jetzt sowohl die Schaltfläche Validieren als auch die Schaltfläche Ablehnen angezeigt.
  5. Der Workflow wird jetzt pausiert und wartet auf eine explizite HTTP-POST-Anfrage an die Callback-Endpunkt-URL.
  6. Sie können entscheiden, ob Sie die Übersetzung validieren oder ablehnen möchten. Durch Klicken auf eine Schaltfläche wird eine zweite Cloud Run-Funktion aufgerufen, die wiederum den vom Workflow erstellten Callback-Endpunkt aufruft und den Genehmigungsstatus übergibt. Der Workflow wird fortgesetzt und speichert den Genehmigungsstatus true oder false in der Firestore-Datenbank.

Dieses Diagramm bietet einen Überblick über den Prozess:

Workflow mit Callback

Erste Cloud Run-Funktion bereitstellen

Diese Cloud Run-Funktion startet die Ausführung des Workflows. Der zu übersetzende Text wird als Parameter sowohl an die Funktion als auch an den Workflow übergeben.

  1. Erstellen Sie ein Verzeichnis namens callback-translation mit den Unterverzeichnissen invokeTranslationWorkflow, translationCallbackCall und public:

    mkdir -p ~/callback-translation/{invokeTranslationWorkflow,translationCallbackCall,public}
  2. Wechseln Sie in das Verzeichnis invokeTranslationWorkflow:

    cd ~/callback-translation/invokeTranslationWorkflow
  3. Erstellen Sie eine Textdatei mit dem Dateinamen index.js, die den folgenden Node.js-Code enthält:

    const cors = require('cors')({origin: true});
    const {ExecutionsClient} = require('@google-cloud/workflows');
    const client = new ExecutionsClient();
    
    exports.invokeTranslationWorkflow = async (req, res) => {
      cors(req, res, async () => {
        const text = req.body.text;
        console.log(`Translation request for "${text}"`);
    
        const PROJECT_ID = process.env.PROJECT_ID;
        const CLOUD_REGION = process.env.CLOUD_REGION;
        const WORKFLOW_NAME = process.env.WORKFLOW_NAME;
    
        const execResponse = await client.createExecution({
          parent: client.workflowPath(PROJECT_ID, CLOUD_REGION, WORKFLOW_NAME),
          execution: {
            argument: JSON.stringify({text})
          }
        });
        console.log(`Translation workflow execution request: ${JSON.stringify(execResponse)}`);
    
        const execName = execResponse[0].name;
        console.log(`Created translation workflow execution: ${execName}`);
    
        res.set('Access-Control-Allow-Origin', '*');
        res.status(200).json({executionId: execName});
      });
    };
  4. Erstellen Sie eine Textdatei mit dem Dateinamen package.json, die die folgenden npm-Metadaten enthält:

    {
      "name": "launch-translation-workflow",
      "version": "0.0.1",
      "dependencies": {
        "@google-cloud/workflows": "^1.2.5",
        "cors": "^2.8.5"
      }
    }
    
  5. Stellen Sie die Funktion mit einem HTTP-Trigger bereit und lassen Sie nicht authentifizierten Zugriff zu:

    gcloud functions deploy invokeTranslationWorkflow \
    --region=${REGION} \
    --runtime nodejs14 \
    --entry-point=invokeTranslationWorkflow \
    --set-env-vars PROJECT_ID=${GOOGLE_CLOUD_PROJECT},CLOUD_REGION=${REGION},WORKFLOW_NAME=translation_validation \
    --trigger-http \
    --allow-unauthenticated

    Die Bereitstellung der Funktion kann einige Minuten dauern. Alternativ können Sie die Funktion über die Cloud Run Functions-Oberfläche in der Google Cloud -Console bereitstellen.

  6. Nachdem die Funktion bereitgestellt wurde, können Sie das Attribut httpsTrigger.url bestätigen:

    gcloud functions describe invokeTranslationWorkflow

    Notieren Sie sich die zurückgegebene URL, damit Sie sie in einem späteren Schritt verwenden können.

Zweite Cloud Run-Funktion bereitstellen

Diese Cloud Run-Funktion stellt eine HTTP-POST-Anfrage an den vom Workflow erstellten Callback-Endpunkt und übergibt einen Genehmigungsstatus, der angibt, ob die Übersetzung validiert oder abgelehnt wurde.

  1. Wechseln Sie in das Verzeichnis translationCallbackCall:

    cd ../translationCallbackCall
  2. Erstellen Sie eine Textdatei mit dem Dateinamen index.js, die den folgenden Node.js-Code enthält:

    const cors = require('cors')({origin: true});
    const fetch = require('node-fetch');
    
    exports.translationCallbackCall = async (req, res) => {
      cors(req, res, async () => {
        res.set('Access-Control-Allow-Origin', '*');
    
        const {url, approved} = req.body;
        console.log("Approved? ", approved);
        console.log("URL = ", url);
        const {GoogleAuth} = require('google-auth-library');
        const auth = new GoogleAuth();
        const token = await auth.getAccessToken();
        console.log("Token", token);
    
        try {
          const resp = await fetch(url, {
              method: 'POST',
              headers: {
                  'accept': 'application/json',
                  'content-type': 'application/json',
                  'authorization': `Bearer ${token}`
              },
              body: JSON.stringify({ approved })
          });
          console.log("Response = ", JSON.stringify(resp));
    
          const result = await resp.json();
          console.log("Outcome = ", JSON.stringify(result));
    
          res.status(200).json({status: 'OK'});
        } catch(e) {
          console.error(e);
    
          res.status(200).json({status: 'error'});
        }
      });
    };
  3. Erstellen Sie eine Textdatei mit dem Dateinamen package.json, die die folgenden npm-Metadaten enthält:

    {
      "name": "approve-translation-workflow",
      "version": "0.0.1",
      "dependencies": {
        "cors": "^2.8.5",
        "node-fetch": "^2.6.1",
        "google-auth-library": "^7.1.1"
      }
    }
    
  4. Stellen Sie die Funktion mit einem HTTP-Trigger bereit und lassen Sie nicht authentifizierten Zugriff zu:

    gcloud functions deploy translationCallbackCall \
    --region=${REGION} \
    --runtime nodejs14 \
    --entry-point=translationCallbackCall \
    --trigger-http \
    --allow-unauthenticated

    Die Bereitstellung der Funktion kann einige Minuten dauern. Alternativ können Sie die Funktion über die Cloud Run Functions-Oberfläche in der Google Cloud -Console bereitstellen.

  5. Nachdem die Funktion bereitgestellt wurde, können Sie das Attribut httpsTrigger.url bestätigen:

    gcloud functions describe translationCallbackCall

    Notieren Sie sich die zurückgegebene URL, damit Sie sie in einem späteren Schritt verwenden können.

Workflow bereitstellen

Ein Workflow besteht aus einer Reihe von Schritten, die mit der Workflows-Syntax beschrieben werden. Diese kann entweder im YAML- oder JSON-Format geschrieben werden. Dies ist die Definition des Workflows. Nachdem Sie einen Workflow erstellt haben, stellen Sie ihn bereit, um ihn für die Ausführung verfügbar zu machen.

  1. Wechseln Sie in das Verzeichnis callback-translation:

    cd ..
  2. Erstellen Sie eine Textdatei mit dem Dateinamen translation-validation.yaml und folgendem Inhalt:

    main:
        params: [translation_request]
        steps:
            - log_request:
                call: sys.log
                args:
                    text: ${translation_request}
            - vars:
                assign:
                    - exec_id: ${sys.get_env("GOOGLE_CLOUD_WORKFLOW_EXECUTION_ID")}
                    - text_to_translate: ${translation_request.text}
                    - database_root: ${"projects/" + sys.get_env("GOOGLE_CLOUD_PROJECT_ID") + "/databases/(default)/documents/translations/"}
            - log_translation_request:
                call: sys.log
                args:
                    text: ${text_to_translate}
    
            - store_translation_request:
                call: googleapis.firestore.v1.projects.databases.documents.patch
                args:
                    name: ${database_root + exec_id}
                    updateMask:
                        fieldPaths: ['text']
                    body:
                        fields:
                            text:
                                stringValue: ${text_to_translate}
                result: store_translation_request_result
    
            - translate:
                call: googleapis.translate.v2.translations.translate
                args:
                    query:
                        q: ${text_to_translate}
                        target: "FR"
                        format: "text"
                        source: "EN"
                result: translation_result
            - assign_translation:
                assign:
                    - translation: ${translation_result.data.translations[0].translatedText} 
            - log_translation_result:
                call: sys.log
                args:
                    text: ${translation}
    
            - store_translated_text:
                call: googleapis.firestore.v1.projects.databases.documents.patch
                args:
                    name: ${database_root + exec_id}
                    updateMask:
                        fieldPaths: ['translation']
                    body:
                        fields:
                            translation:
                                stringValue: ${translation}
                result: store_translation_request_result   
    
            - create_callback:
                call: events.create_callback_endpoint
                args:
                    http_callback_method: "POST"
                result: callback_details
            - log_callback_details:
                call: sys.log
                args:
                    text: ${callback_details}
    
            - store_callback_details:
                call: googleapis.firestore.v1.projects.databases.documents.patch
                args:
                    name: ${database_root + exec_id}
                    updateMask:
                        fieldPaths: ['callback']
                    body:
                        fields:
                            callback:
                                stringValue: ${callback_details.url}
                result: store_callback_details_result
    
            - await_callback:
                call: events.await_callback
                args:
                    callback: ${callback_details}
                    timeout: 3600
                result: callback_request
            - assign_approval:
                assign:
                    - approved: ${callback_request.http_request.body.approved}
    
            - store_approval:
                call: googleapis.firestore.v1.projects.databases.documents.patch
                args:
                    name: ${database_root + exec_id}
                    updateMask:
                        fieldPaths: ['approved']
                    body:
                        fields:
                            approved:
                                booleanValue: ${approved}
                result: store_approval_result
    
            - return_outcome:
                return:
                    text: ${text_to_translate}
                    translation: ${translation}
                    approved: ${approved}
  3. Nachdem Sie den Workflow erstellt haben, können Sie ihn bereitstellen, aber nicht den Workflow ausführen:

    gcloud workflows deploy translation_validation --source=translation-validation.yaml

Webanwendung erstellen

Erstellen Sie eine Webanwendung, die eine Cloud Functions-Funktion aufruft, die die Ausführung des Workflows startet. Die Webseite wird in Echtzeit aktualisiert, um das Ergebnis der Übersetzungsanfrage anzuzeigen.

  1. Wechseln Sie in das Verzeichnis public:

    cd public
  2. Erstellen Sie eine Textdatei mit dem Dateinamen index.html, die das folgende HTML-Markup enthält. In einem späteren Schritt ändern Sie die Datei index.html und fügen die Firebase SDK-Skripts hinzu.

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
    
        <title>Frenglish translation — Feature Workflows callbacks</title>
    
        <link rel="stylesheet"
            href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.42/dist/themes/base.css">
        <script type="module"
            src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.42/dist/shoelace.js"></script>
        <link rel="stylesheet" href="./style.css">
    </head>
    
    <body>
        <h1>Translate from English to French</h1>
    
        <sl-form class="form-overview">
            <sl-textarea id="text" placeholder="The quick brown fox jumps over the lazy dog."
                label="English text to translate"></sl-textarea>
            <p></p>
            <sl-button id="translateBtn" type="primary">Translate</sl-button>
            <p></p>
            <sl-alert id="translation" type="primary">
                Le rapide renard brun saute au dessus du chien paresseux.
            </sl-alert>
            <p></p>
            <div id="buttonRow" style="display: none;">
                <sl-button id="validateBtn" type="success">Validate</sl-button>
                <sl-button id="rejectBtn" type="danger">Reject</sl-button>
            </div>
            <p></p>
            <sl-alert id="validationAlert" type="success">
                <sl-icon slot="icon" name="check2-circle"></sl-icon>
                <strong>The translation has been validated</strong><br>
                Glad that you liked our translation! We'll save it in our database.
            </sl-alert>
            <sl-alert id="rejectionAlert" type="danger">
                <sl-icon slot="icon" name="exclamation-octagon"></sl-icon>
                <strong>The translation has been rejected</strong><br>
                A pity the translation isn't good! We'll do better next time!
            </sl-alert>
            <p></p>
            <sl-button id="newBtn" style="display: none;" type="primary">New translation</sl-button>
        </sl-form>
    
        <script src="https://www.gstatic.com/firebasejs/8.6.3/firebase-app.js"></script>
        <script src="https://www.gstatic.com/firebasejs/8.6.3/firebase-firestore.js"></script>
    
        <script>
            var firebaseConfig = {
                apiKey: "XXXX",
                authDomain: "XXXX",
                projectId: "XXXX",
                storageBucket: "XXXX",
                messagingSenderId: "XXXX",
                appId: "XXXX",
                measurementId: "XXXX"
            };
            // Initialize Firebase
            firebase.initializeApp(firebaseConfig);
        </script>
        <script src="./script.js" type="module"></script>
    </body>
    
    </html>
    
  3. Erstellen Sie eine Textdatei mit dem Dateinamen script.js, die den folgenden JavaScript-Code enthält:

    document.addEventListener("DOMContentLoaded", async function (event) {
        const textArea = document.getElementById("text");
        textArea.focus();
    
        const newBtn = document.getElementById("newBtn");
        newBtn.addEventListener("sl-focus", event => {
            event.target.blur();
            window.location.reload();
        });
    
        const translationAlert = document.getElementById("translation");
        const buttonRow = document.getElementById("buttonRow");
    
        var callbackUrl = "";
    
        const validationAlert = document.getElementById("validationAlert");
        const rejectionAlert = document.getElementById("rejectionAlert");
        const validateBtn = document.getElementById("validateBtn");
        const rejectBtn = document.getElementById("rejectBtn");
    
        const translateBtn = document.getElementById("translateBtn");
        translateBtn.addEventListener("sl-focus", async event => {
            event.target.disabled = true;
            event.target.loading = true;
            textArea.disabled = true;
    
            console.log("Text to translate = ", textArea.value);
    
            const fnUrl = UPDATE_ME;
    
            try {
                console.log("Calling workflow executor function...");
                const resp = await fetch(fnUrl, {
                    method: "POST",
                    headers: {
                        "accept": "application/json",
                        "content-type": "application/json"
                    },
                    body: JSON.stringify({ text: textArea.value })
                });
                const executionResp = await resp.json();
                const executionId = executionResp.executionId.slice(-36);
                console.log("Execution ID = ", executionId);
    
                const db = firebase.firestore();
                const translationDoc = db.collection("translations").doc(executionId);
    
                var translationReceived = false;
                var callbackReceived =  false;
                var approvalReceived = false;
                translationDoc.onSnapshot((doc) => {
                    console.log("Firestore update", doc.data());
                    if (doc.data()) {
                        if ("translation" in doc.data()) {
                            if (!translationReceived) {
                                console.log("Translation = ", doc.data().translation);
                                translationReceived = true;
                                translationAlert.innerText = doc.data().translation;
                                translationAlert.open = true;
                            }
                        }
                        if ("callback" in doc.data()) {
                            if (!callbackReceived) {
                                console.log("Callback URL = ", doc.data().callback);
                                callbackReceived = true;
                                callbackUrl = doc.data().callback;
                                buttonRow.style.display = "block";
                            }
                        }
                        if ("approved" in doc.data()) {
                            if (!approvalReceived) {
                                const approved = doc.data().approved;
                                console.log("Approval received = ", approved);
                                if (approved) {
                                    validationAlert.open = true;
                                    buttonRow.style.display = "none";
                                    newBtn.style.display = "inline-block";   
                                } else {
                                    rejectionAlert.open = true;
                                    buttonRow.style.display = "none";
                                    newBtn.style.display = "inline-block";
                                }
                                approvalReceived = true;
                            }
                        }
                    }
                });
            } catch (e) {
                console.log(e);
            }
            event.target.loading = false;
        });
    
        validateBtn.addEventListener("sl-focus", async event => {
            validateBtn.disabled = true;
            rejectBtn.disabled = true;
            validateBtn.loading = true;
            validateBtn.blur();
    
            // call callback
            await callCallbackUrl(callbackUrl, true);
        });
    
        rejectBtn.addEventListener("sl-focus", async event => {
            rejectBtn.disabled = true;
            validateBtn.disabled = true;
            rejectBtn.loading = true;
            rejectBtn.blur();
    
            // call callback
            await callCallbackUrl(callbackUrl, false);
        });
    
    });
    
    async function callCallbackUrl(url, approved) {
        console.log("Calling callback URL with status = ", approved);
    
        const fnUrl = UPDATE_ME;
        try {
            const resp = await fetch(fnUrl, {
                method: "POST",
                headers: {
                    "accept": "application/json",
                    "content-type": "application/json"
                },
                body: JSON.stringify({ url, approved })
            });
            const result = await resp.json();
            console.log("Callback answer = ", result);
        } catch(e) {
            console.log(e);
        }
    }
  4. Bearbeiten Sie die Datei script.js und ersetzen Sie die Platzhalter UPDATE_ME durch die zuvor notierten Cloud Run-Funktions-URLs.

    1. Ersetzen Sie in der Methode translateBtn.addEventListener const fnUrl = UPDATE_ME; durch:

      const fnUrl = "https://REGION-PROJECT_ID.cloudfunctions.net/invokeTranslationWorkflow";

    2. Ersetzen Sie in der Funktion callCallbackUrl const fnUrl = UPDATE_ME; durch:

      const fnUrl = "https://REGION-PROJECT_ID.cloudfunctions.net/translationCallbackCall";

  5. Erstellen Sie eine Textdatei mit dem Dateinamen style.css, die die folgenden kaskadierenden Stile enthält:

    * {
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
    }
    
    body {
        margin: 20px;
    }
    
    h1, h2, h3, h4 {
        color: #0ea5e9;
    }
    

Firebase zu meiner Web-App hinzufügen

In dieser Anleitung werden die HTML-Seite, das JavaScript-Script und das CSS-Stylesheet als statische Assets mit Firebase Hosting bereitgestellt. Sie können jedoch auch an einem beliebigen anderen Ort gehostet und zu Testzwecken lokal auf Ihrem eigenen Computer bereitgestellt werden.

Firebase-Projekt erstellen

Bevor Sie Firebase zu Ihrer Anwendung hinzufügen können, müssen Sie ein Firebase-Projekt erstellen, um eine Verbindung zu Ihrer Anwendung herzustellen.

  1. Klicken Sie in der Firebase Console auf Projekt erstellen und wählen Sie Ihr vorhandenes Google Cloud -Projekt aus dem Drop-down-Menü aus, um Firebase-Ressourcen zu diesem Projekt hinzuzufügen.

  2. Klicken Sie auf Weiter, bis Sie die Option zum Hinzufügen von Firebase sehen.

  3. Überspringen Sie die Einrichtung von Google Analytics für Ihr Projekt.

  4. Klicken Sie auf Firebase hinzufügen.

Firebase stellt automatisch Ressourcen für Ihr Firebase-Projekt bereit. Nach Abschluss des Vorgangs werden Sie zur Übersichtsseite für Ihr Projekt in der Firebase Console weitergeleitet.

App bei Firebase registrieren

Nachdem Sie ein Firebase-Projekt haben, können Sie Ihre Webanwendung hinzufügen.

  1. Klicken Sie in der Mitte der Projektübersicht auf das Symbol Web (</>), um den Einrichtungsworkflow zu starten.

  2. Geben Sie einen Alias für die Anwendung ein.

    Dieser ist nur in der Firebase Console sichtbar.

  3. Überspringen Sie die Einrichtung von Firebase Hosting.

  4. Klicken Sie auf App registrieren und fahren Sie mit der Konsole fort.

Cloud Firestore aktivieren

Die Webanwendung verwendet Cloud Firestore, um Daten zu empfangen und zu speichern. Sie müssen Cloud Firestore aktivieren.

  1. Klicken Sie im Abschnitt Build in der Firebase Console auf Firestore-Datenbank.

    Möglicherweise müssen Sie zuerst den linken Navigationsbereich erweitern, um den Abschnitt Build einzublenden.

  2. Klicken Sie im Cloud Firestore-Bereich auf Datenbank erstellen.

  3. Wählen Sie Im Testmodus starten mit einer Sicherheitsregel wie der folgenden aus:

    rules_version = '2';
    service cloud.firestore {
    match /databases/{database}/documents {
      match /{document=**} {
        allow read, write;
      }
    }
    }
  4. Klicken Sie auf Weiter, nachdem Sie den Haftungsausschluss zu den Sicherheitsregeln gelesen haben.

  5. Legen Sie den Speicherort für Cloud Firestore-Daten fest. Sie können die Standardeinstellung übernehmen oder eine Region in Ihrer Nähe auswählen.

  6. Klicken Sie auf Aktivieren, um Firestore bereitzustellen.

Firebase SDK hinzufügen und Firebase initialisieren

Firebase stellt JavaScript-Bibliotheken für die meisten Firebase-Produkte bereit. Bevor Sie Firebase Hosting verwenden, müssen Sie die Firebase SDKs Ihrer Webanwendung hinzufügen.

  1. Zum Initialisieren von Firebase in Ihrer Anwendung müssen Sie die Firebase-Projektkonfiguration Ihrer Anwendung angeben.
    1. Rufen Sie in der Firebase Console die Projekteinstellungen auf.
    2. Wählen Sie im Bereich Meine Apps Ihre App aus.
    3. Wählen Sie im Bereich SDK-Einrichtung und -Konfiguration die Option CDN aus, um Firebase SDK-Bibliotheken aus dem CDN zu laden.
    4. Kopieren Sie das Snippet in Ihre Datei index.html unten in das <body>-Tag und ersetzen Sie die Platzhalterwerte XXXX.
  2. Installieren Sie das Firebase JavaScript SDK.

    1. Wenn Sie noch keine package.json-Datei haben, erstellen Sie eine mit dem folgenden Befehl im Verzeichnis callback-translation:

      npm init
    2. Installieren Sie das npm-Paket firebase und speichern Sie es in der package.json-Datei:

      npm install firebase

Projekt initialisieren und bereitstellen

Sie müssen Ihr Projekt initialisieren, um Ihre lokalen Projektdateien mit Ihrem Firebase-Projekt zu verbinden. Sie können dann Ihre Webanwendung bereitstellen.

  1. Führen Sie im Verzeichnis callback-translation den folgenden Befehl aus:

    firebase init
  2. Wählen Sie die Option Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys aus.

  3. Verwenden Sie ein vorhandenes Projekt und geben Sie Ihre Projekt-ID ein.

  4. Übernehmen Sie public als standardmäßiges öffentliches Stammverzeichnis.

  5. Konfigurieren Sie eine einseitige App.

  6. Überspringen Sie die Einrichtung automatischer Builds und Bereitstellungen mit GitHub.

  7. Geben Sie bei der Eingabeaufforderung File public/index.html already exists. Overwrite? Nein ein.

  8. Wechseln Sie in das Verzeichnis public:

    cd public
  9. Führen Sie im Verzeichnis public den folgenden Befehl aus, um das Projekt auf Ihrer Website bereitzustellen:

    firebase deploy --only hosting

Webanwendung lokal testen

Mit Firebase Hosting können Sie Änderungen lokal ansehen und testen und mit emulierten Backend-Projektressourcen interagieren. Wenn Sie firebase serve verwenden, interagiert Ihre Anwendung mit einem emulierten Backend für Ihre Hosting-Inhalte und Ihre Konfiguration, aber Ihr echtes Backend tut dies für alle anderen Projektressourcen. Für diese Anleitung können Sie firebase serve verwenden. Dies wird jedoch nicht empfohlen, wenn Sie umfangreichere Tests durchführen.

  1. Führen Sie im Verzeichnis public den folgenden Befehl aus:

    firebase serve
  2. Öffnen Sie Ihre Webanwendung unter der zurückgegebenen lokalen URL (in der Regel http://localhost:5000).

  3. Geben Sie Text in Englisch ein und klicken Sie dann auf Übersetzen.

    Eine Übersetzung des Textes auf Französisch sollte angezeigt werden.

  4. Sie können jetzt auf Validieren oder Ablehnen klicken.

    In der Firestore-Datenbank können Sie den Inhalt prüfen. Diese sollten in etwa so aussehen:

    approved: true
    callback: "https://workflowexecutions.googleapis.com/v1/projects/26811016474/locations/us-central1/workflows/translation_validation/executions/68bfce75-5f62-445f-9cd5-eda23e6fa693/callbacks/72851c97-6bb2-45e3-9816-1e3dcc610662_1a16697f-6d90-478d-9736-33190bbe222b"
    text: "The quick brown fox jumps over the lazy dog."
    translation: "Le renard brun rapide saute par-dessus le chien paresseux."
    

    Der Status approved lautet true oder false, je nachdem, ob Sie die Übersetzung validieren oder ablehnen.

Das war's auch schon! Sie haben einen Human-in-the-Loop-Workflow erstellt, der Workflow-Callbacks verwendet.