Tìm hiểu cách xây dựng và triển khai ứng dụng LangChain trên Cloud Run

1. Tổng quan

Trong lớp học lập trình này, bạn sẽ tìm hiểu cách triển khai ứng dụng LangChain sử dụng Gemini để đặt câu hỏi về ghi chú phát hành của Cloud Run.

Sau đây là ví dụ về cách hoạt động của ứng dụng: Nếu bạn đặt câu hỏi "Tôi có thể gắn một bộ nhớ trên Cloud Storage làm phương tiện lưu trữ trong Cloud Run không?", thì ứng dụng sẽ trả lời "Có, kể từ ngày 19 tháng 1 năm 2024" hoặc nội dung tương tự.

Để trả về các câu trả lời dựa trên cơ sở, trước tiên, ứng dụng truy xuất ghi chú phát hành của Cloud Run tương tự như câu hỏi, sau đó nhắc Gemini bằng cả câu hỏi và ghi chú phát hành. (Đây là một mẫu thường được gọi là RAG.) Dưới đây là sơ đồ thể hiện cấu trúc của ứng dụng:

2. Thiết lập và yêu cầu

Trước tiên, hãy đảm bảo môi trường phát triển của bạn được thiết lập chính xác.

  • Bạn cần có một dự án Google Cloud để triển khai các tài nguyên cần thiết cho ứng dụng.
  • Để triển khai ứng dụng này, bạn phải cài đặt gcloud trên máy cục bộ, đã xác thực và định cấu hình để sử dụng dự án.
    • gcloud auth login
    • gcloud config set project
  • Nếu muốn chạy ứng dụng trên máy cục bộ (đây là cách nên làm), bạn cần đảm bảo thông tin xác thực mặc định của ứng dụng được thiết lập chính xác, bao gồm cả việc thiết lập dự án hạn mức.
    • gcloud auth application-default login
    • gcloud auth application-default set-quota-project
  • Bạn cũng cần cài đặt các phần mềm sau:
    • Python (cần có phiên bản 3.11 trở lên)
    • LangChain CLI
    • Thơ để quản lý phần phụ thuộc
    • pipx để cài đặt và chạy LangChain CLI và thơ trong các môi trường ảo tách biệt

Sau đây là một blog giúp bạn bắt đầu cài đặt các công cụ cần thiết cho hướng dẫn này.

Máy trạm trên đám mây

Thay vì dùng máy cục bộ, bạn cũng có thể sử dụng Cloud Workstation trên Google Cloud. Xin lưu ý rằng kể từ tháng 4 năm 2024, phiên bản này sẽ chạy phiên bản Python thấp hơn 3.11, vì vậy, bạn có thể cần nâng cấp Python trước khi bắt đầu.

Bật Cloud API

Trước tiên, hãy chạy lệnh sau để đảm bảo bạn đã định cấu hình đúng dự án Google Cloud cần sử dụng:

gcloud config list project

Nếu dự án chính xác không xuất hiện, bạn có thể đặt dự án đó bằng lệnh sau:

gcloud config set project <PROJECT_ID>

Bây giờ, hãy bật các API sau:

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

Chọn vùng

Google Cloud có ở nhiều vị trí trên toàn cầu và bạn cần chọn một vị trí để triển khai các tài nguyên mà bạn sẽ sử dụng cho lớp học này. Đặt khu vực làm biến môi trường trong shell (các lệnh sau này sử dụng biến này):

export REGION=us-central1

3. Tạo thực thể cơ sở dữ liệu vectơ

Một phần quan trọng của ứng dụng này là truy xuất ghi chú phát hành có liên quan đến câu hỏi của người dùng. Để làm cho việc đó cụ thể hơn, nếu đưa ra câu hỏi về Cloud Storage, bạn nên thêm ghi chú phát hành sau đây vào câu lệnh:

Bạn có thể sử dụng tính năng nhúng văn bản và cơ sở dữ liệu vectơ để tìm các ghi chú phát hành có ngữ nghĩa tương tự.

Tôi sẽ hướng dẫn bạn cách sử dụng PostgreSQL trên Cloud SQL làm cơ sở dữ liệu vectơ. Việc tạo một phiên bản Cloud SQL mới sẽ mất chút thời gian, vì vậy, hãy bắt đầu ngay.

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

Bạn có thể để lệnh này chạy và tiếp tục thực hiện các bước tiếp theo. Đến một lúc nào đó, bạn sẽ cần tạo cơ sở dữ liệu và thêm người dùng, nhưng đừng lãng phí thời gian xem vòng quay ngay bây giờ.

PostgreSQL là một máy chủ cơ sở dữ liệu quan hệ và theo mặc định, mọi phiên bản mới của Cloud SQL đều được cài đặt tiện ích pgvector. Điều này có nghĩa là bạn cũng có thể sử dụng phiên bản này làm cơ sở dữ liệu vectơ.

4. Xây dựng ứng dụng LangChain

Để tiếp tục, bạn cần cài đặt LangChain CLI và phần thơ để quản lý các phần phụ thuộc. Dưới đây là cách cài đặt bằng pipx:

pipx install langchain-cli poetry

Tạo khung cho ứng dụng LangChain bằng lệnh sau. Khi được hỏi, hãy đặt tên thư mục là run-rag và bỏ qua việc cài đặt gói bằng cách nhấn enter:

langchain app new

Chuyển sang thư mục run-rag và cài đặt các phần phụ thuộc

poetry install

Bạn vừa tạo một ứng dụng LangServe. LangServe gói FastAPI xung quanh một chuỗi LangChain. Công cụ này có một sân chơi tích hợp giúp bạn dễ dàng gửi lời nhắc và kiểm tra kết quả, bao gồm cả tất cả các bước trung gian. Bạn nên mở thư mục run-rag trong trình chỉnh sửa và khám phá nội dung trong đó.

5. Tạo công việc lập chỉ mục

Trước khi bắt đầu tạo ứng dụng web, hãy đảm bảo rằng ghi chú phát hành Cloud Run được lập chỉ mục trong cơ sở dữ liệu Cloud SQL. Trong phần này, bạn sẽ tạo một công việc lập chỉ mục thực hiện những việc sau:

Công việc lập chỉ mục sẽ ghi chú phát hành, chuyển đổi các ghi chú đó thành các vectơ bằng mô hình nhúng văn bản rồi lưu trữ các ghi chú đó trong cơ sở dữ liệu vectơ. Điều này cho phép bạn tìm kiếm các ghi chú phát hành tương tự một cách hiệu quả dựa trên ý nghĩa ngữ nghĩa.

Trong thư mục run-rag/app, hãy tạo tệp indexer.py có nội dung sau:

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

Thêm các phần phụ thuộc bắt buộc:

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

Tạo cơ sở dữ liệu và người dùng

Tạo cơ sở dữ liệu release-notes trên phiên bản Cloud SQL sql-instance:

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

Tạo người dùng cơ sở dữ liệu có tên là app:

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

Triển khai và chạy công việc lập chỉ mục

Bây giờ, hãy triển khai và chạy công việc:

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

Đó là một lệnh dài, hãy xem những gì đang diễn ra:

Lệnh đầu tiên truy xuất tên kết nối (mã nhận dạng duy nhất có định dạng là project:region:instance) và đặt tên đó làm biến môi trường DB_INSTANCE_NAME.

Lệnh thứ hai triển khai công việc trên Cloud Run. Dưới đây là chức năng của cờ:

  • --source .: Chỉ định mã nguồn cho công việc nằm trong thư mục đang làm việc (thư mục mà bạn đang chạy lệnh).
  • --command python: Thiết lập lệnh để thực thi bên trong vùng chứa. Trong trường hợp này, đó là để chạy Python.
  • --args app/indexer.py: Cung cấp đối số cho lệnh python. Thao tác này sẽ yêu cầu ứng dụng chạy tập lệnhindexer.py trong thư mục ứng dụng.
  • --set-env-vars: Thiết lập các biến môi trường mà tập lệnh Python có thể truy cập trong quá trình thực thi.
  • --region=$REGION: Chỉ định khu vực mà bạn sẽ triển khai công việc.
  • --execute-now: Yêu cầu Cloud Run bắt đầu công việc ngay sau khi triển khai.

Để xác minh rằng công việc đã hoàn tất thành công, bạn có thể làm như sau:

  • Đọc nhật ký thực hiện lệnh thông qua bảng điều khiển web. Thao tác này sẽ báo cáo "Đã lưu xong: ghi chú phát hành xxx" (trong đó xxx là số ghi chú phát hành đã lưu).
  • Bạn cũng có thể chuyển đến phiên bản Cloud SQL trong bảng điều khiển web rồi sử dụng Cloud SQL Studio để truy vấn số lượng bản ghi trong bảng langchain_pg_embedding.

6. Viết ứng dụng web

Mở tệp app/server.py trong trình chỉnh sửa. Bạn sẽ thấy một dòng có nội dung như sau:

# Edit this to add the chain you want to add

Thay thế nhận xét đó bằng đoạn mã sau:

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

Bạn cũng cần thêm các lệnh nhập sau:

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

Cuối cùng, hãy thay đổi dòng có nội dung "NotDeployed" (Chưa được triển khai) thành:

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

7. Triển khai ứng dụng web cho Cloud Run

Từ thư mục run-rag, hãy sử dụng lệnh sau để triển khai ứng dụng lên 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

Lệnh này thực hiện những việc sau:

  • Tải mã nguồn lên Cloud Build
  • Chạy bản dựng docker.
  • Đẩy hình ảnh vùng chứa thu được vào Cấu phần phần mềm.
  • Tạo dịch vụ Cloud Run bằng hình ảnh vùng chứa.

Khi hoàn tất, lệnh này sẽ liệt kê một URL HTTPS trên miền run.app. Đây là URL công khai của dịch vụ Cloud Run mới

8. Khám phá sân chơi

Mở URL dịch vụ Cloud Run rồi chuyển đến /playground. Thao tác này sẽ hiển thị một trường văn bản. Hãy sử dụng dịch vụ này để đặt câu hỏi về ghi chú phát hành của Cloud Run, chẳng hạn như dưới đây:

9. Xin chúc mừng

Bạn đã tạo và triển khai thành công ứng dụng LangChain trên Cloud Run. Chính xác!

Sau đây là các khái niệm chính:

  • Sử dụng khung LangChain để xây dựng ứng dụng Thế hệ tăng cường truy xuất (RAG).
  • Sử dụng PostgreSQL trên Cloud SQL làm cơ sở dữ liệu vectơ với pgvector, được cài đặt theo mặc định trên Cloud SQL.
  • Chạy một công việc lập chỉ mục chạy trong thời gian dài hơn dưới dạng công việc trên Cloud Run và một ứng dụng web dưới dạng dịch vụ trên Cloud Run.
  • Gói chuỗi LangChain trong ứng dụng FastAPI bằng LangServe, giúp cung cấp một giao diện thuận tiện để tương tác với ứng dụng RAG.

Dọn dẹp

Để tránh bị tính phí cho tài khoản Google Cloud Platform của bạn đối với các tài nguyên được sử dụng trong hướng dẫn này, hãy làm như sau:

  • Trong Cloud Console, hãy chuyển đến trang Quản lý tài nguyên.
  • Trong danh sách dự án, hãy chọn dự án của bạn rồi nhấp vào Xoá.
  • Trong hộp thoại, hãy nhập mã dự án rồi nhấp vào Shut down (Tắt) để xoá dự án.

Nếu bạn muốn giữ lại dự án, hãy nhớ xoá các tài nguyên sau:

  • Phiên bản Cloud SQL
  • Dịch vụ Cloud Run
  • Công việc trên Cloud Run