瞭解如何在 Cloud Run 中建構及部署 LangChain 應用程式

1. 總覽

在本程式碼研究室中,您將瞭解如何部署使用 Gemini 的 LangChain 應用程式,以便您透過 Cloud Run 發布說明詢問問題。

以下舉例說明應用程式的運作方式:如果詢問「我可以在 Cloud Run 中將 Cloud Storage 值區做為磁碟區嗎?」這個問題,應用程式會傳回「是,自 2024 年 1 月 19 日以來」或類似回應。

為了傳回具體回應,應用程式會先擷取與問題相似的 Cloud Run 發布說明,然後向 Gemini 提示問題和發布說明。(這就是通常稱為 RAG 的模式)。以下是應用程式架構的圖表:

2. 設定和需求

首先,請確認您的開發環境設定正確無誤。

  • 您需要建立 Google Cloud 專案,才能部署應用程式所需的資源。
  • 如要部署應用程式,您的本機電腦需要安裝 gcloud經過驗證,並設定為使用專案。
    • gcloud auth login
    • gcloud config set project
  • 如果您想在本機上執行應用程式 (這是我建議的做法),請務必正確設定應用程式預設憑證,包括設定配額專案
    • gcloud auth application-default login
    • gcloud auth application-default set-quota-project
  • 您也必須安裝下列軟體:
    • Python (需要 3.11 以上版本)
    • LangChain CLI
    • poetry 可用於依附元件管理
    • pipx:在隔離的虛擬環境中安裝及執行 LangChain CLI 和 poetry

以下說明如何安裝本教學課程所需的工具

Cloud Workstations

您也可以在 Google Cloud 上使用 Cloud Workstations,而非本機電腦。請注意,截至 2024 年 4 月,該服務執行的 Python 版本低於 3.11,因此您可能需要先升級 Python,再開始使用。

啟用 Cloud API

首先,請執行下列指令,確認已設定要使用的正確 Google Cloud 專案:

gcloud config list project

如果未顯示正確的專案,請輸入下列指令設定專案:

gcloud config set project <PROJECT_ID>

現在啟用下列 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

選擇一個區域

Google Cloud 在全球多個地區提供服務,您必須選擇其中一個地區來部署本實驗室的資源。在 Shell 中將區域設為環境變數 (後續指令會使用這個變數):

export REGION=us-central1

3. 建立向量資料庫例項

這款應用程式的主要功能是擷取與使用者問題相關的發布說明。舉例來說,如果您想詢問 Cloud Storage 相關問題,請在提示中加入下列版本說明:

您可以使用文字嵌入和向量資料庫,找出語意相似的版本資訊。

我將示範如何在 Cloud SQL 上使用 PostgreSQL 做為向量資料庫。建立新的 Cloud SQL 執行個體需要一些時間,因此我們現在就來建立。

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

您可以讓這項指令執行,並繼續執行後續步驟。您必須在某個時間點建立資料庫並新增使用者,但現在請不要浪費時間等待旋轉圖示。

PostgreSQL 是關聯資料庫伺服器,每個新的 Cloud SQL 執行個體都會預設安裝 pgvector 擴充功能,也就是說,您也可以將其用作向量資料庫。

4. Scaffold the LangChain 應用程式

如要繼續操作,您必須先安裝 LangChain CLI,並使用 Poetry 管理依附元件。以下說明如何使用 pipx 安裝:

pipx install langchain-cli poetry

請使用下列指令建立 LangChain 應用程式的專案架構。系統提示時,請將資料夾命名為 run-rag,然後按下 Enter 鍵略過安裝套件:

langchain app new

切換至 run-rag 目錄並安裝依附元件

poetry install

您剛剛建立了 LangServe 應用程式。LangServe 會在 LangChain 鏈結中包裝 FastAPI。內建的遊樂場可讓您輕鬆傳送提示並檢查結果,包括所有中介步驟。建議您開啟編輯器中的 run-rag 資料夾,並瀏覽當中的內容。

5. 建立索引工作

開始整合網頁應用程式之前,請先確認 Cloud Run 發布說明已在 Cloud SQL 資料庫中建立索引。在本節中,您將建立索引工作,執行以下操作:

索引工作會擷取發布說明,並使用文字嵌入模型將其轉換為向量,然後儲存在向量資料庫中。這可讓您根據語意意義,快速搜尋類似的發布說明。

run-rag/app 資料夾中,建立含有下列內容的 indexer.py 檔案:

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

新增必要的依附元件:

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

建立資料庫和使用者

在 Cloud SQL 執行個體 sql-instance 上建立資料庫 release-notes

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

建立名為 app 的資料庫使用者:

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

部署及執行索引工作

接著部署及執行工作:

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

這是一條長指令,讓我們來看看發生了什麼事:

第一個指令會擷取連線名稱 (格式為 project:region:instance 的不重複 ID),並將其設為環境變數 DB_INSTANCE_NAME

第二個指令會部署 Cloud Run 工作。旗標的作用如下:

  • --source .:指定工作原始碼位於目前工作目錄 (您執行指令的目錄)。
  • --command python:設定要在容器中執行的指令。在本例中,我們要執行 Python。
  • --args app/indexer.py:提供 Python 指令的引數。這會指示它在應用程式目錄中執行指令碼 indexer.py。
  • --set-env-vars:設定 Python 指令碼在執行期間可存取的環境變數。
  • --region=$REGION:指定要部署工作所在的區域。
  • --execute-now:指示 Cloud Run 在工作部署後立即啟動。

如要確認工作是否順利完成,您可以執行下列操作:

  • 透過網頁控制台讀取工作執行記錄。系統應會回報「Done saving: xxx release notes」(xxx 是已儲存的版本資訊數量)。
  • 您也可以前往網路控制台的 Cloud SQL 執行個體,並使用 Cloud SQL Studio 查詢 langchain_pg_embedding 資料表中的記錄數量。

6. 編寫網頁應用程式

在編輯器中開啟 app/server.py 檔案。您會看到一行內容如下:

# Edit this to add the chain you want to add

將該註解替換為下列程式碼片段:

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

您也需要新增下列匯入項目:

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

最後,將「NotImplemented」這一行改為:

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

7. 將網頁應用程式部署至 Cloud Run

run-rag 目錄中,使用下列指令將應用程式部署至 Cloud Run:

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

這個指令會執行以下操作:

  • 將原始碼上傳至 Cloud Build
  • 執行 docker 建構作業。
  • 將產生的容器映像檔推送至 Artifact Registry。
  • 使用容器映像檔建立 Cloud Run 服務。

指令執行完成後,系統會在 run.app 網域上列出 HTTPS 網址。這是新 Cloud Run 服務的公開網址

8. 探索遊樂場

開啟 Cloud Run 服務網址,然後前往 /playground。這會產生文字欄位您可以使用這項功能,針對 Cloud Run 版本資訊提出問題,例如:

9. 恭喜

您已成功在 Cloud Run 上建構及部署 LangChain 應用程式。非常好!

以下是關鍵概念:

  • 使用 LangChain 架構建構檢索增強生成 (RAG) 應用程式。
  • 使用 Cloud SQL 上的 PostgreSQL 做為向量資料庫,搭配 Cloud SQL 預設安裝的 pgvector。
  • 以 Cloud Run 工作形式執行較長時間的索引工作,並以 Cloud Run 服務形式執行網頁應用程式。
  • 使用 LangServe 在 FastAPI 應用程式中包裝 LangChain 鏈結,提供方便的介面,以便與 RAG 應用程式互動。

清除所用資源

如要避免系統向您的 Google Cloud Platform 帳戶收取在本教學課程中使用資源的相關費用:

  • 前往 Cloud Console 中的「管理資源」頁面。
  • 在專案清單中選取專案,然後按一下「刪除」。
  • 在對話方塊中輸入專案 ID,然後按一下「Shut down」(關閉) 即可刪除專案。

如果您想保留專案,請務必刪除下列資源:

  • Cloud SQL 執行個體
  • Cloud Run 服務
  • Cloud Run 工作