Cloud SQL은 고성능, 원활한 통합 및 인상적인 확장성을 제공하는 완전 관리형 관계형 데이터베이스 서비스입니다. MySQL, PostgreSQL, SQL Server 데이터베이스 엔진을 제공합니다. Cloud SQL의 LangChain 통합을 활용하여 AI 기반 경험을 구축하도록 데이터베이스 애플리케이션을 확장하세요.
이 노트북은 Cloud SQL for MySQL을 사용하여 MySQLLoaderMySQLDocumentSaverlangchain 문서를 저장, 로드 및 삭제하는 방법을 다룹니다. GitHub에서 패키지에 대해 자세히 알아보세요. Open In Colab

시작하기 전에

이 노트북을 실행하려면 다음을 수행해야 합니다: 이 노트북의 런타임 환경에서 데이터베이스에 대한 액세스를 확인한 후, 다음 값을 입력하고 예제 스크립트를 실행하기 전에 셀을 실행하세요.
# @markdown Please fill in the both the Google Cloud region and name of your Cloud SQL instance.
REGION = "us-central1"  # @param {type:"string"}
INSTANCE = "test-instance"  # @param {type:"string"}

# @markdown Please specify a database and a table for demo purpose.
DATABASE = "test"  # @param {type:"string"}
TABLE_NAME = "test-default"  # @param {type:"string"}

🦜🔗 라이브러리 설치

이 통합은 자체 langchain-google-cloud-sql-mysql 패키지에 있으므로 설치해야 합니다.
pip install -upgrade --quiet langchain-google-cloud-sql-mysql
Colab 전용: 다음 셀의 주석을 해제하여 커널을 다시 시작하거나 버튼을 사용하여 커널을 다시 시작하세요. Vertex AI Workbench의 경우 상단의 버튼을 사용하여 터미널을 다시 시작할 수 있습니다.
# # Automatically restart kernel after installs so that your environment can access the new packages
# import IPython

# app = IPython.Application.instance()
# app.kernel.do_shutdown(True)

☁ Google Cloud Project 설정

이 노트북 내에서 Google Cloud 리소스를 활용할 수 있도록 Google Cloud 프로젝트를 설정하세요. 프로젝트 ID를 모르는 경우 다음을 시도해 보세요:
  • gcloud config list를 실행하세요.
  • gcloud projects list를 실행하세요.
  • 지원 페이지를 참조하세요: 프로젝트 ID 찾기.
# @markdown Please fill in the value below with your Google Cloud project ID and then run the cell.

PROJECT_ID = "my-project-id"  # @param {type:"string"}

# Set the project id
!gcloud config set project {PROJECT_ID}

🔐 인증

Google Cloud Project에 액세스하기 위해 이 노트북에 로그인한 IAM 사용자로 Google Cloud에 인증하세요.
  • Colab을 사용하여 이 노트북을 실행하는 경우 아래 셀을 사용하고 계속하세요.
  • Vertex AI Workbench를 사용하는 경우 여기에서 설정 지침을 확인하세요.
from google.colab import auth

auth.authenticate_user()

기본 사용법

MySQLEngine Connection Pool

MySQL 테이블에서 문서를 저장하거나 로드하기 전에 먼저 Cloud SQL 데이터베이스에 대한 connection pool을 구성해야 합니다. MySQLEngine은 Cloud SQL 데이터베이스에 대한 connection pool을 구성하여 애플리케이션에서 성공적인 연결을 가능하게 하고 업계 모범 사례를 따릅니다. MySQLEngine.from_instance()를 사용하여 MySQLEngine을 생성하려면 다음 4가지만 제공하면 됩니다:
  1. project_id : Cloud SQL 인스턴스가 위치한 Google Cloud Project의 Project ID.
  2. region : Cloud SQL 인스턴스가 위치한 Region.
  3. instance : Cloud SQL 인스턴스의 이름.
  4. database : Cloud SQL 인스턴스에서 연결할 데이터베이스의 이름.
기본적으로 IAM 데이터베이스 인증이 데이터베이스 인증 방법으로 사용됩니다. 이 라이브러리는 환경에서 가져온 Application Default Credentials (ADC)에 속한 IAM principal을 사용합니다. IAM 데이터베이스 인증에 대한 자세한 내용은 다음을 참조하세요: 선택적으로, 사용자 이름과 비밀번호를 사용하여 Cloud SQL 데이터베이스에 액세스하는 기본 제공 데이터베이스 인증도 사용할 수 있습니다. MySQLEngine.from_instance()에 선택적 userpassword 인수를 제공하기만 하면 됩니다:
  • user : 기본 제공 데이터베이스 인증 및 로그인에 사용할 데이터베이스 사용자
  • password : 기본 제공 데이터베이스 인증 및 로그인에 사용할 데이터베이스 비밀번호.
from langchain_google_cloud_sql_mysql import MySQLEngine

engine = MySQLEngine.from_instance(
    project_id=PROJECT_ID, region=REGION, instance=INSTANCE, database=DATABASE
)

테이블 초기화

MySQLEngine.init_document_table(<table_name>)을 통해 기본 스키마의 테이블을 초기화합니다. 테이블 컬럼:
  • page_content (type: text)
  • langchain_metadata (type: JSON)
overwrite_existing=True 플래그는 새로 초기화된 테이블이 동일한 이름의 기존 테이블을 대체한다는 것을 의미합니다.
engine.init_document_table(TABLE_NAME, overwrite_existing=True)

문서 저장

MySQLDocumentSaver.add_documents(<documents>)로 langchain 문서를 저장합니다. MySQLDocumentSaver 클래스를 초기화하려면 다음 2가지를 제공해야 합니다:
  1. engine - MySQLEngine 엔진의 인스턴스.
  2. table_name - langchain 문서를 저장할 Cloud SQL 데이터베이스 내 테이블의 이름.
from langchain_core.documents import Document
from langchain_google_cloud_sql_mysql import MySQLDocumentSaver

test_docs = [
    Document(
        page_content="Apple Granny Smith 150 0.99 1",
        metadata={"fruit_id": 1},
    ),
    Document(
        page_content="Banana Cavendish 200 0.59 0",
        metadata={"fruit_id": 2},
    ),
    Document(
        page_content="Orange Navel 80 1.29 1",
        metadata={"fruit_id": 3},
    ),
]
saver = MySQLDocumentSaver(engine=engine, table_name=TABLE_NAME)
saver.add_documents(test_docs)

문서 로드

MySQLLoader.load() 또는 MySQLLoader.lazy_load()로 langchain 문서를 로드합니다. lazy_load는 반복 중에만 데이터베이스를 쿼리하는 generator를 반환합니다. MySQLLoader 클래스를 초기화하려면 다음을 제공해야 합니다:
  1. engine - MySQLEngine 엔진의 인스턴스.
  2. table_name - langchain 문서를 저장할 Cloud SQL 데이터베이스 내 테이블의 이름.
from langchain_google_cloud_sql_mysql import MySQLLoader

loader = MySQLLoader(engine=engine, table_name=TABLE_NAME)
docs = loader.lazy_load()
for doc in docs:
    print("Loaded documents:", doc)

쿼리를 통한 문서 로드

테이블에서 문서를 로드하는 것 외에도 SQL 쿼리에서 생성된 view에서 문서를 로드하도록 선택할 수도 있습니다. 예를 들어:
from langchain_google_cloud_sql_mysql import MySQLLoader

loader = MySQLLoader(
    engine=engine,
    query=f"select * from `{TABLE_NAME}` where JSON_EXTRACT(langchain_metadata, '$.fruit_id') = 1;",
)
onedoc = loader.load()
onedoc
SQL 쿼리에서 생성된 view는 기본 테이블과 다른 스키마를 가질 수 있습니다. 이러한 경우 MySQLLoader의 동작은 기본이 아닌 스키마를 가진 테이블에서 로드하는 것과 동일합니다. 사용자 정의된 문서 page content 및 metadata로 문서 로드 섹션을 참조하세요.

문서 삭제

MySQLDocumentSaver.delete(<documents>)로 MySQL 테이블에서 langchain 문서 목록을 삭제합니다. 기본 스키마(page_content, langchain_metadata)를 가진 테이블의 경우 삭제 기준은 다음과 같습니다: 다음과 같은 document가 목록에 존재하는 경우 row를 삭제해야 합니다:
  • document.page_contentrow[page_content]와 같음
  • document.metadatarow[langchain_metadata]와 같음
from langchain_google_cloud_sql_mysql import MySQLLoader

loader = MySQLLoader(engine=engine, table_name=TABLE_NAME)
docs = loader.load()
print("Documents before delete:", docs)
saver.delete(onedoc)
print("Documents after delete:", loader.load())

고급 사용법

사용자 정의된 문서 page content 및 metadata로 문서 로드

먼저 기본이 아닌 스키마를 가진 예제 테이블을 준비하고 임의의 데이터로 채웁니다.
import sqlalchemy

with engine.connect() as conn:
    conn.execute(sqlalchemy.text(f"DROP TABLE IF EXISTS `{TABLE_NAME}`"))
    conn.commit()
    conn.execute(
        sqlalchemy.text(
            f"""
            CREATE TABLE IF NOT EXISTS `{TABLE_NAME}`(
                fruit_id INT AUTO_INCREMENT PRIMARY KEY,
                fruit_name VARCHAR(100) NOT NULL,
                variety VARCHAR(50),
                quantity_in_stock INT NOT NULL,
                price_per_unit DECIMAL(6,2) NOT NULL,
                organic TINYINT(1) NOT NULL
            )
            """
        )
    )
    conn.execute(
        sqlalchemy.text(
            f"""
            INSERT INTO `{TABLE_NAME}` (fruit_name, variety, quantity_in_stock, price_per_unit, organic)
            VALUES
                ('Apple', 'Granny Smith', 150, 0.99, 1),
                ('Banana', 'Cavendish', 200, 0.59, 0),
                ('Orange', 'Navel', 80, 1.29, 1);
            """
        )
    )
    conn.commit()
이 예제 테이블에서 MySQLLoader의 기본 매개변수로 langchain 문서를 로드하면 로드된 문서의 page_content는 테이블의 첫 번째 컬럼이 되고 metadata는 다른 모든 컬럼의 key-value 쌍으로 구성됩니다.
loader = MySQLLoader(
    engine=engine,
    table_name=TABLE_NAME,
)
loader.load()
MySQLLoader를 초기화할 때 content_columnsmetadata_columns를 설정하여 로드하려는 content와 metadata를 지정할 수 있습니다.
  1. content_columns: 문서의 page_content에 쓸 컬럼.
  2. metadata_columns: 문서의 metadata에 쓸 컬럼.
예를 들어 여기서 content_columns의 컬럼 값은 공백으로 구분된 문자열로 결합되어 로드된 문서의 page_content가 되고, 로드된 문서의 metadatametadata_columns에 지정된 컬럼의 key-value 쌍만 포함합니다.
loader = MySQLLoader(
    engine=engine,
    table_name=TABLE_NAME,
    content_columns=[
        "variety",
        "quantity_in_stock",
        "price_per_unit",
        "organic",
    ],
    metadata_columns=["fruit_id", "fruit_name"],
)
loader.load()

사용자 정의된 page content 및 metadata로 문서 저장

사용자 정의된 metadata 필드가 있는 테이블에 langchain 문서를 저장하려면 먼저 MySQLEngine.init_document_table()을 통해 해당 테이블을 생성하고 원하는 metadata_columns 목록을 지정해야 합니다. 이 예제에서 생성된 테이블은 다음과 같은 테이블 컬럼을 갖습니다:
  • description (type: text): 과일 설명을 저장하기 위한 컬럼.
  • fruit_name (type text): 과일 이름을 저장하기 위한 컬럼.
  • organic (type tinyint(1)): 과일이 유기농인지 알려주는 컬럼.
  • other_metadata (type: JSON): 과일의 다른 metadata 정보를 저장하기 위한 컬럼.
MySQLEngine.init_document_table()과 함께 다음 매개변수를 사용하여 테이블을 생성할 수 있습니다:
  1. table_name: langchain 문서를 저장할 Cloud SQL 데이터베이스 내 테이블의 이름.
  2. metadata_columns: 필요한 metadata 컬럼 목록을 나타내는 sqlalchemy.Column 목록.
  3. content_column: langchain 문서의 page_content를 저장할 컬럼의 이름. 기본값: page_content.
  4. metadata_json_column: langchain 문서의 추가 metadata를 저장할 JSON 컬럼의 이름. 기본값: langchain_metadata.
engine.init_document_table(
    TABLE_NAME,
    metadata_columns=[
        sqlalchemy.Column(
            "fruit_name",
            sqlalchemy.UnicodeText,
            primary_key=False,
            nullable=True,
        ),
        sqlalchemy.Column(
            "organic",
            sqlalchemy.Boolean,
            primary_key=False,
            nullable=True,
        ),
    ],
    content_column="description",
    metadata_json_column="other_metadata",
    overwrite_existing=True,
)
MySQLDocumentSaver.add_documents(<documents>)로 문서를 저장합니다. 이 예제에서 볼 수 있듯이,
  • document.page_contentdescription 컬럼에 저장됩니다.
  • document.metadata.fruit_namefruit_name 컬럼에 저장됩니다.
  • document.metadata.organicorganic 컬럼에 저장됩니다.
  • document.metadata.fruit_idother_metadata 컬럼에 JSON 형식으로 저장됩니다.
test_docs = [
    Document(
        page_content="Granny Smith 150 0.99",
        metadata={"fruit_id": 1, "fruit_name": "Apple", "organic": 1},
    ),
]
saver = MySQLDocumentSaver(
    engine=engine,
    table_name=TABLE_NAME,
    content_column="description",
    metadata_json_column="other_metadata",
)
saver.add_documents(test_docs)
with engine.connect() as conn:
    result = conn.execute(sqlalchemy.text(f"select * from `{TABLE_NAME}`;"))
    print(result.keys())
    print(result.fetchall())

사용자 정의된 page content 및 metadata로 문서 삭제

MySQLDocumentSaver.delete(<documents>)를 통해 사용자 정의된 metadata 컬럼이 있는 테이블에서 문서를 삭제할 수도 있습니다. 삭제 기준은 다음과 같습니다: 다음과 같은 document가 목록에 존재하는 경우 row를 삭제해야 합니다:
  • document.page_contentrow[page_content]와 같음
  • document.metadata의 모든 metadata 필드 k에 대해
    • document.metadata[k]row[k]와 같거나 document.metadata[k]row[langchain_metadata][k]와 같음
  • row에는 있지만 document.metadata에는 없는 추가 metadata 필드가 없음.
loader = MySQLLoader(engine=engine, table_name=TABLE_NAME)
docs = loader.load()
print("Documents before delete:", docs)
saver.delete(docs)
print("Documents after delete:", loader.load())

Connect these docs programmatically to Claude, VSCode, and more via MCP for real-time answers.
I