Dowiedz się, jak utworzyć i wdrożyć aplikację LangChain w Cloud Run

1. Omówienie

Z tego modułu dotyczącego kodu dowiesz się, jak wdrożyć aplikację LangChain, która korzysta z Gemini, aby umożliwić Ci zadawanie pytań w informacjach o wersji Cloud Run.

Oto przykład działania aplikacji: jeśli zapytasz „Czy mogę podłączyć zasobnik Cloud Storage jako wolumin w Cloud Run?”, aplikacja odpowie „Tak, od 19 stycznia 2024 roku” lub podobną.

Aby zwrócić uzasadnione odpowiedzi, aplikacja najpierw pobiera informacje o wersji Cloud Run podobne do pytania, a potem wyświetla Gemini zarówno pytanie, jak i informacje o wersji. (Ten wzorzec często określa się jako RAG). Oto schemat przedstawiający architekturę aplikacji:

2. Konfiguracja i wymagania

Najpierw sprawdźmy, czy środowisko programistyczne jest prawidłowo skonfigurowane.

  • Aby wdrożyć zasoby potrzebne do aplikacji, musisz mieć projekt Google Cloud.
  • Aby wdrożyć aplikację, musisz zainstalować narzędzie gcloud na komputerze lokalnym, uwierzytelnić je i skonfigurować do korzystania z projektu.
    • gcloud auth login
    • gcloud config set project
  • Jeśli chcesz uruchomić aplikację na swoim komputerze (co zalecamy), upewnij się, że domyślne dane logowania aplikacji są prawidłowo skonfigurowane, a także ustawiając projekt limitu.
    • gcloud auth application-default login
    • gcloud auth application-default set-quota-project
  • Musisz również zainstalować następujące oprogramowanie:
    • Python (wymagana wersja 3.11 lub nowsza)
    • interfejs wiersza poleceń LangChain,
    • poezja na temat zarządzania zależnościami.
    • pipx, aby zainstalować i uruchomić interfejs wiersza poleceń LangChain i poezję w izolowanych środowiskach wirtualnych

Oto blog, który pomoże Ci w rozpoczęciu instalowania narzędzi wymaganych w tym przewodniku.

Cloud Workstations

Zamiast komputera lokalnego możesz też używać Cloud Workstations w Google Cloud. Pamiętaj, że w kwietniu 2024 r. używa ona Pythona w wersji starszej niż 3.11, więc zanim rozpoczniesz, może być konieczne uaktualnienie.

Włączanie Cloud APIs

Najpierw uruchom to polecenie, aby sprawdzić, czy masz skonfigurowany odpowiedni projekt Google Cloud:

gcloud config list project

Jeśli nie wyświetla się właściwy projekt, możesz go ustawić za pomocą tego polecenia:

gcloud config set project <PROJECT_ID>

Teraz włącz te interfejsy API:

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

Wybierz region

Usługa Google Cloud jest dostępna w wielu lokalizacjach na całym świecie. Musisz wybrać jedną z nich, aby wdrożyć zasoby, których będziesz używać w tym module. Ustaw region jako zmienną środowiskową w powłoce (późniejsze polecenia korzystają z tej zmiennej):

export REGION=us-central1

3. Tworzenie instancji wektorowej bazy danych

Kluczową częścią tej aplikacji jest pobieranie informacji o wersji związanych z pytaniem użytkownika. Jeśli pytasz o Cloud Storage, możesz dodać do promptu tę informację o wersji:

Możesz użyć wektorów dystrybucyjnych tekstu i wektorowej bazy danych, aby znaleźć informacje o wersji podobne pod względem semantycznym.

Pokażę Ci, jak używać PostgreSQL w Cloud SQL jako wektorowej bazy danych. Tworzenie nowej instancji Cloud SQL zajmuje trochę czasu, więc zrobimy to teraz.

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

Możesz uruchomić to polecenie i kontynuować kolejne kroki. W pewnym momencie konieczne będzie utworzenie bazy danych i dodanie użytkownika, ale nie traćmy czasu na obserwowanie wskaźnika postępu.

PostgreSQL to serwer relacyjnej bazy danych, a w każdej nowej instancji Cloud SQL domyślnie jest zainstalowane rozszerzenie pgvector, co oznacza, że można z niego korzystać również jako wektorowej bazy danych.

4. Scaffold the LangChain

Aby kontynuować, musisz zainstalować interfejs wiersza poleceń LangChain i zarządzać zależnościami poezji. Oto jak zainstalować te z pipx:

pipx install langchain-cli poetry

Rozbuduj aplikację LangChain za pomocą następującego polecenia. Gdy pojawi się prośba, nadaj folderowi nazwę run-rag i pomiń instalowanie pakietów, naciskając Enter:

langchain app new

Przejdź do katalogu run-rag i zainstaluj zależności

poetry install

Właśnie udało Ci się utworzyć aplikację LangServe. LangServe wykorzystuje interfejs FastAPI dookoła łańcucha LangChain. Ma on wbudowany plac zabaw, co ułatwia wysyłanie promptów i sprawdzanie wyników, w tym wszystkich czynności pośrednich. Otwórz folder run-rag w edytorze i sprawdź, co się w nim znajduje.

5. Tworzenie zadania indeksowania

Zanim zaczniesz tworzyć aplikację internetową, sprawdźmy, czy informacje o wersji Cloud Run są zindeksowane w bazie danych Cloud SQL. W tej sekcji utworzysz zadanie indeksowania, które wykona te czynności:

Zadanie indeksowania rejestruje informacje o wersji, konwertuje je na wektory za pomocą modelu wektora dystrybucyjnego tekstu i zapisuje w wektorowej bazie danych. Dzięki temu można sprawnie wyszukiwać podobne informacje o wersji na podstawie ich znaczenia semantycznego.

W folderze run-rag/app utwórz plik indexer.py o następującej treści:

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

Dodaj wymagane zależności:

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

Tworzenie bazy danych i użytkownika

Utwórz bazę danych release-notes w instancji Cloud SQL sql-instance:

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

Utwórz użytkownika bazy danych o nazwie app:

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

Wdrażanie i uruchamianie zadania indeksowania

Teraz wdróż i uruchom zadanie:

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

To długie polecenie. Zobaczmy, co się dzieje:

Pierwsze polecenie pobiera nazwę połączenia (unikalny identyfikator w formacie project:region:instance) i ustawia ją jako zmienną środowiskową DB_INSTANCE_NAME.

Drugie polecenie pozwala wdrożyć zadanie Cloud Run. Flagi mogą sprawiać takie problemy:

  • --source .: określa, że kod źródłowy zadania znajduje się w bieżącym katalogu roboczym (katalogu, w którym uruchamiasz polecenie).
  • --command python: ustawia polecenie do wykonania w kontenerze. W tym przypadku jest to Python.
  • --args app/indexer.py: podaje argumenty polecenia w języku Python. Zapewnia to uruchomienie skryptu indexer.py w katalogu aplikacji.
  • --set-env-vars: ustawia zmienne środowiskowe, do których skrypt Pythona ma dostęp podczas wykonywania.
  • --region=$REGION: określa region, w którym zadanie powinno zostać wdrożone.
  • --execute-now: informuje Cloud Run o konieczności uruchomienia zadania natychmiast po jego wdrożeniu.

Aby sprawdzić, czy zadanie zostało wykonane, możesz wykonać te czynności:

  • Odczytuj logi wykonania zadania w konsoli internetowej. Powinno wyświetlić się komunikat „Zakończono zapisywanie: informacje o wersji xxx” (gdzie xxx to liczba zapisanych informacji o wersji).
  • Możesz też przejść do instancji Cloud SQL w konsoli internetowej i za pomocą Cloud SQL Studio wykonać zapytanie o liczbę rekordów w tabeli langchain_pg_embedding.

6. Tworzenie aplikacji internetowej

Otwórz plik app/server.py w edytorze. Znajdziesz tam następujący tekst:

# Edit this to add the chain you want to add

Zastąp ten komentarz następującym fragmentem:

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

Musisz też zaimportować te elementy:

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

Na koniec zmień wiersz z informacją „NotImplemented” (Nie zaimplementowano). do:

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

7. Wdrażanie aplikacji internetowej w Cloud Run

W katalogu run-rag przeprowadź wdrożenie aplikacji w Cloud Run za pomocą tego polecenia:

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

To polecenie wykonuje te operacje:

  • Przesyłanie kodu źródłowego do Cloud Build
  • Uruchom kompilację Dockera.
  • Przekaż utworzony obraz kontenera do Artifact Registry.
  • Utwórz usługę Cloud Run za pomocą obrazu kontenera.

Po zakończeniu wykonywania polecenia wyświetli się adres URL HTTPS w domenie run.app. To jest publiczny adres URL Twojej nowej usługi Cloud Run

8. Poznaj plac zabaw

Otwórz adres URL usługi Cloud Run i przejdź do usługi /playground. Wyświetla się pole tekstowe. Służy on do zadawania pytań w informacjach o wersji Cloud Run, na przykład:

9. Gratulacje

Udało Ci się utworzyć i wdrożyć aplikację LangChain w Cloud Run. Brawo!

Oto główne koncepcje:

  • Wykorzystanie platformy LangChain do stworzenia aplikacji Retrieval Augmented Generation (RAG).
  • Korzystanie z PostgreSQL w Cloud SQL jako wektorowej bazy danych z użyciem narzędzia pgvector, który jest domyślnie instalowany w Cloud SQL.
  • Uruchamianie dłuższego zadania indeksowania jako zadania Cloud Run, a aplikacji internetowej jako usługi Cloud Run.
  • Opakuj łańcuch LangChain do aplikacji FastAPI za pomocą LangServe, by mieć wygodny interfejs do interakcji z aplikacją RAG.

Czyszczenie danych

Aby uniknąć obciążenia konta Google Cloud Platform opłatami za zasoby zużyte w tym samouczku:

  • W konsoli Cloud otwórz stronę Zarządzanie zasobami.
  • Na liście projektów wybierz swój projekt i kliknij Usuń.
  • W oknie wpisz identyfikator projektu i kliknij Wyłącz, aby usunąć projekt.

Jeśli chcesz zachować projekt, usuń te zasoby:

  • Instancja Cloud SQL
  • Usługa Cloud Run
  • Zadanie Cloud Run