LangChain-Anwendung in Cloud Run erstellen und bereitstellen

1. Übersicht

In diesem Codelab erfahren Sie, wie Sie eine LangChain-App bereitstellen, die Gemini verwendet, um Fragen über die Cloud Run-Versionshinweise zu stellen.

Hier ein Beispiel für die Funktionsweise der Anwendung: Wenn Sie die Frage „Kann ich einen Cloud Storage-Bucket als Volume in Cloud Run bereitstellen?“ stellen, antwortet die Anwendung mit „Ja, seit dem 19. Januar 2024“ oder Ähnliches.

Um fundierte Antworten zurückzugeben, ruft die App zuerst Cloud Run-Versionshinweise ab, die der Frage ähneln, und fordert Gemini dann sowohl die Frage als auch die Versionshinweise an. (Dieses Muster wird allgemein als RAG bezeichnet.) Das folgende Diagramm zeigt die Architektur der Anwendung:

2. Einrichtung und Anforderungen

Prüfen Sie zuerst, ob Ihre Entwicklungsumgebung richtig eingerichtet ist.

  • Sie benötigen ein Google Cloud-Projekt, um die für die Anwendung erforderlichen Ressourcen bereitzustellen.
  • Damit Sie die Anwendung bereitstellen können, muss auf Ihrem lokalen Computer gcloud installiert, authentifizierte und für die Verwendung des Projekts konfiguriert sein.
    • gcloud auth login
    • gcloud config set project
  • Wenn Sie die Anwendung auf Ihrem lokalen Computer ausführen möchten, müssen Sie darauf achten, dass Ihre Standardanmeldedaten für Anwendungen korrekt eingerichtet sind. Dazu gehört auch das Festlegen des Kontingentprojekts.
    • gcloud auth application-default login
    • gcloud auth application-default set-quota-project
  • Außerdem müssen Sie folgende Software installiert haben:
    • Python (Version 3.11 oder höher ist erforderlich)
    • LangChain-CLI
    • poetry für das Abhängigkeitsmanagement
    • pipx zum Installieren und Ausführen der LangChain-Befehlszeile und der Gedichte in isolierten virtuellen Umgebungen

In diesem Blog finden Sie Informationen zur Installation der Tools, die für diese Schritt-für-Schritt-Anleitung erforderlich sind.

Cloud Workstations

Anstelle Ihres lokalen Computers können Sie auch Cloud Workstations in Google Cloud verwenden. Beachten Sie, dass dort seit April 2024 eine niedrigere Python-Version als 3.11 ausgeführt wird. Daher müssen Sie Python möglicherweise aktualisieren, bevor Sie beginnen können.

Cloud APIs aktivieren

Führen Sie zuerst den folgenden Befehl aus, um zu prüfen, ob Sie das richtige Google Cloud-Projekt konfiguriert haben:

gcloud config list project

Wenn nicht das richtige Projekt angezeigt wird, können Sie es mit dem folgenden Befehl festlegen:

gcloud config set project <PROJECT_ID>

Aktivieren Sie jetzt die folgenden APIs:

gcloud services enable \
  bigquery.googleapis.com \
  sqladmin.googleapis.com \
  aiplatform.googleapis.com \
  cloudresourcemanager.googleapis.com \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  run.googleapis.com \
  secretmanager.googleapis.com

Region auswählen

Google Cloud ist weltweit an vielen Standorten verfügbar. Sie müssen einen Anbieter auswählen, um die Ressourcen bereitzustellen, die Sie für dieses Lab verwenden möchten. Legen Sie die Region in der Shell als Umgebungsvariable fest (spätere Befehle verwenden diese Variable):

export REGION=us-central1

3. Instanz der Vektordatenbank erstellen

Ein wichtiger Teil dieser App besteht darin, Versionshinweise abzurufen, die für die Frage des Nutzers relevant sind. Wenn Sie eine Frage zu Cloud Storage stellen, soll dem Prompt der folgende Release-Hinweis hinzugefügt werden:

Sie können Texteinbettungen und eine Vektordatenbank verwenden, um semantisch ähnliche Versionshinweise zu finden.

zeige ich Ihnen, wie Sie PostgreSQL in Cloud SQL als Vektordatenbank verwenden. Das Erstellen einer neuen Cloud SQL-Instanz dauert einige Zeit.

gcloud sql instances create sql-instance \
  --database-version POSTGRES_14 \
  --tier db-f1-micro \
  --region $REGION

Sie können diesen Befehl ausführen lassen und mit den nächsten Schritten fortfahren. Irgendwann müssen Sie eine Datenbank erstellen und einen Benutzer hinzufügen, aber lassen Sie uns keine Zeit damit verschwenden, das Kreiselsymbol zu beobachten.

PostgreSQL ist ein relationaler Datenbankserver. Bei jeder neuen Instanz von Cloud SQL ist standardmäßig die Erweiterung pgvector installiert. Sie können sie also auch als Vektordatenbank verwenden.

4. LangChain-App einrichten

Damit Sie fortfahren können, müssen Sie die LangChain-Befehlszeile installiert haben sowie Gedichte, um Abhängigkeiten zu verwalten. So installieren Sie diese mithilfe von pipx:

pipx install langchain-cli poetry

Erstellen Sie die LangChain-Anwendung mit dem folgenden Befehl. Wenn Sie dazu aufgefordert werden, nennen Sie den Ordner run-rag und überspringen Sie die Installation von Paketen, indem Sie die Eingabetaste drücken:

langchain app new

Zum Verzeichnis run-rag wechseln und Abhängigkeiten installieren

poetry install

Sie haben soeben eine LangServe-App erstellt. LangServe umschließt FastAPI um eine LangChain-Kette. Es verfügt über einen integrierten Playground, in dem es einfach ist, Prompts zu senden und die Ergebnisse einschließlich aller Zwischenschritte zu prüfen. Öffnen Sie am besten den Ordner run-rag in Ihrem Editor und sehen Sie sich den Inhalt an.

5. Indexierungsjob erstellen

Bevor Sie mit dem Erstellen der Webanwendung beginnen, prüfen Sie, ob die Cloud Run-Versionshinweise in der Cloud SQL-Datenbank indexiert sind. In diesem Abschnitt erstellen Sie einen Indexierungsjob, der Folgendes ausführt:

Der Indexierungsjob erstellt Versionshinweise, wandelt sie mithilfe eines Texteinbettungsmodells in Vektoren um und speichert sie in einer Vektordatenbank. Dies ermöglicht eine effiziente Suche nach ähnlichen Versionshinweisen auf Grundlage ihrer semantischen Bedeutung.

Erstellen Sie im Ordner run-rag/app eine Datei indexer.py mit folgendem Inhalt:

import os
from google.cloud.sql.connector import Connector
import pg8000
from langchain_community.vectorstores.pgvector import PGVector
from langchain_google_vertexai import VertexAIEmbeddings
from google.cloud import bigquery


# Retrieve all Cloud Run release notes from BigQuery 
client = bigquery.Client()
query = """
SELECT
  CONCAT(FORMAT_DATE("%B %d, %Y", published_at), ": ", description) AS release_note
FROM `bigquery-public-data.google_cloud_release_notes.release_notes`
WHERE product_name= "Cloud Run"
ORDER BY published_at DESC
"""
rows = client.query(query)

print(f"Number of release notes retrieved: {rows.result().total_rows}")

# Set up a PGVector instance 
connector = Connector()

def getconn() -> pg8000.dbapi.Connection:
    conn: pg8000.dbapi.Connection = connector.connect(
        os.getenv("DB_INSTANCE_NAME", ""),
        "pg8000",
        user=os.getenv("DB_USER", ""),
        password=os.getenv("DB_PASS", ""),
        db=os.getenv("DB_NAME", ""),
    )
    return conn

store = PGVector(
    connection_string="postgresql+pg8000://",
    use_jsonb=True,
    engine_args=dict(
        creator=getconn,
    ),
    embedding_function=VertexAIEmbeddings(
        model_name="textembedding-gecko@003"
    ),
    pre_delete_collection=True  
)

# Save all release notes into the Cloud SQL database
texts = list(row["release_note"] for row in rows)
ids = store.add_texts(texts)

print(f"Done saving: {len(ids)} release notes")

Fügen Sie die erforderlichen Abhängigkeiten hinzu:

poetry add \
  cloud-sql-python-connector["pg8000"] \
  langchain-google-vertexai==1.0.5 \
  langchain-community==0.2.5 \
  pgvector

Datenbank und Nutzer erstellen

Erstellen Sie die Datenbank release-notes in der Cloud SQL-Instanz sql-instance:

gcloud sql databases create release-notes --instance sql-instance

Erstellen Sie einen Datenbanknutzer mit dem Namen app:

gcloud sql users create app --instance sql-instance --password "myprecious"

Indexierungsjob bereitstellen und ausführen

Stellen Sie nun den Job bereit und führen Sie ihn aus:

DB_INSTANCE_NAME=$(gcloud sql instances describe sql-instance --format="value(connectionName)")

gcloud run jobs deploy indexer \
  --source . \
  --command python \
  --args app/indexer.py \
  --set-env-vars=DB_INSTANCE_NAME=$DB_INSTANCE_NAME \
  --set-env-vars=DB_USER=app \
  --set-env-vars=DB_NAME=release-notes \
  --set-env-vars=DB_PASS=myprecious \
  --region=$REGION \
  --execute-now

Das ist ein langer Befehl. Sehen wir uns an, was passiert:

Mit dem ersten Befehl wird der Verbindungsname abgerufen (eine eindeutige ID im Format project:region:instance) und als Umgebungsvariable DB_INSTANCE_NAME festgelegt.

Der zweite Befehl stellt den Cloud Run-Job bereit. So funktionieren die Flags:

  • --source .: gibt an, dass sich der Quellcode für den Job im aktuellen Arbeitsverzeichnis (dem Verzeichnis, in dem Sie den Befehl ausführen) befindet.
  • --command python: Legt den Befehl fest, der im Container ausgeführt werden soll. In diesem Fall wird Python ausgeführt.
  • --args app/indexer.py: Stellt die Argumente für den Python-Befehl bereit. Damit wird er angewiesen, das Skript „indexer.py“ im Anwendungsverzeichnis auszuführen.
  • --set-env-vars: Legt Umgebungsvariablen fest, auf die das Python-Skript während der Ausführung zugreifen kann.
  • --region=$REGION: Gibt die Region an, in der der Job bereitgestellt werden soll.
  • --execute-now: Weist Cloud Run an, den Job sofort nach der Bereitstellung zu starten.

So überprüfen Sie, ob der Job erfolgreich abgeschlossen wurde:

  • Lesen Sie die Logs der Jobausführung über die Webkonsole. Es sollte folgende Meldung angezeigt werden: „Speichern abgeschlossen: xxx-Versionshinweise“ (xxx steht hier für die Anzahl der gespeicherten Versionshinweise).
  • Sie können auch in der Webkonsole die Cloud SQL-Instanz aufrufen und mit Cloud SQL Studio die Anzahl der Datensätze in der Tabelle langchain_pg_embedding abfragen.

6. Webanwendung schreiben

Öffnen Sie die Datei app/server.py in Ihrem Editor. Sie sehen eine Zeile mit folgendem Text:

# Edit this to add the chain you want to add

Ersetzen Sie diesen Kommentar durch das folgende Snippet:

# (1) Initialize VectorStore
connector = Connector()


def getconn() -> pg8000.dbapi.Connection:
    conn: pg8000.dbapi.Connection = connector.connect(
        os.getenv("DB_INSTANCE_NAME", ""),
        "pg8000",
        user=os.getenv("DB_USER", ""),
        password=os.getenv("DB_PASS", ""),
        db=os.getenv("DB_NAME", ""),
    )
    return conn


vectorstore = PGVector(
    connection_string="postgresql+pg8000://",
    use_jsonb=True,
    engine_args=dict(
        creator=getconn,
    ),
    embedding_function=VertexAIEmbeddings(
        model_name="textembedding-gecko@003"
    )
)

# (2) Build retriever


def concatenate_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)


notes_retriever = vectorstore.as_retriever() | concatenate_docs

# (3) Create prompt template
prompt_template = PromptTemplate.from_template(
    """You are a Cloud Run expert answering questions. 
Use the retrieved release notes to answer questions
Give a concise answer, and if you are unsure of the answer, just say so.

Release notes: {notes}

Here is your question: {query}
Your answer: """)

# (4) Initialize LLM
llm = VertexAI(
    model_name="gemini-1.0-pro-001",
    temperature=0.2,
    max_output_tokens=100,
    top_k=40,
    top_p=0.95
)

# (5) Chain everything together
chain = (
    RunnableParallel({
        "notes": notes_retriever,
        "query": RunnablePassthrough()
    })
    | prompt_template
    | llm
    | StrOutputParser()
)

Sie müssen außerdem diese Importe hinzufügen:

import pg8000
import os
from google.cloud.sql.connector import Connector
from langchain_google_vertexai import VertexAI
from langchain_google_vertexai import VertexAIEmbeddings
from langchain_core.runnables import RunnablePassthrough, RunnableParallel
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_community.vectorstores.pgvector import PGVector

Ändern Sie abschließend die Zeile "NotImplemented" (Nicht implementiert). in:

# add_routes(app, NotImplemented)
add_routes(app, chain)

7. Webanwendung in Cloud Run bereitstellen

Verwenden Sie im Verzeichnis run-rag den folgenden Befehl, um die Anwendung in Cloud Run bereitzustellen:

DB_INSTANCE_NAME=$(gcloud sql instances describe sql-instance --format="value(connectionName)")

gcloud run deploy run-rag \
  --source . \
  --set-env-vars=DB_INSTANCE_NAME=$DB_INSTANCE_NAME \
  --set-env-vars=DB_USER=app \
  --set-env-vars=DB_NAME=release-notes \
  --set-env-vars=DB_PASS=myprecious \
  --region=$REGION \
  --allow-unauthenticated

Mit diesem Befehl wird Folgendes ausgeführt:

  • Quellcode in Cloud Build hochladen
  • Führen Sie „docker build“ aus.
  • Übertragen Sie das resultierende Container-Image per Push an Artifact Registry.
  • Erstellen Sie mit dem Container-Image einen Cloud Run-Dienst.

Wenn der Befehl ausgeführt wurde, wird eine HTTPS-URL in der Domain „run.app“ aufgelistet. Dies ist die öffentliche URL Ihres neuen Cloud Run-Dienstes

8. Spielplatz entdecken

Öffnen Sie die URL des Cloud Run-Dienstes und rufen Sie /playground auf. Ein Textfeld wird angezeigt. Hier können Sie Fragen zu den Versionshinweisen zu Cloud Run stellen:

9. Glückwunsch

Sie haben erfolgreich eine LangChain-Anwendung in Cloud Run erstellt und bereitgestellt. Gut gemacht!

Hier die wichtigsten Konzepte:

  • LangChain-Framework zum Erstellen einer RAG-Anwendung (Retrieval Augmented Generation) verwenden
  • PostgreSQL in Cloud SQL als Vektordatenbank mit pgvector verwenden, das standardmäßig in Cloud SQL installiert ist
  • Einen länger laufenden Indexierungsjob als Cloud Run-Jobs und eine Webanwendung als Cloud Run-Dienst ausführen.
  • Schließen Sie eine LangChain-Kette mit LangServe in eine FastAPI-Anwendung ein, um eine praktische Schnittstelle für die Interaktion mit Ihrer RAG-Anwendung zu erhalten.

Bereinigen

So vermeiden Sie, dass Ihrem Google Cloud Platform-Konto die in dieser Anleitung verwendeten Ressourcen berechnet werden:

  • Wechseln Sie in der Cloud Console zur Seite „Ressourcen verwalten“.
  • Wählen Sie Ihr Projekt in der Projektliste aus und klicken Sie auf „Löschen“.
  • Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie dann auf „Beenden“, um das Projekt zu löschen.

Wenn Sie das Projekt behalten möchten, löschen Sie die folgenden Ressourcen:

  • Cloud SQL-Instanz
  • Cloud Run-Dienst
  • Cloud Run-Job